@agimon-ai/doompi-session 0.0.1-alpha.4 → 0.0.1-alpha.6
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/{src/schemas/apiContracts.cjs → apiContracts.cjs} +7 -3
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/{src/schemas/apiContracts.d.mts.map → apiContracts.d.mts.map} +1 -1
- package/dist/{src/schemas/apiContracts.mjs → apiContracts.mjs} +1 -1
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/{src/services/backgroundWorkService/index.cjs → backgroundWorkService-BC0743Nn.cjs} +17 -7
- package/dist/backgroundWorkService-BC0743Nn.cjs.map +1 -0
- package/dist/{src/services/backgroundWorkService/index.mjs → backgroundWorkService-ChVXCzxj.mjs} +3 -3
- package/dist/backgroundWorkService-ChVXCzxj.mjs.map +1 -0
- package/dist/extensions/pi.cjs +12 -6
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.mts +1 -1
- package/dist/extensions/pi.d.mts.map +1 -1
- package/dist/extensions/pi.mjs +9 -3
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/extensions/server.cjs +154 -10
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +1 -1
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +146 -4
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/index.cjs +24 -31
- package/dist/index.d.mts +295 -11
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -9
- package/dist/sessionDelivery-C_rANfaY.mjs +796 -0
- package/dist/sessionDelivery-C_rANfaY.mjs.map +1 -0
- package/dist/sessionDelivery-DNbpgU5C.cjs +951 -0
- package/dist/sessionDelivery-DNbpgU5C.cjs.map +1 -0
- package/package.json +12 -12
- package/dist/_virtual/_rolldown/runtime.cjs +0 -23
- package/dist/api-contracts.cjs +0 -7
- package/dist/api-contracts.d.cts +0 -2
- package/dist/api-contracts.d.mts +0 -2
- package/dist/api-contracts.mjs +0 -2
- package/dist/extensions/pi.d.cts +0 -5
- package/dist/extensions/pi.d.cts.map +0 -1
- package/dist/extensions/server.d.cts +0 -5
- package/dist/extensions/server.d.cts.map +0 -1
- package/dist/index.d.cts +0 -11
- package/dist/src/extensions/(backend)/api/session-peer/route.server.cjs +0 -7
- package/dist/src/extensions/(backend)/api/session-peer/route.server.cjs.map +0 -1
- package/dist/src/extensions/(backend)/api/session-peer/route.server.mjs +0 -8
- package/dist/src/extensions/(backend)/api/session-peer/route.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +0 -10
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +0 -11
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +0 -101
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +0 -99
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +0 -1
- package/dist/src/schemas/apiContracts.cjs.map +0 -1
- package/dist/src/schemas/apiContracts.d.cts +0 -52
- package/dist/src/schemas/apiContracts.d.cts.map +0 -1
- package/dist/src/schemas/apiContracts.mjs.map +0 -1
- package/dist/src/services/backgroundWorkService/index.cjs.map +0 -1
- package/dist/src/services/backgroundWorkService/index.d.cts +0 -9
- package/dist/src/services/backgroundWorkService/index.d.cts.map +0 -1
- package/dist/src/services/backgroundWorkService/index.d.mts +0 -9
- package/dist/src/services/backgroundWorkService/index.d.mts.map +0 -1
- package/dist/src/services/backgroundWorkService/index.mjs.map +0 -1
- package/dist/src/services/peerInbox/index.cjs +0 -18
- package/dist/src/services/peerInbox/index.cjs.map +0 -1
- package/dist/src/services/peerInbox/index.mjs +0 -17
- package/dist/src/services/peerInbox/index.mjs.map +0 -1
- package/dist/src/services/peerInboxApi/index.cjs +0 -48
- package/dist/src/services/peerInboxApi/index.cjs.map +0 -1
- package/dist/src/services/peerInboxApi/index.mjs +0 -48
- package/dist/src/services/peerInboxApi/index.mjs.map +0 -1
- package/dist/src/services/peerTransport/index.cjs +0 -206
- package/dist/src/services/peerTransport/index.cjs.map +0 -1
- package/dist/src/services/peerTransport/index.d.cts +0 -49
- package/dist/src/services/peerTransport/index.d.cts.map +0 -1
- package/dist/src/services/peerTransport/index.d.mts +0 -49
- package/dist/src/services/peerTransport/index.d.mts.map +0 -1
- package/dist/src/services/peerTransport/index.mjs +0 -195
- package/dist/src/services/peerTransport/index.mjs.map +0 -1
- package/dist/src/services/sessionDelivery/index.cjs +0 -277
- package/dist/src/services/sessionDelivery/index.cjs.map +0 -1
- package/dist/src/services/sessionDelivery/index.d.cts +0 -10
- package/dist/src/services/sessionDelivery/index.d.cts.map +0 -1
- package/dist/src/services/sessionDelivery/index.d.mts +0 -10
- package/dist/src/services/sessionDelivery/index.d.mts.map +0 -1
- package/dist/src/services/sessionDelivery/index.mjs +0 -274
- package/dist/src/services/sessionDelivery/index.mjs.map +0 -1
- package/dist/src/services/sessionDelivery/type.cjs +0 -11
- package/dist/src/services/sessionDelivery/type.cjs.map +0 -1
- package/dist/src/services/sessionDelivery/type.d.cts +0 -73
- package/dist/src/services/sessionDelivery/type.d.cts.map +0 -1
- package/dist/src/services/sessionDelivery/type.d.mts +0 -73
- package/dist/src/services/sessionDelivery/type.d.mts.map +0 -1
- package/dist/src/services/sessionDelivery/type.mjs +0 -10
- package/dist/src/services/sessionDelivery/type.mjs.map +0 -1
- package/dist/src/services/sessionDirectory/index.cjs +0 -120
- package/dist/src/services/sessionDirectory/index.cjs.map +0 -1
- package/dist/src/services/sessionDirectory/index.d.cts +0 -7
- package/dist/src/services/sessionDirectory/index.d.cts.map +0 -1
- package/dist/src/services/sessionDirectory/index.d.mts +0 -7
- package/dist/src/services/sessionDirectory/index.d.mts.map +0 -1
- package/dist/src/services/sessionDirectory/index.mjs +0 -120
- package/dist/src/services/sessionDirectory/index.mjs.map +0 -1
- package/dist/src/services/sessionDirectory/type.d.cts +0 -54
- package/dist/src/services/sessionDirectory/type.d.cts.map +0 -1
- package/dist/src/services/sessionDirectory/type.d.mts +0 -54
- package/dist/src/services/sessionDirectory/type.d.mts.map +0 -1
- package/dist/src/services/sessionGroups/index.cjs +0 -105
- package/dist/src/services/sessionGroups/index.cjs.map +0 -1
- package/dist/src/services/sessionGroups/index.d.cts +0 -7
- package/dist/src/services/sessionGroups/index.d.cts.map +0 -1
- package/dist/src/services/sessionGroups/index.d.mts +0 -7
- package/dist/src/services/sessionGroups/index.d.mts.map +0 -1
- package/dist/src/services/sessionGroups/index.mjs +0 -104
- package/dist/src/services/sessionGroups/index.mjs.map +0 -1
- package/dist/src/services/sessionGroups/type.cjs +0 -11
- package/dist/src/services/sessionGroups/type.cjs.map +0 -1
- package/dist/src/services/sessionGroups/type.d.cts +0 -32
- package/dist/src/services/sessionGroups/type.d.cts.map +0 -1
- package/dist/src/services/sessionGroups/type.d.mts +0 -32
- package/dist/src/services/sessionGroups/type.d.mts.map +0 -1
- package/dist/src/services/sessionGroups/type.mjs +0 -11
- package/dist/src/services/sessionGroups/type.mjs.map +0 -1
- package/dist/src/services/sessionIntercom/index.cjs +0 -89
- package/dist/src/services/sessionIntercom/index.cjs.map +0 -1
- package/dist/src/services/sessionIntercom/index.d.cts +0 -11
- package/dist/src/services/sessionIntercom/index.d.cts.map +0 -1
- package/dist/src/services/sessionIntercom/index.d.mts +0 -11
- package/dist/src/services/sessionIntercom/index.d.mts.map +0 -1
- package/dist/src/services/sessionIntercom/index.mjs +0 -85
- package/dist/src/services/sessionIntercom/index.mjs.map +0 -1
- package/dist/src/services/sessionIntercom/type.cjs +0 -16
- package/dist/src/services/sessionIntercom/type.cjs.map +0 -1
- package/dist/src/services/sessionIntercom/type.d.cts +0 -60
- package/dist/src/services/sessionIntercom/type.d.cts.map +0 -1
- package/dist/src/services/sessionIntercom/type.d.mts +0 -60
- package/dist/src/services/sessionIntercom/type.d.mts.map +0 -1
- package/dist/src/services/sessionIntercom/type.mjs +0 -14
- package/dist/src/services/sessionIntercom/type.mjs.map +0 -1
- /package/dist/{src/schemas/apiContracts.d.mts → apiContracts.d.mts} +0 -0
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
let _agimon_ai_doompi_core_apiContracts = require("@agimon-ai/doompi-core/apiContracts");
|
|
2
6
|
let typebox = require("typebox");
|
|
3
7
|
//#region src/schemas/apiContracts.ts
|
|
4
8
|
/** The endpoint validates its own HMAC peer credential because tunnel device authentication is intentionally bypassed. */
|
|
@@ -15,12 +19,12 @@ const http = [{
|
|
|
15
19
|
required: true,
|
|
16
20
|
schema: typebox.Type.Unknown()
|
|
17
21
|
},
|
|
18
|
-
responses: (0,
|
|
22
|
+
responses: (0, _agimon_ai_doompi_core_apiContracts.jsonApiResponses)(typebox.Type.Object({
|
|
19
23
|
accepted: typebox.Type.Boolean(),
|
|
20
24
|
state: typebox.Type.String()
|
|
21
25
|
}))
|
|
22
26
|
}];
|
|
23
|
-
const apiContracts = (0,
|
|
27
|
+
const apiContracts = (0, _agimon_ai_doompi_core_apiContracts.defineApiContract)({
|
|
24
28
|
version: 1,
|
|
25
29
|
http,
|
|
26
30
|
sockets: [],
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.cjs","names":["Type","jsonApiResponses","defineApiContract"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses, type DoomHttpContract } from '@agimon-ai/doompi-core/apiContracts';\nimport { Type } from 'typebox';\n\n/** The endpoint validates its own HMAC peer credential because tunnel device authentication is intentionally bypassed. */\nconst http: DoomHttpContract[] = [\n {\n id: 'peer-inbox',\n scope: 'global',\n basePath: 'session-peer',\n method: 'POST',\n path: '/inbox',\n authentication: 'none',\n description:\n 'Accept an HMAC-authenticated durable Session delivery envelope from an explicitly configured tunnel peer.',\n body: { contentType: 'application/json', required: true, schema: Type.Unknown() },\n responses: jsonApiResponses(Type.Object({ accepted: Type.Boolean(), state: Type.String() })),\n },\n];\n\nexport const apiContracts = defineApiContract({ version: 1, http, sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;;;;;;AAIA,MAAM,OAA2B,CAC/B;CACE,IAAI;CACJ,OAAO;CACP,UAAU;CACV,QAAQ;CACR,MAAM;CACN,gBAAgB;CAChB,aACE;CACF,MAAM;EAAE,aAAa;EAAoB,UAAU;EAAM,QAAQA,QAAAA,KAAK,QAAQ;CAAE;CAChF,YAAA,GAAWC,oCAAAA,iBAAAA,CAAiBD,QAAAA,KAAK,OAAO;EAAE,UAAUA,QAAAA,KAAK,QAAQ;EAAG,OAAOA,QAAAA,KAAK,OAAO;CAAE,CAAC,CAAC;AAC7F,CACF;AAEA,MAAa,gBAAA,GAAeE,oCAAAA,kBAAAA,CAAkB;CAAE,SAAS;CAAG;CAAM,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiContracts.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../src/schemas/apiContracts.ts"],"mappings":";qBAmBa"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineApiContract, jsonApiResponses } from "@agimon-ai/doompi-core/
|
|
1
|
+
import { defineApiContract, jsonApiResponses } from "@agimon-ai/doompi-core/apiContracts";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
//#region src/schemas/apiContracts.ts
|
|
4
4
|
/** The endpoint validates its own HMAC peer credential because tunnel device authentication is intentionally bypassed. */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses, type DoomHttpContract } from '@agimon-ai/doompi-core/apiContracts';\nimport { Type } from 'typebox';\n\n/** The endpoint validates its own HMAC peer credential because tunnel device authentication is intentionally bypassed. */\nconst http: DoomHttpContract[] = [\n {\n id: 'peer-inbox',\n scope: 'global',\n basePath: 'session-peer',\n method: 'POST',\n path: '/inbox',\n authentication: 'none',\n description:\n 'Accept an HMAC-authenticated durable Session delivery envelope from an explicitly configured tunnel peer.',\n body: { contentType: 'application/json', required: true, schema: Type.Unknown() },\n responses: jsonApiResponses(Type.Object({ accepted: Type.Boolean(), state: Type.String() })),\n },\n];\n\nexport const apiContracts = defineApiContract({ version: 1, http, sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;;AAIA,MAAM,OAA2B,CAC/B;CACE,IAAI;CACJ,OAAO;CACP,UAAU;CACV,QAAQ;CACR,MAAM;CACN,gBAAgB;CAChB,aACE;CACF,MAAM;EAAE,aAAa;EAAoB,UAAU;EAAM,QAAQ,KAAK,QAAQ;CAAE;CAChF,WAAW,iBAAiB,KAAK,OAAO;EAAE,UAAU,KAAK,QAAQ;EAAG,OAAO,KAAK,OAAO;CAAE,CAAC,CAAC;AAC7F,CACF;AAEA,MAAa,eAAe,kBAAkB;CAAE,SAAS;CAAG;CAAM,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
|
package/dist/{src/services/backgroundWorkService/index.cjs → backgroundWorkService-BC0743Nn.cjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
let
|
|
1
|
+
let _agimon_ai_doompi_core_backgroundWork = require("@agimon-ai/doompi-core/backgroundWork");
|
|
2
2
|
let typebox_value = require("typebox/value");
|
|
3
3
|
//#region src/services/backgroundWorkService/index.ts
|
|
4
4
|
/** Creates the generation-bound, pull-based coordinator shared by session extensions. */
|
|
@@ -6,7 +6,7 @@ function createBackgroundWorkService(ctx) {
|
|
|
6
6
|
const registrations = /* @__PURE__ */ new Map();
|
|
7
7
|
const generation = `doom-background-work:${crypto.randomUUID()}`;
|
|
8
8
|
const changed = (provider, providerGeneration, kind) => {
|
|
9
|
-
ctx.emit(
|
|
9
|
+
ctx.emit(_agimon_ai_doompi_core_backgroundWork.DOOM_BACKGROUND_WORK_CHANGED_EVENT, {
|
|
10
10
|
provider,
|
|
11
11
|
generation: providerGeneration,
|
|
12
12
|
kind
|
|
@@ -49,7 +49,7 @@ function createBackgroundWorkService(ctx) {
|
|
|
49
49
|
const current = registration.provider.listActiveWork();
|
|
50
50
|
if (!Array.isArray(current)) throw new TypeError("listActiveWork() must return an array.");
|
|
51
51
|
for (const item of current) {
|
|
52
|
-
if (!(0, typebox_value.Check)(
|
|
52
|
+
if (!(0, typebox_value.Check)(_agimon_ai_doompi_core_backgroundWork.BackgroundProviderWorkItemSchema, item)) throw new TypeError("listActiveWork() returned an invalid item.");
|
|
53
53
|
if (sessionId === void 0 || item.sessionId === sessionId) items.push({
|
|
54
54
|
provider,
|
|
55
55
|
...item
|
|
@@ -70,10 +70,20 @@ function createBackgroundWorkService(ctx) {
|
|
|
70
70
|
}
|
|
71
71
|
/** Installs one coordinator in the current session service context. */
|
|
72
72
|
function provideBackgroundWorkService(context) {
|
|
73
|
-
context.provide(
|
|
73
|
+
context.provide(_agimon_ai_doompi_core_backgroundWork.DOOM_BACKGROUND_WORK_SERVICE, createBackgroundWorkService(context));
|
|
74
74
|
}
|
|
75
75
|
//#endregion
|
|
76
|
-
exports
|
|
77
|
-
|
|
76
|
+
Object.defineProperty(exports, "createBackgroundWorkService", {
|
|
77
|
+
enumerable: true,
|
|
78
|
+
get: function() {
|
|
79
|
+
return createBackgroundWorkService;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
Object.defineProperty(exports, "provideBackgroundWorkService", {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
get: function() {
|
|
85
|
+
return provideBackgroundWorkService;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
78
88
|
|
|
79
|
-
//# sourceMappingURL=
|
|
89
|
+
//# sourceMappingURL=backgroundWorkService-BC0743Nn.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backgroundWorkService-BC0743Nn.cjs","names":["DOOM_BACKGROUND_WORK_CHANGED_EVENT","Check","BackgroundProviderWorkItemSchema","DOOM_BACKGROUND_WORK_SERVICE"],"sources":["../src/services/backgroundWorkService/index.ts"],"sourcesContent":["import {\n BackgroundProviderWorkItemSchema,\n DOOM_BACKGROUND_WORK_CHANGED_EVENT,\n DOOM_BACKGROUND_WORK_SERVICE,\n type BackgroundWorkProvider,\n type BackgroundWorkProviderHandle,\n type DoomBackgroundWorkService,\n type DoomBackgroundWorkSnapshot,\n} from '@agimon-ai/doompi-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): DoomBackgroundWorkService {\n const registrations = new Map<string, ProviderRegistration>();\n const generation = `doom-background-work:${crypto.randomUUID()}`;\n\n const changed = (\n provider: string,\n providerGeneration: string,\n kind: 'registered' | 'updated' | 'unregistered',\n ): void => {\n ctx.emit(DOOM_BACKGROUND_WORK_CHANGED_EVENT, { provider, generation: providerGeneration, kind });\n };\n\n const service: DoomBackgroundWorkService = {\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): DoomBackgroundWorkSnapshot {\n const items: DoomBackgroundWorkSnapshot['items'][number][] = [];\n const errors: DoomBackgroundWorkSnapshot['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(DOOM_BACKGROUND_WORK_SERVICE, createBackgroundWorkService(context));\n}\n"],"mappings":";;;;AAmBA,SAAgB,4BAA4B,KAAyC;CACnF,MAAM,gCAAgB,IAAI,IAAkC;CAC5D,MAAM,aAAa,wBAAwB,OAAO,WAAW;CAE7D,MAAM,WACJ,UACA,oBACA,SACS;EACT,IAAI,KAAKA,sCAAAA,oCAAoC;GAAE;GAAU,YAAY;GAAoB;EAAK,CAAC;CACjG;CAsDA,OAAO,OAAO,OAAO;EAnDnB;EACA,SAAS,UAAwC;GAC/C,IAAI,CAAC,YAAY,OAAO,aAAa,YAAY,OAAO,SAAS,mBAAmB,YAClF,MAAM,IAAI,UAAU,0DAA0D;GAEhF,MAAM,OAAO,SAAS,SAAS,KAAK;GACpC,IAAI,CAAC,QAAQ,SAAS,SAAS,UAC7B,MAAM,IAAI,UAAU,gEAAgE;GAEtF,MAAM,QAAQ,OAAO,IAAI;GACzB,MAAM,qBAAqB,GAAG,KAAK,GAAG,OAAO,WAAW;GACxD,cAAc,IAAI,MAAM;IAAE;IAAO,YAAY;IAAoB;GAAS,CAAC;GAC3E,QAAQ,MAAM,oBAAoB,YAAY;GAC9C,IAAI,WAAW;GACf,OAAO,OAAO,OAAO;IACnB,UAAU;IACV,YAAY;IACZ,SAAe;KACb,IAAI,CAAC,YAAY,cAAc,IAAI,IAAI,CAAC,EAAE,UAAU,OAClD,QAAQ,MAAM,oBAAoB,SAAS;IAE/C;IACA,UAAgB;KACd,IAAI,UAAU;KACd,WAAW;KACX,IAAI,cAAc,IAAI,IAAI,CAAC,EAAE,UAAU,OAAO;KAC9C,cAAc,OAAO,IAAI;KACzB,QAAQ,MAAM,oBAAoB,cAAc;IAClD;GACF,CAAC;EACH;EACA,SAAS,WAAgD;GACvD,MAAM,QAAuD,CAAC;GAC9D,MAAM,SAAyD,CAAC;GAChE,KAAK,MAAM,CAAC,UAAU,iBAAiB,eACrC,IAAI;IACF,MAAM,UAAU,aAAa,SAAS,eAAe;IACrD,IAAI,CAAC,MAAM,QAAQ,OAAO,GAAG,MAAM,IAAI,UAAU,wCAAwC;IACzF,KAAK,MAAM,QAAQ,SAAS;KAC1B,IAAI,EAAA,GAACC,cAAAA,MAAAA,CAAMC,sCAAAA,kCAAkC,IAAI,GAC/C,MAAM,IAAI,UAAU,4CAA4C;KAElE,IAAI,cAAc,KAAA,KAAa,KAAK,cAAc,WAAW,MAAM,KAAK;MAAE;MAAU,GAAG;KAAK,CAAC;IAC/F;GACF,SAAS,OAAO;IACd,OAAO,KAAK;KAAE;KAAU,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;IAAE,CAAC;GAC3F;GAEF,OAAO,OAAO,OAAO;IAAE,OAAO,OAAO,OAAO,KAAK;IAAG,QAAQ,OAAO,OAAO,MAAM;GAAE,CAAC;EACrF;CAEyB,CAAC;AAC9B;;AAGA,SAAgB,6BAA6B,SAAwB;CACnE,QAAQ,QAAQC,sCAAAA,8BAA8B,4BAA4B,OAAO,CAAC;AACpF"}
|
package/dist/{src/services/backgroundWorkService/index.mjs → backgroundWorkService-ChVXCzxj.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BackgroundProviderWorkItemSchema, DOOM_BACKGROUND_WORK_CHANGED_EVENT, DOOM_BACKGROUND_WORK_SERVICE } from "@agimon-ai/doompi-core/
|
|
1
|
+
import { BackgroundProviderWorkItemSchema, DOOM_BACKGROUND_WORK_CHANGED_EVENT, DOOM_BACKGROUND_WORK_SERVICE } from "@agimon-ai/doompi-core/backgroundWork";
|
|
2
2
|
import { Check } from "typebox/value";
|
|
3
3
|
//#region src/services/backgroundWorkService/index.ts
|
|
4
4
|
/** Creates the generation-bound, pull-based coordinator shared by session extensions. */
|
|
@@ -73,6 +73,6 @@ function provideBackgroundWorkService(context) {
|
|
|
73
73
|
context.provide(DOOM_BACKGROUND_WORK_SERVICE, createBackgroundWorkService(context));
|
|
74
74
|
}
|
|
75
75
|
//#endregion
|
|
76
|
-
export {
|
|
76
|
+
export { provideBackgroundWorkService as n, createBackgroundWorkService as t };
|
|
77
77
|
|
|
78
|
-
//# sourceMappingURL=
|
|
78
|
+
//# sourceMappingURL=backgroundWorkService-ChVXCzxj.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backgroundWorkService-ChVXCzxj.mjs","names":[],"sources":["../src/services/backgroundWorkService/index.ts"],"sourcesContent":["import {\n BackgroundProviderWorkItemSchema,\n DOOM_BACKGROUND_WORK_CHANGED_EVENT,\n DOOM_BACKGROUND_WORK_SERVICE,\n type BackgroundWorkProvider,\n type BackgroundWorkProviderHandle,\n type DoomBackgroundWorkService,\n type DoomBackgroundWorkSnapshot,\n} from '@agimon-ai/doompi-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): DoomBackgroundWorkService {\n const registrations = new Map<string, ProviderRegistration>();\n const generation = `doom-background-work:${crypto.randomUUID()}`;\n\n const changed = (\n provider: string,\n providerGeneration: string,\n kind: 'registered' | 'updated' | 'unregistered',\n ): void => {\n ctx.emit(DOOM_BACKGROUND_WORK_CHANGED_EVENT, { provider, generation: providerGeneration, kind });\n };\n\n const service: DoomBackgroundWorkService = {\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): DoomBackgroundWorkSnapshot {\n const items: DoomBackgroundWorkSnapshot['items'][number][] = [];\n const errors: DoomBackgroundWorkSnapshot['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(DOOM_BACKGROUND_WORK_SERVICE, createBackgroundWorkService(context));\n}\n"],"mappings":";;;;AAmBA,SAAgB,4BAA4B,KAAyC;CACnF,MAAM,gCAAgB,IAAI,IAAkC;CAC5D,MAAM,aAAa,wBAAwB,OAAO,WAAW;CAE7D,MAAM,WACJ,UACA,oBACA,SACS;EACT,IAAI,KAAK,oCAAoC;GAAE;GAAU,YAAY;GAAoB;EAAK,CAAC;CACjG;CAsDA,OAAO,OAAO,OAAO;EAnDnB;EACA,SAAS,UAAwC;GAC/C,IAAI,CAAC,YAAY,OAAO,aAAa,YAAY,OAAO,SAAS,mBAAmB,YAClF,MAAM,IAAI,UAAU,0DAA0D;GAEhF,MAAM,OAAO,SAAS,SAAS,KAAK;GACpC,IAAI,CAAC,QAAQ,SAAS,SAAS,UAC7B,MAAM,IAAI,UAAU,gEAAgE;GAEtF,MAAM,QAAQ,OAAO,IAAI;GACzB,MAAM,qBAAqB,GAAG,KAAK,GAAG,OAAO,WAAW;GACxD,cAAc,IAAI,MAAM;IAAE;IAAO,YAAY;IAAoB;GAAS,CAAC;GAC3E,QAAQ,MAAM,oBAAoB,YAAY;GAC9C,IAAI,WAAW;GACf,OAAO,OAAO,OAAO;IACnB,UAAU;IACV,YAAY;IACZ,SAAe;KACb,IAAI,CAAC,YAAY,cAAc,IAAI,IAAI,CAAC,EAAE,UAAU,OAClD,QAAQ,MAAM,oBAAoB,SAAS;IAE/C;IACA,UAAgB;KACd,IAAI,UAAU;KACd,WAAW;KACX,IAAI,cAAc,IAAI,IAAI,CAAC,EAAE,UAAU,OAAO;KAC9C,cAAc,OAAO,IAAI;KACzB,QAAQ,MAAM,oBAAoB,cAAc;IAClD;GACF,CAAC;EACH;EACA,SAAS,WAAgD;GACvD,MAAM,QAAuD,CAAC;GAC9D,MAAM,SAAyD,CAAC;GAChE,KAAK,MAAM,CAAC,UAAU,iBAAiB,eACrC,IAAI;IACF,MAAM,UAAU,aAAa,SAAS,eAAe;IACrD,IAAI,CAAC,MAAM,QAAQ,OAAO,GAAG,MAAM,IAAI,UAAU,wCAAwC;IACzF,KAAK,MAAM,QAAQ,SAAS;KAC1B,IAAI,CAAC,MAAM,kCAAkC,IAAI,GAC/C,MAAM,IAAI,UAAU,4CAA4C;KAElE,IAAI,cAAc,KAAA,KAAa,KAAK,cAAc,WAAW,MAAM,KAAK;MAAE;MAAU,GAAG;KAAK,CAAC;IAC/F;GACF,SAAS,OAAO;IACd,OAAO,KAAK;KAAE;KAAU,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;IAAE,CAAC;GAC3F;GAEF,OAAO,OAAO,OAAO;IAAE,OAAO,OAAO,OAAO,KAAK;IAAG,QAAQ,OAAO,OAAO,MAAM;GAAE,CAAC;EACrF;CAEyB,CAAC;AAC9B;;AAGA,SAAgB,6BAA6B,SAAwB;CACnE,QAAQ,QAAQ,8BAA8B,4BAA4B,OAAO,CAAC;AACpF"}
|
package/dist/extensions/pi.cjs
CHANGED
|
@@ -2,14 +2,20 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const
|
|
6
|
-
let
|
|
7
|
-
let
|
|
5
|
+
const require_backgroundWorkService = require("../backgroundWorkService-BC0743Nn.cjs");
|
|
6
|
+
let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
|
|
7
|
+
let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
|
|
8
|
+
//#region src/extensions/workspaces/sessions/(backend)/root.cli.ts
|
|
9
|
+
var root_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoot)((_context) => ({
|
|
10
|
+
value: void 0,
|
|
11
|
+
services: [require_backgroundWorkService.provideBackgroundWorkService]
|
|
12
|
+
}));
|
|
13
|
+
//#endregion
|
|
8
14
|
//#region generated/pi.ts
|
|
9
|
-
const extension = (0,
|
|
10
|
-
const scopeSession = await
|
|
15
|
+
const extension = (0, _agimon_ai_doompi_core_piExtension.definePiExtension)("@agimon-ai/doompi-session", async (context) => {
|
|
16
|
+
const scopeSession = await root_cli_default(context);
|
|
11
17
|
return {
|
|
12
|
-
...(0,
|
|
18
|
+
...(0, _agimon_ai_doompi_core_extensionFile.composeRootHooks)(scopeSession),
|
|
13
19
|
services: [...scopeSession.services ?? []]
|
|
14
20
|
};
|
|
15
21
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi.cjs","names":["definePiExtension","rootSession","composeRootHooks"],"sources":["../../generated/pi.ts"],"sourcesContent":["// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext } from '@agimon-ai/doompi-core/
|
|
1
|
+
{"version":3,"file":"pi.cjs","names":["defineRoot","provideBackgroundWorkService","definePiExtension","rootSession","composeRootHooks"],"sources":["../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../generated/pi.ts"],"sourcesContent":["import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { provideBackgroundWorkService } from '../../../../services/backgroundWorkService';\n\nexport default defineRoot((_context: PiPluginContext) => ({\n value: undefined,\n services: [provideBackgroundWorkService],\n}));\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-session', async (context) => {\n const scopeSession = await rootSession(context);\n return {\n ...composeRootHooks(scopeSession),\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":";;;;;;;;AAKA,IAAA,oBAAA,GAAeA,qCAAAA,WAAAA,EAAY,cAA+B;CACxD,OAAO,KAAA;CACP,UAAU,CAACC,8BAAAA,4BAA4B;AACzC,EAAE;;;ACIF,MAAa,aAAA,GAAYC,mCAAAA,kBAAAA,CAAoC,6BAA6B,OAAO,YAAY;CAC3G,MAAM,eAAe,MAAMC,iBAAY,OAAO;CAC9C,OAAO;EACL,IAAA,GAAGC,qCAAAA,iBAAAA,CAAiB,YAAY;EAChC,UAAU,CAAC,GAAI,aAAa,YAAY,CAAC,CAAE;CAC7C;AACF,CAAC"}
|
package/dist/extensions/pi.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region generated/pi.d.ts
|
|
2
|
-
export declare const extension: import("@agimon-ai/doompi-core/
|
|
2
|
+
export declare const extension: import("@agimon-ai/doompi-core/runtimePiExtension").DefinedPiExtension<undefined>;
|
|
3
3
|
//#endregion
|
|
4
4
|
export { extension as default };
|
|
5
5
|
//# sourceMappingURL=pi.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi.d.mts","names":[],"sources":["../../generated/pi.ts"],"mappings":";qBAYa
|
|
1
|
+
{"version":3,"file":"pi.d.mts","names":[],"sources":["../../generated/pi.ts"],"mappings":";qBAYa,+DAAS"}
|
package/dist/extensions/pi.mjs
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { definePiExtension } from "@agimon-ai/doompi-core/
|
|
3
|
-
import { composeRootHooks } from "@agimon-ai/doompi-core/
|
|
1
|
+
import { n as provideBackgroundWorkService } from "../backgroundWorkService-ChVXCzxj.mjs";
|
|
2
|
+
import { definePiExtension } from "@agimon-ai/doompi-core/piExtension";
|
|
3
|
+
import { composeRootHooks, defineRoot } from "@agimon-ai/doompi-core/extensionFile";
|
|
4
|
+
//#region src/extensions/workspaces/sessions/(backend)/root.cli.ts
|
|
5
|
+
var root_cli_default = defineRoot((_context) => ({
|
|
6
|
+
value: void 0,
|
|
7
|
+
services: [provideBackgroundWorkService]
|
|
8
|
+
}));
|
|
9
|
+
//#endregion
|
|
4
10
|
//#region generated/pi.ts
|
|
5
11
|
const extension = definePiExtension("@agimon-ai/doompi-session", async (context) => {
|
|
6
12
|
const scopeSession = await root_cli_default(context);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi.mjs","names":["rootSession"],"sources":["../../generated/pi.ts"],"sourcesContent":["// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext } from '@agimon-ai/doompi-core/
|
|
1
|
+
{"version":3,"file":"pi.mjs","names":["rootSession"],"sources":["../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../generated/pi.ts"],"sourcesContent":["import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { provideBackgroundWorkService } from '../../../../services/backgroundWorkService';\n\nexport default defineRoot((_context: PiPluginContext) => ({\n value: undefined,\n services: [provideBackgroundWorkService],\n}));\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-session', async (context) => {\n const scopeSession = await rootSession(context);\n return {\n ...composeRootHooks(scopeSession),\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":";;;;AAKA,IAAA,mBAAe,YAAY,cAA+B;CACxD,OAAO,KAAA;CACP,UAAU,CAAC,4BAA4B;AACzC,EAAE;;;ACIF,MAAa,YAAY,kBAAoC,6BAA6B,OAAO,YAAY;CAC3G,MAAM,eAAe,MAAMA,iBAAY,OAAO;CAC9C,OAAO;EACL,GAAG,iBAAiB,YAAY;EAChC,UAAU,CAAC,GAAI,aAAa,YAAY,CAAC,CAAE;CAC7C;AACF,CAAC"}
|
|
@@ -2,26 +2,170 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
let
|
|
8
|
-
|
|
5
|
+
const require_sessionDelivery = require("../sessionDelivery-DNbpgU5C.cjs");
|
|
6
|
+
const require_backgroundWorkService = require("../backgroundWorkService-BC0743Nn.cjs");
|
|
7
|
+
let node_fs = require("node:fs");
|
|
8
|
+
node_fs = require_sessionDelivery.__toESM(node_fs, 1);
|
|
9
|
+
let node_path = require("node:path");
|
|
10
|
+
node_path = require_sessionDelivery.__toESM(node_path, 1);
|
|
11
|
+
let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
|
|
12
|
+
let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
|
|
13
|
+
//#region src/services/peerInbox/index.ts
|
|
14
|
+
const inboxes = /* @__PURE__ */ new Map();
|
|
15
|
+
/** Registers one live session-owned peer inbox. This registry is reachable only by the Session route. */
|
|
16
|
+
function registerSessionPeerInbox(sessionId, inbox) {
|
|
17
|
+
if (inboxes.has(sessionId)) throw new Error(`Session peer inbox '${sessionId}' is already registered.`);
|
|
18
|
+
inboxes.set(sessionId, inbox);
|
|
19
|
+
return () => {
|
|
20
|
+
if (inboxes.get(sessionId) === inbox) inboxes.delete(sessionId);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function deliverSessionPeerEnvelope(targetSessionId, sourceKey, type, payload) {
|
|
24
|
+
return inboxes.get(targetSessionId)?.(sourceKey, type, payload);
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/extensions/workspaces/sessions/(backend)/root.server.ts
|
|
28
|
+
var root_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoot)((pluginContext) => ({
|
|
29
|
+
value: void 0,
|
|
30
|
+
services: [require_backgroundWorkService.provideBackgroundWorkService, (context) => {
|
|
31
|
+
const agent = pluginContext.agent;
|
|
32
|
+
const session = agent?.context.session;
|
|
33
|
+
const communication = pluginContext.host.context.sessionCommunication;
|
|
34
|
+
const homeDirectory = pluginContext.host.context.homeDirectory;
|
|
35
|
+
const sessionService = pluginContext.host.context.sessionService;
|
|
36
|
+
if (!agent || !session?.admitPrompt || !communication || !homeDirectory || !sessionService?.canCommunicate) throw new Error("Session delivery requires the headless agent, authenticated session communication, host home directory, and communication policy.");
|
|
37
|
+
const sessionDirectory = node_path.default.join(homeDirectory, ".pi", ".doom", "session");
|
|
38
|
+
const deliveryDirectory = node_path.default.join(sessionDirectory, "delivery");
|
|
39
|
+
node_fs.default.mkdirSync(deliveryDirectory, {
|
|
40
|
+
recursive: true,
|
|
41
|
+
mode: 448
|
|
42
|
+
});
|
|
43
|
+
const peerCommunication = require_sessionDelivery.createPeerCommunication({
|
|
44
|
+
local: communication,
|
|
45
|
+
homeDirectory
|
|
46
|
+
});
|
|
47
|
+
const peerConfig = require_sessionDelivery.readSessionPeerConfig(homeDirectory);
|
|
48
|
+
const remotePeerIsGranted = (peerKey) => {
|
|
49
|
+
const peer = require_sessionDelivery.parseRemoteSessionReference(peerKey);
|
|
50
|
+
return peer !== void 0 && peerConfig?.peers.some((candidate) => candidate.hostId === peer.hostId && candidate.allowedSessionIds.includes(agent.context.sessionId)) === true;
|
|
51
|
+
};
|
|
52
|
+
const fallbackAuthorization = (peerKey) => sessionService.canCommunicate?.(agent.context.sessionId, peerKey) === true || remotePeerIsGranted(peerKey);
|
|
53
|
+
const groups = peerConfig ? require_sessionDelivery.createSessionGroupStore({ databasePath: node_path.default.join(sessionDirectory, "groups.sqlite") }) : void 0;
|
|
54
|
+
const localHostId = peerConfig?.hostId;
|
|
55
|
+
const selfReference = localHostId ? require_sessionDelivery.peerSessionReference(localHostId, agent.context.sessionId) : void 0;
|
|
56
|
+
const groupAuthorization = groups && selfReference && localHostId ? require_sessionDelivery.createSessionGroupDeliveryAuthorizer({
|
|
57
|
+
selfReference,
|
|
58
|
+
groups,
|
|
59
|
+
peerReference: (peerKey) => require_sessionDelivery.parseRemoteSessionReference(peerKey) === void 0 ? require_sessionDelivery.peerSessionReference(localHostId, peerKey) : peerKey,
|
|
60
|
+
fallback: fallbackAuthorization
|
|
61
|
+
}) : void 0;
|
|
62
|
+
const { service, close: closeDelivery } = require_sessionDelivery.provideSessionDeliveryService(context, {
|
|
63
|
+
databasePath: node_path.default.join(deliveryDirectory, `${agent.context.sessionId}.sqlite`),
|
|
64
|
+
recipientKey: agent.context.sessionId,
|
|
65
|
+
communication: peerCommunication,
|
|
66
|
+
authorizePeer: (peerKey, metadata) => groupAuthorization?.(peerKey, metadata) ?? fallbackAuthorization(peerKey),
|
|
67
|
+
admitPrompt: (prompt, delivery) => session.admitPrompt(prompt, delivery)
|
|
68
|
+
});
|
|
69
|
+
const unprovide = [];
|
|
70
|
+
if (groups && selfReference && peerConfig) {
|
|
71
|
+
const directory = require_sessionDelivery.createSessionDirectory({ authorizeDiscovery: (caller, subject) => {
|
|
72
|
+
const reference = require_sessionDelivery.peerSessionReference(subject.hostId, subject.sessionId);
|
|
73
|
+
return groups.groupsFor(caller).some((group) => group.members.includes(reference)) ? { capabilities: ["message"] } : void 0;
|
|
74
|
+
} });
|
|
75
|
+
for (const peer of peerConfig.peers) for (const sessionId of peer.allowedSessionIds) directory.observe({
|
|
76
|
+
hostId: peer.hostId,
|
|
77
|
+
sessionId,
|
|
78
|
+
hostIncarnation: "unknown",
|
|
79
|
+
sessionIncarnation: "unknown",
|
|
80
|
+
sequence: 0,
|
|
81
|
+
observedAt: 0,
|
|
82
|
+
staleAfterMs: 0,
|
|
83
|
+
deliveryTarget: require_sessionDelivery.peerSessionReference(peer.hostId, sessionId),
|
|
84
|
+
reachability: "unknown",
|
|
85
|
+
runtime: "unknown",
|
|
86
|
+
activity: "unknown",
|
|
87
|
+
voice: {
|
|
88
|
+
eligible: "unknown",
|
|
89
|
+
readiness: "unknown"
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
unprovide.push(context.provide(require_sessionDelivery.DOOM_SESSION_INTERCOM_SERVICE, require_sessionDelivery.createSessionIntercom({
|
|
93
|
+
selfReference,
|
|
94
|
+
directory,
|
|
95
|
+
groups,
|
|
96
|
+
delivery: service
|
|
97
|
+
})));
|
|
98
|
+
}
|
|
99
|
+
const unregister = registerSessionPeerInbox(agent.context.sessionId, (sourceKey, kind, payload) => service.receive?.(sourceKey, kind, payload));
|
|
100
|
+
return async () => {
|
|
101
|
+
unregister();
|
|
102
|
+
for (const release of unprovide.reverse()) release();
|
|
103
|
+
await closeDelivery();
|
|
104
|
+
groups?.close();
|
|
105
|
+
};
|
|
106
|
+
}]
|
|
107
|
+
}));
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/services/peerInboxApi/index.ts
|
|
110
|
+
const MAX_BODY_BYTES = 65536;
|
|
111
|
+
const DELIVERY_TYPES = /* @__PURE__ */ new Set(["doom/session-delivery/envelope", "doom/session-delivery/ack"]);
|
|
112
|
+
function response(status, error) {
|
|
113
|
+
return Response.json({ error }, { status });
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/extensions/(backend)/api/session-peer/route.server.ts
|
|
117
|
+
var route_server_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoute)({
|
|
118
|
+
basePath: "session-peer",
|
|
119
|
+
start(context) {
|
|
120
|
+
const config = context.homeDirectory === void 0 ? void 0 : require_sessionDelivery.readSessionPeerConfig(context.homeDirectory);
|
|
121
|
+
const replay = context.homeDirectory === void 0 ? void 0 : require_sessionDelivery.createPeerReplayGuard(context.homeDirectory);
|
|
122
|
+
return {
|
|
123
|
+
async fetch(request) {
|
|
124
|
+
if (request.method !== "POST" || new URL(request.url).pathname !== "/inbox") return response(404, "Not found.");
|
|
125
|
+
if (!config) return response(503, "Paired Session delivery is not configured.");
|
|
126
|
+
const length = request.headers.get("content-length");
|
|
127
|
+
if (length !== null && (!/^\d+$/u.test(length) || Number(length) > MAX_BODY_BYTES)) return response(413, "Request body is too large.");
|
|
128
|
+
const body = await request.text();
|
|
129
|
+
if (Buffer.byteLength(body) > MAX_BODY_BYTES) return response(413, "Request body is too large.");
|
|
130
|
+
const peer = require_sessionDelivery.verifyPeerRequest(config, request, body);
|
|
131
|
+
if (!peer) return response(401, "Paired Session request is unauthorized.");
|
|
132
|
+
if (!replay?.admit(request)) return response(409, "Paired Session request was already received.");
|
|
133
|
+
let parsed;
|
|
134
|
+
try {
|
|
135
|
+
parsed = JSON.parse(body);
|
|
136
|
+
} catch {
|
|
137
|
+
return response(400, "Paired Session request is malformed.");
|
|
138
|
+
}
|
|
139
|
+
const envelope = require_sessionDelivery.parseSessionPeerEnvelope(parsed);
|
|
140
|
+
if (!envelope || !DELIVERY_TYPES.has(envelope.type)) return response(400, "Paired Session envelope is invalid.");
|
|
141
|
+
if (!peer.allowedSessionIds.includes(envelope.targetSessionId)) return response(403, "Peer is not granted this session.");
|
|
142
|
+
const state = deliverSessionPeerEnvelope(envelope.targetSessionId, require_sessionDelivery.peerSessionReference(peer.hostId, envelope.sourceSessionId), envelope.type, envelope.payload);
|
|
143
|
+
return state === void 0 ? response(404, "Target Session is unavailable.") : Response.json({
|
|
144
|
+
accepted: true,
|
|
145
|
+
state
|
|
146
|
+
}, { status: 202 });
|
|
147
|
+
},
|
|
148
|
+
close: () => replay?.close()
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
//#endregion
|
|
9
153
|
//#region generated/server.ts
|
|
10
154
|
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
11
|
-
const facet = (0,
|
|
155
|
+
const facet = (0, _agimon_ai_doompi_core_serverFacet.defineServerPlugin)({
|
|
12
156
|
name: "@agimon-ai/doompi-session",
|
|
13
157
|
global: (context) => ({ get api() {
|
|
14
|
-
return [at(
|
|
158
|
+
return [at(route_server_default, context)];
|
|
15
159
|
} }),
|
|
16
160
|
workspace: (context) => ({ get api() {
|
|
17
|
-
return [at(
|
|
161
|
+
return [at(route_server_default, context)];
|
|
18
162
|
} }),
|
|
19
163
|
session: async (context) => {
|
|
20
|
-
const scopeSession = await
|
|
164
|
+
const scopeSession = await root_server_default(context);
|
|
21
165
|
return {
|
|
22
|
-
...(0,
|
|
166
|
+
...(0, _agimon_ai_doompi_core_extensionFile.composeRootHooks)(scopeSession),
|
|
23
167
|
get api() {
|
|
24
|
-
return [at(
|
|
168
|
+
return [at(route_server_default, context)];
|
|
25
169
|
},
|
|
26
170
|
services: [...scopeSession.services ?? []],
|
|
27
171
|
get activities() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.cjs","names":["defineServerPlugin","apiRoute","rootSession","composeRootHooks"],"sources":["../../generated/server.ts"],"sourcesContent":["// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extension-file';\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/doompi-session',\n global: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":";;;;;;;;;AAQA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAa,SAAA,GAAQA,oCAAAA,mBAAAA,CAAmB;CACtC,MAAM;CACN,SAAS,aAAa,EACpB,IAAI,MAAsC;EAAE,OAAO,CAAC,GAAGC,qBAAAA,SAAU,OAAO,CAAC;CAAG,EAC9E;CACA,YAAY,aAAa,EACvB,IAAI,MAAsC;EAAE,OAAO,CAAC,GAAGA,qBAAAA,SAAU,OAAO,CAAC;CAAG,EAC9E;CACA,SAAS,OAAO,YAAY;EAC1B,MAAM,eAAe,MAAMC,oBAAAA,QAAY,OAAO;EAC9C,OAAO;GACL,IAAA,GAAGC,sCAAAA,iBAAAA,CAAiB,YAAY;GAChC,IAAI,MAAsC;IAAE,OAAO,CAAC,GAAGF,qBAAAA,SAAU,OAAO,CAAC;GAAG;GAC5E,UAAU,CAAC,GAAI,aAAa,YAAY,CAAC,CAAE;GAC3C,IAAI,aAAoD;IAAE,OAAO,CAAC,GAAI,aAAa,cAAc,CAAC,CAAE;GAAG;EACzG;CACF;AACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"server.cjs","names":["defineRoot","provideBackgroundWorkService","path","createPeerCommunication","readSessionPeerConfig","parseRemoteSessionReference","createSessionGroupStore","peerSessionReference","createSessionGroupDeliveryAuthorizer","provideSessionDeliveryService","createSessionDirectory","DOOM_SESSION_INTERCOM_SERVICE","createSessionIntercom","readSessionPeerConfig","createPeerReplayGuard","verifyPeerRequest","parseSessionPeerEnvelope","peerSessionReference","defineRoute","defineServerPlugin","apiRoute","rootSession","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 { DoomSessionDeliveryInboxState } from '../sessionDelivery';\n\nexport type SessionPeerInbox = (\n sourceKey: string,\n type: string,\n payload: unknown,\n) => DoomSessionDeliveryInboxState | undefined;\n\nconst inboxes = new Map<string, SessionPeerInbox>();\n\n/** Registers one live session-owned peer inbox. This registry is reachable only by the Session route. */\nexport function registerSessionPeerInbox(sessionId: string, inbox: SessionPeerInbox): () => void {\n if (inboxes.has(sessionId)) throw new Error(`Session peer inbox '${sessionId}' is already registered.`);\n inboxes.set(sessionId, inbox);\n return () => {\n if (inboxes.get(sessionId) === inbox) inboxes.delete(sessionId);\n };\n}\n\nexport function deliverSessionPeerEnvelope(\n targetSessionId: string,\n sourceKey: string,\n type: string,\n payload: unknown,\n): DoomSessionDeliveryInboxState | undefined {\n return inboxes.get(targetSessionId)?.(sourceKey, type, payload);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { provideBackgroundWorkService } from '../../../../services/backgroundWorkService';\nimport { registerSessionPeerInbox } from '../../../../services/peerInbox';\nimport {\n createPeerCommunication,\n parseRemoteSessionReference,\n peerSessionReference,\n readSessionPeerConfig,\n} from '../../../../services/peerTransport';\nimport { provideSessionDeliveryService } from '../../../../services/sessionDelivery';\nimport { createSessionDirectory } from '../../../../services/sessionDirectory';\nimport { createSessionGroupStore } from '../../../../services/sessionGroups';\nimport {\n DOOM_SESSION_INTERCOM_SERVICE,\n createSessionGroupDeliveryAuthorizer,\n createSessionIntercom,\n} from '../../../../services/sessionIntercom';\n\nexport default defineRoot((pluginContext: DoomServerPluginContext) => ({\n value: undefined,\n services: [\n provideBackgroundWorkService,\n (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 sessionDirectory = path.join(homeDirectory, '.pi', '.doom', 'session');\n const deliveryDirectory = path.join(sessionDirectory, 'delivery');\n fs.mkdirSync(deliveryDirectory, { recursive: true, mode: 0o700 });\n const peerCommunication = createPeerCommunication({ local: communication, homeDirectory });\n const peerConfig = readSessionPeerConfig(homeDirectory);\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 ? createSessionGroupStore({ databasePath: path.join(sessionDirectory, 'groups.sqlite') })\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 const { service, close: closeDelivery } = provideSessionDeliveryService(context, {\n databasePath: path.join(deliveryDirectory, `${agent.context.sessionId}.sqlite`),\n recipientKey: agent.context.sessionId,\n communication: peerCommunication,\n authorizePeer: (peerKey, metadata) => groupAuthorization?.(peerKey, metadata) ?? fallbackAuthorization(peerKey),\n admitPrompt: (prompt, delivery) => session.admitPrompt!(prompt, delivery),\n });\n const unprovide: (() => void)[] = [];\n if (groups && selfReference && peerConfig) {\n const directory = createSessionDirectory({\n authorizeDiscovery: (caller, subject) => {\n const reference = peerSessionReference(subject.hostId, subject.sessionId);\n const permitted = 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 DOOM_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 groups?.close();\n };\n },\n ],\n}));\n","import type { DoomApi, DoomApiHandler } from '@agimon-ai/doompi-core/packageApi';\n\nimport { deliverSessionPeerEnvelope } from '../peerInbox';\nimport {\n createPeerReplayGuard,\n parseSessionPeerEnvelope,\n peerSessionReference,\n readSessionPeerConfig,\n verifyPeerRequest,\n} from '../peerTransport';\n\nconst MAX_BODY_BYTES = 64 * 1024;\nconst DELIVERY_TYPES = new Set(['doom/session-delivery/envelope', 'doom/session-delivery/ack']);\n\nfunction response(status: number, error: string): Response {\n return Response.json({ error }, { status });\n}\n\n/** Narrow HMAC-authenticated endpoint that a trusted tunnel may forward without device authentication. */\nexport const peerInboxApi: DoomApi = {\n basePath: 'session-peer',\n start(context): DoomApiHandler {\n const config = context.homeDirectory === undefined ? undefined : readSessionPeerConfig(context.homeDirectory);\n const replay = context.homeDirectory === undefined ? undefined : createPeerReplayGuard(context.homeDirectory);\n return {\n async fetch(request) {\n if (request.method !== 'POST' || new URL(request.url).pathname !== '/inbox') return response(404, 'Not found.');\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 (!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 = 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 close: () => replay?.close(),\n };\n },\n};\n","import { defineRoute } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { peerInboxApi } from '../../../../services/peerInboxApi';\n\nexport default defineRoute(peerInboxApi);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-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/doompi-session',\n global: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n workspace: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return [at(apiRoute, context)]; },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region generated/server.d.ts
|
|
2
|
-
export declare const facet: import("@agimon-ai/doompi-core/
|
|
2
|
+
export declare const facet: import("@agimon-ai/doompi-core/serverFacet").DoomServerFacet;
|
|
3
3
|
//#endregion
|
|
4
4
|
export { facet as default };
|
|
5
5
|
//# sourceMappingURL=server.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAWa,
|
|
1
|
+
{"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAWa,oDAAK"}
|
|
@@ -1,7 +1,149 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import { n as provideBackgroundWorkService } from "../backgroundWorkService-ChVXCzxj.mjs";
|
|
2
|
+
import { a as createSessionGroupDeliveryAuthorizer, f as createSessionDirectory, g as parseSessionPeerEnvelope, h as parseRemoteSessionReference, m as createPeerReplayGuard, n as provideSessionDeliveryService, o as createSessionIntercom, p as createPeerCommunication, s as DOOM_SESSION_INTERCOM_SERVICE, u as createSessionGroupStore, v as peerSessionReference, x as verifyPeerRequest, y as readSessionPeerConfig } from "../sessionDelivery-C_rANfaY.mjs";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { composeRootHooks, defineRoot, defineRoute } from "@agimon-ai/doompi-core/extensionFile";
|
|
6
|
+
import { defineServerPlugin } from "@agimon-ai/doompi-core/serverFacet";
|
|
7
|
+
//#region src/services/peerInbox/index.ts
|
|
8
|
+
const inboxes = /* @__PURE__ */ new Map();
|
|
9
|
+
/** Registers one live session-owned peer inbox. This registry is reachable only by the Session route. */
|
|
10
|
+
function registerSessionPeerInbox(sessionId, inbox) {
|
|
11
|
+
if (inboxes.has(sessionId)) throw new Error(`Session peer inbox '${sessionId}' is already registered.`);
|
|
12
|
+
inboxes.set(sessionId, inbox);
|
|
13
|
+
return () => {
|
|
14
|
+
if (inboxes.get(sessionId) === inbox) inboxes.delete(sessionId);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function deliverSessionPeerEnvelope(targetSessionId, sourceKey, type, payload) {
|
|
18
|
+
return inboxes.get(targetSessionId)?.(sourceKey, type, payload);
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/extensions/workspaces/sessions/(backend)/root.server.ts
|
|
22
|
+
var root_server_default = defineRoot((pluginContext) => ({
|
|
23
|
+
value: void 0,
|
|
24
|
+
services: [provideBackgroundWorkService, (context) => {
|
|
25
|
+
const agent = pluginContext.agent;
|
|
26
|
+
const session = agent?.context.session;
|
|
27
|
+
const communication = pluginContext.host.context.sessionCommunication;
|
|
28
|
+
const homeDirectory = pluginContext.host.context.homeDirectory;
|
|
29
|
+
const sessionService = pluginContext.host.context.sessionService;
|
|
30
|
+
if (!agent || !session?.admitPrompt || !communication || !homeDirectory || !sessionService?.canCommunicate) throw new Error("Session delivery requires the headless agent, authenticated session communication, host home directory, and communication policy.");
|
|
31
|
+
const sessionDirectory = path.join(homeDirectory, ".pi", ".doom", "session");
|
|
32
|
+
const deliveryDirectory = path.join(sessionDirectory, "delivery");
|
|
33
|
+
fs.mkdirSync(deliveryDirectory, {
|
|
34
|
+
recursive: true,
|
|
35
|
+
mode: 448
|
|
36
|
+
});
|
|
37
|
+
const peerCommunication = createPeerCommunication({
|
|
38
|
+
local: communication,
|
|
39
|
+
homeDirectory
|
|
40
|
+
});
|
|
41
|
+
const peerConfig = readSessionPeerConfig(homeDirectory);
|
|
42
|
+
const remotePeerIsGranted = (peerKey) => {
|
|
43
|
+
const peer = parseRemoteSessionReference(peerKey);
|
|
44
|
+
return peer !== void 0 && peerConfig?.peers.some((candidate) => candidate.hostId === peer.hostId && candidate.allowedSessionIds.includes(agent.context.sessionId)) === true;
|
|
45
|
+
};
|
|
46
|
+
const fallbackAuthorization = (peerKey) => sessionService.canCommunicate?.(agent.context.sessionId, peerKey) === true || remotePeerIsGranted(peerKey);
|
|
47
|
+
const groups = peerConfig ? createSessionGroupStore({ databasePath: path.join(sessionDirectory, "groups.sqlite") }) : void 0;
|
|
48
|
+
const localHostId = peerConfig?.hostId;
|
|
49
|
+
const selfReference = localHostId ? peerSessionReference(localHostId, agent.context.sessionId) : void 0;
|
|
50
|
+
const groupAuthorization = groups && selfReference && localHostId ? createSessionGroupDeliveryAuthorizer({
|
|
51
|
+
selfReference,
|
|
52
|
+
groups,
|
|
53
|
+
peerReference: (peerKey) => parseRemoteSessionReference(peerKey) === void 0 ? peerSessionReference(localHostId, peerKey) : peerKey,
|
|
54
|
+
fallback: fallbackAuthorization
|
|
55
|
+
}) : void 0;
|
|
56
|
+
const { service, close: closeDelivery } = provideSessionDeliveryService(context, {
|
|
57
|
+
databasePath: path.join(deliveryDirectory, `${agent.context.sessionId}.sqlite`),
|
|
58
|
+
recipientKey: agent.context.sessionId,
|
|
59
|
+
communication: peerCommunication,
|
|
60
|
+
authorizePeer: (peerKey, metadata) => groupAuthorization?.(peerKey, metadata) ?? fallbackAuthorization(peerKey),
|
|
61
|
+
admitPrompt: (prompt, delivery) => session.admitPrompt(prompt, delivery)
|
|
62
|
+
});
|
|
63
|
+
const unprovide = [];
|
|
64
|
+
if (groups && selfReference && peerConfig) {
|
|
65
|
+
const directory = createSessionDirectory({ authorizeDiscovery: (caller, subject) => {
|
|
66
|
+
const reference = peerSessionReference(subject.hostId, subject.sessionId);
|
|
67
|
+
return groups.groupsFor(caller).some((group) => group.members.includes(reference)) ? { capabilities: ["message"] } : void 0;
|
|
68
|
+
} });
|
|
69
|
+
for (const peer of peerConfig.peers) for (const sessionId of peer.allowedSessionIds) directory.observe({
|
|
70
|
+
hostId: peer.hostId,
|
|
71
|
+
sessionId,
|
|
72
|
+
hostIncarnation: "unknown",
|
|
73
|
+
sessionIncarnation: "unknown",
|
|
74
|
+
sequence: 0,
|
|
75
|
+
observedAt: 0,
|
|
76
|
+
staleAfterMs: 0,
|
|
77
|
+
deliveryTarget: peerSessionReference(peer.hostId, sessionId),
|
|
78
|
+
reachability: "unknown",
|
|
79
|
+
runtime: "unknown",
|
|
80
|
+
activity: "unknown",
|
|
81
|
+
voice: {
|
|
82
|
+
eligible: "unknown",
|
|
83
|
+
readiness: "unknown"
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
unprovide.push(context.provide(DOOM_SESSION_INTERCOM_SERVICE, createSessionIntercom({
|
|
87
|
+
selfReference,
|
|
88
|
+
directory,
|
|
89
|
+
groups,
|
|
90
|
+
delivery: service
|
|
91
|
+
})));
|
|
92
|
+
}
|
|
93
|
+
const unregister = registerSessionPeerInbox(agent.context.sessionId, (sourceKey, kind, payload) => service.receive?.(sourceKey, kind, payload));
|
|
94
|
+
return async () => {
|
|
95
|
+
unregister();
|
|
96
|
+
for (const release of unprovide.reverse()) release();
|
|
97
|
+
await closeDelivery();
|
|
98
|
+
groups?.close();
|
|
99
|
+
};
|
|
100
|
+
}]
|
|
101
|
+
}));
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/services/peerInboxApi/index.ts
|
|
104
|
+
const MAX_BODY_BYTES = 65536;
|
|
105
|
+
const DELIVERY_TYPES = /* @__PURE__ */ new Set(["doom/session-delivery/envelope", "doom/session-delivery/ack"]);
|
|
106
|
+
function response(status, error) {
|
|
107
|
+
return Response.json({ error }, { status });
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/extensions/(backend)/api/session-peer/route.server.ts
|
|
111
|
+
var route_server_default = defineRoute({
|
|
112
|
+
basePath: "session-peer",
|
|
113
|
+
start(context) {
|
|
114
|
+
const config = context.homeDirectory === void 0 ? void 0 : readSessionPeerConfig(context.homeDirectory);
|
|
115
|
+
const replay = context.homeDirectory === void 0 ? void 0 : createPeerReplayGuard(context.homeDirectory);
|
|
116
|
+
return {
|
|
117
|
+
async fetch(request) {
|
|
118
|
+
if (request.method !== "POST" || new URL(request.url).pathname !== "/inbox") return response(404, "Not found.");
|
|
119
|
+
if (!config) return response(503, "Paired Session delivery is not configured.");
|
|
120
|
+
const length = request.headers.get("content-length");
|
|
121
|
+
if (length !== null && (!/^\d+$/u.test(length) || Number(length) > MAX_BODY_BYTES)) return response(413, "Request body is too large.");
|
|
122
|
+
const body = await request.text();
|
|
123
|
+
if (Buffer.byteLength(body) > MAX_BODY_BYTES) return response(413, "Request body is too large.");
|
|
124
|
+
const peer = verifyPeerRequest(config, request, body);
|
|
125
|
+
if (!peer) return response(401, "Paired Session request is unauthorized.");
|
|
126
|
+
if (!replay?.admit(request)) return response(409, "Paired Session request was already received.");
|
|
127
|
+
let parsed;
|
|
128
|
+
try {
|
|
129
|
+
parsed = JSON.parse(body);
|
|
130
|
+
} catch {
|
|
131
|
+
return response(400, "Paired Session request is malformed.");
|
|
132
|
+
}
|
|
133
|
+
const envelope = parseSessionPeerEnvelope(parsed);
|
|
134
|
+
if (!envelope || !DELIVERY_TYPES.has(envelope.type)) return response(400, "Paired Session envelope is invalid.");
|
|
135
|
+
if (!peer.allowedSessionIds.includes(envelope.targetSessionId)) return response(403, "Peer is not granted this session.");
|
|
136
|
+
const state = deliverSessionPeerEnvelope(envelope.targetSessionId, peerSessionReference(peer.hostId, envelope.sourceSessionId), envelope.type, envelope.payload);
|
|
137
|
+
return state === void 0 ? response(404, "Target Session is unavailable.") : Response.json({
|
|
138
|
+
accepted: true,
|
|
139
|
+
state
|
|
140
|
+
}, { status: 202 });
|
|
141
|
+
},
|
|
142
|
+
close: () => replay?.close()
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
//#endregion
|
|
5
147
|
//#region generated/server.ts
|
|
6
148
|
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
7
149
|
const facet = defineServerPlugin({
|