@di-code/coding-agent 0.1.3 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -30
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +96 -17
- package/dist/cli.js.map +1 -1
- package/dist/core/clipboard-image.d.ts +3 -3
- package/dist/core/clipboard-image.d.ts.map +1 -1
- package/dist/core/clipboard-image.js +26 -13
- package/dist/core/clipboard-image.js.map +1 -1
- package/dist/core/context-builder.d.ts.map +1 -1
- package/dist/core/context-builder.js +6 -2
- package/dist/core/context-builder.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 +55 -10
- package/dist/core/image-input.js.map +1 -1
- package/dist/core/resources/loader.d.ts.map +1 -1
- package/dist/core/resources/loader.js +15 -42
- package/dist/core/resources/loader.js.map +1 -1
- package/dist/core/resources/types.d.ts +6 -9
- package/dist/core/resources/types.d.ts.map +1 -1
- package/dist/core/resources/types.js.map +1 -1
- package/dist/core/session/session-manager.d.ts +12 -1
- package/dist/core/session/session-manager.d.ts.map +1 -1
- package/dist/core/session/session-manager.js +66 -3
- package/dist/core/session/session-manager.js.map +1 -1
- package/dist/core/session/session-storage.d.ts.map +1 -1
- package/dist/core/session/session-storage.js +30 -15
- package/dist/core/session/session-storage.js.map +1 -1
- package/dist/core/session/types.d.ts +6 -1
- package/dist/core/session/types.d.ts.map +1 -1
- package/dist/core/session/types.js +1 -1
- package/dist/core/session/types.js.map +1 -1
- package/dist/core/session.d.ts +38 -3
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +167 -9
- package/dist/core/session.js.map +1 -1
- package/dist/core/system-prompt.js +2 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -2
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +25 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +136 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +13 -4
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +64 -30
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-search.d.ts +14 -0
- package/dist/core/tools/file-search.d.ts.map +1 -0
- package/dist/core/tools/file-search.js +99 -0
- package/dist/core/tools/file-search.js.map +1 -0
- package/dist/core/tools/glob.d.ts +11 -0
- package/dist/core/tools/glob.d.ts.map +1 -0
- package/dist/core/tools/glob.js +44 -0
- package/dist/core/tools/glob.js.map +1 -0
- package/dist/core/tools/grep.d.ts +13 -0
- package/dist/core/tools/grep.d.ts.map +1 -0
- package/dist/core/tools/grep.js +67 -0
- package/dist/core/tools/grep.js.map +1 -0
- package/dist/core/tools/load-skill.d.ts +10 -0
- package/dist/core/tools/load-skill.d.ts.map +1 -0
- package/dist/core/tools/load-skill.js +22 -0
- package/dist/core/tools/load-skill.js.map +1 -0
- package/dist/core/tools/path-boundary.d.ts +2 -0
- package/dist/core/tools/path-boundary.d.ts.map +1 -1
- package/dist/core/tools/path-boundary.js +4 -0
- package/dist/core/tools/path-boundary.js.map +1 -1
- package/dist/core/tools/read.d.ts +2 -2
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts +2 -2
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/user-data.d.ts +3 -0
- package/dist/core/user-data.d.ts.map +1 -0
- package/dist/core/user-data.js +8 -0
- package/dist/core/user-data.js.map +1 -0
- package/dist/entry.js +22 -2
- package/dist/entry.js.map +1 -1
- package/dist/extensions/runtime.js +2 -2
- package/dist/extensions/runtime.js.map +1 -1
- package/dist/i18n.d.ts +5 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +223 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +20 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +272 -17
- package/dist/main.js.map +1 -1
- package/dist/mcp/config.d.ts +33 -0
- package/dist/mcp/config.d.ts.map +1 -0
- package/dist/mcp/config.js +211 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/loader.d.ts +21 -0
- package/dist/mcp/loader.d.ts.map +1 -0
- package/dist/mcp/loader.js +60 -0
- package/dist/mcp/loader.js.map +1 -0
- package/dist/mcp/tool-adapter.d.ts +5 -0
- package/dist/mcp/tool-adapter.d.ts.map +1 -0
- package/dist/mcp/tool-adapter.js +149 -0
- package/dist/mcp/tool-adapter.js.map +1 -0
- package/dist/modes/interactive-components.d.ts +2 -0
- package/dist/modes/interactive-components.d.ts.map +1 -1
- package/dist/modes/interactive-components.js +55 -31
- package/dist/modes/interactive-components.js.map +1 -1
- package/dist/modes/interactive-diff.d.ts +8 -0
- package/dist/modes/interactive-diff.d.ts.map +1 -0
- package/dist/modes/interactive-diff.js +78 -0
- package/dist/modes/interactive-diff.js.map +1 -0
- package/dist/modes/interactive-layout.d.ts +4 -0
- package/dist/modes/interactive-layout.d.ts.map +1 -1
- package/dist/modes/interactive-layout.js +4 -0
- package/dist/modes/interactive-layout.js.map +1 -1
- package/dist/modes/interactive-state.d.ts +5 -0
- package/dist/modes/interactive-state.d.ts.map +1 -1
- package/dist/modes/interactive-state.js +65 -11
- package/dist/modes/interactive-state.js.map +1 -1
- package/dist/modes/interactive.d.ts +19 -0
- package/dist/modes/interactive.d.ts.map +1 -1
- package/dist/modes/interactive.js +351 -52
- package/dist/modes/interactive.js.map +1 -1
- package/dist/modes/tree-selector.d.ts +30 -0
- package/dist/modes/tree-selector.d.ts.map +1 -0
- package/dist/modes/tree-selector.js +205 -0
- package/dist/modes/tree-selector.js.map +1 -0
- package/dist/plugins/loader.d.ts +19 -1
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +21 -2
- package/dist/plugins/loader.js.map +1 -1
- package/dist/provider-onboarding.d.ts +8 -1
- package/dist/provider-onboarding.d.ts.map +1 -1
- package/dist/provider-onboarding.js +160 -40
- package/dist/provider-onboarding.js.map +1 -1
- package/dist/rpc-entry.js +1 -1
- package/dist/rpc-entry.js.map +1 -1
- package/dist/startup.d.ts +34 -3
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +407 -87
- package/dist/startup.js.map +1 -1
- package/package.json +7 -4
|
@@ -4,6 +4,7 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { basename, dirname, join, resolve } from "node:path";
|
|
6
6
|
import { imageContentFromBytes } from "./image-input.js";
|
|
7
|
+
import { workspaceStorageKey } from "./user-data.js";
|
|
7
8
|
const CLIPBOARD_FILE_PREFIX = "di-code-clipboard-";
|
|
8
9
|
const CLIPBOARD_FILE_PATTERN = new RegExp(`^${CLIPBOARD_FILE_PREFIX}[0-9a-f-]+\\.(?:png|jpg|jpeg|gif|webp)$`, "i");
|
|
9
10
|
const DEFAULT_STALE_AGE_MS = 24 * 60 * 60 * 1000;
|
|
@@ -38,19 +39,19 @@ function extensionForMimeType(mimeType) {
|
|
|
38
39
|
return "png";
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
|
-
export function clipboardImageDirectory(root) {
|
|
42
|
-
return join(
|
|
42
|
+
export function clipboardImageDirectory(agentDir, root) {
|
|
43
|
+
return join(agentDir, "clipboard", workspaceStorageKey(root), String(process.pid));
|
|
43
44
|
}
|
|
44
45
|
export function isClipboardImagePath(path, directory) {
|
|
45
46
|
const absolutePath = resolve(path);
|
|
46
47
|
return dirname(absolutePath) === resolve(directory) && CLIPBOARD_FILE_PATTERN.test(basename(absolutePath));
|
|
47
48
|
}
|
|
48
|
-
/** Removes generated clipboard images that were left by
|
|
49
|
-
export async function cleanupStaleClipboardImages(root, maxAgeMs = DEFAULT_STALE_AGE_MS) {
|
|
50
|
-
const
|
|
51
|
-
let
|
|
49
|
+
/** Removes generated clipboard images that were left by older processes for this workspace. */
|
|
50
|
+
export async function cleanupStaleClipboardImages(agentDir, root, maxAgeMs = DEFAULT_STALE_AGE_MS) {
|
|
51
|
+
const workspaceDirectory = join(agentDir, "clipboard", workspaceStorageKey(root));
|
|
52
|
+
let processDirectories;
|
|
52
53
|
try {
|
|
53
|
-
|
|
54
|
+
processDirectories = await readdir(workspaceDirectory, { withFileTypes: true });
|
|
54
55
|
}
|
|
55
56
|
catch (cause) {
|
|
56
57
|
if (cause instanceof Error && "code" in cause && cause.code === "ENOENT")
|
|
@@ -58,13 +59,25 @@ export async function cleanupStaleClipboardImages(root, maxAgeMs = DEFAULT_STALE
|
|
|
58
59
|
throw cause;
|
|
59
60
|
}
|
|
60
61
|
const cutoff = Date.now() - maxAgeMs;
|
|
61
|
-
await Promise.all(
|
|
62
|
-
.filter((entry) => entry.
|
|
63
|
-
.map(async (
|
|
64
|
-
const
|
|
62
|
+
await Promise.all(processDirectories
|
|
63
|
+
.filter((entry) => entry.isDirectory())
|
|
64
|
+
.map(async (processDirectory) => {
|
|
65
|
+
const directory = join(workspaceDirectory, processDirectory.name);
|
|
65
66
|
try {
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
68
|
+
await Promise.all(entries
|
|
69
|
+
.filter((entry) => entry.isFile() && CLIPBOARD_FILE_PATTERN.test(entry.name))
|
|
70
|
+
.map(async (entry) => {
|
|
71
|
+
const path = join(directory, entry.name);
|
|
72
|
+
try {
|
|
73
|
+
if ((await stat(path)).mtimeMs < cutoff)
|
|
74
|
+
await unlink(path);
|
|
75
|
+
}
|
|
76
|
+
catch (cause) {
|
|
77
|
+
if (!(cause instanceof Error && "code" in cause && cause.code === "ENOENT"))
|
|
78
|
+
throw cause;
|
|
79
|
+
}
|
|
80
|
+
}));
|
|
68
81
|
}
|
|
69
82
|
catch (cause) {
|
|
70
83
|
if (!(cause instanceof Error && "code" in cause && cause.code === "ENOENT"))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard-image.js","sourceRoot":"","sources":["../../src/core/clipboard-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"clipboard-image.js","sourceRoot":"","sources":["../../src/core/clipboard-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAOrD,MAAM,qBAAqB,GAAG,oBAAoB,CAAC;AACnD,MAAM,sBAAsB,GAAG,IAAI,MAAM,CAAC,IAAI,qBAAqB,yCAAyC,EAAE,GAAG,CAAC,CAAC;AACnH,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEjD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,SAAS,mBAAmB;IAC3B,IAAI,CAAC;QACJ,OAAO,OAAO,CAAC,yBAAyB,CAAoB,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACvC,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IACxC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,cAAc,EAAE,CAAC;IAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,qBAAqB,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAgB;IAC7C,QAAQ,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,KAAK,YAAY;YAChB,OAAO,KAAK,CAAC;QACd,KAAK,WAAW;YACf,OAAO,KAAK,CAAC;QACd,KAAK,YAAY;YAChB,OAAO,MAAM,CAAC;QACf;YACC,OAAO,KAAK,CAAC;IACf,CAAC;AACF,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,QAAgB,EAAE,IAAY;IACrE,OAAO,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,SAAiB;IACnE,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,OAAO,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC,SAAS,CAAC,IAAI,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;AAC5G,CAAC;AAED,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAChD,QAAgB,EAChB,IAAY,EACZ,QAAQ,GAAG,oBAAoB;IAE/B,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,IAAI,kBAA4B,CAAC;IACjC,IAAI,CAAC;QACJ,kBAAkB,GAAG,MAAM,OAAO,CAAC,kBAAkB,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACjF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO;QACjF,MAAM,KAAK,CAAC;IACb,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;IACrC,MAAM,OAAO,CAAC,GAAG,CAChB,kBAAkB;SAChB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;SACtC,GAAG,CAAC,KAAK,EAAE,gBAAgB,EAAE,EAAE;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAClE,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAClE,MAAM,OAAO,CAAC,GAAG,CAChB,OAAO;iBACL,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;iBAC5E,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACpB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACzC,IAAI,CAAC;oBACJ,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,GAAG,MAAM;wBAAE,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;gBAC7D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;wBAAE,MAAM,KAAK,CAAC;gBAC1F,CAAC;YACF,CAAC,CAAC,CACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;gBAAE,MAAM,KAAK,CAAC;QAC1F,CAAC;IACF,CAAC,CAAC,CACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAY,EAAE,SAAiB;IACzE,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC;QAAE,OAAO;IACnD,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;YAAE,MAAM,KAAK,CAAC;IAC1F,CAAC;AACF,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAAmB,EAAE,SAAS,GAAG,MAAM,EAAE;IAC1F,MAAM,SAAS,GAAG,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,qBAAqB,GAAG,UAAU,EAAE,IAAI,SAAS,EAAE,CAAC,CAAC;IACrF,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,SAAS,GAAG,MAAM,EAAE;IAChE,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;IACzC,OAAO,KAAK,CAAC,CAAC,CAAC,2BAA2B,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACrE,CAAC","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { Dirent } from \"node:fs\";\nimport { mkdir, readdir, stat, unlink, writeFile } from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport type { ImageContent } from \"@di-code/ai\";\nimport { imageContentFromBytes } from \"./image-input.ts\";\nimport { workspaceStorageKey } from \"./user-data.ts\";\n\ninterface ClipboardModule {\n\thasImage(): boolean;\n\tgetImageBinary(): Promise<Uint8Array | readonly number[]>;\n}\n\nconst CLIPBOARD_FILE_PREFIX = \"di-code-clipboard-\";\nconst CLIPBOARD_FILE_PATTERN = new RegExp(`^${CLIPBOARD_FILE_PREFIX}[0-9a-f-]+\\\\.(?:png|jpg|jpeg|gif|webp)$`, \"i\");\nconst DEFAULT_STALE_AGE_MS = 24 * 60 * 60 * 1000;\n\nconst require = createRequire(import.meta.url);\n\nfunction loadClipboardModule(): ClipboardModule | undefined {\n\ttry {\n\t\treturn require(\"@mariozechner/clipboard\") as ClipboardModule;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** Reads a native clipboard image when the optional platform package is available. */\nexport async function readClipboardImage(): Promise<ImageContent | null> {\n\tconst clipboard = loadClipboardModule();\n\tif (!clipboard?.hasImage()) return null;\n\tconst bytes = await clipboard.getImageBinary();\n\tif (bytes.length === 0) return null;\n\treturn imageContentFromBytes(Uint8Array.from(bytes), \"clipboard image\");\n}\n\nfunction extensionForMimeType(mimeType: string): string {\n\tswitch (mimeType.toLowerCase().split(\";\", 1)[0]) {\n\t\tcase \"image/jpeg\":\n\t\t\treturn \"jpg\";\n\t\tcase \"image/gif\":\n\t\t\treturn \"gif\";\n\t\tcase \"image/webp\":\n\t\t\treturn \"webp\";\n\t\tdefault:\n\t\t\treturn \"png\";\n\t}\n}\n\nexport function clipboardImageDirectory(agentDir: string, root: string): string {\n\treturn join(agentDir, \"clipboard\", workspaceStorageKey(root), String(process.pid));\n}\n\nexport function isClipboardImagePath(path: string, directory: string): boolean {\n\tconst absolutePath = resolve(path);\n\treturn dirname(absolutePath) === resolve(directory) && CLIPBOARD_FILE_PATTERN.test(basename(absolutePath));\n}\n\n/** Removes generated clipboard images that were left by older processes for this workspace. */\nexport async function cleanupStaleClipboardImages(\n\tagentDir: string,\n\troot: string,\n\tmaxAgeMs = DEFAULT_STALE_AGE_MS,\n): Promise<void> {\n\tconst workspaceDirectory = join(agentDir, \"clipboard\", workspaceStorageKey(root));\n\tlet processDirectories: Dirent[];\n\ttry {\n\t\tprocessDirectories = await readdir(workspaceDirectory, { withFileTypes: true });\n\t} catch (cause) {\n\t\tif (cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\") return;\n\t\tthrow cause;\n\t}\n\tconst cutoff = Date.now() - maxAgeMs;\n\tawait Promise.all(\n\t\tprocessDirectories\n\t\t\t.filter((entry) => entry.isDirectory())\n\t\t\t.map(async (processDirectory) => {\n\t\t\t\tconst directory = join(workspaceDirectory, processDirectory.name);\n\t\t\t\ttry {\n\t\t\t\t\tconst entries = await readdir(directory, { withFileTypes: true });\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tentries\n\t\t\t\t\t\t\t.filter((entry) => entry.isFile() && CLIPBOARD_FILE_PATTERN.test(entry.name))\n\t\t\t\t\t\t\t.map(async (entry) => {\n\t\t\t\t\t\t\t\tconst path = join(directory, entry.name);\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif ((await stat(path)).mtimeMs < cutoff) await unlink(path);\n\t\t\t\t\t\t\t\t} catch (cause) {\n\t\t\t\t\t\t\t\t\tif (!(cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\")) throw cause;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tif (!(cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\")) throw cause;\n\t\t\t\t}\n\t\t\t}),\n\t);\n}\n\nexport async function removeClipboardImage(path: string, directory: string): Promise<void> {\n\tif (!isClipboardImagePath(path, directory)) return;\n\ttry {\n\t\tawait unlink(path);\n\t} catch (cause) {\n\t\tif (!(cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\")) throw cause;\n\t}\n}\n\n/** Writes one clipboard image to a temporary file, matching Pi's editor flow. */\nexport async function writeImageContentToTempFile(image: ImageContent, directory = tmpdir()): Promise<string> {\n\tconst extension = extensionForMimeType(image.mimeType);\n\tawait mkdir(directory, { recursive: true });\n\tconst path = join(directory, `${CLIPBOARD_FILE_PREFIX}${randomUUID()}.${extension}`);\n\tawait writeFile(path, Buffer.from(image.data, \"base64\"));\n\treturn path;\n}\n\n/** Reads the clipboard and returns the temporary path that should be inserted into the editor. */\nexport async function readClipboardImagePath(directory = tmpdir()): Promise<string | null> {\n\tconst image = await readClipboardImage();\n\treturn image ? writeImageContentToTempFile(image, directory) : null;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../src/core/context-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAA4C,MAAM,oBAAoB,CAAC;AAEjG,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CACpD;
|
|
1
|
+
{"version":3,"file":"context-builder.d.ts","sourceRoot":"","sources":["../../src/core/context-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAA4C,MAAM,oBAAoB,CAAC;AAEjG,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CACpD;AA2BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,mBAAmB,CAkCzF"}
|
|
@@ -13,6 +13,10 @@ function createSummaryMessage(entry) {
|
|
|
13
13
|
function messageEntries(entries) {
|
|
14
14
|
return entries.filter((entry) => entry.type === "message");
|
|
15
15
|
}
|
|
16
|
+
function contextMessageEntries(entries) {
|
|
17
|
+
return messageEntries(entries).filter((entry) => entry.message.role !== "assistant" ||
|
|
18
|
+
(entry.message.stopReason !== "error" && entry.message.stopReason !== "aborted"));
|
|
19
|
+
}
|
|
16
20
|
export function buildSessionContext(entries) {
|
|
17
21
|
const snapshot = structuredClone([...entries]);
|
|
18
22
|
let summaryIndex = -1;
|
|
@@ -23,7 +27,7 @@ export function buildSessionContext(entries) {
|
|
|
23
27
|
}
|
|
24
28
|
}
|
|
25
29
|
if (summaryIndex < 0) {
|
|
26
|
-
const messages =
|
|
30
|
+
const messages = contextMessageEntries(snapshot);
|
|
27
31
|
return {
|
|
28
32
|
messages: messages.map((entry) => entry.message),
|
|
29
33
|
sourceEntryIds: messages.map((entry) => entry.id),
|
|
@@ -37,7 +41,7 @@ export function buildSessionContext(entries) {
|
|
|
37
41
|
if (firstKeptIndex < 0) {
|
|
38
42
|
throw new Error("Summary firstKeptEntryId must reference an earlier message entry.");
|
|
39
43
|
}
|
|
40
|
-
const keptEntries =
|
|
44
|
+
const keptEntries = contextMessageEntries(snapshot.slice(firstKeptIndex));
|
|
41
45
|
return {
|
|
42
46
|
messages: [createSummaryMessage(summary), ...keptEntries.map((entry) => entry.message)],
|
|
43
47
|
sourceEntryIds: [null, ...keptEntries.map((entry) => entry.id)],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../../src/core/context-builder.ts"],"names":[],"mappings":"AAQA,SAAS,oBAAoB,CAAC,KAA0B;IACvD,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE;YACR;gBACC,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,2BAA2B,KAAK,CAAC,OAAO,2BAA2B;aACzE;SACD;QACD,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;KACtC,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,OAAgC;IACvD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAgC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgC;IACnE,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAC/C,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC;IACtB,KAAK,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3D,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;YACzC,YAAY,GAAG,KAAK,CAAC;YACrB,MAAM;QACP,CAAC;IACF,CAAC;IAED,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../../src/core/context-builder.ts"],"names":[],"mappings":"AAQA,SAAS,oBAAoB,CAAC,KAA0B;IACvD,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE;YACR;gBACC,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,2BAA2B,KAAK,CAAC,OAAO,2BAA2B;aACzE;SACD;QACD,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;KACtC,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,OAAgC;IACvD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAgC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;AAC1F,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAgC;IAC9D,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,CACpC,CAAC,KAAK,EAAE,EAAE,CACT,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;QAClC,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,KAAK,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CACjF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgC;IACnE,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAC/C,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC;IACtB,KAAK,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3D,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;YACzC,YAAY,GAAG,KAAK,CAAC;YACrB,MAAM;QACP,CAAC;IACF,CAAC;IAED,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QACjD,OAAO;YACN,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;YAChD,cAAc,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;SACjD,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IACvC,IAAI,OAAO,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,cAAc,GAAG,QAAQ,CAAC,SAAS,CACxC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,gBAAgB,CAC3G,CAAC;IACF,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,WAAW,GAAG,qBAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IAC1E,OAAO;QACN,QAAQ,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvF,cAAc,EAAE,CAAC,IAAI,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KAC/D,CAAC;AACH,CAAC","sourcesContent":["import type { Message, UserMessage } from \"@di-code/ai\";\nimport type { SessionEntry, SessionMessageEntry, SessionSummaryEntry } from \"./session/types.ts\";\n\nexport interface BuiltSessionContext {\n\treadonly messages: readonly Message[];\n\treadonly sourceEntryIds: readonly (string | null)[];\n}\n\nfunction createSummaryMessage(entry: SessionSummaryEntry): UserMessage {\n\treturn {\n\t\trole: \"user\",\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: `<conversation-summary>\\n${entry.summary}\\n</conversation-summary>`,\n\t\t\t},\n\t\t],\n\t\ttimestamp: Date.parse(entry.timestamp),\n\t};\n}\n\nfunction messageEntries(entries: readonly SessionEntry[]): SessionMessageEntry[] {\n\treturn entries.filter((entry): entry is SessionMessageEntry => entry.type === \"message\");\n}\n\nfunction contextMessageEntries(entries: readonly SessionEntry[]): SessionMessageEntry[] {\n\treturn messageEntries(entries).filter(\n\t\t(entry) =>\n\t\t\tentry.message.role !== \"assistant\" ||\n\t\t\t(entry.message.stopReason !== \"error\" && entry.message.stopReason !== \"aborted\"),\n\t);\n}\n\nexport function buildSessionContext(entries: readonly SessionEntry[]): BuiltSessionContext {\n\tconst snapshot = structuredClone([...entries]);\n\tlet summaryIndex = -1;\n\tfor (let index = snapshot.length - 1; index >= 0; index--) {\n\t\tif (snapshot[index]?.type === \"summary\") {\n\t\t\tsummaryIndex = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (summaryIndex < 0) {\n\t\tconst messages = contextMessageEntries(snapshot);\n\t\treturn {\n\t\t\tmessages: messages.map((entry) => entry.message),\n\t\t\tsourceEntryIds: messages.map((entry) => entry.id),\n\t\t};\n\t}\n\n\tconst summary = snapshot[summaryIndex];\n\tif (summary?.type !== \"summary\") {\n\t\tthrow new Error(\"Latest summary entry could not be resolved.\");\n\t}\n\tconst firstKeptIndex = snapshot.findIndex(\n\t\t(entry, index) => index < summaryIndex && entry.type === \"message\" && entry.id === summary.firstKeptEntryId,\n\t);\n\tif (firstKeptIndex < 0) {\n\t\tthrow new Error(\"Summary firstKeptEntryId must reference an earlier message entry.\");\n\t}\n\n\tconst keptEntries = contextMessageEntries(snapshot.slice(firstKeptIndex));\n\treturn {\n\t\tmessages: [createSummaryMessage(summary), ...keptEntries.map((entry) => entry.message)],\n\t\tsourceEntryIds: [null, ...keptEntries.map((entry) => entry.id)],\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
|
|
8
|
+
/** Extracts @path references into image attachments or bounded text blocks for the model prompt. */
|
|
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;
|
|
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;AAUD,oGAAoG;AACpG,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,CA8BnD"}
|
package/dist/core/image-input.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { readFile, stat } from "node:fs/promises";
|
|
2
|
-
import { basename, resolve } from "node:path";
|
|
2
|
+
import { basename, isAbsolute, relative, resolve } from "node:path";
|
|
3
|
+
import { resolveAllowedFilePath } from "./tools/path-boundary.js";
|
|
4
|
+
import { DEFAULT_READ_MAX_BYTES, DEFAULT_READ_MAX_LINES } from "./tools/read.js";
|
|
3
5
|
export const MAX_IMAGE_INPUTS = 4;
|
|
4
6
|
export const MAX_IMAGE_INPUT_BYTES = 5 * 1024 * 1024;
|
|
5
7
|
const IMAGE_REFERENCE = /(^|\s)@(?:"([^"\r\n]+)"|'([^'\r\n]+)'|([^\s@]+))/g;
|
|
@@ -58,6 +60,42 @@ async function loadImageInput(path, cwd) {
|
|
|
58
60
|
}
|
|
59
61
|
return imageContentFromBytes(data, path);
|
|
60
62
|
}
|
|
63
|
+
function containsNulByte(data) {
|
|
64
|
+
for (const byte of data)
|
|
65
|
+
if (byte === 0)
|
|
66
|
+
return true;
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
function escapeFileName(path) {
|
|
70
|
+
return path.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
71
|
+
}
|
|
72
|
+
function relativeAttachmentPath(path, cwd) {
|
|
73
|
+
const absolutePath = resolve(cwd, path);
|
|
74
|
+
const relativePath = relative(resolve(cwd), absolutePath).replaceAll("\\", "/");
|
|
75
|
+
return relativePath || basename(absolutePath);
|
|
76
|
+
}
|
|
77
|
+
async function loadTextAttachment(path, cwd) {
|
|
78
|
+
const absolutePath = await resolveAllowedFilePath(path, cwd);
|
|
79
|
+
const metadata = await stat(absolutePath);
|
|
80
|
+
if (!metadata.isFile())
|
|
81
|
+
throw new Error(`File attachment is not a regular file: ${displayPath(path)}`);
|
|
82
|
+
if (metadata.size > DEFAULT_READ_MAX_BYTES) {
|
|
83
|
+
throw new Error(`Text attachment exceeds the 50 KiB limit: ${displayPath(path)}`);
|
|
84
|
+
}
|
|
85
|
+
const data = await readFile(absolutePath);
|
|
86
|
+
if (data.length > DEFAULT_READ_MAX_BYTES) {
|
|
87
|
+
throw new Error(`Text attachment exceeds the 50 KiB limit: ${displayPath(path)}`);
|
|
88
|
+
}
|
|
89
|
+
if (containsNulByte(data))
|
|
90
|
+
throw new Error(`Binary files are not supported by @ attachments: ${displayPath(path)}`);
|
|
91
|
+
const normalized = data.toString("utf8").replace(/\r\n?/g, "\n");
|
|
92
|
+
const lines = normalized.split("\n");
|
|
93
|
+
const content = lines.length > DEFAULT_READ_MAX_LINES
|
|
94
|
+
? `${lines.slice(0, DEFAULT_READ_MAX_LINES).join("\n")}\n\n[File truncated after ${DEFAULT_READ_MAX_LINES} lines.]`
|
|
95
|
+
: normalized;
|
|
96
|
+
const fileName = escapeFileName(relativeAttachmentPath(path, cwd));
|
|
97
|
+
return `<file name="${fileName}">\n${content}\n</file>`;
|
|
98
|
+
}
|
|
61
99
|
/** Reads explicitly requested local image files into the provider-neutral user-message format. */
|
|
62
100
|
export async function loadImageInputs(paths, cwd) {
|
|
63
101
|
if (paths.length > MAX_IMAGE_INPUTS) {
|
|
@@ -68,10 +106,13 @@ export async function loadImageInputs(paths, cwd) {
|
|
|
68
106
|
function isMissingFileError(cause) {
|
|
69
107
|
return cause instanceof Error && "code" in cause && cause.code === "ENOENT";
|
|
70
108
|
}
|
|
71
|
-
|
|
109
|
+
function isUnsupportedImageError(cause) {
|
|
110
|
+
return cause instanceof Error && cause.message.startsWith("Unsupported image format:");
|
|
111
|
+
}
|
|
112
|
+
/** Extracts @path references into image attachments or bounded text blocks for the model prompt. */
|
|
72
113
|
export async function extractImageAttachments(text, cwd) {
|
|
73
114
|
const images = [];
|
|
74
|
-
const
|
|
115
|
+
const attachments = [];
|
|
75
116
|
let result = "";
|
|
76
117
|
let cursor = 0;
|
|
77
118
|
for (const match of text.matchAll(IMAGE_REFERENCE)) {
|
|
@@ -80,23 +121,27 @@ export async function extractImageAttachments(text, cwd) {
|
|
|
80
121
|
const path = match[2] ?? match[3] ?? match[4] ?? "";
|
|
81
122
|
result += `${text.slice(cursor, index)}${leading}`;
|
|
82
123
|
cursor = index + match[0].length;
|
|
83
|
-
if (images.length >= MAX_IMAGE_INPUTS) {
|
|
84
|
-
throw new Error(`At most ${MAX_IMAGE_INPUTS} images can be attached to one prompt.`);
|
|
85
|
-
}
|
|
86
124
|
try {
|
|
125
|
+
if (!isAbsolute(path))
|
|
126
|
+
await resolveAllowedFilePath(path, cwd);
|
|
87
127
|
const [image] = await loadImageInputs([path], cwd);
|
|
88
128
|
if (!image)
|
|
89
129
|
throw new Error("Image attachment was not loaded.");
|
|
130
|
+
if (images.length >= MAX_IMAGE_INPUTS) {
|
|
131
|
+
throw new Error(`At most ${MAX_IMAGE_INPUTS} images can be attached to one prompt.`);
|
|
132
|
+
}
|
|
90
133
|
images.push(image);
|
|
91
|
-
|
|
134
|
+
attachments.push(`[Attached image: ${basename(path)}]`);
|
|
92
135
|
}
|
|
93
136
|
catch (cause) {
|
|
94
137
|
if (isMissingFileError(cause))
|
|
95
|
-
throw new Error(`
|
|
96
|
-
|
|
138
|
+
throw new Error(`File attachment was not found: ${path}`);
|
|
139
|
+
if (!isUnsupportedImageError(cause))
|
|
140
|
+
throw cause;
|
|
141
|
+
attachments.push(await loadTextAttachment(path, cwd));
|
|
97
142
|
}
|
|
98
143
|
}
|
|
99
144
|
const prompt = `${result}${text.slice(cursor)}`.replace(/[ \t]{2,}/g, " ").trim();
|
|
100
|
-
return { text: [...
|
|
145
|
+
return { text: [...attachments, prompt].filter((value) => value.length > 0).join("\n"), images };
|
|
101
146
|
}
|
|
102
147
|
//# sourceMappingURL=image-input.js.map
|
|
@@ -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, resolve } from \"node:path\";\nimport type { ImageContent } from \"@di-code/ai\";\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\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\n/** Extracts @path image references while preserving a concise attachment label in 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 labels: 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\tif (images.length >= MAX_IMAGE_INPUTS) {\n\t\t\tthrow new Error(`At most ${MAX_IMAGE_INPUTS} images can be attached to one prompt.`);\n\t\t}\n\t\ttry {\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\timages.push(image);\n\t\t\tlabels.push(`[Attached image: ${basename(path)}]`);\n\t\t} catch (cause) {\n\t\t\tif (isMissingFileError(cause)) throw new Error(`Image attachment was not found: ${path}`);\n\t\t\tthrow cause;\n\t\t}\n\t}\n\n\tconst prompt = `${result}${text.slice(cursor)}`.replace(/[ \\t]{2,}/g, \" \").trim();\n\treturn { text: [...labels, 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":"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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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/resources/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGX,cAAc,EACd,qBAAqB,EAErB,gBAAgB,EAEhB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/resources/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGX,cAAc,EACd,qBAAqB,EAErB,gBAAgB,EAEhB,MAAM,YAAY,CAAC;AAiFpB,qBAAa,qBAAsB,YAAW,cAAc;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;gBAEpC,OAAO,EAAE,qBAAqB;IAIpC,IAAI,IAAI,OAAO,CAAC,gBAAgB,CAAC;CAsDvC;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAE7F"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { access, readFile, stat } from "node:fs/promises";
|
|
2
|
-
import {
|
|
3
|
-
import { discoverSkills, loadSkill } from "
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { createSkillCatalog, discoverSkills, loadSkill } from "@di-code/skills";
|
|
4
4
|
const MAX_CONTEXT_FILE_BYTES = 256 * 1024;
|
|
5
5
|
function isMissingPath(cause) {
|
|
6
6
|
return cause instanceof Error && "code" in cause && cause.code === "ENOENT";
|
|
@@ -64,17 +64,7 @@ async function loadContextFiles(options) {
|
|
|
64
64
|
diagnostics.push(loaded.diagnostic);
|
|
65
65
|
};
|
|
66
66
|
await add(resolve(options.agentDir), "global");
|
|
67
|
-
|
|
68
|
-
let current = resolve(options.cwd);
|
|
69
|
-
while (true) {
|
|
70
|
-
ancestors.unshift(current);
|
|
71
|
-
const parent = dirname(current);
|
|
72
|
-
if (parent === current || parse(current).root === current)
|
|
73
|
-
break;
|
|
74
|
-
current = parent;
|
|
75
|
-
}
|
|
76
|
-
for (const directory of ancestors)
|
|
77
|
-
await add(directory, directory === resolve(options.cwd) ? "project" : "ancestor");
|
|
67
|
+
await add(resolve(options.cwd), "project");
|
|
78
68
|
return { contextFiles, diagnostics };
|
|
79
69
|
}
|
|
80
70
|
async function exists(directory) {
|
|
@@ -96,29 +86,9 @@ export class DefaultResourceLoader {
|
|
|
96
86
|
async load() {
|
|
97
87
|
const context = await loadContextFiles(this.options);
|
|
98
88
|
const diagnostics = [...context.diagnostics];
|
|
99
|
-
const
|
|
100
|
-
const add = (candidate, candidateDiagnostics) => {
|
|
101
|
-
diagnostics.push(...candidateDiagnostics);
|
|
102
|
-
const existing = skills.get(candidate.name);
|
|
103
|
-
if (existing) {
|
|
104
|
-
diagnostics.push({
|
|
105
|
-
path: candidate.filePath,
|
|
106
|
-
kind: "skill",
|
|
107
|
-
stage: "collision",
|
|
108
|
-
severity: "warning",
|
|
109
|
-
message: `Skill name collision: "${candidate.name}"; using ${existing.filePath}`,
|
|
110
|
-
});
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
skills.set(candidate.name, candidate);
|
|
114
|
-
};
|
|
89
|
+
const skillResults = [];
|
|
115
90
|
const addResults = (results) => {
|
|
116
|
-
|
|
117
|
-
if (result.skill)
|
|
118
|
-
add(result.skill, result.diagnostics);
|
|
119
|
-
else
|
|
120
|
-
diagnostics.push(...result.diagnostics);
|
|
121
|
-
}
|
|
91
|
+
skillResults.push(...results);
|
|
122
92
|
};
|
|
123
93
|
if (!this.options.noSkills) {
|
|
124
94
|
for (const rawPath of this.options.skillPaths ?? []) {
|
|
@@ -129,10 +99,7 @@ export class DefaultResourceLoader {
|
|
|
129
99
|
addResults(await discoverSkills(path, "explicit"));
|
|
130
100
|
else {
|
|
131
101
|
const result = await loadSkill(path, "explicit");
|
|
132
|
-
|
|
133
|
-
add(result.skill, result.diagnostics);
|
|
134
|
-
else
|
|
135
|
-
diagnostics.push(...result.diagnostics);
|
|
102
|
+
skillResults.push(result);
|
|
136
103
|
}
|
|
137
104
|
}
|
|
138
105
|
catch (cause) {
|
|
@@ -144,7 +111,7 @@ export class DefaultResourceLoader {
|
|
|
144
111
|
}
|
|
145
112
|
const projectDirectories = [
|
|
146
113
|
join(this.options.cwd, ".di-code", "skills"),
|
|
147
|
-
join(this.options.cwd, ".
|
|
114
|
+
join(this.options.cwd, ".agents", "skills"),
|
|
148
115
|
];
|
|
149
116
|
if (this.options.projectTrusted === true) {
|
|
150
117
|
for (const directory of projectDirectories)
|
|
@@ -163,9 +130,15 @@ export class DefaultResourceLoader {
|
|
|
163
130
|
}
|
|
164
131
|
}
|
|
165
132
|
}
|
|
166
|
-
addResults(await discoverSkills(join(this.options.agentDir, "skills"), "
|
|
133
|
+
addResults(await discoverSkills(join(this.options.agentDir, "skills"), "user"));
|
|
167
134
|
}
|
|
168
|
-
|
|
135
|
+
const catalog = createSkillCatalog(skillResults);
|
|
136
|
+
const skillDiagnostics = catalog.diagnostics.map((diagnostic) => diagnostic);
|
|
137
|
+
const skills = catalog.skills.map((skill) => ({
|
|
138
|
+
...skill,
|
|
139
|
+
scope: skill.source === "explicit" ? "explicit" : skill.source === "project" ? "project" : "global",
|
|
140
|
+
}));
|
|
141
|
+
return { contextFiles: context.contextFiles, skills, diagnostics: [...diagnostics, ...skillDiagnostics] };
|
|
169
142
|
}
|
|
170
143
|
}
|
|
171
144
|
export async function loadResources(options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/resources/loader.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, readFile, stat } from \"node:fs/promises\";\nimport { dirname, join, parse, resolve } from \"node:path\";\nimport { discoverSkills, loadSkill } from \"./skills.ts\";\nimport type {\n\tContextFile,\n\tResourceDiagnostic,\n\tResourceLoader,\n\tResourceLoaderOptions,\n\tResourceScope,\n\tResourceSnapshot,\n\tSkillResource,\n} from \"./types.ts\";\n\nconst MAX_CONTEXT_FILE_BYTES = 256 * 1024;\n\nfunction isMissingPath(cause: unknown): boolean {\n\treturn cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\";\n}\n\nfunction contextDiagnostic(path: string, stage: ResourceDiagnostic[\"stage\"], message: string): ResourceDiagnostic {\n\treturn { path, kind: \"agents\", stage, severity: \"warning\", message };\n}\n\nasync function locateAgentsFile(directory: string): Promise<string | undefined> {\n\tfor (const name of [\"AGENTS.md\", \"AGENTS.MD\"]) {\n\t\tconst path = join(directory, name);\n\t\ttry {\n\t\t\tif ((await stat(path)).isFile()) return path;\n\t\t} catch (cause) {\n\t\t\tif (!isMissingPath(cause)) throw cause;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function loadContextFile(\n\tpath: string,\n\tscope: ResourceScope,\n): Promise<{ file?: ContextFile; diagnostic?: ResourceDiagnostic }> {\n\ttry {\n\t\tconst metadata = await stat(path);\n\t\tif (metadata.size > MAX_CONTEXT_FILE_BYTES) {\n\t\t\treturn { diagnostic: contextDiagnostic(path, \"read\", `AGENTS.md exceeds ${MAX_CONTEXT_FILE_BYTES} byte limit`) };\n\t\t}\n\t\treturn { file: { kind: \"agents\", path: resolve(path), scope, content: await readFile(path, \"utf8\") } };\n\t} catch (cause) {\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\treturn { diagnostic: contextDiagnostic(path, \"read\", `Failed to read AGENTS.md: ${message}`) };\n\t}\n}\n\nasync function loadContextFiles(options: ResourceLoaderOptions): Promise<{\n\tcontextFiles: ContextFile[];\n\tdiagnostics: ResourceDiagnostic[];\n}> {\n\tif (options.noContextFiles) return { contextFiles: [], diagnostics: [] };\n\tconst contextFiles: ContextFile[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tconst seen = new Set<string>();\n\tconst add = async (directory: string, scope: ResourceScope): Promise<void> => {\n\t\tlet path: string | undefined;\n\t\ttry {\n\t\t\tpath = await locateAgentsFile(directory);\n\t\t} catch (cause) {\n\t\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\t\tdiagnostics.push(contextDiagnostic(directory, \"discover\", `Failed to discover AGENTS.md: ${message}`));\n\t\t\treturn;\n\t\t}\n\t\tif (!path) return;\n\t\tconst absolutePath = resolve(path);\n\t\tif (seen.has(absolutePath)) return;\n\t\tseen.add(absolutePath);\n\t\tconst loaded = await loadContextFile(absolutePath, scope);\n\t\tif (loaded.file) contextFiles.push(loaded.file);\n\t\tif (loaded.diagnostic) diagnostics.push(loaded.diagnostic);\n\t};\n\n\tawait add(resolve(options.agentDir), \"global\");\n\tconst ancestors: string[] = [];\n\tlet current = resolve(options.cwd);\n\twhile (true) {\n\t\tancestors.unshift(current);\n\t\tconst parent = dirname(current);\n\t\tif (parent === current || parse(current).root === current) break;\n\t\tcurrent = parent;\n\t}\n\tfor (const directory of ancestors) await add(directory, directory === resolve(options.cwd) ? \"project\" : \"ancestor\");\n\treturn { contextFiles, diagnostics };\n}\n\nasync function exists(directory: string): Promise<boolean> {\n\ttry {\n\t\tawait access(directory);\n\t\treturn true;\n\t} catch (cause) {\n\t\tif (isMissingPath(cause)) return false;\n\t\tthrow cause;\n\t}\n}\n\nexport class DefaultResourceLoader implements ResourceLoader {\n\tprivate readonly options: ResourceLoaderOptions;\n\n\tconstructor(options: ResourceLoaderOptions) {\n\t\tthis.options = options;\n\t}\n\n\tasync load(): Promise<ResourceSnapshot> {\n\t\tconst context = await loadContextFiles(this.options);\n\t\tconst diagnostics = [...context.diagnostics];\n\t\tconst skills = new Map<string, SkillResource>();\n\t\tconst add = (candidate: SkillResource, candidateDiagnostics: readonly ResourceDiagnostic[]): void => {\n\t\t\tdiagnostics.push(...candidateDiagnostics);\n\t\t\tconst existing = skills.get(candidate.name);\n\t\t\tif (existing) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\tpath: candidate.filePath,\n\t\t\t\t\tkind: \"skill\",\n\t\t\t\t\tstage: \"collision\",\n\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\tmessage: `Skill name collision: \"${candidate.name}\"; using ${existing.filePath}`,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tskills.set(candidate.name, candidate);\n\t\t};\n\t\tconst addResults = (results: Awaited<ReturnType<typeof discoverSkills>>): void => {\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.skill) add(result.skill, result.diagnostics);\n\t\t\t\telse diagnostics.push(...result.diagnostics);\n\t\t\t}\n\t\t};\n\n\t\tif (!this.options.noSkills) {\n\t\t\tfor (const rawPath of this.options.skillPaths ?? []) {\n\t\t\t\tconst path = resolve(this.options.cwd, rawPath);\n\t\t\t\ttry {\n\t\t\t\t\tconst metadata = await stat(path);\n\t\t\t\t\tif (metadata.isDirectory()) addResults(await discoverSkills(path, \"explicit\"));\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst result = await loadSkill(path, \"explicit\");\n\t\t\t\t\t\tif (result.skill) add(result.skill, result.diagnostics);\n\t\t\t\t\t\telse diagnostics.push(...result.diagnostics);\n\t\t\t\t\t}\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tconst message = isMissingPath(cause)\n\t\t\t\t\t\t? \"Skill path does not exist\"\n\t\t\t\t\t\t: `Failed to discover skill path: ${String(cause)}`;\n\t\t\t\t\tdiagnostics.push({ path, kind: \"skill\", stage: \"discover\", severity: \"warning\", message });\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst projectDirectories = [\n\t\t\t\tjoin(this.options.cwd, \".di-code\", \"skills\"),\n\t\t\t\tjoin(this.options.cwd, \".pi\", \"skills\"),\n\t\t\t];\n\t\t\tif (this.options.projectTrusted === true) {\n\t\t\t\tfor (const directory of projectDirectories) addResults(await discoverSkills(directory, \"project\"));\n\t\t\t} else {\n\t\t\t\tfor (const directory of projectDirectories) {\n\t\t\t\t\tif (await exists(directory)) {\n\t\t\t\t\t\tdiagnostics.push({\n\t\t\t\t\t\t\tpath: resolve(directory),\n\t\t\t\t\t\t\tkind: \"skill\",\n\t\t\t\t\t\t\tstage: \"trust\",\n\t\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t\t\tmessage: \"Project skill skipped because project trust is not granted\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\taddResults(await discoverSkills(join(this.options.agentDir, \"skills\"), \"global\"));\n\t\t}\n\t\treturn { contextFiles: context.contextFiles, skills: [...skills.values()], diagnostics };\n\t}\n}\n\nexport async function loadResources(options: ResourceLoaderOptions): Promise<ResourceSnapshot> {\n\treturn new DefaultResourceLoader(options).load();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/resources/loader.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, readFile, stat } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { createSkillCatalog, discoverSkills, loadSkill, type SkillLoadResult } from \"@di-code/skills\";\nimport type {\n\tContextFile,\n\tResourceDiagnostic,\n\tResourceLoader,\n\tResourceLoaderOptions,\n\tResourceScope,\n\tResourceSnapshot,\n\tSkillResource,\n} from \"./types.ts\";\n\nconst MAX_CONTEXT_FILE_BYTES = 256 * 1024;\n\nfunction isMissingPath(cause: unknown): boolean {\n\treturn cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\";\n}\n\nfunction contextDiagnostic(path: string, stage: ResourceDiagnostic[\"stage\"], message: string): ResourceDiagnostic {\n\treturn { path, kind: \"agents\", stage, severity: \"warning\", message };\n}\n\nasync function locateAgentsFile(directory: string): Promise<string | undefined> {\n\tfor (const name of [\"AGENTS.md\", \"AGENTS.MD\"]) {\n\t\tconst path = join(directory, name);\n\t\ttry {\n\t\t\tif ((await stat(path)).isFile()) return path;\n\t\t} catch (cause) {\n\t\t\tif (!isMissingPath(cause)) throw cause;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function loadContextFile(\n\tpath: string,\n\tscope: ResourceScope,\n): Promise<{ file?: ContextFile; diagnostic?: ResourceDiagnostic }> {\n\ttry {\n\t\tconst metadata = await stat(path);\n\t\tif (metadata.size > MAX_CONTEXT_FILE_BYTES) {\n\t\t\treturn { diagnostic: contextDiagnostic(path, \"read\", `AGENTS.md exceeds ${MAX_CONTEXT_FILE_BYTES} byte limit`) };\n\t\t}\n\t\treturn { file: { kind: \"agents\", path: resolve(path), scope, content: await readFile(path, \"utf8\") } };\n\t} catch (cause) {\n\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\treturn { diagnostic: contextDiagnostic(path, \"read\", `Failed to read AGENTS.md: ${message}`) };\n\t}\n}\n\nasync function loadContextFiles(options: ResourceLoaderOptions): Promise<{\n\tcontextFiles: ContextFile[];\n\tdiagnostics: ResourceDiagnostic[];\n}> {\n\tif (options.noContextFiles) return { contextFiles: [], diagnostics: [] };\n\tconst contextFiles: ContextFile[] = [];\n\tconst diagnostics: ResourceDiagnostic[] = [];\n\tconst seen = new Set<string>();\n\tconst add = async (directory: string, scope: ResourceScope): Promise<void> => {\n\t\tlet path: string | undefined;\n\t\ttry {\n\t\t\tpath = await locateAgentsFile(directory);\n\t\t} catch (cause) {\n\t\t\tconst message = cause instanceof Error ? cause.message : String(cause);\n\t\t\tdiagnostics.push(contextDiagnostic(directory, \"discover\", `Failed to discover AGENTS.md: ${message}`));\n\t\t\treturn;\n\t\t}\n\t\tif (!path) return;\n\t\tconst absolutePath = resolve(path);\n\t\tif (seen.has(absolutePath)) return;\n\t\tseen.add(absolutePath);\n\t\tconst loaded = await loadContextFile(absolutePath, scope);\n\t\tif (loaded.file) contextFiles.push(loaded.file);\n\t\tif (loaded.diagnostic) diagnostics.push(loaded.diagnostic);\n\t};\n\n\tawait add(resolve(options.agentDir), \"global\");\n\tawait add(resolve(options.cwd), \"project\");\n\treturn { contextFiles, diagnostics };\n}\n\nasync function exists(directory: string): Promise<boolean> {\n\ttry {\n\t\tawait access(directory);\n\t\treturn true;\n\t} catch (cause) {\n\t\tif (isMissingPath(cause)) return false;\n\t\tthrow cause;\n\t}\n}\n\nexport class DefaultResourceLoader implements ResourceLoader {\n\tprivate readonly options: ResourceLoaderOptions;\n\n\tconstructor(options: ResourceLoaderOptions) {\n\t\tthis.options = options;\n\t}\n\n\tasync load(): Promise<ResourceSnapshot> {\n\t\tconst context = await loadContextFiles(this.options);\n\t\tconst diagnostics = [...context.diagnostics];\n\t\tconst skillResults: SkillLoadResult[] = [];\n\t\tconst addResults = (results: readonly SkillLoadResult[]): void => {\n\t\t\tskillResults.push(...results);\n\t\t};\n\n\t\tif (!this.options.noSkills) {\n\t\t\tfor (const rawPath of this.options.skillPaths ?? []) {\n\t\t\t\tconst path = resolve(this.options.cwd, rawPath);\n\t\t\t\ttry {\n\t\t\t\t\tconst metadata = await stat(path);\n\t\t\t\t\tif (metadata.isDirectory()) addResults(await discoverSkills(path, \"explicit\"));\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst result = await loadSkill(path, \"explicit\");\n\t\t\t\t\t\tskillResults.push(result);\n\t\t\t\t\t}\n\t\t\t\t} catch (cause) {\n\t\t\t\t\tconst message = isMissingPath(cause)\n\t\t\t\t\t\t? \"Skill path does not exist\"\n\t\t\t\t\t\t: `Failed to discover skill path: ${String(cause)}`;\n\t\t\t\t\tdiagnostics.push({ path, kind: \"skill\", stage: \"discover\", severity: \"warning\", message });\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst projectDirectories = [\n\t\t\t\tjoin(this.options.cwd, \".di-code\", \"skills\"),\n\t\t\t\tjoin(this.options.cwd, \".agents\", \"skills\"),\n\t\t\t];\n\t\t\tif (this.options.projectTrusted === true) {\n\t\t\t\tfor (const directory of projectDirectories) addResults(await discoverSkills(directory, \"project\"));\n\t\t\t} else {\n\t\t\t\tfor (const directory of projectDirectories) {\n\t\t\t\t\tif (await exists(directory)) {\n\t\t\t\t\t\tdiagnostics.push({\n\t\t\t\t\t\t\tpath: resolve(directory),\n\t\t\t\t\t\t\tkind: \"skill\",\n\t\t\t\t\t\t\tstage: \"trust\",\n\t\t\t\t\t\t\tseverity: \"warning\",\n\t\t\t\t\t\t\tmessage: \"Project skill skipped because project trust is not granted\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\taddResults(await discoverSkills(join(this.options.agentDir, \"skills\"), \"user\"));\n\t\t}\n\t\tconst catalog = createSkillCatalog(skillResults);\n\t\tconst skillDiagnostics = catalog.diagnostics.map((diagnostic): ResourceDiagnostic => diagnostic);\n\t\tconst skills: SkillResource[] = catalog.skills.map((skill) => ({\n\t\t\t...skill,\n\t\t\tscope: skill.source === \"explicit\" ? \"explicit\" : skill.source === \"project\" ? \"project\" : \"global\",\n\t\t}));\n\t\treturn { contextFiles: context.contextFiles, skills, diagnostics: [...diagnostics, ...skillDiagnostics] };\n\t}\n}\n\nexport async function loadResources(options: ResourceLoaderOptions): Promise<ResourceSnapshot> {\n\treturn new DefaultResourceLoader(options).load();\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import type { SkillDescriptor, SkillSource } from "@di-code/skills";
|
|
2
|
+
export type ResourceScope = "global" | "project" | "explicit";
|
|
2
3
|
export type ResourceDiagnosticStage = "discover" | "read" | "parse" | "collision" | "trust";
|
|
3
4
|
export interface ResourceDiagnostic {
|
|
4
5
|
readonly path: string;
|
|
@@ -13,15 +14,11 @@ export interface ContextFile {
|
|
|
13
14
|
readonly scope: ResourceScope;
|
|
14
15
|
readonly content: string;
|
|
15
16
|
}
|
|
16
|
-
export
|
|
17
|
-
readonly kind: "skill";
|
|
18
|
-
readonly name: string;
|
|
19
|
-
readonly description: string;
|
|
20
|
-
readonly filePath: string;
|
|
21
|
-
readonly baseDir: string;
|
|
17
|
+
export type SkillResource = Omit<SkillDescriptor, "source" | "userInvocable"> & {
|
|
22
18
|
readonly scope: ResourceScope;
|
|
23
|
-
readonly
|
|
24
|
-
|
|
19
|
+
readonly source?: SkillSource;
|
|
20
|
+
readonly userInvocable?: boolean;
|
|
21
|
+
};
|
|
25
22
|
export interface ResourceSnapshot {
|
|
26
23
|
readonly contextFiles: readonly ContextFile[];
|
|
27
24
|
readonly skills: readonly SkillResource[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/resources/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/resources/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAE9D,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,CAAC;AAE5F,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,eAAe,CAAC,GAAG;IAC/E,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,YAAY,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,CAAC;CACpD;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAClC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/resources/types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/resources/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { SkillDescriptor, SkillSource } from \"@di-code/skills\";\n\nexport type ResourceScope = \"global\" | \"project\" | \"explicit\";\n\nexport type ResourceDiagnosticStage = \"discover\" | \"read\" | \"parse\" | \"collision\" | \"trust\";\n\nexport interface ResourceDiagnostic {\n\treadonly path: string;\n\treadonly kind: \"agents\" | \"skill\";\n\treadonly stage: ResourceDiagnosticStage;\n\treadonly severity: \"warning\" | \"error\";\n\treadonly message: string;\n}\n\nexport interface ContextFile {\n\treadonly kind: \"agents\";\n\treadonly path: string;\n\treadonly scope: ResourceScope;\n\treadonly content: string;\n}\n\nexport type SkillResource = Omit<SkillDescriptor, \"source\" | \"userInvocable\"> & {\n\treadonly scope: ResourceScope;\n\treadonly source?: SkillSource;\n\treadonly userInvocable?: boolean;\n};\n\nexport interface ResourceSnapshot {\n\treadonly contextFiles: readonly ContextFile[];\n\treadonly skills: readonly SkillResource[];\n\treadonly diagnostics: readonly ResourceDiagnostic[];\n}\n\nexport interface ResourceLoaderOptions {\n\treadonly cwd: string;\n\treadonly agentDir: string;\n\treadonly projectTrusted?: boolean;\n\treadonly noSkills?: boolean;\n\treadonly noContextFiles?: boolean;\n\treadonly skillPaths?: readonly string[];\n}\n\nexport interface ResourceLoader {\n\tload(): Promise<ResourceSnapshot>;\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Message } from "@di-code/ai";
|
|
2
|
+
import { type BuiltSessionContext } from "../context-builder.ts";
|
|
2
3
|
import { type SessionAppendOptions } from "./session-storage.ts";
|
|
3
|
-
import { type SessionDiagnostic, type SessionEntry, type SessionHeader, type SessionMessageEntry, type SessionSummaryEntry } from "./types.ts";
|
|
4
|
+
import { type SessionDiagnostic, type SessionEntry, type SessionHeader, type SessionMessageEntry, type SessionSummaryEntry, type SessionTreeNode } from "./types.ts";
|
|
4
5
|
export interface SessionManagerCreateOptions {
|
|
5
6
|
readonly filePath: string;
|
|
6
7
|
readonly cwd: string;
|
|
@@ -21,7 +22,10 @@ export declare class SessionManager {
|
|
|
21
22
|
private readonly createId;
|
|
22
23
|
private readonly appendOptions;
|
|
23
24
|
private readonly sessionEntries;
|
|
25
|
+
private readonly entriesById;
|
|
26
|
+
private readonly childrenByParentId;
|
|
24
27
|
private readonly sessionDiagnostics;
|
|
28
|
+
private activeLeafId;
|
|
25
29
|
private fileCreated;
|
|
26
30
|
private appendQueue;
|
|
27
31
|
private constructor();
|
|
@@ -30,6 +34,12 @@ export declare class SessionManager {
|
|
|
30
34
|
get entries(): readonly SessionEntry[];
|
|
31
35
|
get header(): SessionHeader;
|
|
32
36
|
get messages(): readonly Message[];
|
|
37
|
+
getEntry(id: string): SessionEntry | undefined;
|
|
38
|
+
getTree(): readonly SessionTreeNode[];
|
|
39
|
+
getBranch(leafId?: string): readonly SessionEntry[];
|
|
40
|
+
setLeaf(id: string): void;
|
|
41
|
+
resetLeaf(): void;
|
|
42
|
+
buildContext(leafId?: string): BuiltSessionContext;
|
|
33
43
|
get latestSummary(): SessionSummaryEntry | undefined;
|
|
34
44
|
get diagnostics(): readonly SessionDiagnostic[];
|
|
35
45
|
get leafId(): string;
|
|
@@ -40,5 +50,6 @@ export declare class SessionManager {
|
|
|
40
50
|
readonly firstKeptEntryId: string;
|
|
41
51
|
readonly tokensBefore: number;
|
|
42
52
|
}): Promise<SessionSummaryEntry>;
|
|
53
|
+
private addToIndexes;
|
|
43
54
|
}
|
|
44
55
|
//# sourceMappingURL=session-manager.d.ts.map
|