UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

165 lines (164 loc) • 7.62 kB
import { r as resolveStateDir } from "./state-dir-BHJORNly.mjs"; import { n as captureOpenClawStateReadWorkerContext } from "./openclaw-state-worker-context-DRG_I6tz.mjs"; import { c as resolveOpenClawAgentSqlitePath, i as isIncognitoOpenClawAgentSqlitePath, r as createOpenClawAgentDatabasePathMatcher } from "./openclaw-agent-db.paths-DVbbFaej.mjs"; import { l as resolveSessionStorePathCore } from "./paths-dpReqUI8.mjs"; import { a as getOpenClawAgentDatabaseIfOpen, s as openOpenClawAgentDatabase } from "./openclaw-agent-db-DBug3LUA.mjs"; import { t as captureSessionTranscriptStorageEnvironment } from "./transcript-target-binding-WjVavOYj.mjs"; import { n as withOpenClawAgentDatabaseReadOnly } from "./openclaw-agent-db-readonly-C4wDuLrp.mjs"; import { i as toDatabaseOptions } from "./session-accessor.sqlite-scope-helpers-DOK3pvYX.mjs"; import { o as resolveSqliteReadScope } from "./session-accessor.sqlite-scope-CdpbxR_m.mjs"; import { L as upsertConversationIdentity } from "./session-accessor.sqlite-entry-store-CS34_uoa.mjs"; import { t as captureSessionStoreReadCandidates } from "./session-store-target-inventory-Dj6Sq0En.mjs"; import { f as withSessionStoreReaderInWorker } from "./session-entry-read-runtime-0qc4qizi.mjs"; import { t as withOpenClawAgentDatabaseWrite } from "./openclaw-agent-db-write-CVe9DulI.mjs"; import { n as selectConversationRowsFromDatabase } from "./session-accessor.sqlite-conversation-read-N9UYrpaO.mjs"; import path from "node:path"; //#region src/config/sessions/conversation-registry.ts function resolveConversationRegistryScope(params) { return pinConversationDatabaseScope({ agentId: params.agentId, storePath: resolveSessionStorePathCore(params.config.session?.store, { agentId: params.agentId }) }).scope; } async function prepareConversationRegistryScope(params) { const input = { agentId: params.agentId, storePath: resolveSessionStorePathCore(params.config.session?.store, { agentId: params.agentId }) }; if (isIncognitoOpenClawAgentSqlitePath(input.storePath, input)) return pinConversationDatabaseScope(input).scope; return withConversationRead(input, async ({ database, logicalAgentId }) => ({ agentId: logicalAgentId, databaseAgentId: database.agentId, storePath: database.path, env: database.env })); } function withConversationRead(input, read) { const env = captureSessionTranscriptStorageEnvironment(input.env ?? process.env); const storePath = path.resolve(input.storePath ?? resolveSessionStorePathCore(void 0, { agentId: input.agentId, env })); const context = captureOpenClawStateReadWorkerContext({ env }); const source = createOpenClawAgentDatabasePathMatcher(); for (const candidate of captureSessionStoreReadCandidates(storePath)) source(candidate.path, candidate.path); return withSessionStoreReaderInWorker({ agentId: input.agentId, storePath, env }, async (owner) => { if (input.databaseAgentId && owner.database.agentId !== input.databaseAgentId) throw new Error("Conversation database owner changed. Retry the request."); const result = await read(owner); owner.assertCurrent(); return result; }, { dataOnly: true, logical: { assertCurrent() { context.maintenanceScope?.assertAdmission(); context.admission.assertCurrent(); if (!source.isCurrent()) throw new Error("Session store changed while reading conversations. Retry the request."); } } }); } function selectConversationRowsInWorker(scope, query) { const capturedQuery = structuredClone(query); if (scope.storePath && isIncognitoOpenClawAgentSqlitePath(scope.storePath, scope)) return Promise.resolve(selectConversationRows(scope, capturedQuery)); return withConversationRead(scope, ({ reader, database }) => reader.readConversations({ query: capturedQuery, env: database.env })); } function pinConversationDatabaseScope(input) { const env = { ...input.env ?? process.env }; env.OPENCLAW_STATE_DIR = resolveStateDir(env); const options = input.databaseAgentId && input.storePath ? { agentId: input.databaseAgentId, path: input.storePath, env } : toDatabaseOptions(resolveSqliteReadScope({ ...input, env })); const storePath = resolveOpenClawAgentSqlitePath(options); return { options: { ...options, path: storePath }, scope: { ...input, databaseAgentId: options.agentId, storePath, env } }; } /** Keep the logical agent and physical store fixed while its synchronous write waits. */ function runConversationDatabaseWrite(input, operation) { const { options, scope } = pinConversationDatabaseScope(input); return withOpenClawAgentDatabaseWrite(options, () => operation(scope)); } function selectConversationRows(scope, options = {}) { const resolved = resolveSqliteReadScope({ agentId: scope.agentId, ...scope.env ? { env: scope.env } : {}, ...scope.storePath ? { storePath: scope.storePath } : {} }); const databaseOptions = toDatabaseOptions(resolved); const readRows = (database) => selectConversationRowsFromDatabase(database, options); const held = getOpenClawAgentDatabaseIfOpen(databaseOptions); if (held?.db.isTransaction) return readRows(held); const read = withOpenClawAgentDatabaseReadOnly(readRows, databaseOptions); return read.found ? read.value : []; } /** Catalogs routable addresses without creating model-context sessions. */ function registerConversationAddresses(scope, identities, discoveredAt = Date.now()) { if (identities.length === 0) return; const resolved = resolveSqliteReadScope({ agentId: scope.agentId, ...scope.env ? { env: scope.env } : {}, ...scope.storePath ? { storePath: scope.storePath } : {} }); const database = openOpenClawAgentDatabase(toDatabaseOptions(resolved)); for (const identity of identities) upsertConversationIdentity(database, identity, discoveredAt); } /** Lists stable external addresses for one agent, newest activity first. */ function listConversations(scope, options = {}) { return selectConversationRowsInWorker(scope, options); } async function readConversation(scope, conversationRef) { return (await selectConversationRowsInWorker(scope, { conversationRef, limit: 1 }))[0]; } /** Resolves an opaque address to one exact channel target and its context binding, when present. */ function resolveConversation(scope, conversationRef) { return selectConversationRows(scope, { conversationRef, limit: 1 })[0]; } /** Reads only an authoritative association on an address's current session window. */ function resolveCurrentConversationSession(scope, conversationRef, currentSession) { const [conversation] = selectConversationRows(scope, { conversationRef, currentBindingOnly: true, currentSession, limit: 1 }); return conversation?.sessionKey && conversation.sessionId ? { sessionKey: conversation.sessionKey, sessionId: conversation.sessionId } : void 0; } /** Reads only the primary address bound to this exact current session window. */ async function resolveCurrentSessionPrimaryConversation(scope) { const [conversation] = await selectConversationRowsInWorker(scope, { primarySession: { sessionId: scope.sessionId, sessionKey: scope.sessionKey } }); return conversation?.sessionId === scope.sessionId && conversation.sessionKey === scope.sessionKey ? conversation : void 0; } //#endregion export { registerConversationAddresses as a, resolveCurrentConversationSession as c, readConversation as i, resolveCurrentSessionPrimaryConversation as l, pinConversationDatabaseScope as n, resolveConversation as o, prepareConversationRegistryScope as r, resolveConversationRegistryScope as s, listConversations as t, runConversationDatabaseWrite as u };