kode-sdk 2.7.0
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/LICENSE +201 -0
- package/README.md +74 -0
- package/dist/core/agent/breakpoint-manager.d.ts +16 -0
- package/dist/core/agent/breakpoint-manager.js +36 -0
- package/dist/core/agent/message-queue.d.ts +26 -0
- package/dist/core/agent/message-queue.js +47 -0
- package/dist/core/agent/permission-manager.d.ts +9 -0
- package/dist/core/agent/permission-manager.js +32 -0
- package/dist/core/agent/todo-manager.d.ts +26 -0
- package/dist/core/agent/todo-manager.js +91 -0
- package/dist/core/agent/tool-runner.d.ts +9 -0
- package/dist/core/agent/tool-runner.js +45 -0
- package/dist/core/agent.d.ts +271 -0
- package/dist/core/agent.js +2334 -0
- package/dist/core/checkpointer.d.ts +96 -0
- package/dist/core/checkpointer.js +57 -0
- package/dist/core/checkpointers/file.d.ts +20 -0
- package/dist/core/checkpointers/file.js +153 -0
- package/dist/core/checkpointers/index.d.ts +3 -0
- package/dist/core/checkpointers/index.js +9 -0
- package/dist/core/checkpointers/redis.d.ts +35 -0
- package/dist/core/checkpointers/redis.js +113 -0
- package/dist/core/compression/ai-strategy.d.ts +53 -0
- package/dist/core/compression/ai-strategy.js +298 -0
- package/dist/core/compression/index.d.ts +12 -0
- package/dist/core/compression/index.js +27 -0
- package/dist/core/compression/prompts.d.ts +35 -0
- package/dist/core/compression/prompts.js +114 -0
- package/dist/core/compression/simple-strategy.d.ts +44 -0
- package/dist/core/compression/simple-strategy.js +240 -0
- package/dist/core/compression/token-estimator.d.ts +42 -0
- package/dist/core/compression/token-estimator.js +121 -0
- package/dist/core/compression/types.d.ts +140 -0
- package/dist/core/compression/types.js +9 -0
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.js +2 -0
- package/dist/core/context-manager.d.ts +115 -0
- package/dist/core/context-manager.js +107 -0
- package/dist/core/errors.d.ts +6 -0
- package/dist/core/errors.js +17 -0
- package/dist/core/events.d.ts +49 -0
- package/dist/core/events.js +312 -0
- package/dist/core/file-pool.d.ts +43 -0
- package/dist/core/file-pool.js +120 -0
- package/dist/core/hooks.d.ts +23 -0
- package/dist/core/hooks.js +71 -0
- package/dist/core/permission-modes.d.ts +31 -0
- package/dist/core/permission-modes.js +61 -0
- package/dist/core/pool.d.ts +31 -0
- package/dist/core/pool.js +87 -0
- package/dist/core/room.d.ts +15 -0
- package/dist/core/room.js +57 -0
- package/dist/core/scheduler.d.ts +33 -0
- package/dist/core/scheduler.js +58 -0
- package/dist/core/template.d.ts +69 -0
- package/dist/core/template.js +35 -0
- package/dist/core/time-bridge.d.ts +18 -0
- package/dist/core/time-bridge.js +100 -0
- package/dist/core/todo.d.ts +34 -0
- package/dist/core/todo.js +89 -0
- package/dist/core/types.d.ts +380 -0
- package/dist/core/types.js +3 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +147 -0
- package/dist/infra/provider.d.ts +144 -0
- package/dist/infra/provider.js +294 -0
- package/dist/infra/sandbox-factory.d.ts +10 -0
- package/dist/infra/sandbox-factory.js +21 -0
- package/dist/infra/sandbox.d.ts +87 -0
- package/dist/infra/sandbox.js +255 -0
- package/dist/infra/store.d.ts +154 -0
- package/dist/infra/store.js +584 -0
- package/dist/skills/index.d.ts +12 -0
- package/dist/skills/index.js +36 -0
- package/dist/skills/injector.d.ts +29 -0
- package/dist/skills/injector.js +96 -0
- package/dist/skills/loader.d.ts +59 -0
- package/dist/skills/loader.js +215 -0
- package/dist/skills/manager.d.ts +85 -0
- package/dist/skills/manager.js +221 -0
- package/dist/skills/parser.d.ts +40 -0
- package/dist/skills/parser.js +107 -0
- package/dist/skills/types.d.ts +107 -0
- package/dist/skills/types.js +7 -0
- package/dist/skills/validator.d.ts +30 -0
- package/dist/skills/validator.js +121 -0
- package/dist/store.d.ts +1 -0
- package/dist/store.js +5 -0
- package/dist/tools/bash_kill/index.d.ts +1 -0
- package/dist/tools/bash_kill/index.js +35 -0
- package/dist/tools/bash_kill/prompt.d.ts +2 -0
- package/dist/tools/bash_kill/prompt.js +14 -0
- package/dist/tools/bash_logs/index.d.ts +1 -0
- package/dist/tools/bash_logs/index.js +40 -0
- package/dist/tools/bash_logs/prompt.d.ts +2 -0
- package/dist/tools/bash_logs/prompt.js +14 -0
- package/dist/tools/bash_run/index.d.ts +16 -0
- package/dist/tools/bash_run/index.js +61 -0
- package/dist/tools/bash_run/prompt.d.ts +2 -0
- package/dist/tools/bash_run/prompt.js +18 -0
- package/dist/tools/builtin.d.ts +9 -0
- package/dist/tools/builtin.js +27 -0
- package/dist/tools/define.d.ts +101 -0
- package/dist/tools/define.js +214 -0
- package/dist/tools/fs_edit/index.d.ts +1 -0
- package/dist/tools/fs_edit/index.js +62 -0
- package/dist/tools/fs_edit/prompt.d.ts +2 -0
- package/dist/tools/fs_edit/prompt.js +15 -0
- package/dist/tools/fs_glob/index.d.ts +1 -0
- package/dist/tools/fs_glob/index.js +60 -0
- package/dist/tools/fs_glob/prompt.d.ts +2 -0
- package/dist/tools/fs_glob/prompt.js +18 -0
- package/dist/tools/fs_grep/index.d.ts +1 -0
- package/dist/tools/fs_grep/index.js +66 -0
- package/dist/tools/fs_grep/prompt.d.ts +2 -0
- package/dist/tools/fs_grep/prompt.js +16 -0
- package/dist/tools/fs_multi_edit/index.d.ts +1 -0
- package/dist/tools/fs_multi_edit/index.js +106 -0
- package/dist/tools/fs_multi_edit/prompt.d.ts +2 -0
- package/dist/tools/fs_multi_edit/prompt.js +16 -0
- package/dist/tools/fs_read/index.d.ts +1 -0
- package/dist/tools/fs_read/index.js +40 -0
- package/dist/tools/fs_read/prompt.d.ts +2 -0
- package/dist/tools/fs_read/prompt.js +16 -0
- package/dist/tools/fs_rm/index.d.ts +1 -0
- package/dist/tools/fs_rm/index.js +41 -0
- package/dist/tools/fs_rm/prompt.d.ts +2 -0
- package/dist/tools/fs_rm/prompt.js +14 -0
- package/dist/tools/fs_write/index.d.ts +1 -0
- package/dist/tools/fs_write/index.js +40 -0
- package/dist/tools/fs_write/prompt.d.ts +2 -0
- package/dist/tools/fs_write/prompt.js +15 -0
- package/dist/tools/index.d.ts +9 -0
- package/dist/tools/index.js +56 -0
- package/dist/tools/mcp.d.ts +73 -0
- package/dist/tools/mcp.js +198 -0
- package/dist/tools/registry.d.ts +29 -0
- package/dist/tools/registry.js +26 -0
- package/dist/tools/skill_activate/index.d.ts +5 -0
- package/dist/tools/skill_activate/index.js +63 -0
- package/dist/tools/skill_list/index.d.ts +5 -0
- package/dist/tools/skill_list/index.js +48 -0
- package/dist/tools/skill_resource/index.d.ts +5 -0
- package/dist/tools/skill_resource/index.js +82 -0
- package/dist/tools/task_run/index.d.ts +7 -0
- package/dist/tools/task_run/index.js +60 -0
- package/dist/tools/task_run/prompt.d.ts +5 -0
- package/dist/tools/task_run/prompt.js +29 -0
- package/dist/tools/todo_read/index.d.ts +1 -0
- package/dist/tools/todo_read/index.js +29 -0
- package/dist/tools/todo_read/prompt.d.ts +2 -0
- package/dist/tools/todo_read/prompt.js +18 -0
- package/dist/tools/todo_write/index.d.ts +1 -0
- package/dist/tools/todo_write/index.js +42 -0
- package/dist/tools/todo_write/prompt.d.ts +2 -0
- package/dist/tools/todo_write/prompt.js +23 -0
- package/dist/tools/tool.d.ts +43 -0
- package/dist/tools/tool.js +104 -0
- package/dist/tools/toolkit.d.ts +69 -0
- package/dist/tools/toolkit.js +98 -0
- package/dist/tools/type-inference.d.ts +127 -0
- package/dist/tools/type-inference.js +207 -0
- package/dist/utils/agent-id.d.ts +1 -0
- package/dist/utils/agent-id.js +28 -0
- package/dist/utils/session-id.d.ts +21 -0
- package/dist/utils/session-id.js +64 -0
- package/dist/utils/unicode.d.ts +17 -0
- package/dist/utils/unicode.js +62 -0
- package/package.json +117 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FsMultiEdit = void 0;
|
|
4
|
+
const tool_1 = require("../tool");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const type_inference_1 = require("../type-inference");
|
|
7
|
+
const prompt_1 = require("./prompt");
|
|
8
|
+
const editSchema = zod_1.z.object({
|
|
9
|
+
path: type_inference_1.patterns.filePath('File path'),
|
|
10
|
+
find: zod_1.z.string().describe('Existing text to replace'),
|
|
11
|
+
replace: zod_1.z.string().describe('Replacement text'),
|
|
12
|
+
replace_all: zod_1.z.boolean().optional().describe('Replace all occurrences (default: false)'),
|
|
13
|
+
});
|
|
14
|
+
exports.FsMultiEdit = (0, tool_1.tool)({
|
|
15
|
+
name: 'fs_multi_edit',
|
|
16
|
+
description: prompt_1.DESCRIPTION,
|
|
17
|
+
parameters: zod_1.z.object({
|
|
18
|
+
edits: zod_1.z.array(editSchema).describe('List of edit operations'),
|
|
19
|
+
}),
|
|
20
|
+
async execute(args, ctx) {
|
|
21
|
+
const { edits } = args;
|
|
22
|
+
const results = [];
|
|
23
|
+
for (const edit of edits) {
|
|
24
|
+
try {
|
|
25
|
+
const freshness = await ctx.services?.filePool?.validateWrite(edit.path);
|
|
26
|
+
if (freshness && !freshness.isFresh) {
|
|
27
|
+
results.push({
|
|
28
|
+
path: edit.path,
|
|
29
|
+
replacements: 0,
|
|
30
|
+
status: 'skipped',
|
|
31
|
+
message: 'File changed externally',
|
|
32
|
+
});
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const content = await ctx.sandbox.fs.read(edit.path);
|
|
36
|
+
if (edit.replace_all) {
|
|
37
|
+
const occurrences = content.split(edit.find).length - 1;
|
|
38
|
+
if (occurrences === 0) {
|
|
39
|
+
results.push({
|
|
40
|
+
path: edit.path,
|
|
41
|
+
replacements: 0,
|
|
42
|
+
status: 'skipped',
|
|
43
|
+
message: 'Pattern not found',
|
|
44
|
+
});
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const updated = content.split(edit.find).join(edit.replace);
|
|
48
|
+
await ctx.sandbox.fs.write(edit.path, updated);
|
|
49
|
+
await ctx.services?.filePool?.recordEdit(edit.path);
|
|
50
|
+
results.push({
|
|
51
|
+
path: edit.path,
|
|
52
|
+
replacements: occurrences,
|
|
53
|
+
status: 'ok',
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const index = content.indexOf(edit.find);
|
|
58
|
+
if (index === -1) {
|
|
59
|
+
results.push({
|
|
60
|
+
path: edit.path,
|
|
61
|
+
replacements: 0,
|
|
62
|
+
status: 'skipped',
|
|
63
|
+
message: 'Pattern not found',
|
|
64
|
+
});
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const occurrences = content.split(edit.find).length - 1;
|
|
68
|
+
if (occurrences > 1) {
|
|
69
|
+
results.push({
|
|
70
|
+
path: edit.path,
|
|
71
|
+
replacements: 0,
|
|
72
|
+
status: 'skipped',
|
|
73
|
+
message: `Pattern occurs ${occurrences} times; set replace_all=true if intended`,
|
|
74
|
+
});
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const updated = content.replace(edit.find, edit.replace);
|
|
78
|
+
await ctx.sandbox.fs.write(edit.path, updated);
|
|
79
|
+
await ctx.services?.filePool?.recordEdit(edit.path);
|
|
80
|
+
results.push({
|
|
81
|
+
path: edit.path,
|
|
82
|
+
replacements: 1,
|
|
83
|
+
status: 'ok',
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
results.push({
|
|
89
|
+
path: edit.path,
|
|
90
|
+
replacements: 0,
|
|
91
|
+
status: 'error',
|
|
92
|
+
message: error?.message || String(error),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
ok: results.every((r) => r.status === 'ok'),
|
|
98
|
+
results,
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
metadata: {
|
|
102
|
+
readonly: false,
|
|
103
|
+
version: '1.0',
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
exports.FsMultiEdit.prompt = prompt_1.PROMPT;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const DESCRIPTION = "Apply multiple string replacements across files";
|
|
2
|
+
export declare const PROMPT = "Batch apply targeted edits across files.\n\nGuidelines:\n- Each operation specifies a path and the text to replace.\n- Use fs_read to verify context beforehand.\n- All edits are applied sequentially; failures are isolated per file.\n- Each edit includes status feedback (ok, skipped, or error).\n\nSafety/Limitations:\n- Freshness validation prevents conflicts with external modifications.\n- Failed edits are reported but don't halt the batch.\n- Non-unique patterns require explicit replace_all flag.";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROMPT = exports.DESCRIPTION = void 0;
|
|
4
|
+
exports.DESCRIPTION = 'Apply multiple string replacements across files';
|
|
5
|
+
exports.PROMPT = `Batch apply targeted edits across files.
|
|
6
|
+
|
|
7
|
+
Guidelines:
|
|
8
|
+
- Each operation specifies a path and the text to replace.
|
|
9
|
+
- Use fs_read to verify context beforehand.
|
|
10
|
+
- All edits are applied sequentially; failures are isolated per file.
|
|
11
|
+
- Each edit includes status feedback (ok, skipped, or error).
|
|
12
|
+
|
|
13
|
+
Safety/Limitations:
|
|
14
|
+
- Freshness validation prevents conflicts with external modifications.
|
|
15
|
+
- Failed edits are reported but don't halt the batch.
|
|
16
|
+
- Non-unique patterns require explicit replace_all flag.`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const FsRead: import("..").ToolInstance;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FsRead = void 0;
|
|
4
|
+
const tool_1 = require("../tool");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const type_inference_1 = require("../type-inference");
|
|
7
|
+
const prompt_1 = require("./prompt");
|
|
8
|
+
exports.FsRead = (0, tool_1.tool)({
|
|
9
|
+
name: 'fs_read',
|
|
10
|
+
description: prompt_1.DESCRIPTION,
|
|
11
|
+
parameters: zod_1.z.object({
|
|
12
|
+
path: type_inference_1.patterns.filePath('Path to file relative to sandbox root'),
|
|
13
|
+
offset: type_inference_1.patterns.optionalNumber('Line offset (1-indexed)'),
|
|
14
|
+
limit: type_inference_1.patterns.optionalNumber('Max lines to read'),
|
|
15
|
+
}),
|
|
16
|
+
async execute(args, ctx) {
|
|
17
|
+
const { path, offset, limit } = args;
|
|
18
|
+
const content = await ctx.sandbox.fs.read(path);
|
|
19
|
+
const lines = content.split('\n');
|
|
20
|
+
const startLine = offset ? offset - 1 : 0;
|
|
21
|
+
const endLine = limit ? startLine + limit : lines.length;
|
|
22
|
+
const selected = lines.slice(startLine, endLine);
|
|
23
|
+
await ctx.services?.filePool?.recordRead(path);
|
|
24
|
+
const truncated = endLine < lines.length;
|
|
25
|
+
const result = selected.join('\n');
|
|
26
|
+
return {
|
|
27
|
+
path,
|
|
28
|
+
offset: startLine + 1,
|
|
29
|
+
limit: selected.length,
|
|
30
|
+
truncated,
|
|
31
|
+
totalLines: lines.length,
|
|
32
|
+
content: result,
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
metadata: {
|
|
36
|
+
readonly: true,
|
|
37
|
+
version: '1.0',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
exports.FsRead.prompt = prompt_1.PROMPT;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const DESCRIPTION = "Read contents from a file";
|
|
2
|
+
export declare const PROMPT = "Use this tool to inspect files within the sandboxed workspace.\n\nUsage guidance:\n- Always pass paths relative to the sandbox working directory.\n- You may optionally provide \"offset\" and \"limit\" to control the slice of lines to inspect.\n- Large files will be truncated to keep responses compact; request additional ranges if needed.\n- Prefer batching adjacent reads in a single turn to minimize context churn.\n\nSafety/Limitations:\n- This tool is read-only and integrates with FilePool for conflict detection.\n- File modifications are tracked to warn about stale reads.\n- Paths must stay inside the sandbox root directory.";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROMPT = exports.DESCRIPTION = void 0;
|
|
4
|
+
exports.DESCRIPTION = 'Read contents from a file';
|
|
5
|
+
exports.PROMPT = `Use this tool to inspect files within the sandboxed workspace.
|
|
6
|
+
|
|
7
|
+
Usage guidance:
|
|
8
|
+
- Always pass paths relative to the sandbox working directory.
|
|
9
|
+
- You may optionally provide "offset" and "limit" to control the slice of lines to inspect.
|
|
10
|
+
- Large files will be truncated to keep responses compact; request additional ranges if needed.
|
|
11
|
+
- Prefer batching adjacent reads in a single turn to minimize context churn.
|
|
12
|
+
|
|
13
|
+
Safety/Limitations:
|
|
14
|
+
- This tool is read-only and integrates with FilePool for conflict detection.
|
|
15
|
+
- File modifications are tracked to warn about stale reads.
|
|
16
|
+
- Paths must stay inside the sandbox root directory.`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const FsRm: import("..").ToolInstance;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FsRm = void 0;
|
|
4
|
+
const tool_1 = require("../tool");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const type_inference_1 = require("../type-inference");
|
|
7
|
+
const prompt_1 = require("./prompt");
|
|
8
|
+
exports.FsRm = (0, tool_1.tool)({
|
|
9
|
+
name: 'fs_rm',
|
|
10
|
+
description: prompt_1.DESCRIPTION,
|
|
11
|
+
parameters: zod_1.z.object({
|
|
12
|
+
path: type_inference_1.patterns.filePath('File or directory path within the sandbox'),
|
|
13
|
+
recursive: zod_1.z.boolean().optional().describe('Remove directories recursively (default: false)'),
|
|
14
|
+
force: zod_1.z.boolean().optional().describe('Ignore missing paths (default: false)'),
|
|
15
|
+
}),
|
|
16
|
+
async execute(args, ctx) {
|
|
17
|
+
const { path, recursive = false, force = false } = args;
|
|
18
|
+
const freshness = await ctx.services?.filePool?.validateWrite(path);
|
|
19
|
+
if (freshness && !freshness.isFresh) {
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
error: 'Path appears to have changed externally. Please re-check it before deleting.',
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
await ctx.sandbox.fs.rm(path, { recursive, force });
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (force && (err?.code === 'ENOENT' || /ENOENT/i.test(String(err?.message || '')))) {
|
|
30
|
+
return { ok: true, path, recursive, force, existed: false };
|
|
31
|
+
}
|
|
32
|
+
return { ok: false, error: err?.message || String(err), path, recursive, force };
|
|
33
|
+
}
|
|
34
|
+
return { ok: true, path, recursive, force, existed: true };
|
|
35
|
+
},
|
|
36
|
+
metadata: {
|
|
37
|
+
readonly: false,
|
|
38
|
+
version: '1.0',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
exports.FsRm.prompt = prompt_1.PROMPT;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const DESCRIPTION = "Remove a file or directory within the sandbox";
|
|
2
|
+
export declare const PROMPT = "Use this tool to delete files or directories inside the sandbox.\n\nGuidelines:\n- Prefer using fs_glob first to confirm the exact path(s) you intend to remove.\n- Deleting directories requires recursive=true.\n- Use force=true only when you intentionally want idempotent cleanup (ignore missing paths).\n\nImportant (Next.js routes):\n- Glob patterns treat square brackets as special syntax. To match a literal Next.js dynamic segment like \"[id]\",\n escape it in the glob pattern using \"[[]id[]]\" (recommended) or \"\\\\[id\\\\]\".";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROMPT = exports.DESCRIPTION = void 0;
|
|
4
|
+
exports.DESCRIPTION = 'Remove a file or directory within the sandbox';
|
|
5
|
+
exports.PROMPT = `Use this tool to delete files or directories inside the sandbox.
|
|
6
|
+
|
|
7
|
+
Guidelines:
|
|
8
|
+
- Prefer using fs_glob first to confirm the exact path(s) you intend to remove.
|
|
9
|
+
- Deleting directories requires recursive=true.
|
|
10
|
+
- Use force=true only when you intentionally want idempotent cleanup (ignore missing paths).
|
|
11
|
+
|
|
12
|
+
Important (Next.js routes):
|
|
13
|
+
- Glob patterns treat square brackets as special syntax. To match a literal Next.js dynamic segment like "[id]",
|
|
14
|
+
escape it in the glob pattern using "[[]id[]]" (recommended) or "\\\\[id\\\\]".`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const FsWrite: import("..").ToolInstance;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FsWrite = void 0;
|
|
4
|
+
const tool_1 = require("../tool");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const type_inference_1 = require("../type-inference");
|
|
7
|
+
const prompt_1 = require("./prompt");
|
|
8
|
+
exports.FsWrite = (0, tool_1.tool)({
|
|
9
|
+
name: 'fs_write',
|
|
10
|
+
description: prompt_1.DESCRIPTION,
|
|
11
|
+
parameters: zod_1.z.object({
|
|
12
|
+
path: type_inference_1.patterns.filePath('Path to file within the sandbox'),
|
|
13
|
+
content: zod_1.z.string().describe('Content to write'),
|
|
14
|
+
}),
|
|
15
|
+
async execute(args, ctx) {
|
|
16
|
+
const { path, content } = args;
|
|
17
|
+
const freshness = await ctx.services?.filePool?.validateWrite(path);
|
|
18
|
+
if (freshness && !freshness.isFresh) {
|
|
19
|
+
return {
|
|
20
|
+
ok: false,
|
|
21
|
+
error: 'File appears to have changed externally. Please read it again before writing.',
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
await ctx.sandbox.fs.write(path, content);
|
|
25
|
+
await ctx.services?.filePool?.recordEdit(path);
|
|
26
|
+
const bytes = Buffer.byteLength(content, 'utf8');
|
|
27
|
+
const lines = content.split('\n').length;
|
|
28
|
+
return {
|
|
29
|
+
ok: true,
|
|
30
|
+
path,
|
|
31
|
+
bytes,
|
|
32
|
+
lines,
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
metadata: {
|
|
36
|
+
readonly: false,
|
|
37
|
+
version: '1.0',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
exports.FsWrite.prompt = prompt_1.PROMPT;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const DESCRIPTION = "Write contents to a file (creates or overwrites)";
|
|
2
|
+
export declare const PROMPT = "Use this tool to create or overwrite files inside the sandbox.\n\nGuidelines:\n- Paths must stay inside the sandbox root. The SDK will deny attempts to escape the workspace.\n- Provide the full target contents. The previous file body will be replaced.\n- Pair with fs_read when editing existing files so the FilePool can validate freshness.\n- The tool returns the number of bytes written for auditing purposes.\n\nSafety/Limitations:\n- File freshness validation ensures you don't overwrite externally modified files.\n- Large file writes are allowed but may impact performance.";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROMPT = exports.DESCRIPTION = void 0;
|
|
4
|
+
exports.DESCRIPTION = 'Write contents to a file (creates or overwrites)';
|
|
5
|
+
exports.PROMPT = `Use this tool to create or overwrite files inside the sandbox.
|
|
6
|
+
|
|
7
|
+
Guidelines:
|
|
8
|
+
- Paths must stay inside the sandbox root. The SDK will deny attempts to escape the workspace.
|
|
9
|
+
- Provide the full target contents. The previous file body will be replaced.
|
|
10
|
+
- Pair with fs_read when editing existing files so the FilePool can validate freshness.
|
|
11
|
+
- The tool returns the number of bytes written for auditing purposes.
|
|
12
|
+
|
|
13
|
+
Safety/Limitations:
|
|
14
|
+
- File freshness validation ensures you don't overwrite externally modified files.
|
|
15
|
+
- Large file writes are allowed but may impact performance.`;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { tool, tools } from './tool';
|
|
2
|
+
export type { ToolDefinition, EnhancedToolContext } from './tool';
|
|
3
|
+
export { defineTool, defineTools, extractTools } from './define';
|
|
4
|
+
export type { SimpleToolDef, ToolAttributes, ParamDef } from './define';
|
|
5
|
+
export { getMCPTools, disconnectMCP, disconnectAllMCP } from './mcp';
|
|
6
|
+
export type { MCPConfig, MCPTransportType } from './mcp';
|
|
7
|
+
export { ToolRegistry, globalToolRegistry } from './registry';
|
|
8
|
+
export type { ToolInstance, ToolDescriptor, ToolFactory, ToolSource } from './registry';
|
|
9
|
+
export * as builtin from './builtin';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.builtin = exports.globalToolRegistry = exports.ToolRegistry = exports.disconnectAllMCP = exports.disconnectMCP = exports.getMCPTools = exports.extractTools = exports.defineTools = exports.defineTool = exports.tools = exports.tool = void 0;
|
|
37
|
+
// 统一的工具定义 API (v2.0 推荐)
|
|
38
|
+
var tool_1 = require("./tool");
|
|
39
|
+
Object.defineProperty(exports, "tool", { enumerable: true, get: function () { return tool_1.tool; } });
|
|
40
|
+
Object.defineProperty(exports, "tools", { enumerable: true, get: function () { return tool_1.tools; } });
|
|
41
|
+
// 简化的工具定义 API (保留兼容)
|
|
42
|
+
var define_1 = require("./define");
|
|
43
|
+
Object.defineProperty(exports, "defineTool", { enumerable: true, get: function () { return define_1.defineTool; } });
|
|
44
|
+
Object.defineProperty(exports, "defineTools", { enumerable: true, get: function () { return define_1.defineTools; } });
|
|
45
|
+
Object.defineProperty(exports, "extractTools", { enumerable: true, get: function () { return define_1.extractTools; } });
|
|
46
|
+
// MCP 集成
|
|
47
|
+
var mcp_1 = require("./mcp");
|
|
48
|
+
Object.defineProperty(exports, "getMCPTools", { enumerable: true, get: function () { return mcp_1.getMCPTools; } });
|
|
49
|
+
Object.defineProperty(exports, "disconnectMCP", { enumerable: true, get: function () { return mcp_1.disconnectMCP; } });
|
|
50
|
+
Object.defineProperty(exports, "disconnectAllMCP", { enumerable: true, get: function () { return mcp_1.disconnectAllMCP; } });
|
|
51
|
+
// 工具注册表
|
|
52
|
+
var registry_1 = require("./registry");
|
|
53
|
+
Object.defineProperty(exports, "ToolRegistry", { enumerable: true, get: function () { return registry_1.ToolRegistry; } });
|
|
54
|
+
Object.defineProperty(exports, "globalToolRegistry", { enumerable: true, get: function () { return registry_1.globalToolRegistry; } });
|
|
55
|
+
// 内置工具
|
|
56
|
+
exports.builtin = __importStar(require("./builtin"));
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ToolInstance } from './registry';
|
|
2
|
+
/**
|
|
3
|
+
* MCP Transport 类型
|
|
4
|
+
*/
|
|
5
|
+
export type MCPTransportType = 'stdio' | 'sse' | 'http' | 'streamableHttp';
|
|
6
|
+
/**
|
|
7
|
+
* MCP 连接配置
|
|
8
|
+
*/
|
|
9
|
+
export interface MCPConfig {
|
|
10
|
+
/**
|
|
11
|
+
* 传输类型
|
|
12
|
+
*/
|
|
13
|
+
transport: MCPTransportType;
|
|
14
|
+
/**
|
|
15
|
+
* Stdio transport: 命令和参数
|
|
16
|
+
*/
|
|
17
|
+
command?: string;
|
|
18
|
+
args?: string[];
|
|
19
|
+
env?: Record<string, string>;
|
|
20
|
+
/**
|
|
21
|
+
* HTTP/SSE transport: URL
|
|
22
|
+
*/
|
|
23
|
+
url?: string;
|
|
24
|
+
/**
|
|
25
|
+
* HTTP headers for transport
|
|
26
|
+
*/
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
/**
|
|
29
|
+
* Server 名称(用于命名空间)
|
|
30
|
+
*/
|
|
31
|
+
serverName?: string;
|
|
32
|
+
/**
|
|
33
|
+
* 包含的工具(白名单,不提供则全部包含)
|
|
34
|
+
*/
|
|
35
|
+
include?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* 排除的工具(黑名单)
|
|
38
|
+
*/
|
|
39
|
+
exclude?: string[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 获取 MCP 工具
|
|
43
|
+
*
|
|
44
|
+
* 连接到 MCP 服务器并将其工具转换为 ToolInstance[]
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* // Stdio transport
|
|
49
|
+
* const tools = await getMCPTools({
|
|
50
|
+
* transport: 'stdio',
|
|
51
|
+
* command: 'uvx',
|
|
52
|
+
* args: ['mcp-server-git'],
|
|
53
|
+
* serverName: 'git'
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // HTTP/SSE transport
|
|
57
|
+
* const tools = await getMCPTools({
|
|
58
|
+
* transport: 'sse',
|
|
59
|
+
* url: 'http://localhost:3000/mcp',
|
|
60
|
+
* serverName: 'company',
|
|
61
|
+
* include: ['search', 'summarize']
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function getMCPTools(config: MCPConfig): Promise<ToolInstance[]>;
|
|
66
|
+
/**
|
|
67
|
+
* 断开 MCP 服务器连接
|
|
68
|
+
*/
|
|
69
|
+
export declare function disconnectMCP(serverName: string): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* 断开所有 MCP 服务器连接
|
|
72
|
+
*/
|
|
73
|
+
export declare function disconnectAllMCP(): Promise<void>;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMCPTools = getMCPTools;
|
|
4
|
+
exports.disconnectMCP = disconnectMCP;
|
|
5
|
+
exports.disconnectAllMCP = disconnectAllMCP;
|
|
6
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
7
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
8
|
+
const sse_js_1 = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
9
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
10
|
+
const registry_1 = require("./registry");
|
|
11
|
+
/**
|
|
12
|
+
* MCP Client 管理器
|
|
13
|
+
*
|
|
14
|
+
* 维护 MCP 客户端连接,支持多种传输方式
|
|
15
|
+
*/
|
|
16
|
+
class MCPClientManager {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.clients = new Map();
|
|
19
|
+
this.transports = new Map();
|
|
20
|
+
}
|
|
21
|
+
async connect(serverName, config) {
|
|
22
|
+
// 如果已连接,返回现有客户端
|
|
23
|
+
if (this.clients.has(serverName)) {
|
|
24
|
+
return this.clients.get(serverName);
|
|
25
|
+
}
|
|
26
|
+
// 创建 transport
|
|
27
|
+
let transport;
|
|
28
|
+
if (config.transport === 'stdio') {
|
|
29
|
+
if (!config.command) {
|
|
30
|
+
throw new Error('command is required for stdio transport');
|
|
31
|
+
}
|
|
32
|
+
transport = new stdio_js_1.StdioClientTransport({
|
|
33
|
+
command: config.command,
|
|
34
|
+
args: config.args || [],
|
|
35
|
+
env: config.env,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else if (config.transport === 'sse') {
|
|
39
|
+
if (!config.url) {
|
|
40
|
+
throw new Error('url is required for sse transport');
|
|
41
|
+
}
|
|
42
|
+
transport = new sse_js_1.SSEClientTransport(new URL(config.url));
|
|
43
|
+
}
|
|
44
|
+
else if (config.transport === 'http' || config.transport === 'streamableHttp') {
|
|
45
|
+
if (!config.url) {
|
|
46
|
+
throw new Error('url is required for http/streamableHttp transport');
|
|
47
|
+
}
|
|
48
|
+
transport = new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(config.url), {
|
|
49
|
+
requestInit: {
|
|
50
|
+
headers: config.headers,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
throw new Error(`Unsupported transport type: ${config.transport}`);
|
|
56
|
+
}
|
|
57
|
+
// 创建客户端
|
|
58
|
+
const client = new index_js_1.Client({
|
|
59
|
+
name: 'kode-sdk',
|
|
60
|
+
version: '2.0.0',
|
|
61
|
+
}, {
|
|
62
|
+
capabilities: {
|
|
63
|
+
tools: {},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
// 连接
|
|
67
|
+
await client.connect(transport);
|
|
68
|
+
// 缓存
|
|
69
|
+
this.clients.set(serverName, client);
|
|
70
|
+
this.transports.set(serverName, transport);
|
|
71
|
+
return client;
|
|
72
|
+
}
|
|
73
|
+
async disconnect(serverName) {
|
|
74
|
+
const client = this.clients.get(serverName);
|
|
75
|
+
if (client) {
|
|
76
|
+
await client.close();
|
|
77
|
+
this.clients.delete(serverName);
|
|
78
|
+
}
|
|
79
|
+
const transport = this.transports.get(serverName);
|
|
80
|
+
if (transport) {
|
|
81
|
+
await transport.close();
|
|
82
|
+
this.transports.delete(serverName);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async disconnectAll() {
|
|
86
|
+
const servers = Array.from(this.clients.keys());
|
|
87
|
+
await Promise.all(servers.map((name) => this.disconnect(name)));
|
|
88
|
+
}
|
|
89
|
+
getClient(serverName) {
|
|
90
|
+
return this.clients.get(serverName);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const mcpManager = new MCPClientManager();
|
|
94
|
+
/**
|
|
95
|
+
* 获取 MCP 工具
|
|
96
|
+
*
|
|
97
|
+
* 连接到 MCP 服务器并将其工具转换为 ToolInstance[]
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* // Stdio transport
|
|
102
|
+
* const tools = await getMCPTools({
|
|
103
|
+
* transport: 'stdio',
|
|
104
|
+
* command: 'uvx',
|
|
105
|
+
* args: ['mcp-server-git'],
|
|
106
|
+
* serverName: 'git'
|
|
107
|
+
* });
|
|
108
|
+
*
|
|
109
|
+
* // HTTP/SSE transport
|
|
110
|
+
* const tools = await getMCPTools({
|
|
111
|
+
* transport: 'sse',
|
|
112
|
+
* url: 'http://localhost:3000/mcp',
|
|
113
|
+
* serverName: 'company',
|
|
114
|
+
* include: ['search', 'summarize']
|
|
115
|
+
* });
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
async function getMCPTools(config) {
|
|
119
|
+
const serverName = config.serverName || 'default';
|
|
120
|
+
// 连接到 MCP 服务器
|
|
121
|
+
const client = await mcpManager.connect(serverName, config);
|
|
122
|
+
// 列出可用工具
|
|
123
|
+
const toolsResponse = await client.listTools();
|
|
124
|
+
const mcpTools = toolsResponse.tools;
|
|
125
|
+
// 过滤工具
|
|
126
|
+
let filtered = mcpTools;
|
|
127
|
+
if (config.include) {
|
|
128
|
+
filtered = filtered.filter((tool) => config.include.includes(tool.name));
|
|
129
|
+
}
|
|
130
|
+
if (config.exclude) {
|
|
131
|
+
filtered = filtered.filter((tool) => !config.exclude.includes(tool.name));
|
|
132
|
+
}
|
|
133
|
+
// 转换为 ToolInstance[]
|
|
134
|
+
const toolInstances = filtered.map((mcpTool) => {
|
|
135
|
+
// 生成命名空间化的工具名:mcp__serverName__toolName
|
|
136
|
+
const toolName = `mcp__${serverName}__${mcpTool.name}`;
|
|
137
|
+
const toolInstance = {
|
|
138
|
+
name: toolName,
|
|
139
|
+
description: mcpTool.description || `MCP tool: ${mcpTool.name}`,
|
|
140
|
+
input_schema: mcpTool.inputSchema,
|
|
141
|
+
async exec(args, _ctx) {
|
|
142
|
+
try {
|
|
143
|
+
// 调用 MCP 工具
|
|
144
|
+
const result = await client.callTool({
|
|
145
|
+
name: mcpTool.name,
|
|
146
|
+
arguments: args,
|
|
147
|
+
});
|
|
148
|
+
// 返回结果
|
|
149
|
+
return {
|
|
150
|
+
content: result.content,
|
|
151
|
+
isError: result.isError,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
throw new Error(`MCP tool execution failed: ${error}`);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
toDescriptor() {
|
|
159
|
+
return {
|
|
160
|
+
source: 'mcp',
|
|
161
|
+
name: toolName,
|
|
162
|
+
registryId: toolName,
|
|
163
|
+
metadata: {
|
|
164
|
+
mcpServer: serverName,
|
|
165
|
+
mcpToolName: mcpTool.name,
|
|
166
|
+
transport: config.transport,
|
|
167
|
+
},
|
|
168
|
+
config: {
|
|
169
|
+
serverName,
|
|
170
|
+
transport: config.transport,
|
|
171
|
+
url: config.url,
|
|
172
|
+
command: config.command,
|
|
173
|
+
args: config.args,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
// 自动注册到 global registry(支持 Resume)
|
|
179
|
+
registry_1.globalToolRegistry.register(toolName, (_registryConfig) => {
|
|
180
|
+
// Resume 时重建 MCP 连接
|
|
181
|
+
return toolInstance;
|
|
182
|
+
});
|
|
183
|
+
return toolInstance;
|
|
184
|
+
});
|
|
185
|
+
return toolInstances;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 断开 MCP 服务器连接
|
|
189
|
+
*/
|
|
190
|
+
async function disconnectMCP(serverName) {
|
|
191
|
+
await mcpManager.disconnect(serverName);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* 断开所有 MCP 服务器连接
|
|
195
|
+
*/
|
|
196
|
+
async function disconnectAllMCP() {
|
|
197
|
+
await mcpManager.disconnectAll();
|
|
198
|
+
}
|