@agimon-ai/po-session 0.0.0-alpha.12 → 0.0.0-alpha.14
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.
|
@@ -7,7 +7,7 @@ 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");
|
|
9
9
|
let _agimon_ai_po_core_piSettings = require("@agimon-ai/po-core/piSettings");
|
|
10
|
-
let
|
|
10
|
+
let _agimon_ai_po_core_serverPlugin = require("@agimon-ai/po-core/serverPlugin");
|
|
11
11
|
let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
|
|
12
12
|
//#region src/services/peerInbox/index.ts
|
|
13
13
|
const inboxes = /* @__PURE__ */ new Map();
|
|
@@ -188,9 +188,10 @@ var route_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoute)(({
|
|
|
188
188
|
//#endregion
|
|
189
189
|
//#region generated/server.ts
|
|
190
190
|
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
191
|
-
const
|
|
191
|
+
const serverPlugin = (0, _agimon_ai_po_core_serverPlugin.defineServerPlugin)({
|
|
192
192
|
name: "@agimon-ai/po-session",
|
|
193
|
-
providerOverrides: (0,
|
|
193
|
+
providerOverrides: (0, _agimon_ai_po_core_serverPlugin.composeServerProviderOverrides)(root_server_default),
|
|
194
|
+
injects: (0, _agimon_ai_po_core_extensionFile.composeRootInjects)({ session: [root_server_default] }),
|
|
194
195
|
global: (context) => ({ get api() {
|
|
195
196
|
return [at(route_server_default, context)];
|
|
196
197
|
} }),
|
|
@@ -198,7 +199,7 @@ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
|
|
|
198
199
|
return [at(route_server_default, context)];
|
|
199
200
|
} }),
|
|
200
201
|
session: async (context) => {
|
|
201
|
-
const scopeSession = await root_server_default
|
|
202
|
+
const scopeSession = await context.scopeRoot("session", root_server_default, context);
|
|
202
203
|
return {
|
|
203
204
|
...(0, _agimon_ai_po_core_extensionFile.composeRootHooks)(scopeSession),
|
|
204
205
|
get api() {
|
|
@@ -212,7 +213,7 @@ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
|
|
|
212
213
|
}
|
|
213
214
|
});
|
|
214
215
|
//#endregion
|
|
215
|
-
exports.default =
|
|
216
|
-
exports.
|
|
216
|
+
exports.default = serverPlugin;
|
|
217
|
+
exports.serverPlugin = serverPlugin;
|
|
217
218
|
|
|
218
219
|
//# sourceMappingURL=server.cjs.map
|
|
@@ -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","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/serverFacet';\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/serverFacet';\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/serverFacet';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverFacet';\nimport { composeRootHooks } 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 facet = defineServerPlugin({\n name: '@agimon-ai/po-session',\n providerOverrides: composeServerProviderOverrides(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 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 facet;\n"],"mappings":";;;;;;;;;;;;AAQA,MAAM,0BAAU,IAAI,IAA8B;;;;;;;AAQlD,SAAgB,yBAAyB,WAAmB,OAAqC;CAC/F,QAAQ,IAAI,WAAW,KAAK;CAC5B,aAAa;EACX,IAAI,QAAQ,IAAI,SAAS,MAAM,OAAO,QAAQ,OAAO,SAAS;CAChE;AACF;AAEA,eAAsB,2BACpB,iBACA,WACA,MACA,SACkD;CAClD,OAAO,QAAQ,IAAI,eAAe,CAAC,GAAG,WAAW,MAAM,OAAO;AAChE;;;ACLA,IAAA,uBAAA,GAAeA,iCAAAA,WAAAA,EAAY,mBAA0C;CACnE,OAAO,KAAA;CACP,UAAU,CACRC,wBAAAA,8BACA,OAAO,YAAY;EACjB,MAAM,QAAQ,cAAc;EAC5B,MAAM,UAAU,OAAO,QAAQ;EAC/B,MAAM,gBAAgB,cAAc,KAAK,QAAQ;EACjD,MAAM,gBAAgB,cAAc,KAAK,QAAQ;EACjD,MAAM,iBAAiB,cAAc,KAAK,QAAQ;EAClD,IAAI,CAAC,SAAS,CAAC,SAAS,eAAe,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,gBAAgB,gBAC1F,MAAM,IAAI,MACR,mIACF;EAEF,MAAM,MAAA,GAAKC,4BAAAA,YAAAA,CAAY,cAAc,OAAO;EAC5C,MAAM,UAAA,GAASC,4BAAAA,gBAAAA,CAAgB,cAAc,OAAO;EACpD,MAAM,KAAKC,4BAAAA;EACX,MAAM,mBAAmBC,UAAAA,QAAK,MAAA,GAAKC,8BAAAA,gBAAAA,CAAgB,aAAa,GAAG,SAAS;EAC5E,MAAM,oBAAoBD,UAAAA,QAAK,KAAK,kBAAkB,UAAU;EAChE,MAAME,wBAAAA,uBAAuB,IAAI,mBAAmB,EAAE;EACtD,MAAM,aAAa,MAAMC,wBAAAA,2BAA2B,IAAI,eAAe,EAAE;EACzE,MAAM,oBAAoBC,wBAAAA,wBAAwB;GAAE,OAAO;GAAe,QAAQ;EAAW,CAAC;EAC9F,MAAM,uBAAuB,YAA6B;GACxD,MAAM,OAAOC,wBAAAA,4BAA4B,OAAO;GAChD,OACE,SAAS,KAAA,KACT,YAAY,MAAM,MACf,cACC,UAAU,WAAW,KAAK,UAAU,UAAU,kBAAkB,SAAS,MAAM,QAAQ,SAAS,CACpG,MAAM;EAEV;EACA,MAAM,yBAAyB,YAC7B,eAAe,iBAAiB,MAAM,QAAQ,WAAW,OAAO,MAAM,QAAQ,oBAAoB,OAAO;EAC3G,MAAM,SAAS,aACX,MAAMC,wBAAAA,wBAAwB,EAC5B,UAAU,MAAM,OAAO,KAAKN,UAAAA,QAAK,KAAK,kBAAkB,eAAe,GAAG,EAAE,EAC9E,CAAC,IACD,KAAA;EACJ,MAAM,cAAc,YAAY;EAChC,MAAM,gBAAgB,cAAcO,wBAAAA,qBAAqB,aAAa,MAAM,QAAQ,SAAS,IAAI,KAAA;EACjG,MAAM,qBACJ,UAAU,iBAAiB,cACvBC,wBAAAA,qCAAqC;GACnC;GACA;GACA,gBAAgB,YACdH,wBAAAA,4BAA4B,OAAO,MAAM,KAAA,IACrCE,wBAAAA,qBAAqB,aAAa,OAAO,IACzC;GACN,UAAU;EACZ,CAAC,IACD,KAAA;EACN,IAAI;EACJ,IAAI;GACF,WAAW,MAAME,wBAAAA,8BAA8B,SAAS;IACtD,UAAU,MAAM,OAAO,KAAKT,UAAAA,QAAK,KAAK,mBAAmB,GAAG,MAAM,QAAQ,UAAU,QAAQ,GAAG,EAAE;IACjG,cAAc,MAAM,QAAQ;IAC5B,eAAe;IACf,gBAAgB,SAAS,aACvB,qBAAqB,mBAAmB,SAAS,QAAQ,IAAI,sBAAsB,OAAO;IAC5F,cAAc,QAAQ,WAAW,cAAc,QAAQ,YAAa,QAAQ,WAAW,KAAA,GAAW,SAAS;GAC7G,CAAC;EACH,SAAS,OAAO;GACd,MAAM,QAAQ,MAAM;GACpB,MAAM;EACR;EACA,MAAM,EAAE,SAAS,OAAO,kBAAkB;EAC1C,MAAM,YAA4B,CAAC;EACnC,IAAI,UAAU,iBAAiB,YAAY;GACzC,MAAM,YAAYU,wBAAAA,uBAAuB,EACvC,oBAAoB,OAAO,QAAQ,YAAY;IAC7C,MAAM,YAAYH,wBAAAA,qBAAqB,QAAQ,QAAQ,QAAQ,SAAS;IAExE,QADmB,MAAM,OAAO,UAAU,MAAM,EAAA,CAAG,MAAM,UAAU,MAAM,QAAQ,SAAS,SAAS,CACpF,IAAI,EAAE,cAAc,CAAC,SAAS,EAAE,IAAI,KAAA;GACrD,EACF,CAAC;GACD,KAAK,MAAM,QAAQ,WAAW,OAC5B,KAAK,MAAM,aAAa,KAAK,mBAC3B,UAAU,QAAQ;IAChB,QAAQ,KAAK;IACb;IACA,iBAAiB;IACjB,oBAAoB;IACpB,UAAU;IACV,YAAY;IACZ,cAAc;IACd,gBAAgBA,wBAAAA,qBAAqB,KAAK,QAAQ,SAAS;IAC3D,cAAc;IACd,SAAS;IACT,UAAU;IACV,OAAO;KAAE,UAAU;KAAW,WAAW;IAAU;GACrD,CAAC;GACL,UAAU,KACR,QAAQ,QACNI,wBAAAA,6BACAC,wBAAAA,sBAAsB;IAAE;IAAe;IAAW;IAAQ,UAAU;GAAQ,CAAC,CAC/E,CACF;EACF;EACA,MAAM,aAAa,yBAAyB,MAAM,QAAQ,YAAY,WAAW,MAAM,YACrF,QAAQ,UAAU,WAAW,MAAM,OAAO,CAC5C;EACA,OAAO,YAAY;GACjB,WAAW;GACX,KAAK,MAAM,WAAW,UAAU,QAAQ,GAAG,QAAQ;GACnD,MAAM,cAAc;GACpB,MAAM,QAAQ,MAAM;EACtB;CACF,CACF;AACF,EAAE;;;ACtHF,MAAM,iBAAiB;AACvB,MAAM,iCAAiB,IAAI,IAAI,CAAC,gCAAgC,yBAAyB,CAAC;AAE1F,SAAS,SAAS,QAAgB,OAAyB;CACzD,OAAO,SAAS,KAAK,EAAE,MAAM,GAAG,EAAE,OAAO,CAAC;AAC5C;;AAQA,SAAgB,mBAAmB,UAAgF;CACjH,OAAO;EACL,UAAU;EACV,MAAM,SAAuB;GAC3B,MAAM,gBAAgB,QAAQ;GAE9B,IAAI;GACJ,MAAM,aACH,YAAY,YAAY;IACvB,IAAI,kBAAkB,KAAA,GAAW,OAAO;KAAE,QAAQ,KAAA;KAAW,QAAQ,KAAA;IAAU;IAC/E,MAAM,SAAS,MAAMC,wBAAAA,2BAA2B,SAAS,IAAI,eAAeC,4BAAAA,kBAAkB;IAC9F,MAAM,OAAOC,UAAAA,QAAK,KAAKA,UAAAA,QAAK,QAAQC,wBAAAA,sBAAsB,aAAa,CAAC,GAAGC,wBAAAA,yBAAyB;IACpG,MAAMC,wBAAAA,uBAAuB,SAAS,IAAIH,UAAAA,QAAK,QAAQ,IAAI,GAAGD,4BAAAA,kBAAkB;IAEhF,OAAO;KAAE;KAAQ,QAAA,MADIK,wBAAAA,2BAA2B,MAAM,SAAS,OAAO,KAAK,MAAML,4BAAAA,kBAAkB,CAAC;IAC5E;GAC1B,EAAA,CAAG,CAAC,CAAC,OAAO,UAAmB;IAE7B,SAAS,KAAA;IACT,MAAM;GACR,CAAC;GACH,OAAO;IACL,MAAM,MAAM,SAAS;KACnB,IAAI,QAAQ,WAAW,UAAU,IAAI,IAAI,QAAQ,GAAG,CAAC,CAAC,aAAa,UACjE,OAAO,SAAS,KAAK,YAAY;KACnC,MAAM,EAAE,QAAQ,WAAW,MAAM,KAAK;KACtC,IAAI,CAAC,QAAQ,OAAO,SAAS,KAAK,4CAA4C;KAC9E,MAAM,SAAS,QAAQ,QAAQ,IAAI,gBAAgB;KACnD,IAAI,WAAW,SAAS,CAAC,SAAS,KAAK,MAAM,KAAK,OAAO,MAAM,IAAI,iBACjE,OAAO,SAAS,KAAK,4BAA4B;KACnD,MAAM,OAAO,MAAM,QAAQ,KAAK;KAChC,IAAI,OAAO,WAAW,IAAI,IAAI,gBAAgB,OAAO,SAAS,KAAK,4BAA4B;KAC/F,MAAM,OAAOM,wBAAAA,kBAAkB,QAAQ,SAAS,IAAI;KACpD,IAAI,CAAC,MAAM,OAAO,SAAS,KAAK,yCAAyC;KACzE,IAAI,CAAE,MAAM,QAAQ,MAAM,OAAO,GAAI,OAAO,SAAS,KAAK,8CAA8C;KACxG,IAAI;KACJ,IAAI;MACF,SAAS,KAAK,MAAM,IAAI;KAC1B,QAAQ;MACN,OAAO,SAAS,KAAK,sCAAsC;KAC7D;KACA,MAAM,WAAWC,wBAAAA,yBAAyB,MAAM;KAChD,IAAI,CAAC,YAAY,CAAC,eAAe,IAAI,SAAS,IAAI,GAChD,OAAO,SAAS,KAAK,qCAAqC;KAC5D,IAAI,CAAC,KAAK,kBAAkB,SAAS,SAAS,eAAe,GAC3D,OAAO,SAAS,KAAK,mCAAmC;KAC1D,MAAM,QAAQ,MAAM,2BAClB,SAAS,iBACTC,wBAAAA,qBAAqB,KAAK,QAAQ,SAAS,eAAe,GAC1D,SAAS,MACT,SAAS,OACX;KACA,OAAO,UAAU,KAAA,IACb,SAAS,KAAK,gCAAgC,IAC9C,SAAS,KAAK;MAAE,UAAU;MAAM;KAAM,GAAG,EAAE,QAAQ,IAAI,CAAC;IAC9D;IACA,MAAM,QAAQ;KAEZ,OAAM,MADc,QAAQ,YAAY,KAAA,CAAS,EAAA,EACpC,QAAQ,MAAM;IAC7B;GACF;EACF;CACF;AACF;;;ACxFA,IAAA,wBAAA,GAAeC,iCAAAA,YAAAA,EAAa,EAAE,cAC5B,mBAAmB;CAAE,KAAA,GAAIC,4BAAAA,YAAAA,CAAY,OAAO;CAAG,SAAA,GAAQC,4BAAAA,gBAAAA,CAAgB,OAAO;AAAE,CAAC,CACnF;;;ACCA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAa,SAAA,GAAQC,+BAAAA,mBAAAA,CAAmB;CACtC,MAAM;CACN,oBAAA,GAAmBC,+BAAAA,+BAAAA,CAA+BC,mBAAW;CAC7D,SAAS,aAAa,EACpB,IAAI,MAAoC;EAAE,OAAO,CAAC,GAAGC,sBAAU,OAAO,CAAC;CAAG,EAC5E;CACA,YAAY,aAAa,EACvB,IAAI,MAAoC;EAAE,OAAO,CAAC,GAAGA,sBAAU,OAAO,CAAC;CAAG,EAC5E;CACA,SAAS,OAAO,YAAY;EAC1B,MAAM,eAAe,MAAMD,oBAAY,OAAO;EAC9C,OAAO;GACL,IAAA,GAAGE,iCAAAA,iBAAAA,CAAiB,YAAY;GAChC,IAAI,MAAoC;IAAE,OAAO,CAAC,GAAGD,sBAAU,OAAO,CAAC;GAAG;GAC1E,UAAU,CAAC,GAAI,aAAa,YAAY,CAAC,CAAE;GAC3C,IAAI,aAAkD;IAAE,OAAO,CAAC,GAAI,aAAa,cAAc,CAAC,CAAE;GAAG;EACvG;CACF;AACF,CAAC"}
|
|
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,5 +1,5 @@
|
|
|
1
1
|
//#region generated/server.d.ts
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const serverPlugin: import("@agimon-ai/po-core/serverPlugin").PoServerPlugin;
|
|
3
3
|
//#endregion
|
|
4
|
-
export {
|
|
4
|
+
export { serverPlugin as default };
|
|
5
5
|
//# sourceMappingURL=server.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAYa,
|
|
1
|
+
{"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAYa,wDAAY"}
|
|
@@ -2,8 +2,8 @@ import { D as provideBackgroundWorkService, T as sessionPeerConfigPath, _ as par
|
|
|
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";
|
|
5
|
-
import { composeServerProviderOverrides, defineServerPlugin } from "@agimon-ai/po-core/
|
|
6
|
-
import { composeRootHooks, defineRoot, defineRoute } from "@agimon-ai/po-core/extensionFile";
|
|
5
|
+
import { composeServerProviderOverrides, defineServerPlugin } from "@agimon-ai/po-core/serverPlugin";
|
|
6
|
+
import { composeRootHooks, composeRootInjects, defineRoot, defineRoute } from "@agimon-ai/po-core/extensionFile";
|
|
7
7
|
//#region src/services/peerInbox/index.ts
|
|
8
8
|
const inboxes = /* @__PURE__ */ new Map();
|
|
9
9
|
/**
|
|
@@ -183,9 +183,10 @@ var route_server_default = defineRoute(({ context }) => createPeerInboxApi({
|
|
|
183
183
|
//#endregion
|
|
184
184
|
//#region generated/server.ts
|
|
185
185
|
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
186
|
-
const
|
|
186
|
+
const serverPlugin = defineServerPlugin({
|
|
187
187
|
name: "@agimon-ai/po-session",
|
|
188
188
|
providerOverrides: composeServerProviderOverrides(root_server_default),
|
|
189
|
+
injects: composeRootInjects({ session: [root_server_default] }),
|
|
189
190
|
global: (context) => ({ get api() {
|
|
190
191
|
return [at(route_server_default, context)];
|
|
191
192
|
} }),
|
|
@@ -193,7 +194,7 @@ const facet = defineServerPlugin({
|
|
|
193
194
|
return [at(route_server_default, context)];
|
|
194
195
|
} }),
|
|
195
196
|
session: async (context) => {
|
|
196
|
-
const scopeSession = await root_server_default
|
|
197
|
+
const scopeSession = await context.scopeRoot("session", root_server_default, context);
|
|
197
198
|
return {
|
|
198
199
|
...composeRootHooks(scopeSession),
|
|
199
200
|
get api() {
|
|
@@ -207,6 +208,6 @@ const facet = defineServerPlugin({
|
|
|
207
208
|
}
|
|
208
209
|
});
|
|
209
210
|
//#endregion
|
|
210
|
-
export {
|
|
211
|
+
export { serverPlugin as default, serverPlugin };
|
|
211
212
|
|
|
212
213
|
//# sourceMappingURL=server.mjs.map
|
|
@@ -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/serverFacet';\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/serverFacet';\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/serverFacet';\nimport { composeServerProviderOverrides } from '@agimon-ai/po-core/serverFacet';\nimport { composeRootHooks } 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 facet = defineServerPlugin({\n name: '@agimon-ai/po-session',\n providerOverrides: composeServerProviderOverrides(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 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 facet;\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) => 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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/po-session",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.14",
|
|
4
4
|
"description": "Shared session coordination services for Po.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
"access": "public"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@agimon-ai/po-core": "0.0.0-alpha.
|
|
61
|
-
"@deepseek-ai/cordis": "4.0.
|
|
60
|
+
"@agimon-ai/po-core": "0.0.0-alpha.14",
|
|
61
|
+
"@deepseek-ai/cordis": "4.0.5",
|
|
62
62
|
"typebox": "1.3.37"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@agimon-ai/po-build": "0.0.0-alpha.
|
|
66
|
-
"@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.
|
|
65
|
+
"@agimon-ai/po-build": "0.0.0-alpha.14",
|
|
66
|
+
"@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.14",
|
|
67
67
|
"@earendil-works/pi-coding-agent": "1.3.0",
|
|
68
68
|
"@types/node": "26.6.5",
|
|
69
69
|
"@vitest/coverage-v8": "5.0.4",
|