@agimon-ai/po-session 0.0.0-alpha.29 → 0.0.0-alpha.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/server.cjs +11 -2
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.mjs +11 -2
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{sessionDelivery-CGWuQyLV.cjs → sessionDelivery-BAXrVTum.cjs} +2 -2
- package/dist/sessionDelivery-BAXrVTum.cjs.map +1 -0
- package/dist/{sessionDelivery-4svjzWUW.mjs → sessionDelivery-CN7GF38B.mjs} +2 -2
- package/dist/sessionDelivery-CN7GF38B.mjs.map +1 -0
- package/package.json +4 -4
- package/dist/sessionDelivery-4svjzWUW.mjs.map +0 -1
- package/dist/sessionDelivery-CGWuQyLV.cjs.map +0 -1
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_sessionDelivery = require("../sessionDelivery-
|
|
5
|
+
const require_sessionDelivery = require("../sessionDelivery-BAXrVTum.cjs");
|
|
6
6
|
let node_path = require("node:path");
|
|
7
7
|
node_path = require_sessionDelivery.__toESM(node_path, 1);
|
|
8
8
|
let _agimon_ai_po_core_platform = require("@agimon-ai/po-core/platform");
|
|
@@ -69,7 +69,16 @@ var root_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoot)((plug
|
|
|
69
69
|
recipientKey: agent.context.sessionId,
|
|
70
70
|
communication: peerCommunication,
|
|
71
71
|
authorizePeer: (peerKey, metadata) => groupAuthorization ? groupAuthorization(peerKey, metadata) : fallbackAuthorization(peerKey),
|
|
72
|
-
admitPrompt: (prompt, admission, requestId) =>
|
|
72
|
+
admitPrompt: (prompt, admission, requestId, metadata) => {
|
|
73
|
+
if (!metadata.customType) return session.admitPrompt(prompt, admission, void 0, requestId);
|
|
74
|
+
if (!session.admitMessage) throw new Error("The session cannot admit a custom delivery.");
|
|
75
|
+
return session.admitMessage({
|
|
76
|
+
type: metadata.customType,
|
|
77
|
+
text: prompt,
|
|
78
|
+
display: true,
|
|
79
|
+
details: metadata.customDetails === void 0 ? void 0 : JSON.parse(metadata.customDetails)
|
|
80
|
+
}, admission === "steer" ? "steer" : "followUp", requestId);
|
|
81
|
+
}
|
|
73
82
|
});
|
|
74
83
|
} catch (error) {
|
|
75
84
|
await groups?.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.cjs","names":["defineRoot","provideBackgroundWorkService","requirePoFs","requirePoSqlite","BACKGROUND_CONTEXT","path","poHomeDirectory","ensurePrivateDirectory","readSessionPeerConfigAsync","createPeerCommunication","parseRemoteSessionReference","createSessionGroupStore","peerSessionReference","createSessionGroupDeliveryAuthorizer","provideSessionDeliveryService","createSessionDirectory","PO_SESSION_INTERCOM_SERVICE","createSessionIntercom","readSessionPeerConfigAsync","BACKGROUND_CONTEXT","path","sessionPeerConfigPath","PEER_REPLAY_DATABASE_FILE","ensurePrivateDirectory","createPeerReplayGuardAsync","verifyPeerRequest","parseSessionPeerEnvelope","peerSessionReference","defineRoute","requirePoFs","requirePoSqlite","defineServerPlugin","composeServerProviderOverrides","rootSession","composeRootInjects","apiRoute","composeRootHooks"],"sources":["../../src/services/peerInbox/index.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/peerInboxApi/index.ts","../../src/extensions/(backend)/api/session-peer/route.server.ts","../../generated/server.ts"],"sourcesContent":["import type { PoSessionDeliveryInboxState } from '../sessionDelivery';\n\nexport type SessionPeerInbox = (\n sourceKey: string,\n type: string,\n payload: unknown,\n) => Promise<PoSessionDeliveryInboxState | undefined> | undefined;\n\nconst inboxes = new Map<string, SessionPeerInbox>();\n\n/**\n * Registers one live session-owned peer inbox. This registry is reachable only by the Session route.\n * The newest registration wins: a Durable Object evicted without disposal leaves its entry in the\n * isolate's module state, and the restarted session must replace it. The hub still rejects two live\n * sessions with one id, and an older unregister cannot remove a newer inbox.\n */\nexport function registerSessionPeerInbox(sessionId: string, inbox: SessionPeerInbox): () => void {\n inboxes.set(sessionId, inbox);\n return () => {\n if (inboxes.get(sessionId) === inbox) inboxes.delete(sessionId);\n };\n}\n\nexport async function deliverSessionPeerEnvelope(\n targetSessionId: string,\n sourceKey: string,\n type: string,\n payload: unknown,\n): Promise<PoSessionDeliveryInboxState | undefined> {\n return inboxes.get(targetSessionId)?.(sourceKey, type, payload);\n}\n","import path from 'node:path';\n\nimport { defineRoot } from '@agimon-ai/po-core/extensionFile';\nimport { poHomeDirectory } from '@agimon-ai/po-core/piSettings';\nimport { BACKGROUND_CONTEXT, requirePoFs, requirePoSqlite } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext } from '@agimon-ai/po-core/serverPlugin';\n\nimport { provideBackgroundWorkService } from '../../../../services/backgroundWorkService';\nimport { registerSessionPeerInbox } from '../../../../services/peerInbox';\nimport {\n createPeerCommunication,\n ensurePrivateDirectory,\n parseRemoteSessionReference,\n peerSessionReference,\n readSessionPeerConfigAsync,\n} from '../../../../services/peerTransport';\nimport { provideSessionDeliveryService } from '../../../../services/sessionDelivery';\nimport { createSessionDirectory } from '../../../../services/sessionDirectory';\nimport { createSessionGroupStore } from '../../../../services/sessionGroups';\nimport {\n PO_SESSION_INTERCOM_SERVICE,\n createSessionGroupDeliveryAuthorizer,\n createSessionIntercom,\n} from '../../../../services/sessionIntercom';\n\nexport default defineRoot((pluginContext: PoServerPluginContext) => ({\n value: undefined,\n services: [\n provideBackgroundWorkService,\n async (context) => {\n const agent = pluginContext.agent;\n const session = agent?.context.session;\n const communication = pluginContext.host.context.sessionCommunication;\n const homeDirectory = pluginContext.host.context.homeDirectory;\n const sessionService = pluginContext.host.context.sessionService;\n if (!agent || !session?.admitPrompt || !communication || !homeDirectory || !sessionService?.canCommunicate) {\n throw new Error(\n 'Session delivery requires the headless agent, authenticated session communication, host home directory, and communication policy.',\n );\n }\n const fs = requirePoFs(pluginContext.context);\n const sqlite = requirePoSqlite(pluginContext.context);\n const io = BACKGROUND_CONTEXT;\n const sessionDirectory = path.join(poHomeDirectory(homeDirectory), 'session');\n const deliveryDirectory = path.join(sessionDirectory, 'delivery');\n await ensurePrivateDirectory(fs, deliveryDirectory, io);\n const peerConfig = await readSessionPeerConfigAsync(fs, homeDirectory, io);\n const peerCommunication = createPeerCommunication({ local: communication, config: peerConfig });\n const remotePeerIsGranted = (peerKey: string): boolean => {\n const peer = parseRemoteSessionReference(peerKey);\n return (\n peer !== undefined &&\n peerConfig?.peers.some(\n (candidate) =>\n candidate.hostId === peer.hostId && candidate.allowedSessionIds.includes(agent.context.sessionId),\n ) === true\n );\n };\n const fallbackAuthorization = (peerKey: string): boolean =>\n sessionService.canCommunicate?.(agent.context.sessionId, peerKey) === true || remotePeerIsGranted(peerKey);\n const groups = peerConfig\n ? await createSessionGroupStore({\n database: await sqlite.open(path.join(sessionDirectory, 'groups.sqlite'), io),\n })\n : undefined;\n const localHostId = peerConfig?.hostId;\n const selfReference = localHostId ? peerSessionReference(localHostId, agent.context.sessionId) : undefined;\n const groupAuthorization =\n groups && selfReference && localHostId\n ? createSessionGroupDeliveryAuthorizer({\n selfReference,\n groups,\n peerReference: (peerKey) =>\n parseRemoteSessionReference(peerKey) === undefined\n ? peerSessionReference(localHostId, peerKey)\n : peerKey,\n fallback: fallbackAuthorization,\n })\n : undefined;\n let delivery: Awaited<ReturnType<typeof provideSessionDeliveryService>>;\n try {\n delivery = await provideSessionDeliveryService(context, {\n database: await sqlite.open(path.join(deliveryDirectory, `${agent.context.sessionId}.sqlite`), io),\n recipientKey: agent.context.sessionId,\n communication: peerCommunication,\n authorizePeer: (peerKey, metadata) =>\n groupAuthorization ? groupAuthorization(peerKey, metadata) : fallbackAuthorization(peerKey),\n admitPrompt: (prompt, admission, requestId) => session.admitPrompt!(prompt, admission, undefined, requestId),\n });\n } catch (error) {\n await groups?.close();\n throw error;\n }\n const { service, close: closeDelivery } = delivery;\n const unprovide: (() => void)[] = [];\n if (groups && selfReference && peerConfig) {\n const directory = createSessionDirectory({\n authorizeDiscovery: async (caller, subject) => {\n const reference = peerSessionReference(subject.hostId, subject.sessionId);\n const permitted = (await groups.groupsFor(caller)).some((group) => group.members.includes(reference));\n return permitted ? { capabilities: ['message'] } : undefined;\n },\n });\n for (const peer of peerConfig.peers)\n for (const sessionId of peer.allowedSessionIds)\n directory.observe({\n hostId: peer.hostId,\n sessionId,\n hostIncarnation: 'unknown',\n sessionIncarnation: 'unknown',\n sequence: 0,\n observedAt: 0,\n staleAfterMs: 0,\n deliveryTarget: peerSessionReference(peer.hostId, sessionId),\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: { eligible: 'unknown', readiness: 'unknown' },\n });\n unprovide.push(\n context.provide(\n PO_SESSION_INTERCOM_SERVICE,\n createSessionIntercom({ selfReference, directory, groups, delivery: service }),\n ),\n );\n }\n const unregister = registerSessionPeerInbox(agent.context.sessionId, (sourceKey, kind, payload) =>\n service.receive?.(sourceKey, kind, payload),\n );\n return async () => {\n unregister();\n for (const release of unprovide.reverse()) release();\n await closeDelivery();\n await groups?.close();\n };\n },\n ],\n}));\n","import path from 'node:path';\n\nimport type { PoApi, PoApiHandler } from '@agimon-ai/po-core/packageApi';\nimport { BACKGROUND_CONTEXT, type PoSqliteService, type FileSystem } from '@agimon-ai/po-core/platform';\n\nimport { deliverSessionPeerEnvelope } from '../peerInbox';\nimport {\n PEER_REPLAY_DATABASE_FILE,\n createPeerReplayGuardAsync,\n ensurePrivateDirectory,\n parseSessionPeerEnvelope,\n peerSessionReference,\n readSessionPeerConfigAsync,\n sessionPeerConfigPath,\n verifyPeerRequest,\n type SessionPeerConfig,\n type SessionPeerReplayGuardAsync,\n} from '../peerTransport';\n\nconst MAX_BODY_BYTES = 64 * 1024;\nconst DELIVERY_TYPES = new Set(['po/session-delivery/envelope', 'po/session-delivery/ack']);\n\nfunction response(status: number, error: string): Response {\n return Response.json({ error }, { status });\n}\n\ninterface PeerInboxState {\n readonly config: SessionPeerConfig | undefined;\n readonly replay: SessionPeerReplayGuardAsync | undefined;\n}\n\n/** Narrow HMAC-authenticated endpoint that a trusted tunnel may forward without device authentication. */\nexport function createPeerInboxApi(platform: { readonly fs: FileSystem; readonly sqlite: PoSqliteService }): PoApi {\n return {\n basePath: 'session-peer',\n start(context): PoApiHandler {\n const homeDirectory = context.homeDirectory;\n // Opened once on first use: the handler starts synchronously, the platform services are async.\n let opened: Promise<PeerInboxState> | undefined;\n const open = (): Promise<PeerInboxState> =>\n (opened ??= (async () => {\n if (homeDirectory === undefined) return { config: undefined, replay: undefined };\n const config = await readSessionPeerConfigAsync(platform.fs, homeDirectory, BACKGROUND_CONTEXT);\n const file = path.join(path.dirname(sessionPeerConfigPath(homeDirectory)), PEER_REPLAY_DATABASE_FILE);\n await ensurePrivateDirectory(platform.fs, path.dirname(file), BACKGROUND_CONTEXT);\n const replay = await createPeerReplayGuardAsync(await platform.sqlite.open(file, BACKGROUND_CONTEXT));\n return { config, replay };\n })().catch((error: unknown) => {\n // A failed open is retried by the next request rather than cached.\n opened = undefined;\n throw error;\n }));\n return {\n async fetch(request) {\n if (request.method !== 'POST' || new URL(request.url).pathname !== '/inbox')\n return response(404, 'Not found.');\n const { config, replay } = await open();\n if (!config) return response(503, 'Paired Session delivery is not configured.');\n const length = request.headers.get('content-length');\n if (length !== null && (!/^\\d+$/u.test(length) || Number(length) > MAX_BODY_BYTES))\n return response(413, 'Request body is too large.');\n const body = await request.text();\n if (Buffer.byteLength(body) > MAX_BODY_BYTES) return response(413, 'Request body is too large.');\n const peer = verifyPeerRequest(config, request, body);\n if (!peer) return response(401, 'Paired Session request is unauthorized.');\n if (!(await replay?.admit(request))) return response(409, 'Paired Session request was already received.');\n let parsed: unknown;\n try {\n parsed = JSON.parse(body) as unknown;\n } catch {\n return response(400, 'Paired Session request is malformed.');\n }\n const envelope = parseSessionPeerEnvelope(parsed);\n if (!envelope || !DELIVERY_TYPES.has(envelope.type))\n return response(400, 'Paired Session envelope is invalid.');\n if (!peer.allowedSessionIds.includes(envelope.targetSessionId))\n return response(403, 'Peer is not granted this session.');\n const state = await deliverSessionPeerEnvelope(\n envelope.targetSessionId,\n peerSessionReference(peer.hostId, envelope.sourceSessionId),\n envelope.type,\n envelope.payload,\n );\n return state === undefined\n ? response(404, 'Target Session is unavailable.')\n : Response.json({ accepted: true, state }, { status: 202 });\n },\n async close() {\n const state = await opened?.catch(() => undefined);\n await state?.replay?.close();\n },\n };\n },\n };\n}\n","import { defineRoute } from '@agimon-ai/po-core/extensionFile';\nimport { requirePoFs, requirePoSqlite } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext } from '@agimon-ai/po-core/serverPlugin';\n\nimport { createPeerInboxApi } from '../../../../services/peerInboxApi';\n\nexport default defineRoute(({ context }: PoServerPluginContext) =>\n createPeerInboxApi({ fs: requirePoFs(context), sqlite: requirePoSqlite(context) }),\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverPlugin';\nimport { composeRootHooks, composeRootInjects } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/session-peer/route.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const serverPlugin = defineServerPlugin({\n name: '@agimon-ai/po-session',\n providerOverrides: composeServerProviderOverrides(rootSession),\n injects: composeRootInjects({ session: [rootSession] }),\n global: (context) => ({\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await context.scopeRoot('session', rootSession, context);\n return {\n ...composeRootHooks(scopeSession),\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): PoServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default serverPlugin;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.cjs","names":["defineRoot","provideBackgroundWorkService","requirePoFs","requirePoSqlite","BACKGROUND_CONTEXT","path","poHomeDirectory","ensurePrivateDirectory","readSessionPeerConfigAsync","createPeerCommunication","parseRemoteSessionReference","createSessionGroupStore","peerSessionReference","createSessionGroupDeliveryAuthorizer","provideSessionDeliveryService","createSessionDirectory","PO_SESSION_INTERCOM_SERVICE","createSessionIntercom","readSessionPeerConfigAsync","BACKGROUND_CONTEXT","path","sessionPeerConfigPath","PEER_REPLAY_DATABASE_FILE","ensurePrivateDirectory","createPeerReplayGuardAsync","verifyPeerRequest","parseSessionPeerEnvelope","peerSessionReference","defineRoute","requirePoFs","requirePoSqlite","defineServerPlugin","composeServerProviderOverrides","rootSession","composeRootInjects","apiRoute","composeRootHooks"],"sources":["../../src/services/peerInbox/index.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/peerInboxApi/index.ts","../../src/extensions/(backend)/api/session-peer/route.server.ts","../../generated/server.ts"],"sourcesContent":["import type { PoSessionDeliveryInboxState } from '../sessionDelivery';\n\nexport type SessionPeerInbox = (\n sourceKey: string,\n type: string,\n payload: unknown,\n) => Promise<PoSessionDeliveryInboxState | undefined> | undefined;\n\nconst inboxes = new Map<string, SessionPeerInbox>();\n\n/**\n * Registers one live session-owned peer inbox. This registry is reachable only by the Session route.\n * The newest registration wins: a Durable Object evicted without disposal leaves its entry in the\n * isolate's module state, and the restarted session must replace it. The hub still rejects two live\n * sessions with one id, and an older unregister cannot remove a newer inbox.\n */\nexport function registerSessionPeerInbox(sessionId: string, inbox: SessionPeerInbox): () => void {\n inboxes.set(sessionId, inbox);\n return () => {\n if (inboxes.get(sessionId) === inbox) inboxes.delete(sessionId);\n };\n}\n\nexport async function deliverSessionPeerEnvelope(\n targetSessionId: string,\n sourceKey: string,\n type: string,\n payload: unknown,\n): Promise<PoSessionDeliveryInboxState | undefined> {\n return inboxes.get(targetSessionId)?.(sourceKey, type, payload);\n}\n","import path from 'node:path';\n\nimport { defineRoot } from '@agimon-ai/po-core/extensionFile';\nimport { poHomeDirectory } from '@agimon-ai/po-core/piSettings';\nimport { BACKGROUND_CONTEXT, requirePoFs, requirePoSqlite } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext } from '@agimon-ai/po-core/serverPlugin';\n\nimport { provideBackgroundWorkService } from '../../../../services/backgroundWorkService';\nimport { registerSessionPeerInbox } from '../../../../services/peerInbox';\nimport {\n createPeerCommunication,\n ensurePrivateDirectory,\n parseRemoteSessionReference,\n peerSessionReference,\n readSessionPeerConfigAsync,\n} from '../../../../services/peerTransport';\nimport { provideSessionDeliveryService } from '../../../../services/sessionDelivery';\nimport { createSessionDirectory } from '../../../../services/sessionDirectory';\nimport { createSessionGroupStore } from '../../../../services/sessionGroups';\nimport {\n PO_SESSION_INTERCOM_SERVICE,\n createSessionGroupDeliveryAuthorizer,\n createSessionIntercom,\n} from '../../../../services/sessionIntercom';\n\nexport default defineRoot((pluginContext: PoServerPluginContext) => ({\n value: undefined,\n services: [\n provideBackgroundWorkService,\n async (context) => {\n const agent = pluginContext.agent;\n const session = agent?.context.session;\n const communication = pluginContext.host.context.sessionCommunication;\n const homeDirectory = pluginContext.host.context.homeDirectory;\n const sessionService = pluginContext.host.context.sessionService;\n if (!agent || !session?.admitPrompt || !communication || !homeDirectory || !sessionService?.canCommunicate) {\n throw new Error(\n 'Session delivery requires the headless agent, authenticated session communication, host home directory, and communication policy.',\n );\n }\n const fs = requirePoFs(pluginContext.context);\n const sqlite = requirePoSqlite(pluginContext.context);\n const io = BACKGROUND_CONTEXT;\n const sessionDirectory = path.join(poHomeDirectory(homeDirectory), 'session');\n const deliveryDirectory = path.join(sessionDirectory, 'delivery');\n await ensurePrivateDirectory(fs, deliveryDirectory, io);\n const peerConfig = await readSessionPeerConfigAsync(fs, homeDirectory, io);\n const peerCommunication = createPeerCommunication({ local: communication, config: peerConfig });\n const remotePeerIsGranted = (peerKey: string): boolean => {\n const peer = parseRemoteSessionReference(peerKey);\n return (\n peer !== undefined &&\n peerConfig?.peers.some(\n (candidate) =>\n candidate.hostId === peer.hostId && candidate.allowedSessionIds.includes(agent.context.sessionId),\n ) === true\n );\n };\n const fallbackAuthorization = (peerKey: string): boolean =>\n sessionService.canCommunicate?.(agent.context.sessionId, peerKey) === true || remotePeerIsGranted(peerKey);\n const groups = peerConfig\n ? await createSessionGroupStore({\n database: await sqlite.open(path.join(sessionDirectory, 'groups.sqlite'), io),\n })\n : undefined;\n const localHostId = peerConfig?.hostId;\n const selfReference = localHostId ? peerSessionReference(localHostId, agent.context.sessionId) : undefined;\n const groupAuthorization =\n groups && selfReference && localHostId\n ? createSessionGroupDeliveryAuthorizer({\n selfReference,\n groups,\n peerReference: (peerKey) =>\n parseRemoteSessionReference(peerKey) === undefined\n ? peerSessionReference(localHostId, peerKey)\n : peerKey,\n fallback: fallbackAuthorization,\n })\n : undefined;\n let delivery: Awaited<ReturnType<typeof provideSessionDeliveryService>>;\n try {\n delivery = await provideSessionDeliveryService(context, {\n database: await sqlite.open(path.join(deliveryDirectory, `${agent.context.sessionId}.sqlite`), io),\n recipientKey: agent.context.sessionId,\n communication: peerCommunication,\n authorizePeer: (peerKey, metadata) =>\n groupAuthorization ? groupAuthorization(peerKey, metadata) : fallbackAuthorization(peerKey),\n admitPrompt: (prompt, admission, requestId, metadata) => {\n if (!metadata.customType) return session.admitPrompt!(prompt, admission, undefined, requestId);\n if (!session.admitMessage) throw new Error('The session cannot admit a custom delivery.');\n return session.admitMessage(\n {\n type: metadata.customType,\n text: prompt,\n display: true,\n details: metadata.customDetails === undefined ? undefined : JSON.parse(metadata.customDetails),\n },\n admission === 'steer' ? 'steer' : 'followUp',\n requestId,\n );\n },\n });\n } catch (error) {\n await groups?.close();\n throw error;\n }\n const { service, close: closeDelivery } = delivery;\n const unprovide: (() => void)[] = [];\n if (groups && selfReference && peerConfig) {\n const directory = createSessionDirectory({\n authorizeDiscovery: async (caller, subject) => {\n const reference = peerSessionReference(subject.hostId, subject.sessionId);\n const permitted = (await groups.groupsFor(caller)).some((group) => group.members.includes(reference));\n return permitted ? { capabilities: ['message'] } : undefined;\n },\n });\n for (const peer of peerConfig.peers)\n for (const sessionId of peer.allowedSessionIds)\n directory.observe({\n hostId: peer.hostId,\n sessionId,\n hostIncarnation: 'unknown',\n sessionIncarnation: 'unknown',\n sequence: 0,\n observedAt: 0,\n staleAfterMs: 0,\n deliveryTarget: peerSessionReference(peer.hostId, sessionId),\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: { eligible: 'unknown', readiness: 'unknown' },\n });\n unprovide.push(\n context.provide(\n PO_SESSION_INTERCOM_SERVICE,\n createSessionIntercom({ selfReference, directory, groups, delivery: service }),\n ),\n );\n }\n const unregister = registerSessionPeerInbox(agent.context.sessionId, (sourceKey, kind, payload) =>\n service.receive?.(sourceKey, kind, payload),\n );\n return async () => {\n unregister();\n for (const release of unprovide.reverse()) release();\n await closeDelivery();\n await groups?.close();\n };\n },\n ],\n}));\n","import path from 'node:path';\n\nimport type { PoApi, PoApiHandler } from '@agimon-ai/po-core/packageApi';\nimport { BACKGROUND_CONTEXT, type PoSqliteService, type FileSystem } from '@agimon-ai/po-core/platform';\n\nimport { deliverSessionPeerEnvelope } from '../peerInbox';\nimport {\n PEER_REPLAY_DATABASE_FILE,\n createPeerReplayGuardAsync,\n ensurePrivateDirectory,\n parseSessionPeerEnvelope,\n peerSessionReference,\n readSessionPeerConfigAsync,\n sessionPeerConfigPath,\n verifyPeerRequest,\n type SessionPeerConfig,\n type SessionPeerReplayGuardAsync,\n} from '../peerTransport';\n\nconst MAX_BODY_BYTES = 64 * 1024;\nconst DELIVERY_TYPES = new Set(['po/session-delivery/envelope', 'po/session-delivery/ack']);\n\nfunction response(status: number, error: string): Response {\n return Response.json({ error }, { status });\n}\n\ninterface PeerInboxState {\n readonly config: SessionPeerConfig | undefined;\n readonly replay: SessionPeerReplayGuardAsync | undefined;\n}\n\n/** Narrow HMAC-authenticated endpoint that a trusted tunnel may forward without device authentication. */\nexport function createPeerInboxApi(platform: { readonly fs: FileSystem; readonly sqlite: PoSqliteService }): PoApi {\n return {\n basePath: 'session-peer',\n start(context): PoApiHandler {\n const homeDirectory = context.homeDirectory;\n // Opened once on first use: the handler starts synchronously, the platform services are async.\n let opened: Promise<PeerInboxState> | undefined;\n const open = (): Promise<PeerInboxState> =>\n (opened ??= (async () => {\n if (homeDirectory === undefined) return { config: undefined, replay: undefined };\n const config = await readSessionPeerConfigAsync(platform.fs, homeDirectory, BACKGROUND_CONTEXT);\n const file = path.join(path.dirname(sessionPeerConfigPath(homeDirectory)), PEER_REPLAY_DATABASE_FILE);\n await ensurePrivateDirectory(platform.fs, path.dirname(file), BACKGROUND_CONTEXT);\n const replay = await createPeerReplayGuardAsync(await platform.sqlite.open(file, BACKGROUND_CONTEXT));\n return { config, replay };\n })().catch((error: unknown) => {\n // A failed open is retried by the next request rather than cached.\n opened = undefined;\n throw error;\n }));\n return {\n async fetch(request) {\n if (request.method !== 'POST' || new URL(request.url).pathname !== '/inbox')\n return response(404, 'Not found.');\n const { config, replay } = await open();\n if (!config) return response(503, 'Paired Session delivery is not configured.');\n const length = request.headers.get('content-length');\n if (length !== null && (!/^\\d+$/u.test(length) || Number(length) > MAX_BODY_BYTES))\n return response(413, 'Request body is too large.');\n const body = await request.text();\n if (Buffer.byteLength(body) > MAX_BODY_BYTES) return response(413, 'Request body is too large.');\n const peer = verifyPeerRequest(config, request, body);\n if (!peer) return response(401, 'Paired Session request is unauthorized.');\n if (!(await replay?.admit(request))) return response(409, 'Paired Session request was already received.');\n let parsed: unknown;\n try {\n parsed = JSON.parse(body) as unknown;\n } catch {\n return response(400, 'Paired Session request is malformed.');\n }\n const envelope = parseSessionPeerEnvelope(parsed);\n if (!envelope || !DELIVERY_TYPES.has(envelope.type))\n return response(400, 'Paired Session envelope is invalid.');\n if (!peer.allowedSessionIds.includes(envelope.targetSessionId))\n return response(403, 'Peer is not granted this session.');\n const state = await deliverSessionPeerEnvelope(\n envelope.targetSessionId,\n peerSessionReference(peer.hostId, envelope.sourceSessionId),\n envelope.type,\n envelope.payload,\n );\n return state === undefined\n ? response(404, 'Target Session is unavailable.')\n : Response.json({ accepted: true, state }, { status: 202 });\n },\n async close() {\n const state = await opened?.catch(() => undefined);\n await state?.replay?.close();\n },\n };\n },\n };\n}\n","import { defineRoute } from '@agimon-ai/po-core/extensionFile';\nimport { requirePoFs, requirePoSqlite } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext } from '@agimon-ai/po-core/serverPlugin';\n\nimport { createPeerInboxApi } from '../../../../services/peerInboxApi';\n\nexport default defineRoute(({ context }: PoServerPluginContext) =>\n createPeerInboxApi({ fs: requirePoFs(context), sqlite: requirePoSqlite(context) }),\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverPlugin';\nimport { composeRootHooks, composeRootInjects } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/session-peer/route.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const serverPlugin = defineServerPlugin({\n name: '@agimon-ai/po-session',\n providerOverrides: composeServerProviderOverrides(rootSession),\n injects: composeRootInjects({ session: [rootSession] }),\n global: (context) => ({\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await context.scopeRoot('session', rootSession, context);\n return {\n ...composeRootHooks(scopeSession),\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): PoServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default serverPlugin;\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as provideBackgroundWorkService, T as sessionPeerConfigPath, _ as parseSessionPeerEnvelope, a as createSessionGroupDeliveryAuthorizer, b as readSessionPeerConfigAsync, f as createSessionDirectory, g as parseRemoteSessionReference, h as ensurePrivateDirectory, m as createPeerReplayGuardAsync, n as provideSessionDeliveryService, o as createSessionIntercom, p as createPeerCommunication, s as PO_SESSION_INTERCOM_SERVICE, u as createSessionGroupStore, w as PEER_REPLAY_DATABASE_FILE, x as verifyPeerRequest, y as peerSessionReference } from "../sessionDelivery-
|
|
1
|
+
import { D as provideBackgroundWorkService, T as sessionPeerConfigPath, _ as parseSessionPeerEnvelope, a as createSessionGroupDeliveryAuthorizer, b as readSessionPeerConfigAsync, f as createSessionDirectory, g as parseRemoteSessionReference, h as ensurePrivateDirectory, m as createPeerReplayGuardAsync, n as provideSessionDeliveryService, o as createSessionIntercom, p as createPeerCommunication, s as PO_SESSION_INTERCOM_SERVICE, u as createSessionGroupStore, w as PEER_REPLAY_DATABASE_FILE, x as verifyPeerRequest, y as peerSessionReference } from "../sessionDelivery-CN7GF38B.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { BACKGROUND_CONTEXT, requirePoFs, requirePoSqlite } from "@agimon-ai/po-core/platform";
|
|
4
4
|
import { poHomeDirectory } from "@agimon-ai/po-core/piSettings";
|
|
@@ -64,7 +64,16 @@ var root_server_default = defineRoot((pluginContext) => ({
|
|
|
64
64
|
recipientKey: agent.context.sessionId,
|
|
65
65
|
communication: peerCommunication,
|
|
66
66
|
authorizePeer: (peerKey, metadata) => groupAuthorization ? groupAuthorization(peerKey, metadata) : fallbackAuthorization(peerKey),
|
|
67
|
-
admitPrompt: (prompt, admission, requestId) =>
|
|
67
|
+
admitPrompt: (prompt, admission, requestId, metadata) => {
|
|
68
|
+
if (!metadata.customType) return session.admitPrompt(prompt, admission, void 0, requestId);
|
|
69
|
+
if (!session.admitMessage) throw new Error("The session cannot admit a custom delivery.");
|
|
70
|
+
return session.admitMessage({
|
|
71
|
+
type: metadata.customType,
|
|
72
|
+
text: prompt,
|
|
73
|
+
display: true,
|
|
74
|
+
details: metadata.customDetails === void 0 ? void 0 : JSON.parse(metadata.customDetails)
|
|
75
|
+
}, admission === "steer" ? "steer" : "followUp", requestId);
|
|
76
|
+
}
|
|
68
77
|
});
|
|
69
78
|
} catch (error) {
|
|
70
79
|
await groups?.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.mjs","names":["rootSession","apiRoute"],"sources":["../../src/services/peerInbox/index.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/peerInboxApi/index.ts","../../src/extensions/(backend)/api/session-peer/route.server.ts","../../generated/server.ts"],"sourcesContent":["import type { PoSessionDeliveryInboxState } from '../sessionDelivery';\n\nexport type SessionPeerInbox = (\n sourceKey: string,\n type: string,\n payload: unknown,\n) => Promise<PoSessionDeliveryInboxState | undefined> | undefined;\n\nconst inboxes = new Map<string, SessionPeerInbox>();\n\n/**\n * Registers one live session-owned peer inbox. This registry is reachable only by the Session route.\n * The newest registration wins: a Durable Object evicted without disposal leaves its entry in the\n * isolate's module state, and the restarted session must replace it. The hub still rejects two live\n * sessions with one id, and an older unregister cannot remove a newer inbox.\n */\nexport function registerSessionPeerInbox(sessionId: string, inbox: SessionPeerInbox): () => void {\n inboxes.set(sessionId, inbox);\n return () => {\n if (inboxes.get(sessionId) === inbox) inboxes.delete(sessionId);\n };\n}\n\nexport async function deliverSessionPeerEnvelope(\n targetSessionId: string,\n sourceKey: string,\n type: string,\n payload: unknown,\n): Promise<PoSessionDeliveryInboxState | undefined> {\n return inboxes.get(targetSessionId)?.(sourceKey, type, payload);\n}\n","import path from 'node:path';\n\nimport { defineRoot } from '@agimon-ai/po-core/extensionFile';\nimport { poHomeDirectory } from '@agimon-ai/po-core/piSettings';\nimport { BACKGROUND_CONTEXT, requirePoFs, requirePoSqlite } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext } from '@agimon-ai/po-core/serverPlugin';\n\nimport { provideBackgroundWorkService } from '../../../../services/backgroundWorkService';\nimport { registerSessionPeerInbox } from '../../../../services/peerInbox';\nimport {\n createPeerCommunication,\n ensurePrivateDirectory,\n parseRemoteSessionReference,\n peerSessionReference,\n readSessionPeerConfigAsync,\n} from '../../../../services/peerTransport';\nimport { provideSessionDeliveryService } from '../../../../services/sessionDelivery';\nimport { createSessionDirectory } from '../../../../services/sessionDirectory';\nimport { createSessionGroupStore } from '../../../../services/sessionGroups';\nimport {\n PO_SESSION_INTERCOM_SERVICE,\n createSessionGroupDeliveryAuthorizer,\n createSessionIntercom,\n} from '../../../../services/sessionIntercom';\n\nexport default defineRoot((pluginContext: PoServerPluginContext) => ({\n value: undefined,\n services: [\n provideBackgroundWorkService,\n async (context) => {\n const agent = pluginContext.agent;\n const session = agent?.context.session;\n const communication = pluginContext.host.context.sessionCommunication;\n const homeDirectory = pluginContext.host.context.homeDirectory;\n const sessionService = pluginContext.host.context.sessionService;\n if (!agent || !session?.admitPrompt || !communication || !homeDirectory || !sessionService?.canCommunicate) {\n throw new Error(\n 'Session delivery requires the headless agent, authenticated session communication, host home directory, and communication policy.',\n );\n }\n const fs = requirePoFs(pluginContext.context);\n const sqlite = requirePoSqlite(pluginContext.context);\n const io = BACKGROUND_CONTEXT;\n const sessionDirectory = path.join(poHomeDirectory(homeDirectory), 'session');\n const deliveryDirectory = path.join(sessionDirectory, 'delivery');\n await ensurePrivateDirectory(fs, deliveryDirectory, io);\n const peerConfig = await readSessionPeerConfigAsync(fs, homeDirectory, io);\n const peerCommunication = createPeerCommunication({ local: communication, config: peerConfig });\n const remotePeerIsGranted = (peerKey: string): boolean => {\n const peer = parseRemoteSessionReference(peerKey);\n return (\n peer !== undefined &&\n peerConfig?.peers.some(\n (candidate) =>\n candidate.hostId === peer.hostId && candidate.allowedSessionIds.includes(agent.context.sessionId),\n ) === true\n );\n };\n const fallbackAuthorization = (peerKey: string): boolean =>\n sessionService.canCommunicate?.(agent.context.sessionId, peerKey) === true || remotePeerIsGranted(peerKey);\n const groups = peerConfig\n ? await createSessionGroupStore({\n database: await sqlite.open(path.join(sessionDirectory, 'groups.sqlite'), io),\n })\n : undefined;\n const localHostId = peerConfig?.hostId;\n const selfReference = localHostId ? peerSessionReference(localHostId, agent.context.sessionId) : undefined;\n const groupAuthorization =\n groups && selfReference && localHostId\n ? createSessionGroupDeliveryAuthorizer({\n selfReference,\n groups,\n peerReference: (peerKey) =>\n parseRemoteSessionReference(peerKey) === undefined\n ? peerSessionReference(localHostId, peerKey)\n : peerKey,\n fallback: fallbackAuthorization,\n })\n : undefined;\n let delivery: Awaited<ReturnType<typeof provideSessionDeliveryService>>;\n try {\n delivery = await provideSessionDeliveryService(context, {\n database: await sqlite.open(path.join(deliveryDirectory, `${agent.context.sessionId}.sqlite`), io),\n recipientKey: agent.context.sessionId,\n communication: peerCommunication,\n authorizePeer: (peerKey, metadata) =>\n groupAuthorization ? groupAuthorization(peerKey, metadata) : fallbackAuthorization(peerKey),\n admitPrompt: (prompt, admission, requestId) => session.admitPrompt!(prompt, admission, undefined, requestId),\n });\n } catch (error) {\n await groups?.close();\n throw error;\n }\n const { service, close: closeDelivery } = delivery;\n const unprovide: (() => void)[] = [];\n if (groups && selfReference && peerConfig) {\n const directory = createSessionDirectory({\n authorizeDiscovery: async (caller, subject) => {\n const reference = peerSessionReference(subject.hostId, subject.sessionId);\n const permitted = (await groups.groupsFor(caller)).some((group) => group.members.includes(reference));\n return permitted ? { capabilities: ['message'] } : undefined;\n },\n });\n for (const peer of peerConfig.peers)\n for (const sessionId of peer.allowedSessionIds)\n directory.observe({\n hostId: peer.hostId,\n sessionId,\n hostIncarnation: 'unknown',\n sessionIncarnation: 'unknown',\n sequence: 0,\n observedAt: 0,\n staleAfterMs: 0,\n deliveryTarget: peerSessionReference(peer.hostId, sessionId),\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: { eligible: 'unknown', readiness: 'unknown' },\n });\n unprovide.push(\n context.provide(\n PO_SESSION_INTERCOM_SERVICE,\n createSessionIntercom({ selfReference, directory, groups, delivery: service }),\n ),\n );\n }\n const unregister = registerSessionPeerInbox(agent.context.sessionId, (sourceKey, kind, payload) =>\n service.receive?.(sourceKey, kind, payload),\n );\n return async () => {\n unregister();\n for (const release of unprovide.reverse()) release();\n await closeDelivery();\n await groups?.close();\n };\n },\n ],\n}));\n","import path from 'node:path';\n\nimport type { PoApi, PoApiHandler } from '@agimon-ai/po-core/packageApi';\nimport { BACKGROUND_CONTEXT, type PoSqliteService, type FileSystem } from '@agimon-ai/po-core/platform';\n\nimport { deliverSessionPeerEnvelope } from '../peerInbox';\nimport {\n PEER_REPLAY_DATABASE_FILE,\n createPeerReplayGuardAsync,\n ensurePrivateDirectory,\n parseSessionPeerEnvelope,\n peerSessionReference,\n readSessionPeerConfigAsync,\n sessionPeerConfigPath,\n verifyPeerRequest,\n type SessionPeerConfig,\n type SessionPeerReplayGuardAsync,\n} from '../peerTransport';\n\nconst MAX_BODY_BYTES = 64 * 1024;\nconst DELIVERY_TYPES = new Set(['po/session-delivery/envelope', 'po/session-delivery/ack']);\n\nfunction response(status: number, error: string): Response {\n return Response.json({ error }, { status });\n}\n\ninterface PeerInboxState {\n readonly config: SessionPeerConfig | undefined;\n readonly replay: SessionPeerReplayGuardAsync | undefined;\n}\n\n/** Narrow HMAC-authenticated endpoint that a trusted tunnel may forward without device authentication. */\nexport function createPeerInboxApi(platform: { readonly fs: FileSystem; readonly sqlite: PoSqliteService }): PoApi {\n return {\n basePath: 'session-peer',\n start(context): PoApiHandler {\n const homeDirectory = context.homeDirectory;\n // Opened once on first use: the handler starts synchronously, the platform services are async.\n let opened: Promise<PeerInboxState> | undefined;\n const open = (): Promise<PeerInboxState> =>\n (opened ??= (async () => {\n if (homeDirectory === undefined) return { config: undefined, replay: undefined };\n const config = await readSessionPeerConfigAsync(platform.fs, homeDirectory, BACKGROUND_CONTEXT);\n const file = path.join(path.dirname(sessionPeerConfigPath(homeDirectory)), PEER_REPLAY_DATABASE_FILE);\n await ensurePrivateDirectory(platform.fs, path.dirname(file), BACKGROUND_CONTEXT);\n const replay = await createPeerReplayGuardAsync(await platform.sqlite.open(file, BACKGROUND_CONTEXT));\n return { config, replay };\n })().catch((error: unknown) => {\n // A failed open is retried by the next request rather than cached.\n opened = undefined;\n throw error;\n }));\n return {\n async fetch(request) {\n if (request.method !== 'POST' || new URL(request.url).pathname !== '/inbox')\n return response(404, 'Not found.');\n const { config, replay } = await open();\n if (!config) return response(503, 'Paired Session delivery is not configured.');\n const length = request.headers.get('content-length');\n if (length !== null && (!/^\\d+$/u.test(length) || Number(length) > MAX_BODY_BYTES))\n return response(413, 'Request body is too large.');\n const body = await request.text();\n if (Buffer.byteLength(body) > MAX_BODY_BYTES) return response(413, 'Request body is too large.');\n const peer = verifyPeerRequest(config, request, body);\n if (!peer) return response(401, 'Paired Session request is unauthorized.');\n if (!(await replay?.admit(request))) return response(409, 'Paired Session request was already received.');\n let parsed: unknown;\n try {\n parsed = JSON.parse(body) as unknown;\n } catch {\n return response(400, 'Paired Session request is malformed.');\n }\n const envelope = parseSessionPeerEnvelope(parsed);\n if (!envelope || !DELIVERY_TYPES.has(envelope.type))\n return response(400, 'Paired Session envelope is invalid.');\n if (!peer.allowedSessionIds.includes(envelope.targetSessionId))\n return response(403, 'Peer is not granted this session.');\n const state = await deliverSessionPeerEnvelope(\n envelope.targetSessionId,\n peerSessionReference(peer.hostId, envelope.sourceSessionId),\n envelope.type,\n envelope.payload,\n );\n return state === undefined\n ? response(404, 'Target Session is unavailable.')\n : Response.json({ accepted: true, state }, { status: 202 });\n },\n async close() {\n const state = await opened?.catch(() => undefined);\n await state?.replay?.close();\n },\n };\n },\n };\n}\n","import { defineRoute } from '@agimon-ai/po-core/extensionFile';\nimport { requirePoFs, requirePoSqlite } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext } from '@agimon-ai/po-core/serverPlugin';\n\nimport { createPeerInboxApi } from '../../../../services/peerInboxApi';\n\nexport default defineRoute(({ context }: PoServerPluginContext) =>\n createPeerInboxApi({ fs: requirePoFs(context), sqlite: requirePoSqlite(context) }),\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverPlugin';\nimport { composeRootHooks, composeRootInjects } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/session-peer/route.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const serverPlugin = defineServerPlugin({\n name: '@agimon-ai/po-session',\n providerOverrides: composeServerProviderOverrides(rootSession),\n injects: composeRootInjects({ session: [rootSession] }),\n global: (context) => ({\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await context.scopeRoot('session', rootSession, context);\n return {\n ...composeRootHooks(scopeSession),\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): PoServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default serverPlugin;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.mjs","names":["rootSession","apiRoute"],"sources":["../../src/services/peerInbox/index.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/peerInboxApi/index.ts","../../src/extensions/(backend)/api/session-peer/route.server.ts","../../generated/server.ts"],"sourcesContent":["import type { PoSessionDeliveryInboxState } from '../sessionDelivery';\n\nexport type SessionPeerInbox = (\n sourceKey: string,\n type: string,\n payload: unknown,\n) => Promise<PoSessionDeliveryInboxState | undefined> | undefined;\n\nconst inboxes = new Map<string, SessionPeerInbox>();\n\n/**\n * Registers one live session-owned peer inbox. This registry is reachable only by the Session route.\n * The newest registration wins: a Durable Object evicted without disposal leaves its entry in the\n * isolate's module state, and the restarted session must replace it. The hub still rejects two live\n * sessions with one id, and an older unregister cannot remove a newer inbox.\n */\nexport function registerSessionPeerInbox(sessionId: string, inbox: SessionPeerInbox): () => void {\n inboxes.set(sessionId, inbox);\n return () => {\n if (inboxes.get(sessionId) === inbox) inboxes.delete(sessionId);\n };\n}\n\nexport async function deliverSessionPeerEnvelope(\n targetSessionId: string,\n sourceKey: string,\n type: string,\n payload: unknown,\n): Promise<PoSessionDeliveryInboxState | undefined> {\n return inboxes.get(targetSessionId)?.(sourceKey, type, payload);\n}\n","import path from 'node:path';\n\nimport { defineRoot } from '@agimon-ai/po-core/extensionFile';\nimport { poHomeDirectory } from '@agimon-ai/po-core/piSettings';\nimport { BACKGROUND_CONTEXT, requirePoFs, requirePoSqlite } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext } from '@agimon-ai/po-core/serverPlugin';\n\nimport { provideBackgroundWorkService } from '../../../../services/backgroundWorkService';\nimport { registerSessionPeerInbox } from '../../../../services/peerInbox';\nimport {\n createPeerCommunication,\n ensurePrivateDirectory,\n parseRemoteSessionReference,\n peerSessionReference,\n readSessionPeerConfigAsync,\n} from '../../../../services/peerTransport';\nimport { provideSessionDeliveryService } from '../../../../services/sessionDelivery';\nimport { createSessionDirectory } from '../../../../services/sessionDirectory';\nimport { createSessionGroupStore } from '../../../../services/sessionGroups';\nimport {\n PO_SESSION_INTERCOM_SERVICE,\n createSessionGroupDeliveryAuthorizer,\n createSessionIntercom,\n} from '../../../../services/sessionIntercom';\n\nexport default defineRoot((pluginContext: PoServerPluginContext) => ({\n value: undefined,\n services: [\n provideBackgroundWorkService,\n async (context) => {\n const agent = pluginContext.agent;\n const session = agent?.context.session;\n const communication = pluginContext.host.context.sessionCommunication;\n const homeDirectory = pluginContext.host.context.homeDirectory;\n const sessionService = pluginContext.host.context.sessionService;\n if (!agent || !session?.admitPrompt || !communication || !homeDirectory || !sessionService?.canCommunicate) {\n throw new Error(\n 'Session delivery requires the headless agent, authenticated session communication, host home directory, and communication policy.',\n );\n }\n const fs = requirePoFs(pluginContext.context);\n const sqlite = requirePoSqlite(pluginContext.context);\n const io = BACKGROUND_CONTEXT;\n const sessionDirectory = path.join(poHomeDirectory(homeDirectory), 'session');\n const deliveryDirectory = path.join(sessionDirectory, 'delivery');\n await ensurePrivateDirectory(fs, deliveryDirectory, io);\n const peerConfig = await readSessionPeerConfigAsync(fs, homeDirectory, io);\n const peerCommunication = createPeerCommunication({ local: communication, config: peerConfig });\n const remotePeerIsGranted = (peerKey: string): boolean => {\n const peer = parseRemoteSessionReference(peerKey);\n return (\n peer !== undefined &&\n peerConfig?.peers.some(\n (candidate) =>\n candidate.hostId === peer.hostId && candidate.allowedSessionIds.includes(agent.context.sessionId),\n ) === true\n );\n };\n const fallbackAuthorization = (peerKey: string): boolean =>\n sessionService.canCommunicate?.(agent.context.sessionId, peerKey) === true || remotePeerIsGranted(peerKey);\n const groups = peerConfig\n ? await createSessionGroupStore({\n database: await sqlite.open(path.join(sessionDirectory, 'groups.sqlite'), io),\n })\n : undefined;\n const localHostId = peerConfig?.hostId;\n const selfReference = localHostId ? peerSessionReference(localHostId, agent.context.sessionId) : undefined;\n const groupAuthorization =\n groups && selfReference && localHostId\n ? createSessionGroupDeliveryAuthorizer({\n selfReference,\n groups,\n peerReference: (peerKey) =>\n parseRemoteSessionReference(peerKey) === undefined\n ? peerSessionReference(localHostId, peerKey)\n : peerKey,\n fallback: fallbackAuthorization,\n })\n : undefined;\n let delivery: Awaited<ReturnType<typeof provideSessionDeliveryService>>;\n try {\n delivery = await provideSessionDeliveryService(context, {\n database: await sqlite.open(path.join(deliveryDirectory, `${agent.context.sessionId}.sqlite`), io),\n recipientKey: agent.context.sessionId,\n communication: peerCommunication,\n authorizePeer: (peerKey, metadata) =>\n groupAuthorization ? groupAuthorization(peerKey, metadata) : fallbackAuthorization(peerKey),\n admitPrompt: (prompt, admission, requestId, metadata) => {\n if (!metadata.customType) return session.admitPrompt!(prompt, admission, undefined, requestId);\n if (!session.admitMessage) throw new Error('The session cannot admit a custom delivery.');\n return session.admitMessage(\n {\n type: metadata.customType,\n text: prompt,\n display: true,\n details: metadata.customDetails === undefined ? undefined : JSON.parse(metadata.customDetails),\n },\n admission === 'steer' ? 'steer' : 'followUp',\n requestId,\n );\n },\n });\n } catch (error) {\n await groups?.close();\n throw error;\n }\n const { service, close: closeDelivery } = delivery;\n const unprovide: (() => void)[] = [];\n if (groups && selfReference && peerConfig) {\n const directory = createSessionDirectory({\n authorizeDiscovery: async (caller, subject) => {\n const reference = peerSessionReference(subject.hostId, subject.sessionId);\n const permitted = (await groups.groupsFor(caller)).some((group) => group.members.includes(reference));\n return permitted ? { capabilities: ['message'] } : undefined;\n },\n });\n for (const peer of peerConfig.peers)\n for (const sessionId of peer.allowedSessionIds)\n directory.observe({\n hostId: peer.hostId,\n sessionId,\n hostIncarnation: 'unknown',\n sessionIncarnation: 'unknown',\n sequence: 0,\n observedAt: 0,\n staleAfterMs: 0,\n deliveryTarget: peerSessionReference(peer.hostId, sessionId),\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: { eligible: 'unknown', readiness: 'unknown' },\n });\n unprovide.push(\n context.provide(\n PO_SESSION_INTERCOM_SERVICE,\n createSessionIntercom({ selfReference, directory, groups, delivery: service }),\n ),\n );\n }\n const unregister = registerSessionPeerInbox(agent.context.sessionId, (sourceKey, kind, payload) =>\n service.receive?.(sourceKey, kind, payload),\n );\n return async () => {\n unregister();\n for (const release of unprovide.reverse()) release();\n await closeDelivery();\n await groups?.close();\n };\n },\n ],\n}));\n","import path from 'node:path';\n\nimport type { PoApi, PoApiHandler } from '@agimon-ai/po-core/packageApi';\nimport { BACKGROUND_CONTEXT, type PoSqliteService, type FileSystem } from '@agimon-ai/po-core/platform';\n\nimport { deliverSessionPeerEnvelope } from '../peerInbox';\nimport {\n PEER_REPLAY_DATABASE_FILE,\n createPeerReplayGuardAsync,\n ensurePrivateDirectory,\n parseSessionPeerEnvelope,\n peerSessionReference,\n readSessionPeerConfigAsync,\n sessionPeerConfigPath,\n verifyPeerRequest,\n type SessionPeerConfig,\n type SessionPeerReplayGuardAsync,\n} from '../peerTransport';\n\nconst MAX_BODY_BYTES = 64 * 1024;\nconst DELIVERY_TYPES = new Set(['po/session-delivery/envelope', 'po/session-delivery/ack']);\n\nfunction response(status: number, error: string): Response {\n return Response.json({ error }, { status });\n}\n\ninterface PeerInboxState {\n readonly config: SessionPeerConfig | undefined;\n readonly replay: SessionPeerReplayGuardAsync | undefined;\n}\n\n/** Narrow HMAC-authenticated endpoint that a trusted tunnel may forward without device authentication. */\nexport function createPeerInboxApi(platform: { readonly fs: FileSystem; readonly sqlite: PoSqliteService }): PoApi {\n return {\n basePath: 'session-peer',\n start(context): PoApiHandler {\n const homeDirectory = context.homeDirectory;\n // Opened once on first use: the handler starts synchronously, the platform services are async.\n let opened: Promise<PeerInboxState> | undefined;\n const open = (): Promise<PeerInboxState> =>\n (opened ??= (async () => {\n if (homeDirectory === undefined) return { config: undefined, replay: undefined };\n const config = await readSessionPeerConfigAsync(platform.fs, homeDirectory, BACKGROUND_CONTEXT);\n const file = path.join(path.dirname(sessionPeerConfigPath(homeDirectory)), PEER_REPLAY_DATABASE_FILE);\n await ensurePrivateDirectory(platform.fs, path.dirname(file), BACKGROUND_CONTEXT);\n const replay = await createPeerReplayGuardAsync(await platform.sqlite.open(file, BACKGROUND_CONTEXT));\n return { config, replay };\n })().catch((error: unknown) => {\n // A failed open is retried by the next request rather than cached.\n opened = undefined;\n throw error;\n }));\n return {\n async fetch(request) {\n if (request.method !== 'POST' || new URL(request.url).pathname !== '/inbox')\n return response(404, 'Not found.');\n const { config, replay } = await open();\n if (!config) return response(503, 'Paired Session delivery is not configured.');\n const length = request.headers.get('content-length');\n if (length !== null && (!/^\\d+$/u.test(length) || Number(length) > MAX_BODY_BYTES))\n return response(413, 'Request body is too large.');\n const body = await request.text();\n if (Buffer.byteLength(body) > MAX_BODY_BYTES) return response(413, 'Request body is too large.');\n const peer = verifyPeerRequest(config, request, body);\n if (!peer) return response(401, 'Paired Session request is unauthorized.');\n if (!(await replay?.admit(request))) return response(409, 'Paired Session request was already received.');\n let parsed: unknown;\n try {\n parsed = JSON.parse(body) as unknown;\n } catch {\n return response(400, 'Paired Session request is malformed.');\n }\n const envelope = parseSessionPeerEnvelope(parsed);\n if (!envelope || !DELIVERY_TYPES.has(envelope.type))\n return response(400, 'Paired Session envelope is invalid.');\n if (!peer.allowedSessionIds.includes(envelope.targetSessionId))\n return response(403, 'Peer is not granted this session.');\n const state = await deliverSessionPeerEnvelope(\n envelope.targetSessionId,\n peerSessionReference(peer.hostId, envelope.sourceSessionId),\n envelope.type,\n envelope.payload,\n );\n return state === undefined\n ? response(404, 'Target Session is unavailable.')\n : Response.json({ accepted: true, state }, { status: 202 });\n },\n async close() {\n const state = await opened?.catch(() => undefined);\n await state?.replay?.close();\n },\n };\n },\n };\n}\n","import { defineRoute } from '@agimon-ai/po-core/extensionFile';\nimport { requirePoFs, requirePoSqlite } from '@agimon-ai/po-core/platform';\nimport type { PoServerPluginContext } from '@agimon-ai/po-core/serverPlugin';\n\nimport { createPeerInboxApi } from '../../../../services/peerInboxApi';\n\nexport default defineRoute(({ context }: PoServerPluginContext) =>\n createPeerInboxApi({ fs: requirePoFs(context), sqlite: requirePoSqlite(context) }),\n);\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineServerPlugin, type PoServerSessionPlugin } from '@agimon-ai/po-core/serverPlugin';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverPlugin';\nimport { composeRootHooks, composeRootInjects } from '@agimon-ai/po-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/session-peer/route.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n\nexport const serverPlugin = defineServerPlugin({\n name: '@agimon-ai/po-session',\n providerOverrides: composeServerProviderOverrides(rootSession),\n injects: composeRootInjects({ session: [rootSession] }),\n global: (context) => ({\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await context.scopeRoot('session', rootSession, context);\n return {\n ...composeRootHooks(scopeSession),\n get api(): PoServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): PoServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default serverPlugin;\n"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sessionDelivery = require("./sessionDelivery-
|
|
2
|
+
const require_sessionDelivery = require("./sessionDelivery-BAXrVTum.cjs");
|
|
3
3
|
exports.PO_SESSION_DELIVERY_SERVICE = require_sessionDelivery.PO_SESSION_DELIVERY_SERVICE;
|
|
4
4
|
exports.PO_SESSION_INTERCOM_SERVICE = require_sessionDelivery.PO_SESSION_INTERCOM_SERVICE;
|
|
5
5
|
exports.SessionGroupRevisionError = require_sessionDelivery.SessionGroupRevisionError;
|
package/dist/index.d.mts
CHANGED
|
@@ -186,6 +186,10 @@ type PoSessionDeliveryMode = 'prompt' | 'steer' | 'followUp';
|
|
|
186
186
|
interface PoSessionDeliveryMetadata extends Readonly<Record<string, string | undefined>> {
|
|
187
187
|
readonly worktreeId?: string;
|
|
188
188
|
readonly fromRole?: string;
|
|
189
|
+
/** Admit the prompt as a custom message, retaining the model text and separate display details. */
|
|
190
|
+
readonly customType?: string;
|
|
191
|
+
/** JSON-encoded custom-message details, persisted with the delivery for replay. */
|
|
192
|
+
readonly customDetails?: string;
|
|
189
193
|
}
|
|
190
194
|
interface PoSessionDeliveryRequest {
|
|
191
195
|
readonly deliveryId?: string;
|
|
@@ -244,7 +248,7 @@ interface SessionDeliveryServiceOptions {
|
|
|
244
248
|
/** Host-owned relationship check applied before sends, retries, and recipient acceptance. */
|
|
245
249
|
readonly authorizePeer: (peerKey: string, metadata?: PoSessionDeliveryMetadata) => boolean | Promise<boolean>;
|
|
246
250
|
/** `requestId` is the delivery id; the recipient runtime dedupes on it, so a restart may replay an admission. */
|
|
247
|
-
readonly admitPrompt: (prompt: string, delivery: PoSessionDeliveryMode | undefined, requestId: string) => Promise<void>;
|
|
251
|
+
readonly admitPrompt: (prompt: string, delivery: PoSessionDeliveryMode | undefined, requestId: string, metadata: PoSessionDeliveryMetadata) => Promise<void>;
|
|
248
252
|
}
|
|
249
253
|
declare module '@deepseek-ai/cordis' {
|
|
250
254
|
interface Context {
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":["_0"],"sources":["../src/services/backgroundWorkService/index.ts","../src/services/sessionGroups/type.ts","../src/services/peerTransport/config.ts","../src/services/peerTransport/sync.ts","../src/services/peerTransport/index.ts","../src/services/sessionDirectory/type.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts"],"mappings":";;;;;;wBAmBgB,4BAA4B,KAAK,UAAU;;wBAoE3C,6BAA6B,SAAS;;;;KCpF1C,wBAAwB,QAAQ,WAAW;UAEtC;WACN;WACA;WACA;WACA;;UAGM;WACN;WACA;WACA;WACA;WACA;;UAGM;;;;;WAKN,UAAU;WACV,uBAAuB,mBAAmB,OAAO;WACjD,sBAAsB,iBAAiB;;UAGjC;EACf,OAAO,iBAAiB,wBAAwB,6BAA6B,QAAQ;EACrF,OAAO,UAAU,uBAAuB,QAAQ;EAChD,IAAI,kBAAkB,QAAQ;EAC9B,UAAU,0BAA0B,iBAAiB;EACrD,WAAW,iBAAiB,yBAAyB,0BAA0B;EAC/E,SAAS;;qBAGE,kCAAkC;EAC7C,YAAY,iBAAiB,kBAAkB;;;;cCpCpC;UAWI;WACN;WACA;WACA;;WAEA;;WAEA;;UAGM;WACN,gBAAgB;WAChB;WACA,gBAAgB;;UAGV;EACf,MAAM,SAAS,SAAS;EACxB;;UAGe;EACf,MAAM,SAAS,SAAS,eAAe;EACvC,SAAS;;wBAqCK,sBAAsB;;;;;;;;wBCrDtB,sBAAsB,wBAAwB;;;;;;wBAiB9C,sBAAsB,wBAAwB;;;;KCZzD,YAAY,WAAW;UAEX;WACN;WACA;;UAGM;WACN;WACA;WACA;WACA;;;wBAIW,2BACpB,IAAI,YACJ,uBACA,SAAS,YACR,QAAQ;;wBA+BK,4BAA4B,gBAAgB;wBAK5C,qBAAqB,gBAAgB;wBAWrC,mBACd,sBACA,MAAM,aACN,gBACA,kBACA,cACA,eACC;;;;;wBAemB,2BACpB,UAAU,wBACT,QAAQ;wBAoBK,kBACd,QAAQ,mBACR,SAAS,SACT,cACA,eACC;;wBAmCa,wBAAwB;WAC7B,OAAO;;WAEP,QAAQ;WACR,eAAe;IACtB;;;KCtLQ;KACA;KACA;KACA;UAEK;WACN,cAAc;WACd,SAAS;WACT,UAAU;WACV;aACE;aACA,WAAW;;;UAIP,mCAAmC;WACzC;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;UAGM;WACN;WACA;;UAGM,0BAA0B;WAChC;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;UAGM;WACN;WACA,qBACP,yBACA,SAAS,SAAS,KAAK,mEACpB,oCAAoC,QAAQ;;UAGlC;EACf,QAAQ,aAAa;EACrB,oBACE,gBACA,yBACA,uBAAuB;EAEzB,iBAAiB;EACjB,SAAS,yBAAyB,oBAAoB,sBAAsB,iBAAiB;EAC7F,sBAAsB,yBAAyB,oBAAoB;EACnE,UAAU,yBAAyB,WAAW,mBAAmB;;;;;wBCRnD,uBAAuB,SAAS,0BAA0B;;;;wBCOpD,wBAAwB,SAAS,2BAA2B,QAAQ;;;qBCxD7E;KAED;KACA;UAEK,kCAAkC,SAAS;WACjD;WACA;;UAGM;WACN;WACA;WACA;WACA;WACA,WAAW;WACX,WAAW;;UAGL;WACN;WACA,WAAW;WACX,QAAQ;WACR;;UAGM;WACN;WACA;WACA;WACA;WACA;WACA,UAAU;WACV,UAAU;WACV,OAAO;WACP;;UAGM;WACN;WACA;WACA;WACA,UAAU;WACV;WACA,iBAAiB;;UAGX;WACN;EACT,QAAQ,SAAS,2BAA2B;IAAU;;EACtD,iBAAiB,oBAAoB,qBAAqB,QAAQ;EAClE,MAAM,QAAQ,sBAAsB,iBAAiB;;EAErD,SAAS,mBAAmB,cAAc,mBAAmB,QAAQ;EACrE,QAAQ,qBAAqB;EAC7B,OAAO,qBAAqB,QAAQ;EACpC,SAAS;;UAGM;;;;;WAKN,UAAU;WACV;WACA,eAAe;;WAEf,gBAAgB,iBAAiB,WAAW,wCAAwC;;WAEpF,cACP,gBACA,UAAU,mCACV,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":["_0"],"sources":["../src/services/backgroundWorkService/index.ts","../src/services/sessionGroups/type.ts","../src/services/peerTransport/config.ts","../src/services/peerTransport/sync.ts","../src/services/peerTransport/index.ts","../src/services/sessionDirectory/type.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { r as PO_SESSION_DELIVERY_SERVICE, s as PO_SESSION_INTERCOM_SERVICE, d as SessionGroupRevisionError, E as createBackgroundWorkService, p as createPeerCommunication, S as createPeerReplayGuard, m as createPeerReplayGuardAsync, t as createSessionDeliveryService, f as createSessionDirectory, a as createSessionGroupDeliveryAuthorizer, u as createSessionGroupStore, o as createSessionIntercom, g as parseRemoteSessionReference, v as peerRequestHeaders, y as peerSessionReference, D as provideBackgroundWorkService, n as provideSessionDeliveryService, i as readPoSessionDelivery, c as readSessionIntercom, C as readSessionPeerConfig, b as readSessionPeerConfigAsync, l as requireSessionIntercom, T as sessionPeerConfigPath, x as verifyPeerRequest } from "./sessionDelivery-
|
|
1
|
+
export { r as PO_SESSION_DELIVERY_SERVICE, s as PO_SESSION_INTERCOM_SERVICE, d as SessionGroupRevisionError, E as createBackgroundWorkService, p as createPeerCommunication, S as createPeerReplayGuard, m as createPeerReplayGuardAsync, t as createSessionDeliveryService, f as createSessionDirectory, a as createSessionGroupDeliveryAuthorizer, u as createSessionGroupStore, o as createSessionIntercom, g as parseRemoteSessionReference, v as peerRequestHeaders, y as peerSessionReference, D as provideBackgroundWorkService, n as provideSessionDeliveryService, i as readPoSessionDelivery, c as readSessionIntercom, C as readSessionPeerConfig, b as readSessionPeerConfigAsync, l as requireSessionIntercom, T as sessionPeerConfigPath, x as verifyPeerRequest } from "./sessionDelivery-CN7GF38B.mjs";
|
|
@@ -841,7 +841,7 @@ async function createSessionDeliveryService(options) {
|
|
|
841
841
|
if (!row) return;
|
|
842
842
|
publishAck(deliveryId, row.sender_key, "admitting");
|
|
843
843
|
try {
|
|
844
|
-
await options.admitPrompt(row.prompt, row.delivery_mode, deliveryId);
|
|
844
|
+
await options.admitPrompt(row.prompt, row.delivery_mode, deliveryId, JSON.parse(row.metadata_json));
|
|
845
845
|
} catch {
|
|
846
846
|
await database.run(SET_INBOX_STATE, "recovery_required", Date.now(), deliveryId);
|
|
847
847
|
publishAck(deliveryId, row.sender_key, "recovery_required");
|
|
@@ -1216,4 +1216,4 @@ Object.defineProperty(exports, "verifyPeerRequest", {
|
|
|
1216
1216
|
}
|
|
1217
1217
|
});
|
|
1218
1218
|
|
|
1219
|
-
//# sourceMappingURL=sessionDelivery-
|
|
1219
|
+
//# sourceMappingURL=sessionDelivery-BAXrVTum.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionDelivery-BAXrVTum.cjs","names":["PO_BACKGROUND_WORK_CHANGED_EVENT","Check","BackgroundProviderWorkItemSchema","PO_BACKGROUND_WORK_SERVICE","path","poHomeDirectory","fs","path","DatabaseSync","nodeHost","readTextIfExists","path","getOrThrow","createHash","createHmac","timingSafeEqual","envelopeOf","SCHEMA","setInterval","setTimeout"],"sources":["../src/services/backgroundWorkService/index.ts","../src/services/peerTransport/config.ts","../src/services/peerTransport/sync.ts","../src/services/peerTransport/index.ts","../src/services/sessionDirectory/index.ts","../src/services/sessionGroups/type.ts","../src/services/sessionGroups/index.ts","../src/services/sessionIntercom/type.ts","../src/services/sessionIntercom/index.ts","../src/services/sessionDelivery/type.ts","../src/services/sessionDelivery/index.ts"],"sourcesContent":["import {\n BackgroundProviderWorkItemSchema,\n PO_BACKGROUND_WORK_CHANGED_EVENT,\n PO_BACKGROUND_WORK_SERVICE,\n type BackgroundWorkProvider,\n type BackgroundWorkProviderHandle,\n type PoBackgroundWorkService,\n type PoBackgroundWorkSnapshot,\n} from '@agimon-ai/po-core/backgroundWork';\nimport type { Context } from '@deepseek-ai/cordis';\nimport { Check } from 'typebox/value';\n\ninterface ProviderRegistration {\n readonly token: symbol;\n readonly generation: string;\n readonly provider: BackgroundWorkProvider;\n}\n\n/** Creates the generation-bound, pull-based coordinator shared by session extensions. */\nexport function createBackgroundWorkService(ctx: Context): PoBackgroundWorkService {\n const registrations = new Map<string, ProviderRegistration>();\n const generation = `po-background-work:${crypto.randomUUID()}`;\n\n const changed = (\n provider: string,\n providerGeneration: string,\n kind: 'registered' | 'updated' | 'unregistered',\n ): void => {\n ctx.emit(PO_BACKGROUND_WORK_CHANGED_EVENT, { provider, generation: providerGeneration, kind });\n };\n\n const service: PoBackgroundWorkService = {\n generation,\n register(provider): BackgroundWorkProviderHandle {\n if (!provider || typeof provider !== 'object' || typeof provider.listActiveWork !== 'function') {\n throw new TypeError('A background-work provider must expose listActiveWork().');\n }\n const name = provider.provider.trim();\n if (!name || name !== provider.provider) {\n throw new TypeError('A background-work provider requires a trimmed, non-empty name.');\n }\n const token = Symbol(name);\n const providerGeneration = `${name}:${crypto.randomUUID()}`;\n registrations.set(name, { token, generation: providerGeneration, provider });\n changed(name, providerGeneration, 'registered');\n let disposed = false;\n return Object.freeze({\n provider: name,\n generation: providerGeneration,\n update(): void {\n if (!disposed && registrations.get(name)?.token === token) {\n changed(name, providerGeneration, 'updated');\n }\n },\n dispose(): void {\n if (disposed) return;\n disposed = true;\n if (registrations.get(name)?.token !== token) return;\n registrations.delete(name);\n changed(name, providerGeneration, 'unregistered');\n },\n });\n },\n snapshot(sessionId?: string): PoBackgroundWorkSnapshot {\n const items: PoBackgroundWorkSnapshot['items'][number][] = [];\n const errors: PoBackgroundWorkSnapshot['errors'][number][] = [];\n for (const [provider, registration] of registrations) {\n try {\n const current = registration.provider.listActiveWork();\n if (!Array.isArray(current)) throw new TypeError('listActiveWork() must return an array.');\n for (const item of current) {\n if (!Check(BackgroundProviderWorkItemSchema, item)) {\n throw new TypeError('listActiveWork() returned an invalid item.');\n }\n if (sessionId === undefined || item.sessionId === sessionId) items.push({ provider, ...item });\n }\n } catch (error) {\n errors.push({ provider, message: error instanceof Error ? error.message : String(error) });\n }\n }\n return Object.freeze({ items: Object.freeze(items), errors: Object.freeze(errors) });\n },\n };\n return Object.freeze(service);\n}\n\n/** Installs one coordinator in the current session service context. */\nexport function provideBackgroundWorkService(context: Context): void {\n context.provide(PO_BACKGROUND_WORK_SERVICE, createBackgroundWorkService(context));\n}\n","import path from 'node:path';\n\nimport { poHomeDirectory } from '@agimon-ai/po-core/piSettings';\n\nexport const PEER_CONFIG_VERSION = 1;\nconst PEER_CONFIG_FILE = 'peers.json';\nexport const PEER_ROUTE = '/api/plugins/session-peer/inbox';\nexport const PEER_HEADER = 'x-po-session-peer';\nexport const TIMESTAMP_HEADER = 'x-po-session-timestamp';\nexport const SIGNATURE_HEADER = 'x-po-session-signature';\nexport const MAX_CLOCK_SKEW_MS = 5 * 60_000;\nconst MAX_REPLAY_ENTRIES = 10_000;\n/** File the replay guard database lives in, beside the peer config. */\nexport const PEER_REPLAY_DATABASE_FILE = 'peer-replay.sqlite';\n\nexport interface SessionPeer {\n readonly hostId: string;\n readonly url: string;\n readonly secret: string;\n /** Explicit remote durable-message targets. Empty means no delivery grant. */\n readonly allowedSessionIds: readonly string[];\n /** Explicit remote Voice media targets. Empty means no media grant. */\n readonly allowedVoiceSessionIds: readonly string[];\n}\n\nexport interface SessionPeerConfig {\n readonly version: typeof PEER_CONFIG_VERSION;\n readonly hostId: string;\n readonly peers: readonly SessionPeer[];\n}\n\nexport interface SessionPeerReplayGuard {\n admit(request: Request, now?: number): boolean;\n close(): void;\n}\n\nexport interface SessionPeerReplayGuardAsync {\n admit(request: Request, now?: number): Promise<boolean>;\n close(): Promise<void>;\n}\n\nexport function validId(value: unknown): value is string {\n return typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(value);\n}\n\nfunction peerOf(value: unknown): SessionPeer | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n if (!validId(record.hostId) || typeof record.url !== 'string' || typeof record.secret !== 'string') return undefined;\n let url: URL;\n try {\n url = new URL(record.url);\n } catch {\n return undefined;\n }\n if (url.protocol !== 'https:' || url.username !== '' || url.password !== '' || url.search !== '' || url.hash !== '')\n return undefined;\n const allowedSessionIds =\n Array.isArray(record.allowedSessionIds) && record.allowedSessionIds.every(validId)\n ? record.allowedSessionIds\n : undefined;\n const allowedVoiceSessionIds =\n Array.isArray(record.allowedVoiceSessionIds) && record.allowedVoiceSessionIds.every(validId)\n ? record.allowedVoiceSessionIds\n : [];\n if (allowedSessionIds === undefined || record.secret.length < 32) return undefined;\n return {\n hostId: record.hostId,\n url: url.toString(),\n secret: record.secret,\n allowedSessionIds,\n allowedVoiceSessionIds,\n };\n}\n\nexport function sessionPeerConfigPath(homeDirectory: string): string {\n return path.join(poHomeDirectory(homeDirectory), 'session', PEER_CONFIG_FILE);\n}\n\n/** Group or other permission bits on the peer config make it untrusted. */\nexport function peerConfigModeIsPrivate(mode: number): boolean {\n return (mode & 0o077) === 0;\n}\n\n/** Validates peer config text. Invalid config fails closed. */\nexport function parseSessionPeerConfig(text: string): SessionPeerConfig | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n return undefined;\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return undefined;\n const record = parsed as Record<string, unknown>;\n if (record.version !== PEER_CONFIG_VERSION || !validId(record.hostId) || !Array.isArray(record.peers))\n return undefined;\n const peers = record.peers.map(peerOf);\n if (peers.some((peer) => peer === undefined)) return undefined;\n const resolved = peers as SessionPeer[];\n if (\n new Set(resolved.map((peer) => peer.hostId)).size !== resolved.length ||\n resolved.some((peer) => peer.hostId === record.hostId)\n )\n return undefined;\n return { version: PEER_CONFIG_VERSION, hostId: record.hostId, peers: resolved };\n}\n\n/** Replay guard SQL shared by the async guard and the Node-only sync shim. */\nexport const PEER_REPLAY_SQL = Object.freeze({\n // Kept from the Node on-disk schema. Also unique within a Durable Object's shared database:\n // pi-durable's session storage uses durable_*, record_ids, conversations, entries, tasks,\n // submissions, documents and document_revisions, and the edge files use po_fs_*.\n schema: `\n CREATE TABLE IF NOT EXISTS peer_request_replays (\n signature TEXT PRIMARY KEY,\n expires_at INTEGER NOT NULL\n );\n `,\n removeExpired: 'DELETE FROM peer_request_replays WHERE expires_at < ?',\n insert: 'INSERT OR IGNORE INTO peer_request_replays (signature, expires_at) VALUES (?, ?)',\n insertReturning:\n 'INSERT OR IGNORE INTO peer_request_replays (signature, expires_at) VALUES (?, ?) RETURNING signature',\n count: 'SELECT COUNT(*) AS count FROM peer_request_replays',\n trim: `\n DELETE FROM peer_request_replays\n WHERE signature IN (\n SELECT signature FROM peer_request_replays ORDER BY expires_at ASC, signature ASC LIMIT ?\n )\n `,\n});\n\nexport function peerRequestSignature(request: Request): string | null {\n return request.headers.get(SIGNATURE_HEADER);\n}\n\nexport function peerReplayExpiry(now: number): number {\n return now + MAX_CLOCK_SKEW_MS;\n}\n\nexport function peerReplayOverflow(total: number): number {\n return total > MAX_REPLAY_ENTRIES ? total - MAX_REPLAY_ENTRIES : 0;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\n\nimport {\n PEER_REPLAY_DATABASE_FILE,\n PEER_REPLAY_SQL,\n parseSessionPeerConfig,\n peerConfigModeIsPrivate,\n peerReplayExpiry,\n peerReplayOverflow,\n peerRequestSignature,\n sessionPeerConfigPath,\n type SessionPeerConfig,\n type SessionPeerReplayGuard,\n} from './config';\n\n/**\n * Reads operator-provisioned peers. Invalid or unreadable config fails closed.\n *\n * @deprecated Node-only sync shim; use readSessionPeerConfigAsync. Removed in M2.\n */\nexport function readSessionPeerConfig(homeDirectory: string): SessionPeerConfig | undefined {\n let text: string;\n try {\n const file = sessionPeerConfigPath(homeDirectory);\n if (!peerConfigModeIsPrivate(fs.statSync(file).mode)) return undefined;\n text = fs.readFileSync(file, 'utf8');\n } catch {\n return undefined;\n }\n return parseSessionPeerConfig(text);\n}\n\n/**\n * Persists accepted peer signatures so a valid request cannot be replayed within its clock-skew window.\n *\n * @deprecated Node-only sync shim; use createPeerReplayGuardAsync. Removed in M2.\n */\nexport function createPeerReplayGuard(homeDirectory: string): SessionPeerReplayGuard {\n const directory = path.dirname(sessionPeerConfigPath(homeDirectory));\n fs.mkdirSync(directory, { recursive: true, mode: 0o700 });\n const database = new DatabaseSync(path.join(directory, PEER_REPLAY_DATABASE_FILE));\n database.exec(`PRAGMA journal_mode = WAL;${PEER_REPLAY_SQL.schema}`);\n const removeExpired = database.prepare(PEER_REPLAY_SQL.removeExpired);\n const insert = database.prepare(PEER_REPLAY_SQL.insert);\n const count = database.prepare(PEER_REPLAY_SQL.count);\n const trim = database.prepare(PEER_REPLAY_SQL.trim);\n return {\n admit(request, now = Date.now()) {\n const supplied = peerRequestSignature(request);\n if (!supplied) return false;\n database.exec('BEGIN IMMEDIATE');\n try {\n removeExpired.run(now);\n const accepted = insert.run(supplied, peerReplayExpiry(now)).changes === 1;\n const overflow = peerReplayOverflow(Number((count.get() as { count: number | bigint }).count));\n if (overflow > 0) trim.run(overflow);\n database.exec('COMMIT');\n return accepted;\n } catch (cause) {\n database.exec('ROLLBACK');\n throw cause;\n }\n },\n close: () => database.close(),\n };\n}\n","import { createHash, createHmac, timingSafeEqual } from 'node:crypto';\nimport path from 'node:path';\n\nimport type { PoSessionCommunicationEndpoint } from '@agimon-ai/po-core/hubChannel';\nimport { getOrThrow, nodeHost, readTextIfExists, type FileSystem } from '@agimon-ai/po-core/platform';\n\nimport type { SessionSqliteDatabase } from '../sessionGroups/type';\nimport {\n MAX_CLOCK_SKEW_MS,\n PEER_HEADER,\n PEER_REPLAY_SQL,\n PEER_ROUTE,\n SIGNATURE_HEADER,\n TIMESTAMP_HEADER,\n parseSessionPeerConfig,\n peerConfigModeIsPrivate,\n peerReplayExpiry,\n peerReplayOverflow,\n peerRequestSignature,\n sessionPeerConfigPath,\n validId,\n type SessionPeer,\n type SessionPeerConfig,\n type SessionPeerReplayGuardAsync,\n} from './config';\n\n/** chord IO context, reached through po-core so this package needs no direct dependency. */\ntype IoContext = Parameters<FileSystem['readTextFile']>[1];\n\nexport interface RemoteSessionReference {\n readonly hostId: string;\n readonly sessionId: string;\n}\n\nexport interface SessionPeerEnvelope {\n readonly sourceSessionId: string;\n readonly targetSessionId: string;\n readonly type: string;\n readonly payload: unknown;\n}\n\n/** Reads operator-provisioned peers. Invalid or unreadable config fails closed. */\nexport async function readSessionPeerConfigAsync(\n fs: FileSystem,\n homeDirectory: string,\n context: IoContext,\n): Promise<SessionPeerConfig | undefined> {\n try {\n const file = sessionPeerConfigPath(homeDirectory);\n // Undefined: the file is missing (Node) or the host has no modes (edge).\n const mode = await nodeHost.fileMode(file);\n if (mode !== undefined && !peerConfigModeIsPrivate(mode)) return undefined;\n const text = await readTextIfExists(fs, file, context);\n return text === undefined ? undefined : parseSessionPeerConfig(text);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Creates a directory tree, giving each directory it creates owner-only access, the way\n * `mkdirSync(directory, { recursive: true, mode: 0o700 })` does. Existing directories keep their mode.\n */\nexport async function ensurePrivateDirectory(fs: FileSystem, directory: string, context: IoContext): Promise<void> {\n const missing: string[] = [];\n for (let current = path.resolve(directory); !getOrThrow(await fs.exists(current, context));) {\n missing.unshift(current);\n const parent = path.dirname(current);\n if (parent === current) break;\n current = parent;\n }\n if (missing.length === 0) return;\n getOrThrow(await fs.createDir(directory, { recursive: true }, context));\n for (const created of missing) await nodeHost.setMode(created, 0o700);\n}\n\n/** `peer/<host-id>/<session-id>` is the only remote target spelling. */\nexport function parseRemoteSessionReference(value: string): RemoteSessionReference | undefined {\n const match = /^peer\\/([^/]+)\\/([^/]+)$/u.exec(value);\n return match && validId(match[1]) && validId(match[2]) ? { hostId: match[1], sessionId: match[2] } : undefined;\n}\n\nexport function peerSessionReference(hostId: string, sessionId: string): string {\n if (!validId(hostId) || !validId(sessionId))\n throw new TypeError('Remote host and session identifiers must be safe opaque IDs.');\n return `peer/${hostId}/${sessionId}`;\n}\n\nfunction signature(secret: string, method: string, pathname: string, timestamp: string, body: string): string {\n const digest = createHash('sha256').update(body).digest('base64url');\n return createHmac('sha256', secret).update(`${method}\\n${pathname}\\n${timestamp}\\n${digest}`).digest('base64url');\n}\n\nexport function peerRequestHeaders(\n sourceHostId: string,\n peer: SessionPeer,\n method: string,\n pathname: string,\n body: string,\n now = Date.now(),\n): Headers {\n if (!validId(sourceHostId)) throw new TypeError('Source host identity must be a safe opaque ID.');\n const timestamp = String(now);\n return new Headers({\n 'content-type': 'application/json',\n [PEER_HEADER]: sourceHostId,\n [TIMESTAMP_HEADER]: timestamp,\n [SIGNATURE_HEADER]: signature(peer.secret, method, pathname, timestamp, body),\n });\n}\n\n/**\n * Persists accepted peer signatures so a valid request cannot be replayed within its clock-skew window.\n * Takes over the database and closes it in `close()`.\n */\nexport async function createPeerReplayGuardAsync(\n database: SessionSqliteDatabase,\n): Promise<SessionPeerReplayGuardAsync> {\n await database.exec(PEER_REPLAY_SQL.schema);\n return {\n async admit(request, now = Date.now()) {\n const supplied = peerRequestSignature(request);\n if (!supplied) return false;\n return database.transaction(async (transaction) => {\n await transaction.run(PEER_REPLAY_SQL.removeExpired, now);\n const accepted =\n (await transaction.get(PEER_REPLAY_SQL.insertReturning, supplied, peerReplayExpiry(now))) !== undefined;\n const row = await transaction.get<{ count: number | bigint }>(PEER_REPLAY_SQL.count);\n const overflow = peerReplayOverflow(Number(row?.count ?? 0));\n if (overflow > 0) await transaction.run(PEER_REPLAY_SQL.trim, overflow);\n return accepted;\n });\n },\n close: () => database.close(),\n };\n}\n\nexport function verifyPeerRequest(\n config: SessionPeerConfig,\n request: Request,\n body: string,\n now = Date.now(),\n): SessionPeer | undefined {\n const hostId = request.headers.get(PEER_HEADER);\n const timestamp = request.headers.get(TIMESTAMP_HEADER);\n const supplied = request.headers.get(SIGNATURE_HEADER);\n if (!hostId || !timestamp || !supplied || !/^\\d{1,16}$/u.test(timestamp)) return undefined;\n const sentAt = Number(timestamp);\n if (!Number.isSafeInteger(sentAt) || Math.abs(now - sentAt) > MAX_CLOCK_SKEW_MS) return undefined;\n const peer = config.peers.find((candidate) => candidate.hostId === hostId);\n if (!peer) return undefined;\n const expected = Buffer.from(signature(peer.secret, request.method, new URL(request.url).pathname, timestamp, body));\n const actual = Buffer.from(supplied);\n return actual.byteLength === expected.byteLength && timingSafeEqual(actual, expected) ? peer : undefined;\n}\n\nfunction envelopeOf(value: unknown): SessionPeerEnvelope | undefined {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;\n const record = value as Record<string, unknown>;\n return validId(record.sourceSessionId) &&\n validId(record.targetSessionId) &&\n typeof record.type === 'string' &&\n record.type !== ''\n ? {\n sourceSessionId: record.sourceSessionId,\n targetSessionId: record.targetSessionId,\n type: record.type,\n payload: record.payload,\n }\n : undefined;\n}\n\nexport function parseSessionPeerEnvelope(value: unknown): SessionPeerEnvelope | undefined {\n return envelopeOf(value);\n}\n\n/** Adds asynchronous tunnel publication to a host-bound local communication endpoint. */\nexport function createPeerCommunication(options: {\n readonly local: PoSessionCommunicationEndpoint;\n /** Read once by the caller, for example with readSessionPeerConfigAsync. */\n readonly config: SessionPeerConfig | undefined;\n readonly fetch?: typeof fetch;\n}): PoSessionCommunicationEndpoint {\n const config = options.config;\n const send = options.fetch ?? fetch;\n return {\n sessionId: options.local.sessionId,\n publish(target, type, payload) {\n const remote = parseRemoteSessionReference(target);\n if (!remote) return options.local.publish(target, type, payload);\n const peer = config?.peers.find((candidate) => candidate.hostId === remote.hostId);\n // Pairing is not a grant. Outbound delivery needs the same explicit target\n // allowlist that the receiver enforces for inbound envelopes.\n if (!config || !peer || !peer.allowedSessionIds.includes(remote.sessionId)) return false;\n const body = JSON.stringify({\n sourceSessionId: options.local.sessionId,\n targetSessionId: remote.sessionId,\n type,\n payload,\n });\n const url = new URL(PEER_ROUTE, peer.url);\n void send(url, {\n method: 'POST',\n headers: peerRequestHeaders(config.hostId, peer, 'POST', '/inbox', body),\n body,\n }).catch(() => undefined);\n return true;\n },\n subscribe: (type, listener) => options.local.subscribe(type, listener),\n onPeerReady: (listener) => options.local.onPeerReady(listener),\n close: () => options.local.close(),\n };\n}\n\nexport { createPeerReplayGuard, readSessionPeerConfig } from './sync';\nexport {\n PEER_REPLAY_DATABASE_FILE,\n PEER_REPLAY_SQL,\n parseSessionPeerConfig,\n peerConfigModeIsPrivate,\n peerReplayExpiry,\n peerReplayOverflow,\n peerRequestSignature,\n sessionPeerConfigPath,\n type SessionPeer,\n type SessionPeerConfig,\n type SessionPeerReplayGuard,\n type SessionPeerReplayGuardAsync,\n} from './config';\n","import { peerSessionReference } from '../peerTransport';\nimport type {\n DiscoveredSession,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionPresenceFacts,\n SessionPresenceObservation,\n} from './type';\n\nconst UNKNOWN_FACTS: SessionPresenceFacts = Object.freeze({\n reachability: 'unknown',\n runtime: 'unknown',\n activity: 'unknown',\n voice: Object.freeze({ eligible: 'unknown', readiness: 'unknown' }),\n});\n\nfunction keyOf(observation: Pick<SessionPresenceObservation, 'hostId' | 'sessionId'>): string {\n return peerSessionReference(observation.hostId, observation.sessionId);\n}\n\nfunction publicEntry(\n observation: SessionPresenceObservation,\n now: number,\n label: string | undefined,\n capabilities: readonly string[],\n): DiscoveredSession {\n const freshUntil = observation.observedAt + observation.staleAfterMs;\n const fresh = now <= freshUntil;\n const facts: SessionPresenceFacts = fresh ? observation : UNKNOWN_FACTS;\n return Object.freeze({\n reference: keyOf(observation),\n ...(label === undefined ? {} : { label }),\n capabilities: Object.freeze([...capabilities]),\n hostIncarnation: observation.hostIncarnation,\n sessionIncarnation: observation.sessionIncarnation,\n sequence: observation.sequence,\n observedAt: observation.observedAt,\n freshUntil,\n fresh,\n reachability: facts.reachability,\n runtime: facts.runtime,\n activity: facts.activity,\n voice: Object.freeze({ ...facts.voice }),\n });\n}\n\ninterface Subscriber {\n readonly callerReference: string;\n readonly listener: (sessions: readonly DiscoveredSession[]) => void;\n /** Serialises this subscriber's pushes so an older result never lands after a newer one. */\n queue: Promise<void>;\n}\n\n/** In-memory authenticated presence cache. Restart deliberately forgets every observation. */\nexport function createSessionDirectory(options: SessionDirectoryOptions): SessionDirectory {\n const now = options.now ?? Date.now;\n const observations = new Map<string, SessionPresenceObservation>();\n const snapshotRequired = new Set<string>();\n const subscribers = new Set<Subscriber>();\n\n const discover = async (\n callerReference: string,\n allowedReferences?: ReadonlySet<string>,\n ): Promise<readonly DiscoveredSession[]> => {\n const result: DiscoveredSession[] = [];\n // Snapshot first: authorization may await while observations change.\n for (const observation of Array.from(observations.values())) {\n const reference = keyOf(observation);\n if (allowedReferences && !allowedReferences.has(reference)) continue;\n const grant = await options.authorizeDiscovery(callerReference, observation);\n if (!grant) continue;\n result.push(publicEntry(observation, now(), grant.label ?? observation.label, grant.capabilities));\n }\n return result.sort((left, right) => left.reference.localeCompare(right.reference));\n };\n const push = (subscriber: Subscriber): void => {\n subscriber.queue = subscriber.queue\n .then(async () => {\n if (!subscribers.has(subscriber)) return;\n const sessions = await discover(subscriber.callerReference);\n if (subscribers.has(subscriber)) subscriber.listener(sessions);\n })\n .catch(() => undefined);\n };\n const notify = (): void => {\n for (const subscriber of subscribers) push(subscriber);\n };\n\n return {\n observe(observation) {\n const key = keyOf(observation);\n const current = observations.get(key);\n if (snapshotRequired.has(observation.hostId)) return false;\n if (current?.hostIncarnation === observation.hostIncarnation) {\n if (current.sessionIncarnation === observation.sessionIncarnation && observation.sequence <= current.sequence)\n return false;\n if (observation.sequence !== current.sequence + 1) {\n snapshotRequired.add(observation.hostId);\n for (const [reference, candidate] of observations)\n if (candidate.hostId === observation.hostId)\n observations.set(reference, { ...candidate, ...UNKNOWN_FACTS, observedAt: now(), staleAfterMs: 0 });\n notify();\n return false;\n }\n }\n observations.set(key, Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }));\n notify();\n return true;\n },\n replaceHostSnapshot(hostId, hostIncarnation, replacements) {\n if (\n replacements.some(\n (observation) => observation.hostId !== hostId || observation.hostIncarnation !== hostIncarnation,\n )\n ) {\n throw new TypeError('A presence snapshot must contain only the declared host incarnation.');\n }\n for (const [reference, observation] of observations)\n if (observation.hostId === hostId) observations.delete(reference);\n for (const observation of replacements)\n observations.set(\n keyOf(observation),\n Object.freeze({ ...observation, voice: Object.freeze({ ...observation.voice }) }),\n );\n snapshotRequired.delete(hostId);\n notify();\n },\n hostDisconnected(hostId) {\n for (const [reference, observation] of observations) {\n if (observation.hostId !== hostId) continue;\n observations.set(reference, { ...observation, reachability: 'unreachable' });\n }\n notify();\n },\n discover,\n async resolveDeliveryTarget(callerReference, reference) {\n const observation = observations.get(reference);\n return observation && (await options.authorizeDiscovery(callerReference, observation))\n ? observation.deliveryTarget\n : undefined;\n },\n subscribe(callerReference, listener) {\n const subscriber = { callerReference, listener, queue: Promise.resolve() };\n subscribers.add(subscriber);\n push(subscriber);\n return () => subscribers.delete(subscriber);\n },\n };\n}\n\nexport type {\n DiscoveredSession,\n SessionActivityState,\n SessionDirectory,\n SessionDirectoryOptions,\n SessionDiscoveryGrant,\n SessionHostReachability,\n SessionPresenceFacts,\n SessionPresenceObservation,\n SessionRuntimeState,\n SessionVoiceReadiness,\n} from './type';\n","import type { PoSqliteService } from '@agimon-ai/po-core/platform';\n\n/** pi-durable `SqliteDatabase`, reached through po-core so this package needs no direct dependency. */\nexport type SessionSqliteDatabase = Awaited<ReturnType<PoSqliteService['open']>>;\n\nexport interface SessionCommunicationGroup {\n readonly id: string;\n readonly ownerAuthority: string;\n readonly revision: number;\n readonly members: readonly string[];\n}\n\nexport interface SessionGroupMutation {\n readonly groupId: string;\n readonly authority: string;\n readonly expectedRevision: number;\n readonly add?: readonly string[];\n readonly remove?: readonly string[];\n}\n\nexport interface SessionGroupStoreOptions {\n /**\n * Taken over by the store and closed by `close()`. On the edge every open returns the Durable\n * Object's one shared database, so the store's table names must stay unique across that database.\n */\n readonly database: SessionSqliteDatabase;\n readonly authorizeManagement?: (authority: string, group: SessionCommunicationGroup) => boolean;\n readonly validateEnrollment?: (groupId: string, memberReference: string) => boolean;\n}\n\nexport interface SessionGroupStore {\n create(groupId: string, ownerAuthority: string, members: readonly string[]): Promise<SessionCommunicationGroup>;\n mutate(mutation: SessionGroupMutation): Promise<SessionCommunicationGroup>;\n get(groupId: string): Promise<SessionCommunicationGroup | undefined>;\n groupsFor(memberReference: string): Promise<readonly SessionCommunicationGroup[]>;\n canMessage(groupId: string, sourceReference: string, targetReference: string): Promise<boolean>;\n close(): Promise<void>;\n}\n\nexport class SessionGroupRevisionError extends Error {\n constructor(groupId: string, expected: number, actual: number) {\n super(`Session group '${groupId}' revision conflict: expected ${expected}, current ${actual}.`);\n this.name = 'SessionGroupRevisionError';\n }\n}\n","import {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n type SessionSqliteDatabase,\n} from './type';\n\ninterface GroupRow {\n group_id: string;\n owner_authority: string;\n revision: number;\n}\n\nconst ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\nconst REFERENCE_PATTERN = /^peer\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}\\/[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;\n\nfunction validateGroupId(value: string): void {\n if (!ID_PATTERN.test(value)) throw new TypeError('Session group IDs must be safe opaque IDs.');\n}\n\nfunction validateReference(value: string): void {\n if (!REFERENCE_PATTERN.test(value))\n throw new TypeError(`Session group member '${value}' is not a qualified reference.`);\n}\n\ntype SqliteExecutor = Pick<SessionSqliteDatabase, 'exec' | 'run' | 'get' | 'all'>;\n\n// Node keeps its existing on-disk table names. They are also unique within a Durable Object's\n// shared database: pi-durable's session storage uses durable_*, record_ids, conversations,\n// entries, tasks, submissions, documents and document_revisions, and the edge files use po_fs_*.\nconst SCHEMA = `\n CREATE TABLE IF NOT EXISTS session_groups (\n group_id TEXT PRIMARY KEY,\n owner_authority TEXT NOT NULL,\n revision INTEGER NOT NULL\n );\n CREATE TABLE IF NOT EXISTS session_group_members (\n group_id TEXT NOT NULL REFERENCES session_groups(group_id) ON DELETE CASCADE,\n member_reference TEXT NOT NULL,\n PRIMARY KEY (group_id, member_reference)\n );\n`;\n\nasync function readGroup(database: SqliteExecutor, groupId: string): Promise<SessionCommunicationGroup | undefined> {\n const row = await database.get<GroupRow>('SELECT * FROM session_groups WHERE group_id = ?', groupId);\n if (!row) return undefined;\n const members = await database.all<{ member_reference: string }>(\n 'SELECT member_reference FROM session_group_members WHERE group_id = ? ORDER BY member_reference',\n groupId,\n );\n return Object.freeze({\n id: row.group_id,\n ownerAuthority: row.owner_authority,\n revision: Number(row.revision),\n members: Object.freeze(members.map((member) => member.member_reference)),\n });\n}\n\n/** Opens a revisioned SQLite registry for communication-only group membership. */\nexport async function createSessionGroupStore(options: SessionGroupStoreOptions): Promise<SessionGroupStore> {\n const { database } = options;\n try {\n await database.exec('PRAGMA foreign_keys = ON');\n } catch {\n // A Durable Object database always enforces foreign keys and rejects this pragma.\n }\n await database.exec(SCHEMA);\n\n const enroll = async (transaction: SqliteExecutor, groupId: string, members: readonly string[]): Promise<void> => {\n for (const member of new Set(members)) {\n validateReference(member);\n if (options.validateEnrollment?.(groupId, member) === false)\n throw new Error(`Session group enrollment policy rejected '${member}'.`);\n await transaction.run(\n 'INSERT OR IGNORE INTO session_group_members (group_id, member_reference) VALUES (?, ?)',\n groupId,\n member,\n );\n }\n };\n\n return {\n async create(groupId, ownerAuthority, members) {\n validateGroupId(groupId);\n if (!ownerAuthority.trim()) throw new TypeError('Session group owner authority is required.');\n return database.transaction(async (transaction) => {\n await transaction.run(\n 'INSERT INTO session_groups (group_id, owner_authority, revision) VALUES (?, ?, 1)',\n groupId,\n ownerAuthority,\n );\n await enroll(transaction, groupId, members);\n return (await readGroup(transaction, groupId))!;\n });\n },\n async mutate(mutation: SessionGroupMutation) {\n return database.transaction(async (transaction) => {\n const current = await readGroup(transaction, mutation.groupId);\n if (!current) throw new Error(`Session group '${mutation.groupId}' does not exist.`);\n if (\n mutation.authority !== current.ownerAuthority &&\n options.authorizeManagement?.(mutation.authority, current) !== true\n ) {\n throw new Error(`Authority '${mutation.authority}' cannot manage Session group '${mutation.groupId}'.`);\n }\n if (mutation.expectedRevision !== current.revision)\n throw new SessionGroupRevisionError(mutation.groupId, mutation.expectedRevision, current.revision);\n await enroll(transaction, mutation.groupId, mutation.add ?? []);\n for (const member of new Set(mutation.remove ?? [])) {\n validateReference(member);\n await transaction.run(\n 'DELETE FROM session_group_members WHERE group_id = ? AND member_reference = ?',\n mutation.groupId,\n member,\n );\n }\n await transaction.run(\n 'UPDATE session_groups SET revision = revision + 1 WHERE group_id = ? AND revision = ?',\n mutation.groupId,\n current.revision,\n );\n return (await readGroup(transaction, mutation.groupId))!;\n });\n },\n get: (groupId) => readGroup(database, groupId),\n async groupsFor(memberReference) {\n validateReference(memberReference);\n const rows = await database.all<{ group_id: string }>(\n `SELECT g.group_id FROM session_groups g\n INNER JOIN session_group_members m ON m.group_id = g.group_id\n WHERE m.member_reference = ? ORDER BY g.group_id`,\n memberReference,\n );\n const groups: SessionCommunicationGroup[] = [];\n for (const row of rows) {\n const group = await readGroup(database, row.group_id);\n if (group) groups.push(group);\n }\n return groups;\n },\n async canMessage(groupId, sourceReference, targetReference) {\n validateReference(sourceReference);\n validateReference(targetReference);\n const row = await database.get<{ count: number | bigint }>(\n `SELECT COUNT(*) AS count FROM session_group_members\n WHERE group_id = ? AND member_reference IN (?, ?)`,\n groupId,\n sourceReference,\n targetReference,\n );\n return Number(row?.count ?? 0) === (sourceReference === targetReference ? 1 : 2);\n },\n close: () => database.close(),\n };\n}\n\nexport {\n SessionGroupRevisionError,\n type SessionCommunicationGroup,\n type SessionGroupMutation,\n type SessionGroupStore,\n type SessionGroupStoreOptions,\n type SessionSqliteDatabase,\n} from './type';\n","import type { Context } from '@deepseek-ai/cordis';\n\nimport type {\n PoSessionDeliveryMetadata,\n PoSessionDeliveryService,\n PoSessionInboxEntry,\n PoSessionOutboxEntry,\n} from '../sessionDelivery';\nimport type { DiscoveredSession, SessionDirectory } from '../sessionDirectory';\nimport type { SessionGroupStore } from '../sessionGroups';\n\nexport const PO_SESSION_INTERCOM_SERVICE = 'po/session-intercom';\n\nexport type SessionReportStatus = 'done' | 'blocked' | 'failed';\n\nexport interface SessionIntercomMessage {\n readonly deliveryId: string;\n readonly sourceReference: string;\n readonly targetReference: string;\n readonly groupId: string;\n readonly correlationId?: string;\n readonly text: string;\n readonly reportStatus?: SessionReportStatus;\n readonly state: PoSessionInboxEntry['state'];\n readonly consumed: boolean;\n}\n\nexport interface SessionIntercomSendRequest {\n readonly targetReference: string;\n readonly groupId: string;\n readonly text: string;\n readonly correlationId?: string;\n readonly deliveryId?: string;\n}\n\nexport interface SessionIntercomOptions {\n readonly selfReference: string;\n readonly directory: SessionDirectory;\n readonly groups: SessionGroupStore;\n readonly delivery: PoSessionDeliveryService;\n}\n\nexport interface SessionIntercom {\n discover(): Promise<readonly DiscoveredSession[]>;\n send(request: SessionIntercomSendRequest): Promise<{ deliveryId: string }>;\n report(\n request: SessionIntercomSendRequest & { readonly status: SessionReportStatus },\n ): Promise<{ deliveryId: string }>;\n messages(): Promise<readonly SessionIntercomMessage[]>;\n delivery(deliveryId: string): Promise<PoSessionOutboxEntry | undefined>;\n}\n\nexport interface SessionGroupDeliveryAuthorizationOptions {\n readonly selfReference: string;\n readonly groups: SessionGroupStore;\n readonly peerReference: (peerKey: string) => string | undefined;\n readonly fallback?: (peerKey: string, metadata: PoSessionDeliveryMetadata | undefined) => boolean | Promise<boolean>;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'po/session-intercom': SessionIntercom;\n }\n}\n\nexport function readSessionIntercom(context: Context): SessionIntercom | undefined {\n return context.get(PO_SESSION_INTERCOM_SERVICE) as SessionIntercom | undefined;\n}\n\nexport function requireSessionIntercom(context: Context): SessionIntercom {\n const service = readSessionIntercom(context);\n if (!service)\n throw new Error('Session intercom is unavailable. Activate Session with a configured persistent host identity.');\n return service;\n}\n","import type { PoSessionDeliveryMetadata } from '../sessionDelivery';\nimport type { SessionIntercomMessage } from './type';\nimport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n\nconst MESSAGE_KIND = 'session-message';\nconst REPORT_KIND = 'session-report';\n\nasync function metadataFor(\n options: SessionIntercomOptions,\n request: SessionIntercomSendRequest,\n reportStatus?: SessionReportStatus,\n): Promise<PoSessionDeliveryMetadata> {\n const group = await options.groups.get(request.groupId);\n if (!group || !(await options.groups.canMessage(request.groupId, options.selfReference, request.targetReference)))\n throw new Error(`Session group '${request.groupId}' does not authorize this message.`);\n return {\n sourceReference: options.selfReference,\n targetReference: request.targetReference,\n groupId: request.groupId,\n groupRevision: String(group.revision),\n ...(request.correlationId === undefined ? {} : { correlationId: request.correlationId }),\n ...(reportStatus === undefined ? {} : { reportStatus }),\n };\n}\n\n/** The group IDs, among those given, whose current membership includes this session. */\nasync function groupMembership(\n options: SessionIntercomOptions,\n groupIds: readonly (string | undefined)[],\n): Promise<ReadonlySet<string>> {\n const memberOf = new Set<string>();\n for (const groupId of new Set(groupIds)) {\n if (groupId === undefined) continue;\n if ((await options.groups.get(groupId))?.members.includes(options.selfReference) === true) memberOf.add(groupId);\n }\n return memberOf;\n}\n\n/** Agent-facing intercom operations. A composition may acquire this service without gaining session controls. */\nexport function createSessionIntercom(options: SessionIntercomOptions): SessionIntercom {\n const deliver = async (\n request: SessionIntercomSendRequest,\n kind: typeof MESSAGE_KIND | typeof REPORT_KIND,\n status?: SessionReportStatus,\n ): Promise<{ deliveryId: string }> => {\n const recipientKey = await options.directory.resolveDeliveryTarget(options.selfReference, request.targetReference);\n if (!recipientKey) throw new Error(`Session '${request.targetReference}' is not discoverable.`);\n const metadata = await metadataFor(options, request, status);\n return options.delivery.deliver({\n ...(request.deliveryId === undefined ? {} : { deliveryId: request.deliveryId }),\n recipientKey,\n kind,\n prompt: `[Session ${status === undefined ? 'message' : `report: ${status}`} from ${options.selfReference}] ${request.text}`,\n metadata,\n });\n };\n\n const intercom: SessionIntercom = {\n async discover() {\n const members = new Set(\n (await options.groups.groupsFor(options.selfReference))\n .flatMap((group) => group.members)\n .filter((reference) => reference !== options.selfReference),\n );\n return options.directory.discover(options.selfReference, members);\n },\n send: (request) => deliver(request, MESSAGE_KIND),\n report: (request) => deliver(request, REPORT_KIND, request.status),\n async messages() {\n const entries = (await options.delivery.inbox()).filter(\n (entry) => entry.kind === MESSAGE_KIND || entry.kind === REPORT_KIND,\n );\n const memberOf = await groupMembership(\n options,\n entries.map((entry) => entry.metadata.groupId),\n );\n return entries\n .filter((entry) => {\n const groupId = entry.metadata.groupId;\n return groupId !== undefined && memberOf.has(groupId);\n })\n .flatMap((entry): SessionIntercomMessage[] => {\n const sourceReference = entry.metadata.sourceReference;\n const targetReference = entry.metadata.targetReference;\n const groupId = entry.metadata.groupId;\n if (!sourceReference || !targetReference || !groupId) return [];\n const reportStatus = entry.metadata.reportStatus;\n return [\n {\n deliveryId: entry.deliveryId,\n sourceReference,\n targetReference,\n groupId,\n ...(entry.metadata.correlationId === undefined ? {} : { correlationId: entry.metadata.correlationId }),\n text: entry.prompt,\n ...(reportStatus === 'done' || reportStatus === 'blocked' || reportStatus === 'failed'\n ? { reportStatus }\n : {}),\n state: entry.state,\n consumed: entry.consumed,\n },\n ];\n });\n },\n async delivery(deliveryId) {\n const entry = await options.delivery.outbox(deliveryId);\n const groupId = entry?.metadata.groupId;\n return entry && groupId !== undefined && (await groupMembership(options, [groupId])).has(groupId)\n ? entry\n : undefined;\n },\n };\n return Object.freeze(intercom);\n}\n\n/** Builds the dynamic delivery check used before every send, retry, and recipient acceptance. */\nexport function createSessionGroupDeliveryAuthorizer(\n options: SessionGroupDeliveryAuthorizationOptions,\n): (peerKey: string, metadata: PoSessionDeliveryMetadata | undefined) => Promise<boolean> {\n return async (peerKey, metadata) => {\n const sourceReference = metadata?.sourceReference;\n const targetReference = metadata?.targetReference;\n const groupId = metadata?.groupId;\n if (sourceReference && targetReference && groupId) {\n const peerReference = options.peerReference(peerKey);\n if (!peerReference) return false;\n const directionMatches =\n (sourceReference === options.selfReference && targetReference === peerReference) ||\n (targetReference === options.selfReference && sourceReference === peerReference);\n return directionMatches && (await options.groups.canMessage(groupId, sourceReference, targetReference));\n }\n return (await options.fallback?.(peerKey, metadata)) === true;\n };\n}\n\nexport { PO_SESSION_INTERCOM_SERVICE, readSessionIntercom, requireSessionIntercom } from './type';\nexport type {\n SessionGroupDeliveryAuthorizationOptions,\n SessionIntercom,\n SessionIntercomMessage,\n SessionIntercomOptions,\n SessionIntercomSendRequest,\n SessionReportStatus,\n} from './type';\n","import type { PoSessionCommunicationEndpoint } from '@agimon-ai/po-core/hubChannel';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport type { SessionSqliteDatabase } from '../sessionGroups/type';\n\nexport const PO_SESSION_DELIVERY_SERVICE = 'po/session-delivery';\n\nexport type PoSessionDeliveryInboxState = 'accepted' | 'admitting' | 'admitted' | 'recovery_required';\nexport type PoSessionDeliveryMode = 'prompt' | 'steer' | 'followUp';\n\nexport interface PoSessionDeliveryMetadata extends Readonly<Record<string, string | undefined>> {\n readonly worktreeId?: string;\n readonly fromRole?: string;\n /** Admit the prompt as a custom message, retaining the model text and separate display details. */\n readonly customType?: string;\n /** JSON-encoded custom-message details, persisted with the delivery for replay. */\n readonly customDetails?: string;\n}\n\nexport interface PoSessionDeliveryRequest {\n readonly deliveryId?: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery?: PoSessionDeliveryMode;\n readonly metadata?: PoSessionDeliveryMetadata;\n}\n\nexport interface PoSessionInboxQuery {\n readonly kind?: string;\n readonly metadata?: PoSessionDeliveryMetadata;\n readonly state?: PoSessionDeliveryInboxState;\n readonly consumed?: boolean;\n}\n\nexport interface PoSessionInboxEntry {\n readonly deliveryId: string;\n readonly senderKey: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: PoSessionDeliveryMode;\n readonly metadata: PoSessionDeliveryMetadata;\n readonly state: PoSessionDeliveryInboxState;\n readonly consumed: boolean;\n}\n\nexport interface PoSessionOutboxEntry {\n readonly deliveryId: string;\n readonly recipientKey: string;\n readonly kind: string;\n readonly metadata: PoSessionDeliveryMetadata;\n readonly state: 'queued' | 'acknowledged';\n readonly recipientState?: PoSessionDeliveryInboxState;\n}\n\nexport interface PoSessionDeliveryService {\n readonly recipientKey: string;\n deliver(request: PoSessionDeliveryRequest): Promise<{ deliveryId: string }>;\n waitForAdmission(deliveryId: string, timeoutMs?: number): Promise<PoSessionDeliveryInboxState | undefined>;\n inbox(query?: PoSessionInboxQuery): Promise<readonly PoSessionInboxEntry[]>;\n /** Optional host-routed peer envelope admission. Local-only consumers need no transport receiver. */\n receive?(senderKey: string, kind: string, payload: unknown): Promise<PoSessionDeliveryInboxState | undefined>;\n consume(deliveryId: string): Promise<boolean>;\n outbox(deliveryId: string): Promise<PoSessionOutboxEntry | undefined>;\n close(): Promise<void>;\n}\n\nexport interface SessionDeliveryServiceOptions {\n /**\n * Taken over by the service and closed by `close()`. On the edge every open returns the Durable\n * Object's one shared database, so the service's table names must stay unique across that database.\n */\n readonly database: SessionSqliteDatabase;\n readonly recipientKey: string;\n readonly communication: PoSessionCommunicationEndpoint;\n /** Host-owned relationship check applied before sends, retries, and recipient acceptance. */\n readonly authorizePeer: (peerKey: string, metadata?: PoSessionDeliveryMetadata) => boolean | Promise<boolean>;\n /** `requestId` is the delivery id; the recipient runtime dedupes on it, so a restart may replay an admission. */\n readonly admitPrompt: (\n prompt: string,\n delivery: PoSessionDeliveryMode | undefined,\n requestId: string,\n metadata: PoSessionDeliveryMetadata,\n ) => Promise<void>;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'po/session-delivery': PoSessionDeliveryService;\n }\n}\n\n/** Reads the currently active provider each time, without retaining a stale binding. */\nexport function readPoSessionDelivery(context: Context): PoSessionDeliveryService | undefined {\n return context.get(PO_SESSION_DELIVERY_SERVICE) as PoSessionDeliveryService | undefined;\n}\n","import { clearInterval, setInterval, setTimeout } from 'node:timers';\n\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport {\n PO_SESSION_DELIVERY_SERVICE,\n type PoSessionDeliveryInboxState,\n type PoSessionDeliveryMetadata,\n type PoSessionDeliveryMode,\n type PoSessionDeliveryRequest,\n type PoSessionDeliveryService,\n type PoSessionInboxEntry,\n type PoSessionInboxQuery,\n type PoSessionOutboxEntry,\n type SessionDeliveryServiceOptions,\n} from './type';\n\nconst DELIVERY_EVENT = 'po/session-delivery/envelope';\nconst ACK_EVENT = 'po/session-delivery/ack';\nconst DEFAULT_DELIVERY: PoSessionDeliveryMode = 'prompt';\nconst INBOX_STATES = new Set<PoSessionDeliveryInboxState>(['accepted', 'admitting', 'admitted', 'recovery_required']);\n\ninterface DeliveryEnvelope {\n readonly deliveryId: string;\n readonly kind: string;\n readonly prompt: string;\n readonly delivery: PoSessionDeliveryMode;\n readonly metadata: PoSessionDeliveryMetadata;\n}\n\ninterface DeliveryAck {\n readonly deliveryId: string;\n readonly state: PoSessionDeliveryInboxState;\n}\n\ninterface InboxRow {\n delivery_id: string;\n sender_key: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: PoSessionDeliveryMode;\n metadata_json: string;\n state: PoSessionDeliveryInboxState;\n consumed_at: number | null;\n}\n\ninterface OutboxRow {\n delivery_id: string;\n recipient_key: string;\n kind: string;\n prompt: string;\n delivery_mode: PoSessionDeliveryMode;\n metadata_json: string;\n state: 'queued' | 'acknowledged';\n recipient_state: PoSessionDeliveryInboxState | null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isMode(value: unknown): value is PoSessionDeliveryMode {\n return value === 'prompt' || value === 'steer' || value === 'followUp';\n}\n\nfunction metadataOf(value: unknown): PoSessionDeliveryMetadata | undefined {\n if (!isRecord(value)) return undefined;\n const metadata: Record<string, string> = {};\n for (const [key, item] of Object.entries(value)) {\n if (typeof item !== 'string') return undefined;\n metadata[key] = item;\n }\n return metadata;\n}\n\nfunction envelopeOf(value: unknown): DeliveryEnvelope | undefined {\n if (!isRecord(value)) return undefined;\n const metadata = metadataOf(value.metadata);\n if (\n typeof value.deliveryId !== 'string' ||\n !value.deliveryId ||\n typeof value.kind !== 'string' ||\n !value.kind ||\n typeof value.prompt !== 'string' ||\n !isMode(value.delivery) ||\n metadata === undefined\n ) {\n return undefined;\n }\n return {\n deliveryId: value.deliveryId,\n kind: value.kind,\n prompt: value.prompt,\n delivery: value.delivery,\n metadata,\n };\n}\n\nfunction ackOf(value: unknown): DeliveryAck | undefined {\n if (!isRecord(value)) return undefined;\n if (\n typeof value.deliveryId !== 'string' ||\n typeof value.state !== 'string' ||\n !INBOX_STATES.has(value.state as PoSessionDeliveryInboxState)\n ) {\n return undefined;\n }\n return value as unknown as DeliveryAck;\n}\n\nfunction normalizedMetadata(metadata: PoSessionDeliveryMetadata | undefined): PoSessionDeliveryMetadata {\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(metadata ?? {})) {\n if (value !== undefined) normalized[key] = value;\n }\n return normalized;\n}\n\nfunction matchesMetadata(entry: PoSessionDeliveryMetadata, query: PoSessionDeliveryMetadata | undefined): boolean {\n return Object.entries(query ?? {}).every(([key, value]) => value === undefined || entry[key] === value);\n}\n\nfunction sameMetadata(left: PoSessionDeliveryMetadata, right: PoSessionDeliveryMetadata): boolean {\n return matchesMetadata(left, right) && matchesMetadata(right, left);\n}\n\ntype SqliteExecutor = Pick<SessionDeliveryServiceOptions['database'], 'exec' | 'run' | 'get' | 'all'>;\n\n// Node keeps its existing on-disk table names. They are also unique within a Durable Object's\n// shared database: pi-durable's session storage uses durable_*, record_ids, conversations,\n// entries, tasks, submissions, documents and document_revisions, and the edge files use po_fs_*.\nconst SCHEMA = `\n CREATE TABLE IF NOT EXISTS session_delivery_outbox (\n delivery_id TEXT PRIMARY KEY,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n recipient_state TEXT,\n created_at INTEGER NOT NULL,\n acknowledged_at INTEGER\n );\n CREATE TABLE IF NOT EXISTS session_delivery_inbox (\n delivery_id TEXT PRIMARY KEY,\n sender_key TEXT NOT NULL,\n recipient_key TEXT NOT NULL,\n kind TEXT NOT NULL,\n prompt TEXT NOT NULL,\n delivery_mode TEXT NOT NULL,\n metadata_json TEXT NOT NULL,\n state TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n updated_at INTEGER NOT NULL,\n consumed_at INTEGER\n );\n`;\nconst SET_INBOX_STATE = 'UPDATE session_delivery_inbox SET state = ?, updated_at = ? WHERE delivery_id = ?';\nconst UNSETTLED_OUTBOX = \"(recipient_state IS NULL OR recipient_state NOT IN ('admitted', 'recovery_required'))\";\n\n/** Opens and starts one durable delivery endpoint. */\nexport async function createSessionDeliveryService(\n options: SessionDeliveryServiceOptions,\n): Promise<PoSessionDeliveryService> {\n if (!options.recipientKey.trim() || options.recipientKey !== options.recipientKey.trim()) {\n throw new TypeError('Session delivery requires a trimmed, non-empty recipient key.');\n }\n const database: SqliteExecutor & Pick<SessionDeliveryServiceOptions['database'], 'close'> = options.database;\n try {\n await database.exec(SCHEMA);\n // Admission dedupes on the delivery id, so an admission a crash interrupted is safe to replay.\n await database.run(\n \"UPDATE session_delivery_inbox SET state = 'accepted', updated_at = ? WHERE state = 'admitting'\",\n Date.now(),\n );\n } catch (error) {\n await database.close();\n throw error;\n }\n\n let closed = false;\n const scheduled = new Set<string>();\n let admissionQueue = Promise.resolve();\n const pending = new Set<Promise<unknown>>();\n /** Tracks fire-and-forget work so close() can wait for it before the database closes. */\n const track = (work: Promise<unknown>): void => {\n const settled = work.catch(() => undefined);\n pending.add(settled);\n void settled.finally(() => pending.delete(settled));\n };\n const authorized = async (peerKey: string, metadata?: PoSessionDeliveryMetadata): Promise<boolean> =>\n (await options.authorizePeer(peerKey, metadata)) === true;\n\n const publishAck = (deliveryId: string, senderKey: string, state: PoSessionDeliveryInboxState): void => {\n options.communication.publish(senderKey, ACK_EVENT, { deliveryId, state } satisfies DeliveryAck);\n };\n\n const readInboxRow = (deliveryId: string): Promise<InboxRow | undefined> =>\n database.get<InboxRow>('SELECT * FROM session_delivery_inbox WHERE delivery_id = ?', deliveryId);\n\n const scheduleAdmission = (deliveryId: string): void => {\n if (closed || scheduled.has(deliveryId)) return;\n scheduled.add(deliveryId);\n admissionQueue = admissionQueue\n .then(async () => {\n try {\n if (closed) return;\n const row = await database.get<InboxRow>(\n \"UPDATE session_delivery_inbox SET state = 'admitting', updated_at = ? WHERE delivery_id = ? AND state = 'accepted' RETURNING *\",\n Date.now(),\n deliveryId,\n );\n if (!row) return;\n publishAck(deliveryId, row.sender_key, 'admitting');\n try {\n await options.admitPrompt(\n row.prompt,\n row.delivery_mode,\n deliveryId,\n JSON.parse(row.metadata_json) as PoSessionDeliveryMetadata,\n );\n } catch {\n await database.run(SET_INBOX_STATE, 'recovery_required', Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n return;\n }\n await database.run(SET_INBOX_STATE, 'admitted', Date.now(), deliveryId);\n publishAck(deliveryId, row.sender_key, 'admitted');\n } finally {\n scheduled.delete(deliveryId);\n }\n })\n .catch(async () => {\n scheduled.delete(deliveryId);\n try {\n const row = await readInboxRow(deliveryId);\n if (row?.state !== 'admitting') return;\n await database.run(SET_INBOX_STATE, 'recovery_required', Date.now(), deliveryId);\n try {\n publishAck(deliveryId, row.sender_key, 'recovery_required');\n } catch {\n // The durable state is authoritative; readiness replay can request another acknowledgement.\n }\n } catch {\n // A database failure remains recoverable on restart when the schema can be opened again.\n }\n });\n };\n\n const receiveEnvelope = async (\n senderKey: string,\n value: unknown,\n ): Promise<PoSessionDeliveryInboxState | undefined> => {\n if (closed) return undefined;\n const envelope = envelopeOf(value);\n if (!envelope || !(await authorized(senderKey, envelope.metadata)) || closed) return undefined;\n await database.run(\n `INSERT OR IGNORE INTO session_delivery_inbox\n (delivery_id, sender_key, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, 'accepted', ?, ?)`,\n envelope.deliveryId,\n senderKey,\n options.recipientKey,\n envelope.kind,\n envelope.prompt,\n envelope.delivery,\n JSON.stringify(envelope.metadata),\n Date.now(),\n Date.now(),\n );\n const current = await readInboxRow(envelope.deliveryId);\n if (!current) return undefined;\n const sameEnvelope =\n current.sender_key === senderKey &&\n current.recipient_key === options.recipientKey &&\n current.kind === envelope.kind &&\n current.prompt === envelope.prompt &&\n current.delivery_mode === envelope.delivery &&\n sameMetadata(JSON.parse(current.metadata_json) as PoSessionDeliveryMetadata, envelope.metadata);\n if (!sameEnvelope) return undefined;\n publishAck(envelope.deliveryId, current.sender_key, current.state);\n if (current.state === 'accepted') scheduleAdmission(envelope.deliveryId);\n return current.state;\n };\n\n const receiveAck = async (recipientKey: string, value: unknown): Promise<void> => {\n const ack = ackOf(value);\n if (closed || !ack) return;\n await database.run(\n `UPDATE session_delivery_outbox\n SET state = 'acknowledged', recipient_state = ?, acknowledged_at = ?\n WHERE delivery_id = ? AND recipient_key = ?\n AND (recipient_state IS NULL\n OR (recipient_state = 'accepted' AND ? != 'accepted')\n OR (recipient_state = 'admitting' AND ? IN ('admitted', 'recovery_required')))`,\n ack.state,\n Date.now(),\n ack.deliveryId,\n recipientKey,\n ack.state,\n ack.state,\n );\n };\n\n const publishOutbox = async (deliveryId: string): Promise<void> => {\n if (closed) return;\n const row = await database.get<OutboxRow>(\n `SELECT * FROM session_delivery_outbox WHERE delivery_id = ? AND ${UNSETTLED_OUTBOX}`,\n deliveryId,\n );\n if (!row) return;\n const metadata = JSON.parse(row.metadata_json) as PoSessionDeliveryMetadata;\n if (!(await authorized(row.recipient_key, metadata)) || closed) return;\n options.communication.publish(row.recipient_key, DELIVERY_EVENT, {\n deliveryId: row.delivery_id,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n } satisfies DeliveryEnvelope);\n };\n\n const publishQueued = async (recipientKey: string): Promise<void> => {\n if (closed) return;\n for (const row of await database.all<{ delivery_id: string }>(\n `SELECT delivery_id FROM session_delivery_outbox WHERE recipient_key = ? AND ${UNSETTLED_OUTBOX}`,\n recipientKey,\n )) {\n await publishOutbox(row.delivery_id);\n }\n };\n // A publish only means the transport accepted the envelope. Repeat stable delivery\n // IDs until a terminal acknowledgement arrives, including after a tunnel restart.\n // The timer runs only while unsettled rows exist: an idle poll would keep a\n // Durable Object (and its SQLite) awake forever, and unref() is a no-op there.\n let retryTimer: ReturnType<typeof setInterval> | undefined;\n const startRetry = (): void => {\n if (closed || retryTimer) return;\n retryTimer = setInterval(() => track(publishAllQueued()), 1_000);\n retryTimer.unref?.();\n };\n const stopRetry = (): void => {\n if (retryTimer) clearInterval(retryTimer);\n retryTimer = undefined;\n };\n let retrying: Promise<void> | undefined;\n const publishAllQueued = (): Promise<void> => {\n // A slow pass is not overlapped by the next timer tick.\n retrying ??= (async () => {\n try {\n if (closed) return;\n const rows = await database.all<{ delivery_id: string }>(\n `SELECT delivery_id FROM session_delivery_outbox WHERE ${UNSETTLED_OUTBOX}`,\n );\n if (rows.length === 0) stopRetry();\n else startRetry();\n for (const row of rows) {\n await publishOutbox(row.delivery_id);\n }\n } finally {\n retrying = undefined;\n }\n })();\n return retrying;\n };\n const releaseEnvelope = options.communication.subscribe(DELIVERY_EVENT, (senderKey, payload) => {\n track(receiveEnvelope(senderKey, payload));\n });\n const releaseAck = options.communication.subscribe(ACK_EVENT, (recipientKey, payload) => {\n track(receiveAck(recipientKey, payload));\n });\n const releaseReady = options.communication.onPeerReady((recipientKey) => {\n track(publishQueued(recipientKey));\n });\n\n for (const row of await database.all<{ delivery_id: string; sender_key: string }>(\n \"SELECT delivery_id, sender_key FROM session_delivery_inbox WHERE state = 'recovery_required'\",\n )) {\n publishAck(row.delivery_id, row.sender_key, 'recovery_required');\n }\n for (const row of await database.all<{ delivery_id: string }>(\n \"SELECT delivery_id FROM session_delivery_inbox WHERE state = 'accepted'\",\n )) {\n scheduleAdmission(row.delivery_id);\n }\n track(publishAllQueued());\n\n return Object.freeze({\n recipientKey: options.recipientKey,\n async deliver(request: PoSessionDeliveryRequest): Promise<{ deliveryId: string }> {\n if (closed) throw new Error('Session delivery service is closed.');\n const deliveryId = request.deliveryId ?? crypto.randomUUID();\n const mode = request.delivery ?? DEFAULT_DELIVERY;\n if (!deliveryId.trim() || !request.recipientKey.trim() || !request.kind.trim() || !isMode(mode)) {\n throw new TypeError('Delivery id, recipient key, kind, and mode must be valid.');\n }\n if (!(await authorized(request.recipientKey, request.metadata))) {\n throw new Error(`Session '${request.recipientKey}' is not an authorized communication peer.`);\n }\n if (closed) throw new Error('Session delivery service is closed.');\n const metadata = normalizedMetadata(request.metadata);\n await database.run(\n `INSERT OR IGNORE INTO session_delivery_outbox\n (delivery_id, recipient_key, kind, prompt, delivery_mode, metadata_json, state, created_at)\n VALUES (?, ?, ?, ?, ?, ?, 'queued', ?)`,\n deliveryId,\n request.recipientKey,\n request.kind,\n request.prompt,\n mode,\n JSON.stringify(metadata),\n Date.now(),\n );\n const current = await database.get<OutboxRow>(\n 'SELECT * FROM session_delivery_outbox WHERE delivery_id = ?',\n deliveryId,\n );\n if (\n !current ||\n current.recipient_key !== request.recipientKey ||\n current.kind !== request.kind ||\n current.prompt !== request.prompt ||\n current.delivery_mode !== mode ||\n !sameMetadata(JSON.parse(current.metadata_json) as PoSessionDeliveryMetadata, metadata)\n ) {\n throw new TypeError(`Delivery id '${deliveryId}' is already bound to another envelope.`);\n }\n startRetry();\n await publishOutbox(deliveryId);\n return { deliveryId };\n },\n async waitForAdmission(deliveryId: string, timeoutMs = 5_000): Promise<PoSessionDeliveryInboxState | undefined> {\n const deadline = Date.now() + Math.max(0, timeoutMs);\n let state: PoSessionDeliveryInboxState | undefined;\n do {\n const row = await database.get<{ recipient_state: PoSessionDeliveryInboxState | null }>(\n 'SELECT recipient_state FROM session_delivery_outbox WHERE delivery_id = ?',\n deliveryId,\n );\n state = row?.recipient_state ?? undefined;\n if (state === 'admitted' || state === 'recovery_required') return state;\n if (Date.now() >= deadline) return state;\n await new Promise((resolve) => setTimeout(resolve, Math.min(10, deadline - Date.now())));\n } while (!closed);\n return state;\n },\n async receive(senderKey: string, kind: string, payload: unknown) {\n if (kind === DELIVERY_EVENT) return receiveEnvelope(senderKey, payload);\n if (kind === ACK_EVENT) {\n await receiveAck(senderKey, payload);\n return 'accepted';\n }\n return undefined;\n },\n async inbox(query: PoSessionInboxQuery = {}): Promise<readonly PoSessionInboxEntry[]> {\n const rows = await database.all<InboxRow>(\n 'SELECT * FROM session_delivery_inbox ORDER BY created_at, delivery_id',\n );\n return rows\n .map((row): PoSessionInboxEntry => {\n const metadata = JSON.parse(row.metadata_json) as PoSessionDeliveryMetadata;\n return {\n deliveryId: row.delivery_id,\n senderKey: row.sender_key,\n recipientKey: row.recipient_key,\n kind: row.kind,\n prompt: row.prompt,\n delivery: row.delivery_mode,\n metadata,\n state: row.state,\n consumed: row.consumed_at !== null,\n };\n })\n .filter(\n (entry) =>\n (query.kind === undefined || entry.kind === query.kind) &&\n (query.state === undefined || entry.state === query.state) &&\n (query.consumed === undefined || entry.consumed === query.consumed) &&\n matchesMetadata(entry.metadata, query.metadata),\n );\n },\n async consume(deliveryId: string): Promise<boolean> {\n const consumed = await database.get<{ delivery_id: string }>(\n \"UPDATE session_delivery_inbox SET consumed_at = ? WHERE delivery_id = ? AND state IN ('admitted', 'recovery_required') AND consumed_at IS NULL RETURNING delivery_id\",\n Date.now(),\n deliveryId,\n );\n return consumed !== undefined;\n },\n async outbox(deliveryId: string): Promise<PoSessionOutboxEntry | undefined> {\n const row = await database.get<OutboxRow>(\n 'SELECT delivery_id, recipient_key, kind, metadata_json, state, recipient_state FROM session_delivery_outbox WHERE delivery_id = ?',\n deliveryId,\n );\n if (!row) return undefined;\n return {\n deliveryId: row.delivery_id,\n recipientKey: row.recipient_key,\n kind: row.kind,\n metadata: JSON.parse(row.metadata_json) as PoSessionDeliveryMetadata,\n state: row.state,\n ...(row.recipient_state === null ? {} : { recipientState: row.recipient_state }),\n };\n },\n async close(): Promise<void> {\n if (closed) return;\n closed = true;\n stopRetry();\n releaseEnvelope();\n releaseAck();\n releaseReady();\n try {\n await admissionQueue;\n await Promise.all(pending);\n } finally {\n await database.close();\n }\n },\n });\n}\n\n/**\n * Installs a provider-owned endpoint in the current Cordis context.\n *\n * Returns the instance because a provider cannot read its own service back out:\n * `ctx.get` is strict and hides an implementation while its providing fiber is\n * LOADING, which is the whole of that fiber's own callback.\n */\nexport async function provideSessionDeliveryService(\n context: Context,\n options: SessionDeliveryServiceOptions,\n): Promise<{ readonly service: PoSessionDeliveryService; readonly close: () => Promise<void> }> {\n const service = await createSessionDeliveryService(options);\n const unprovide = context.provide(PO_SESSION_DELIVERY_SERVICE, service);\n // A caller that throws before returning its disposer would otherwise leave the\n // database, its WAL files and its retry timer open for the life of the process.\n // close() is idempotent, so this net never conflicts with the ordered close below.\n context.effect(() => () => service.close(), 'session delivery database');\n return {\n service,\n close: async () => {\n unprovide();\n await service.close();\n },\n };\n}\n\nexport type {\n PoSessionDeliveryInboxState,\n PoSessionDeliveryMetadata,\n PoSessionDeliveryMode,\n PoSessionDeliveryRequest,\n PoSessionDeliveryService,\n PoSessionInboxEntry,\n PoSessionInboxQuery,\n PoSessionOutboxEntry,\n SessionDeliveryServiceOptions,\n} from './type';\nexport { PO_SESSION_DELIVERY_SERVICE, readPoSessionDelivery } from './type';\n"],"mappings":"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"}
|
|
@@ -817,7 +817,7 @@ async function createSessionDeliveryService(options) {
|
|
|
817
817
|
if (!row) return;
|
|
818
818
|
publishAck(deliveryId, row.sender_key, "admitting");
|
|
819
819
|
try {
|
|
820
|
-
await options.admitPrompt(row.prompt, row.delivery_mode, deliveryId);
|
|
820
|
+
await options.admitPrompt(row.prompt, row.delivery_mode, deliveryId, JSON.parse(row.metadata_json));
|
|
821
821
|
} catch {
|
|
822
822
|
await database.run(SET_INBOX_STATE, "recovery_required", Date.now(), deliveryId);
|
|
823
823
|
publishAck(deliveryId, row.sender_key, "recovery_required");
|
|
@@ -1025,4 +1025,4 @@ async function provideSessionDeliveryService(context, options) {
|
|
|
1025
1025
|
//#endregion
|
|
1026
1026
|
export { readSessionPeerConfig as C, provideBackgroundWorkService as D, createBackgroundWorkService as E, createPeerReplayGuard as S, sessionPeerConfigPath as T, parseSessionPeerEnvelope as _, createSessionGroupDeliveryAuthorizer as a, readSessionPeerConfigAsync as b, readSessionIntercom as c, SessionGroupRevisionError as d, createSessionDirectory as f, parseRemoteSessionReference as g, ensurePrivateDirectory as h, readPoSessionDelivery as i, requireSessionIntercom as l, createPeerReplayGuardAsync as m, provideSessionDeliveryService as n, createSessionIntercom as o, createPeerCommunication as p, PO_SESSION_DELIVERY_SERVICE as r, PO_SESSION_INTERCOM_SERVICE as s, createSessionDeliveryService as t, createSessionGroupStore as u, peerRequestHeaders as v, PEER_REPLAY_DATABASE_FILE as w, verifyPeerRequest as x, peerSessionReference as y };
|
|
1027
1027
|
|
|
1028
|
-
//# sourceMappingURL=sessionDelivery-
|
|
1028
|
+
//# sourceMappingURL=sessionDelivery-CN7GF38B.mjs.map
|