@luckydraw/cumulus 0.27.40 → 0.28.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.
Files changed (99) hide show
  1. package/dist/gateway/adapters/webchat.d.ts +5 -7
  2. package/dist/gateway/adapters/webchat.d.ts.map +1 -1
  3. package/dist/gateway/adapters/webchat.js +204 -57
  4. package/dist/gateway/adapters/webchat.js.map +1 -1
  5. package/dist/gateway/config.d.ts +48 -0
  6. package/dist/gateway/config.d.ts.map +1 -1
  7. package/dist/gateway/config.js +90 -0
  8. package/dist/gateway/config.js.map +1 -1
  9. package/dist/gateway/daemon.d.ts.map +1 -1
  10. package/dist/gateway/daemon.js +268 -27
  11. package/dist/gateway/daemon.js.map +1 -1
  12. package/dist/gateway/gateway-agents-mcp.js +570 -31
  13. package/dist/gateway/gateway-agents-mcp.js.map +1 -1
  14. package/dist/gateway/hooks.d.ts +101 -0
  15. package/dist/gateway/hooks.d.ts.map +1 -0
  16. package/dist/gateway/hooks.js +200 -0
  17. package/dist/gateway/hooks.js.map +1 -0
  18. package/dist/gateway/scheduler.d.ts +50 -0
  19. package/dist/gateway/scheduler.d.ts.map +1 -0
  20. package/dist/gateway/scheduler.js +263 -0
  21. package/dist/gateway/scheduler.js.map +1 -0
  22. package/dist/gateway/server.d.ts +16 -1
  23. package/dist/gateway/server.d.ts.map +1 -1
  24. package/dist/gateway/server.js +451 -22
  25. package/dist/gateway/server.js.map +1 -1
  26. package/dist/gateway/static/blex.min.js +74 -17
  27. package/dist/gateway/static/chat.html +1 -4
  28. package/dist/gateway/static/dashboard.html +151 -0
  29. package/dist/gateway/static/dashboard.js +229 -0
  30. package/dist/gateway/static/widget.js +656 -460
  31. package/dist/index.d.ts +13 -5
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +9 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/lib/agentic-loop.d.ts +124 -0
  36. package/dist/lib/agentic-loop.d.ts.map +1 -0
  37. package/dist/lib/agentic-loop.js +338 -0
  38. package/dist/lib/agentic-loop.js.map +1 -0
  39. package/dist/lib/config.d.ts +28 -15
  40. package/dist/lib/config.d.ts.map +1 -1
  41. package/dist/lib/config.js +47 -41
  42. package/dist/lib/config.js.map +1 -1
  43. package/dist/lib/gateway.d.ts +34 -3
  44. package/dist/lib/gateway.d.ts.map +1 -1
  45. package/dist/lib/gateway.js +584 -37
  46. package/dist/lib/gateway.js.map +1 -1
  47. package/dist/lib/huggingface-provider.d.ts +26 -0
  48. package/dist/lib/huggingface-provider.d.ts.map +1 -0
  49. package/dist/lib/huggingface-provider.js +338 -0
  50. package/dist/lib/huggingface-provider.js.map +1 -0
  51. package/dist/lib/provider.d.ts +71 -0
  52. package/dist/lib/provider.d.ts.map +1 -0
  53. package/dist/lib/provider.js +90 -0
  54. package/dist/lib/provider.js.map +1 -0
  55. package/dist/lib/tools/ask-user-question.d.ts +14 -0
  56. package/dist/lib/tools/ask-user-question.d.ts.map +1 -0
  57. package/dist/lib/tools/ask-user-question.js +74 -0
  58. package/dist/lib/tools/ask-user-question.js.map +1 -0
  59. package/dist/lib/tools/bash.d.ts +6 -0
  60. package/dist/lib/tools/bash.d.ts.map +1 -0
  61. package/dist/lib/tools/bash.js +85 -0
  62. package/dist/lib/tools/bash.js.map +1 -0
  63. package/dist/lib/tools/edit.d.ts +6 -0
  64. package/dist/lib/tools/edit.d.ts.map +1 -0
  65. package/dist/lib/tools/edit.js +79 -0
  66. package/dist/lib/tools/edit.js.map +1 -0
  67. package/dist/lib/tools/glob.d.ts +6 -0
  68. package/dist/lib/tools/glob.d.ts.map +1 -0
  69. package/dist/lib/tools/glob.js +91 -0
  70. package/dist/lib/tools/glob.js.map +1 -0
  71. package/dist/lib/tools/grep.d.ts +6 -0
  72. package/dist/lib/tools/grep.d.ts.map +1 -0
  73. package/dist/lib/tools/grep.js +110 -0
  74. package/dist/lib/tools/grep.js.map +1 -0
  75. package/dist/lib/tools/index.d.ts +29 -0
  76. package/dist/lib/tools/index.d.ts.map +1 -0
  77. package/dist/lib/tools/index.js +52 -0
  78. package/dist/lib/tools/index.js.map +1 -0
  79. package/dist/lib/tools/read.d.ts +6 -0
  80. package/dist/lib/tools/read.d.ts.map +1 -0
  81. package/dist/lib/tools/read.js +80 -0
  82. package/dist/lib/tools/read.js.map +1 -0
  83. package/dist/lib/tools/tool-search.d.ts +30 -0
  84. package/dist/lib/tools/tool-search.d.ts.map +1 -0
  85. package/dist/lib/tools/tool-search.js +108 -0
  86. package/dist/lib/tools/tool-search.js.map +1 -0
  87. package/dist/lib/tools/web-fetch.d.ts +9 -0
  88. package/dist/lib/tools/web-fetch.d.ts.map +1 -0
  89. package/dist/lib/tools/web-fetch.js +114 -0
  90. package/dist/lib/tools/web-fetch.js.map +1 -0
  91. package/dist/lib/tools/web-search.d.ts +12 -0
  92. package/dist/lib/tools/web-search.d.ts.map +1 -0
  93. package/dist/lib/tools/web-search.js +89 -0
  94. package/dist/lib/tools/web-search.js.map +1 -0
  95. package/dist/lib/tools/write.d.ts +6 -0
  96. package/dist/lib/tools/write.d.ts.map +1 -0
  97. package/dist/lib/tools/write.js +44 -0
  98. package/dist/lib/tools/write.js.map +1 -0
  99. package/package.json +3 -2
@@ -0,0 +1,90 @@
1
+ /**
2
+ * LLM Provider abstraction.
3
+ *
4
+ * Normalizes the interface across different LLM APIs so the agentic loop
5
+ * doesn't care who generates the response.
6
+ */
7
+ import Anthropic from '@anthropic-ai/sdk';
8
+ // ─── Anthropic Provider ──────────────────────────────────────────────────────
9
+ const DEFAULT_MAX_TOKENS = 16384;
10
+ const MAX_RETRIES = 3;
11
+ const RETRY_DELAYS = [1000, 2000, 4000]; // exponential backoff
12
+ export class AnthropicProvider {
13
+ client;
14
+ constructor(apiKey) {
15
+ this.client = new Anthropic({
16
+ apiKey: apiKey || process.env.ANTHROPIC_API_KEY,
17
+ });
18
+ }
19
+ async chat(options) {
20
+ const { model, system, messages, tools, maxTokens, onEvent, signal } = options;
21
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
22
+ try {
23
+ return await this._streamChat(model, system, messages, tools, maxTokens, onEvent, signal);
24
+ }
25
+ catch (err) {
26
+ const status = err.status;
27
+ const isRetryable = status === 429 || status === 529 || status === 500;
28
+ const isOversize = status === 413;
29
+ if (isOversize) {
30
+ // Context too large — caller should trim messages and retry
31
+ throw Object.assign(new Error('Context too large (413)'), { status: 413 });
32
+ }
33
+ if (isRetryable && attempt < MAX_RETRIES) {
34
+ const delay = RETRY_DELAYS[attempt] || 4000;
35
+ console.warn(`[AnthropicProvider] ${status} error, retrying in ${delay}ms (attempt ${attempt + 1}/${MAX_RETRIES})`);
36
+ await sleep(delay);
37
+ continue;
38
+ }
39
+ throw err;
40
+ }
41
+ }
42
+ // Should not reach here
43
+ throw new Error('Max retries exceeded');
44
+ }
45
+ async _streamChat(model, system, messages, tools, maxTokens, onEvent, signal) {
46
+ const stream = this.client.messages.stream({
47
+ model,
48
+ max_tokens: maxTokens || DEFAULT_MAX_TOKENS,
49
+ system: system,
50
+ messages,
51
+ tools: tools.length > 0 ? tools : undefined,
52
+ }, signal ? { signal } : undefined);
53
+ stream.on('text', (text) => {
54
+ onEvent?.({ type: 'text', text });
55
+ });
56
+ stream.on('contentBlock', (block) => {
57
+ if (block.type === 'tool_use') {
58
+ const toolCall = {
59
+ id: block.id,
60
+ name: block.name,
61
+ input: block.input,
62
+ };
63
+ onEvent?.({ type: 'tool_use_complete', toolCall });
64
+ }
65
+ });
66
+ const finalMessage = await stream.finalMessage();
67
+ const usage = {
68
+ input_tokens: finalMessage.usage.input_tokens,
69
+ output_tokens: finalMessage.usage.output_tokens,
70
+ cache_read_input_tokens: finalMessage.usage
71
+ .cache_read_input_tokens,
72
+ cache_creation_input_tokens: finalMessage.usage
73
+ .cache_creation_input_tokens,
74
+ };
75
+ onEvent?.({
76
+ type: 'done',
77
+ stopReason: finalMessage.stop_reason || 'end_turn',
78
+ usage,
79
+ });
80
+ return {
81
+ content: finalMessage.content,
82
+ stopReason: finalMessage.stop_reason || 'end_turn',
83
+ usage,
84
+ };
85
+ }
86
+ }
87
+ function sleep(ms) {
88
+ return new Promise(resolve => setTimeout(resolve, ms));
89
+ }
90
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/lib/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * AskUserQuestion tool — pauses the agentic loop to ask the user a question.
3
+ *
4
+ * This tool is intercepted by the agentic loop before execution. When the LLM
5
+ * calls it, the loop yields a `needsInput` result instead of executing the tool
6
+ * locally. The caller (gateway) sends the question to the user, waits for a
7
+ * response, then resumes the loop with the user's answer as the tool_result.
8
+ *
9
+ * Renders as blex:poll (multiple options) or blex:confirm (yes/no) in webchat.
10
+ */
11
+ import type { Tool } from './index.js';
12
+ export declare const ASK_USER_QUESTION_TOOL = "AskUserQuestion";
13
+ export declare const askUserQuestionTool: Tool;
14
+ //# sourceMappingURL=ask-user-question.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-user-question.d.ts","sourceRoot":"","sources":["../../../src/lib/tools/ask-user-question.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,sBAAsB,oBAAoB,CAAC;AAExD,eAAO,MAAM,mBAAmB,EAAE,IAkEjC,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * AskUserQuestion tool — pauses the agentic loop to ask the user a question.
3
+ *
4
+ * This tool is intercepted by the agentic loop before execution. When the LLM
5
+ * calls it, the loop yields a `needsInput` result instead of executing the tool
6
+ * locally. The caller (gateway) sends the question to the user, waits for a
7
+ * response, then resumes the loop with the user's answer as the tool_result.
8
+ *
9
+ * Renders as blex:poll (multiple options) or blex:confirm (yes/no) in webchat.
10
+ */
11
+ export const ASK_USER_QUESTION_TOOL = 'AskUserQuestion';
12
+ export const askUserQuestionTool = {
13
+ definition: {
14
+ name: ASK_USER_QUESTION_TOOL,
15
+ description: 'Ask the user one or more questions and wait for their response. Use this when you need ' +
16
+ 'clarification, confirmation, or choices from the user before proceeding. ' +
17
+ 'The agentic loop pauses until the user responds.\n\n' +
18
+ 'For a SINGLE question: provide `question` + optional `options`.\n' +
19
+ 'For MULTIPLE questions: provide `questions` array (renders as a multi-question carousel).\n' +
20
+ 'If no options are provided and allowFreeform is false, it becomes a yes/no confirm.',
21
+ input_schema: {
22
+ type: 'object',
23
+ properties: {
24
+ question: {
25
+ type: 'string',
26
+ description: 'The question to ask the user (for single-question mode).',
27
+ },
28
+ options: {
29
+ type: 'array',
30
+ items: { type: 'string' },
31
+ description: 'Optional list of choices for a single question. ' +
32
+ 'If omitted and allowFreeform is false, renders as a yes/no confirmation.',
33
+ },
34
+ allowFreeform: {
35
+ type: 'boolean',
36
+ description: 'If true, the user can type a free-text answer in addition to (or instead of) picking an option. ' +
37
+ 'Default: false.',
38
+ },
39
+ questions: {
40
+ type: 'array',
41
+ description: 'For multi-question carousels. Each item has question, options, and optional multiSelect/writeIn. ' +
42
+ 'When provided, `question` and `options` are ignored.',
43
+ items: {
44
+ type: 'object',
45
+ properties: {
46
+ question: { type: 'string', description: 'The question text.' },
47
+ options: {
48
+ type: 'array',
49
+ items: { type: 'string' },
50
+ description: 'Choices for this question.',
51
+ },
52
+ multiSelect: {
53
+ type: 'boolean',
54
+ description: 'Allow selecting multiple options. Default: false.',
55
+ },
56
+ writeIn: {
57
+ type: 'boolean',
58
+ description: 'Allow a free-text write-in answer. Default: false.',
59
+ },
60
+ },
61
+ required: ['question', 'options'],
62
+ },
63
+ },
64
+ },
65
+ required: [],
66
+ },
67
+ },
68
+ // This executor should never actually run — the agentic loop intercepts this
69
+ // tool before execution. If it somehow executes, return a sensible fallback.
70
+ async execute(input, _cwd) {
71
+ return `[AskUserQuestion was not intercepted by the loop. Question: ${input.question}]`;
72
+ },
73
+ };
74
+ //# sourceMappingURL=ask-user-question.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-user-question.js","sourceRoot":"","sources":["../../../src/lib/tools/ask-user-question.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,CAAC,MAAM,sBAAsB,GAAG,iBAAiB,CAAC;AAExD,MAAM,CAAC,MAAM,mBAAmB,GAAS;IACvC,UAAU,EAAE;QACV,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EACT,yFAAyF;YACzF,2EAA2E;YAC3E,sDAAsD;YACtD,mEAAmE;YACnE,6FAA6F;YAC7F,qFAAqF;QACvF,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,0DAA0D;iBACxE;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EACT,kDAAkD;wBAClD,0EAA0E;iBAC7E;gBACD,aAAa,EAAE;oBACb,IAAI,EAAE,SAAS;oBACf,WAAW,EACT,kGAAkG;wBAClG,iBAAiB;iBACpB;gBACD,SAAS,EAAE;oBACT,IAAI,EAAE,OAAO;oBACb,WAAW,EACT,mGAAmG;wBACnG,sDAAsD;oBACxD,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;4BAC/D,OAAO,EAAE;gCACP,IAAI,EAAE,OAAO;gCACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gCACzB,WAAW,EAAE,4BAA4B;6BAC1C;4BACD,WAAW,EAAE;gCACX,IAAI,EAAE,SAAS;gCACf,WAAW,EAAE,mDAAmD;6BACjE;4BACD,OAAO,EAAE;gCACP,IAAI,EAAE,SAAS;gCACf,WAAW,EAAE,oDAAoD;6BAClE;yBACF;wBACD,QAAQ,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC;qBAClC;iBACF;aACF;YACD,QAAQ,EAAE,EAAE;SACb;KACF;IAED,6EAA6E;IAC7E,6EAA6E;IAC7E,KAAK,CAAC,OAAO,CAAC,KAA8B,EAAE,IAAY;QACxD,OAAO,+DAA+D,KAAK,CAAC,QAAQ,GAAG,CAAC;IAC1F,CAAC;CACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Bash tool — execute shell commands with timeout.
3
+ */
4
+ import type { Tool } from './index.js';
5
+ export declare const bashTool: Tool;
6
+ //# sourceMappingURL=bash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/lib/tools/bash.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAMvC,eAAO,MAAM,QAAQ,EAAE,IAqFtB,CAAC"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Bash tool — execute shell commands with timeout.
3
+ */
4
+ import { spawn } from 'child_process';
5
+ const DEFAULT_TIMEOUT = 120_000; // 2 minutes
6
+ const MAX_TIMEOUT = 600_000; // 10 minutes
7
+ const MAX_OUTPUT = 100_000; // 100KB output cap
8
+ export const bashTool = {
9
+ definition: {
10
+ name: 'Bash',
11
+ description: 'Execute a shell command and return its output. ' +
12
+ 'The working directory is the project directory. ' +
13
+ 'Commands time out after 2 minutes by default (configurable up to 10 minutes).',
14
+ input_schema: {
15
+ type: 'object',
16
+ properties: {
17
+ command: {
18
+ type: 'string',
19
+ description: 'The bash command to execute',
20
+ },
21
+ timeout: {
22
+ type: 'number',
23
+ description: 'Timeout in milliseconds (default: 120000, max: 600000)',
24
+ },
25
+ },
26
+ required: ['command'],
27
+ },
28
+ },
29
+ async execute(input, cwd) {
30
+ const command = input.command;
31
+ const timeout = Math.min(input.timeout || DEFAULT_TIMEOUT, MAX_TIMEOUT);
32
+ return new Promise(resolve => {
33
+ let stdout = '';
34
+ let stderr = '';
35
+ let killed = false;
36
+ const proc = spawn('bash', ['-c', command], {
37
+ cwd,
38
+ env: { ...process.env, TERM: 'dumb' },
39
+ stdio: ['ignore', 'pipe', 'pipe'],
40
+ });
41
+ const timer = setTimeout(() => {
42
+ killed = true;
43
+ proc.kill('SIGTERM');
44
+ setTimeout(() => proc.kill('SIGKILL'), 5000);
45
+ }, timeout);
46
+ proc.stdout.on('data', (data) => {
47
+ stdout += data.toString();
48
+ if (stdout.length > MAX_OUTPUT) {
49
+ stdout = stdout.slice(0, MAX_OUTPUT) + '\n\n[Output truncated at 100KB]';
50
+ killed = true;
51
+ proc.kill('SIGTERM');
52
+ }
53
+ });
54
+ proc.stderr.on('data', (data) => {
55
+ stderr += data.toString();
56
+ if (stderr.length > MAX_OUTPUT) {
57
+ stderr = stderr.slice(0, MAX_OUTPUT);
58
+ }
59
+ });
60
+ proc.on('close', code => {
61
+ clearTimeout(timer);
62
+ let result = '';
63
+ if (stdout)
64
+ result += stdout;
65
+ if (stderr) {
66
+ if (result)
67
+ result += '\n';
68
+ result += `STDERR:\n${stderr}`;
69
+ }
70
+ if (killed) {
71
+ result += `\n\n[Command timed out after ${timeout}ms]`;
72
+ }
73
+ else if (code !== 0 && code !== null) {
74
+ result += `\nExit code: ${code}`;
75
+ }
76
+ resolve(result || `(no output, exit code ${code})`);
77
+ });
78
+ proc.on('error', err => {
79
+ clearTimeout(timer);
80
+ resolve(`Error executing command: ${err.message}`);
81
+ });
82
+ });
83
+ },
84
+ };
85
+ //# sourceMappingURL=bash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/lib/tools/bash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Edit tool — exact string replacement in files.
3
+ */
4
+ import type { Tool } from './index.js';
5
+ export declare const editTool: Tool;
6
+ //# sourceMappingURL=edit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/lib/tools/edit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,QAAQ,EAAE,IA8EtB,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Edit tool — exact string replacement in files.
3
+ */
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ export const editTool = {
7
+ definition: {
8
+ name: 'Edit',
9
+ description: 'Perform exact string replacements in files. The old_string must be unique in the file ' +
10
+ 'unless replace_all is true. Use this for surgical edits — prefer over Write for modifying existing files.',
11
+ input_schema: {
12
+ type: 'object',
13
+ properties: {
14
+ file_path: {
15
+ type: 'string',
16
+ description: 'Absolute path to the file to modify',
17
+ },
18
+ old_string: {
19
+ type: 'string',
20
+ description: 'The exact text to find and replace',
21
+ },
22
+ new_string: {
23
+ type: 'string',
24
+ description: 'The replacement text',
25
+ },
26
+ replace_all: {
27
+ type: 'boolean',
28
+ description: 'If true, replace all occurrences. Default: false.',
29
+ },
30
+ },
31
+ required: ['file_path', 'old_string', 'new_string'],
32
+ },
33
+ },
34
+ async execute(input, cwd) {
35
+ const filePath = resolvePath(input.file_path, cwd);
36
+ const oldString = input.old_string;
37
+ const newString = input.new_string;
38
+ const replaceAll = input.replace_all || false;
39
+ if (!fs.existsSync(filePath)) {
40
+ return `Error: File not found: ${filePath}`;
41
+ }
42
+ const content = fs.readFileSync(filePath, 'utf-8');
43
+ if (oldString === newString) {
44
+ return 'Error: old_string and new_string are identical';
45
+ }
46
+ if (!content.includes(oldString)) {
47
+ // Provide context: show similar lines
48
+ const lines = content.split('\n');
49
+ const needle = oldString.trim().split('\n')[0].trim();
50
+ const similar = lines
51
+ .filter(l => l.includes(needle.slice(0, 20)))
52
+ .slice(0, 3)
53
+ .map(l => ` ${l.trim()}`);
54
+ let msg = `Error: old_string not found in ${filePath}`;
55
+ if (similar.length > 0) {
56
+ msg += `\nSimilar lines found:\n${similar.join('\n')}`;
57
+ }
58
+ return msg;
59
+ }
60
+ if (!replaceAll) {
61
+ const count = content.split(oldString).length - 1;
62
+ if (count > 1) {
63
+ return `Error: old_string appears ${count} times in ${filePath}. Use replace_all: true to replace all, or provide more context to make old_string unique.`;
64
+ }
65
+ }
66
+ const updated = replaceAll
67
+ ? content.split(oldString).join(newString)
68
+ : content.replace(oldString, newString);
69
+ fs.writeFileSync(filePath, updated, 'utf-8');
70
+ const replacements = replaceAll ? content.split(oldString).length - 1 : 1;
71
+ return `Edited ${filePath}: ${replacements} replacement(s) made`;
72
+ },
73
+ };
74
+ function resolvePath(filePath, cwd) {
75
+ if (path.isAbsolute(filePath))
76
+ return filePath;
77
+ return path.resolve(cwd, filePath);
78
+ }
79
+ //# sourceMappingURL=edit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/lib/tools/edit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Glob tool — find files by pattern.
3
+ */
4
+ import type { Tool } from './index.js';
5
+ export declare const globTool: Tool;
6
+ //# sourceMappingURL=glob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../../src/lib/tools/glob.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,eAAO,MAAM,QAAQ,EAAE,IAqDtB,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Glob tool — find files by pattern.
3
+ */
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
6
+ const MAX_RESULTS = 500;
7
+ export const globTool = {
8
+ definition: {
9
+ name: 'Glob',
10
+ description: 'Find files matching a glob pattern. Returns file paths sorted by modification time (newest first).',
11
+ input_schema: {
12
+ type: 'object',
13
+ properties: {
14
+ pattern: {
15
+ type: 'string',
16
+ description: 'Glob pattern to match (e.g., "**/*.ts", "src/**/*.test.ts")',
17
+ },
18
+ path: {
19
+ type: 'string',
20
+ description: 'Directory to search in. Defaults to current working directory.',
21
+ },
22
+ },
23
+ required: ['pattern'],
24
+ },
25
+ },
26
+ async execute(input, cwd) {
27
+ const pattern = input.pattern;
28
+ const searchPath = input.path || cwd;
29
+ try {
30
+ const files = await globMatch(pattern, searchPath);
31
+ if (files.length === 0) {
32
+ return '(no matching files)';
33
+ }
34
+ // Sort by mtime (newest first)
35
+ const withStats = files.map(f => {
36
+ try {
37
+ const stat = fs.statSync(f);
38
+ return { path: f, mtime: stat.mtimeMs };
39
+ }
40
+ catch {
41
+ return { path: f, mtime: 0 };
42
+ }
43
+ });
44
+ withStats.sort((a, b) => b.mtime - a.mtime);
45
+ const result = withStats.slice(0, MAX_RESULTS).map(f => f.path);
46
+ let output = result.join('\n');
47
+ if (files.length > MAX_RESULTS) {
48
+ output += `\n\n(${files.length - MAX_RESULTS} more files not shown)`;
49
+ }
50
+ return output;
51
+ }
52
+ catch (err) {
53
+ return `Error: ${err.message}`;
54
+ }
55
+ },
56
+ };
57
+ /**
58
+ * Simple glob matching using Node's fs.
59
+ * Handles **, *, and ? patterns.
60
+ */
61
+ async function globMatch(pattern, baseDir) {
62
+ // Use node:fs with recursive readdir + minimatch-style filtering
63
+ // For simplicity, use a shell glob via find or bash
64
+ const { execFileSync } = await import('child_process');
65
+ try {
66
+ // Use bash globbing (simplest, most reliable)
67
+ const result = execFileSync('bash', ['-c', `shopt -s globstar nullglob; printf '%s\\n' ${pattern}`], {
68
+ cwd: baseDir,
69
+ encoding: 'utf-8',
70
+ maxBuffer: 1024 * 1024,
71
+ timeout: 10_000,
72
+ });
73
+ return result
74
+ .trim()
75
+ .split('\n')
76
+ .filter(line => line.length > 0)
77
+ .map(f => path.resolve(baseDir, f))
78
+ .filter(f => {
79
+ try {
80
+ return fs.statSync(f).isFile();
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ });
86
+ }
87
+ catch {
88
+ return [];
89
+ }
90
+ }
91
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sourceRoot":"","sources":["../../../src/lib/tools/glob.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Grep tool — search file contents using ripgrep.
3
+ */
4
+ import type { Tool } from './index.js';
5
+ export declare const grepTool: Tool;
6
+ //# sourceMappingURL=grep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../../src/lib/tools/grep.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,eAAO,MAAM,QAAQ,EAAE,IAwFtB,CAAC"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Grep tool — search file contents using ripgrep.
3
+ */
4
+ import { execFileSync } from 'child_process';
5
+ const MAX_RESULTS = 200;
6
+ export const grepTool = {
7
+ definition: {
8
+ name: 'Grep',
9
+ description: 'Search file contents using regular expressions (powered by ripgrep). ' +
10
+ 'Returns matching file paths by default, or matching lines with content mode.',
11
+ input_schema: {
12
+ type: 'object',
13
+ properties: {
14
+ pattern: {
15
+ type: 'string',
16
+ description: 'Regular expression pattern to search for',
17
+ },
18
+ path: {
19
+ type: 'string',
20
+ description: 'File or directory to search in. Defaults to current working directory.',
21
+ },
22
+ output_mode: {
23
+ type: 'string',
24
+ enum: ['files_with_matches', 'content', 'count'],
25
+ description: 'Output mode. Default: files_with_matches.',
26
+ },
27
+ glob: {
28
+ type: 'string',
29
+ description: 'Glob pattern to filter files (e.g., "*.ts", "*.{js,jsx}")',
30
+ },
31
+ type: {
32
+ type: 'string',
33
+ description: 'File type to search (e.g., "ts", "py", "js")',
34
+ },
35
+ context: {
36
+ type: 'number',
37
+ description: 'Number of context lines before and after each match',
38
+ },
39
+ '-i': {
40
+ type: 'boolean',
41
+ description: 'Case insensitive search',
42
+ },
43
+ },
44
+ required: ['pattern'],
45
+ },
46
+ },
47
+ async execute(input, cwd) {
48
+ const pattern = input.pattern;
49
+ const searchPath = input.path || cwd;
50
+ const outputMode = input.output_mode || 'files_with_matches';
51
+ const globPattern = input.glob;
52
+ const fileType = input.type;
53
+ const context = input.context;
54
+ const caseInsensitive = input['-i'];
55
+ // Build rg args
56
+ const args = ['--no-heading'];
57
+ if (outputMode === 'files_with_matches') {
58
+ args.push('-l');
59
+ }
60
+ else if (outputMode === 'count') {
61
+ args.push('-c');
62
+ }
63
+ else {
64
+ args.push('-n'); // line numbers for content mode
65
+ }
66
+ if (caseInsensitive)
67
+ args.push('-i');
68
+ if (globPattern)
69
+ args.push('--glob', globPattern);
70
+ if (fileType)
71
+ args.push('--type', fileType);
72
+ if (context && outputMode === 'content')
73
+ args.push('-C', String(context));
74
+ args.push('--max-count', String(MAX_RESULTS));
75
+ args.push('--', pattern, searchPath);
76
+ try {
77
+ const rgPath = findRg();
78
+ const result = execFileSync(rgPath, args, {
79
+ cwd,
80
+ encoding: 'utf-8',
81
+ maxBuffer: 1024 * 1024, // 1MB
82
+ timeout: 30_000,
83
+ });
84
+ return result.trim() || '(no matches)';
85
+ }
86
+ catch (err) {
87
+ const execErr = err;
88
+ if (execErr.status === 1) {
89
+ return '(no matches)';
90
+ }
91
+ return `Error: ${execErr.stderr || 'grep failed'}`;
92
+ }
93
+ },
94
+ };
95
+ function findRg() {
96
+ // Try common locations
97
+ const candidates = ['rg', '/usr/bin/rg', '/usr/local/bin/rg'];
98
+ for (const candidate of candidates) {
99
+ try {
100
+ execFileSync('which', [candidate], { encoding: 'utf-8', stdio: 'pipe' });
101
+ return candidate;
102
+ }
103
+ catch {
104
+ // continue
105
+ }
106
+ }
107
+ // Fallback to PATH
108
+ return 'rg';
109
+ }
110
+ //# sourceMappingURL=grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/lib/tools/grep.ts"],"names":[],"mappings":"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"}