@probelabs/probe 0.6.0-rc239 → 0.6.0-rc241

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 (31) hide show
  1. package/bin/binaries/probe-v0.6.0-rc241-aarch64-apple-darwin.tar.gz +0 -0
  2. package/bin/binaries/{probe-v0.6.0-rc239-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc241-aarch64-unknown-linux-musl.tar.gz} +0 -0
  3. package/bin/binaries/probe-v0.6.0-rc241-x86_64-apple-darwin.tar.gz +0 -0
  4. package/bin/binaries/probe-v0.6.0-rc241-x86_64-pc-windows-msvc.zip +0 -0
  5. package/bin/binaries/probe-v0.6.0-rc241-x86_64-unknown-linux-musl.tar.gz +0 -0
  6. package/build/agent/ProbeAgent.js +20 -2
  7. package/build/agent/dsl/validator.js +99 -8
  8. package/build/agent/index.js +213 -22
  9. package/build/agent/probeTool.js +9 -0
  10. package/build/agent/schemaUtils.js +34 -10
  11. package/build/agent/tools.js +9 -0
  12. package/build/index.js +5 -1
  13. package/build/tools/common.js +6 -0
  14. package/build/tools/executePlan.js +136 -2
  15. package/build/tools/index.js +3 -2
  16. package/cjs/agent/ProbeAgent.cjs +213 -22
  17. package/cjs/index.cjs +219 -19
  18. package/package.json +1 -1
  19. package/src/agent/ProbeAgent.js +20 -2
  20. package/src/agent/dsl/validator.js +99 -8
  21. package/src/agent/probeTool.js +9 -0
  22. package/src/agent/schemaUtils.js +34 -10
  23. package/src/agent/tools.js +9 -0
  24. package/src/index.js +5 -1
  25. package/src/tools/common.js +6 -0
  26. package/src/tools/executePlan.js +136 -2
  27. package/src/tools/index.js +3 -2
  28. package/bin/binaries/probe-v0.6.0-rc239-aarch64-apple-darwin.tar.gz +0 -0
  29. package/bin/binaries/probe-v0.6.0-rc239-x86_64-apple-darwin.tar.gz +0 -0
  30. package/bin/binaries/probe-v0.6.0-rc239-x86_64-pc-windows-msvc.zip +0 -0
  31. package/bin/binaries/probe-v0.6.0-rc239-x86_64-unknown-linux-musl.tar.gz +0 -0
@@ -784,18 +784,42 @@ export function isSimpleTextWrapperSchema(schema) {
784
784
 
785
785
  const trimmed = schema.trim();
786
786
 
787
- // Match patterns like: {text: string}, {"text": "string"}, {response: string}, etc.
788
- // These are simple wrappers that just need a single text field
789
- const simplePatterns = [
790
- /^\{\s*["']?(\w+)["']?\s*:\s*["']?string["']?\s*\}$/i,
791
- /^\{\s*["']?type["']?\s*:\s*["']?object["']?\s*,\s*["']?properties["']?\s*:\s*\{\s*["']?(\w+)["']?\s*:\s*\{\s*["']?type["']?\s*:\s*["']?string["']?\s*\}\s*\}\s*\}$/i
792
- ];
787
+ // First, try parsing as JSON for full JSON Schema format
788
+ try {
789
+ const parsed = JSON.parse(trimmed);
790
+ if (typeof parsed !== 'object' || parsed === null) {
791
+ // Fall through to regex matching
792
+ } else {
793
+ // Shorthand JSON format: {"text": "string"} or {"fieldName": "string"}
794
+ const keys = Object.keys(parsed);
795
+ if (keys.length === 1 && parsed[keys[0]] === 'string') {
796
+ return { fieldName: keys[0] };
797
+ }
793
798
 
794
- for (const pattern of simplePatterns) {
795
- const match = trimmed.match(pattern);
796
- if (match) {
797
- return { fieldName: match[1] };
799
+ // Full JSON Schema format: {"type":"object","properties":{"text":{"type":"string",...}}}
800
+ // Handles schemas with "required", "description", and other extra fields
801
+ if (parsed.type === 'object' && parsed.properties) {
802
+ const propKeys = Object.keys(parsed.properties);
803
+ if (propKeys.length === 1) {
804
+ const prop = parsed.properties[propKeys[0]];
805
+ if (prop && prop.type === 'string') {
806
+ return { fieldName: propKeys[0] };
807
+ }
808
+ }
809
+ }
810
+
811
+ // Valid JSON but not a simple wrapper
812
+ return null;
798
813
  }
814
+ } catch {
815
+ // Not valid JSON, fall through to regex matching
816
+ }
817
+
818
+ // Fallback: regex matching for shorthand formats like {text: string}, {'text': 'string'}
819
+ const simplePattern = /^\{\s*["']?(\w+)["']?\s*:\s*["']?string["']?\s*\}$/i;
820
+ const match = trimmed.match(simplePattern);
821
+ if (match) {
822
+ return { fieldName: match[1] };
799
823
  }
800
824
 
801
825
  return null;
@@ -6,6 +6,7 @@ import {
6
6
  delegateTool,
7
7
  analyzeAllTool,
8
8
  createExecutePlanTool,
9
+ createCleanupExecutePlanTool,
9
10
  bashTool,
10
11
  editTool,
11
12
  createTool,
@@ -18,6 +19,7 @@ import {
18
19
  delegateSchema,
19
20
  analyzeAllSchema,
20
21
  executePlanSchema,
22
+ cleanupExecutePlanSchema,
21
23
  bashSchema,
22
24
  editSchema,
23
25
  createSchema,
@@ -27,6 +29,7 @@ import {
27
29
  delegateToolDefinition,
28
30
  analyzeAllToolDefinition,
29
31
  getExecutePlanToolDefinition,
32
+ getCleanupExecutePlanToolDefinition,
30
33
  bashToolDefinition,
31
34
  editToolDefinition,
32
35
  createToolDefinition,
@@ -63,6 +66,10 @@ export function createTools(configOptions) {
63
66
  }
64
67
  if (configOptions.enableExecutePlan && isToolAllowed('execute_plan')) {
65
68
  tools.executePlanTool = createExecutePlanTool(configOptions);
69
+ // cleanup_execute_plan is enabled together with execute_plan
70
+ if (isToolAllowed('cleanup_execute_plan')) {
71
+ tools.cleanupExecutePlanTool = createCleanupExecutePlanTool(configOptions);
72
+ }
66
73
  } else if (isToolAllowed('analyze_all')) {
67
74
  // analyze_all is fallback when execute_plan is not enabled
68
75
  tools.analyzeAllTool = analyzeAllTool(configOptions);
@@ -104,6 +111,7 @@ export {
104
111
  delegateSchema,
105
112
  analyzeAllSchema,
106
113
  executePlanSchema,
114
+ cleanupExecutePlanSchema,
107
115
  bashSchema,
108
116
  editSchema,
109
117
  createSchema,
@@ -114,6 +122,7 @@ export {
114
122
  delegateToolDefinition,
115
123
  analyzeAllToolDefinition,
116
124
  getExecutePlanToolDefinition,
125
+ getCleanupExecutePlanToolDefinition,
117
126
  bashToolDefinition,
118
127
  editToolDefinition,
119
128
  createToolDefinition,
package/build/index.js CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  delegateSchema,
28
28
  analyzeAllSchema,
29
29
  executePlanSchema,
30
+ cleanupExecutePlanSchema,
30
31
  attemptCompletionSchema,
31
32
  bashSchema,
32
33
  searchToolDefinition,
@@ -47,7 +48,7 @@ import {
47
48
  createToolDefinition
48
49
  } from './tools/edit.js';
49
50
  import { searchTool, queryTool, extractTool, delegateTool, analyzeAllTool } from './tools/vercel.js';
50
- import { createExecutePlanTool, getExecutePlanToolDefinition } from './tools/executePlan.js';
51
+ import { createExecutePlanTool, getExecutePlanToolDefinition, createCleanupExecutePlanTool, getCleanupExecutePlanToolDefinition } from './tools/executePlan.js';
51
52
  import { bashTool } from './tools/bash.js';
52
53
  import { editTool, createTool } from './tools/edit.js';
53
54
  import { ProbeAgent } from './agent/ProbeAgent.js';
@@ -93,6 +94,7 @@ export {
93
94
  delegateTool,
94
95
  analyzeAllTool,
95
96
  createExecutePlanTool,
97
+ createCleanupExecutePlanTool,
96
98
  bashTool,
97
99
  editTool,
98
100
  createTool,
@@ -106,6 +108,7 @@ export {
106
108
  delegateSchema,
107
109
  analyzeAllSchema,
108
110
  executePlanSchema,
111
+ cleanupExecutePlanSchema,
109
112
  attemptCompletionSchema,
110
113
  bashSchema,
111
114
  editSchema,
@@ -117,6 +120,7 @@ export {
117
120
  delegateToolDefinition,
118
121
  analyzeAllToolDefinition,
119
122
  getExecutePlanToolDefinition,
123
+ getCleanupExecutePlanToolDefinition,
120
124
  attemptCompletionToolDefinition,
121
125
  bashToolDefinition,
122
126
  editToolDefinition,
@@ -59,6 +59,11 @@ export const executePlanSchema = z.object({
59
59
  description: z.string().optional().describe('Human-readable description of what this plan does, for logging.')
60
60
  });
61
61
 
62
+ export const cleanupExecutePlanSchema = z.object({
63
+ clearOutputBuffer: z.boolean().optional().default(true).describe('Clear the output buffer from previous execute_plan calls'),
64
+ clearSessionStore: z.boolean().optional().default(false).describe('Clear the session store (persisted data across execute_plan calls)')
65
+ });
66
+
62
67
  // Schema for the attempt_completion tool - flexible validation for direct XML response
63
68
  export const attemptCompletionSchema = {
64
69
  // Custom validation that requires result parameter but allows direct XML response
@@ -431,6 +436,7 @@ export const DEFAULT_VALID_TOOLS = [
431
436
  'delegate',
432
437
  'analyze_all',
433
438
  'execute_plan',
439
+ 'cleanup_execute_plan',
434
440
  'listSkills',
435
441
  'useSkill',
436
442
  'listFiles',
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { tool } from 'ai';
9
- import { executePlanSchema, parseAndResolvePaths } from './common.js';
9
+ import { executePlanSchema, cleanupExecutePlanSchema, parseAndResolvePaths } from './common.js';
10
10
  import { createDSLRuntime } from '../agent/dsl/runtime.js';
11
11
  import { search } from '../search.js';
12
12
  import { query } from '../query.js';
@@ -16,8 +16,42 @@ import { glob } from 'glob';
16
16
 
17
17
  export { executePlanSchema };
18
18
 
19
+ /**
20
+ * Decode common HTML entities that LLMs sometimes produce when generating code.
21
+ * This handles entities like &amp;&amp; → &&, &lt;= → <=, etc.
22
+ */
23
+ function decodeHtmlEntities(str) {
24
+ const entities = {
25
+ '&amp;': '&',
26
+ '&lt;': '<',
27
+ '&gt;': '>',
28
+ '&quot;': '"',
29
+ '&apos;': "'",
30
+ '&#39;': "'",
31
+ '&#x27;': "'",
32
+ };
33
+
34
+ // Replace named/common entities
35
+ let result = str.replace(/&(?:amp|lt|gt|quot|apos|#39|#x27);/gi, (match) => {
36
+ return entities[match.toLowerCase()] || match;
37
+ });
38
+
39
+ // Handle numeric entities (decimal): &#60; → <
40
+ result = result.replace(/&#(\d+);/g, (match, dec) => {
41
+ return String.fromCharCode(parseInt(dec, 10));
42
+ });
43
+
44
+ // Handle numeric entities (hex): &#x3C; → <
45
+ result = result.replace(/&#x([0-9a-f]+);/gi, (match, hex) => {
46
+ return String.fromCharCode(parseInt(hex, 16));
47
+ });
48
+
49
+ return result;
50
+ }
51
+
19
52
  /**
20
53
  * Strip markdown fences and XML tags that LLMs sometimes wrap code in.
54
+ * Also decodes HTML entities that may appear in XML-extracted code.
21
55
  */
22
56
  function stripCodeWrapping(code) {
23
57
  let s = String(code || '');
@@ -25,6 +59,8 @@ function stripCodeWrapping(code) {
25
59
  s = s.replace(/^```(?:javascript|js)?\n?/gm, '').replace(/```$/gm, '');
26
60
  // Strip XML-style tags: <execute_plan>, </execute_plan>, <code>, </code>
27
61
  s = s.replace(/<\/?(?:execute_plan|code)>/g, '');
62
+ // Decode HTML entities (e.g., &amp;&amp; → &&, &lt;= → <=)
63
+ s = decodeHtmlEntities(s);
28
64
  return s.trim();
29
65
  }
30
66
 
@@ -347,7 +383,16 @@ RULES REMINDER:
347
383
  });
348
384
  }
349
385
 
350
- // All retries exhausted
386
+ // All retries exhausted — auto-cleanup output buffer to prevent stale data
387
+ if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
388
+ const clearedChars = outputBuffer.items.reduce((sum, item) => sum + item.length, 0);
389
+ outputBuffer.items = [];
390
+ planSpan?.addEvent?.('dsl.auto_cleanup', {
391
+ 'cleanup.chars_cleared': clearedChars,
392
+ 'cleanup.reason': 'all_retries_exhausted',
393
+ });
394
+ }
395
+
351
396
  finalOutput = `Plan execution failed after ${maxRetries} retries.\n\nLast error: ${lastError}`;
352
397
  planSpan?.setAttributes?.({
353
398
  'dsl.result': 'all_retries_exhausted',
@@ -358,6 +403,11 @@ RULES REMINDER:
358
403
  planSpan?.end?.();
359
404
  return finalOutput;
360
405
  } catch (e) {
406
+ // Auto-cleanup output buffer on exception to prevent stale data
407
+ if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
408
+ outputBuffer.items = [];
409
+ }
410
+
361
411
  planSpan?.setStatus?.('ERROR');
362
412
  planSpan?.addEvent?.('exception', {
363
413
  'exception.message': e.message,
@@ -808,3 +858,87 @@ output(table);
808
858
  return "Generated table with " + results.length + " items.";
809
859
  \`\`\``;
810
860
  }
861
+
862
+ /**
863
+ * Create the cleanup_execute_plan tool for the Vercel AI SDK.
864
+ *
865
+ * Cleans up output buffer and optionally session store from previous
866
+ * failed or interrupted execute_plan calls.
867
+ *
868
+ * @param {Object} options
869
+ * @param {Object} [options.outputBuffer] - Output buffer to clear
870
+ * @param {Object} [options.sessionStore] - Session store to clear
871
+ * @param {Object} [options.tracer] - OTEL tracer for tracing
872
+ * @returns {Object} Vercel AI SDK tool
873
+ */
874
+ export function createCleanupExecutePlanTool(options) {
875
+ const { outputBuffer, sessionStore, tracer } = options;
876
+
877
+ return tool({
878
+ description: 'Clean up output buffer and session store from previous execute_plan calls. ' +
879
+ 'Use this when a previous execute_plan failed and left stale data, or before starting a fresh analysis.',
880
+ parameters: cleanupExecutePlanSchema,
881
+ execute: async ({ clearOutputBuffer = true, clearSessionStore = false }) => {
882
+ const span = tracer?.createToolSpan?.('cleanup_execute_plan', {
883
+ 'cleanup.clear_output_buffer': clearOutputBuffer,
884
+ 'cleanup.clear_session_store': clearSessionStore,
885
+ }) || null;
886
+
887
+ const results = [];
888
+
889
+ try {
890
+ if (clearOutputBuffer && outputBuffer) {
891
+ const itemCount = outputBuffer.items?.length || 0;
892
+ const charCount = outputBuffer.items?.reduce((sum, item) => sum + item.length, 0) || 0;
893
+ outputBuffer.items = [];
894
+ results.push(`Output buffer cleared (${itemCount} items, ${charCount} chars)`);
895
+ }
896
+
897
+ if (clearSessionStore && sessionStore) {
898
+ const keyCount = Object.keys(sessionStore).length;
899
+ for (const key of Object.keys(sessionStore)) {
900
+ delete sessionStore[key];
901
+ }
902
+ results.push(`Session store cleared (${keyCount} keys)`);
903
+ }
904
+
905
+ const output = results.length > 0
906
+ ? `Cleanup complete:\n- ${results.join('\n- ')}`
907
+ : 'Nothing to clean up';
908
+
909
+ span?.setAttributes?.({
910
+ 'cleanup.result': output,
911
+ 'cleanup.success': true,
912
+ });
913
+ span?.setStatus?.('OK');
914
+ span?.end?.();
915
+
916
+ return output;
917
+ } catch (e) {
918
+ span?.setStatus?.('ERROR');
919
+ span?.addEvent?.('exception', { 'exception.message': e.message });
920
+ span?.end?.();
921
+ return `Cleanup failed: ${e.message}`;
922
+ }
923
+ },
924
+ });
925
+ }
926
+
927
+ /**
928
+ * XML tool definition for cleanup_execute_plan.
929
+ *
930
+ * @returns {string} Tool definition text
931
+ */
932
+ export function getCleanupExecutePlanToolDefinition() {
933
+ return `## cleanup_execute_plan
934
+ Description: Clean up output buffer and session store from previous execute_plan calls. Use when a previous execute_plan failed and left stale data, or before starting a fresh analysis.
935
+
936
+ Parameters:
937
+ - clearOutputBuffer: (optional, default: true) Clear the output buffer from previous execute_plan calls
938
+ - clearSessionStore: (optional, default: false) Clear the session store (persisted data across execute_plan calls)
939
+
940
+ Example:
941
+ <cleanup_execute_plan>
942
+ <clearOutputBuffer>true</clearOutputBuffer>
943
+ </cleanup_execute_plan>`;
944
+ }
@@ -11,8 +11,8 @@ export { editTool, createTool } from './edit.js';
11
11
  // Export LangChain tools
12
12
  export { createSearchTool, createQueryTool, createExtractTool } from './langchain.js';
13
13
 
14
- // Export execute_plan tool
15
- export { createExecutePlanTool, getExecutePlanToolDefinition } from './executePlan.js';
14
+ // Export execute_plan and cleanup_execute_plan tools
15
+ export { createExecutePlanTool, getExecutePlanToolDefinition, createCleanupExecutePlanTool, getCleanupExecutePlanToolDefinition } from './executePlan.js';
16
16
 
17
17
  // Export common schemas and utilities
18
18
  export {
@@ -22,6 +22,7 @@ export {
22
22
  delegateSchema,
23
23
  bashSchema,
24
24
  executePlanSchema,
25
+ cleanupExecutePlanSchema,
25
26
  delegateDescription,
26
27
  delegateToolDefinition,
27
28
  bashDescription,