@di-code/coding-agent 0.1.9 → 0.2.2
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/README.md +7 -0
- package/compositions/base.yml +3 -0
- package/dist/compositions.d.ts.map +1 -1
- package/dist/compositions.js +2 -0
- package/dist/compositions.js.map +1 -1
- package/dist/core/image-input.d.ts +1 -1
- package/dist/core/image-input.d.ts.map +1 -1
- package/dist/core/image-input.js +15 -4
- package/dist/core/image-input.js.map +1 -1
- package/dist/core/session/session-manager.d.ts +18 -1
- package/dist/core/session/session-manager.d.ts.map +1 -1
- package/dist/core/session/session-manager.js +90 -1
- package/dist/core/session/session-manager.js.map +1 -1
- package/dist/core/session/session-storage.d.ts +2 -0
- package/dist/core/session/session-storage.d.ts.map +1 -1
- package/dist/core/session/session-storage.js +34 -2
- package/dist/core/session/session-storage.js.map +1 -1
- package/dist/core/session/types.d.ts +16 -1
- package/dist/core/session/types.d.ts.map +1 -1
- package/dist/core/session/types.js.map +1 -1
- package/dist/core/session.d.ts +27 -2
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +59 -0
- package/dist/core/session.js.map +1 -1
- package/dist/entry.js +1 -1
- package/dist/entry.js.map +1 -1
- package/dist/i18n.js +4 -4
- package/dist/i18n.js.map +1 -1
- package/dist/interactive-host-entry.d.ts.map +1 -1
- package/dist/interactive-host-entry.js +107 -12
- package/dist/interactive-host-entry.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +8 -1
- package/dist/main.js.map +1 -1
- package/dist/mcp/config.d.ts.map +1 -1
- package/dist/mcp/config.js +19 -0
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp-command-entry.d.ts +8 -0
- package/dist/mcp-command-entry.d.ts.map +1 -0
- package/dist/mcp-command-entry.js +56 -0
- package/dist/mcp-command-entry.js.map +1 -0
- package/dist/modes/interactive-components.d.ts +8 -0
- package/dist/modes/interactive-components.d.ts.map +1 -1
- package/dist/modes/interactive-components.js +7 -2
- package/dist/modes/interactive-components.js.map +1 -1
- package/dist/modes/interactive-state.d.ts.map +1 -1
- package/dist/modes/interactive-state.js +1 -4
- package/dist/modes/interactive-state.js.map +1 -1
- package/dist/modes/interactive.d.ts +4 -0
- package/dist/modes/interactive.d.ts.map +1 -1
- package/dist/modes/interactive.js +69 -0
- package/dist/modes/interactive.js.map +1 -1
- package/dist/modes/tree-selector.d.ts.map +1 -1
- package/dist/modes/tree-selector.js +5 -4
- package/dist/modes/tree-selector.js.map +1 -1
- package/dist/rpc/client.d.ts +2 -0
- package/dist/rpc/client.d.ts.map +1 -1
- package/dist/rpc/client.js +3 -0
- package/dist/rpc/client.js.map +1 -1
- package/dist/rpc/dispatcher.d.ts +14 -0
- package/dist/rpc/dispatcher.d.ts.map +1 -1
- package/dist/rpc/dispatcher.js +222 -7
- package/dist/rpc/dispatcher.js.map +1 -1
- package/dist/rpc/protocol.d.ts +12 -5
- package/dist/rpc/protocol.d.ts.map +1 -1
- package/dist/rpc/protocol.js +56 -0
- package/dist/rpc/protocol.js.map +1 -1
- package/dist/rpc/server.d.ts +5 -0
- package/dist/rpc/server.d.ts.map +1 -1
- package/dist/rpc/server.js +4 -0
- package/dist/rpc/server.js.map +1 -1
- package/dist/rpc-server-entry.d.ts.map +1 -1
- package/dist/rpc-server-entry.js +15 -1
- package/dist/rpc-server-entry.js.map +1 -1
- package/dist/runtime/product-host.d.ts +7 -0
- package/dist/runtime/product-host.d.ts.map +1 -1
- package/dist/runtime/product-host.js +29 -9
- package/dist/runtime/product-host.js.map +1 -1
- package/dist/runtime/session-factory.d.ts +18 -2
- package/dist/runtime/session-factory.d.ts.map +1 -1
- package/dist/runtime/session-factory.js +286 -23
- package/dist/runtime/session-factory.js.map +1 -1
- package/dist/runtime/session-host.d.ts +46 -1
- package/dist/runtime/session-host.d.ts.map +1 -1
- package/dist/runtime/session-host.js +38 -6
- package/dist/runtime/session-host.js.map +1 -1
- package/dist/ui-host.d.ts.map +1 -1
- package/dist/ui-host.js +3 -0
- package/dist/ui-host.js.map +1 -1
- package/dist/web/assets/index-C2SOU925.css +1 -0
- package/dist/web/assets/index-knXkInvO.js +41 -0
- package/dist/web/assets/index-knXkInvO.js.map +1 -0
- package/dist/web/index.html +2 -2
- package/dist/web-command.d.ts.map +1 -1
- package/dist/web-command.js +8 -1
- package/dist/web-command.js.map +1 -1
- package/dist/webui-entry.js +9 -1
- package/dist/webui-entry.js.map +1 -1
- package/dist/webui.d.ts +10 -0
- package/dist/webui.d.ts.map +1 -1
- package/dist/webui.js +21 -0
- package/dist/webui.js.map +1 -1
- package/package.json +11 -9
- package/dist/web/assets/index-BwfuGMvv.css +0 -1
- package/dist/web/assets/index-DPUaJqFJ.js +0 -41
- package/dist/web/assets/index-DPUaJqFJ.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
- `di-code-webui`:供自定义客户端使用的 HTTP/SSE WebUI 传输层;
|
|
8
8
|
- `di-code-rpc`:供 Node.js 宿主程序管理 Agent 的 JSONL RPC 入口。
|
|
9
9
|
|
|
10
|
+
助手消息可以包含 Provider 返回的图片内容。WebUI 会把图片和文本一起渲染在助手聊天气泡中,并通过 Session/RPC transcript 持久化;插件可注册支持 `image` 输出的 Provider 以接入生图模型。
|
|
11
|
+
|
|
10
12
|
需要 Node.js `>=22.19.0`。已发布版本可直接安装:
|
|
11
13
|
|
|
12
14
|
```powershell
|
|
@@ -76,6 +78,8 @@ npm run dev
|
|
|
76
78
|
npm run dev -- --interactive
|
|
77
79
|
```
|
|
78
80
|
|
|
81
|
+
交互模式中可使用 `/plan` 进入 Plan Mode,`/plan <message>` 会先启用模式并提交该需求,`/plan off` 退出。命令会显示在 `/` 补全和 `/help` 列表中,不会把命令本身作为用户消息发送。
|
|
82
|
+
|
|
79
83
|
### 首次 Provider 向导
|
|
80
84
|
|
|
81
85
|
在真实 TTY 中启动,且没有 `DI_CODE_PROVIDER`、默认 Provider 或唯一已配置 Provider 时,会自动打开向导。向导依次让你:
|
|
@@ -102,3 +106,6 @@ README 只保留最短启动路径,其他功能请按主题阅读 GitHub `docs
|
|
|
102
106
|
- [插件使用指南](https://github.com/qddidi/di-code/tree/master/docs/插件使用指南.md)
|
|
103
107
|
- [开发教程](https://github.com/qddidi/di-code/tree/master/docs/开发教程.md)
|
|
104
108
|
- [运行时与 RPC 架构](https://github.com/qddidi/di-code/tree/master/docs/架构/运行时与RPC.md)
|
|
109
|
+
# User interaction
|
|
110
|
+
|
|
111
|
+
RPC/WebUI hosts expose versioned `interaction_request` events and accept `respond_interaction` replies. Requests correlate `requestId` and optional `toolCallId`; duplicate replies are idempotent, and unavailable channels fail fast. Legacy tool approval remains deny-by-default without a negotiated UI channel.
|
package/compositions/base.yml
CHANGED
|
@@ -15,6 +15,7 @@ entries:
|
|
|
15
15
|
- { id: credential-env, name: "@di-code/builtins/credential-env", dependsOn: [provider-registry] }
|
|
16
16
|
- { id: runtime-selection, name: "@di-code/builtins/runtime-selection", dependsOn: [provider-registry] }
|
|
17
17
|
- { id: provider-faux, name: "@di-code/builtins/provider-faux", dependsOn: [provider-registry] }
|
|
18
|
+
- { id: image-generation, name: "@di-code/builtins/image-generation", dependsOn: [runtime], required: false }
|
|
18
19
|
- { id: provider-openai, name: "@di-code/builtins/provider-openai", dependsOn: [provider-registry, runtime-selection, credential-env], required: false }
|
|
19
20
|
- { id: provider-anthropic, name: "@di-code/builtins/provider-anthropic", dependsOn: [provider-registry, runtime-selection, credential-env], required: false }
|
|
20
21
|
- { id: provider-deepseek, name: "@di-code/builtins/provider-deepseek", dependsOn: [provider-registry, runtime-selection, credential-env], required: false }
|
|
@@ -31,6 +32,7 @@ entries:
|
|
|
31
32
|
- { id: tool-output, name: "@di-code/builtins/tool-output", dependsOn: [tool-registry] }
|
|
32
33
|
- { id: tool-read, name: "@di-code/builtins/tool-read", dependsOn: [tool-registry, workspace] }
|
|
33
34
|
- { id: tool-write, name: "@di-code/builtins/tool-write", dependsOn: [tool-registry, workspace] }
|
|
35
|
+
- { id: tool-generate-image, name: "@di-code/builtins/tool-generate-image", dependsOn: [tool-registry, image-generation], required: false }
|
|
34
36
|
- { id: tool-edit, name: "@di-code/builtins/tool-edit", dependsOn: [tool-registry, workspace] }
|
|
35
37
|
- { id: tool-bash, name: "@di-code/builtins/tool-bash", dependsOn: [tool-registry, workspace] }
|
|
36
38
|
- { id: tool-glob, name: "@di-code/builtins/tool-glob", dependsOn: [tool-registry, workspace] }
|
|
@@ -52,3 +54,4 @@ entries:
|
|
|
52
54
|
- { id: mcp-transport, name: "@di-code/coding-agent/mcp-transport-entry", dependsOn: [mcp-config] }
|
|
53
55
|
- { id: mcp-client, name: "@di-code/coding-agent/mcp-client-entry", dependsOn: [mcp-config, mcp-transport] }
|
|
54
56
|
- { id: mcp-tools, name: "@di-code/coding-agent/mcp-tools-entry", dependsOn: [mcp-config, mcp-client] }
|
|
57
|
+
- { id: mcp-command, name: "@di-code/coding-agent/mcp-command-entry", dependsOn: [command-core, mcp-config] }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compositions.d.ts","sourceRoot":"","sources":["../src/compositions.ts"],"names":[],"mappings":"AAGA,OAAO,EAEN,KAAK,gBAAgB,EAIrB,KAAK,YAAY,EAGjB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;AAEjG,MAAM,WAAW,4BAA4B;IAC5C,qFAAqF;IACrF,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,qEAAqE;IACrE,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAkBD,sEAAsE;AACtE,wBAAsB,yBAAyB,CAC9C,IAAI,EAAE,sBAAsB,EAC5B,OAAO,GAAE;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/E,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAetC;AAyDD;;;GAGG;AACH,wBAAsB,yBAAyB,CAC9C,IAAI,EAAE,sBAAsB,EAC5B,OAAO,GAAE,4BAAiC,GACxC,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CA2BtC;AAED;;;GAGG;AACH,wBAAsB,gCAAgC,CACrD,QAAQ,SAA8B,GACpC,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAatC;AAED,wGAAwG;AACxG,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"compositions.d.ts","sourceRoot":"","sources":["../src/compositions.ts"],"names":[],"mappings":"AAGA,OAAO,EAEN,KAAK,gBAAgB,EAIrB,KAAK,YAAY,EAGjB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;AAEjG,MAAM,WAAW,4BAA4B;IAC5C,qFAAqF;IACrF,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,qEAAqE;IACrE,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAkBD,sEAAsE;AACtE,wBAAsB,yBAAyB,CAC9C,IAAI,EAAE,sBAAsB,EAC5B,OAAO,GAAE;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/E,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAetC;AAyDD;;;GAGG;AACH,wBAAsB,yBAAyB,CAC9C,IAAI,EAAE,sBAAsB,EAC5B,OAAO,GAAE,4BAAiC,GACxC,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CA2BtC;AAED;;;GAGG;AACH,wBAAsB,gCAAgC,CACrD,QAAQ,SAA8B,GACpC,OAAO,CAAC,SAAS,gBAAgB,EAAE,CAAC,CAatC;AAED,wGAAwG;AACxG,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAyC3E"}
|
package/dist/compositions.js
CHANGED
|
@@ -148,6 +148,8 @@ export function importCompositionModule(name) {
|
|
|
148
148
|
return import("./mcp-transport-entry.js");
|
|
149
149
|
case "@di-code/coding-agent/mcp-tools-entry":
|
|
150
150
|
return import("./mcp-tools-entry.js");
|
|
151
|
+
case "@di-code/coding-agent/mcp-command-entry":
|
|
152
|
+
return import("./mcp-command-entry.js");
|
|
151
153
|
case "@di-code/coding-agent/session-factory-entry":
|
|
152
154
|
return import("./session-factory-entry.js");
|
|
153
155
|
case "@di-code/coding-agent/session-store-jsonl-entry":
|
package/dist/compositions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compositions.js","sourceRoot":"","sources":["../src/compositions.ts"],"names":[],"mappings":"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","sourcesContent":["import { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n\ttype CompositionDocument,\n\ttype CompositionEntry,\n\ttype CompositionLayer,\n\tmergeCompositionLayers,\n\tPluginInstallManager,\n\ttype PluginModule,\n\treadCompositionFile,\n\tresolvePackagePluginExport,\n} from \"@di-code/plugin-loader\";\n\nexport type DefaultCompositionName = \"base\" | \"interactive\" | \"print\" | \"json\" | \"rpc\" | \"webui\";\n\nexport interface CompositionResolutionOptions {\n\t/** Work root used for project composition discovery and the workspace capability. */\n\treadonly cwd?: string;\n\t/** User data root containing the optional user composition document. */\n\treadonly agentDir?: string;\n\t/** Explicit JSON or YAML composition document applied last. */\n\treadonly compositionPath?: string;\n\t/** Excludes the project composition document for this invocation. */\n\treadonly includeProjectComposition?: boolean;\n\treadonly observability?: boolean;\n\treadonly allowedRoot?: string;\n}\n\nconst observabilityEntries = [\n\t{ id: \"plugin-profiler\", name: \"@di-code/builtins/plugin-profiler\", dependsOn: [\"runtime\"] },\n\t{ id: \"plugin-invariants\", name: \"@di-code/builtins/plugin-invariants\", dependsOn: [\"runtime\"] },\n\t{ id: \"plugin-test-runtime\", name: \"@di-code/builtins/plugin-test-runtime\", dependsOn: [\"runtime\"] },\n\t{ id: \"plugin-trace\", name: \"@di-code/coding-agent/plugin-trace\", dependsOn: [\"plugin-inventory\"] },\n\t{\n\t\tid: \"plugin-dump-composition\",\n\t\tname: \"@di-code/coding-agent/plugin-dump-composition\",\n\t\tdependsOn: [\"plugin-inventory\"],\n\t},\n] as const satisfies readonly CompositionEntry[];\n\nfunction builtinCompositionPath(name: DefaultCompositionName): string {\n\treturn fileURLToPath(new URL(`../compositions/${name}.yml`, import.meta.url));\n}\n\n/** Resolves the package-owned base plus exactly one mode document. */\nexport async function resolveDefaultComposition(\n\tname: DefaultCompositionName,\n\toptions: { readonly observability?: boolean; readonly allowedRoot?: string } = {},\n): Promise<readonly CompositionEntry[]> {\n\tconst base = await readRequiredComposition(builtinCompositionPath(\"base\"));\n\tconst mode = name === \"base\" ? { entries: [] } : await readRequiredComposition(builtinCompositionPath(name));\n\treturn Object.freeze(\n\t\twithWorkspaceRoot(\n\t\t\tmergeCompositionLayers([\n\t\t\t\t{ name: \"base\", document: base },\n\t\t\t\t{\n\t\t\t\t\tname: \"mode\",\n\t\t\t\t\tdocument: { entries: [...(mode.entries ?? []), ...(options.observability ? observabilityEntries : [])] },\n\t\t\t\t},\n\t\t\t]),\n\t\t\toptions.allowedRoot,\n\t\t),\n\t);\n}\n\nfunction isJsonObject(\n\tvalue: CompositionEntry[\"config\"],\n): value is Readonly<Record<string, import(\"@di-code/plugin-loader\").JsonValue>> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withWorkspaceRoot(\n\tentries: readonly CompositionEntry[],\n\tallowedRoot: string | undefined,\n): readonly CompositionEntry[] {\n\tif (allowedRoot === undefined) return entries;\n\treturn entries.map((entry) =>\n\t\tentry.id === \"workspace\"\n\t\t\t? { ...entry, config: { ...(isJsonObject(entry.config) ? entry.config : {}), allowedRoot } }\n\t\t\t: entry,\n\t);\n}\n\nfunction markProjectEntries(document: CompositionDocument): CompositionDocument {\n\tconst mark = (entry: CompositionEntry): CompositionEntry => ({ ...entry, projectLocal: true });\n\treturn {\n\t\t...(document.entries ? { entries: document.entries.map(mark) } : {}),\n\t\t...(document.patches\n\t\t\t? {\n\t\t\t\t\tpatches: document.patches.map((patch) =>\n\t\t\t\t\t\t\"entry\" in patch && patch.entry !== undefined ? { ...patch, entry: mark(patch.entry) } : patch,\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nfunction isMissingFile(cause: unknown): boolean {\n\treturn typeof cause === \"object\" && cause !== null && \"code\" in cause && cause.code === \"ENOENT\";\n}\n\nasync function readOptionalComposition(filePath: string): Promise<CompositionDocument | undefined> {\n\ttry {\n\t\treturn await readCompositionFile(filePath);\n\t} catch (cause) {\n\t\tif (isMissingFile(cause)) return undefined;\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\tthrow new Error(`Failed to read composition ${filePath}: ${message}`, { cause });\n\t}\n}\n\nasync function readRequiredComposition(filePath: string): Promise<CompositionDocument> {\n\ttry {\n\t\treturn await readCompositionFile(filePath);\n\t} catch (cause) {\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\tthrow new Error(`Failed to read composition ${filePath}: ${message}`, { cause });\n\t}\n}\n\n/**\n * Resolves built-in, user, project, and explicit composition layers in their fixed precedence order.\n * Project entries are marked local so the Loader retains trust checks for entries added through project configuration.\n */\nexport async function resolveCompositionEntries(\n\tname: DefaultCompositionName,\n\toptions: CompositionResolutionOptions = {},\n): Promise<readonly CompositionEntry[]> {\n\tconst cwd = resolve(options.cwd ?? process.cwd());\n\tconst agentDir = resolve(options.agentDir ?? join(homedir(), \".di-code\"));\n\tconst [base, mode] = await Promise.all([\n\t\treadRequiredComposition(builtinCompositionPath(\"base\")),\n\t\treadRequiredComposition(builtinCompositionPath(name)),\n\t]);\n\tconst layers: CompositionLayer[] = [\n\t\t{ name: \"base\", document: base },\n\t\t{\n\t\t\tname: \"mode\",\n\t\t\tdocument: {\n\t\t\t\tentries: [...(mode.entries ?? []), ...(options.observability ? observabilityEntries : [])],\n\t\t\t},\n\t\t},\n\t];\n\tconst userComposition = await readOptionalComposition(join(agentDir, \"composition.yml\"));\n\tif (userComposition !== undefined) layers.push({ name: \"user\", document: userComposition });\n\tif (options.includeProjectComposition !== false) {\n\t\tconst projectComposition = await readOptionalComposition(join(cwd, \".di-code\", \"composition.yml\"));\n\t\tif (projectComposition !== undefined)\n\t\t\tlayers.push({ name: \"project\", document: markProjectEntries(projectComposition) });\n\t}\n\tif (options.compositionPath !== undefined) {\n\t\tlayers.push({ name: \"explicit\", document: await readRequiredComposition(resolve(cwd, options.compositionPath)) });\n\t}\n\treturn Object.freeze(withWorkspaceRoot(mergeCompositionLayers(layers), options.allowedRoot));\n}\n\n/**\n * Resolves only enabled managed plugins before the Loader receives its entry list.\n * Disabled manifests are not resolved or dynamically imported.\n */\nexport async function resolveManagedCompositionEntries(\n\tagentDir = join(homedir(), \".di-code\"),\n): Promise<readonly CompositionEntry[]> {\n\tconst manager = new PluginInstallManager({ managedRoot: join(resolve(agentDir), \"plugins\", \"installed\") });\n\tconst plugins = await manager.list();\n\treturn await Promise.all(\n\t\tplugins\n\t\t\t.filter((plugin) => plugin.enabled)\n\t\t\t.map(async (plugin) => ({\n\t\t\t\tid: `managed.${plugin.id}`,\n\t\t\t\tname: pathToFileURL(await resolvePackagePluginExport(plugin.installedPath, plugin.manifest.entry)).href,\n\t\t\t\tdependsOn: [\"Bootstrap\"],\n\t\t\t\trequired: false,\n\t\t\t})),\n\t);\n}\n\n/** Imports own composition entries from source in development; package exports handle published use. */\nexport function importCompositionModule(name: string): Promise<PluginModule> {\n\tswitch (name) {\n\t\tcase \"@di-code/coding-agent/plugin-manager\":\n\t\t\treturn import(\"./plugin-manager.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/plugin-inventory\":\n\t\t\treturn import(\"./plugin-inventory.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/plugin-trace\":\n\t\t\treturn import(\"./plugin-trace.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/plugin-dump-composition\":\n\t\t\treturn import(\"./plugin-dump-composition.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-config-entry\":\n\t\t\treturn import(\"./mcp-config-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-client-entry\":\n\t\t\treturn import(\"./mcp-client-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-transport-entry\":\n\t\t\treturn import(\"./mcp-transport-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-tools-entry\":\n\t\t\treturn import(\"./mcp-tools-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/session-factory-entry\":\n\t\t\treturn import(\"./session-factory-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/session-store-jsonl-entry\":\n\t\t\treturn import(\"./session-store-jsonl-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/rpc-server-entry\":\n\t\t\treturn import(\"./rpc-server-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/interactive-resources-entry\":\n\t\t\treturn import(\"./interactive-resources-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/interactive-host-entry\":\n\t\t\treturn import(\"./interactive-host-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/runtime-core-entry\":\n\t\t\treturn import(\"./runtime-core-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/composition-loader-entry\":\n\t\t\treturn import(\"./composition-loader-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/project-trust-entry\":\n\t\t\treturn import(\"./project-trust-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/rpc-client-sdk-entry\":\n\t\t\treturn import(\"./rpc-client-sdk-entry.ts\") as Promise<PluginModule>;\n\t\tdefault:\n\t\t\treturn import(name) as Promise<PluginModule>;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"compositions.js","sourceRoot":"","sources":["../src/compositions.ts"],"names":[],"mappings":"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","sourcesContent":["import { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport {\n\ttype CompositionDocument,\n\ttype CompositionEntry,\n\ttype CompositionLayer,\n\tmergeCompositionLayers,\n\tPluginInstallManager,\n\ttype PluginModule,\n\treadCompositionFile,\n\tresolvePackagePluginExport,\n} from \"@di-code/plugin-loader\";\n\nexport type DefaultCompositionName = \"base\" | \"interactive\" | \"print\" | \"json\" | \"rpc\" | \"webui\";\n\nexport interface CompositionResolutionOptions {\n\t/** Work root used for project composition discovery and the workspace capability. */\n\treadonly cwd?: string;\n\t/** User data root containing the optional user composition document. */\n\treadonly agentDir?: string;\n\t/** Explicit JSON or YAML composition document applied last. */\n\treadonly compositionPath?: string;\n\t/** Excludes the project composition document for this invocation. */\n\treadonly includeProjectComposition?: boolean;\n\treadonly observability?: boolean;\n\treadonly allowedRoot?: string;\n}\n\nconst observabilityEntries = [\n\t{ id: \"plugin-profiler\", name: \"@di-code/builtins/plugin-profiler\", dependsOn: [\"runtime\"] },\n\t{ id: \"plugin-invariants\", name: \"@di-code/builtins/plugin-invariants\", dependsOn: [\"runtime\"] },\n\t{ id: \"plugin-test-runtime\", name: \"@di-code/builtins/plugin-test-runtime\", dependsOn: [\"runtime\"] },\n\t{ id: \"plugin-trace\", name: \"@di-code/coding-agent/plugin-trace\", dependsOn: [\"plugin-inventory\"] },\n\t{\n\t\tid: \"plugin-dump-composition\",\n\t\tname: \"@di-code/coding-agent/plugin-dump-composition\",\n\t\tdependsOn: [\"plugin-inventory\"],\n\t},\n] as const satisfies readonly CompositionEntry[];\n\nfunction builtinCompositionPath(name: DefaultCompositionName): string {\n\treturn fileURLToPath(new URL(`../compositions/${name}.yml`, import.meta.url));\n}\n\n/** Resolves the package-owned base plus exactly one mode document. */\nexport async function resolveDefaultComposition(\n\tname: DefaultCompositionName,\n\toptions: { readonly observability?: boolean; readonly allowedRoot?: string } = {},\n): Promise<readonly CompositionEntry[]> {\n\tconst base = await readRequiredComposition(builtinCompositionPath(\"base\"));\n\tconst mode = name === \"base\" ? { entries: [] } : await readRequiredComposition(builtinCompositionPath(name));\n\treturn Object.freeze(\n\t\twithWorkspaceRoot(\n\t\t\tmergeCompositionLayers([\n\t\t\t\t{ name: \"base\", document: base },\n\t\t\t\t{\n\t\t\t\t\tname: \"mode\",\n\t\t\t\t\tdocument: { entries: [...(mode.entries ?? []), ...(options.observability ? observabilityEntries : [])] },\n\t\t\t\t},\n\t\t\t]),\n\t\t\toptions.allowedRoot,\n\t\t),\n\t);\n}\n\nfunction isJsonObject(\n\tvalue: CompositionEntry[\"config\"],\n): value is Readonly<Record<string, import(\"@di-code/plugin-loader\").JsonValue>> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction withWorkspaceRoot(\n\tentries: readonly CompositionEntry[],\n\tallowedRoot: string | undefined,\n): readonly CompositionEntry[] {\n\tif (allowedRoot === undefined) return entries;\n\treturn entries.map((entry) =>\n\t\tentry.id === \"workspace\"\n\t\t\t? { ...entry, config: { ...(isJsonObject(entry.config) ? entry.config : {}), allowedRoot } }\n\t\t\t: entry,\n\t);\n}\n\nfunction markProjectEntries(document: CompositionDocument): CompositionDocument {\n\tconst mark = (entry: CompositionEntry): CompositionEntry => ({ ...entry, projectLocal: true });\n\treturn {\n\t\t...(document.entries ? { entries: document.entries.map(mark) } : {}),\n\t\t...(document.patches\n\t\t\t? {\n\t\t\t\t\tpatches: document.patches.map((patch) =>\n\t\t\t\t\t\t\"entry\" in patch && patch.entry !== undefined ? { ...patch, entry: mark(patch.entry) } : patch,\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nfunction isMissingFile(cause: unknown): boolean {\n\treturn typeof cause === \"object\" && cause !== null && \"code\" in cause && cause.code === \"ENOENT\";\n}\n\nasync function readOptionalComposition(filePath: string): Promise<CompositionDocument | undefined> {\n\ttry {\n\t\treturn await readCompositionFile(filePath);\n\t} catch (cause) {\n\t\tif (isMissingFile(cause)) return undefined;\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\tthrow new Error(`Failed to read composition ${filePath}: ${message}`, { cause });\n\t}\n}\n\nasync function readRequiredComposition(filePath: string): Promise<CompositionDocument> {\n\ttry {\n\t\treturn await readCompositionFile(filePath);\n\t} catch (cause) {\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\tthrow new Error(`Failed to read composition ${filePath}: ${message}`, { cause });\n\t}\n}\n\n/**\n * Resolves built-in, user, project, and explicit composition layers in their fixed precedence order.\n * Project entries are marked local so the Loader retains trust checks for entries added through project configuration.\n */\nexport async function resolveCompositionEntries(\n\tname: DefaultCompositionName,\n\toptions: CompositionResolutionOptions = {},\n): Promise<readonly CompositionEntry[]> {\n\tconst cwd = resolve(options.cwd ?? process.cwd());\n\tconst agentDir = resolve(options.agentDir ?? join(homedir(), \".di-code\"));\n\tconst [base, mode] = await Promise.all([\n\t\treadRequiredComposition(builtinCompositionPath(\"base\")),\n\t\treadRequiredComposition(builtinCompositionPath(name)),\n\t]);\n\tconst layers: CompositionLayer[] = [\n\t\t{ name: \"base\", document: base },\n\t\t{\n\t\t\tname: \"mode\",\n\t\t\tdocument: {\n\t\t\t\tentries: [...(mode.entries ?? []), ...(options.observability ? observabilityEntries : [])],\n\t\t\t},\n\t\t},\n\t];\n\tconst userComposition = await readOptionalComposition(join(agentDir, \"composition.yml\"));\n\tif (userComposition !== undefined) layers.push({ name: \"user\", document: userComposition });\n\tif (options.includeProjectComposition !== false) {\n\t\tconst projectComposition = await readOptionalComposition(join(cwd, \".di-code\", \"composition.yml\"));\n\t\tif (projectComposition !== undefined)\n\t\t\tlayers.push({ name: \"project\", document: markProjectEntries(projectComposition) });\n\t}\n\tif (options.compositionPath !== undefined) {\n\t\tlayers.push({ name: \"explicit\", document: await readRequiredComposition(resolve(cwd, options.compositionPath)) });\n\t}\n\treturn Object.freeze(withWorkspaceRoot(mergeCompositionLayers(layers), options.allowedRoot));\n}\n\n/**\n * Resolves only enabled managed plugins before the Loader receives its entry list.\n * Disabled manifests are not resolved or dynamically imported.\n */\nexport async function resolveManagedCompositionEntries(\n\tagentDir = join(homedir(), \".di-code\"),\n): Promise<readonly CompositionEntry[]> {\n\tconst manager = new PluginInstallManager({ managedRoot: join(resolve(agentDir), \"plugins\", \"installed\") });\n\tconst plugins = await manager.list();\n\treturn await Promise.all(\n\t\tplugins\n\t\t\t.filter((plugin) => plugin.enabled)\n\t\t\t.map(async (plugin) => ({\n\t\t\t\tid: `managed.${plugin.id}`,\n\t\t\t\tname: pathToFileURL(await resolvePackagePluginExport(plugin.installedPath, plugin.manifest.entry)).href,\n\t\t\t\tdependsOn: [\"Bootstrap\"],\n\t\t\t\trequired: false,\n\t\t\t})),\n\t);\n}\n\n/** Imports own composition entries from source in development; package exports handle published use. */\nexport function importCompositionModule(name: string): Promise<PluginModule> {\n\tswitch (name) {\n\t\tcase \"@di-code/coding-agent/plugin-manager\":\n\t\t\treturn import(\"./plugin-manager.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/plugin-inventory\":\n\t\t\treturn import(\"./plugin-inventory.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/plugin-trace\":\n\t\t\treturn import(\"./plugin-trace.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/plugin-dump-composition\":\n\t\t\treturn import(\"./plugin-dump-composition.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-config-entry\":\n\t\t\treturn import(\"./mcp-config-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-client-entry\":\n\t\t\treturn import(\"./mcp-client-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-transport-entry\":\n\t\t\treturn import(\"./mcp-transport-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-tools-entry\":\n\t\t\treturn import(\"./mcp-tools-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/mcp-command-entry\":\n\t\t\treturn import(\"./mcp-command-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/session-factory-entry\":\n\t\t\treturn import(\"./session-factory-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/session-store-jsonl-entry\":\n\t\t\treturn import(\"./session-store-jsonl-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/rpc-server-entry\":\n\t\t\treturn import(\"./rpc-server-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/interactive-resources-entry\":\n\t\t\treturn import(\"./interactive-resources-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/interactive-host-entry\":\n\t\t\treturn import(\"./interactive-host-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/runtime-core-entry\":\n\t\t\treturn import(\"./runtime-core-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/composition-loader-entry\":\n\t\t\treturn import(\"./composition-loader-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/project-trust-entry\":\n\t\t\treturn import(\"./project-trust-entry.ts\") as Promise<PluginModule>;\n\t\tcase \"@di-code/coding-agent/rpc-client-sdk-entry\":\n\t\t\treturn import(\"./rpc-client-sdk-entry.ts\") as Promise<PluginModule>;\n\t\tdefault:\n\t\t\treturn import(name) as Promise<PluginModule>;\n\t}\n}\n"]}
|
|
@@ -5,7 +5,7 @@ export declare const MAX_IMAGE_INPUT_BYTES: number;
|
|
|
5
5
|
export declare function imageContentFromBytes(data: Uint8Array, source: string): ImageContent;
|
|
6
6
|
/** Reads explicitly requested local image files into the provider-neutral user-message format. */
|
|
7
7
|
export declare function loadImageInputs(paths: readonly string[], cwd: string): Promise<ImageContent[]>;
|
|
8
|
-
/** Extracts @path references into
|
|
8
|
+
/** Extracts existing @path references into attachments; unrecognized references remain ordinary prompt text. */
|
|
9
9
|
export declare function extractImageAttachments(text: string, cwd: string): Promise<{
|
|
10
10
|
text: string;
|
|
11
11
|
images: ImageContent[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-input.d.ts","sourceRoot":"","sources":["../../src/core/image-input.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,qBAAqB,QAAkB,CAAC;AAwCrD,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAOpF;AAyDD,kGAAkG;AAClG,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAKpG;
|
|
1
|
+
{"version":3,"file":"image-input.d.ts","sourceRoot":"","sources":["../../src/core/image-input.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,qBAAqB,QAAkB,CAAC;AAwCrD,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAOpF;AAyDD,kGAAkG;AAClG,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAKpG;AAoBD,gHAAgH;AAChH,wBAAsB,uBAAuB,CAC5C,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACT,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,CAiCnD"}
|
package/dist/core/image-input.js
CHANGED
|
@@ -104,12 +104,21 @@ export async function loadImageInputs(paths, cwd) {
|
|
|
104
104
|
return Promise.all(paths.map((path) => loadImageInput(path, cwd)));
|
|
105
105
|
}
|
|
106
106
|
function isMissingFileError(cause) {
|
|
107
|
-
return cause instanceof Error && "code" in cause && cause.code === "ENOENT";
|
|
107
|
+
return cause instanceof Error && "code" in cause && (cause.code === "ENOENT" || cause.code === "ENOTDIR");
|
|
108
108
|
}
|
|
109
109
|
function isUnsupportedImageError(cause) {
|
|
110
110
|
return cause instanceof Error && cause.message.startsWith("Unsupported image format:");
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
function isUnrecognizedAttachmentError(cause) {
|
|
113
|
+
if (isMissingFileError(cause))
|
|
114
|
+
return true;
|
|
115
|
+
if (!(cause instanceof Error))
|
|
116
|
+
return false;
|
|
117
|
+
return (cause.message === "Path is outside the allowed root" ||
|
|
118
|
+
cause.message.startsWith("Image path is not a regular file:") ||
|
|
119
|
+
cause.message.startsWith("File attachment is not a regular file:"));
|
|
120
|
+
}
|
|
121
|
+
/** Extracts existing @path references into attachments; unrecognized references remain ordinary prompt text. */
|
|
113
122
|
export async function extractImageAttachments(text, cwd) {
|
|
114
123
|
const images = [];
|
|
115
124
|
const attachments = [];
|
|
@@ -134,8 +143,10 @@ export async function extractImageAttachments(text, cwd) {
|
|
|
134
143
|
attachments.push(`[Attached image: ${basename(path)}]`);
|
|
135
144
|
}
|
|
136
145
|
catch (cause) {
|
|
137
|
-
if (
|
|
138
|
-
|
|
146
|
+
if (isUnrecognizedAttachmentError(cause)) {
|
|
147
|
+
result += match[0].slice(leading.length);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
139
150
|
if (!isUnsupportedImageError(cause))
|
|
140
151
|
throw cause;
|
|
141
152
|
attachments.push(await loadTextAttachment(path, cwd));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-input.js","sourceRoot":"","sources":["../../src/core/image-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile, stat } from \"node:fs/promises\";\nimport { basename, isAbsolute, relative, resolve } from \"node:path\";\nimport type { ImageContent } from \"@di-code/ai\";\nimport { resolveAllowedFilePath } from \"./tools/path-boundary.ts\";\nimport { DEFAULT_READ_MAX_BYTES, DEFAULT_READ_MAX_LINES } from \"./tools/read.ts\";\n\nexport const MAX_IMAGE_INPUTS = 4;\nexport const MAX_IMAGE_INPUT_BYTES = 5 * 1024 * 1024;\n\nconst IMAGE_REFERENCE = /(^|\\s)@(?:\"([^\"\\r\\n]+)\"|'([^'\\r\\n]+)'|([^\\s@]+))/g;\n\nfunction detectImageMimeType(data: Uint8Array): ImageContent[\"mimeType\"] | undefined {\n\tif (\n\t\tdata.length >= 8 &&\n\t\tdata[0] === 137 &&\n\t\tdata[1] === 80 &&\n\t\tdata[2] === 78 &&\n\t\tdata[3] === 71 &&\n\t\tdata[4] === 13 &&\n\t\tdata[5] === 10 &&\n\t\tdata[6] === 26 &&\n\t\tdata[7] === 10\n\t) {\n\t\treturn \"image/png\";\n\t}\n\tif (data.length >= 3 && data[0] === 255 && data[1] === 216 && data[2] === 255) return \"image/jpeg\";\n\tif (\n\t\tdata.length >= 6 &&\n\t\t(Buffer.from(data.subarray(0, 6)).equals(Buffer.from(\"GIF87a\")) ||\n\t\t\tBuffer.from(data.subarray(0, 6)).equals(Buffer.from(\"GIF89a\")))\n\t) {\n\t\treturn \"image/gif\";\n\t}\n\tif (\n\t\tdata.length >= 12 &&\n\t\tBuffer.from(data.subarray(0, 4)).equals(Buffer.from(\"RIFF\")) &&\n\t\tBuffer.from(data.subarray(8, 12)).equals(Buffer.from(\"WEBP\"))\n\t) {\n\t\treturn \"image/webp\";\n\t}\n\treturn undefined;\n}\n\nfunction displayPath(path: string): string {\n\treturn path.trim() || \"<empty path>\";\n}\n\n/** Converts already-read bytes into validated provider-neutral image content. */\nexport function imageContentFromBytes(data: Uint8Array, source: string): ImageContent {\n\tif (data.byteLength > MAX_IMAGE_INPUT_BYTES) {\n\t\tthrow new Error(`Image exceeds the 5 MiB limit: ${displayPath(source)}`);\n\t}\n\tconst mimeType = detectImageMimeType(data);\n\tif (!mimeType) throw new Error(`Unsupported image format: ${displayPath(source)}`);\n\treturn { type: \"image\", data: Buffer.from(data).toString(\"base64\"), mimeType };\n}\n\nasync function loadImageInput(path: string, cwd: string): Promise<ImageContent> {\n\tif (path.trim().length === 0) throw new Error(\"Image path must not be empty.\");\n\tconst absolutePath = resolve(cwd, path);\n\tconst metadata = await stat(absolutePath);\n\tif (!metadata.isFile()) throw new Error(`Image path is not a regular file: ${displayPath(path)}`);\n\tif (metadata.size > MAX_IMAGE_INPUT_BYTES) {\n\t\tthrow new Error(`Image exceeds the 5 MiB limit: ${displayPath(path)}`);\n\t}\n\n\tconst data = await readFile(absolutePath);\n\tif (data.length > MAX_IMAGE_INPUT_BYTES) {\n\t\tthrow new Error(`Image exceeds the 5 MiB limit: ${displayPath(path)}`);\n\t}\n\treturn imageContentFromBytes(data, path);\n}\n\nfunction containsNulByte(data: Uint8Array): boolean {\n\tfor (const byte of data) if (byte === 0) return true;\n\treturn false;\n}\n\nfunction escapeFileName(path: string): string {\n\treturn path.replaceAll(\"&\", \"&\").replaceAll(\"<\", \"<\").replaceAll(\">\", \">\").replaceAll('\"', \""\");\n}\n\nfunction relativeAttachmentPath(path: string, cwd: string): string {\n\tconst absolutePath = resolve(cwd, path);\n\tconst relativePath = relative(resolve(cwd), absolutePath).replaceAll(\"\\\\\", \"/\");\n\treturn relativePath || basename(absolutePath);\n}\n\nasync function loadTextAttachment(path: string, cwd: string): Promise<string> {\n\tconst absolutePath = await resolveAllowedFilePath(path, cwd);\n\tconst metadata = await stat(absolutePath);\n\tif (!metadata.isFile()) throw new Error(`File attachment is not a regular file: ${displayPath(path)}`);\n\tif (metadata.size > DEFAULT_READ_MAX_BYTES) {\n\t\tthrow new Error(`Text attachment exceeds the 50 KiB limit: ${displayPath(path)}`);\n\t}\n\n\tconst data = await readFile(absolutePath);\n\tif (data.length > DEFAULT_READ_MAX_BYTES) {\n\t\tthrow new Error(`Text attachment exceeds the 50 KiB limit: ${displayPath(path)}`);\n\t}\n\tif (containsNulByte(data)) throw new Error(`Binary files are not supported by @ attachments: ${displayPath(path)}`);\n\n\tconst normalized = data.toString(\"utf8\").replace(/\\r\\n?/g, \"\\n\");\n\tconst lines = normalized.split(\"\\n\");\n\tconst content =\n\t\tlines.length > DEFAULT_READ_MAX_LINES\n\t\t\t? `${lines.slice(0, DEFAULT_READ_MAX_LINES).join(\"\\n\")}\\n\\n[File truncated after ${DEFAULT_READ_MAX_LINES} lines.]`\n\t\t\t: normalized;\n\tconst fileName = escapeFileName(relativeAttachmentPath(path, cwd));\n\treturn `<file name=\"${fileName}\">\\n${content}\\n</file>`;\n}\n\n/** Reads explicitly requested local image files into the provider-neutral user-message format. */\nexport async function loadImageInputs(paths: readonly string[], cwd: string): Promise<ImageContent[]> {\n\tif (paths.length > MAX_IMAGE_INPUTS) {\n\t\tthrow new Error(`At most ${MAX_IMAGE_INPUTS} images can be attached to one prompt.`);\n\t}\n\treturn Promise.all(paths.map((path) => loadImageInput(path, cwd)));\n}\n\nfunction isMissingFileError(cause: unknown): boolean {\n\treturn cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\";\n}\n\nfunction isUnsupportedImageError(cause: unknown): boolean {\n\treturn cause instanceof Error && cause.message.startsWith(\"Unsupported image format:\");\n}\n\n/** Extracts @path references into image attachments or bounded text blocks for the model prompt. */\nexport async function extractImageAttachments(\n\ttext: string,\n\tcwd: string,\n): Promise<{ text: string; images: ImageContent[] }> {\n\tconst images: ImageContent[] = [];\n\tconst attachments: string[] = [];\n\tlet result = \"\";\n\tlet cursor = 0;\n\n\tfor (const match of text.matchAll(IMAGE_REFERENCE)) {\n\t\tconst index = match.index ?? 0;\n\t\tconst leading = match[1] ?? \"\";\n\t\tconst path = match[2] ?? match[3] ?? match[4] ?? \"\";\n\t\tresult += `${text.slice(cursor, index)}${leading}`;\n\t\tcursor = index + match[0].length;\n\t\ttry {\n\t\t\tif (!isAbsolute(path)) await resolveAllowedFilePath(path, cwd);\n\t\t\tconst [image] = await loadImageInputs([path], cwd);\n\t\t\tif (!image) throw new Error(\"Image attachment was not loaded.\");\n\t\t\tif (images.length >= MAX_IMAGE_INPUTS) {\n\t\t\t\tthrow new Error(`At most ${MAX_IMAGE_INPUTS} images can be attached to one prompt.`);\n\t\t\t}\n\t\t\timages.push(image);\n\t\t\tattachments.push(`[Attached image: ${basename(path)}]`);\n\t\t} catch (cause) {\n\t\t\tif (isMissingFileError(cause)) throw new Error(`File attachment was not found: ${path}`);\n\t\t\tif (!isUnsupportedImageError(cause)) throw cause;\n\t\t\tattachments.push(await loadTextAttachment(path, cwd));\n\t\t}\n\t}\n\n\tconst prompt = `${result}${text.slice(cursor)}`.replace(/[ \\t]{2,}/g, \" \").trim();\n\treturn { text: [...attachments, prompt].filter((value) => value.length > 0).join(\"\\n\"), images };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"image-input.js","sourceRoot":"","sources":["../../src/core/image-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEjF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAClC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAErD,MAAM,eAAe,GAAG,mDAAmD,CAAC;AAE5E,SAAS,mBAAmB,CAAC,IAAgB;IAC5C,IACC,IAAI,CAAC,MAAM,IAAI,CAAC;QAChB,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;QACf,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;QACd,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;QACd,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;QACd,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;QACd,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;QACd,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;QACd,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,EACb,CAAC;QACF,OAAO,WAAW,CAAC;IACpB,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,YAAY,CAAC;IACnG,IACC,IAAI,CAAC,MAAM,IAAI,CAAC;QAChB,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAC/D,CAAC;QACF,OAAO,WAAW,CAAC;IACpB,CAAC;IACD,IACC,IAAI,CAAC,MAAM,IAAI,EAAE;QACjB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAC5D,CAAC;QACF,OAAO,YAAY,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,cAAc,CAAC;AACtC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,qBAAqB,CAAC,IAAgB,EAAE,MAAc;IACrE,IAAI,IAAI,CAAC,UAAU,GAAG,qBAAqB,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,kCAAkC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACnF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;AAChF,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,GAAW;IACtD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC/E,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClG,IAAI,QAAQ,CAAC,IAAI,GAAG,qBAAqB,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,kCAAkC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC1C,IAAI,IAAI,CAAC,MAAM,GAAG,qBAAqB,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,kCAAkC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,eAAe,CAAC,IAAgB;IACxC,KAAK,MAAM,IAAI,IAAI,IAAI;QAAE,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IACrD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAChH,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAY,EAAE,GAAW;IACxD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAChF,OAAO,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,IAAY,EAAE,GAAW;IAC1D,MAAM,YAAY,GAAG,MAAM,sBAAsB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvG,IAAI,QAAQ,CAAC,IAAI,GAAG,sBAAsB,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,6CAA6C,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC1C,IAAI,IAAI,CAAC,MAAM,GAAG,sBAAsB,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,6CAA6C,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;IACD,IAAI,eAAe,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEpH,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,OAAO,GACZ,KAAK,CAAC,MAAM,GAAG,sBAAsB;QACpC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,6BAA6B,sBAAsB,UAAU;QACnH,CAAC,CAAC,UAAU,CAAC;IACf,MAAM,QAAQ,GAAG,cAAc,CAAC,sBAAsB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACnE,OAAO,eAAe,QAAQ,OAAO,OAAO,WAAW,CAAC;AACzD,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAwB,EAAE,GAAW;IAC1E,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,WAAW,gBAAgB,wCAAwC,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;AAC3G,CAAC;AAED,SAAS,uBAAuB,CAAC,KAAc;IAC9C,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,2BAA2B,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,6BAA6B,CAAC,KAAc;IACpD,IAAI,kBAAkB,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,CACN,KAAK,CAAC,OAAO,KAAK,kCAAkC;QACpD,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,mCAAmC,CAAC;QAC7D,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,wCAAwC,CAAC,CAClE,CAAC;AACH,CAAC;AAED,gHAAgH;AAChH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC5C,IAAY,EACZ,GAAW;IAEX,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,OAAO,EAAE,CAAC;QACnD,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC;YACJ,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,MAAM,sBAAsB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/D,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;YACnD,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAChE,IAAI,MAAM,CAAC,MAAM,IAAI,gBAAgB,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CAAC,WAAW,gBAAgB,wCAAwC,CAAC,CAAC;YACtF,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,WAAW,CAAC,IAAI,CAAC,oBAAoB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,6BAA6B,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACzC,SAAS;YACV,CAAC;YACD,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YACjD,WAAW,CAAC,IAAI,CAAC,MAAM,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACvD,CAAC;IACF,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAClF,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,WAAW,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;AAClG,CAAC","sourcesContent":["import { readFile, stat } from \"node:fs/promises\";\nimport { basename, isAbsolute, relative, resolve } from \"node:path\";\nimport type { ImageContent } from \"@di-code/ai\";\nimport { resolveAllowedFilePath } from \"./tools/path-boundary.ts\";\nimport { DEFAULT_READ_MAX_BYTES, DEFAULT_READ_MAX_LINES } from \"./tools/read.ts\";\n\nexport const MAX_IMAGE_INPUTS = 4;\nexport const MAX_IMAGE_INPUT_BYTES = 5 * 1024 * 1024;\n\nconst IMAGE_REFERENCE = /(^|\\s)@(?:\"([^\"\\r\\n]+)\"|'([^'\\r\\n]+)'|([^\\s@]+))/g;\n\nfunction detectImageMimeType(data: Uint8Array): ImageContent[\"mimeType\"] | undefined {\n\tif (\n\t\tdata.length >= 8 &&\n\t\tdata[0] === 137 &&\n\t\tdata[1] === 80 &&\n\t\tdata[2] === 78 &&\n\t\tdata[3] === 71 &&\n\t\tdata[4] === 13 &&\n\t\tdata[5] === 10 &&\n\t\tdata[6] === 26 &&\n\t\tdata[7] === 10\n\t) {\n\t\treturn \"image/png\";\n\t}\n\tif (data.length >= 3 && data[0] === 255 && data[1] === 216 && data[2] === 255) return \"image/jpeg\";\n\tif (\n\t\tdata.length >= 6 &&\n\t\t(Buffer.from(data.subarray(0, 6)).equals(Buffer.from(\"GIF87a\")) ||\n\t\t\tBuffer.from(data.subarray(0, 6)).equals(Buffer.from(\"GIF89a\")))\n\t) {\n\t\treturn \"image/gif\";\n\t}\n\tif (\n\t\tdata.length >= 12 &&\n\t\tBuffer.from(data.subarray(0, 4)).equals(Buffer.from(\"RIFF\")) &&\n\t\tBuffer.from(data.subarray(8, 12)).equals(Buffer.from(\"WEBP\"))\n\t) {\n\t\treturn \"image/webp\";\n\t}\n\treturn undefined;\n}\n\nfunction displayPath(path: string): string {\n\treturn path.trim() || \"<empty path>\";\n}\n\n/** Converts already-read bytes into validated provider-neutral image content. */\nexport function imageContentFromBytes(data: Uint8Array, source: string): ImageContent {\n\tif (data.byteLength > MAX_IMAGE_INPUT_BYTES) {\n\t\tthrow new Error(`Image exceeds the 5 MiB limit: ${displayPath(source)}`);\n\t}\n\tconst mimeType = detectImageMimeType(data);\n\tif (!mimeType) throw new Error(`Unsupported image format: ${displayPath(source)}`);\n\treturn { type: \"image\", data: Buffer.from(data).toString(\"base64\"), mimeType };\n}\n\nasync function loadImageInput(path: string, cwd: string): Promise<ImageContent> {\n\tif (path.trim().length === 0) throw new Error(\"Image path must not be empty.\");\n\tconst absolutePath = resolve(cwd, path);\n\tconst metadata = await stat(absolutePath);\n\tif (!metadata.isFile()) throw new Error(`Image path is not a regular file: ${displayPath(path)}`);\n\tif (metadata.size > MAX_IMAGE_INPUT_BYTES) {\n\t\tthrow new Error(`Image exceeds the 5 MiB limit: ${displayPath(path)}`);\n\t}\n\n\tconst data = await readFile(absolutePath);\n\tif (data.length > MAX_IMAGE_INPUT_BYTES) {\n\t\tthrow new Error(`Image exceeds the 5 MiB limit: ${displayPath(path)}`);\n\t}\n\treturn imageContentFromBytes(data, path);\n}\n\nfunction containsNulByte(data: Uint8Array): boolean {\n\tfor (const byte of data) if (byte === 0) return true;\n\treturn false;\n}\n\nfunction escapeFileName(path: string): string {\n\treturn path.replaceAll(\"&\", \"&\").replaceAll(\"<\", \"<\").replaceAll(\">\", \">\").replaceAll('\"', \""\");\n}\n\nfunction relativeAttachmentPath(path: string, cwd: string): string {\n\tconst absolutePath = resolve(cwd, path);\n\tconst relativePath = relative(resolve(cwd), absolutePath).replaceAll(\"\\\\\", \"/\");\n\treturn relativePath || basename(absolutePath);\n}\n\nasync function loadTextAttachment(path: string, cwd: string): Promise<string> {\n\tconst absolutePath = await resolveAllowedFilePath(path, cwd);\n\tconst metadata = await stat(absolutePath);\n\tif (!metadata.isFile()) throw new Error(`File attachment is not a regular file: ${displayPath(path)}`);\n\tif (metadata.size > DEFAULT_READ_MAX_BYTES) {\n\t\tthrow new Error(`Text attachment exceeds the 50 KiB limit: ${displayPath(path)}`);\n\t}\n\n\tconst data = await readFile(absolutePath);\n\tif (data.length > DEFAULT_READ_MAX_BYTES) {\n\t\tthrow new Error(`Text attachment exceeds the 50 KiB limit: ${displayPath(path)}`);\n\t}\n\tif (containsNulByte(data)) throw new Error(`Binary files are not supported by @ attachments: ${displayPath(path)}`);\n\n\tconst normalized = data.toString(\"utf8\").replace(/\\r\\n?/g, \"\\n\");\n\tconst lines = normalized.split(\"\\n\");\n\tconst content =\n\t\tlines.length > DEFAULT_READ_MAX_LINES\n\t\t\t? `${lines.slice(0, DEFAULT_READ_MAX_LINES).join(\"\\n\")}\\n\\n[File truncated after ${DEFAULT_READ_MAX_LINES} lines.]`\n\t\t\t: normalized;\n\tconst fileName = escapeFileName(relativeAttachmentPath(path, cwd));\n\treturn `<file name=\"${fileName}\">\\n${content}\\n</file>`;\n}\n\n/** Reads explicitly requested local image files into the provider-neutral user-message format. */\nexport async function loadImageInputs(paths: readonly string[], cwd: string): Promise<ImageContent[]> {\n\tif (paths.length > MAX_IMAGE_INPUTS) {\n\t\tthrow new Error(`At most ${MAX_IMAGE_INPUTS} images can be attached to one prompt.`);\n\t}\n\treturn Promise.all(paths.map((path) => loadImageInput(path, cwd)));\n}\n\nfunction isMissingFileError(cause: unknown): boolean {\n\treturn cause instanceof Error && \"code\" in cause && (cause.code === \"ENOENT\" || cause.code === \"ENOTDIR\");\n}\n\nfunction isUnsupportedImageError(cause: unknown): boolean {\n\treturn cause instanceof Error && cause.message.startsWith(\"Unsupported image format:\");\n}\n\nfunction isUnrecognizedAttachmentError(cause: unknown): boolean {\n\tif (isMissingFileError(cause)) return true;\n\tif (!(cause instanceof Error)) return false;\n\treturn (\n\t\tcause.message === \"Path is outside the allowed root\" ||\n\t\tcause.message.startsWith(\"Image path is not a regular file:\") ||\n\t\tcause.message.startsWith(\"File attachment is not a regular file:\")\n\t);\n}\n\n/** Extracts existing @path references into attachments; unrecognized references remain ordinary prompt text. */\nexport async function extractImageAttachments(\n\ttext: string,\n\tcwd: string,\n): Promise<{ text: string; images: ImageContent[] }> {\n\tconst images: ImageContent[] = [];\n\tconst attachments: string[] = [];\n\tlet result = \"\";\n\tlet cursor = 0;\n\n\tfor (const match of text.matchAll(IMAGE_REFERENCE)) {\n\t\tconst index = match.index ?? 0;\n\t\tconst leading = match[1] ?? \"\";\n\t\tconst path = match[2] ?? match[3] ?? match[4] ?? \"\";\n\t\tresult += `${text.slice(cursor, index)}${leading}`;\n\t\tcursor = index + match[0].length;\n\t\ttry {\n\t\t\tif (!isAbsolute(path)) await resolveAllowedFilePath(path, cwd);\n\t\t\tconst [image] = await loadImageInputs([path], cwd);\n\t\t\tif (!image) throw new Error(\"Image attachment was not loaded.\");\n\t\t\tif (images.length >= MAX_IMAGE_INPUTS) {\n\t\t\t\tthrow new Error(`At most ${MAX_IMAGE_INPUTS} images can be attached to one prompt.`);\n\t\t\t}\n\t\t\timages.push(image);\n\t\t\tattachments.push(`[Attached image: ${basename(path)}]`);\n\t\t} catch (cause) {\n\t\t\tif (isUnrecognizedAttachmentError(cause)) {\n\t\t\t\tresult += match[0].slice(leading.length);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!isUnsupportedImageError(cause)) throw cause;\n\t\t\tattachments.push(await loadTextAttachment(path, cwd));\n\t\t}\n\t}\n\n\tconst prompt = `${result}${text.slice(cursor)}`.replace(/[ \\t]{2,}/g, \" \").trim();\n\treturn { text: [...attachments, prompt].filter((value) => value.length > 0).join(\"\\n\"), images };\n}\n"]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { JsonValue, Message } from "@di-code/ai";
|
|
2
|
+
import type { SessionEventRegistry, SessionProjectionRegistry } from "@di-code/plugin-sdk";
|
|
2
3
|
import { type BuiltSessionContext } from "../context-builder.ts";
|
|
3
4
|
import { type SessionAppendOptions } from "./session-storage.ts";
|
|
4
|
-
import { type SessionDiagnostic, type SessionEntry, type SessionHeader, type SessionMessageEntry, type SessionPluginEntry, type SessionSummaryEntry, type SessionTreeNode } from "./types.ts";
|
|
5
|
+
import { type SessionDiagnostic, type SessionEntry, type SessionEventEntry, type SessionHeader, type SessionMessageEntry, type SessionPluginEntry, type SessionSummaryEntry, type SessionTreeNode } from "./types.ts";
|
|
5
6
|
export interface SessionManagerCreateOptions {
|
|
6
7
|
readonly filePath: string;
|
|
7
8
|
readonly cwd: string;
|
|
@@ -9,11 +10,13 @@ export interface SessionManagerCreateOptions {
|
|
|
9
10
|
readonly createId?: () => string;
|
|
10
11
|
readonly appendOptions?: SessionAppendOptions;
|
|
11
12
|
readonly deferCreate?: boolean;
|
|
13
|
+
readonly eventRegistry?: SessionEventRegistry;
|
|
12
14
|
}
|
|
13
15
|
export interface SessionManagerOpenOptions {
|
|
14
16
|
readonly now?: () => number;
|
|
15
17
|
readonly createId?: () => string;
|
|
16
18
|
readonly appendOptions?: SessionAppendOptions;
|
|
19
|
+
readonly eventRegistry?: SessionEventRegistry;
|
|
17
20
|
}
|
|
18
21
|
export declare class SessionManager {
|
|
19
22
|
readonly filePath: string;
|
|
@@ -21,6 +24,7 @@ export declare class SessionManager {
|
|
|
21
24
|
private readonly now;
|
|
22
25
|
private readonly createId;
|
|
23
26
|
private readonly appendOptions;
|
|
27
|
+
private eventRegistry?;
|
|
24
28
|
private readonly sessionEntries;
|
|
25
29
|
private readonly entriesById;
|
|
26
30
|
private readonly childrenByParentId;
|
|
@@ -34,6 +38,9 @@ export declare class SessionManager {
|
|
|
34
38
|
get entries(): readonly SessionEntry[];
|
|
35
39
|
get header(): SessionHeader;
|
|
36
40
|
get messages(): readonly Message[];
|
|
41
|
+
get events(): readonly SessionEventEntry[];
|
|
42
|
+
/** Cold-reads the complete durable event log; no in-memory mirror is used as the source of truth. */
|
|
43
|
+
project(registry: SessionProjectionRegistry): readonly unknown[];
|
|
37
44
|
getEntry(id: string): SessionEntry | undefined;
|
|
38
45
|
getTree(): readonly SessionTreeNode[];
|
|
39
46
|
getBranch(leafId?: string): readonly SessionEntry[];
|
|
@@ -42,6 +49,8 @@ export declare class SessionManager {
|
|
|
42
49
|
buildContext(leafId?: string): BuiltSessionContext;
|
|
43
50
|
get latestSummary(): SessionSummaryEntry | undefined;
|
|
44
51
|
get diagnostics(): readonly SessionDiagnostic[];
|
|
52
|
+
/** Binds the active plugin registry and diagnoses already-loaded extension events. */
|
|
53
|
+
bindEventRegistry(registry: SessionEventRegistry): void;
|
|
45
54
|
get leafId(): string;
|
|
46
55
|
private ensureFileCreated;
|
|
47
56
|
appendMessage(message: Message): Promise<SessionMessageEntry>;
|
|
@@ -57,6 +66,14 @@ export declare class SessionManager {
|
|
|
57
66
|
readonly schemaVersion: number;
|
|
58
67
|
readonly data: JsonValue;
|
|
59
68
|
}): Promise<SessionPluginEntry>;
|
|
69
|
+
/** Appends a versioned plugin event through the same queue and file lock as messages. */
|
|
70
|
+
appendEvent(input: {
|
|
71
|
+
readonly namespace: string;
|
|
72
|
+
readonly eventName: string;
|
|
73
|
+
readonly schemaVersion: number;
|
|
74
|
+
readonly payload: JsonValue;
|
|
75
|
+
readonly signal?: AbortSignal;
|
|
76
|
+
}): Promise<SessionEventEntry>;
|
|
60
77
|
private addToIndexes;
|
|
61
78
|
}
|
|
62
79
|
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../../src/core/session/session-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,KAAK,mBAAmB,EAAuB,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAIN,KAAK,oBAAoB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGN,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,oBAAoB,CAAC;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../../src/core/session/session-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,6 +21,7 @@ export class SessionManager {
|
|
|
21
21
|
now;
|
|
22
22
|
createId;
|
|
23
23
|
appendOptions;
|
|
24
|
+
eventRegistry;
|
|
24
25
|
sessionEntries;
|
|
25
26
|
entriesById = new Map();
|
|
26
27
|
childrenByParentId = new Map();
|
|
@@ -39,6 +40,7 @@ export class SessionManager {
|
|
|
39
40
|
this.now = options.now ?? Date.now;
|
|
40
41
|
this.createId = options.createId ?? randomUUID;
|
|
41
42
|
this.appendOptions = options.appendOptions ?? {};
|
|
43
|
+
this.eventRegistry = options.eventRegistry;
|
|
42
44
|
this.fileCreated = fileCreated;
|
|
43
45
|
}
|
|
44
46
|
static async create(options) {
|
|
@@ -58,7 +60,7 @@ export class SessionManager {
|
|
|
58
60
|
};
|
|
59
61
|
if (!options.deferCreate)
|
|
60
62
|
await createSessionFile(filePath, header);
|
|
61
|
-
return new SessionManager(filePath, { header, entries: [], messages: [], diagnostics: [] }, { now, createId, appendOptions: options.appendOptions }, !options.deferCreate);
|
|
63
|
+
return new SessionManager(filePath, { header, entries: [], messages: [], diagnostics: [] }, { now, createId, appendOptions: options.appendOptions, eventRegistry: options.eventRegistry }, !options.deferCreate);
|
|
62
64
|
}
|
|
63
65
|
static async open(filePath, options = {}) {
|
|
64
66
|
const resolvedPath = resolve(filePath);
|
|
@@ -75,6 +77,18 @@ export class SessionManager {
|
|
|
75
77
|
.filter((entry) => entry.type === "message")
|
|
76
78
|
.map((entry) => entry.message));
|
|
77
79
|
}
|
|
80
|
+
get events() {
|
|
81
|
+
return structuredClone(this.sessionEntries.filter((entry) => entry.type === "event"));
|
|
82
|
+
}
|
|
83
|
+
/** Cold-reads the complete durable event log; no in-memory mirror is used as the source of truth. */
|
|
84
|
+
project(registry) {
|
|
85
|
+
return registry.replay(this.events.map((event) => ({
|
|
86
|
+
namespace: event.namespace,
|
|
87
|
+
eventName: event.eventName,
|
|
88
|
+
schemaVersion: event.schemaVersion,
|
|
89
|
+
payload: event.payload,
|
|
90
|
+
})));
|
|
91
|
+
}
|
|
78
92
|
getEntry(id) {
|
|
79
93
|
const entry = this.entriesById.get(id);
|
|
80
94
|
return entry ? structuredClone(entry) : undefined;
|
|
@@ -132,6 +146,32 @@ export class SessionManager {
|
|
|
132
146
|
get diagnostics() {
|
|
133
147
|
return structuredClone(this.sessionDiagnostics);
|
|
134
148
|
}
|
|
149
|
+
/** Binds the active plugin registry and diagnoses already-loaded extension events. */
|
|
150
|
+
bindEventRegistry(registry) {
|
|
151
|
+
this.eventRegistry = registry;
|
|
152
|
+
for (let index = this.sessionDiagnostics.length - 1; index >= 0; index--)
|
|
153
|
+
if (this.sessionDiagnostics[index]?.kind === "event_validation")
|
|
154
|
+
this.sessionDiagnostics.splice(index, 1);
|
|
155
|
+
for (const event of this.events) {
|
|
156
|
+
try {
|
|
157
|
+
registry.migrate({
|
|
158
|
+
namespace: event.namespace,
|
|
159
|
+
eventName: event.eventName,
|
|
160
|
+
schemaVersion: event.schemaVersion,
|
|
161
|
+
payload: event.payload,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
this.sessionDiagnostics.push({
|
|
166
|
+
kind: "event_validation",
|
|
167
|
+
namespace: event.namespace,
|
|
168
|
+
eventName: event.eventName,
|
|
169
|
+
schemaVersion: event.schemaVersion,
|
|
170
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
135
175
|
get leafId() {
|
|
136
176
|
return this.activeLeafId;
|
|
137
177
|
}
|
|
@@ -219,6 +259,55 @@ export class SessionManager {
|
|
|
219
259
|
this.appendQueue = operation.then(() => undefined, () => undefined);
|
|
220
260
|
return operation;
|
|
221
261
|
}
|
|
262
|
+
/** Appends a versioned plugin event through the same queue and file lock as messages. */
|
|
263
|
+
appendEvent(input) {
|
|
264
|
+
const inputSnapshot = {
|
|
265
|
+
namespace: input.namespace,
|
|
266
|
+
eventName: input.eventName,
|
|
267
|
+
schemaVersion: input.schemaVersion,
|
|
268
|
+
payload: structuredClone(input.payload),
|
|
269
|
+
signal: input.signal,
|
|
270
|
+
};
|
|
271
|
+
const validated = this.eventRegistry?.migrate({
|
|
272
|
+
namespace: inputSnapshot.namespace,
|
|
273
|
+
eventName: inputSnapshot.eventName,
|
|
274
|
+
schemaVersion: inputSnapshot.schemaVersion,
|
|
275
|
+
payload: inputSnapshot.payload,
|
|
276
|
+
});
|
|
277
|
+
if (validated) {
|
|
278
|
+
inputSnapshot.schemaVersion = validated.schemaVersion;
|
|
279
|
+
inputSnapshot.payload = validated.payload;
|
|
280
|
+
}
|
|
281
|
+
const operation = this.appendQueue.then(async () => {
|
|
282
|
+
if (inputSnapshot.signal?.aborted)
|
|
283
|
+
throw inputSnapshot.signal.reason ?? new DOMException("The operation was aborted", "AbortError");
|
|
284
|
+
await this.ensureFileCreated();
|
|
285
|
+
const id = this.createId();
|
|
286
|
+
assertRecordId(id);
|
|
287
|
+
const expectedParentId = this.leafId;
|
|
288
|
+
const entry = {
|
|
289
|
+
type: "event",
|
|
290
|
+
version: SESSION_FORMAT_VERSION,
|
|
291
|
+
id,
|
|
292
|
+
parentId: expectedParentId,
|
|
293
|
+
timestamp: createIsoTimestamp(this.now),
|
|
294
|
+
namespace: inputSnapshot.namespace,
|
|
295
|
+
eventName: inputSnapshot.eventName,
|
|
296
|
+
schemaVersion: inputSnapshot.schemaVersion,
|
|
297
|
+
payload: inputSnapshot.payload,
|
|
298
|
+
};
|
|
299
|
+
await appendSessionEntry(this.filePath, entry, expectedParentId, {
|
|
300
|
+
...this.appendOptions,
|
|
301
|
+
signal: inputSnapshot.signal,
|
|
302
|
+
});
|
|
303
|
+
this.sessionEntries.push(structuredClone(entry));
|
|
304
|
+
this.addToIndexes(entry);
|
|
305
|
+
this.activeLeafId = entry.id;
|
|
306
|
+
return structuredClone(entry);
|
|
307
|
+
});
|
|
308
|
+
this.appendQueue = operation.then(() => undefined, () => undefined);
|
|
309
|
+
return operation;
|
|
310
|
+
}
|
|
222
311
|
addToIndexes(entry) {
|
|
223
312
|
this.entriesById.set(entry.id, structuredClone(entry));
|
|
224
313
|
const children = this.childrenByParentId.get(entry.parentId) ?? [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../../src/core/session/session-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport type { JsonValue, Message } from \"@di-code/ai\";\nimport { type BuiltSessionContext, buildSessionContext } from \"../context-builder.ts\";\nimport {\n\tappendSessionEntry,\n\tcreateSessionFile,\n\tloadSessionFile,\n\ttype SessionAppendOptions,\n} from \"./session-storage.ts\";\nimport {\n\ttype LoadedSession,\n\tSESSION_FORMAT_VERSION,\n\ttype SessionDiagnostic,\n\ttype SessionEntry,\n\ttype SessionHeader,\n\ttype SessionMessageEntry,\n\ttype SessionPluginEntry,\n\ttype SessionSummaryEntry,\n\ttype SessionTreeNode,\n} from \"./types.ts\";\n\nexport interface SessionManagerCreateOptions {\n\treadonly filePath: string;\n\treadonly cwd: string;\n\treadonly now?: () => number;\n\treadonly createId?: () => string;\n\treadonly appendOptions?: SessionAppendOptions;\n\treadonly deferCreate?: boolean;\n}\n\nexport interface SessionManagerOpenOptions {\n\treadonly now?: () => number;\n\treadonly createId?: () => string;\n\treadonly appendOptions?: SessionAppendOptions;\n}\n\nfunction assertRecordId(id: string): void {\n\tif (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {\n\t\tthrow new Error(`Generated session record id is invalid: ${JSON.stringify(id)}.`);\n\t}\n}\n\nfunction createIsoTimestamp(now: () => number): string {\n\tconst milliseconds = now();\n\tif (!Number.isFinite(milliseconds)) {\n\t\tthrow new Error(\"Session clock must return a finite Unix millisecond timestamp.\");\n\t}\n\treturn new Date(milliseconds).toISOString();\n}\n\nexport class SessionManager {\n\treadonly filePath: string;\n\tprivate readonly sessionHeader: SessionHeader;\n\tprivate readonly now: () => number;\n\tprivate readonly createId: () => string;\n\tprivate readonly appendOptions: SessionAppendOptions;\n\tprivate readonly sessionEntries: SessionEntry[];\n\tprivate readonly entriesById = new Map<string, SessionEntry>();\n\tprivate readonly childrenByParentId = new Map<string, string[]>();\n\tprivate readonly sessionDiagnostics: SessionDiagnostic[];\n\tprivate activeLeafId: string;\n\tprivate fileCreated: boolean;\n\tprivate appendQueue: Promise<void> = Promise.resolve();\n\n\tprivate constructor(filePath: string, loaded: LoadedSession, options: SessionManagerOpenOptions, fileCreated = true) {\n\t\tthis.filePath = filePath;\n\t\tthis.sessionHeader = structuredClone(loaded.header);\n\t\tthis.sessionEntries = structuredClone([...loaded.entries]);\n\t\tfor (const entry of this.sessionEntries) this.addToIndexes(entry);\n\t\tthis.activeLeafId = this.sessionEntries.at(-1)?.id ?? this.sessionHeader.id;\n\t\tthis.sessionDiagnostics = structuredClone([...loaded.diagnostics]);\n\t\tthis.now = options.now ?? Date.now;\n\t\tthis.createId = options.createId ?? randomUUID;\n\t\tthis.appendOptions = options.appendOptions ?? {};\n\t\tthis.fileCreated = fileCreated;\n\t}\n\n\tstatic async create(options: SessionManagerCreateOptions): Promise<SessionManager> {\n\t\tconst filePath = resolve(options.filePath);\n\t\tconst cwd = resolve(options.cwd);\n\t\tconst now = options.now ?? Date.now;\n\t\tconst createId = options.createId ?? randomUUID;\n\t\tconst id = createId();\n\t\tassertRecordId(id);\n\t\tconst header: SessionHeader = {\n\t\t\ttype: \"session\",\n\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\tid,\n\t\t\tparentId: null,\n\t\t\ttimestamp: createIsoTimestamp(now),\n\t\t\tcwd,\n\t\t};\n\t\tif (!options.deferCreate) await createSessionFile(filePath, header);\n\t\treturn new SessionManager(\n\t\t\tfilePath,\n\t\t\t{ header, entries: [], messages: [], diagnostics: [] },\n\t\t\t{ now, createId, appendOptions: options.appendOptions },\n\t\t\t!options.deferCreate,\n\t\t);\n\t}\n\n\tstatic async open(filePath: string, options: SessionManagerOpenOptions = {}): Promise<SessionManager> {\n\t\tconst resolvedPath = resolve(filePath);\n\t\treturn new SessionManager(resolvedPath, await loadSessionFile(resolvedPath), options);\n\t}\n\n\tget entries(): readonly SessionEntry[] {\n\t\treturn structuredClone(this.sessionEntries);\n\t}\n\n\tget header(): SessionHeader {\n\t\treturn structuredClone(this.sessionHeader);\n\t}\n\n\tget messages(): readonly Message[] {\n\t\treturn structuredClone(\n\t\t\tthis.sessionEntries\n\t\t\t\t.filter((entry): entry is SessionMessageEntry => entry.type === \"message\")\n\t\t\t\t.map((entry) => entry.message),\n\t\t);\n\t}\n\n\tgetEntry(id: string): SessionEntry | undefined {\n\t\tconst entry = this.entriesById.get(id);\n\t\treturn entry ? structuredClone(entry) : undefined;\n\t}\n\n\tgetTree(): readonly SessionTreeNode[] {\n\t\tconst nodes = new Map<string, { entry: SessionEntry; children: SessionTreeNode[] }>();\n\t\tconst roots: SessionTreeNode[] = [];\n\t\tfor (const entry of this.sessionEntries) {\n\t\t\tconst node = { entry: structuredClone(entry), children: [] as SessionTreeNode[] };\n\t\t\tnodes.set(entry.id, node);\n\t\t\tif (entry.parentId === this.sessionHeader.id) {\n\t\t\t\troots.push(node);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst parent = nodes.get(entry.parentId);\n\t\t\tif (!parent) throw new Error(`Session tree parent \"${entry.parentId}\" is missing.`);\n\t\t\tparent.children.push(node);\n\t\t}\n\t\treturn roots;\n\t}\n\n\tgetBranch(leafId = this.activeLeafId): readonly SessionEntry[] {\n\t\tconst branch: SessionEntry[] = [];\n\t\tlet currentId = leafId;\n\t\twhile (currentId !== this.sessionHeader.id) {\n\t\t\tconst entry = this.entriesById.get(currentId);\n\t\t\tif (!entry) throw new Error(`Unknown session leaf \"${currentId}\".`);\n\t\t\tbranch.push(structuredClone(entry));\n\t\t\tcurrentId = entry.parentId;\n\t\t}\n\t\tbranch.reverse();\n\t\treturn branch;\n\t}\n\n\tsetLeaf(id: string): void {\n\t\tif (id !== this.sessionHeader.id && !this.entriesById.has(id)) throw new Error(`Unknown session leaf \"${id}\".`);\n\t\tthis.activeLeafId = id;\n\t}\n\n\tresetLeaf(): void {\n\t\tthis.activeLeafId = this.sessionEntries.at(-1)?.id ?? this.sessionHeader.id;\n\t}\n\n\tbuildContext(leafId = this.activeLeafId): BuiltSessionContext {\n\t\treturn buildSessionContext(this.getBranch(leafId));\n\t}\n\n\tget latestSummary(): SessionSummaryEntry | undefined {\n\t\tconst branch = this.getBranch();\n\t\tfor (let index = branch.length - 1; index >= 0; index--) {\n\t\t\tconst entry = branch[index];\n\t\t\tif (entry?.type === \"summary\") return structuredClone(entry);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tget diagnostics(): readonly SessionDiagnostic[] {\n\t\treturn structuredClone(this.sessionDiagnostics);\n\t}\n\n\tget leafId(): string {\n\t\treturn this.activeLeafId;\n\t}\n\n\tprivate async ensureFileCreated(): Promise<void> {\n\t\tif (this.fileCreated) return;\n\t\tawait createSessionFile(this.filePath, this.sessionHeader);\n\t\tthis.fileCreated = true;\n\t}\n\n\tappendMessage(message: Message): Promise<SessionMessageEntry> {\n\t\tconst messageSnapshot = structuredClone(message);\n\t\tconst operation = this.appendQueue.then(async () => {\n\t\t\tawait this.ensureFileCreated();\n\t\t\tconst id = this.createId();\n\t\t\tassertRecordId(id);\n\t\t\tconst expectedParentId = this.leafId;\n\t\t\tconst entry: SessionMessageEntry = {\n\t\t\t\ttype: \"message\",\n\t\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\t\tid,\n\t\t\t\tparentId: expectedParentId,\n\t\t\t\ttimestamp: createIsoTimestamp(this.now),\n\t\t\t\tmessage: messageSnapshot,\n\t\t\t};\n\t\t\tawait appendSessionEntry(this.filePath, entry, expectedParentId, this.appendOptions);\n\t\t\tthis.sessionEntries.push(structuredClone(entry));\n\t\t\tthis.addToIndexes(entry);\n\t\t\tthis.activeLeafId = entry.id;\n\t\t\treturn structuredClone(entry);\n\t\t});\n\n\t\tthis.appendQueue = operation.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn operation;\n\t}\n\n\tappendSummary(input: {\n\t\treadonly summary: string;\n\t\treadonly firstKeptEntryId: string;\n\t\treadonly tokensBefore: number;\n\t}): Promise<SessionSummaryEntry> {\n\t\tconst inputSnapshot = structuredClone(input);\n\t\tconst operation = this.appendQueue.then(async () => {\n\t\t\tawait this.ensureFileCreated();\n\t\t\tconst id = this.createId();\n\t\t\tassertRecordId(id);\n\t\t\tconst expectedParentId = this.leafId;\n\t\t\tconst entry: SessionSummaryEntry = {\n\t\t\t\ttype: \"summary\",\n\t\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\t\tid,\n\t\t\t\tparentId: expectedParentId,\n\t\t\t\ttimestamp: createIsoTimestamp(this.now),\n\t\t\t\tsummary: inputSnapshot.summary,\n\t\t\t\tfirstKeptEntryId: inputSnapshot.firstKeptEntryId,\n\t\t\t\ttokensBefore: inputSnapshot.tokensBefore,\n\t\t\t};\n\t\t\tawait appendSessionEntry(this.filePath, entry, expectedParentId, this.appendOptions);\n\t\t\tthis.sessionEntries.push(structuredClone(entry));\n\t\t\tthis.addToIndexes(entry);\n\t\t\tthis.activeLeafId = entry.id;\n\t\t\treturn structuredClone(entry);\n\t\t});\n\n\t\tthis.appendQueue = operation.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn operation;\n\t}\n\n\t/** Appends host-owned metadata without exposing it as a transcript message. */\n\tappendPlugin(input: {\n\t\treadonly pluginId: string;\n\t\treadonly pluginVersion: string;\n\t\treadonly schemaVersion: number;\n\t\treadonly data: JsonValue;\n\t}): Promise<SessionPluginEntry> {\n\t\tconst inputSnapshot = structuredClone(input);\n\t\tconst operation = this.appendQueue.then(async () => {\n\t\t\tawait this.ensureFileCreated();\n\t\t\tconst id = this.createId();\n\t\t\tassertRecordId(id);\n\t\t\tconst expectedParentId = this.leafId;\n\t\t\tconst entry: SessionPluginEntry = {\n\t\t\t\ttype: \"plugin\",\n\t\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\t\tid,\n\t\t\t\tparentId: expectedParentId,\n\t\t\t\ttimestamp: createIsoTimestamp(this.now),\n\t\t\t\tpluginId: inputSnapshot.pluginId,\n\t\t\t\tpluginVersion: inputSnapshot.pluginVersion,\n\t\t\t\tschemaVersion: inputSnapshot.schemaVersion,\n\t\t\t\tdata: inputSnapshot.data,\n\t\t\t};\n\t\t\tawait appendSessionEntry(this.filePath, entry, expectedParentId, this.appendOptions);\n\t\t\tthis.sessionEntries.push(structuredClone(entry));\n\t\t\tthis.addToIndexes(entry);\n\t\t\tthis.activeLeafId = entry.id;\n\t\t\treturn structuredClone(entry);\n\t\t});\n\n\t\tthis.appendQueue = operation.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn operation;\n\t}\n\n\tprivate addToIndexes(entry: SessionEntry): void {\n\t\tthis.entriesById.set(entry.id, structuredClone(entry));\n\t\tconst children = this.childrenByParentId.get(entry.parentId) ?? [];\n\t\tchildren.push(entry.id);\n\t\tthis.childrenByParentId.set(entry.parentId, children);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../../src/core/session/session-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { resolve } from \"node:path\";\nimport type { JsonValue, Message } from \"@di-code/ai\";\nimport type { SessionEventRegistry, SessionProjectionRegistry } from \"@di-code/plugin-sdk\";\nimport { type BuiltSessionContext, buildSessionContext } from \"../context-builder.ts\";\nimport {\n\tappendSessionEntry,\n\tcreateSessionFile,\n\tloadSessionFile,\n\ttype SessionAppendOptions,\n} from \"./session-storage.ts\";\nimport {\n\ttype LoadedSession,\n\tSESSION_FORMAT_VERSION,\n\ttype SessionDiagnostic,\n\ttype SessionEntry,\n\ttype SessionEventEntry,\n\ttype SessionHeader,\n\ttype SessionMessageEntry,\n\ttype SessionPluginEntry,\n\ttype SessionSummaryEntry,\n\ttype SessionTreeNode,\n} from \"./types.ts\";\n\nexport interface SessionManagerCreateOptions {\n\treadonly filePath: string;\n\treadonly cwd: string;\n\treadonly now?: () => number;\n\treadonly createId?: () => string;\n\treadonly appendOptions?: SessionAppendOptions;\n\treadonly deferCreate?: boolean;\n\treadonly eventRegistry?: SessionEventRegistry;\n}\n\nexport interface SessionManagerOpenOptions {\n\treadonly now?: () => number;\n\treadonly createId?: () => string;\n\treadonly appendOptions?: SessionAppendOptions;\n\treadonly eventRegistry?: SessionEventRegistry;\n}\n\nfunction assertRecordId(id: string): void {\n\tif (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {\n\t\tthrow new Error(`Generated session record id is invalid: ${JSON.stringify(id)}.`);\n\t}\n}\n\nfunction createIsoTimestamp(now: () => number): string {\n\tconst milliseconds = now();\n\tif (!Number.isFinite(milliseconds)) {\n\t\tthrow new Error(\"Session clock must return a finite Unix millisecond timestamp.\");\n\t}\n\treturn new Date(milliseconds).toISOString();\n}\n\nexport class SessionManager {\n\treadonly filePath: string;\n\tprivate readonly sessionHeader: SessionHeader;\n\tprivate readonly now: () => number;\n\tprivate readonly createId: () => string;\n\tprivate readonly appendOptions: SessionAppendOptions;\n\tprivate eventRegistry?: SessionEventRegistry;\n\tprivate readonly sessionEntries: SessionEntry[];\n\tprivate readonly entriesById = new Map<string, SessionEntry>();\n\tprivate readonly childrenByParentId = new Map<string, string[]>();\n\tprivate readonly sessionDiagnostics: SessionDiagnostic[];\n\tprivate activeLeafId: string;\n\tprivate fileCreated: boolean;\n\tprivate appendQueue: Promise<void> = Promise.resolve();\n\n\tprivate constructor(filePath: string, loaded: LoadedSession, options: SessionManagerOpenOptions, fileCreated = true) {\n\t\tthis.filePath = filePath;\n\t\tthis.sessionHeader = structuredClone(loaded.header);\n\t\tthis.sessionEntries = structuredClone([...loaded.entries]);\n\t\tfor (const entry of this.sessionEntries) this.addToIndexes(entry);\n\t\tthis.activeLeafId = this.sessionEntries.at(-1)?.id ?? this.sessionHeader.id;\n\t\tthis.sessionDiagnostics = structuredClone([...loaded.diagnostics]);\n\t\tthis.now = options.now ?? Date.now;\n\t\tthis.createId = options.createId ?? randomUUID;\n\t\tthis.appendOptions = options.appendOptions ?? {};\n\t\tthis.eventRegistry = options.eventRegistry;\n\t\tthis.fileCreated = fileCreated;\n\t}\n\n\tstatic async create(options: SessionManagerCreateOptions): Promise<SessionManager> {\n\t\tconst filePath = resolve(options.filePath);\n\t\tconst cwd = resolve(options.cwd);\n\t\tconst now = options.now ?? Date.now;\n\t\tconst createId = options.createId ?? randomUUID;\n\t\tconst id = createId();\n\t\tassertRecordId(id);\n\t\tconst header: SessionHeader = {\n\t\t\ttype: \"session\",\n\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\tid,\n\t\t\tparentId: null,\n\t\t\ttimestamp: createIsoTimestamp(now),\n\t\t\tcwd,\n\t\t};\n\t\tif (!options.deferCreate) await createSessionFile(filePath, header);\n\t\treturn new SessionManager(\n\t\t\tfilePath,\n\t\t\t{ header, entries: [], messages: [], diagnostics: [] },\n\t\t\t{ now, createId, appendOptions: options.appendOptions, eventRegistry: options.eventRegistry },\n\t\t\t!options.deferCreate,\n\t\t);\n\t}\n\n\tstatic async open(filePath: string, options: SessionManagerOpenOptions = {}): Promise<SessionManager> {\n\t\tconst resolvedPath = resolve(filePath);\n\t\treturn new SessionManager(resolvedPath, await loadSessionFile(resolvedPath), options);\n\t}\n\n\tget entries(): readonly SessionEntry[] {\n\t\treturn structuredClone(this.sessionEntries);\n\t}\n\n\tget header(): SessionHeader {\n\t\treturn structuredClone(this.sessionHeader);\n\t}\n\n\tget messages(): readonly Message[] {\n\t\treturn structuredClone(\n\t\t\tthis.sessionEntries\n\t\t\t\t.filter((entry): entry is SessionMessageEntry => entry.type === \"message\")\n\t\t\t\t.map((entry) => entry.message),\n\t\t);\n\t}\n\n\tget events(): readonly SessionEventEntry[] {\n\t\treturn structuredClone(this.sessionEntries.filter((entry): entry is SessionEventEntry => entry.type === \"event\"));\n\t}\n\n\t/** Cold-reads the complete durable event log; no in-memory mirror is used as the source of truth. */\n\tproject(registry: SessionProjectionRegistry): readonly unknown[] {\n\t\treturn registry.replay(\n\t\t\tthis.events.map((event) => ({\n\t\t\t\tnamespace: event.namespace,\n\t\t\t\teventName: event.eventName,\n\t\t\t\tschemaVersion: event.schemaVersion,\n\t\t\t\tpayload: event.payload,\n\t\t\t})),\n\t\t);\n\t}\n\n\tgetEntry(id: string): SessionEntry | undefined {\n\t\tconst entry = this.entriesById.get(id);\n\t\treturn entry ? structuredClone(entry) : undefined;\n\t}\n\n\tgetTree(): readonly SessionTreeNode[] {\n\t\tconst nodes = new Map<string, { entry: SessionEntry; children: SessionTreeNode[] }>();\n\t\tconst roots: SessionTreeNode[] = [];\n\t\tfor (const entry of this.sessionEntries) {\n\t\t\tconst node = { entry: structuredClone(entry), children: [] as SessionTreeNode[] };\n\t\t\tnodes.set(entry.id, node);\n\t\t\tif (entry.parentId === this.sessionHeader.id) {\n\t\t\t\troots.push(node);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst parent = nodes.get(entry.parentId);\n\t\t\tif (!parent) throw new Error(`Session tree parent \"${entry.parentId}\" is missing.`);\n\t\t\tparent.children.push(node);\n\t\t}\n\t\treturn roots;\n\t}\n\n\tgetBranch(leafId = this.activeLeafId): readonly SessionEntry[] {\n\t\tconst branch: SessionEntry[] = [];\n\t\tlet currentId = leafId;\n\t\twhile (currentId !== this.sessionHeader.id) {\n\t\t\tconst entry = this.entriesById.get(currentId);\n\t\t\tif (!entry) throw new Error(`Unknown session leaf \"${currentId}\".`);\n\t\t\tbranch.push(structuredClone(entry));\n\t\t\tcurrentId = entry.parentId;\n\t\t}\n\t\tbranch.reverse();\n\t\treturn branch;\n\t}\n\n\tsetLeaf(id: string): void {\n\t\tif (id !== this.sessionHeader.id && !this.entriesById.has(id)) throw new Error(`Unknown session leaf \"${id}\".`);\n\t\tthis.activeLeafId = id;\n\t}\n\n\tresetLeaf(): void {\n\t\tthis.activeLeafId = this.sessionEntries.at(-1)?.id ?? this.sessionHeader.id;\n\t}\n\n\tbuildContext(leafId = this.activeLeafId): BuiltSessionContext {\n\t\treturn buildSessionContext(this.getBranch(leafId));\n\t}\n\n\tget latestSummary(): SessionSummaryEntry | undefined {\n\t\tconst branch = this.getBranch();\n\t\tfor (let index = branch.length - 1; index >= 0; index--) {\n\t\t\tconst entry = branch[index];\n\t\t\tif (entry?.type === \"summary\") return structuredClone(entry);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tget diagnostics(): readonly SessionDiagnostic[] {\n\t\treturn structuredClone(this.sessionDiagnostics);\n\t}\n\n\t/** Binds the active plugin registry and diagnoses already-loaded extension events. */\n\tbindEventRegistry(registry: SessionEventRegistry): void {\n\t\tthis.eventRegistry = registry;\n\t\tfor (let index = this.sessionDiagnostics.length - 1; index >= 0; index--)\n\t\t\tif (this.sessionDiagnostics[index]?.kind === \"event_validation\") this.sessionDiagnostics.splice(index, 1);\n\t\tfor (const event of this.events) {\n\t\t\ttry {\n\t\t\t\tregistry.migrate({\n\t\t\t\t\tnamespace: event.namespace,\n\t\t\t\t\teventName: event.eventName,\n\t\t\t\t\tschemaVersion: event.schemaVersion,\n\t\t\t\t\tpayload: event.payload,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tthis.sessionDiagnostics.push({\n\t\t\t\t\tkind: \"event_validation\",\n\t\t\t\t\tnamespace: event.namespace,\n\t\t\t\t\teventName: event.eventName,\n\t\t\t\t\tschemaVersion: event.schemaVersion,\n\t\t\t\t\treason: error instanceof Error ? error.message : String(error),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tget leafId(): string {\n\t\treturn this.activeLeafId;\n\t}\n\n\tprivate async ensureFileCreated(): Promise<void> {\n\t\tif (this.fileCreated) return;\n\t\tawait createSessionFile(this.filePath, this.sessionHeader);\n\t\tthis.fileCreated = true;\n\t}\n\n\tappendMessage(message: Message): Promise<SessionMessageEntry> {\n\t\tconst messageSnapshot = structuredClone(message);\n\t\tconst operation = this.appendQueue.then(async () => {\n\t\t\tawait this.ensureFileCreated();\n\t\t\tconst id = this.createId();\n\t\t\tassertRecordId(id);\n\t\t\tconst expectedParentId = this.leafId;\n\t\t\tconst entry: SessionMessageEntry = {\n\t\t\t\ttype: \"message\",\n\t\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\t\tid,\n\t\t\t\tparentId: expectedParentId,\n\t\t\t\ttimestamp: createIsoTimestamp(this.now),\n\t\t\t\tmessage: messageSnapshot,\n\t\t\t};\n\t\t\tawait appendSessionEntry(this.filePath, entry, expectedParentId, this.appendOptions);\n\t\t\tthis.sessionEntries.push(structuredClone(entry));\n\t\t\tthis.addToIndexes(entry);\n\t\t\tthis.activeLeafId = entry.id;\n\t\t\treturn structuredClone(entry);\n\t\t});\n\n\t\tthis.appendQueue = operation.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn operation;\n\t}\n\n\tappendSummary(input: {\n\t\treadonly summary: string;\n\t\treadonly firstKeptEntryId: string;\n\t\treadonly tokensBefore: number;\n\t}): Promise<SessionSummaryEntry> {\n\t\tconst inputSnapshot = structuredClone(input);\n\t\tconst operation = this.appendQueue.then(async () => {\n\t\t\tawait this.ensureFileCreated();\n\t\t\tconst id = this.createId();\n\t\t\tassertRecordId(id);\n\t\t\tconst expectedParentId = this.leafId;\n\t\t\tconst entry: SessionSummaryEntry = {\n\t\t\t\ttype: \"summary\",\n\t\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\t\tid,\n\t\t\t\tparentId: expectedParentId,\n\t\t\t\ttimestamp: createIsoTimestamp(this.now),\n\t\t\t\tsummary: inputSnapshot.summary,\n\t\t\t\tfirstKeptEntryId: inputSnapshot.firstKeptEntryId,\n\t\t\t\ttokensBefore: inputSnapshot.tokensBefore,\n\t\t\t};\n\t\t\tawait appendSessionEntry(this.filePath, entry, expectedParentId, this.appendOptions);\n\t\t\tthis.sessionEntries.push(structuredClone(entry));\n\t\t\tthis.addToIndexes(entry);\n\t\t\tthis.activeLeafId = entry.id;\n\t\t\treturn structuredClone(entry);\n\t\t});\n\n\t\tthis.appendQueue = operation.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn operation;\n\t}\n\n\t/** Appends host-owned metadata without exposing it as a transcript message. */\n\tappendPlugin(input: {\n\t\treadonly pluginId: string;\n\t\treadonly pluginVersion: string;\n\t\treadonly schemaVersion: number;\n\t\treadonly data: JsonValue;\n\t}): Promise<SessionPluginEntry> {\n\t\tconst inputSnapshot = structuredClone(input);\n\t\tconst operation = this.appendQueue.then(async () => {\n\t\t\tawait this.ensureFileCreated();\n\t\t\tconst id = this.createId();\n\t\t\tassertRecordId(id);\n\t\t\tconst expectedParentId = this.leafId;\n\t\t\tconst entry: SessionPluginEntry = {\n\t\t\t\ttype: \"plugin\",\n\t\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\t\tid,\n\t\t\t\tparentId: expectedParentId,\n\t\t\t\ttimestamp: createIsoTimestamp(this.now),\n\t\t\t\tpluginId: inputSnapshot.pluginId,\n\t\t\t\tpluginVersion: inputSnapshot.pluginVersion,\n\t\t\t\tschemaVersion: inputSnapshot.schemaVersion,\n\t\t\t\tdata: inputSnapshot.data,\n\t\t\t};\n\t\t\tawait appendSessionEntry(this.filePath, entry, expectedParentId, this.appendOptions);\n\t\t\tthis.sessionEntries.push(structuredClone(entry));\n\t\t\tthis.addToIndexes(entry);\n\t\t\tthis.activeLeafId = entry.id;\n\t\t\treturn structuredClone(entry);\n\t\t});\n\n\t\tthis.appendQueue = operation.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn operation;\n\t}\n\n\t/** Appends a versioned plugin event through the same queue and file lock as messages. */\n\tappendEvent(input: {\n\t\treadonly namespace: string;\n\t\treadonly eventName: string;\n\t\treadonly schemaVersion: number;\n\t\treadonly payload: JsonValue;\n\t\treadonly signal?: AbortSignal;\n\t}): Promise<SessionEventEntry> {\n\t\tconst inputSnapshot = {\n\t\t\tnamespace: input.namespace,\n\t\t\teventName: input.eventName,\n\t\t\tschemaVersion: input.schemaVersion,\n\t\t\tpayload: structuredClone(input.payload),\n\t\t\tsignal: input.signal,\n\t\t};\n\t\tconst validated = this.eventRegistry?.migrate({\n\t\t\tnamespace: inputSnapshot.namespace,\n\t\t\teventName: inputSnapshot.eventName,\n\t\t\tschemaVersion: inputSnapshot.schemaVersion,\n\t\t\tpayload: inputSnapshot.payload,\n\t\t});\n\t\tif (validated) {\n\t\t\tinputSnapshot.schemaVersion = validated.schemaVersion;\n\t\t\tinputSnapshot.payload = validated.payload;\n\t\t}\n\t\tconst operation = this.appendQueue.then(async () => {\n\t\t\tif (inputSnapshot.signal?.aborted)\n\t\t\t\tthrow inputSnapshot.signal.reason ?? new DOMException(\"The operation was aborted\", \"AbortError\");\n\t\t\tawait this.ensureFileCreated();\n\t\t\tconst id = this.createId();\n\t\t\tassertRecordId(id);\n\t\t\tconst expectedParentId = this.leafId;\n\t\t\tconst entry: SessionEventEntry = {\n\t\t\t\ttype: \"event\",\n\t\t\t\tversion: SESSION_FORMAT_VERSION,\n\t\t\t\tid,\n\t\t\t\tparentId: expectedParentId,\n\t\t\t\ttimestamp: createIsoTimestamp(this.now),\n\t\t\t\tnamespace: inputSnapshot.namespace,\n\t\t\t\teventName: inputSnapshot.eventName,\n\t\t\t\tschemaVersion: inputSnapshot.schemaVersion,\n\t\t\t\tpayload: inputSnapshot.payload,\n\t\t\t};\n\t\t\tawait appendSessionEntry(this.filePath, entry, expectedParentId, {\n\t\t\t\t...this.appendOptions,\n\t\t\t\tsignal: inputSnapshot.signal,\n\t\t\t});\n\t\t\tthis.sessionEntries.push(structuredClone(entry));\n\t\t\tthis.addToIndexes(entry);\n\t\t\tthis.activeLeafId = entry.id;\n\t\t\treturn structuredClone(entry);\n\t\t});\n\t\tthis.appendQueue = operation.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn operation;\n\t}\n\n\tprivate addToIndexes(entry: SessionEntry): void {\n\t\tthis.entriesById.set(entry.id, structuredClone(entry));\n\t\tconst children = this.childrenByParentId.get(entry.parentId) ?? [];\n\t\tchildren.push(entry.id);\n\t\tthis.childrenByParentId.set(entry.parentId, children);\n\t}\n}\n"]}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type LoadedSession, type SessionEntry, type SessionHeader } from "./types.ts";
|
|
2
|
+
export declare const MAX_SESSION_EVENT_PAYLOAD_BYTES: number;
|
|
2
3
|
export declare function loadSessionFile(filePath: string): Promise<LoadedSession>;
|
|
3
4
|
export interface SessionAppendOptions {
|
|
4
5
|
readonly lockTimeoutMs?: number;
|
|
5
6
|
readonly lockRetryMs?: number;
|
|
6
7
|
readonly now?: () => number;
|
|
7
8
|
readonly sleep?: (milliseconds: number) => Promise<void>;
|
|
9
|
+
readonly signal?: AbortSignal;
|
|
8
10
|
}
|
|
9
11
|
export declare function createSessionFile(filePath: string, header: SessionHeader): Promise<void>;
|
|
10
12
|
export declare function appendSessionEntry(filePath: string, entry: SessionEntry, expectedParentId: string, options?: SessionAppendOptions): Promise<void>;
|