@probelabs/probe 0.6.0-rc67 → 0.6.0-rc70
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/build/agent/ProbeAgent.js +63 -3
- package/build/agent/acp/tools.js +26 -0
- package/build/agent/acp/tools.test.js +27 -1
- package/build/agent/index.js +374 -64
- package/build/agent/probeTool.js +9 -0
- package/build/agent/schemaUtils.js +140 -10
- package/build/agent/tools.js +10 -3
- package/build/delegate.js +187 -0
- package/build/index.js +8 -1
- package/build/tools/common.js +93 -47
- package/build/tools/index.js +6 -2
- package/build/tools/vercel.js +38 -1
- package/cjs/agent/ProbeAgent.cjs +382 -71
- package/cjs/index.cjs +414 -71
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +63 -3
- package/src/agent/acp/tools.js +26 -0
- package/src/agent/acp/tools.test.js +27 -1
- package/src/agent/probeTool.js +9 -0
- package/src/agent/schemaUtils.js +140 -10
- package/src/agent/tools.js +10 -3
- package/src/delegate.js +187 -0
- package/src/index.js +8 -1
- package/src/tools/common.js +93 -47
- package/src/tools/index.js +6 -2
- package/src/tools/vercel.js +38 -1
|
@@ -115,9 +115,13 @@ export class ProbeAgent {
|
|
|
115
115
|
search: wrappedTools.searchToolInstance,
|
|
116
116
|
query: wrappedTools.queryToolInstance,
|
|
117
117
|
extract: wrappedTools.extractToolInstance,
|
|
118
|
+
delegate: wrappedTools.delegateToolInstance,
|
|
118
119
|
listFiles: listFilesToolInstance,
|
|
119
120
|
searchFiles: searchFilesToolInstance,
|
|
120
121
|
};
|
|
122
|
+
|
|
123
|
+
// Store wrapped tools for ACP system
|
|
124
|
+
this.wrappedTools = wrappedTools;
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
/**
|
|
@@ -580,8 +584,15 @@ When troubleshooting:
|
|
|
580
584
|
throw new Error(finalResult);
|
|
581
585
|
}
|
|
582
586
|
|
|
583
|
-
// Parse tool call from response
|
|
584
|
-
const
|
|
587
|
+
// Parse tool call from response with valid tools list
|
|
588
|
+
const validTools = [
|
|
589
|
+
'search', 'query', 'extract', 'listFiles', 'searchFiles', 'attempt_completion'
|
|
590
|
+
];
|
|
591
|
+
if (this.allowEdit) {
|
|
592
|
+
validTools.push('implement');
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const parsedTool = parseXmlToolCallWithThinking(assistantResponseContent, validTools);
|
|
585
596
|
if (parsedTool) {
|
|
586
597
|
const { toolName, params } = parsedTool;
|
|
587
598
|
if (this.debug) console.log(`[DEBUG] Parsed tool call: ${toolName} with params:`, params);
|
|
@@ -614,6 +625,22 @@ When troubleshooting:
|
|
|
614
625
|
|
|
615
626
|
// Execute tool with tracing if available
|
|
616
627
|
const executeToolCall = async () => {
|
|
628
|
+
// For delegate tool, pass current iteration and max iterations
|
|
629
|
+
if (toolName === 'delegate') {
|
|
630
|
+
const enhancedParams = {
|
|
631
|
+
...toolParams,
|
|
632
|
+
currentIteration,
|
|
633
|
+
maxIterations,
|
|
634
|
+
debug: this.debug
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
if (this.debug) {
|
|
638
|
+
console.log(`[DEBUG] Executing delegate tool at iteration ${currentIteration}/${maxIterations}`);
|
|
639
|
+
console.log(`[DEBUG] Delegate task: ${toolParams.task?.substring(0, 100)}...`);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
return await this.toolImplementations[toolName].execute(enhancedParams);
|
|
643
|
+
}
|
|
617
644
|
return await this.toolImplementations[toolName].execute(toolParams);
|
|
618
645
|
};
|
|
619
646
|
|
|
@@ -722,7 +749,8 @@ When troubleshooting:
|
|
|
722
749
|
this.tokenCounter.updateHistory(this.history);
|
|
723
750
|
|
|
724
751
|
// Schema handling - format response according to provided schema
|
|
725
|
-
|
|
752
|
+
// Skip schema processing if result came from attempt_completion tool
|
|
753
|
+
if (options.schema && !options._schemaFormatted && !completionAttempted) {
|
|
726
754
|
if (this.debug) {
|
|
727
755
|
console.log('[DEBUG] Schema provided, applying automatic formatting...');
|
|
728
756
|
}
|
|
@@ -822,6 +850,38 @@ Convert your previous response content into this JSON format now. Return nothing
|
|
|
822
850
|
console.error('[ERROR] Schema formatting failed:', error);
|
|
823
851
|
// Return the original result if schema formatting fails
|
|
824
852
|
}
|
|
853
|
+
} else if (completionAttempted && options.schema) {
|
|
854
|
+
// For attempt_completion results with schema, still clean markdown if needed
|
|
855
|
+
try {
|
|
856
|
+
finalResult = cleanSchemaResponse(finalResult);
|
|
857
|
+
|
|
858
|
+
// Validate and fix Mermaid diagrams if present
|
|
859
|
+
const mermaidValidation = await validateAndFixMermaidResponse(finalResult, {
|
|
860
|
+
debug: this.debug,
|
|
861
|
+
path: this.allowedFolders[0],
|
|
862
|
+
provider: this.clientApiProvider,
|
|
863
|
+
model: this.model
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
if (mermaidValidation.wasFixed) {
|
|
867
|
+
finalResult = mermaidValidation.fixedResponse;
|
|
868
|
+
if (this.debug) {
|
|
869
|
+
console.log(`[DEBUG] Mermaid diagrams fixed in attempt_completion result`);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// Validate JSON if schema expects JSON
|
|
874
|
+
if (isJsonSchema(options.schema)) {
|
|
875
|
+
const validation = validateJsonResponse(finalResult);
|
|
876
|
+
if (!validation.isValid && this.debug) {
|
|
877
|
+
console.log(`[DEBUG] attempt_completion result JSON validation failed: ${validation.error}`);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
} catch (error) {
|
|
881
|
+
if (this.debug) {
|
|
882
|
+
console.log(`[DEBUG] attempt_completion result cleanup failed: ${error.message}`);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
825
885
|
}
|
|
826
886
|
|
|
827
887
|
return finalResult;
|
package/build/agent/acp/tools.js
CHANGED
|
@@ -160,6 +160,8 @@ export class ACPToolManager {
|
|
|
160
160
|
return ToolCallKind.query;
|
|
161
161
|
case 'extract':
|
|
162
162
|
return ToolCallKind.extract;
|
|
163
|
+
case 'delegate':
|
|
164
|
+
return ToolCallKind.execute;
|
|
163
165
|
case 'implement':
|
|
164
166
|
return ToolCallKind.edit;
|
|
165
167
|
default:
|
|
@@ -202,6 +204,15 @@ export class ACPToolManager {
|
|
|
202
204
|
sessionId: this.probeAgent.sessionId
|
|
203
205
|
});
|
|
204
206
|
|
|
207
|
+
case 'delegate':
|
|
208
|
+
if (!tools.delegateToolInstance) {
|
|
209
|
+
throw new Error('Delegate tool not available');
|
|
210
|
+
}
|
|
211
|
+
return await tools.delegateToolInstance.execute({
|
|
212
|
+
...params,
|
|
213
|
+
sessionId: this.probeAgent.sessionId
|
|
214
|
+
});
|
|
215
|
+
|
|
205
216
|
default:
|
|
206
217
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
207
218
|
}
|
|
@@ -336,6 +347,21 @@ export class ACPToolManager {
|
|
|
336
347
|
},
|
|
337
348
|
required: ['files']
|
|
338
349
|
}
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
name: 'delegate',
|
|
353
|
+
description: 'Automatically delegate big distinct tasks to specialized probe subagents within the agentic loop. Use when complex requests can be broken into focused, parallel tasks.',
|
|
354
|
+
kind: ToolCallKind.execute,
|
|
355
|
+
parameters: {
|
|
356
|
+
type: 'object',
|
|
357
|
+
properties: {
|
|
358
|
+
task: {
|
|
359
|
+
type: 'string',
|
|
360
|
+
description: 'A complete, self-contained task that can be executed independently by a subagent. Should be specific and focused on one area of expertise.'
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
required: ['task']
|
|
364
|
+
}
|
|
339
365
|
}
|
|
340
366
|
];
|
|
341
367
|
}
|
|
@@ -101,6 +101,9 @@ describe('ACPToolManager', () => {
|
|
|
101
101
|
},
|
|
102
102
|
extractToolInstance: {
|
|
103
103
|
execute: jest.fn().mockResolvedValue('extract result')
|
|
104
|
+
},
|
|
105
|
+
delegateToolInstance: {
|
|
106
|
+
execute: jest.fn().mockResolvedValue('delegate result')
|
|
104
107
|
}
|
|
105
108
|
}
|
|
106
109
|
};
|
|
@@ -113,6 +116,7 @@ describe('ACPToolManager', () => {
|
|
|
113
116
|
expect(toolManager.getToolKind('search')).toBe(ToolCallKind.search);
|
|
114
117
|
expect(toolManager.getToolKind('query')).toBe(ToolCallKind.query);
|
|
115
118
|
expect(toolManager.getToolKind('extract')).toBe(ToolCallKind.extract);
|
|
119
|
+
expect(toolManager.getToolKind('delegate')).toBe(ToolCallKind.execute);
|
|
116
120
|
expect(toolManager.getToolKind('implement')).toBe(ToolCallKind.edit);
|
|
117
121
|
expect(toolManager.getToolKind('unknown')).toBe(ToolCallKind.execute);
|
|
118
122
|
});
|
|
@@ -167,6 +171,18 @@ describe('ACPToolManager', () => {
|
|
|
167
171
|
});
|
|
168
172
|
});
|
|
169
173
|
|
|
174
|
+
test('should execute delegate tool successfully', async () => {
|
|
175
|
+
const params = { task: 'Analyze security vulnerabilities in authentication code' };
|
|
176
|
+
|
|
177
|
+
const result = await toolManager.executeToolCall('session-123', 'delegate', params);
|
|
178
|
+
|
|
179
|
+
expect(result).toBe('delegate result');
|
|
180
|
+
expect(mockProbeAgent.wrappedTools.delegateToolInstance.execute).toHaveBeenCalledWith({
|
|
181
|
+
...params,
|
|
182
|
+
sessionId: 'test-session'
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
170
186
|
test('should handle tool execution errors', async () => {
|
|
171
187
|
const error = new Error('Tool execution failed');
|
|
172
188
|
mockProbeAgent.wrappedTools.searchToolInstance.execute.mockRejectedValue(error);
|
|
@@ -187,6 +203,10 @@ describe('ACPToolManager', () => {
|
|
|
187
203
|
mockProbeAgent.wrappedTools.searchToolInstance = null;
|
|
188
204
|
|
|
189
205
|
await expect(toolManager.executeToolCall('session-123', 'search', {})).rejects.toThrow('Search tool not available');
|
|
206
|
+
|
|
207
|
+
mockProbeAgent.wrappedTools.delegateToolInstance = null;
|
|
208
|
+
|
|
209
|
+
await expect(toolManager.executeToolCall('session-123', 'delegate', {})).rejects.toThrow('Delegate tool not available');
|
|
190
210
|
});
|
|
191
211
|
});
|
|
192
212
|
|
|
@@ -263,7 +283,7 @@ describe('ACPToolManager', () => {
|
|
|
263
283
|
test('should provide correct tool definitions', () => {
|
|
264
284
|
const definitions = ACPToolManager.getToolDefinitions();
|
|
265
285
|
|
|
266
|
-
expect(definitions).toHaveLength(
|
|
286
|
+
expect(definitions).toHaveLength(4);
|
|
267
287
|
|
|
268
288
|
const searchTool = definitions.find(d => d.name === 'search');
|
|
269
289
|
expect(searchTool).toBeDefined();
|
|
@@ -282,6 +302,12 @@ describe('ACPToolManager', () => {
|
|
|
282
302
|
expect(extractTool.kind).toBe(ToolCallKind.extract);
|
|
283
303
|
expect(extractTool.parameters.properties.files).toBeDefined();
|
|
284
304
|
expect(extractTool.parameters.required).toContain('files');
|
|
305
|
+
|
|
306
|
+
const delegateTool = definitions.find(d => d.name === 'delegate');
|
|
307
|
+
expect(delegateTool).toBeDefined();
|
|
308
|
+
expect(delegateTool.kind).toBe(ToolCallKind.execute);
|
|
309
|
+
expect(delegateTool.parameters.properties.task).toBeDefined();
|
|
310
|
+
expect(delegateTool.parameters.required).toContain('task');
|
|
285
311
|
});
|
|
286
312
|
});
|
|
287
313
|
|