codeep 1.2.16 → 1.2.18

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 (63) hide show
  1. package/README.md +20 -7
  2. package/dist/api/index.d.ts +7 -0
  3. package/dist/api/index.js +21 -17
  4. package/dist/renderer/App.d.ts +1 -5
  5. package/dist/renderer/App.js +106 -486
  6. package/dist/renderer/Input.js +8 -1
  7. package/dist/renderer/agentExecution.d.ts +36 -0
  8. package/dist/renderer/agentExecution.js +394 -0
  9. package/dist/renderer/commands.d.ts +16 -0
  10. package/dist/renderer/commands.js +838 -0
  11. package/dist/renderer/handlers.d.ts +87 -0
  12. package/dist/renderer/handlers.js +260 -0
  13. package/dist/renderer/highlight.d.ts +18 -0
  14. package/dist/renderer/highlight.js +130 -0
  15. package/dist/renderer/main.d.ts +4 -2
  16. package/dist/renderer/main.js +103 -1550
  17. package/dist/utils/agent.d.ts +5 -15
  18. package/dist/utils/agent.js +9 -693
  19. package/dist/utils/agentChat.d.ts +46 -0
  20. package/dist/utils/agentChat.js +343 -0
  21. package/dist/utils/agentStream.d.ts +23 -0
  22. package/dist/utils/agentStream.js +216 -0
  23. package/dist/utils/keychain.js +3 -2
  24. package/dist/utils/learning.js +9 -3
  25. package/dist/utils/mcpIntegration.d.ts +61 -0
  26. package/dist/utils/mcpIntegration.js +154 -0
  27. package/dist/utils/project.js +8 -3
  28. package/dist/utils/skills.js +21 -11
  29. package/dist/utils/smartContext.d.ts +4 -0
  30. package/dist/utils/smartContext.js +51 -14
  31. package/dist/utils/toolExecution.d.ts +27 -0
  32. package/dist/utils/toolExecution.js +525 -0
  33. package/dist/utils/toolParsing.d.ts +18 -0
  34. package/dist/utils/toolParsing.js +302 -0
  35. package/dist/utils/tools.d.ts +27 -24
  36. package/dist/utils/tools.js +30 -1169
  37. package/package.json +3 -1
  38. package/dist/config/config.test.d.ts +0 -1
  39. package/dist/config/config.test.js +0 -157
  40. package/dist/config/providers.test.d.ts +0 -1
  41. package/dist/config/providers.test.js +0 -187
  42. package/dist/hooks/index.d.ts +0 -4
  43. package/dist/hooks/index.js +0 -4
  44. package/dist/hooks/useAgent.d.ts +0 -29
  45. package/dist/hooks/useAgent.js +0 -148
  46. package/dist/utils/agent.test.d.ts +0 -1
  47. package/dist/utils/agent.test.js +0 -315
  48. package/dist/utils/git.test.d.ts +0 -1
  49. package/dist/utils/git.test.js +0 -193
  50. package/dist/utils/gitignore.test.d.ts +0 -1
  51. package/dist/utils/gitignore.test.js +0 -167
  52. package/dist/utils/project.test.d.ts +0 -1
  53. package/dist/utils/project.test.js +0 -212
  54. package/dist/utils/ratelimit.test.d.ts +0 -1
  55. package/dist/utils/ratelimit.test.js +0 -131
  56. package/dist/utils/retry.test.d.ts +0 -1
  57. package/dist/utils/retry.test.js +0 -163
  58. package/dist/utils/smartContext.test.d.ts +0 -1
  59. package/dist/utils/smartContext.test.js +0 -382
  60. package/dist/utils/tools.test.d.ts +0 -1
  61. package/dist/utils/tools.test.js +0 -676
  62. package/dist/utils/validation.test.d.ts +0 -1
  63. package/dist/utils/validation.test.js +0 -164
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Tool call parsing from LLM responses.
3
+ *
4
+ * Handles OpenAI function-calling format, Anthropic tool_use format,
5
+ * and legacy text-based tool call formats.
6
+ */
7
+ const debug = (...args) => {
8
+ if (process.env.CODEEP_DEBUG === '1') {
9
+ console.error('[DEBUG]', ...args);
10
+ }
11
+ };
12
+ /**
13
+ * Normalize tool name to lowercase with underscores
14
+ */
15
+ export function normalizeToolName(name) {
16
+ const toolNameMap = {
17
+ 'executecommand': 'execute_command',
18
+ 'execute_command': 'execute_command',
19
+ 'readfile': 'read_file',
20
+ 'read_file': 'read_file',
21
+ 'writefile': 'write_file',
22
+ 'write_file': 'write_file',
23
+ 'editfile': 'edit_file',
24
+ 'edit_file': 'edit_file',
25
+ 'deletefile': 'delete_file',
26
+ 'delete_file': 'delete_file',
27
+ 'listfiles': 'list_files',
28
+ 'list_files': 'list_files',
29
+ 'searchcode': 'search_code',
30
+ 'search_code': 'search_code',
31
+ 'createdirectory': 'create_directory',
32
+ 'create_directory': 'create_directory',
33
+ 'findfiles': 'find_files',
34
+ 'find_files': 'find_files',
35
+ 'fetchurl': 'fetch_url',
36
+ 'fetch_url': 'fetch_url',
37
+ };
38
+ const lower = name.toLowerCase().replace(/-/g, '_');
39
+ return toolNameMap[lower] || lower;
40
+ }
41
+ /**
42
+ * Extract parameters from truncated/partial JSON for tool calls.
43
+ * Fallback when JSON.parse fails due to API truncation.
44
+ */
45
+ function extractPartialToolParams(toolName, rawArgs) {
46
+ try {
47
+ if (toolName === 'write_file') {
48
+ const pathMatch = rawArgs.match(/"path"\s*:\s*"([^"]+)"/);
49
+ if (pathMatch) {
50
+ const contentMatch = rawArgs.match(/"content"\s*:\s*"([\s\S]*?)(?:"|$)/);
51
+ if (contentMatch) {
52
+ let content = contentMatch[1]
53
+ .replace(/\\n/g, '\n')
54
+ .replace(/\\t/g, '\t')
55
+ .replace(/\\r/g, '\r')
56
+ .replace(/\\"/g, '"')
57
+ .replace(/\\\\/g, '\\');
58
+ if (!content.endsWith('\n') && !content.endsWith('}') && !content.endsWith(';') && !content.endsWith('>')) {
59
+ content += '\n<!-- Content may be truncated -->\n';
60
+ }
61
+ return { path: pathMatch[1], content };
62
+ }
63
+ return { path: pathMatch[1], content: '<!-- Content was truncated by API -->\n' };
64
+ }
65
+ }
66
+ if (toolName === 'read_file' || toolName === 'list_files' || toolName === 'create_directory') {
67
+ const pathMatch = rawArgs.match(/"path"\s*:\s*"([^"]+)"/);
68
+ if (pathMatch)
69
+ return { path: pathMatch[1] };
70
+ }
71
+ if (toolName === 'edit_file') {
72
+ const pathMatch = rawArgs.match(/"path"\s*:\s*"([^"]+)"/);
73
+ const oldTextMatch = rawArgs.match(/"old_text"\s*:\s*"([\s\S]*?)(?:"|$)/);
74
+ const newTextMatch = rawArgs.match(/"new_text"\s*:\s*"([\s\S]*?)(?:"|$)/);
75
+ if (pathMatch && oldTextMatch && newTextMatch) {
76
+ return {
77
+ path: pathMatch[1],
78
+ old_text: oldTextMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"'),
79
+ new_text: newTextMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"'),
80
+ };
81
+ }
82
+ }
83
+ if (toolName === 'execute_command') {
84
+ const commandMatch = rawArgs.match(/"command"\s*:\s*"([^"]+)"/);
85
+ if (commandMatch) {
86
+ const argsMatch = rawArgs.match(/"args"\s*:\s*\[([\s\S]*?)\]/);
87
+ let args = [];
88
+ if (argsMatch) {
89
+ const argStrings = argsMatch[1].match(/"([^"]+)"/g);
90
+ if (argStrings)
91
+ args = argStrings.map(s => s.replace(/"/g, ''));
92
+ }
93
+ return { command: commandMatch[1], args };
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+ catch (e) {
99
+ debug('Error in extractPartialToolParams:', e);
100
+ return null;
101
+ }
102
+ }
103
+ export function parseOpenAIToolCalls(toolCalls) {
104
+ if (!toolCalls || !Array.isArray(toolCalls))
105
+ return [];
106
+ const parsed = [];
107
+ for (const tc of toolCalls) {
108
+ const t = tc;
109
+ const toolName = normalizeToolName(t.function?.name || '');
110
+ if (!toolName)
111
+ continue;
112
+ let parameters = {};
113
+ const rawArgs = t.function?.arguments || '{}';
114
+ try {
115
+ parameters = JSON.parse(rawArgs);
116
+ }
117
+ catch {
118
+ debug(`Failed to parse tool arguments for ${toolName}, attempting partial extraction...`);
119
+ debug('Raw args preview:', rawArgs.substring(0, 200));
120
+ const partialParams = extractPartialToolParams(toolName, rawArgs);
121
+ if (partialParams) {
122
+ debug(`Successfully extracted partial params for ${toolName}:`, Object.keys(partialParams));
123
+ parameters = partialParams;
124
+ }
125
+ else {
126
+ debug(`Could not extract params, skipping ${toolName}`);
127
+ continue;
128
+ }
129
+ }
130
+ if (toolName === 'write_file' && !parameters.path) {
131
+ debug(`Skipping write_file - missing path. Raw args:`, rawArgs.substring(0, 200));
132
+ continue;
133
+ }
134
+ if (toolName === 'read_file' && !parameters.path) {
135
+ debug(`Skipping read_file - missing path`);
136
+ continue;
137
+ }
138
+ if (toolName === 'edit_file' && (!parameters.path || parameters.old_text === undefined || parameters.new_text === undefined)) {
139
+ debug(`Skipping edit_file - missing required params`);
140
+ continue;
141
+ }
142
+ parsed.push({ tool: toolName, parameters, id: t.id });
143
+ }
144
+ return parsed;
145
+ }
146
+ export function parseAnthropicToolCalls(content) {
147
+ if (!content || !Array.isArray(content))
148
+ return [];
149
+ return content
150
+ .filter((block) => typeof block === 'object' && block !== null && block.type === 'tool_use')
151
+ .map(block => ({
152
+ tool: normalizeToolName(block.name || ''),
153
+ parameters: block.input || {},
154
+ id: block.id,
155
+ }))
156
+ .filter(tc => tc.tool);
157
+ }
158
+ function tryExtractParams(str) {
159
+ const params = {};
160
+ const argsMatch = str.match(/"args"\s*:\s*\[([\s\S]*?)\]/);
161
+ if (argsMatch) {
162
+ try {
163
+ params.args = JSON.parse(`[${argsMatch[1]}]`);
164
+ }
165
+ catch {
166
+ const items = argsMatch[1].match(/"([^"]*)"/g);
167
+ if (items)
168
+ params.args = items.map(i => i.replace(/"/g, ''));
169
+ }
170
+ }
171
+ const cmdMatch = str.match(/"command"\s*:\s*"([^"]*)"/);
172
+ if (cmdMatch)
173
+ params.command = cmdMatch[1];
174
+ const pathMatch = str.match(/"path"\s*:\s*"([^"]*)"/);
175
+ if (pathMatch)
176
+ params.path = pathMatch[1];
177
+ const contentMatch = str.match(/"content"\s*:\s*"([\s\S]*?)(?<!\\)"/);
178
+ if (contentMatch)
179
+ params.content = contentMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"');
180
+ const oldTextMatch = str.match(/"old_text"\s*:\s*"([\s\S]*?)(?<!\\)"/);
181
+ if (oldTextMatch)
182
+ params.old_text = oldTextMatch[1];
183
+ const newTextMatch = str.match(/"new_text"\s*:\s*"([\s\S]*?)(?<!\\)"/);
184
+ if (newTextMatch)
185
+ params.new_text = newTextMatch[1];
186
+ const patternMatch = str.match(/"pattern"\s*:\s*"([^"]*)"/);
187
+ if (patternMatch)
188
+ params.pattern = patternMatch[1];
189
+ const recursiveMatch = str.match(/"recursive"\s*:\s*(true|false)/i);
190
+ if (recursiveMatch)
191
+ params.recursive = recursiveMatch[1].toLowerCase() === 'true';
192
+ return Object.keys(params).length > 0 ? params : null;
193
+ }
194
+ const TEXT_TOOL_NAME_MAP = {
195
+ 'executecommand': 'execute_command',
196
+ 'readfile': 'read_file',
197
+ 'writefile': 'write_file',
198
+ 'editfile': 'edit_file',
199
+ 'deletefile': 'delete_file',
200
+ 'listfiles': 'list_files',
201
+ 'searchcode': 'search_code',
202
+ 'findfiles': 'find_files',
203
+ };
204
+ function tryParseToolCall(str) {
205
+ try {
206
+ const cleaned = str
207
+ .replace(/[\r\n]+/g, ' ')
208
+ .replace(/,\s*}/g, '}')
209
+ .replace(/,\s*]/g, ']')
210
+ .trim();
211
+ const parsed = JSON.parse(cleaned);
212
+ if (parsed.tool && typeof parsed.tool === 'string') {
213
+ return {
214
+ tool: normalizeToolName(parsed.tool),
215
+ parameters: parsed.parameters || {},
216
+ id: parsed.id,
217
+ };
218
+ }
219
+ }
220
+ catch {
221
+ const toolMatch = str.match(/"tool"\s*:\s*"([^"]+)"/i);
222
+ if (toolMatch) {
223
+ const tool = normalizeToolName(toolMatch[1]);
224
+ const params = {};
225
+ const paramMatches = str.matchAll(/"(\w+)"\s*:\s*"([^"]*)"/g);
226
+ for (const m of paramMatches) {
227
+ if (m[1] !== 'tool')
228
+ params[m[1]] = m[2];
229
+ }
230
+ const boolMatches = str.matchAll(/"(\w+)"\s*:\s*(true|false)/gi);
231
+ for (const m of boolMatches) {
232
+ params[m[1]] = m[2].toLowerCase() === 'true';
233
+ }
234
+ if (Object.keys(params).length > 0) {
235
+ return { tool, parameters: params };
236
+ }
237
+ }
238
+ }
239
+ return null;
240
+ }
241
+ /**
242
+ * Parse tool calls from LLM response text.
243
+ * Supports: <tool_call>, <toolcall>, ```tool blocks, inline JSON.
244
+ */
245
+ export function parseToolCalls(response) {
246
+ const toolCalls = [];
247
+ // Format 1: <tool_call>...</tool_call> or <toolcall>...</toolcall>
248
+ const toolCallRegex = /<tool_?call>\s*([\s\S]*?)\s*<\/tool_?call>/gi;
249
+ let match;
250
+ while ((match = toolCallRegex.exec(response)) !== null) {
251
+ const parsed = tryParseToolCall(match[1].trim());
252
+ if (parsed)
253
+ toolCalls.push(parsed);
254
+ }
255
+ // Format 2: <toolcall>toolname{...}
256
+ const malformedRegex = /<toolcall>(\w+)[\s,]*(?:"parameters"\s*:\s*)?(\{[\s\S]*?\})/gi;
257
+ while ((match = malformedRegex.exec(response)) !== null) {
258
+ const toolName = match[1].toLowerCase();
259
+ const actualToolName = TEXT_TOOL_NAME_MAP[toolName] || toolName;
260
+ try {
261
+ const parsed = JSON.parse(match[2]);
262
+ toolCalls.push({ tool: actualToolName, parameters: parsed.parameters || parsed });
263
+ }
264
+ catch {
265
+ const params = tryExtractParams(match[2]);
266
+ if (params)
267
+ toolCalls.push({ tool: actualToolName, parameters: params });
268
+ }
269
+ }
270
+ // Format 2b: loose toolname + parameters key
271
+ const looseRegex = /<toolcall>(\w+)[,\s]+["']?parameters["']?\s*:\s*(\{[\s\S]*?\})(?:<\/toolcall>|<|$)/gi;
272
+ while ((match = looseRegex.exec(response)) !== null) {
273
+ const toolName = match[1].toLowerCase();
274
+ const actualToolName = TEXT_TOOL_NAME_MAP[toolName] || toolName;
275
+ if (toolCalls.some(t => t.tool === actualToolName))
276
+ continue;
277
+ const params = tryExtractParams(match[2]);
278
+ if (params)
279
+ toolCalls.push({ tool: actualToolName, parameters: params });
280
+ }
281
+ // Format 3: ```tool or ```json code blocks
282
+ const codeBlockRegex = /```(?:tool|json)?\s*\n?([\s\S]*?)\n?```/g;
283
+ while ((match = codeBlockRegex.exec(response)) !== null) {
284
+ const content = match[1].trim();
285
+ if (content.includes('"tool"') || content.includes('"parameters"')) {
286
+ const parsed = tryParseToolCall(content);
287
+ if (parsed && !toolCalls.some(t => t.tool === parsed.tool && JSON.stringify(t.parameters) === JSON.stringify(parsed.parameters))) {
288
+ toolCalls.push(parsed);
289
+ }
290
+ }
291
+ }
292
+ // Format 4: Inline JSON with tool property (fallback)
293
+ if (toolCalls.length === 0) {
294
+ const jsonRegex = /\{[^{}]*"tool"\s*:\s*"[^"]+"\s*,\s*"parameters"\s*:\s*\{[^{}]*\}[^{}]*\}/g;
295
+ while ((match = jsonRegex.exec(response)) !== null) {
296
+ const parsed = tryParseToolCall(match[0]);
297
+ if (parsed)
298
+ toolCalls.push(parsed);
299
+ }
300
+ }
301
+ return toolCalls;
302
+ }
@@ -1,5 +1,10 @@
1
1
  /**
2
- * Agent tools - definitions and execution
2
+ * Agent tools - definitions, interfaces, and re-exports.
3
+ *
4
+ * Heavy implementation is split into:
5
+ * mcpIntegration.ts — Z.AI and MiniMax MCP API helpers
6
+ * toolParsing.ts — parseToolCalls, parseOpenAIToolCalls, parseAnthropicToolCalls
7
+ * toolExecution.ts — executeTool, validatePath, createActionLog
3
8
  */
4
9
  export interface OpenAITool {
5
10
  type: 'function';
@@ -273,7 +278,26 @@ export declare const AGENT_TOOLS: {
273
278
  };
274
279
  };
275
280
  };
281
+ minimax_understand_image: {
282
+ name: string;
283
+ description: string;
284
+ parameters: {
285
+ prompt: {
286
+ type: string;
287
+ description: string;
288
+ required: boolean;
289
+ };
290
+ image_url: {
291
+ type: string;
292
+ description: string;
293
+ required: boolean;
294
+ };
295
+ };
296
+ };
276
297
  };
298
+ /**
299
+ * Format tool definitions for system prompt (text-based fallback)
300
+ */
277
301
  export declare function formatToolDefinitions(): string;
278
302
  /**
279
303
  * Get tools in OpenAI Function Calling format
@@ -283,26 +307,5 @@ export declare function getOpenAITools(): OpenAITool[];
283
307
  * Get tools in Anthropic Tool Use format
284
308
  */
285
309
  export declare function getAnthropicTools(): AnthropicTool[];
286
- export declare function parseOpenAIToolCalls(toolCalls: any[]): ToolCall[];
287
- /**
288
- * Parse tool calls from Anthropic response
289
- */
290
- export declare function parseAnthropicToolCalls(content: any[]): ToolCall[];
291
- /**
292
- * Parse tool calls from LLM response
293
- * Supports multiple formats:
294
- * - <tool_call>{"tool": "name", "parameters": {...}}</tool_call>
295
- * - <toolcall>{"tool": "name", "parameters": {...}}</toolcall>
296
- * - <toolcall>toolname{"parameters": {...}}</toolcall>
297
- * - ```tool\n{"tool": "name", "parameters": {...}}\n```
298
- * - Direct JSON blocks with tool property
299
- */
300
- export declare function parseToolCalls(response: string): ToolCall[];
301
- /**
302
- * Execute a tool call
303
- */
304
- export declare function executeTool(toolCall: ToolCall, projectRoot: string): Promise<ToolResult>;
305
- /**
306
- * Create action log from tool result
307
- */
308
- export declare function createActionLog(toolCall: ToolCall, result: ToolResult): ActionLog;
310
+ export { normalizeToolName, parseOpenAIToolCalls, parseAnthropicToolCalls, parseToolCalls } from './toolParsing';
311
+ export { executeTool, validatePath, createActionLog } from './toolExecution';