@shareai-lab/kode-sdk 2.7.1 → 2.7.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.
Files changed (97) hide show
  1. package/dist/core/agent/breakpoint-manager.js +36 -0
  2. package/dist/core/agent/message-queue.js +57 -0
  3. package/dist/core/agent/permission-manager.js +32 -0
  4. package/dist/core/agent/todo-manager.js +91 -0
  5. package/dist/core/agent/tool-runner.js +45 -0
  6. package/dist/core/agent.js +2035 -0
  7. package/dist/core/config.js +2 -0
  8. package/dist/core/context-manager.js +241 -0
  9. package/dist/core/errors.js +49 -0
  10. package/dist/core/events.js +329 -0
  11. package/dist/core/file-pool.d.ts +2 -0
  12. package/dist/core/file-pool.js +125 -0
  13. package/dist/core/hooks.js +71 -0
  14. package/dist/core/permission-modes.js +61 -0
  15. package/dist/core/pool.js +301 -0
  16. package/dist/core/room.js +57 -0
  17. package/dist/core/scheduler.js +58 -0
  18. package/dist/core/skills/index.js +20 -0
  19. package/dist/core/skills/management-manager.js +557 -0
  20. package/dist/core/skills/manager.js +243 -0
  21. package/dist/core/skills/operation-queue.js +113 -0
  22. package/dist/core/skills/sandbox-file-manager.js +183 -0
  23. package/dist/core/skills/types.js +9 -0
  24. package/dist/core/skills/xml-generator.js +70 -0
  25. package/dist/core/template.js +35 -0
  26. package/dist/core/time-bridge.js +100 -0
  27. package/dist/core/todo.js +89 -0
  28. package/dist/core/types.js +3 -0
  29. package/dist/index.js +148 -60461
  30. package/dist/infra/db/postgres/postgres-store.js +1073 -0
  31. package/dist/infra/db/sqlite/sqlite-store.js +800 -0
  32. package/dist/infra/e2b/e2b-fs.js +128 -0
  33. package/dist/infra/e2b/e2b-sandbox.js +156 -0
  34. package/dist/infra/e2b/e2b-template.js +105 -0
  35. package/dist/infra/e2b/index.js +9 -0
  36. package/dist/infra/e2b/types.js +2 -0
  37. package/dist/infra/provider.js +67 -0
  38. package/dist/infra/providers/anthropic.js +308 -0
  39. package/dist/infra/providers/core/errors.js +353 -0
  40. package/dist/infra/providers/core/fork.js +418 -0
  41. package/dist/infra/providers/core/index.js +76 -0
  42. package/dist/infra/providers/core/logger.js +191 -0
  43. package/dist/infra/providers/core/retry.js +189 -0
  44. package/dist/infra/providers/core/usage.js +376 -0
  45. package/dist/infra/providers/gemini.js +493 -0
  46. package/dist/infra/providers/index.js +83 -0
  47. package/dist/infra/providers/openai.js +662 -0
  48. package/dist/infra/providers/types.js +20 -0
  49. package/dist/infra/providers/utils.js +400 -0
  50. package/dist/infra/sandbox-factory.js +30 -0
  51. package/dist/infra/sandbox.js +243 -0
  52. package/dist/infra/store/factory.js +80 -0
  53. package/dist/infra/store/index.js +26 -0
  54. package/dist/infra/store/json-store.js +606 -0
  55. package/dist/infra/store/types.js +2 -0
  56. package/dist/infra/store.js +29 -0
  57. package/dist/tools/bash_kill/index.js +35 -0
  58. package/dist/tools/bash_kill/prompt.js +14 -0
  59. package/dist/tools/bash_logs/index.js +40 -0
  60. package/dist/tools/bash_logs/prompt.js +14 -0
  61. package/dist/tools/bash_run/index.js +61 -0
  62. package/dist/tools/bash_run/prompt.js +18 -0
  63. package/dist/tools/builtin.js +26 -0
  64. package/dist/tools/define.js +214 -0
  65. package/dist/tools/fs_edit/index.js +62 -0
  66. package/dist/tools/fs_edit/prompt.js +15 -0
  67. package/dist/tools/fs_glob/index.js +40 -0
  68. package/dist/tools/fs_glob/prompt.js +15 -0
  69. package/dist/tools/fs_grep/index.js +66 -0
  70. package/dist/tools/fs_grep/prompt.js +16 -0
  71. package/dist/tools/fs_multi_edit/index.js +106 -0
  72. package/dist/tools/fs_multi_edit/prompt.js +16 -0
  73. package/dist/tools/fs_read/index.js +40 -0
  74. package/dist/tools/fs_read/prompt.js +16 -0
  75. package/dist/tools/fs_write/index.js +40 -0
  76. package/dist/tools/fs_write/prompt.js +15 -0
  77. package/dist/tools/index.js +61 -0
  78. package/dist/tools/mcp.js +185 -0
  79. package/dist/tools/registry.js +26 -0
  80. package/dist/tools/scripts.js +205 -0
  81. package/dist/tools/skills.js +115 -0
  82. package/dist/tools/task_run/index.js +58 -0
  83. package/dist/tools/task_run/prompt.js +25 -0
  84. package/dist/tools/todo_read/index.js +29 -0
  85. package/dist/tools/todo_read/prompt.js +18 -0
  86. package/dist/tools/todo_write/index.js +42 -0
  87. package/dist/tools/todo_write/prompt.js +23 -0
  88. package/dist/tools/tool.js +211 -0
  89. package/dist/tools/toolkit.js +98 -0
  90. package/dist/tools/type-inference.js +207 -0
  91. package/dist/utils/agent-id.js +28 -0
  92. package/dist/utils/logger.js +44 -0
  93. package/dist/utils/session-id.js +64 -0
  94. package/package.json +7 -38
  95. package/dist/index.js.map +0 -7
  96. package/dist/index.mjs +0 -60385
  97. package/dist/index.mjs.map +0 -7
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BashLogs = void 0;
4
+ const tool_1 = require("../tool");
5
+ const zod_1 = require("zod");
6
+ const prompt_1 = require("./prompt");
7
+ const bash_run_1 = require("../bash_run");
8
+ exports.BashLogs = (0, tool_1.tool)({
9
+ name: 'bash_logs',
10
+ description: prompt_1.DESCRIPTION,
11
+ parameters: zod_1.z.object({
12
+ shell_id: zod_1.z.string().describe('Shell ID from bash_run'),
13
+ }),
14
+ async execute(args) {
15
+ const { shell_id } = args;
16
+ const proc = bash_run_1.processes.get(shell_id);
17
+ if (!proc) {
18
+ return {
19
+ ok: false,
20
+ error: `Shell not found: ${shell_id}`,
21
+ };
22
+ }
23
+ const isRunning = proc.code === undefined;
24
+ const status = isRunning ? 'running' : `completed (exit code ${proc.code})`;
25
+ const output = [proc.stdout, proc.stderr].filter(Boolean).join('\n').trim();
26
+ return {
27
+ ok: true,
28
+ shell_id,
29
+ status,
30
+ running: isRunning,
31
+ code: proc.code,
32
+ output: output || '(no output yet)',
33
+ };
34
+ },
35
+ metadata: {
36
+ readonly: true,
37
+ version: '1.0',
38
+ },
39
+ });
40
+ exports.BashLogs.prompt = prompt_1.PROMPT;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROMPT = exports.DESCRIPTION = void 0;
4
+ exports.DESCRIPTION = 'Get output from a background bash shell';
5
+ exports.PROMPT = `Fetch stdout/stderr from a background bash session started via bash_run with "background": true.
6
+
7
+ Guidelines:
8
+ - Provide the shell_id returned by bash_run to retrieve incremental logs.
9
+ - Check the status to see if the process is still running or completed.
10
+ - Output includes both stdout and stderr streams.
11
+
12
+ Safety/Limitations:
13
+ - Only processes started in the current session are accessible.
14
+ - Process history is not persisted across SDK restarts.`;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processes = exports.BashRun = 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 processes = new Map();
9
+ exports.processes = processes;
10
+ exports.BashRun = (0, tool_1.tool)({
11
+ name: 'bash_run',
12
+ description: prompt_1.DESCRIPTION,
13
+ parameters: zod_1.z.object({
14
+ cmd: zod_1.z.string().describe('Command to execute'),
15
+ timeout_ms: type_inference_1.patterns.optionalNumber('Timeout in milliseconds (default: 120000)'),
16
+ background: zod_1.z.boolean().optional().describe('Run in background and return shell_id'),
17
+ }),
18
+ async execute(args, ctx) {
19
+ const { cmd, timeout_ms = 120000, background = false } = args;
20
+ if (background) {
21
+ const id = `shell-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
22
+ const promise = ctx.sandbox.exec(cmd, { timeoutMs: timeout_ms });
23
+ const proc = {
24
+ id,
25
+ cmd,
26
+ startTime: Date.now(),
27
+ promise,
28
+ stdout: '',
29
+ stderr: '',
30
+ };
31
+ processes.set(id, proc);
32
+ promise.then((result) => {
33
+ proc.code = result.code;
34
+ proc.stdout = result.stdout;
35
+ proc.stderr = result.stderr;
36
+ }).catch((error) => {
37
+ proc.code = -1;
38
+ proc.stderr = error?.message || String(error);
39
+ });
40
+ return {
41
+ background: true,
42
+ shell_id: id,
43
+ message: `Background shell started: ${id}`,
44
+ };
45
+ }
46
+ else {
47
+ const result = await ctx.sandbox.exec(cmd, { timeoutMs: timeout_ms });
48
+ const output = [result.stdout, result.stderr].filter(Boolean).join('\n').trim();
49
+ return {
50
+ background: false,
51
+ code: result.code,
52
+ output: output || '(no output)',
53
+ };
54
+ }
55
+ },
56
+ metadata: {
57
+ readonly: false,
58
+ version: '1.0',
59
+ },
60
+ });
61
+ exports.BashRun.prompt = prompt_1.PROMPT;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROMPT = exports.DESCRIPTION = void 0;
4
+ exports.DESCRIPTION = 'Execute a bash command';
5
+ exports.PROMPT = `Execute shell commands inside the sandbox environment.
6
+
7
+ Guidelines:
8
+ - Commands run with the sandbox's working directory and limited privileges.
9
+ - Capture output responsibly; large outputs are truncated and saved to temp files.
10
+ - Respect project policies: use fs_read for inspections where possible.
11
+ - Request approval when running high-impact commands if required by policy.
12
+ - Set "background" to true to run long-running processes and poll with bash_logs.
13
+
14
+ Safety/Limitations:
15
+ - Commands are sandboxed and cannot escape the workspace.
16
+ - Dangerous commands may be blocked for security.
17
+ - Timeout defaults to 120 seconds but can be configured.
18
+ - Background processes must be explicitly killed with bash_kill.`;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.builtin = void 0;
4
+ const fs_read_1 = require("./fs_read");
5
+ const fs_write_1 = require("./fs_write");
6
+ const fs_edit_1 = require("./fs_edit");
7
+ const fs_glob_1 = require("./fs_glob");
8
+ const fs_grep_1 = require("./fs_grep");
9
+ const fs_multi_edit_1 = require("./fs_multi_edit");
10
+ const bash_run_1 = require("./bash_run");
11
+ const bash_logs_1 = require("./bash_logs");
12
+ const bash_kill_1 = require("./bash_kill");
13
+ const todo_read_1 = require("./todo_read");
14
+ const todo_write_1 = require("./todo_write");
15
+ const task_run_1 = require("./task_run");
16
+ exports.builtin = {
17
+ fs: () => [fs_read_1.FsRead, fs_write_1.FsWrite, fs_edit_1.FsEdit, fs_glob_1.FsGlob, fs_grep_1.FsGrep, fs_multi_edit_1.FsMultiEdit],
18
+ bash: () => [bash_run_1.BashRun, bash_logs_1.BashLogs, bash_kill_1.BashKill],
19
+ todo: () => [todo_read_1.TodoRead, todo_write_1.TodoWrite],
20
+ task: (templates) => {
21
+ if (!templates || templates.length === 0) {
22
+ return null;
23
+ }
24
+ return (0, task_run_1.createTaskRunTool)(templates);
25
+ },
26
+ };
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ /**
3
+ * 简化的工具定义 API - 提供更好的开发体验
4
+ *
5
+ * 设计目标:
6
+ * 1. 自动从 TypeScript 类型生成 input_schema
7
+ * 2. 简化 metadata 为 readonly/noEffect 布尔值
8
+ * 3. 支持工具内发射自定义事件
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.defineTool = defineTool;
12
+ exports.defineTools = defineTools;
13
+ exports.tool = tool;
14
+ exports.extractTools = extractTools;
15
+ const registry_1 = require("./registry");
16
+ /**
17
+ * 从参数定义自动生成 JSON Schema
18
+ */
19
+ function generateSchema(params) {
20
+ if (!params) {
21
+ return { type: 'object', properties: {} };
22
+ }
23
+ const properties = {};
24
+ const required = [];
25
+ for (const [key, def] of Object.entries(params)) {
26
+ const prop = { type: def.type };
27
+ if (def.description)
28
+ prop.description = def.description;
29
+ if (def.enum)
30
+ prop.enum = def.enum;
31
+ if (def.default !== undefined)
32
+ prop.default = def.default;
33
+ if (def.type === 'array' && def.items) {
34
+ prop.items = generateSchemaProp(def.items);
35
+ }
36
+ if (def.type === 'object' && def.properties) {
37
+ const nested = generateSchema(def.properties);
38
+ prop.properties = nested.properties;
39
+ if (nested.required?.length > 0) {
40
+ prop.required = nested.required;
41
+ }
42
+ }
43
+ properties[key] = prop;
44
+ if (def.required !== false) { // default required
45
+ required.push(key);
46
+ }
47
+ }
48
+ return {
49
+ type: 'object',
50
+ properties,
51
+ ...(required.length > 0 ? { required } : {}),
52
+ };
53
+ }
54
+ function generateSchemaProp(def) {
55
+ const prop = { type: def.type };
56
+ if (def.description)
57
+ prop.description = def.description;
58
+ if (def.enum)
59
+ prop.enum = def.enum;
60
+ if (def.type === 'array' && def.items) {
61
+ prop.items = generateSchemaProp(def.items);
62
+ }
63
+ if (def.type === 'object' && def.properties) {
64
+ const nested = generateSchema(def.properties);
65
+ prop.properties = nested.properties;
66
+ if (nested.required?.length > 0) {
67
+ prop.required = nested.required;
68
+ }
69
+ }
70
+ return prop;
71
+ }
72
+ /**
73
+ * 定义工具(简化版)
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const greet = defineTool({
78
+ * name: 'greet',
79
+ * description: 'Greet a person',
80
+ * params: {
81
+ * name: { type: 'string', description: 'Person name' },
82
+ * formal: { type: 'boolean', description: 'Use formal greeting', required: false }
83
+ * },
84
+ * attributes: { readonly: true, noEffect: true },
85
+ * async exec(args, ctx) {
86
+ * const greeting = args.formal ? `Good day, ${args.name}` : `Hi ${args.name}!`;
87
+ *
88
+ * // 自定义事件
89
+ * ctx.emit('greeting_sent', { name: args.name, greeting });
90
+ *
91
+ * return { greeting };
92
+ * }
93
+ * });
94
+ * ```
95
+ */
96
+ function defineTool(def, options) {
97
+ // 自动生成 schema 或使用提供的
98
+ const input_schema = def.input_schema || generateSchema(def.params);
99
+ const toolInstance = {
100
+ name: def.name,
101
+ description: def.description,
102
+ input_schema,
103
+ prompt: def.prompt,
104
+ async exec(args, ctx) {
105
+ // 增强上下文,添加 emit 方法
106
+ const enhancedCtx = {
107
+ ...ctx,
108
+ emit(eventType, data) {
109
+ // 发射自定义事件到 monitor 通道
110
+ ctx.agent?.events?.emitMonitor({
111
+ type: 'tool_custom_event',
112
+ toolName: def.name,
113
+ eventType,
114
+ data,
115
+ timestamp: Date.now(),
116
+ });
117
+ },
118
+ };
119
+ return await def.exec(args, enhancedCtx);
120
+ },
121
+ toDescriptor() {
122
+ const metadata = {
123
+ tuned: false,
124
+ };
125
+ // 转换简化的 attributes 为内部 metadata
126
+ if (def.attributes?.readonly) {
127
+ metadata.access = 'read';
128
+ metadata.mutates = false;
129
+ }
130
+ else {
131
+ metadata.access = 'write';
132
+ metadata.mutates = true;
133
+ }
134
+ if (def.attributes?.noEffect !== undefined) {
135
+ metadata.safe = def.attributes.noEffect;
136
+ }
137
+ if (def.prompt) {
138
+ metadata.prompt = def.prompt;
139
+ }
140
+ return {
141
+ source: 'registered',
142
+ name: def.name,
143
+ registryId: def.name,
144
+ metadata,
145
+ };
146
+ },
147
+ };
148
+ // 自动注册到全局 registry (支持 Resume)
149
+ if (options?.autoRegister !== false) {
150
+ registry_1.globalToolRegistry.register(def.name, (_config) => {
151
+ // 工厂函数:根据 config 重建工具实例
152
+ // 注意:使用 autoRegister: false 避免重复注册
153
+ return defineTool(def, { autoRegister: false });
154
+ });
155
+ }
156
+ return toolInstance;
157
+ }
158
+ /**
159
+ * 批量定义工具
160
+ */
161
+ function defineTools(defs) {
162
+ return defs.map((def) => defineTool(def));
163
+ }
164
+ /**
165
+ * 工具装饰器(实验性 - 需要 experimentalDecorators)
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * class MyTools {
170
+ * @tool({
171
+ * description: 'Calculate sum',
172
+ * params: {
173
+ * a: { type: 'number' },
174
+ * b: { type: 'number' }
175
+ * },
176
+ * attributes: { readonly: true, noEffect: true }
177
+ * })
178
+ * async sum(args: { a: number; b: number }, ctx: EnhancedToolContext) {
179
+ * return args.a + args.b;
180
+ * }
181
+ * }
182
+ * ```
183
+ */
184
+ function tool(config) {
185
+ return function (target, propertyKey, descriptor) {
186
+ const originalMethod = descriptor.value;
187
+ // 存储工具配置到类的元数据
188
+ if (!target.constructor._toolConfigs) {
189
+ target.constructor._toolConfigs = new Map();
190
+ }
191
+ target.constructor._toolConfigs.set(propertyKey, {
192
+ ...config,
193
+ name: propertyKey,
194
+ exec: originalMethod,
195
+ });
196
+ };
197
+ }
198
+ /**
199
+ * 从带装饰器的类提取所有工具
200
+ */
201
+ function extractTools(instance) {
202
+ const configs = instance.constructor._toolConfigs;
203
+ if (!configs)
204
+ return [];
205
+ const tools = [];
206
+ for (const [_methodName, config] of configs) {
207
+ tools.push(defineTool({
208
+ ...config,
209
+ exec: config.exec.bind(instance),
210
+ }, { autoRegister: true } // 装饰器定义的工具也自动注册
211
+ ));
212
+ }
213
+ return tools;
214
+ }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FsEdit = 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.FsEdit = (0, tool_1.tool)({
9
+ name: 'fs_edit',
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
+ old_string: zod_1.z.string().describe('String to replace'),
14
+ new_string: zod_1.z.string().describe('Replacement string'),
15
+ replace_all: zod_1.z.boolean().optional().describe('Replace all occurrences (default: false)'),
16
+ }),
17
+ async execute(args, ctx) {
18
+ const { path, old_string, new_string, replace_all = false } = args;
19
+ const content = await ctx.sandbox.fs.read(path);
20
+ if (replace_all) {
21
+ const occurrences = content.split(old_string).length - 1;
22
+ if (occurrences === 0) {
23
+ return { ok: false, error: 'old_string not found in file' };
24
+ }
25
+ const updated = content.split(old_string).join(new_string);
26
+ await ctx.sandbox.fs.write(path, updated);
27
+ await ctx.services?.filePool?.recordEdit(path);
28
+ return {
29
+ ok: true,
30
+ path,
31
+ replacements: occurrences,
32
+ lines: updated.split('\n').length,
33
+ };
34
+ }
35
+ else {
36
+ const occurrences = content.split(old_string).length - 1;
37
+ if (occurrences === 0) {
38
+ return { ok: false, error: 'old_string not found in file' };
39
+ }
40
+ if (occurrences > 1) {
41
+ return {
42
+ ok: false,
43
+ error: `old_string appears ${occurrences} times; set replace_all=true or provide more specific text`,
44
+ };
45
+ }
46
+ const updated = content.replace(old_string, new_string);
47
+ await ctx.sandbox.fs.write(path, updated);
48
+ await ctx.services?.filePool?.recordEdit(path);
49
+ return {
50
+ ok: true,
51
+ path,
52
+ replacements: 1,
53
+ lines: updated.split('\n').length,
54
+ };
55
+ }
56
+ },
57
+ metadata: {
58
+ readonly: false,
59
+ version: '1.0',
60
+ },
61
+ });
62
+ exports.FsEdit.prompt = prompt_1.PROMPT;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROMPT = exports.DESCRIPTION = void 0;
4
+ exports.DESCRIPTION = 'Edit a file by replacing old_string with new_string';
5
+ exports.PROMPT = `Use this tool for precise in-place edits.
6
+
7
+ Guidelines:
8
+ - Provide a unique "old_string" snippet to replace. If multiple matches exist, set "replace_all" to true.
9
+ - Combine with fs_read to confirm the current file state before editing.
10
+ - The tool integrates with FilePool to ensure the file has not changed externally.
11
+ - If old_string is not unique, the tool will reject the operation unless replace_all is true.
12
+
13
+ Safety/Limitations:
14
+ - Single replacements require exact unique matches to avoid unintended changes.
15
+ - Freshness validation prevents conflicts with external modifications.`;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FsGlob = 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.FsGlob = (0, tool_1.tool)({
9
+ name: 'fs_glob',
10
+ description: prompt_1.DESCRIPTION,
11
+ parameters: zod_1.z.object({
12
+ pattern: zod_1.z.string().describe('Glob pattern to match'),
13
+ cwd: type_inference_1.patterns.optionalString('Optional directory to resolve from'),
14
+ dot: zod_1.z.boolean().optional().describe('Include dotfiles (default: false)'),
15
+ limit: type_inference_1.patterns.optionalNumber('Maximum number of results (default: 200)'),
16
+ }),
17
+ async execute(args, ctx) {
18
+ const { pattern, cwd, dot = false, limit = 200 } = args;
19
+ const matches = await ctx.sandbox.fs.glob(pattern, {
20
+ cwd,
21
+ dot,
22
+ absolute: false,
23
+ });
24
+ const truncated = matches.length > limit;
25
+ const results = matches.slice(0, limit);
26
+ return {
27
+ ok: true,
28
+ pattern,
29
+ cwd: cwd || '.',
30
+ truncated,
31
+ count: matches.length,
32
+ matches: results,
33
+ };
34
+ },
35
+ metadata: {
36
+ readonly: true,
37
+ version: '1.0',
38
+ },
39
+ });
40
+ exports.FsGlob.prompt = prompt_1.PROMPT;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROMPT = exports.DESCRIPTION = void 0;
4
+ exports.DESCRIPTION = 'List files matching glob patterns';
5
+ exports.PROMPT = `Use this tool to locate files with glob patterns (e.g. "src/**/*.ts").
6
+
7
+ Guidelines:
8
+ - It respects sandbox boundaries and returns relative paths by default.
9
+ - Use standard glob syntax: * (any chars), ** (recursive directories), ? (single char).
10
+ - Set "dot" to true to include hidden files (starting with .).
11
+ - Results are limited to prevent overwhelming responses.
12
+
13
+ Safety/Limitations:
14
+ - All paths are restricted to the sandbox root directory.
15
+ - Large result sets are truncated with a warning.`;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FsGrep = 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.FsGrep = (0, tool_1.tool)({
9
+ name: 'fs_grep',
10
+ description: prompt_1.DESCRIPTION,
11
+ parameters: zod_1.z.object({
12
+ pattern: zod_1.z.string().describe('String or regular expression to search for'),
13
+ path: zod_1.z.string().describe('File path or glob pattern'),
14
+ regex: zod_1.z.boolean().optional().describe('Interpret pattern as regular expression (default: false)'),
15
+ case_sensitive: zod_1.z.boolean().optional().describe('Case sensitive search (default: true)'),
16
+ max_results: type_inference_1.patterns.optionalNumber('Maximum matches to return (default: 200)'),
17
+ }),
18
+ async execute(args, ctx) {
19
+ const { pattern, path, regex = false, case_sensitive = true, max_results = 200 } = args;
20
+ if (!pattern) {
21
+ return { ok: false, error: 'pattern must not be empty' };
22
+ }
23
+ const files = await ctx.sandbox.fs.glob(path, { absolute: false, dot: true });
24
+ const regexPattern = regex
25
+ ? new RegExp(pattern, case_sensitive ? 'g' : 'gi')
26
+ : new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), case_sensitive ? 'g' : 'gi');
27
+ const matches = [];
28
+ for (const file of files) {
29
+ if (matches.length >= max_results)
30
+ break;
31
+ const content = await ctx.sandbox.fs.read(file);
32
+ const lines = content.split('\n');
33
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
34
+ if (matches.length >= max_results)
35
+ break;
36
+ const line = lines[lineIndex];
37
+ regexPattern.lastIndex = 0;
38
+ let match;
39
+ while ((match = regexPattern.exec(line))) {
40
+ matches.push({
41
+ path: file,
42
+ line: lineIndex + 1,
43
+ column: match.index + 1,
44
+ preview: line.trim().slice(0, 200),
45
+ });
46
+ if (matches.length >= max_results)
47
+ break;
48
+ if (!regex)
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ return {
54
+ ok: true,
55
+ pattern,
56
+ path,
57
+ matches,
58
+ truncated: matches.length >= max_results && files.length > 0,
59
+ };
60
+ },
61
+ metadata: {
62
+ readonly: true,
63
+ version: '1.0',
64
+ },
65
+ });
66
+ exports.FsGrep.prompt = prompt_1.PROMPT;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROMPT = exports.DESCRIPTION = void 0;
4
+ exports.DESCRIPTION = 'Search for text patterns inside files';
5
+ exports.PROMPT = `Search one or more files for a literal string or regular expression.
6
+
7
+ Guidelines:
8
+ - Use this to locate references before editing.
9
+ - The "path" parameter can be a specific file or a glob pattern (e.g., "src/**/*.ts").
10
+ - Set "regex" to true to interpret the pattern as a regular expression.
11
+ - Case-sensitive by default; set "case_sensitive" to false for case-insensitive search.
12
+ - Results include file path, line number, column number, and a preview of the match.
13
+
14
+ Safety/Limitations:
15
+ - Result sets are limited to prevent overwhelming responses.
16
+ - Search is constrained to the sandbox directory.`;