@probelabs/probe 0.6.0-rc239 → 0.6.0-rc240

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.
@@ -39352,7 +39352,7 @@ function resolveTargetPath(target, cwd) {
39352
39352
  }
39353
39353
  return filePart + suffix;
39354
39354
  }
39355
- var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
39355
+ var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
39356
39356
  var init_common2 = __esm({
39357
39357
  "src/tools/common.js"() {
39358
39358
  "use strict";
@@ -39401,6 +39401,10 @@ var init_common2 = __esm({
39401
39401
  code: external_exports.string().min(1).describe("JavaScript DSL code to execute. All function calls look synchronous \u2014 do NOT use async/await. Use map(items, fn) for batch operations. Use LLM(instruction, data) for AI processing."),
39402
39402
  description: external_exports.string().optional().describe("Human-readable description of what this plan does, for logging.")
39403
39403
  });
39404
+ cleanupExecutePlanSchema = external_exports.object({
39405
+ clearOutputBuffer: external_exports.boolean().optional().default(true).describe("Clear the output buffer from previous execute_plan calls"),
39406
+ clearSessionStore: external_exports.boolean().optional().default(false).describe("Clear the session store (persisted data across execute_plan calls)")
39407
+ });
39404
39408
  attemptCompletionSchema = {
39405
39409
  // Custom validation that requires result parameter but allows direct XML response
39406
39410
  safeParse: (params) => {
@@ -39748,6 +39752,7 @@ Capabilities:
39748
39752
  "delegate",
39749
39753
  "analyze_all",
39750
39754
  "execute_plan",
39755
+ "cleanup_execute_plan",
39751
39756
  "listSkills",
39752
39757
  "useSkill",
39753
39758
  "listFiles",
@@ -58534,6 +58539,14 @@ Logs: ${result.logs.join(" | ")}` : "";
58534
58539
  "dsl.error": lastError.substring(0, 1e3)
58535
58540
  });
58536
58541
  }
58542
+ if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
58543
+ const clearedChars = outputBuffer.items.reduce((sum, item) => sum + item.length, 0);
58544
+ outputBuffer.items = [];
58545
+ planSpan?.addEvent?.("dsl.auto_cleanup", {
58546
+ "cleanup.chars_cleared": clearedChars,
58547
+ "cleanup.reason": "all_retries_exhausted"
58548
+ });
58549
+ }
58537
58550
  finalOutput = `Plan execution failed after ${maxRetries} retries.
58538
58551
 
58539
58552
  Last error: ${lastError}`;
@@ -58546,6 +58559,9 @@ Last error: ${lastError}`;
58546
58559
  planSpan?.end?.();
58547
58560
  return finalOutput;
58548
58561
  } catch (e5) {
58562
+ if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
58563
+ outputBuffer.items = [];
58564
+ }
58549
58565
  planSpan?.setStatus?.("ERROR");
58550
58566
  planSpan?.addEvent?.("exception", {
58551
58567
  "exception.message": e5.message,
@@ -58989,6 +59005,62 @@ output(table);
58989
59005
  return "Generated table with " + results.length + " items.";
58990
59006
  \`\`\``;
58991
59007
  }
59008
+ function createCleanupExecutePlanTool(options) {
59009
+ const { outputBuffer, sessionStore, tracer } = options;
59010
+ return (0, import_ai4.tool)({
59011
+ description: "Clean up output buffer and session store from previous execute_plan calls. Use this when a previous execute_plan failed and left stale data, or before starting a fresh analysis.",
59012
+ parameters: cleanupExecutePlanSchema,
59013
+ execute: async ({ clearOutputBuffer = true, clearSessionStore = false }) => {
59014
+ const span = tracer?.createToolSpan?.("cleanup_execute_plan", {
59015
+ "cleanup.clear_output_buffer": clearOutputBuffer,
59016
+ "cleanup.clear_session_store": clearSessionStore
59017
+ }) || null;
59018
+ const results = [];
59019
+ try {
59020
+ if (clearOutputBuffer && outputBuffer) {
59021
+ const itemCount = outputBuffer.items?.length || 0;
59022
+ const charCount = outputBuffer.items?.reduce((sum, item) => sum + item.length, 0) || 0;
59023
+ outputBuffer.items = [];
59024
+ results.push(`Output buffer cleared (${itemCount} items, ${charCount} chars)`);
59025
+ }
59026
+ if (clearSessionStore && sessionStore) {
59027
+ const keyCount = Object.keys(sessionStore).length;
59028
+ for (const key of Object.keys(sessionStore)) {
59029
+ delete sessionStore[key];
59030
+ }
59031
+ results.push(`Session store cleared (${keyCount} keys)`);
59032
+ }
59033
+ const output = results.length > 0 ? `Cleanup complete:
59034
+ - ${results.join("\n- ")}` : "Nothing to clean up";
59035
+ span?.setAttributes?.({
59036
+ "cleanup.result": output,
59037
+ "cleanup.success": true
59038
+ });
59039
+ span?.setStatus?.("OK");
59040
+ span?.end?.();
59041
+ return output;
59042
+ } catch (e5) {
59043
+ span?.setStatus?.("ERROR");
59044
+ span?.addEvent?.("exception", { "exception.message": e5.message });
59045
+ span?.end?.();
59046
+ return `Cleanup failed: ${e5.message}`;
59047
+ }
59048
+ }
59049
+ });
59050
+ }
59051
+ function getCleanupExecutePlanToolDefinition() {
59052
+ return `## cleanup_execute_plan
59053
+ 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.
59054
+
59055
+ Parameters:
59056
+ - clearOutputBuffer: (optional, default: true) Clear the output buffer from previous execute_plan calls
59057
+ - clearSessionStore: (optional, default: false) Clear the session store (persisted data across execute_plan calls)
59058
+
59059
+ Example:
59060
+ <cleanup_execute_plan>
59061
+ <clearOutputBuffer>true</clearOutputBuffer>
59062
+ </cleanup_execute_plan>`;
59063
+ }
58992
59064
  var import_ai4;
58993
59065
  var init_executePlan = __esm({
58994
59066
  "src/tools/executePlan.js"() {
@@ -59344,6 +59416,13 @@ function createWrappedTools(baseTools) {
59344
59416
  baseTools.executePlanTool.execute
59345
59417
  );
59346
59418
  }
59419
+ if (baseTools.cleanupExecutePlanTool) {
59420
+ wrappedTools.cleanupExecutePlanToolInstance = wrapToolWithEmitter(
59421
+ baseTools.cleanupExecutePlanTool,
59422
+ "cleanup_execute_plan",
59423
+ baseTools.cleanupExecutePlanTool.execute
59424
+ );
59425
+ }
59347
59426
  if (baseTools.bashTool) {
59348
59427
  wrappedTools.bashToolInstance = wrapToolWithEmitter(
59349
59428
  baseTools.bashTool,
@@ -60260,6 +60339,9 @@ function createTools(configOptions) {
60260
60339
  }
60261
60340
  if (configOptions.enableExecutePlan && isToolAllowed("execute_plan")) {
60262
60341
  tools2.executePlanTool = createExecutePlanTool(configOptions);
60342
+ if (isToolAllowed("cleanup_execute_plan")) {
60343
+ tools2.cleanupExecutePlanTool = createCleanupExecutePlanTool(configOptions);
60344
+ }
60263
60345
  } else if (isToolAllowed("analyze_all")) {
60264
60346
  tools2.analyzeAllTool = analyzeAllTool(configOptions);
60265
60347
  }
@@ -97673,15 +97755,31 @@ function isSimpleTextWrapperSchema(schema) {
97673
97755
  return null;
97674
97756
  }
97675
97757
  const trimmed = schema.trim();
97676
- const simplePatterns = [
97677
- /^\{\s*["']?(\w+)["']?\s*:\s*["']?string["']?\s*\}$/i,
97678
- /^\{\s*["']?type["']?\s*:\s*["']?object["']?\s*,\s*["']?properties["']?\s*:\s*\{\s*["']?(\w+)["']?\s*:\s*\{\s*["']?type["']?\s*:\s*["']?string["']?\s*\}\s*\}\s*\}$/i
97679
- ];
97680
- for (const pattern of simplePatterns) {
97681
- const match2 = trimmed.match(pattern);
97682
- if (match2) {
97683
- return { fieldName: match2[1] };
97758
+ try {
97759
+ const parsed = JSON.parse(trimmed);
97760
+ if (typeof parsed !== "object" || parsed === null) {
97761
+ } else {
97762
+ const keys2 = Object.keys(parsed);
97763
+ if (keys2.length === 1 && parsed[keys2[0]] === "string") {
97764
+ return { fieldName: keys2[0] };
97765
+ }
97766
+ if (parsed.type === "object" && parsed.properties) {
97767
+ const propKeys = Object.keys(parsed.properties);
97768
+ if (propKeys.length === 1) {
97769
+ const prop = parsed.properties[propKeys[0]];
97770
+ if (prop && prop.type === "string") {
97771
+ return { fieldName: propKeys[0] };
97772
+ }
97773
+ }
97774
+ }
97775
+ return null;
97684
97776
  }
97777
+ } catch {
97778
+ }
97779
+ const simplePattern = /^\{\s*["']?(\w+)["']?\s*:\s*["']?string["']?\s*\}$/i;
97780
+ const match2 = trimmed.match(simplePattern);
97781
+ if (match2) {
97782
+ return { fieldName: match2[1] };
97685
97783
  }
97686
97784
  return null;
97687
97785
  }
@@ -110543,6 +110641,9 @@ var init_ProbeAgent = __esm({
110543
110641
  }
110544
110642
  if (this.enableExecutePlan && wrappedTools.executePlanToolInstance && isToolAllowed("execute_plan")) {
110545
110643
  this.toolImplementations.execute_plan = wrappedTools.executePlanToolInstance;
110644
+ if (wrappedTools.cleanupExecutePlanToolInstance && isToolAllowed("cleanup_execute_plan")) {
110645
+ this.toolImplementations.cleanup_execute_plan = wrappedTools.cleanupExecutePlanToolInstance;
110646
+ }
110546
110647
  } else if (wrappedTools.analyzeAllToolInstance && isToolAllowed("analyze_all")) {
110547
110648
  this.toolImplementations.analyze_all = wrappedTools.analyzeAllToolInstance;
110548
110649
  }
@@ -111916,6 +112017,10 @@ Workspace: ${this.allowedFolders.join(", ")}`;
111916
112017
  if (this.enableBash && isToolAllowed("bash")) dslFunctions.push("bash");
111917
112018
  toolDefinitions += `${getExecutePlanToolDefinition(dslFunctions)}
111918
112019
  `;
112020
+ if (isToolAllowed("cleanup_execute_plan")) {
112021
+ toolDefinitions += `${getCleanupExecutePlanToolDefinition()}
112022
+ `;
112023
+ }
111919
112024
  } else if (isToolAllowed("analyze_all")) {
111920
112025
  toolDefinitions += `${analyzeAllToolDefinition}
111921
112026
  `;
@@ -111991,6 +112096,9 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
111991
112096
  }
111992
112097
  if (this.enableExecutePlan && isToolAllowed("execute_plan")) {
111993
112098
  availableToolsList += '- execute_plan: Execute a DSL program to orchestrate tool calls. ALWAYS use this for: questions containing "all"/"every"/"comprehensive"/"complete inventory", multi-topic analysis, open-ended discovery questions, or any task requiring full codebase coverage.\n';
112099
+ if (isToolAllowed("cleanup_execute_plan")) {
112100
+ availableToolsList += "- cleanup_execute_plan: Clean up output buffer and session store from previous execute_plan calls.\n";
112101
+ }
111994
112102
  } else if (isToolAllowed("analyze_all")) {
111995
112103
  availableToolsList += "- analyze_all: Process ALL data matching a query using map-reduce (for aggregate questions needing 100% coverage).\n";
111996
112104
  }
@@ -112217,7 +112325,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
112217
112325
  }
112218
112326
  try {
112219
112327
  const oldHistoryLength = this.history.length;
112220
- if (this._outputBuffer) {
112328
+ if (this._outputBuffer && !options?._schemaFormatted) {
112221
112329
  this._outputBuffer.items = [];
112222
112330
  }
112223
112331
  if (this.enableTasks) {
@@ -112577,6 +112685,9 @@ You are working with a workspace. Available paths: ${workspaceDesc}
112577
112685
  }
112578
112686
  if (this.enableExecutePlan && this.allowedTools.isEnabled("execute_plan")) {
112579
112687
  validTools.push("execute_plan");
112688
+ if (this.allowedTools.isEnabled("cleanup_execute_plan")) {
112689
+ validTools.push("cleanup_execute_plan");
112690
+ }
112580
112691
  } else if (this.allowedTools.isEnabled("analyze_all")) {
112581
112692
  validTools.push("analyze_all");
112582
112693
  }
package/cjs/index.cjs CHANGED
@@ -38518,7 +38518,7 @@ function resolveTargetPath(target, cwd) {
38518
38518
  }
38519
38519
  return filePart + suffix;
38520
38520
  }
38521
- var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
38521
+ var import_path6, searchSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, attemptCompletionSchema, searchToolDefinition, queryToolDefinition, extractToolDefinition, delegateToolDefinition, attemptCompletionToolDefinition, analyzeAllToolDefinition, bashToolDefinition, googleSearchToolDefinition, urlContextToolDefinition, searchDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription, DEFAULT_VALID_TOOLS;
38522
38522
  var init_common2 = __esm({
38523
38523
  "src/tools/common.js"() {
38524
38524
  "use strict";
@@ -38567,6 +38567,10 @@ var init_common2 = __esm({
38567
38567
  code: external_exports.string().min(1).describe("JavaScript DSL code to execute. All function calls look synchronous \u2014 do NOT use async/await. Use map(items, fn) for batch operations. Use LLM(instruction, data) for AI processing."),
38568
38568
  description: external_exports.string().optional().describe("Human-readable description of what this plan does, for logging.")
38569
38569
  });
38570
+ cleanupExecutePlanSchema = external_exports.object({
38571
+ clearOutputBuffer: external_exports.boolean().optional().default(true).describe("Clear the output buffer from previous execute_plan calls"),
38572
+ clearSessionStore: external_exports.boolean().optional().default(false).describe("Clear the session store (persisted data across execute_plan calls)")
38573
+ });
38570
38574
  attemptCompletionSchema = {
38571
38575
  // Custom validation that requires result parameter but allows direct XML response
38572
38576
  safeParse: (params) => {
@@ -38915,6 +38919,7 @@ Capabilities:
38915
38919
  "delegate",
38916
38920
  "analyze_all",
38917
38921
  "execute_plan",
38922
+ "cleanup_execute_plan",
38918
38923
  "listSkills",
38919
38924
  "useSkill",
38920
38925
  "listFiles",
@@ -39560,6 +39565,9 @@ function createTools(configOptions) {
39560
39565
  }
39561
39566
  if (configOptions.enableExecutePlan && isToolAllowed("execute_plan")) {
39562
39567
  tools2.executePlanTool = createExecutePlanTool(configOptions);
39568
+ if (isToolAllowed("cleanup_execute_plan")) {
39569
+ tools2.cleanupExecutePlanTool = createCleanupExecutePlanTool(configOptions);
39570
+ }
39563
39571
  } else if (isToolAllowed("analyze_all")) {
39564
39572
  tools2.analyzeAllTool = analyzeAllTool(configOptions);
39565
39573
  }
@@ -46478,6 +46486,13 @@ function createWrappedTools(baseTools) {
46478
46486
  baseTools.executePlanTool.execute
46479
46487
  );
46480
46488
  }
46489
+ if (baseTools.cleanupExecutePlanTool) {
46490
+ wrappedTools.cleanupExecutePlanToolInstance = wrapToolWithEmitter(
46491
+ baseTools.cleanupExecutePlanTool,
46492
+ "cleanup_execute_plan",
46493
+ baseTools.cleanupExecutePlanTool.execute
46494
+ );
46495
+ }
46481
46496
  if (baseTools.bashTool) {
46482
46497
  wrappedTools.bashToolInstance = wrapToolWithEmitter(
46483
46498
  baseTools.bashTool,
@@ -83956,15 +83971,31 @@ function isSimpleTextWrapperSchema(schema) {
83956
83971
  return null;
83957
83972
  }
83958
83973
  const trimmed = schema.trim();
83959
- const simplePatterns = [
83960
- /^\{\s*["']?(\w+)["']?\s*:\s*["']?string["']?\s*\}$/i,
83961
- /^\{\s*["']?type["']?\s*:\s*["']?object["']?\s*,\s*["']?properties["']?\s*:\s*\{\s*["']?(\w+)["']?\s*:\s*\{\s*["']?type["']?\s*:\s*["']?string["']?\s*\}\s*\}\s*\}$/i
83962
- ];
83963
- for (const pattern of simplePatterns) {
83964
- const match2 = trimmed.match(pattern);
83965
- if (match2) {
83966
- return { fieldName: match2[1] };
83974
+ try {
83975
+ const parsed = JSON.parse(trimmed);
83976
+ if (typeof parsed !== "object" || parsed === null) {
83977
+ } else {
83978
+ const keys2 = Object.keys(parsed);
83979
+ if (keys2.length === 1 && parsed[keys2[0]] === "string") {
83980
+ return { fieldName: keys2[0] };
83981
+ }
83982
+ if (parsed.type === "object" && parsed.properties) {
83983
+ const propKeys = Object.keys(parsed.properties);
83984
+ if (propKeys.length === 1) {
83985
+ const prop = parsed.properties[propKeys[0]];
83986
+ if (prop && prop.type === "string") {
83987
+ return { fieldName: propKeys[0] };
83988
+ }
83989
+ }
83990
+ }
83991
+ return null;
83967
83992
  }
83993
+ } catch {
83994
+ }
83995
+ const simplePattern = /^\{\s*["']?(\w+)["']?\s*:\s*["']?string["']?\s*\}$/i;
83996
+ const match2 = trimmed.match(simplePattern);
83997
+ if (match2) {
83998
+ return { fieldName: match2[1] };
83968
83999
  }
83969
84000
  return null;
83970
84001
  }
@@ -96826,6 +96857,9 @@ var init_ProbeAgent = __esm({
96826
96857
  }
96827
96858
  if (this.enableExecutePlan && wrappedTools.executePlanToolInstance && isToolAllowed("execute_plan")) {
96828
96859
  this.toolImplementations.execute_plan = wrappedTools.executePlanToolInstance;
96860
+ if (wrappedTools.cleanupExecutePlanToolInstance && isToolAllowed("cleanup_execute_plan")) {
96861
+ this.toolImplementations.cleanup_execute_plan = wrappedTools.cleanupExecutePlanToolInstance;
96862
+ }
96829
96863
  } else if (wrappedTools.analyzeAllToolInstance && isToolAllowed("analyze_all")) {
96830
96864
  this.toolImplementations.analyze_all = wrappedTools.analyzeAllToolInstance;
96831
96865
  }
@@ -98199,6 +98233,10 @@ Workspace: ${this.allowedFolders.join(", ")}`;
98199
98233
  if (this.enableBash && isToolAllowed("bash")) dslFunctions.push("bash");
98200
98234
  toolDefinitions += `${getExecutePlanToolDefinition(dslFunctions)}
98201
98235
  `;
98236
+ if (isToolAllowed("cleanup_execute_plan")) {
98237
+ toolDefinitions += `${getCleanupExecutePlanToolDefinition()}
98238
+ `;
98239
+ }
98202
98240
  } else if (isToolAllowed("analyze_all")) {
98203
98241
  toolDefinitions += `${analyzeAllToolDefinition}
98204
98242
  `;
@@ -98274,6 +98312,9 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
98274
98312
  }
98275
98313
  if (this.enableExecutePlan && isToolAllowed("execute_plan")) {
98276
98314
  availableToolsList += '- execute_plan: Execute a DSL program to orchestrate tool calls. ALWAYS use this for: questions containing "all"/"every"/"comprehensive"/"complete inventory", multi-topic analysis, open-ended discovery questions, or any task requiring full codebase coverage.\n';
98315
+ if (isToolAllowed("cleanup_execute_plan")) {
98316
+ availableToolsList += "- cleanup_execute_plan: Clean up output buffer and session store from previous execute_plan calls.\n";
98317
+ }
98277
98318
  } else if (isToolAllowed("analyze_all")) {
98278
98319
  availableToolsList += "- analyze_all: Process ALL data matching a query using map-reduce (for aggregate questions needing 100% coverage).\n";
98279
98320
  }
@@ -98500,7 +98541,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
98500
98541
  }
98501
98542
  try {
98502
98543
  const oldHistoryLength = this.history.length;
98503
- if (this._outputBuffer) {
98544
+ if (this._outputBuffer && !options?._schemaFormatted) {
98504
98545
  this._outputBuffer.items = [];
98505
98546
  }
98506
98547
  if (this.enableTasks) {
@@ -98860,6 +98901,9 @@ You are working with a workspace. Available paths: ${workspaceDesc}
98860
98901
  }
98861
98902
  if (this.enableExecutePlan && this.allowedTools.isEnabled("execute_plan")) {
98862
98903
  validTools.push("execute_plan");
98904
+ if (this.allowedTools.isEnabled("cleanup_execute_plan")) {
98905
+ validTools.push("cleanup_execute_plan");
98906
+ }
98863
98907
  } else if (this.allowedTools.isEnabled("analyze_all")) {
98864
98908
  validTools.push("analyze_all");
98865
98909
  }
@@ -113266,6 +113310,14 @@ Logs: ${result.logs.join(" | ")}` : "";
113266
113310
  "dsl.error": lastError.substring(0, 1e3)
113267
113311
  });
113268
113312
  }
113313
+ if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
113314
+ const clearedChars = outputBuffer.items.reduce((sum, item) => sum + item.length, 0);
113315
+ outputBuffer.items = [];
113316
+ planSpan?.addEvent?.("dsl.auto_cleanup", {
113317
+ "cleanup.chars_cleared": clearedChars,
113318
+ "cleanup.reason": "all_retries_exhausted"
113319
+ });
113320
+ }
113269
113321
  finalOutput = `Plan execution failed after ${maxRetries} retries.
113270
113322
 
113271
113323
  Last error: ${lastError}`;
@@ -113278,6 +113330,9 @@ Last error: ${lastError}`;
113278
113330
  planSpan?.end?.();
113279
113331
  return finalOutput;
113280
113332
  } catch (e5) {
113333
+ if (outputBuffer && outputBuffer.items && outputBuffer.items.length > 0) {
113334
+ outputBuffer.items = [];
113335
+ }
113281
113336
  planSpan?.setStatus?.("ERROR");
113282
113337
  planSpan?.addEvent?.("exception", {
113283
113338
  "exception.message": e5.message,
@@ -113721,6 +113776,62 @@ output(table);
113721
113776
  return "Generated table with " + results.length + " items.";
113722
113777
  \`\`\``;
113723
113778
  }
113779
+ function createCleanupExecutePlanTool(options) {
113780
+ const { outputBuffer, sessionStore, tracer } = options;
113781
+ return (0, import_ai6.tool)({
113782
+ description: "Clean up output buffer and session store from previous execute_plan calls. Use this when a previous execute_plan failed and left stale data, or before starting a fresh analysis.",
113783
+ parameters: cleanupExecutePlanSchema,
113784
+ execute: async ({ clearOutputBuffer = true, clearSessionStore = false }) => {
113785
+ const span = tracer?.createToolSpan?.("cleanup_execute_plan", {
113786
+ "cleanup.clear_output_buffer": clearOutputBuffer,
113787
+ "cleanup.clear_session_store": clearSessionStore
113788
+ }) || null;
113789
+ const results = [];
113790
+ try {
113791
+ if (clearOutputBuffer && outputBuffer) {
113792
+ const itemCount = outputBuffer.items?.length || 0;
113793
+ const charCount = outputBuffer.items?.reduce((sum, item) => sum + item.length, 0) || 0;
113794
+ outputBuffer.items = [];
113795
+ results.push(`Output buffer cleared (${itemCount} items, ${charCount} chars)`);
113796
+ }
113797
+ if (clearSessionStore && sessionStore) {
113798
+ const keyCount = Object.keys(sessionStore).length;
113799
+ for (const key of Object.keys(sessionStore)) {
113800
+ delete sessionStore[key];
113801
+ }
113802
+ results.push(`Session store cleared (${keyCount} keys)`);
113803
+ }
113804
+ const output = results.length > 0 ? `Cleanup complete:
113805
+ - ${results.join("\n- ")}` : "Nothing to clean up";
113806
+ span?.setAttributes?.({
113807
+ "cleanup.result": output,
113808
+ "cleanup.success": true
113809
+ });
113810
+ span?.setStatus?.("OK");
113811
+ span?.end?.();
113812
+ return output;
113813
+ } catch (e5) {
113814
+ span?.setStatus?.("ERROR");
113815
+ span?.addEvent?.("exception", { "exception.message": e5.message });
113816
+ span?.end?.();
113817
+ return `Cleanup failed: ${e5.message}`;
113818
+ }
113819
+ }
113820
+ });
113821
+ }
113822
+ function getCleanupExecutePlanToolDefinition() {
113823
+ return `## cleanup_execute_plan
113824
+ 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.
113825
+
113826
+ Parameters:
113827
+ - clearOutputBuffer: (optional, default: true) Clear the output buffer from previous execute_plan calls
113828
+ - clearSessionStore: (optional, default: false) Clear the session store (persisted data across execute_plan calls)
113829
+
113830
+ Example:
113831
+ <cleanup_execute_plan>
113832
+ <clearOutputBuffer>true</clearOutputBuffer>
113833
+ </cleanup_execute_plan>`;
113834
+ }
113724
113835
  var import_ai6;
113725
113836
  var init_executePlan = __esm({
113726
113837
  "src/tools/executePlan.js"() {
@@ -113879,6 +113990,8 @@ __export(tools_exports, {
113879
113990
  bashTool: () => bashTool,
113880
113991
  bashToolDefinition: () => bashToolDefinition,
113881
113992
  buildToolTagPattern: () => buildToolTagPattern,
113993
+ cleanupExecutePlanSchema: () => cleanupExecutePlanSchema,
113994
+ createCleanupExecutePlanTool: () => createCleanupExecutePlanTool,
113882
113995
  createDescription: () => createDescription,
113883
113996
  createExecutePlanTool: () => createExecutePlanTool,
113884
113997
  createExtractTool: () => createExtractTool,
@@ -113898,6 +114011,7 @@ __export(tools_exports, {
113898
114011
  executePlanSchema: () => executePlanSchema,
113899
114012
  extractSchema: () => extractSchema,
113900
114013
  extractTool: () => extractTool,
114014
+ getCleanupExecutePlanToolDefinition: () => getCleanupExecutePlanToolDefinition,
113901
114015
  getExecutePlanToolDefinition: () => getExecutePlanToolDefinition,
113902
114016
  parseAndResolvePaths: () => parseAndResolvePaths,
113903
114017
  querySchema: () => querySchema,
@@ -114522,6 +114636,8 @@ __export(index_exports, {
114522
114636
  bashSchema: () => bashSchema,
114523
114637
  bashTool: () => bashTool,
114524
114638
  bashToolDefinition: () => bashToolDefinition,
114639
+ cleanupExecutePlanSchema: () => cleanupExecutePlanSchema,
114640
+ createCleanupExecutePlanTool: () => createCleanupExecutePlanTool,
114525
114641
  createExecutePlanTool: () => createExecutePlanTool,
114526
114642
  createSchema: () => createSchema,
114527
114643
  createTaskTool: () => createTaskTool,
@@ -114540,6 +114656,7 @@ __export(index_exports, {
114540
114656
  extractTool: () => extractTool,
114541
114657
  extractToolDefinition: () => extractToolDefinition,
114542
114658
  getBinaryPath: () => getBinaryPath,
114659
+ getCleanupExecutePlanToolDefinition: () => getCleanupExecutePlanToolDefinition,
114543
114660
  getExecutePlanToolDefinition: () => getExecutePlanToolDefinition,
114544
114661
  googleSearchToolDefinition: () => googleSearchToolDefinition,
114545
114662
  grep: () => grep,
@@ -114612,6 +114729,8 @@ init_index();
114612
114729
  bashSchema,
114613
114730
  bashTool,
114614
114731
  bashToolDefinition,
114732
+ cleanupExecutePlanSchema,
114733
+ createCleanupExecutePlanTool,
114615
114734
  createExecutePlanTool,
114616
114735
  createSchema,
114617
114736
  createTaskTool,
@@ -114630,6 +114749,7 @@ init_index();
114630
114749
  extractTool,
114631
114750
  extractToolDefinition,
114632
114751
  getBinaryPath,
114752
+ getCleanupExecutePlanToolDefinition,
114633
114753
  getExecutePlanToolDefinition,
114634
114754
  googleSearchToolDefinition,
114635
114755
  grep,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/probe",
3
- "version": "0.6.0-rc239",
3
+ "version": "0.6.0-rc240",
4
4
  "description": "Node.js wrapper for the probe code search tool",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -49,6 +49,7 @@ import {
49
49
  delegateToolDefinition,
50
50
  analyzeAllToolDefinition,
51
51
  getExecutePlanToolDefinition,
52
+ getCleanupExecutePlanToolDefinition,
52
53
  bashToolDefinition,
53
54
  listFilesToolDefinition,
54
55
  searchFilesToolDefinition,
@@ -870,6 +871,10 @@ export class ProbeAgent {
870
871
  }
871
872
  if (this.enableExecutePlan && wrappedTools.executePlanToolInstance && isToolAllowed('execute_plan')) {
872
873
  this.toolImplementations.execute_plan = wrappedTools.executePlanToolInstance;
874
+ // cleanup_execute_plan is enabled together with execute_plan
875
+ if (wrappedTools.cleanupExecutePlanToolInstance && isToolAllowed('cleanup_execute_plan')) {
876
+ this.toolImplementations.cleanup_execute_plan = wrappedTools.cleanupExecutePlanToolInstance;
877
+ }
873
878
  } else if (wrappedTools.analyzeAllToolInstance && isToolAllowed('analyze_all')) {
874
879
  // analyze_all is fallback when execute_plan is not enabled
875
880
  this.toolImplementations.analyze_all = wrappedTools.analyzeAllToolInstance;
@@ -2582,6 +2587,10 @@ ${extractGuidance}
2582
2587
  if (isToolAllowed('listFiles')) dslFunctions.push('listFiles');
2583
2588
  if (this.enableBash && isToolAllowed('bash')) dslFunctions.push('bash');
2584
2589
  toolDefinitions += `${getExecutePlanToolDefinition(dslFunctions)}\n`;
2590
+ // cleanup_execute_plan is enabled together with execute_plan
2591
+ if (isToolAllowed('cleanup_execute_plan')) {
2592
+ toolDefinitions += `${getCleanupExecutePlanToolDefinition()}\n`;
2593
+ }
2585
2594
  } else if (isToolAllowed('analyze_all')) {
2586
2595
  // Fallback: only register analyze_all if execute_plan is not available
2587
2596
  toolDefinitions += `${analyzeAllToolDefinition}\n`;
@@ -2661,6 +2670,9 @@ The configuration is loaded from src/config.js lines 15-25 which contains the da
2661
2670
  }
2662
2671
  if (this.enableExecutePlan && isToolAllowed('execute_plan')) {
2663
2672
  availableToolsList += '- execute_plan: Execute a DSL program to orchestrate tool calls. ALWAYS use this for: questions containing "all"/"every"/"comprehensive"/"complete inventory", multi-topic analysis, open-ended discovery questions, or any task requiring full codebase coverage.\n';
2673
+ if (isToolAllowed('cleanup_execute_plan')) {
2674
+ availableToolsList += '- cleanup_execute_plan: Clean up output buffer and session store from previous execute_plan calls.\n';
2675
+ }
2664
2676
  } else if (isToolAllowed('analyze_all')) {
2665
2677
  availableToolsList += '- analyze_all: Process ALL data matching a query using map-reduce (for aggregate questions needing 100% coverage).\n';
2666
2678
  }
@@ -2891,8 +2903,10 @@ Follow these instructions carefully:
2891
2903
  // Track initial history length for storage
2892
2904
  const oldHistoryLength = this.history.length;
2893
2905
 
2894
- // Reset output buffer for this answer() call
2895
- if (this._outputBuffer) {
2906
+ // Reset output buffer for this answer() call — but NOT during schema correction recursion
2907
+ // When _schemaFormatted is true, this is a recursive call to fix JSON formatting,
2908
+ // and we must preserve the output buffer so the parent call can append it
2909
+ if (this._outputBuffer && !options?._schemaFormatted) {
2896
2910
  this._outputBuffer.items = [];
2897
2911
  }
2898
2912
 
@@ -3411,6 +3425,10 @@ Follow these instructions carefully:
3411
3425
  // Execute Plan tool (requires enableExecutePlan flag, supersedes analyze_all)
3412
3426
  if (this.enableExecutePlan && this.allowedTools.isEnabled('execute_plan')) {
3413
3427
  validTools.push('execute_plan');
3428
+ // cleanup_execute_plan is enabled together with execute_plan
3429
+ if (this.allowedTools.isEnabled('cleanup_execute_plan')) {
3430
+ validTools.push('cleanup_execute_plan');
3431
+ }
3414
3432
  } else if (this.allowedTools.isEnabled('analyze_all')) {
3415
3433
  validTools.push('analyze_all');
3416
3434
  }
@@ -220,6 +220,15 @@ export function createWrappedTools(baseTools) {
220
220
  );
221
221
  }
222
222
 
223
+ // Wrap cleanup_execute_plan tool
224
+ if (baseTools.cleanupExecutePlanTool) {
225
+ wrappedTools.cleanupExecutePlanToolInstance = wrapToolWithEmitter(
226
+ baseTools.cleanupExecutePlanTool,
227
+ 'cleanup_execute_plan',
228
+ baseTools.cleanupExecutePlanTool.execute
229
+ );
230
+ }
231
+
223
232
  // Wrap bash tool
224
233
  if (baseTools.bashTool) {
225
234
  wrappedTools.bashToolInstance = wrapToolWithEmitter(
@@ -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;