@probelabs/probe 0.6.0-rc284 → 0.6.0-rc285

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 (38) hide show
  1. package/bin/binaries/{probe-v0.6.0-rc284-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc285-aarch64-apple-darwin.tar.gz} +0 -0
  2. package/bin/binaries/probe-v0.6.0-rc285-aarch64-unknown-linux-musl.tar.gz +0 -0
  3. package/bin/binaries/probe-v0.6.0-rc285-x86_64-apple-darwin.tar.gz +0 -0
  4. package/bin/binaries/probe-v0.6.0-rc285-x86_64-pc-windows-msvc.zip +0 -0
  5. package/bin/binaries/probe-v0.6.0-rc285-x86_64-unknown-linux-musl.tar.gz +0 -0
  6. package/build/agent/ProbeAgent.d.ts +1 -1
  7. package/build/agent/ProbeAgent.js +333 -486
  8. package/build/agent/contextCompactor.js +17 -10
  9. package/build/agent/index.js +301 -702
  10. package/build/agent/schemaUtils.js +10 -11
  11. package/build/agent/shared/prompts.js +2 -2
  12. package/build/agent/tasks/taskTool.js +3 -3
  13. package/build/agent/tools.js +0 -2
  14. package/build/index.js +0 -2
  15. package/build/tools/analyzeAll.js +4 -4
  16. package/build/tools/common.js +55 -55
  17. package/build/tools/index.js +0 -1
  18. package/build/tools/vercel.js +3 -3
  19. package/cjs/agent/ProbeAgent.cjs +292 -758
  20. package/cjs/index.cjs +293 -814
  21. package/package.json +1 -1
  22. package/src/agent/ProbeAgent.d.ts +1 -1
  23. package/src/agent/ProbeAgent.js +333 -486
  24. package/src/agent/contextCompactor.js +17 -10
  25. package/src/agent/index.js +8 -2
  26. package/src/agent/schemaUtils.js +10 -11
  27. package/src/agent/shared/prompts.js +2 -2
  28. package/src/agent/tasks/taskTool.js +3 -3
  29. package/src/agent/tools.js +0 -2
  30. package/src/index.js +0 -2
  31. package/src/tools/analyzeAll.js +4 -4
  32. package/src/tools/common.js +55 -55
  33. package/src/tools/index.js +0 -1
  34. package/src/tools/vercel.js +3 -3
  35. package/bin/binaries/probe-v0.6.0-rc284-aarch64-unknown-linux-musl.tar.gz +0 -0
  36. package/bin/binaries/probe-v0.6.0-rc284-x86_64-apple-darwin.tar.gz +0 -0
  37. package/bin/binaries/probe-v0.6.0-rc284-x86_64-pc-windows-msvc.zip +0 -0
  38. package/bin/binaries/probe-v0.6.0-rc284-x86_64-unknown-linux-musl.tar.gz +0 -0
@@ -58,7 +58,7 @@ export function generateExampleFromSchema(schema, options = {}) {
58
58
  export function generateSchemaInstructions(schema, options = {}) {
59
59
  const { debug = false } = options;
60
60
 
61
- let instructions = '\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n';
61
+ let instructions = '\n\nIMPORTANT: When you provide your final answer, you MUST format it as valid JSON matching this schema:\n\n';
62
62
 
63
63
  try {
64
64
  const parsedSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
@@ -70,7 +70,7 @@ export function generateSchemaInstructions(schema, options = {}) {
70
70
  instructions += `${schema}\n\n`;
71
71
  }
72
72
 
73
- instructions += 'Your response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.\n\nIMPORTANT: First complete the requested analysis/task thoroughly, then provide your final answer in the JSON format above.';
73
+ instructions += 'Your final response must be ONLY valid JSON - no plain text, no explanations, no markdown.\n\nIMPORTANT: First complete the requested analysis/task thoroughly, then provide your final answer in the JSON format above.';
74
74
 
75
75
  return instructions;
76
76
  }
@@ -1167,22 +1167,22 @@ export function createJsonCorrectionPrompt(invalidResponse, schema, errorOrValid
1167
1167
  }
1168
1168
 
1169
1169
  // Create increasingly stronger prompts based on retry attempt
1170
- // These prompts explicitly instruct the AI to use attempt_completion with the JSON result
1170
+ // These prompts instruct the AI to respond with valid JSON
1171
1171
  const strengthLevels = [
1172
1172
  {
1173
1173
  prefix: "CRITICAL JSON ERROR:",
1174
- instruction: "You MUST fix this and respond using attempt_completion with ONLY valid JSON as the result.",
1175
- emphasis: "Use attempt_completion with ONLY the corrected JSON in the result field. No explanatory text, no markdown, no code blocks."
1174
+ instruction: "You MUST fix this and respond with ONLY valid JSON.",
1175
+ emphasis: "Respond with ONLY the corrected JSON. No explanatory text, no markdown, no code blocks."
1176
1176
  },
1177
1177
  {
1178
1178
  prefix: "URGENT - JSON PARSING FAILED:",
1179
- instruction: "This is your second chance. Use attempt_completion with valid JSON that can be parsed by JSON.parse().",
1180
- emphasis: "ABSOLUTELY NO explanatory text or formatting. Use attempt_completion with ONLY raw JSON in the result."
1179
+ instruction: "This is your second chance. Respond with valid JSON that can be parsed by JSON.parse().",
1180
+ emphasis: "ABSOLUTELY NO explanatory text or formatting. Respond with ONLY raw JSON."
1181
1181
  },
1182
1182
  {
1183
1183
  prefix: "FINAL ATTEMPT - CRITICAL JSON ERROR:",
1184
- instruction: "This is the final retry. You MUST use attempt_completion with ONLY raw JSON in the result field.",
1185
- emphasis: "CORRECT: <attempt_completion><result>{\"key\": \"value\"}</result></attempt_completion>\nWRONG: Here is the JSON: {\"key\": \"value\"}\nWRONG: ```json{\"key\": \"value\"}```"
1184
+ instruction: "This is the final retry. You MUST respond with ONLY raw JSON.",
1185
+ emphasis: "CORRECT: {\"key\": \"value\"}\nWRONG: Here is the JSON: {\"key\": \"value\"}\nWRONG: ```json{\"key\": \"value\"}```"
1186
1186
  }
1187
1187
  ];
1188
1188
 
@@ -2081,8 +2081,7 @@ Provide only the corrected Mermaid diagram within a mermaid code block. Do not a
2081
2081
 
2082
2082
  try {
2083
2083
  // Don't pass schema to avoid infinite loop where AI returns raw mermaid code
2084
- // instead of using attempt_completion tool. The custom prompt already instructs
2085
- // to return only mermaid code blocks.
2084
+ // instead of JSON. The custom prompt already instructs to return only mermaid code blocks.
2086
2085
  const result = await this.agent.answer(prompt, []);
2087
2086
 
2088
2087
  // Extract the mermaid code from the response
@@ -61,7 +61,7 @@ When reviewing code:
61
61
 
62
62
  'engineer': `You are a senior engineer focused on software architecture and design.
63
63
  Before jumping on the task you first analyse the user request in detail, and try to provide an elegant and concise solution.
64
- If the solution is clear, you can jump to implementation right away. If not, ask the user a clarification question by calling the attempt_completion tool with the required details.
64
+ If the solution is clear, you can jump to implementation right away. If not, ask the user a clarification question with the required details.
65
65
 
66
66
  # Tone and Style
67
67
  - Be concise and direct. Explain your approach briefly before implementing, then let the code speak for itself.
@@ -84,7 +84,7 @@ If the solution is clear, you can jump to implementation right away. If not, ask
84
84
  When the request has **multiple distinct goals** (e.g. "Fix bug A AND add feature B"), use the task tool to track them:
85
85
  - Call the task tool with action="create" and a tasks array. Each task must have an "id" field.
86
86
  - Update task status to "in_progress" when starting and "completed" when done.
87
- - All tasks must be completed or cancelled before calling attempt_completion.
87
+ - All tasks must be completed or cancelled before providing your final answer.
88
88
  - Stay flexible — add, remove, or reorganize tasks as your understanding changes.
89
89
 
90
90
  Do NOT create tasks for single-goal requests, even complex ones. Multiple internal steps for one goal (search, read, analyze, implement) do not need tasks.
@@ -69,13 +69,13 @@ Tasks = logical units of work, not files or steps.
69
69
 
70
70
  1. **Plan**: Call task tool with action="create" and a tasks array up front
71
71
  2. **Execute**: Update status to "in_progress" / "completed" as you work. Add, split, or cancel tasks as you learn more.
72
- 3. **Finish**: All tasks must be "completed" or "cancelled" before calling attempt_completion.
72
+ 3. **Finish**: All tasks must be "completed" or "cancelled" before providing your final answer.
73
73
 
74
74
  ## Rules
75
75
 
76
76
  - Dependencies are enforced: a task cannot start until its dependencies are completed
77
77
  - Circular dependencies are rejected
78
- - attempt_completion is blocked while tasks remain unresolved
78
+ - Completion is blocked while tasks remain unresolved
79
79
  `;
80
80
 
81
81
  /**
@@ -101,7 +101,7 @@ For each pending/in_progress task, either:
101
101
  - Complete it: call task tool with action="complete", id="task-X"
102
102
  - Cancel it: call task tool with action="update", id="task-X", status="cancelled"
103
103
 
104
- After all tasks are resolved, call attempt_completion again.`;
104
+ After all tasks are resolved, provide your final answer.`;
105
105
  }
106
106
 
107
107
  /**
@@ -12,7 +12,6 @@ import {
12
12
  createTool,
13
13
  multiEditTool,
14
14
  DEFAULT_SYSTEM_MESSAGE,
15
- attemptCompletionSchema,
16
15
  searchSchema,
17
16
  querySchema,
18
17
  extractSchema,
@@ -107,7 +106,6 @@ export {
107
106
  editSchema,
108
107
  createSchema,
109
108
  multiEditSchema,
110
- attemptCompletionSchema,
111
109
  listFilesSchema,
112
110
  searchFilesSchema,
113
111
  readImageSchema,
package/build/index.js CHANGED
@@ -28,7 +28,6 @@ import {
28
28
  analyzeAllSchema,
29
29
  executePlanSchema,
30
30
  cleanupExecutePlanSchema,
31
- attemptCompletionSchema,
32
31
  bashSchema,
33
32
  listFilesSchema,
34
33
  searchFilesSchema,
@@ -105,7 +104,6 @@ export {
105
104
  analyzeAllSchema,
106
105
  executePlanSchema,
107
106
  cleanupExecutePlanSchema,
108
- attemptCompletionSchema,
109
107
  bashSchema,
110
108
  editSchema,
111
109
  createSchema,
@@ -176,7 +176,7 @@ Instructions:
176
176
  - Format as a structured list if multiple items found
177
177
  - If nothing relevant is found in this chunk, respond with "No relevant items found in this chunk."
178
178
  - Do NOT summarize the code - extract the specific information requested
179
- - When done, use the attempt_completion tool with your answer as the result.`;
179
+ - When done, provide your final answer directly.`;
180
180
 
181
181
  try {
182
182
  const result = await delegate({
@@ -269,7 +269,7 @@ async function aggregateResults(chunkResults, aggregation, extractionPrompt, opt
269
269
  .map(r => `--- Chunk ${r.chunk.id} ---\n${stripResultTags(r.result)}`)
270
270
  .join('\n\n');
271
271
 
272
- const completionNote = `\n\nWhen done, use the attempt_completion tool with your answer as the result.`;
272
+ const completionNote = `\n\nWhen done, provide your final answer directly.`;
273
273
 
274
274
  const aggregationPrompts = {
275
275
  summarize: `Synthesize these analyses into a comprehensive summary. Combine related findings, remove redundancy, and present a coherent overview.
@@ -378,7 +378,7 @@ For example, if looking for customer data:
378
378
  STEP 3: CREATE THE FINAL PLAN
379
379
  Based on your experiments, output the BEST search strategy.
380
380
 
381
- Use attempt_completion with this EXACT format:
381
+ Provide your answer in this EXACT format:
382
382
 
383
383
  SEARCH_QUERY: <the query that WORKED in your experiments - use OR for multiple terms>
384
384
  AGGREGATION: <summarize | list_unique | count | group_by>
@@ -458,7 +458,7 @@ Your answer should:
458
458
 
459
459
  Format your response as a well-structured document that fully answers: "${question}"
460
460
 
461
- When done, use the attempt_completion tool with your answer as the result.`;
461
+ When done, provide your final answer directly.`;
462
462
 
463
463
  try {
464
464
  const result = await delegate({
@@ -85,64 +85,14 @@ export const cleanupExecutePlanSchema = z.object({
85
85
  clearSessionStore: z.boolean().optional().default(false).describe('Clear the session store (persisted data across execute_plan calls)')
86
86
  });
87
87
 
88
- // Schema for the attempt_completion tool - flexible validation for direct XML response
88
+ // Legacy: attemptCompletionSchema kept as no-op for backward compatibility of external imports
89
+ // The attempt_completion tool has been removed — the model now completes naturally via text.
89
90
  export const attemptCompletionSchema = {
90
- // Custom validation that requires result parameter but allows direct XML response
91
91
  safeParse: (params) => {
92
- // Validate that params is an object
93
- if (!params || typeof params !== 'object') {
94
- return {
95
- success: false,
96
- error: {
97
- issues: [{
98
- code: 'invalid_type',
99
- expected: 'object',
100
- received: typeof params,
101
- path: [],
102
- message: 'Expected object'
103
- }]
104
- }
105
- };
92
+ if (!params || typeof params !== 'object' || typeof params.result !== 'string') {
93
+ return { success: false, error: { issues: [{ code: 'invalid_type', path: ['result'], message: 'Deprecated' }] } };
106
94
  }
107
-
108
- // Validate that result parameter exists and is a string
109
- if (!('result' in params)) {
110
- return {
111
- success: false,
112
- error: {
113
- issues: [{
114
- code: 'invalid_type',
115
- expected: 'string',
116
- received: 'undefined',
117
- path: ['result'],
118
- message: 'Required'
119
- }]
120
- }
121
- };
122
- }
123
-
124
- if (typeof params.result !== 'string') {
125
- return {
126
- success: false,
127
- error: {
128
- issues: [{
129
- code: 'invalid_type',
130
- expected: 'string',
131
- received: typeof params.result,
132
- path: ['result'],
133
- message: 'Expected string'
134
- }]
135
- }
136
- };
137
- }
138
-
139
- // Filter out command parameter if present (legacy compatibility)
140
- const filteredData = { result: params.result };
141
-
142
- return {
143
- success: true,
144
- data: filteredData
145
- };
95
+ return { success: true, data: { result: params.result } };
146
96
  }
147
97
  };
148
98
 
@@ -188,6 +138,56 @@ export function createMessagePreview(message, charsPerSide = 200) {
188
138
  }
189
139
 
190
140
 
141
+ /**
142
+ * Detect if a response indicates the agent is stuck in a loop or unable to proceed.
143
+ *
144
+ * @param {string} response - The agent's text response
145
+ * @returns {boolean} - True if the response indicates a stuck state
146
+ */
147
+ export function detectStuckResponse(response) {
148
+ if (!response || typeof response !== 'string') {
149
+ return false;
150
+ }
151
+
152
+ const stuckPatterns = [
153
+ /\bi\s+cannot\s+proceed\b/i,
154
+ /\bi\s+can['']t\s+(?:proceed|continue|move\s+forward)\b/i,
155
+ /\bunable\s+to\s+(?:proceed|continue|complete)\b/i,
156
+ /\bblocked\b.*\b(?:proceed|continue)\b/i,
157
+ /\bneed\s+(?:the|an?)\s+\w+(?:\s+\w+)?\s+to\s+(?:proceed|continue)\b/i,
158
+ /\brequire[sd]?\s+(?:the|an?)\s+\w+\b.*\bto\s+(?:proceed|continue)\b/i,
159
+ /\bmissing\s+(?:required|necessary|essential)\b/i,
160
+ /\bdeadlock\b/i,
161
+ /\bwe\s+are\s+in\s+a\s+loop\b/i,
162
+ /\bstuck\s+in\s+a\s+loop\b/i,
163
+ /\bi\s+(?:have|['']ve)\s+(?:explained|stated|mentioned)\s+(?:this|the\s+situation|it)\s+(?:multiple|several)\s+times\b/i,
164
+ /\bi\s+(?:cannot|can['']t|could\s+not|couldn['']t)\s+(?:find|locate|get|retrieve|obtain)\s+(?:the|this|that|an?)\b/i,
165
+ /\bno\s+way\s+to\s+(?:find|get|obtain|retrieve)\b/i,
166
+ /\bi\s+(?:have|['']ve)\s+exhausted\s+(?:all|my)\s+(?:available\s+)?(?:options|methods|approaches)\b/i,
167
+ /\bneither\s+of\s+these\s+methods\b/i,
168
+ ];
169
+
170
+ for (const pattern of stuckPatterns) {
171
+ if (pattern.test(response)) {
172
+ return true;
173
+ }
174
+ }
175
+
176
+ return false;
177
+ }
178
+
179
+ /**
180
+ * Check if two responses both indicate a stuck state.
181
+ *
182
+ * @param {string} response1 - First response
183
+ * @param {string} response2 - Second response
184
+ * @returns {boolean} - True if both responses indicate a stuck state
185
+ */
186
+ export function areBothStuckResponses(response1, response2) {
187
+ return detectStuckResponse(response1) && detectStuckResponse(response2);
188
+ }
189
+
190
+
191
191
  /**
192
192
  * Parse targets string into array of file specifications
193
193
  * Handles both space-separated and comma-separated targets for extract tool
@@ -25,7 +25,6 @@ export {
25
25
  cleanupExecutePlanSchema,
26
26
  delegateDescription,
27
27
  bashDescription,
28
- attemptCompletionSchema,
29
28
  parseAndResolvePaths,
30
29
  resolveTargetPath,
31
30
  listFilesSchema,
@@ -396,7 +396,7 @@ export const searchTool = (options = {}) => {
396
396
  if (debug) {
397
397
  console.error(`[DEDUP] Blocked duplicate search: "${searchQuery}" (path: "${searchPath}")`);
398
398
  }
399
- return 'DUPLICATE SEARCH BLOCKED: You already searched for this exact query. Changing the path does NOT give different results — probe searches recursively. Do NOT repeat the same search. Try a genuinely different keyword, use extract to examine results you already found, or use attempt_completion if you have enough information.';
399
+ return 'DUPLICATE SEARCH BLOCKED: You already searched for this exact query. Changing the path does NOT give different results — probe searches recursively. Do NOT repeat the same search. Try a genuinely different keyword, use extract to examine results you already found, or provide your final answer if you have enough information.';
400
400
  }
401
401
  previousSearches.add(searchKey);
402
402
  paginationCounts.set(searchKey, 0);
@@ -408,7 +408,7 @@ export const searchTool = (options = {}) => {
408
408
  if (debug) {
409
409
  console.error(`[DEDUP] Blocked excessive pagination (page ${pageCount}/${MAX_PAGES_PER_QUERY}): "${searchQuery}" in "${searchPath}"`);
410
410
  }
411
- return `PAGINATION LIMIT REACHED: You have already retrieved ${MAX_PAGES_PER_QUERY} pages of results for this query. You have enough results — use extract to examine specific files, or use attempt_completion to return your findings.`;
411
+ return `PAGINATION LIMIT REACHED: You have already retrieved ${MAX_PAGES_PER_QUERY} pages of results for this query. You have enough results — use extract to examine specific files, or provide your final answer with your findings.`;
412
412
  }
413
413
  }
414
414
  try {
@@ -450,7 +450,7 @@ export const searchTool = (options = {}) => {
450
450
  bashConfig: null,
451
451
  architectureFileName: options.architectureFileName || null,
452
452
  promptType: 'code-searcher',
453
- allowedTools: ['search', 'extract', 'listFiles', 'attempt_completion'],
453
+ allowedTools: ['search', 'extract', 'listFiles'],
454
454
  searchDelegate: false,
455
455
  schema: CODE_SEARCH_SCHEMA,
456
456
  parentAbortSignal: options.parentAbortSignal || null