@probelabs/probe 0.6.0-rc203 → 0.6.0-rc205

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 (44) hide show
  1. package/bin/binaries/probe-v0.6.0-rc205-aarch64-apple-darwin.tar.gz +0 -0
  2. package/bin/binaries/probe-v0.6.0-rc205-aarch64-unknown-linux-musl.tar.gz +0 -0
  3. package/bin/binaries/probe-v0.6.0-rc205-x86_64-apple-darwin.tar.gz +0 -0
  4. package/bin/binaries/probe-v0.6.0-rc205-x86_64-pc-windows-msvc.zip +0 -0
  5. package/bin/binaries/probe-v0.6.0-rc205-x86_64-unknown-linux-musl.tar.gz +0 -0
  6. package/build/agent/ProbeAgent.d.ts +2 -0
  7. package/build/agent/ProbeAgent.js +233 -40
  8. package/build/agent/index.js +1566 -84
  9. package/build/agent/simpleTelemetry.js +12 -0
  10. package/build/agent/tasks/TaskManager.js +604 -0
  11. package/build/agent/tasks/index.js +15 -0
  12. package/build/agent/tasks/taskTool.js +476 -0
  13. package/build/agent/tools.js +11 -0
  14. package/build/delegate.js +7 -2
  15. package/build/index.js +14 -1
  16. package/build/search.js +19 -5
  17. package/build/tools/common.js +67 -0
  18. package/build/tools/vercel.js +28 -12
  19. package/build/utils/error-types.js +303 -0
  20. package/build/utils/path-validation.js +21 -3
  21. package/cjs/agent/ProbeAgent.cjs +8940 -6393
  22. package/cjs/agent/simpleTelemetry.cjs +10 -0
  23. package/cjs/index.cjs +8960 -6393
  24. package/package.json +2 -2
  25. package/src/agent/ProbeAgent.d.ts +2 -0
  26. package/src/agent/ProbeAgent.js +233 -40
  27. package/src/agent/index.js +14 -2
  28. package/src/agent/simpleTelemetry.js +12 -0
  29. package/src/agent/tasks/TaskManager.js +604 -0
  30. package/src/agent/tasks/index.js +15 -0
  31. package/src/agent/tasks/taskTool.js +476 -0
  32. package/src/agent/tools.js +11 -0
  33. package/src/delegate.js +7 -2
  34. package/src/index.js +14 -1
  35. package/src/search.js +19 -5
  36. package/src/tools/common.js +67 -0
  37. package/src/tools/vercel.js +28 -12
  38. package/src/utils/error-types.js +303 -0
  39. package/src/utils/path-validation.js +21 -3
  40. package/bin/binaries/probe-v0.6.0-rc203-aarch64-apple-darwin.tar.gz +0 -0
  41. package/bin/binaries/probe-v0.6.0-rc203-aarch64-unknown-linux-musl.tar.gz +0 -0
  42. package/bin/binaries/probe-v0.6.0-rc203-x86_64-apple-darwin.tar.gz +0 -0
  43. package/bin/binaries/probe-v0.6.0-rc203-x86_64-pc-windows-msvc.zip +0 -0
  44. package/bin/binaries/probe-v0.6.0-rc203-x86_64-unknown-linux-musl.tar.gz +0 -0
@@ -76,6 +76,8 @@ export interface ProbeAgentOptions {
76
76
  skillDirs?: string[];
77
77
  /** Custom prompt to run after attempt_completion for validation/review (runs before mermaid/JSON validation) */
78
78
  completionPrompt?: string;
79
+ /** Enable task management system for tracking multi-step progress */
80
+ enableTasks?: boolean;
79
81
  }
80
82
 
81
83
  /**
@@ -37,7 +37,7 @@ import {
37
37
  attemptCompletionSchema,
38
38
  parseXmlToolCallWithThinking
39
39
  } from './tools.js';
40
- import { createMessagePreview } from '../tools/common.js';
40
+ import { createMessagePreview, detectUnrecognizedToolCall } from '../tools/common.js';
41
41
  import {
42
42
  createWrappedTools,
43
43
  listFilesToolInstance,
@@ -69,6 +69,15 @@ import { createSkillToolInstances } from './skills/tools.js';
69
69
  import { RetryManager, createRetryManagerFromEnv } from './RetryManager.js';
70
70
  import { FallbackManager, createFallbackManagerFromEnv, buildFallbackProvidersFromEnv } from './FallbackManager.js';
71
71
  import { handleContextLimitError } from './contextCompactor.js';
72
+ import { formatErrorForAI, ParameterError } from '../utils/error-types.js';
73
+ import {
74
+ TaskManager,
75
+ createTaskTool,
76
+ taskToolDefinition,
77
+ taskSystemPrompt,
78
+ taskGuidancePrompt,
79
+ createTaskCompletionBlockedMessage
80
+ } from './tasks/index.js';
72
81
 
73
82
  // Maximum tool iterations to prevent infinite loops - configurable via MAX_TOOL_ITERATIONS env var
74
83
  const MAX_TOOL_ITERATIONS = (() => {
@@ -118,6 +127,7 @@ export class ProbeAgent {
118
127
  * @param {string} [options.mcpConfigPath] - Path to MCP configuration file
119
128
  * @param {Object} [options.mcpConfig] - MCP configuration object (overrides mcpConfigPath)
120
129
  * @param {Array} [options.mcpServers] - Deprecated, use mcpConfig instead
130
+ * @param {boolean} [options.enableTasks=false] - Enable task management system for tracking progress
121
131
  * @param {Object} [options.storageAdapter] - Custom storage adapter for history management
122
132
  * @param {Object} [options.hooks] - Hook callbacks for events (e.g., {'tool:start': callback})
123
133
  * @param {Array<string>|null} [options.allowedTools] - List of allowed tool names. Use ['*'] for all tools (default), [] or null for no tools (raw AI mode), or specific tool names like ['search', 'query', 'extract']. Supports exclusion with '!' prefix (e.g., ['*', '!bash'])
@@ -255,6 +265,10 @@ export class ProbeAgent {
255
265
  this.mcpBridge = null;
256
266
  this._mcpInitialized = false; // Track if MCP initialization has been attempted
257
267
 
268
+ // Task management configuration
269
+ this.enableTasks = !!options.enableTasks;
270
+ this.taskManager = null; // Initialized per-request in answer()
271
+
258
272
  // Retry configuration
259
273
  this.retryConfig = options.retry || {};
260
274
  this.retryManager = null; // Will be initialized lazily when needed
@@ -580,6 +594,9 @@ export class ProbeAgent {
580
594
  // Store wrapped tools for ACP system
581
595
  this.wrappedTools = wrappedTools;
582
596
 
597
+ // Note: Task tool is registered dynamically in answer() when enableTasks is true
598
+ // This is because TaskManager is created per-request (request-scoped)
599
+
583
600
  // Log available tools in debug mode
584
601
  if (this.debug) {
585
602
  console.error('\n[DEBUG] ========================================');
@@ -1987,6 +2004,11 @@ ${extractGuidance}
1987
2004
  toolDefinitions += `${bashToolDefinition}\n`;
1988
2005
  }
1989
2006
 
2007
+ // Task tool (require both enableTasks flag AND allowedTools permission)
2008
+ if (this.enableTasks && isToolAllowed('task')) {
2009
+ toolDefinitions += `${taskToolDefinition}\n`;
2010
+ }
2011
+
1990
2012
  // Always include attempt_completion (unless explicitly disabled in raw AI mode)
1991
2013
  if (isToolAllowed('attempt_completion')) {
1992
2014
  toolDefinitions += `${attemptCompletionToolDefinition}\n`;
@@ -1998,7 +2020,81 @@ ${extractGuidance}
1998
2020
  toolDefinitions += `${delegateToolDefinition}\n`;
1999
2021
  }
2000
2022
 
2001
- // Build XML tool guidelines
2023
+ // Build XML tool guidelines with dynamic examples based on allowed tools
2024
+ // Build examples only for allowed tools
2025
+ let toolExamples = '';
2026
+ if (isToolAllowed('search')) {
2027
+ toolExamples += `
2028
+ <search>
2029
+ <query>error handling</query>
2030
+ <path>src/search</path>
2031
+ </search>
2032
+ `;
2033
+ }
2034
+ if (isToolAllowed('extract')) {
2035
+ toolExamples += `
2036
+ <extract>
2037
+ <targets>src/config.js:15-25</targets>
2038
+ </extract>
2039
+ `;
2040
+ }
2041
+ if (isToolAllowed('attempt_completion')) {
2042
+ toolExamples += `
2043
+ <attempt_completion>
2044
+ The configuration is loaded from src/config.js lines 15-25 which contains the database settings.
2045
+ </attempt_completion>
2046
+ `;
2047
+ }
2048
+
2049
+ // Build available tools list dynamically based on allowedTools
2050
+ let availableToolsList = '';
2051
+ if (isToolAllowed('search')) {
2052
+ availableToolsList += `- search: Search code using keyword queries${this.searchDelegate ? ' (returns extracted code blocks via a dedicated subagent)' : ''}.\n`;
2053
+ }
2054
+ if (isToolAllowed('query')) {
2055
+ availableToolsList += '- query: Search code using structural AST patterns.\n';
2056
+ }
2057
+ if (isToolAllowed('extract')) {
2058
+ availableToolsList += '- extract: Extract specific code blocks or lines from files.\n';
2059
+ }
2060
+ if (isToolAllowed('listFiles')) {
2061
+ availableToolsList += '- listFiles: List files and directories in a specified location.\n';
2062
+ }
2063
+ if (isToolAllowed('searchFiles')) {
2064
+ availableToolsList += '- searchFiles: Find files matching a glob pattern with recursive search capability.\n';
2065
+ }
2066
+ if (this.enableSkills && isToolAllowed('listSkills')) {
2067
+ availableToolsList += '- listSkills: List available agent skills discovered in the repository.\n';
2068
+ }
2069
+ if (this.enableSkills && isToolAllowed('useSkill')) {
2070
+ availableToolsList += '- useSkill: Load and activate a specific skill\'s instructions.\n';
2071
+ }
2072
+ if (isToolAllowed('readImage')) {
2073
+ availableToolsList += '- readImage: Read and load an image file for AI analysis.\n';
2074
+ }
2075
+ if (this.allowEdit && isToolAllowed('implement')) {
2076
+ availableToolsList += '- implement: Implement a feature or fix a bug using aider.\n';
2077
+ }
2078
+ if (this.allowEdit && isToolAllowed('edit')) {
2079
+ availableToolsList += '- edit: Edit files using exact string replacement.\n';
2080
+ }
2081
+ if (this.allowEdit && isToolAllowed('create')) {
2082
+ availableToolsList += '- create: Create new files with specified content.\n';
2083
+ }
2084
+ if (this.enableDelegate && isToolAllowed('delegate')) {
2085
+ availableToolsList += '- delegate: Delegate big distinct tasks to specialized probe subagents.\n';
2086
+ }
2087
+ if (this.enableBash && isToolAllowed('bash')) {
2088
+ availableToolsList += '- bash: Execute bash commands for system operations.\n';
2089
+ }
2090
+ if (this.enableTasks && isToolAllowed('task')) {
2091
+ availableToolsList += '- task: Manage tasks for tracking progress (create, update, complete, delete, list).\n';
2092
+ }
2093
+ if (isToolAllowed('attempt_completion')) {
2094
+ availableToolsList += '- attempt_completion: Finalize the task and provide the result to the user.\n';
2095
+ availableToolsList += '- attempt_complete: Quick completion using previous response (shorthand).\n';
2096
+ }
2097
+
2002
2098
  let xmlToolGuidelines = `
2003
2099
  # Tool Use Formatting
2004
2100
 
@@ -2013,20 +2109,7 @@ Structure (note the closing tags):
2013
2109
  ...
2014
2110
  </tool_name>
2015
2111
 
2016
- Examples:
2017
- <search>
2018
- <query>error handling</query>
2019
- <path>src/search</path>
2020
- </search>
2021
-
2022
- <extract>
2023
- <targets>src/config.js:15-25</targets>
2024
- </extract>
2025
-
2026
- <attempt_completion>
2027
- The configuration is loaded from src/config.js lines 15-25 which contains the database settings.
2028
- </attempt_completion>
2029
-
2112
+ Examples:${toolExamples}
2030
2113
  # Special Case: Quick Completion
2031
2114
  If your previous response was already correct and complete, you may respond with just:
2032
2115
  <attempt_complete>
@@ -2055,16 +2138,7 @@ I need to find code related to error handling in the search module. The most app
2055
2138
  10. If your previous response was already correct and complete, you may use \`<attempt_complete>\` as a shorthand.
2056
2139
 
2057
2140
  Available Tools:
2058
- - search: Search code using keyword queries${this.searchDelegate ? ' (returns extracted code blocks via a dedicated subagent)' : ''}.
2059
- - query: Search code using structural AST patterns.
2060
- - extract: Extract specific code blocks or lines from files.
2061
- - listFiles: List files and directories in a specified location.
2062
- - searchFiles: Find files matching a glob pattern with recursive search capability.
2063
- ${this.enableSkills ? '- listSkills: List available agent skills discovered in the repository.\n- useSkill: Load and activate a specific skill\'s instructions.\n' : ''}- readImage: Read and load an image file for AI analysis.
2064
- ${this.allowEdit ? '- implement: Implement a feature or fix a bug using aider.\n- edit: Edit files using exact string replacement.\n- create: Create new files with specified content.\n' : ''}${this.enableDelegate ? '- delegate: Delegate big distinct tasks to specialized probe subagents.\n' : ''}${this.enableBash ? '- bash: Execute bash commands for system operations.\n' : ''}
2065
- - attempt_completion: Finalize the task and provide the result to the user.
2066
- - attempt_complete: Quick completion using previous response (shorthand).
2067
- `;
2141
+ ${availableToolsList}`;
2068
2142
 
2069
2143
  // Common instructions
2070
2144
  const commonInstructions = `<instructions>
@@ -2126,6 +2200,11 @@ Follow these instructions carefully:
2126
2200
  }
2127
2201
  }
2128
2202
 
2203
+ // Add task management system prompt if enabled
2204
+ if (this.enableTasks) {
2205
+ systemMessage += `\n${taskSystemPrompt}\n`;
2206
+ }
2207
+
2129
2208
  // Add MCP tools if available (filtered by allowedTools)
2130
2209
  if (this.mcpBridge && this.mcpBridge.getToolNames().length > 0) {
2131
2210
  const allMcpTools = this.mcpBridge.getToolNames();
@@ -2199,6 +2278,39 @@ Follow these instructions carefully:
2199
2278
  // Track initial history length for storage
2200
2279
  const oldHistoryLength = this.history.length;
2201
2280
 
2281
+ // START CHECKPOINT: Initialize task management for this request
2282
+ if (this.enableTasks) {
2283
+ try {
2284
+ // Create fresh TaskManager for each request (request-scoped)
2285
+ this.taskManager = new TaskManager({ debug: this.debug });
2286
+
2287
+ // Register task tool for this request
2288
+ const isToolAllowed = (toolName) => this.allowedTools.isEnabled(toolName);
2289
+ if (isToolAllowed('task')) {
2290
+ this.toolImplementations.task = createTaskTool({
2291
+ taskManager: this.taskManager,
2292
+ tracer: this.tracer,
2293
+ debug: this.debug
2294
+ });
2295
+ }
2296
+
2297
+ // Record telemetry for task initialization
2298
+ if (this.tracer && typeof this.tracer.recordTaskEvent === 'function') {
2299
+ this.tracer.recordTaskEvent('session_started', {
2300
+ 'task.enabled': true
2301
+ });
2302
+ }
2303
+
2304
+ if (this.debug) {
2305
+ console.log('[DEBUG] Task management initialized for this request');
2306
+ }
2307
+ } catch (taskInitError) {
2308
+ // Log error but don't fail the request - task management is optional
2309
+ console.error('[ProbeAgent] Failed to initialize task management:', taskInitError.message);
2310
+ this.taskManager = null;
2311
+ }
2312
+ }
2313
+
2202
2314
  // Emit user message hook
2203
2315
  await this.hooks.emit(HOOK_TYPES.MESSAGE_USER, {
2204
2316
  sessionId: this.sessionId,
@@ -2212,6 +2324,14 @@ Follow these instructions carefully:
2212
2324
  // Create user message with optional image support
2213
2325
  let userMessage = { role: 'user', content: message.trim() };
2214
2326
 
2327
+ // START CHECKPOINT: Inject task guidance if tasks are enabled
2328
+ if (this.enableTasks) {
2329
+ userMessage.content = userMessage.content + '\n\n' + taskGuidancePrompt;
2330
+ if (this.debug) {
2331
+ console.log('[DEBUG] Task guidance injected into user message');
2332
+ }
2333
+ }
2334
+
2215
2335
  // If schema is provided, prepend JSON format requirement to user message
2216
2336
  if (options.schema && !options._schemaFormatted) {
2217
2337
  const schemaInstructions = generateSchemaInstructions(options.schema, { debug: this.debug });
@@ -2518,9 +2638,16 @@ Follow these instructions carefully:
2518
2638
  };
2519
2639
 
2520
2640
  if (this.tracer) {
2641
+ // Prepare input preview for tracing (truncate if very long)
2642
+ const inputPreview = message.length > 1000
2643
+ ? message.substring(0, 1000) + '... [truncated]'
2644
+ : message;
2645
+
2521
2646
  await this.tracer.withSpan('ai.request', executeAIRequest, {
2522
2647
  'ai.model': this.model,
2523
2648
  'ai.provider': this.clientApiProvider || 'auto',
2649
+ 'ai.input': inputPreview,
2650
+ 'ai.input_length': message.length,
2524
2651
  'iteration': currentIteration,
2525
2652
  'max_tokens': maxResponseTokens,
2526
2653
  'temperature': 0.3,
@@ -2638,6 +2765,10 @@ Follow these instructions carefully:
2638
2765
  if (this.enableDelegate && this.allowedTools.isEnabled('delegate')) {
2639
2766
  validTools.push('delegate');
2640
2767
  }
2768
+ // Task tool (require both enableTasks flag AND allowedTools permission)
2769
+ if (this.enableTasks && this.allowedTools.isEnabled('task')) {
2770
+ validTools.push('task');
2771
+ }
2641
2772
  }
2642
2773
 
2643
2774
  // Try parsing with hybrid parser that supports both native and MCP tools
@@ -2653,6 +2784,40 @@ Follow these instructions carefully:
2653
2784
  if (toolName === 'attempt_completion') {
2654
2785
  completionAttempted = true;
2655
2786
 
2787
+ // END CHECKPOINT: Block completion if there are incomplete tasks
2788
+ if (this.enableTasks && this.taskManager && this.taskManager.hasIncompleteTasks()) {
2789
+ const taskSummary = this.taskManager.getTaskSummary();
2790
+ const blockedMessage = createTaskCompletionBlockedMessage(taskSummary);
2791
+ const incompleteTasks = this.taskManager.getIncompleteTasks();
2792
+
2793
+ // Record telemetry for blocked completion
2794
+ if (this.tracer && typeof this.tracer.recordTaskEvent === 'function') {
2795
+ this.tracer.recordTaskEvent('completion_blocked', {
2796
+ 'task.incomplete_count': incompleteTasks.length,
2797
+ 'task.incomplete_ids': incompleteTasks.map(t => t.id).join(', '),
2798
+ 'task.iteration': currentIteration
2799
+ });
2800
+ }
2801
+
2802
+ if (this.debug) {
2803
+ console.log('[DEBUG] Task checkpoint: Blocking completion due to incomplete tasks');
2804
+ console.log('[DEBUG] Incomplete tasks:', taskSummary);
2805
+ }
2806
+
2807
+ // Add reminder message and continue the loop
2808
+ currentMessages.push({
2809
+ role: 'assistant',
2810
+ content: assistantResponseContent
2811
+ });
2812
+ currentMessages.push({
2813
+ role: 'user',
2814
+ content: blockedMessage
2815
+ });
2816
+
2817
+ completionAttempted = false; // Reset to allow more iterations
2818
+ continue; // Skip the break and continue the loop
2819
+ }
2820
+
2656
2821
  // Handle attempt_complete shorthand - use previous response
2657
2822
  if (params.result === '__PREVIOUS_RESPONSE__') {
2658
2823
  // Find the last assistant message with actual content (not tool calls)
@@ -2732,7 +2897,6 @@ Follow these instructions carefully:
2732
2897
  currentMessages.push({ role: 'user', content: `<tool_result>\n${toolResultContent}\n</tool_result>` });
2733
2898
  } catch (error) {
2734
2899
  console.error(`Error executing MCP tool ${toolName}:`, error);
2735
- const toolResultContent = `Error executing MCP tool ${toolName}: ${error.message}`;
2736
2900
 
2737
2901
  // Log MCP tool error in debug mode
2738
2902
  if (this.debug) {
@@ -2742,7 +2906,9 @@ Follow these instructions carefully:
2742
2906
  console.error(`[DEBUG] ========================================\n`);
2743
2907
  }
2744
2908
 
2745
- currentMessages.push({ role: 'user', content: `<tool_result>\n${toolResultContent}\n</tool_result>` });
2909
+ // Format error with structured information for AI
2910
+ const errorXml = formatErrorForAI(error);
2911
+ currentMessages.push({ role: 'user', content: `<tool_result>\n${errorXml}\n</tool_result>` });
2746
2912
  }
2747
2913
  } else if (this.toolImplementations[toolName]) {
2748
2914
  // Execute native tool
@@ -2810,6 +2976,7 @@ Follow these instructions carefully:
2810
2976
  provider: this.apiType, // Inherit AI provider (string identifier)
2811
2977
  model: this.model, // Inherit model
2812
2978
  searchDelegate: this.searchDelegate,
2979
+ enableTasks: this.enableTasks, // Inherit task management (subagent gets isolated TaskManager)
2813
2980
  debug: this.debug,
2814
2981
  tracer: this.tracer
2815
2982
  };
@@ -2912,9 +3079,11 @@ Follow these instructions carefully:
2912
3079
  } catch (error) {
2913
3080
  console.error(`[ERROR] Tool execution failed for ${toolName}:`, error);
2914
3081
  currentMessages.push({ role: 'assistant', content: assistantResponseContent });
3082
+ // Format error with structured information for AI
3083
+ const errorXml = formatErrorForAI(error);
2915
3084
  currentMessages.push({
2916
- role: 'user',
2917
- content: `<tool_result>\nError: ${error.message}\n</tool_result>`
3085
+ role: 'user',
3086
+ content: `<tool_result>\n${errorXml}\n</tool_result>`
2918
3087
  });
2919
3088
  }
2920
3089
  } else {
@@ -2928,7 +3097,7 @@ Follow these instructions carefully:
2928
3097
 
2929
3098
  currentMessages.push({
2930
3099
  role: 'user',
2931
- content: `<tool_result>\nError: Unknown tool '${toolName}'. Available tools: ${allAvailableTools.join(', ')}\n</tool_result>`
3100
+ content: `<tool_result>\n<error type="parameter_error" recoverable="true">\n<message>Unknown tool '${toolName}'</message>\n<suggestion>Available tools: ${allAvailableTools.join(', ')}. Please use one of these tools.</suggestion>\n</error>\n</tool_result>`
2932
3101
  });
2933
3102
  }
2934
3103
  }
@@ -2952,8 +3121,22 @@ Follow these instructions carefully:
2952
3121
  // Add assistant response and ask for tool usage
2953
3122
  currentMessages.push({ role: 'assistant', content: assistantResponseContent });
2954
3123
 
2955
- // Standard reminder - schema was already provided in initial message
2956
- const reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
3124
+ // Check if the AI tried to use a tool that's not in the valid tools list
3125
+ const unrecognizedTool = detectUnrecognizedToolCall(assistantResponseContent, validTools);
3126
+
3127
+ let reminderContent;
3128
+ if (unrecognizedTool) {
3129
+ // AI tried to use a tool that's not available - provide clear error
3130
+ if (this.debug) {
3131
+ console.log(`[DEBUG] Detected unrecognized tool '${unrecognizedTool}' in assistant response.`);
3132
+ }
3133
+ const toolError = new ParameterError(`Tool '${unrecognizedTool}' is not available in this context.`, {
3134
+ suggestion: `Available tools: ${validTools.join(', ')}. Please use one of these tools instead.`
3135
+ });
3136
+ reminderContent = `<tool_result>\n${formatErrorForAI(toolError)}\n</tool_result>`;
3137
+ } else {
3138
+ // Standard reminder - no tool call detected at all
3139
+ reminderContent = `Please use one of the available tools to help answer the question, or use attempt_completion if you have enough information to provide a final answer.
2957
3140
 
2958
3141
  Remember: Use proper XML format with BOTH opening and closing tags:
2959
3142
 
@@ -2961,17 +3144,27 @@ Remember: Use proper XML format with BOTH opening and closing tags:
2961
3144
  <parameter>value</parameter>
2962
3145
  </tool_name>
2963
3146
 
2964
- Or for quick completion if your previous response was already correct and complete:
2965
- <attempt_complete>
3147
+ Available tools: ${validTools.join(', ')}
2966
3148
 
2967
- IMPORTANT: When using <attempt_complete>, this must be the ONLY content in your response. No additional text, explanations, or other content should be included. This tag signals to reuse your previous response as the final answer.`;
3149
+ To complete with a direct answer:
3150
+ <attempt_completion>Your final answer here</attempt_completion>
3151
+
3152
+ Or if your previous response already contains a complete, direct answer (not a thinking block or JSON):
3153
+ <attempt_complete></attempt_complete>
3154
+
3155
+ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant message as the final answer. Only use this if that message was already a valid, complete response to the user's question.`;
3156
+ }
2968
3157
 
2969
3158
  currentMessages.push({
2970
3159
  role: 'user',
2971
3160
  content: reminderContent
2972
3161
  });
2973
3162
  if (this.debug) {
2974
- console.log(`[DEBUG] No tool call detected in assistant response. Prompting for tool use.`);
3163
+ if (unrecognizedTool) {
3164
+ console.log(`[DEBUG] Unrecognized tool '${unrecognizedTool}' used. Providing error feedback.`);
3165
+ } else {
3166
+ console.log(`[DEBUG] No tool call detected in assistant response. Prompting for tool use.`);
3167
+ }
2975
3168
  }
2976
3169
  }
2977
3170
 
@@ -3872,9 +4065,9 @@ Convert your previous response content into actual JSON data that follows this s
3872
4065
  return true;
3873
4066
  }
3874
4067
 
3875
- // Empty attempt_complete reminders
3876
- if (content.includes('When using <attempt_complete>') &&
3877
- content.includes('this must be the ONLY content in your response')) {
4068
+ // Empty attempt_complete reminders (legacy and new format)
4069
+ if (content.includes('<attempt_complete></attempt_complete>') &&
4070
+ content.includes('reuses your PREVIOUS assistant message')) {
3878
4071
  return true;
3879
4072
  }
3880
4073