@vedangiitb/qwintly-core 1.0.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 +8 -0
- package/dist/ai/ai.d.ts +2 -0
- package/dist/ai/ai.d.ts.map +1 -0
- package/dist/ai/ai.js +2 -0
- package/dist/ai/ai.js.map +1 -0
- package/dist/ai/generate/gemini.client.d.ts +15 -0
- package/dist/ai/generate/gemini.client.d.ts.map +1 -0
- package/dist/ai/generate/gemini.client.js +39 -0
- package/dist/ai/generate/gemini.client.js.map +1 -0
- package/dist/ai/generate/generateClient.d.ts +3 -0
- package/dist/ai/generate/generateClient.d.ts.map +1 -0
- package/dist/ai/generate/generateClient.js +8 -0
- package/dist/ai/generate/generateClient.js.map +1 -0
- package/dist/ai/toolLoop/toolLoopContext.d.ts +33 -0
- package/dist/ai/toolLoop/toolLoopContext.d.ts.map +1 -0
- package/dist/ai/toolLoop/toolLoopContext.js +112 -0
- package/dist/ai/toolLoop/toolLoopContext.js.map +1 -0
- package/dist/ai/toolLoop/toolLoopRunner.d.ts +43 -0
- package/dist/ai/toolLoop/toolLoopRunner.d.ts.map +1 -0
- package/dist/ai/toolLoop/toolLoopRunner.js +227 -0
- package/dist/ai/toolLoop/toolLoopRunner.js.map +1 -0
- package/dist/ai/toolLoop/toolLoopRunnerUtils.d.ts +51 -0
- package/dist/ai/toolLoop/toolLoopRunnerUtils.d.ts.map +1 -0
- package/dist/ai/toolLoop/toolLoopRunnerUtils.js +164 -0
- package/dist/ai/toolLoop/toolLoopRunnerUtils.js.map +1 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.d.ts +36 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.d.ts.map +1 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.js +307 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.js.map +1 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.test.d.ts +2 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.test.d.ts.map +1 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.test.js +50 -0
- package/dist/ai/tools/helpers/applyPatch.helpers.test.js.map +1 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.d.ts +2 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.d.ts.map +1 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.js +45 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.js.map +1 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.test.d.ts +2 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.test.d.ts.map +1 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.test.js +15 -0
- package/dist/ai/tools/helpers/fileSystem.helpers.test.js.map +1 -0
- package/dist/ai/tools/helpers/format.helpers.d.ts +2 -0
- package/dist/ai/tools/helpers/format.helpers.d.ts.map +1 -0
- package/dist/ai/tools/helpers/format.helpers.js +14 -0
- package/dist/ai/tools/helpers/format.helpers.js.map +1 -0
- package/dist/ai/tools/helpers/nextRouteFilePolicy.d.ts +8 -0
- package/dist/ai/tools/helpers/nextRouteFilePolicy.d.ts.map +1 -0
- package/dist/ai/tools/helpers/nextRouteFilePolicy.js +26 -0
- package/dist/ai/tools/helpers/nextRouteFilePolicy.js.map +1 -0
- package/dist/ai/tools/implementations/applyPatch.impl.d.ts +53 -0
- package/dist/ai/tools/implementations/applyPatch.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/applyPatch.impl.js +242 -0
- package/dist/ai/tools/implementations/applyPatch.impl.js.map +1 -0
- package/dist/ai/tools/implementations/applyPatch.impl.test.d.ts +2 -0
- package/dist/ai/tools/implementations/applyPatch.impl.test.d.ts.map +1 -0
- package/dist/ai/tools/implementations/applyPatch.impl.test.js +72 -0
- package/dist/ai/tools/implementations/applyPatch.impl.test.js.map +1 -0
- package/dist/ai/tools/implementations/factories.d.ts +90 -0
- package/dist/ai/tools/implementations/factories.d.ts.map +1 -0
- package/dist/ai/tools/implementations/factories.js +26 -0
- package/dist/ai/tools/implementations/factories.js.map +1 -0
- package/dist/ai/tools/implementations/listDir.impl.d.ts +3 -0
- package/dist/ai/tools/implementations/listDir.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/listDir.impl.js +47 -0
- package/dist/ai/tools/implementations/listDir.impl.js.map +1 -0
- package/dist/ai/tools/implementations/readFile.impl.d.ts +3 -0
- package/dist/ai/tools/implementations/readFile.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/readFile.impl.js +23 -0
- package/dist/ai/tools/implementations/readFile.impl.js.map +1 -0
- package/dist/ai/tools/implementations/search.impl.d.ts +18 -0
- package/dist/ai/tools/implementations/search.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/search.impl.js +74 -0
- package/dist/ai/tools/implementations/search.impl.js.map +1 -0
- package/dist/ai/tools/implementations/workspaceDeps.d.ts +22 -0
- package/dist/ai/tools/implementations/workspaceDeps.d.ts.map +1 -0
- package/dist/ai/tools/implementations/workspaceDeps.js +2 -0
- package/dist/ai/tools/implementations/workspaceDeps.js.map +1 -0
- package/dist/ai/tools/implementations/writeFile.impl.d.ts +27 -0
- package/dist/ai/tools/implementations/writeFile.impl.d.ts.map +1 -0
- package/dist/ai/tools/implementations/writeFile.impl.js +62 -0
- package/dist/ai/tools/implementations/writeFile.impl.js.map +1 -0
- package/dist/ai/tools/schemas/applyPatch.schema.d.ts +16 -0
- package/dist/ai/tools/schemas/applyPatch.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/applyPatch.schema.js +17 -0
- package/dist/ai/tools/schemas/applyPatch.schema.js.map +1 -0
- package/dist/ai/tools/schemas/listDir.schema.d.ts +22 -0
- package/dist/ai/tools/schemas/listDir.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/listDir.schema.js +22 -0
- package/dist/ai/tools/schemas/listDir.schema.js.map +1 -0
- package/dist/ai/tools/schemas/readFile.schema.d.ts +26 -0
- package/dist/ai/tools/schemas/readFile.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/readFile.schema.js +26 -0
- package/dist/ai/tools/schemas/readFile.schema.js.map +1 -0
- package/dist/ai/tools/schemas/search.schema.d.ts +16 -0
- package/dist/ai/tools/schemas/search.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/search.schema.js +16 -0
- package/dist/ai/tools/schemas/search.schema.js.map +1 -0
- package/dist/ai/tools/schemas/submitCodegenDone.schema.d.ts +16 -0
- package/dist/ai/tools/schemas/submitCodegenDone.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/submitCodegenDone.schema.js +16 -0
- package/dist/ai/tools/schemas/submitCodegenDone.schema.js.map +1 -0
- package/dist/ai/tools/schemas/submitPlannerTasks.schema.d.ts +33 -0
- package/dist/ai/tools/schemas/submitPlannerTasks.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/submitPlannerTasks.schema.js +31 -0
- package/dist/ai/tools/schemas/submitPlannerTasks.schema.js.map +1 -0
- package/dist/ai/tools/schemas/writeFile.schema.d.ts +20 -0
- package/dist/ai/tools/schemas/writeFile.schema.d.ts.map +1 -0
- package/dist/ai/tools/schemas/writeFile.schema.js +23 -0
- package/dist/ai/tools/schemas/writeFile.schema.js.map +1 -0
- package/dist/ai/tools/toolsets/codegenTools.d.ts +3 -0
- package/dist/ai/tools/toolsets/codegenTools.d.ts.map +1 -0
- package/dist/ai/tools/toolsets/codegenTools.js +17 -0
- package/dist/ai/tools/toolsets/codegenTools.js.map +1 -0
- package/dist/ai/tools/toolsets/plannerTools.d.ts +3 -0
- package/dist/ai/tools/toolsets/plannerTools.d.ts.map +1 -0
- package/dist/ai/tools/toolsets/plannerTools.js +17 -0
- package/dist/ai/tools/toolsets/plannerTools.js.map +1 -0
- package/dist/core.d.ts +44 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +80 -0
- package/dist/core.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/codegenIndex.d.ts +3 -0
- package/dist/indexer/codegenIndex.d.ts.map +1 -0
- package/dist/indexer/codegenIndex.js +17 -0
- package/dist/indexer/codegenIndex.js.map +1 -0
- package/dist/indexer/data/configs.constants.d.ts +85 -0
- package/dist/indexer/data/configs.constants.d.ts.map +1 -0
- package/dist/indexer/data/configs.constants.js +136 -0
- package/dist/indexer/data/configs.constants.js.map +1 -0
- package/dist/indexer/helpers/buildFolderTree.d.ts +2 -0
- package/dist/indexer/helpers/buildFolderTree.d.ts.map +1 -0
- package/dist/indexer/helpers/buildFolderTree.js +40 -0
- package/dist/indexer/helpers/buildFolderTree.js.map +1 -0
- package/dist/indexer/plannerIndex.d.ts +3 -0
- package/dist/indexer/plannerIndex.d.ts.map +1 -0
- package/dist/indexer/plannerIndex.js +20 -0
- package/dist/indexer/plannerIndex.js.map +1 -0
- package/dist/indexer/projectInfoIndex.d.ts +3 -0
- package/dist/indexer/projectInfoIndex.d.ts.map +1 -0
- package/dist/indexer/projectInfoIndex.js +257 -0
- package/dist/indexer/projectInfoIndex.js.map +1 -0
- package/dist/indexer/validatorIndex.d.ts +3 -0
- package/dist/indexer/validatorIndex.d.ts.map +1 -0
- package/dist/indexer/validatorIndex.js +14 -0
- package/dist/indexer/validatorIndex.js.map +1 -0
- package/dist/lib/redis.d.ts +3 -0
- package/dist/lib/redis.d.ts.map +1 -0
- package/dist/lib/redis.js +7 -0
- package/dist/lib/redis.js.map +1 -0
- package/dist/lib/supabase.d.ts +2 -0
- package/dist/lib/supabase.d.ts.map +1 -0
- package/dist/lib/supabase.js +4 -0
- package/dist/lib/supabase.js.map +1 -0
- package/dist/logging/genStatus.service.d.ts +14 -0
- package/dist/logging/genStatus.service.d.ts.map +1 -0
- package/dist/logging/genStatus.service.js +36 -0
- package/dist/logging/genStatus.service.js.map +1 -0
- package/dist/logging/logging.utils.d.ts +12 -0
- package/dist/logging/logging.utils.d.ts.map +1 -0
- package/dist/logging/logging.utils.js +15 -0
- package/dist/logging/logging.utils.js.map +1 -0
- package/dist/logging/redis.service.d.ts +11 -0
- package/dist/logging/redis.service.d.ts.map +1 -0
- package/dist/logging/redis.service.js +26 -0
- package/dist/logging/redis.service.js.map +1 -0
- package/dist/repository/context.repository.d.ts +8 -0
- package/dist/repository/context.repository.d.ts.map +1 -0
- package/dist/repository/context.repository.js +59 -0
- package/dist/repository/context.repository.js.map +1 -0
- package/dist/repository/genStatus.repository.d.ts +13 -0
- package/dist/repository/genStatus.repository.d.ts.map +1 -0
- package/dist/repository/genStatus.repository.js +18 -0
- package/dist/repository/genStatus.repository.js.map +1 -0
- package/dist/repository/planTasks.repository.d.ts +9 -0
- package/dist/repository/planTasks.repository.d.ts.map +1 -0
- package/dist/repository/planTasks.repository.js +24 -0
- package/dist/repository/planTasks.repository.js.map +1 -0
- package/dist/repository/repository.d.ts +5 -0
- package/dist/repository/repository.d.ts.map +1 -0
- package/dist/repository/repository.js +7 -0
- package/dist/repository/repository.js.map +1 -0
- package/dist/types/context.types.d.ts +64 -0
- package/dist/types/context.types.d.ts.map +1 -0
- package/dist/types/context.types.js +55 -0
- package/dist/types/context.types.js.map +1 -0
- package/dist/types/events.d.ts +16 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +14 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index/configs.types.d.ts +28 -0
- package/dist/types/index/configs.types.d.ts.map +1 -0
- package/dist/types/index/configs.types.js +2 -0
- package/dist/types/index/configs.types.js.map +1 -0
- package/dist/types/index/conventions.types.d.ts +40 -0
- package/dist/types/index/conventions.types.d.ts.map +1 -0
- package/dist/types/index/conventions.types.js +2 -0
- package/dist/types/index/conventions.types.js.map +1 -0
- package/dist/types/index/index.types.d.ts +16 -0
- package/dist/types/index/index.types.d.ts.map +1 -0
- package/dist/types/index/index.types.js +2 -0
- package/dist/types/index/index.types.js.map +1 -0
- package/dist/types/index/indexing.types.d.ts +9 -0
- package/dist/types/index/indexing.types.d.ts.map +1 -0
- package/dist/types/index/indexing.types.js +2 -0
- package/dist/types/index/indexing.types.js.map +1 -0
- package/dist/types/projectInfo.types.d.ts +16 -0
- package/dist/types/projectInfo.types.d.ts.map +1 -0
- package/dist/types/projectInfo.types.js +2 -0
- package/dist/types/projectInfo.types.js.map +1 -0
- package/dist/types/updatePlan.types.d.ts +34 -0
- package/dist/types/updatePlan.types.d.ts.map +1 -0
- package/dist/types/updatePlan.types.js +18 -0
- package/dist/types/updatePlan.types.js.map +1 -0
- package/dist/utils/utils.d.ts +2 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +6 -0
- package/dist/utils/utils.js.map +1 -0
- package/dist/utils/workspace.d.ts +13 -0
- package/dist/utils/workspace.d.ts.map +1 -0
- package/dist/utils/workspace.js +92 -0
- package/dist/utils/workspace.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
import { createApplyPatchImpl } from "./applyPatch.impl.js";
|
|
5
|
+
const enoent = (message) => {
|
|
6
|
+
const err = new Error(message);
|
|
7
|
+
err.code = "ENOENT";
|
|
8
|
+
return err;
|
|
9
|
+
};
|
|
10
|
+
const makeMemFs = () => {
|
|
11
|
+
const files = new Map();
|
|
12
|
+
return {
|
|
13
|
+
files,
|
|
14
|
+
readFile: async (absolutePath) => {
|
|
15
|
+
const key = path.resolve(absolutePath);
|
|
16
|
+
const v = files.get(key);
|
|
17
|
+
if (v === undefined)
|
|
18
|
+
throw enoent(`ENOENT: no such file, open '${absolutePath}'`);
|
|
19
|
+
return v;
|
|
20
|
+
},
|
|
21
|
+
writeFile: async (absolutePath, content) => {
|
|
22
|
+
files.set(path.resolve(absolutePath), String(content ?? ""));
|
|
23
|
+
},
|
|
24
|
+
mkdirp: async () => { },
|
|
25
|
+
rmFile: async (absolutePath) => {
|
|
26
|
+
const key = path.resolve(absolutePath);
|
|
27
|
+
if (!files.has(key))
|
|
28
|
+
throw enoent(`ENOENT: no such file, unlink '${absolutePath}'`);
|
|
29
|
+
files.delete(key);
|
|
30
|
+
},
|
|
31
|
+
stat: async (absolutePath) => {
|
|
32
|
+
const key = path.resolve(absolutePath);
|
|
33
|
+
if (!files.has(key))
|
|
34
|
+
throw enoent(`ENOENT: no such file, stat '${absolutePath}'`);
|
|
35
|
+
return { isDirectory: () => false };
|
|
36
|
+
},
|
|
37
|
+
safeReadDir: async () => [],
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
test('apply_patch: Update + Move writes new path and deletes old path', async () => {
|
|
41
|
+
const workspaceRoot = path.resolve("C:\\virtual-workspace");
|
|
42
|
+
const fs = makeMemFs();
|
|
43
|
+
const applyPatch = createApplyPatchImpl({ workspaceRoot, fs });
|
|
44
|
+
fs.files.set(path.resolve(workspaceRoot, "app/a/page.config.ts"), "export const config = { elements: [] };\n");
|
|
45
|
+
const res = await applyPatch(`*** Begin Patch
|
|
46
|
+
*** Update File: app/a/page.config.ts
|
|
47
|
+
*** Move to: app/b/page.config.ts
|
|
48
|
+
@@
|
|
49
|
+
export const config = { elements: [] };
|
|
50
|
+
*** End Patch
|
|
51
|
+
`);
|
|
52
|
+
assert.equal(res.success, true);
|
|
53
|
+
assert.equal(res.changed, true);
|
|
54
|
+
assert.equal(fs.files.has(path.resolve(workspaceRoot, "app/a/page.config.ts")), false);
|
|
55
|
+
assert.equal(fs.files.get(path.resolve(workspaceRoot, "app/b/page.config.ts")), "export const config = { elements: [] };\n");
|
|
56
|
+
});
|
|
57
|
+
test("apply_patch: context-only Update succeeds as no-op", async () => {
|
|
58
|
+
const workspaceRoot = path.resolve("C:\\virtual-workspace");
|
|
59
|
+
const fs = makeMemFs();
|
|
60
|
+
const applyPatch = createApplyPatchImpl({ workspaceRoot, fs });
|
|
61
|
+
fs.files.set(path.resolve(workspaceRoot, "app/a/page.config.ts"), "export const config = { elements: [] };\n");
|
|
62
|
+
const res = await applyPatch(`*** Begin Patch
|
|
63
|
+
*** Update File: app/a/page.config.ts
|
|
64
|
+
@@
|
|
65
|
+
export const config = { elements: [] };
|
|
66
|
+
*** End Patch
|
|
67
|
+
`);
|
|
68
|
+
assert.equal(res.success, true);
|
|
69
|
+
assert.equal(res.changed, false);
|
|
70
|
+
assert.equal(fs.files.get(path.resolve(workspaceRoot, "app/a/page.config.ts")), "export const config = { elements: [] };\n");
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=applyPatch.impl.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyPatch.impl.test.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/applyPatch.impl.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAM5D,MAAM,MAAM,GAAG,CAAC,OAAe,EAAE,EAAE;IACjC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAA0B,CAAC;IACxD,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC;IACpB,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,GAA6D,EAAE;IAC/E,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,OAAO;QACL,KAAK;QACL,QAAQ,EAAE,KAAK,EAAE,YAAoB,EAAE,EAAE;YACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YACvC,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,SAAS;gBAAE,MAAM,MAAM,CAAC,+BAA+B,YAAY,GAAG,CAAC,CAAC;YAClF,OAAO,CAAC,CAAC;QACX,CAAC;QACD,SAAS,EAAE,KAAK,EAAE,YAAoB,EAAE,OAAe,EAAE,EAAE;YACzD,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;QACtB,MAAM,EAAE,KAAK,EAAE,YAAoB,EAAE,EAAE;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,MAAM,MAAM,CAAC,iCAAiC,YAAY,GAAG,CAAC,CAAC;YACpF,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,IAAI,EAAE,KAAK,EAAE,YAAoB,EAAE,EAAE;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,MAAM,MAAM,CAAC,+BAA+B,YAAY,GAAG,CAAC,CAAC;YAClF,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;QACtC,CAAC;QACD,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE;KAC5B,CAAC;AACJ,CAAC,CAAC;AAEF,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;IACjF,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC5D,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IACvB,MAAM,UAAU,GAAG,oBAAoB,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC;IAE/D,EAAE,CAAC,KAAK,CAAC,GAAG,CACV,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,sBAAsB,CAAC,EACnD,2CAA2C,CAC5C,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC;;;;;;CAM9B,CAAC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,CAAE,GAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACvF,MAAM,CAAC,KAAK,CACV,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC,EACjE,2CAA2C,CAC5C,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;IACpE,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC5D,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IACvB,MAAM,UAAU,GAAG,oBAAoB,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC;IAE/D,EAAE,CAAC,KAAK,CAAC,GAAG,CACV,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,sBAAsB,CAAC,EACnD,2CAA2C,CAC5C,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC;;;;;CAK9B,CAAC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,CAAE,GAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC1C,MAAM,CAAC,KAAK,CACV,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC,EACjE,2CAA2C,CAC5C,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import assert from \"node:assert/strict\";\nimport path from \"node:path\";\nimport test from \"node:test\";\nimport { createApplyPatchImpl } from \"./applyPatch.impl.js\";\n\ntype MemFs = {\n files: Map<string, string>;\n};\n\nconst enoent = (message: string) => {\n const err = new Error(message) as NodeJS.ErrnoException;\n err.code = \"ENOENT\";\n return err;\n};\n\nconst makeMemFs = (): MemFs & Parameters<typeof createApplyPatchImpl>[0][\"fs\"] => {\n const files = new Map<string, string>();\n\n return {\n files,\n readFile: async (absolutePath: string) => {\n const key = path.resolve(absolutePath);\n const v = files.get(key);\n if (v === undefined) throw enoent(`ENOENT: no such file, open '${absolutePath}'`);\n return v;\n },\n writeFile: async (absolutePath: string, content: string) => {\n files.set(path.resolve(absolutePath), String(content ?? \"\"));\n },\n mkdirp: async () => {},\n rmFile: async (absolutePath: string) => {\n const key = path.resolve(absolutePath);\n if (!files.has(key)) throw enoent(`ENOENT: no such file, unlink '${absolutePath}'`);\n files.delete(key);\n },\n stat: async (absolutePath: string) => {\n const key = path.resolve(absolutePath);\n if (!files.has(key)) throw enoent(`ENOENT: no such file, stat '${absolutePath}'`);\n return { isDirectory: () => false };\n },\n safeReadDir: async () => [],\n };\n};\n\ntest('apply_patch: Update + Move writes new path and deletes old path', async () => {\n const workspaceRoot = path.resolve(\"C:\\\\virtual-workspace\");\n const fs = makeMemFs();\n const applyPatch = createApplyPatchImpl({ workspaceRoot, fs });\n\n fs.files.set(\n path.resolve(workspaceRoot, \"app/a/page.config.ts\"),\n \"export const config = { elements: [] };\\n\",\n );\n\n const res = await applyPatch(`*** Begin Patch\n*** Update File: app/a/page.config.ts\n*** Move to: app/b/page.config.ts\n@@\n export const config = { elements: [] };\n*** End Patch\n`);\n\n assert.equal(res.success, true);\n assert.equal((res as any).changed, true);\n assert.equal(fs.files.has(path.resolve(workspaceRoot, \"app/a/page.config.ts\")), false);\n assert.equal(\n fs.files.get(path.resolve(workspaceRoot, \"app/b/page.config.ts\")),\n \"export const config = { elements: [] };\\n\",\n );\n});\n\ntest(\"apply_patch: context-only Update succeeds as no-op\", async () => {\n const workspaceRoot = path.resolve(\"C:\\\\virtual-workspace\");\n const fs = makeMemFs();\n const applyPatch = createApplyPatchImpl({ workspaceRoot, fs });\n\n fs.files.set(\n path.resolve(workspaceRoot, \"app/a/page.config.ts\"),\n \"export const config = { elements: [] };\\n\",\n );\n\n const res = await applyPatch(`*** Begin Patch\n*** Update File: app/a/page.config.ts\n@@\n export const config = { elements: [] };\n*** End Patch\n`);\n\n assert.equal(res.success, true);\n assert.equal((res as any).changed, false);\n assert.equal(\n fs.files.get(path.resolve(workspaceRoot, \"app/a/page.config.ts\")),\n \"export const config = { elements: [] };\\n\",\n );\n});\n"]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { type SearchDeps } from "./search.impl.js";
|
|
2
|
+
export { DEFAULT_NOT_FOUND_RESPONSE } from "./workspaceDeps.js";
|
|
3
|
+
export type { CoreDirent, CoreFs, WorkspaceDeps, } from "./workspaceDeps.js";
|
|
4
|
+
export { createApplyPatchImpl } from "./applyPatch.impl.js";
|
|
5
|
+
export { createListDirImpl } from "./listDir.impl.js";
|
|
6
|
+
export { createReadFileImpl } from "./readFile.impl.js";
|
|
7
|
+
export { createSearchImpl, type SearchDeps, type SearchResult, } from "./search.impl.js";
|
|
8
|
+
export { createWriteFileImpl } from "./writeFile.impl.js";
|
|
9
|
+
export declare const createWorkspaceToolImpls: (deps: SearchDeps) => {
|
|
10
|
+
readFileImpl: (filePath: string, startLine?: number, endLine?: number) => Promise<string>;
|
|
11
|
+
writeFileImpl: (filePath: string, content: string) => Promise<{
|
|
12
|
+
success: boolean;
|
|
13
|
+
rejected: boolean;
|
|
14
|
+
error: string;
|
|
15
|
+
allowed: string[];
|
|
16
|
+
rule?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
success: boolean;
|
|
19
|
+
rejected: boolean;
|
|
20
|
+
error: string;
|
|
21
|
+
allowed?: undefined;
|
|
22
|
+
rule?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
success: boolean;
|
|
25
|
+
rejected: boolean;
|
|
26
|
+
error: string;
|
|
27
|
+
rule: string;
|
|
28
|
+
allowed?: undefined;
|
|
29
|
+
} | {
|
|
30
|
+
success: boolean;
|
|
31
|
+
rejected?: undefined;
|
|
32
|
+
error?: undefined;
|
|
33
|
+
allowed?: undefined;
|
|
34
|
+
rule?: undefined;
|
|
35
|
+
}>;
|
|
36
|
+
listDirImpl: (dirPath: string, depth: number) => Promise<string>;
|
|
37
|
+
searchImpl: (searchQuery: string) => Promise<import("./search.impl.js").SearchResult[]>;
|
|
38
|
+
applyPatchImpl: (patchString: string) => Promise<{
|
|
39
|
+
success: boolean;
|
|
40
|
+
rejected: boolean;
|
|
41
|
+
error: string;
|
|
42
|
+
allowed: string[];
|
|
43
|
+
rule?: undefined;
|
|
44
|
+
changed?: undefined;
|
|
45
|
+
warnings?: undefined;
|
|
46
|
+
debug?: undefined;
|
|
47
|
+
} | {
|
|
48
|
+
success: boolean;
|
|
49
|
+
rejected: boolean;
|
|
50
|
+
error: string;
|
|
51
|
+
allowed?: undefined;
|
|
52
|
+
rule?: undefined;
|
|
53
|
+
changed?: undefined;
|
|
54
|
+
warnings?: undefined;
|
|
55
|
+
debug?: undefined;
|
|
56
|
+
} | {
|
|
57
|
+
success: boolean;
|
|
58
|
+
rejected: boolean;
|
|
59
|
+
error: string;
|
|
60
|
+
rule: string;
|
|
61
|
+
allowed?: undefined;
|
|
62
|
+
changed?: undefined;
|
|
63
|
+
warnings?: undefined;
|
|
64
|
+
debug?: undefined;
|
|
65
|
+
} | {
|
|
66
|
+
success: boolean;
|
|
67
|
+
changed: boolean;
|
|
68
|
+
warnings: string[] | undefined;
|
|
69
|
+
rejected?: undefined;
|
|
70
|
+
error?: undefined;
|
|
71
|
+
allowed?: undefined;
|
|
72
|
+
rule?: undefined;
|
|
73
|
+
debug?: undefined;
|
|
74
|
+
} | {
|
|
75
|
+
success: boolean;
|
|
76
|
+
error: string;
|
|
77
|
+
debug: {
|
|
78
|
+
files: {
|
|
79
|
+
path: string;
|
|
80
|
+
head: string;
|
|
81
|
+
}[];
|
|
82
|
+
} | undefined;
|
|
83
|
+
rejected?: undefined;
|
|
84
|
+
allowed?: undefined;
|
|
85
|
+
rule?: undefined;
|
|
86
|
+
changed?: undefined;
|
|
87
|
+
warnings?: undefined;
|
|
88
|
+
}>;
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=factories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factories.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/factories.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EACV,UAAU,EACV,MAAM,EACN,aAAa,GACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,eAAO,MAAM,wBAAwB,GAAI,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAcxD,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createApplyPatchImpl } from "./applyPatch.impl.js";
|
|
2
|
+
import { createListDirImpl } from "./listDir.impl.js";
|
|
3
|
+
import { createReadFileImpl } from "./readFile.impl.js";
|
|
4
|
+
import { createSearchImpl } from "./search.impl.js";
|
|
5
|
+
import { createWriteFileImpl } from "./writeFile.impl.js";
|
|
6
|
+
export { DEFAULT_NOT_FOUND_RESPONSE } from "./workspaceDeps.js";
|
|
7
|
+
export { createApplyPatchImpl } from "./applyPatch.impl.js";
|
|
8
|
+
export { createListDirImpl } from "./listDir.impl.js";
|
|
9
|
+
export { createReadFileImpl } from "./readFile.impl.js";
|
|
10
|
+
export { createSearchImpl, } from "./search.impl.js";
|
|
11
|
+
export { createWriteFileImpl } from "./writeFile.impl.js";
|
|
12
|
+
export const createWorkspaceToolImpls = (deps) => {
|
|
13
|
+
const readFileImpl = createReadFileImpl(deps);
|
|
14
|
+
const writeFileImpl = createWriteFileImpl(deps);
|
|
15
|
+
const listDirImpl = createListDirImpl(deps);
|
|
16
|
+
const searchImpl = createSearchImpl(deps);
|
|
17
|
+
const applyPatchImpl = createApplyPatchImpl(deps);
|
|
18
|
+
return {
|
|
19
|
+
readFileImpl,
|
|
20
|
+
writeFileImpl,
|
|
21
|
+
listDirImpl,
|
|
22
|
+
searchImpl,
|
|
23
|
+
applyPatchImpl,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=factories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factories.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/factories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAmB,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAOhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,gBAAgB,GAGjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,IAAgB,EAAE,EAAE;IAC3D,MAAM,YAAY,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,cAAc,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAElD,OAAO;QACL,YAAY;QACZ,aAAa;QACb,WAAW;QACX,UAAU;QACV,cAAc;KACf,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { createApplyPatchImpl } from \"./applyPatch.impl.js\";\nimport { createListDirImpl } from \"./listDir.impl.js\";\nimport { createReadFileImpl } from \"./readFile.impl.js\";\nimport { createSearchImpl, type SearchDeps } from \"./search.impl.js\";\nimport { createWriteFileImpl } from \"./writeFile.impl.js\";\n\nexport { DEFAULT_NOT_FOUND_RESPONSE } from \"./workspaceDeps.js\";\nexport type {\n CoreDirent,\n CoreFs,\n WorkspaceDeps,\n} from \"./workspaceDeps.js\";\n\nexport { createApplyPatchImpl } from \"./applyPatch.impl.js\";\nexport { createListDirImpl } from \"./listDir.impl.js\";\nexport { createReadFileImpl } from \"./readFile.impl.js\";\nexport {\n createSearchImpl,\n type SearchDeps,\n type SearchResult,\n} from \"./search.impl.js\";\nexport { createWriteFileImpl } from \"./writeFile.impl.js\";\n\nexport const createWorkspaceToolImpls = (deps: SearchDeps) => {\n const readFileImpl = createReadFileImpl(deps);\n const writeFileImpl = createWriteFileImpl(deps);\n const listDirImpl = createListDirImpl(deps);\n const searchImpl = createSearchImpl(deps);\n const applyPatchImpl = createApplyPatchImpl(deps);\n\n return {\n readFileImpl,\n writeFileImpl,\n listDirImpl,\n searchImpl,\n applyPatchImpl,\n };\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listDir.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/listDir.impl.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8B,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEpF,eAAO,MAAM,iBAAiB,GAAI,MAAM,aAAa,MAKrC,SAAS,MAAM,EAAE,OAAO,MAAM,oBAyC7C,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { toWorkspacePath } from "../helpers/fileSystem.helpers.js";
|
|
3
|
+
import { DEFAULT_NOT_FOUND_RESPONSE } from "./workspaceDeps.js";
|
|
4
|
+
export const createListDirImpl = (deps) => {
|
|
5
|
+
const { workspaceRoot, fs } = deps;
|
|
6
|
+
const MAX_LINES = 500;
|
|
7
|
+
return async (dirPath, depth) => {
|
|
8
|
+
const fullPath = toWorkspacePath(workspaceRoot, dirPath);
|
|
9
|
+
console.log("Tool list_dir", { path: fullPath, depth });
|
|
10
|
+
const effectiveDepth = Math.max(1, Math.min(3, depth ?? 1));
|
|
11
|
+
try {
|
|
12
|
+
const st = await fs.stat(fullPath);
|
|
13
|
+
if (!st.isDirectory())
|
|
14
|
+
return `not a directory: ${dirPath}`;
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
const code = err?.code;
|
|
18
|
+
if (code === "ENOENT")
|
|
19
|
+
return DEFAULT_NOT_FOUND_RESPONSE;
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
const lines = [];
|
|
23
|
+
const walk = async (dir, currentDepth, prefix) => {
|
|
24
|
+
if (lines.length >= MAX_LINES)
|
|
25
|
+
return;
|
|
26
|
+
const entries = await fs.safeReadDir(dir);
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
if (lines.length >= MAX_LINES)
|
|
29
|
+
return;
|
|
30
|
+
if (!entry.isDirectory() && !entry.isFile())
|
|
31
|
+
continue;
|
|
32
|
+
const isDir = entry.isDirectory();
|
|
33
|
+
const displayName = isDir ? `/${entry.name}` : entry.name;
|
|
34
|
+
const line = prefix ? `${prefix}${displayName}` : displayName;
|
|
35
|
+
lines.push(line);
|
|
36
|
+
if (isDir && currentDepth < effectiveDepth) {
|
|
37
|
+
await walk(path.join(dir, entry.name), currentDepth + 1, `${prefix} `);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
await walk(fullPath, 1, "");
|
|
42
|
+
if (lines.length >= MAX_LINES)
|
|
43
|
+
lines.push("... truncated ...");
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=listDir.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listDir.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/listDir.impl.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAsB,MAAM,oBAAoB,CAAC;AAEpF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAmB,EAAE,EAAE;IACvD,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAEnC,MAAM,SAAS,GAAG,GAAG,CAAC;IAEtB,OAAO,KAAK,EAAE,OAAe,EAAE,KAAa,EAAE,EAAE;QAC9C,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QAExD,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAc,CAAC;QAEzE,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE;gBAAE,OAAO,oBAAoB,OAAO,EAAE,CAAC;QAC9D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAAoC,EAAE,IAAI,CAAC;YACzD,IAAI,IAAI,KAAK,QAAQ;gBAAE,OAAO,0BAA0B,CAAC;YACzD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,MAAM,IAAI,GAAG,KAAK,EAAE,GAAW,EAAE,YAAoB,EAAE,MAAc,EAAE,EAAE;YACvE,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS;gBAAE,OAAO;YACtC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAE1C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS;oBAAE,OAAO;gBACtC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;oBAAE,SAAS;gBAEtD,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;gBAClC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;gBAC9D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEjB,IAAI,KAAK,IAAI,YAAY,GAAG,cAAc,EAAE,CAAC;oBAC3C,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,CAAC,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC;gBAC1E,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAE5B,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC/D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import path from \"node:path\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport { DEFAULT_NOT_FOUND_RESPONSE, type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createListDirImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n const MAX_LINES = 500;\n\n return async (dirPath: string, depth: number) => {\n const fullPath = toWorkspacePath(workspaceRoot, dirPath);\n console.log(\"Tool list_dir\", { path: fullPath, depth });\n\n const effectiveDepth = Math.max(1, Math.min(3, depth ?? 1)) as 1 | 2 | 3;\n\n try {\n const st = await fs.stat(fullPath);\n if (!st.isDirectory()) return `not a directory: ${dirPath}`;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return DEFAULT_NOT_FOUND_RESPONSE;\n throw err;\n }\n\n const lines: string[] = [];\n\n const walk = async (dir: string, currentDepth: number, prefix: string) => {\n if (lines.length >= MAX_LINES) return;\n const entries = await fs.safeReadDir(dir);\n\n for (const entry of entries) {\n if (lines.length >= MAX_LINES) return;\n if (!entry.isDirectory() && !entry.isFile()) continue;\n\n const isDir = entry.isDirectory();\n const displayName = isDir ? `/${entry.name}` : entry.name;\n const line = prefix ? `${prefix}${displayName}` : displayName;\n lines.push(line);\n\n if (isDir && currentDepth < effectiveDepth) {\n await walk(path.join(dir, entry.name), currentDepth + 1, `${prefix} `);\n }\n }\n };\n\n await walk(fullPath, 1, \"\");\n\n if (lines.length >= MAX_LINES) lines.push(\"... truncated ...\");\n return lines.join(\"\\n\");\n };\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readFile.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/readFile.impl.ts"],"names":[],"mappings":"AAEA,OAAO,EAA8B,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEpF,eAAO,MAAM,kBAAkB,GAAI,MAAM,aAAa,MAGtC,UAAU,MAAM,EAAE,YAAY,MAAM,EAAE,UAAU,MAAM,oBAgBrE,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { toWorkspacePath } from "../helpers/fileSystem.helpers.js";
|
|
2
|
+
import { sliceByLines } from "../helpers/format.helpers.js";
|
|
3
|
+
import { DEFAULT_NOT_FOUND_RESPONSE } from "./workspaceDeps.js";
|
|
4
|
+
export const createReadFileImpl = (deps) => {
|
|
5
|
+
const { workspaceRoot, fs } = deps;
|
|
6
|
+
return async (filePath, startLine, endLine) => {
|
|
7
|
+
const fullPath = toWorkspacePath(workspaceRoot, filePath);
|
|
8
|
+
console.log("Tool read_file", { path: fullPath });
|
|
9
|
+
try {
|
|
10
|
+
await fs.stat(fullPath);
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
const code = err?.code;
|
|
14
|
+
if (code === "ENOENT")
|
|
15
|
+
return DEFAULT_NOT_FOUND_RESPONSE;
|
|
16
|
+
console.log("Tool read_file failed", err, { path: fullPath });
|
|
17
|
+
throw err;
|
|
18
|
+
}
|
|
19
|
+
const content = await fs.readFile(fullPath);
|
|
20
|
+
return sliceByLines(content, startLine, endLine);
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=readFile.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readFile.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/readFile.impl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAsB,MAAM,oBAAoB,CAAC;AAEpF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAmB,EAAE,EAAE;IACxD,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAEnC,OAAO,KAAK,EAAE,QAAgB,EAAE,SAAkB,EAAE,OAAgB,EAAE,EAAE;QACtE,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAAoC,EAAE,IAAI,CAAC;YACzD,IAAI,IAAI,KAAK,QAAQ;gBAAE,OAAO,0BAA0B,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC9D,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport { sliceByLines } from \"../helpers/format.helpers.js\";\nimport { DEFAULT_NOT_FOUND_RESPONSE, type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createReadFileImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (filePath: string, startLine?: number, endLine?: number) => {\n const fullPath = toWorkspacePath(workspaceRoot, filePath);\n console.log(\"Tool read_file\", { path: fullPath });\n\n try {\n await fs.stat(fullPath);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code === \"ENOENT\") return DEFAULT_NOT_FOUND_RESPONSE;\n console.log(\"Tool read_file failed\", err, { path: fullPath });\n throw err;\n }\n\n const content = await fs.readFile(fullPath);\n return sliceByLines(content, startLine, endLine);\n };\n};\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type WorkspaceDeps } from "./workspaceDeps.js";
|
|
2
|
+
export type SearchResult = {
|
|
3
|
+
path: string;
|
|
4
|
+
content: string;
|
|
5
|
+
};
|
|
6
|
+
export type SearchDeps = WorkspaceDeps & {
|
|
7
|
+
execRg?: (input: {
|
|
8
|
+
query: string;
|
|
9
|
+
cwd: string;
|
|
10
|
+
maxCount: number;
|
|
11
|
+
}) => Promise<{
|
|
12
|
+
code: number;
|
|
13
|
+
stdout: string;
|
|
14
|
+
stderr: string;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
17
|
+
export declare const createSearchImpl: (deps: SearchDeps) => (searchQuery: string) => Promise<SearchResult[]>;
|
|
18
|
+
//# sourceMappingURL=search.impl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/search.impl.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG;IACvC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE;QACf,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE,CAAC;AA0CF,eAAO,MAAM,gBAAgB,GAAI,MAAM,UAAU,MAIjC,aAAa,MAAM,KAAG,OAAO,CAAC,YAAY,EAAE,CAwC3D,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
const defaultExecRg = async ({ query, cwd, maxCount }) => {
|
|
3
|
+
return await new Promise((resolve, reject) => {
|
|
4
|
+
const child = spawn("rg", [
|
|
5
|
+
"-n",
|
|
6
|
+
"--no-heading",
|
|
7
|
+
"--color",
|
|
8
|
+
"never",
|
|
9
|
+
"--max-count",
|
|
10
|
+
String(maxCount),
|
|
11
|
+
query,
|
|
12
|
+
".",
|
|
13
|
+
], { cwd });
|
|
14
|
+
let stdout = "";
|
|
15
|
+
let stderr = "";
|
|
16
|
+
child.stdout.setEncoding("utf8");
|
|
17
|
+
child.stderr.setEncoding("utf8");
|
|
18
|
+
child.stdout.on("data", (chunk) => {
|
|
19
|
+
stdout += chunk;
|
|
20
|
+
});
|
|
21
|
+
child.stderr.on("data", (chunk) => {
|
|
22
|
+
stderr += chunk;
|
|
23
|
+
});
|
|
24
|
+
child.on("error", (err) => {
|
|
25
|
+
reject(err);
|
|
26
|
+
});
|
|
27
|
+
child.on("close", (code) => {
|
|
28
|
+
resolve({ code: code ?? 0, stdout, stderr });
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
export const createSearchImpl = (deps) => {
|
|
33
|
+
const { workspaceRoot } = deps;
|
|
34
|
+
const execRg = deps.execRg ?? defaultExecRg;
|
|
35
|
+
return async (searchQuery) => {
|
|
36
|
+
const trimmed = (searchQuery ?? "").trim();
|
|
37
|
+
console.log("Tool search", { query: trimmed });
|
|
38
|
+
if (!trimmed)
|
|
39
|
+
return [];
|
|
40
|
+
try {
|
|
41
|
+
const { code, stdout, stderr } = await execRg({
|
|
42
|
+
query: trimmed,
|
|
43
|
+
cwd: workspaceRoot,
|
|
44
|
+
maxCount: 20,
|
|
45
|
+
});
|
|
46
|
+
if (code === 1)
|
|
47
|
+
return [];
|
|
48
|
+
if (code !== 0) {
|
|
49
|
+
throw new Error(`rg exited with code ${code}${stderr ? `: ${stderr.trim()}` : ""}`);
|
|
50
|
+
}
|
|
51
|
+
const lines = stdout
|
|
52
|
+
.replace(/\r\n/g, "\n")
|
|
53
|
+
.split("\n")
|
|
54
|
+
.filter(Boolean)
|
|
55
|
+
.slice(0, 20);
|
|
56
|
+
return lines.map((line) => {
|
|
57
|
+
const first = line.indexOf(":");
|
|
58
|
+
const second = first === -1 ? -1 : line.indexOf(":", first + 1);
|
|
59
|
+
if (first === -1 || second === -1)
|
|
60
|
+
return { path: line, content: "" };
|
|
61
|
+
const file = line.slice(0, first);
|
|
62
|
+
const lineNo = line.slice(first + 1, second);
|
|
63
|
+
const content = line.slice(second + 1);
|
|
64
|
+
return { path: `${file}:${lineNo}`, content };
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
69
|
+
console.log("Tool search failed", err, { query: trimmed, message });
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=search.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/search.impl.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport type SearchResult = { path: string; content: string };\n\nexport type SearchDeps = WorkspaceDeps & {\n execRg?: (input: {\n query: string;\n cwd: string;\n maxCount: number;\n }) => Promise<{ code: number; stdout: string; stderr: string }>;\n};\n\nconst defaultExecRg: NonNullable<SearchDeps[\"execRg\"]> = async ({ query, cwd, maxCount }) => {\n return await new Promise((resolve, reject) => {\n const child = spawn(\n \"rg\",\n [\n \"-n\",\n \"--no-heading\",\n \"--color\",\n \"never\",\n \"--max-count\",\n String(maxCount),\n query,\n \".\",\n ],\n { cwd },\n );\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.setEncoding(\"utf8\");\n child.stderr.setEncoding(\"utf8\");\n\n child.stdout.on(\"data\", (chunk) => {\n stdout += chunk;\n });\n child.stderr.on(\"data\", (chunk) => {\n stderr += chunk;\n });\n\n child.on(\"error\", (err) => {\n reject(err);\n });\n\n child.on(\"close\", (code) => {\n resolve({ code: code ?? 0, stdout, stderr });\n });\n });\n};\n\nexport const createSearchImpl = (deps: SearchDeps) => {\n const { workspaceRoot } = deps;\n const execRg = deps.execRg ?? defaultExecRg;\n\n return async (searchQuery: string): Promise<SearchResult[]> => {\n const trimmed = (searchQuery ?? \"\").trim();\n console.log(\"Tool search\", { query: trimmed });\n\n if (!trimmed) return [];\n\n try {\n const { code, stdout, stderr } = await execRg({\n query: trimmed,\n cwd: workspaceRoot,\n maxCount: 20,\n });\n\n if (code === 1) return [];\n if (code !== 0) {\n throw new Error(`rg exited with code ${code}${stderr ? `: ${stderr.trim()}` : \"\"}`);\n }\n\n const lines = stdout\n .replace(/\\r\\n/g, \"\\n\")\n .split(\"\\n\")\n .filter(Boolean)\n .slice(0, 20);\n\n return lines.map((line): SearchResult => {\n const first = line.indexOf(\":\");\n const second = first === -1 ? -1 : line.indexOf(\":\", first + 1);\n if (first === -1 || second === -1) return { path: line, content: \"\" };\n\n const file = line.slice(0, first);\n const lineNo = line.slice(first + 1, second);\n const content = line.slice(second + 1);\n return { path: `${file}:${lineNo}`, content };\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.log(\"Tool search failed\", err, { query: trimmed, message });\n return [];\n }\n };\n};\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type LogMeta = Record<string, unknown>;
|
|
2
|
+
export type CoreDirent = {
|
|
3
|
+
name: string;
|
|
4
|
+
isDirectory: () => boolean;
|
|
5
|
+
isFile: () => boolean;
|
|
6
|
+
};
|
|
7
|
+
export type CoreFs = {
|
|
8
|
+
readFile: (absolutePath: string) => Promise<string>;
|
|
9
|
+
writeFile: (absolutePath: string, content: string) => Promise<void>;
|
|
10
|
+
mkdirp: (absoluteDir: string) => Promise<void>;
|
|
11
|
+
rmFile: (absolutePath: string) => Promise<void>;
|
|
12
|
+
stat: (absolutePath: string) => Promise<{
|
|
13
|
+
isDirectory: () => boolean;
|
|
14
|
+
}>;
|
|
15
|
+
safeReadDir: (absoluteDir: string) => Promise<CoreDirent[]>;
|
|
16
|
+
};
|
|
17
|
+
export type WorkspaceDeps = {
|
|
18
|
+
workspaceRoot: string;
|
|
19
|
+
fs: CoreFs;
|
|
20
|
+
};
|
|
21
|
+
export declare const DEFAULT_NOT_FOUND_RESPONSE = "not found";
|
|
22
|
+
//# sourceMappingURL=workspaceDeps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceDeps.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/workspaceDeps.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B,MAAM,EAAE,MAAM,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,WAAW,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,eAAO,MAAM,0BAA0B,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspaceDeps.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/workspaceDeps.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CAAC","sourcesContent":["export type LogMeta = Record<string, unknown>;\n\nexport type CoreDirent = {\n name: string;\n isDirectory: () => boolean;\n isFile: () => boolean;\n};\n\nexport type CoreFs = {\n readFile: (absolutePath: string) => Promise<string>;\n writeFile: (absolutePath: string, content: string) => Promise<void>;\n mkdirp: (absoluteDir: string) => Promise<void>;\n rmFile: (absolutePath: string) => Promise<void>;\n stat: (absolutePath: string) => Promise<{ isDirectory: () => boolean }>;\n safeReadDir: (absoluteDir: string) => Promise<CoreDirent[]>;\n};\n\nexport type WorkspaceDeps = {\n workspaceRoot: string;\n fs: CoreFs;\n};\n\nexport const DEFAULT_NOT_FOUND_RESPONSE = \"not found\";\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type WorkspaceDeps } from "./workspaceDeps.js";
|
|
2
|
+
export declare const createWriteFileImpl: (deps: WorkspaceDeps) => (filePath: string, content: string) => Promise<{
|
|
3
|
+
success: boolean;
|
|
4
|
+
rejected: boolean;
|
|
5
|
+
error: string;
|
|
6
|
+
allowed: string[];
|
|
7
|
+
rule?: undefined;
|
|
8
|
+
} | {
|
|
9
|
+
success: boolean;
|
|
10
|
+
rejected: boolean;
|
|
11
|
+
error: string;
|
|
12
|
+
allowed?: undefined;
|
|
13
|
+
rule?: undefined;
|
|
14
|
+
} | {
|
|
15
|
+
success: boolean;
|
|
16
|
+
rejected: boolean;
|
|
17
|
+
error: string;
|
|
18
|
+
rule: string;
|
|
19
|
+
allowed?: undefined;
|
|
20
|
+
} | {
|
|
21
|
+
success: boolean;
|
|
22
|
+
rejected?: undefined;
|
|
23
|
+
error?: undefined;
|
|
24
|
+
allowed?: undefined;
|
|
25
|
+
rule?: undefined;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=writeFile.impl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeFile.impl.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/writeFile.impl.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,mBAAmB,GAAI,MAAM,aAAa,MAGvC,UAAU,MAAM,EAAE,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;EA8DhD,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { toWorkspacePath } from "../helpers/fileSystem.helpers.js";
|
|
3
|
+
import { isAllowedRouteFilePath, isPageTsxPath, matchesPageTsxTemplate, normalizeFsPathForPolicy, PAGE_TSX_TEMPLATE, } from "../helpers/nextRouteFilePolicy.js";
|
|
4
|
+
export const createWriteFileImpl = (deps) => {
|
|
5
|
+
const { workspaceRoot, fs } = deps;
|
|
6
|
+
return async (filePath, content) => {
|
|
7
|
+
const policyPath = normalizeFsPathForPolicy(filePath);
|
|
8
|
+
if (!isAllowedRouteFilePath(policyPath)) {
|
|
9
|
+
return {
|
|
10
|
+
success: false,
|
|
11
|
+
rejected: true,
|
|
12
|
+
error: `write_file rejected: only route files named "page.tsx" or "page.config.ts" may be written.\n` +
|
|
13
|
+
`Got: "${policyPath}"`,
|
|
14
|
+
allowed: Array.from(["page.tsx", "page.config.ts"]),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const fullPath = toWorkspacePath(workspaceRoot, filePath);
|
|
18
|
+
console.log("Tool write_file", { path: fullPath });
|
|
19
|
+
if (isPageTsxPath(policyPath)) {
|
|
20
|
+
let exists = false;
|
|
21
|
+
try {
|
|
22
|
+
await fs.stat(fullPath);
|
|
23
|
+
exists = true;
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
const code = err?.code;
|
|
27
|
+
if (code && code !== "ENOENT") {
|
|
28
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
29
|
+
return {
|
|
30
|
+
success: false,
|
|
31
|
+
rejected: true,
|
|
32
|
+
error: `write_file rejected: could not check existing file "${policyPath}": ${message}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (exists) {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
rejected: true,
|
|
40
|
+
error: `write_file rejected: updates to "page.tsx" are not allowed for any route. ` +
|
|
41
|
+
`Only add (create) or delete is allowed, and once created it must never be edited.\n` +
|
|
42
|
+
`Path: "${policyPath}"`,
|
|
43
|
+
rule: "page.tsx is immutable after creation",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (!matchesPageTsxTemplate(content)) {
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
rejected: true,
|
|
50
|
+
error: `write_file rejected: new "page.tsx" must match the exact required template (byte-for-byte).\n` +
|
|
51
|
+
`Path: "${policyPath}"\n` +
|
|
52
|
+
`Expected:\n${PAGE_TSX_TEMPLATE}`,
|
|
53
|
+
rule: "page.tsx must match template on creation",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
await fs.mkdirp(path.dirname(fullPath));
|
|
58
|
+
await fs.writeFile(fullPath, content ?? "");
|
|
59
|
+
return { success: true };
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=writeFile.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeFile.impl.js","sourceRoot":"","sources":["../../../../src/ai/tools/implementations/writeFile.impl.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,wBAAwB,EACxB,iBAAiB,GAClB,MAAM,mCAAmC,CAAC;AAG3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAmB,EAAE,EAAE;IACzD,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC;IAEnC,OAAO,KAAK,EAAE,QAAgB,EAAE,OAAe,EAAE,EAAE;QACjD,MAAM,UAAU,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAC;QACtD,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,IAAI;gBACd,KAAK,EACH,8FAA8F;oBAC9F,SAAS,UAAU,GAAG;gBACxB,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;aACpD,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEnD,IAAI,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACxB,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,IAAI,GAAI,GAAoC,EAAE,IAAI,CAAC;gBACzD,IAAI,IAAI,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC9B,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBACjE,OAAO;wBACL,OAAO,EAAE,KAAK;wBACd,QAAQ,EAAE,IAAI;wBACd,KAAK,EAAE,uDAAuD,UAAU,MAAM,OAAO,EAAE;qBACxF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,QAAQ,EAAE,IAAI;oBACd,KAAK,EACH,4EAA4E;wBAC5E,qFAAqF;wBACrF,UAAU,UAAU,GAAG;oBACzB,IAAI,EAAE,sCAAsC;iBAC7C,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,QAAQ,EAAE,IAAI;oBACd,KAAK,EACH,+FAA+F;wBAC/F,UAAU,UAAU,KAAK;wBACzB,cAAc,iBAAiB,EAAE;oBACnC,IAAI,EAAE,0CAA0C;iBACjD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxC,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import path from \"node:path\";\nimport { toWorkspacePath } from \"../helpers/fileSystem.helpers.js\";\nimport {\n isAllowedRouteFilePath,\n isPageTsxPath,\n matchesPageTsxTemplate,\n normalizeFsPathForPolicy,\n PAGE_TSX_TEMPLATE,\n} from \"../helpers/nextRouteFilePolicy.js\";\nimport { type WorkspaceDeps } from \"./workspaceDeps.js\";\n\nexport const createWriteFileImpl = (deps: WorkspaceDeps) => {\n const { workspaceRoot, fs } = deps;\n\n return async (filePath: string, content: string) => {\n const policyPath = normalizeFsPathForPolicy(filePath);\n if (!isAllowedRouteFilePath(policyPath)) {\n return {\n success: false,\n rejected: true,\n error:\n `write_file rejected: only route files named \"page.tsx\" or \"page.config.ts\" may be written.\\n` +\n `Got: \"${policyPath}\"`,\n allowed: Array.from([\"page.tsx\", \"page.config.ts\"]),\n };\n }\n\n const fullPath = toWorkspacePath(workspaceRoot, filePath);\n console.log(\"Tool write_file\", { path: fullPath });\n\n if (isPageTsxPath(policyPath)) {\n let exists = false;\n try {\n await fs.stat(fullPath);\n exists = true;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | null)?.code;\n if (code && code !== \"ENOENT\") {\n const message = err instanceof Error ? err.message : String(err);\n return {\n success: false,\n rejected: true,\n error: `write_file rejected: could not check existing file \"${policyPath}\": ${message}`,\n };\n }\n }\n\n if (exists) {\n return {\n success: false,\n rejected: true,\n error:\n `write_file rejected: updates to \"page.tsx\" are not allowed for any route. ` +\n `Only add (create) or delete is allowed, and once created it must never be edited.\\n` +\n `Path: \"${policyPath}\"`,\n rule: \"page.tsx is immutable after creation\",\n };\n }\n\n if (!matchesPageTsxTemplate(content)) {\n return {\n success: false,\n rejected: true,\n error:\n `write_file rejected: new \"page.tsx\" must match the exact required template (byte-for-byte).\\n` +\n `Path: \"${policyPath}\"\\n` +\n `Expected:\\n${PAGE_TSX_TEMPLATE}`,\n rule: \"page.tsx must match template on creation\",\n };\n }\n }\n\n await fs.mkdirp(path.dirname(fullPath));\n await fs.writeFile(fullPath, content ?? \"\");\n return { success: true };\n };\n};\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Type } from "@google/genai";
|
|
2
|
+
export declare const ApplyPatchSchema: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
parameters: {
|
|
6
|
+
type: Type;
|
|
7
|
+
properties: {
|
|
8
|
+
patch_string: {
|
|
9
|
+
type: Type;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
required: string[];
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=applyPatch.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyPatch.schema.d.ts","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/applyPatch.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;CAe5B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Type } from "@google/genai";
|
|
2
|
+
export const ApplyPatchSchema = {
|
|
3
|
+
name: "apply_patch",
|
|
4
|
+
description: 'Applies a diff patch to a file or set of files. Policy: only "page.config.ts" and "page.tsx" route files are allowed. ' +
|
|
5
|
+
'"page.tsx" can only be added with the exact required template; updates to "page.tsx" are rejected (only add/delete).',
|
|
6
|
+
parameters: {
|
|
7
|
+
type: Type.OBJECT,
|
|
8
|
+
properties: {
|
|
9
|
+
patch_string: {
|
|
10
|
+
type: Type.STRING,
|
|
11
|
+
description: "The patch string to apply (*** Begin Patch ... *** End Patch).",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
required: ["patch_string"],
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=applyPatch.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyPatch.schema.js","sourceRoot":"","sources":["../../../../src/ai/tools/schemas/applyPatch.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,aAAa;IACnB,WAAW,EACT,wHAAwH;QACxH,sHAAsH;IACxH,UAAU,EAAE;QACV,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE;YACV,YAAY,EAAE;gBACZ,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,WAAW,EAAE,gEAAgE;aAC9E;SACF;QACD,QAAQ,EAAE,CAAC,cAAc,CAAC;KAC3B;CACF,CAAC","sourcesContent":["import { Type } from \"@google/genai\";\n\nexport const ApplyPatchSchema = {\n name: \"apply_patch\",\n description:\n 'Applies a diff patch to a file or set of files. Policy: only \"page.config.ts\" and \"page.tsx\" route files are allowed. ' +\n '\"page.tsx\" can only be added with the exact required template; updates to \"page.tsx\" are rejected (only add/delete).',\n parameters: {\n type: Type.OBJECT,\n properties: {\n patch_string: {\n type: Type.STRING,\n description: \"The patch string to apply (*** Begin Patch ... *** End Patch).\",\n },\n },\n required: [\"patch_string\"],\n },\n};\n"]}
|