@probelabs/probe 0.6.0-rc255 → 0.6.0-rc256

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.
@@ -83,7 +83,8 @@ import {
83
83
  isJsonSchemaDefinition,
84
84
  createSchemaDefinitionCorrectionPrompt,
85
85
  validateAndFixMermaidResponse,
86
- tryAutoWrapForSimpleSchema
86
+ tryAutoWrapForSimpleSchema,
87
+ tryExtractValidJsonPrefix
87
88
  } from './schemaUtils.js';
88
89
  import { removeThinkingTags, extractThinkingContent } from './xmlParsingUtils.js';
89
90
  import { predefinedPrompts } from './shared/prompts.js';
@@ -3027,8 +3028,9 @@ Follow these instructions carefully:
3027
3028
  // +1 for schema formatting
3028
3029
  // +2 for potential Mermaid validation retries (can be multiple diagrams)
3029
3030
  // +1 for potential JSON correction
3030
- const baseMaxIterations = this.maxIterations || MAX_TOOL_ITERATIONS;
3031
- const maxIterations = options.schema ? baseMaxIterations + 4 : baseMaxIterations;
3031
+ // _maxIterationsOverride: used by correction calls to cap iterations (issue #447)
3032
+ const baseMaxIterations = options._maxIterationsOverride || this.maxIterations || MAX_TOOL_ITERATIONS;
3033
+ const maxIterations = (options._maxIterationsOverride) ? baseMaxIterations : (options.schema ? baseMaxIterations + 4 : baseMaxIterations);
3032
3034
 
3033
3035
  // Check if we're using CLI-based engines which handle their own agentic loop
3034
3036
  const isClaudeCode = this.clientApiProvider === 'claude-code' || process.env.USE_CLAUDE_CODE === 'true';
@@ -4693,11 +4695,14 @@ Convert your previous response content into actual JSON data that follows this s
4693
4695
  0
4694
4696
  );
4695
4697
 
4698
+ // Strip schema from correction options to prevent inflated iteration budget (issue #447)
4699
+ const { schema: _unusedSchema1, ...schemaDefCorrectionOptions } = options;
4696
4700
  finalResult = await this.answer(schemaDefinitionPrompt, [], {
4697
- ...options,
4701
+ ...schemaDefCorrectionOptions,
4698
4702
  _schemaFormatted: true,
4699
4703
  _skipValidation: true, // Skip validation in recursive correction calls to prevent loops
4700
- _completionPromptProcessed: true // Prevent cascading completion prompts in retry calls
4704
+ _completionPromptProcessed: true, // Prevent cascading completion prompts in retry calls
4705
+ _maxIterationsOverride: 3 // Correction should complete in 1-2 iterations (issue #447)
4701
4706
  });
4702
4707
  finalResult = cleanSchemaResponse(finalResult);
4703
4708
  validation = validateJsonResponse(finalResult);
@@ -4753,12 +4758,15 @@ Convert your previous response content into actual JSON data that follows this s
4753
4758
  );
4754
4759
  }
4755
4760
 
4761
+ // Strip schema from correction options to prevent inflated iteration budget (issue #447)
4762
+ const { schema: _unusedSchema2, ...correctionOptions } = options;
4756
4763
  finalResult = await this.answer(correctionPrompt, [], {
4757
- ...options,
4764
+ ...correctionOptions,
4758
4765
  _schemaFormatted: true,
4759
4766
  _skipValidation: true, // Skip validation in recursive correction calls to prevent loops
4760
4767
  _disableTools: true, // Only allow attempt_completion - prevent AI from using search/query tools
4761
- _completionPromptProcessed: true // Prevent cascading completion prompts in retry calls
4768
+ _completionPromptProcessed: true, // Prevent cascading completion prompts in retry calls
4769
+ _maxIterationsOverride: 3 // Correction should complete in 1-2 iterations (issue #447)
4762
4770
  });
4763
4771
  finalResult = cleanSchemaResponse(finalResult);
4764
4772
 
@@ -30,13 +30,45 @@ export const DEFAULT_ALLOW_PATTERNS = [
30
30
  'tree', 'tree:*',
31
31
 
32
32
  // Git read-only operations
33
- 'git:status', 'git:log', 'git:log:*', 'git:diff', 'git:diff:*',
33
+ 'git:status', 'git:status:*', 'git:log', 'git:log:*', 'git:diff', 'git:diff:*',
34
34
  'git:show', 'git:show:*', 'git:branch', 'git:branch:*',
35
35
  'git:tag', 'git:tag:*', 'git:describe', 'git:describe:*',
36
36
  'git:remote', 'git:remote:*', 'git:config:*',
37
- 'git:blame', 'git:blame:*', 'git:shortlog', 'git:reflog',
38
- 'git:ls-files', 'git:ls-tree', 'git:rev-parse', 'git:rev-list',
37
+ 'git:blame', 'git:blame:*', 'git:shortlog', 'git:shortlog:*', 'git:reflog', 'git:reflog:*',
38
+ 'git:ls-files', 'git:ls-files:*', 'git:ls-tree', 'git:ls-tree:*',
39
+ 'git:ls-remote', 'git:ls-remote:*',
40
+ 'git:rev-parse', 'git:rev-parse:*', 'git:rev-list', 'git:rev-list:*',
41
+ 'git:cat-file', 'git:cat-file:*',
42
+ 'git:diff-tree', 'git:diff-tree:*', 'git:diff-files', 'git:diff-files:*',
43
+ 'git:diff-index', 'git:diff-index:*',
44
+ 'git:for-each-ref', 'git:for-each-ref:*',
45
+ 'git:merge-base', 'git:merge-base:*',
46
+ 'git:name-rev', 'git:name-rev:*',
47
+ 'git:count-objects', 'git:count-objects:*',
48
+ 'git:verify-commit', 'git:verify-commit:*', 'git:verify-tag', 'git:verify-tag:*',
49
+ 'git:check-ignore', 'git:check-ignore:*', 'git:check-attr', 'git:check-attr:*',
50
+ 'git:stash:list', 'git:stash:show', 'git:stash:show:*',
51
+ 'git:worktree:list', 'git:worktree:list:*',
52
+ 'git:notes:list', 'git:notes:show', 'git:notes:show:*',
39
53
  'git:--version', 'git:help', 'git:help:*',
54
+
55
+ // GitHub CLI (gh) read-only operations
56
+ 'gh:--version', 'gh:help', 'gh:help:*', 'gh:status',
57
+ 'gh:auth:status', 'gh:auth:status:*',
58
+ 'gh:issue:list', 'gh:issue:list:*', 'gh:issue:view', 'gh:issue:view:*',
59
+ 'gh:issue:status', 'gh:issue:status:*',
60
+ 'gh:pr:list', 'gh:pr:list:*', 'gh:pr:view', 'gh:pr:view:*',
61
+ 'gh:pr:status', 'gh:pr:status:*', 'gh:pr:diff', 'gh:pr:diff:*',
62
+ 'gh:pr:checks', 'gh:pr:checks:*',
63
+ 'gh:repo:list', 'gh:repo:list:*', 'gh:repo:view', 'gh:repo:view:*',
64
+ 'gh:release:list', 'gh:release:list:*', 'gh:release:view', 'gh:release:view:*',
65
+ 'gh:run:list', 'gh:run:list:*', 'gh:run:view', 'gh:run:view:*',
66
+ 'gh:workflow:list', 'gh:workflow:list:*', 'gh:workflow:view', 'gh:workflow:view:*',
67
+ 'gh:gist:list', 'gh:gist:list:*', 'gh:gist:view', 'gh:gist:view:*',
68
+ 'gh:search:issues', 'gh:search:issues:*', 'gh:search:prs', 'gh:search:prs:*',
69
+ 'gh:search:repos', 'gh:search:repos:*', 'gh:search:code', 'gh:search:code:*',
70
+ 'gh:search:commits', 'gh:search:commits:*',
71
+ 'gh:api', 'gh:api:*',
40
72
 
41
73
  // Package managers (information only)
42
74
  'npm:list', 'npm:ls', 'npm:view', 'npm:info', 'npm:show',
@@ -165,9 +197,46 @@ export const DEFAULT_DENY_PATTERNS = [
165
197
  'sysctl:-w:*',
166
198
 
167
199
  // Dangerous git operations
168
- 'git:push', 'git:push:*', 'git:force', 'git:reset:--hard:*',
169
- 'git:clean:-fd', 'git:rm:*', 'git:commit', 'git:merge',
170
- 'git:rebase', 'git:cherry-pick', 'git:stash:drop',
200
+ 'git:push', 'git:push:*', 'git:force', 'git:reset', 'git:reset:*',
201
+ 'git:clean', 'git:clean:*', 'git:rm', 'git:rm:*',
202
+ 'git:commit', 'git:commit:*', 'git:merge', 'git:merge:*',
203
+ 'git:rebase', 'git:rebase:*', 'git:cherry-pick', 'git:cherry-pick:*',
204
+ 'git:stash:drop', 'git:stash:drop:*', 'git:stash:pop', 'git:stash:pop:*',
205
+ 'git:stash:push', 'git:stash:push:*', 'git:stash:clear',
206
+ 'git:branch:-d', 'git:branch:-d:*', 'git:branch:-D', 'git:branch:-D:*',
207
+ 'git:branch:--delete', 'git:branch:--delete:*',
208
+ 'git:tag:-d', 'git:tag:-d:*', 'git:tag:--delete', 'git:tag:--delete:*',
209
+ 'git:remote:remove', 'git:remote:remove:*', 'git:remote:rm', 'git:remote:rm:*',
210
+ 'git:checkout:--force', 'git:checkout:--force:*',
211
+ 'git:checkout:-f', 'git:checkout:-f:*',
212
+ 'git:submodule:deinit', 'git:submodule:deinit:*',
213
+ 'git:notes:add', 'git:notes:add:*', 'git:notes:remove', 'git:notes:remove:*',
214
+ 'git:worktree:add', 'git:worktree:add:*',
215
+ 'git:worktree:remove', 'git:worktree:remove:*',
216
+
217
+ // Dangerous GitHub CLI (gh) write operations
218
+ 'gh:issue:create', 'gh:issue:create:*', 'gh:issue:close', 'gh:issue:close:*',
219
+ 'gh:issue:delete', 'gh:issue:delete:*', 'gh:issue:edit', 'gh:issue:edit:*',
220
+ 'gh:issue:reopen', 'gh:issue:reopen:*',
221
+ 'gh:issue:comment', 'gh:issue:comment:*',
222
+ 'gh:pr:create', 'gh:pr:create:*', 'gh:pr:close', 'gh:pr:close:*',
223
+ 'gh:pr:merge', 'gh:pr:merge:*', 'gh:pr:edit', 'gh:pr:edit:*',
224
+ 'gh:pr:reopen', 'gh:pr:reopen:*', 'gh:pr:review', 'gh:pr:review:*',
225
+ 'gh:pr:comment', 'gh:pr:comment:*',
226
+ 'gh:repo:create', 'gh:repo:create:*', 'gh:repo:delete', 'gh:repo:delete:*',
227
+ 'gh:repo:fork', 'gh:repo:fork:*', 'gh:repo:rename', 'gh:repo:rename:*',
228
+ 'gh:repo:archive', 'gh:repo:archive:*', 'gh:repo:clone', 'gh:repo:clone:*',
229
+ 'gh:release:create', 'gh:release:create:*', 'gh:release:delete', 'gh:release:delete:*',
230
+ 'gh:release:edit', 'gh:release:edit:*',
231
+ 'gh:run:cancel', 'gh:run:cancel:*', 'gh:run:rerun', 'gh:run:rerun:*',
232
+ 'gh:workflow:run', 'gh:workflow:run:*',
233
+ 'gh:workflow:enable', 'gh:workflow:enable:*', 'gh:workflow:disable', 'gh:workflow:disable:*',
234
+ 'gh:gist:create', 'gh:gist:create:*', 'gh:gist:delete', 'gh:gist:delete:*',
235
+ 'gh:gist:edit', 'gh:gist:edit:*',
236
+ 'gh:secret:set', 'gh:secret:set:*', 'gh:secret:delete', 'gh:secret:delete:*',
237
+ 'gh:variable:set', 'gh:variable:set:*', 'gh:variable:delete', 'gh:variable:delete:*',
238
+ 'gh:label:create', 'gh:label:create:*', 'gh:label:delete', 'gh:label:delete:*',
239
+ 'gh:ssh-key:add', 'gh:ssh-key:add:*', 'gh:ssh-key:delete', 'gh:ssh-key:delete:*',
171
240
 
172
241
  // File system mounting and partitioning
173
242
  'mount', 'mount:*', 'umount', 'umount:*', 'fdisk', 'fdisk:*',
@@ -10373,6 +10373,10 @@ function getValidParamsForTool(toolName) {
10373
10373
  }
10374
10374
  return [];
10375
10375
  }
10376
+ function unescapeXmlEntities(str) {
10377
+ if (typeof str !== "string") return str;
10378
+ return str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, "&");
10379
+ }
10376
10380
  function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
10377
10381
  let earliestToolName = null;
10378
10382
  let earliestOpenIndex = Infinity;
@@ -10429,10 +10433,10 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
10429
10433
  }
10430
10434
  paramCloseIndex = nextTagIndex;
10431
10435
  }
10432
- let paramValue = innerContent.substring(
10436
+ let paramValue = unescapeXmlEntities(innerContent.substring(
10433
10437
  paramOpenIndex + paramOpenTag.length,
10434
10438
  paramCloseIndex
10435
- ).trim();
10439
+ ).trim());
10436
10440
  if (paramValue.toLowerCase() === "true") {
10437
10441
  paramValue = true;
10438
10442
  } else if (paramValue.toLowerCase() === "false") {
@@ -10446,7 +10450,7 @@ function parseXmlToolCall(xmlString, validTools = DEFAULT_VALID_TOOLS) {
10446
10450
  params[paramName] = paramValue;
10447
10451
  }
10448
10452
  if (toolName === "attempt_completion") {
10449
- params["result"] = innerContent.trim();
10453
+ params["result"] = unescapeXmlEntities(innerContent.trim());
10450
10454
  if (params.command) {
10451
10455
  delete params.command;
10452
10456
  }
@@ -11618,6 +11622,7 @@ var init_bashDefaults = __esm({
11618
11622
  "tree:*",
11619
11623
  // Git read-only operations
11620
11624
  "git:status",
11625
+ "git:status:*",
11621
11626
  "git:log",
11622
11627
  "git:log:*",
11623
11628
  "git:diff",
@@ -11636,14 +11641,109 @@ var init_bashDefaults = __esm({
11636
11641
  "git:blame",
11637
11642
  "git:blame:*",
11638
11643
  "git:shortlog",
11644
+ "git:shortlog:*",
11639
11645
  "git:reflog",
11646
+ "git:reflog:*",
11640
11647
  "git:ls-files",
11648
+ "git:ls-files:*",
11641
11649
  "git:ls-tree",
11650
+ "git:ls-tree:*",
11651
+ "git:ls-remote",
11652
+ "git:ls-remote:*",
11642
11653
  "git:rev-parse",
11654
+ "git:rev-parse:*",
11643
11655
  "git:rev-list",
11656
+ "git:rev-list:*",
11657
+ "git:cat-file",
11658
+ "git:cat-file:*",
11659
+ "git:diff-tree",
11660
+ "git:diff-tree:*",
11661
+ "git:diff-files",
11662
+ "git:diff-files:*",
11663
+ "git:diff-index",
11664
+ "git:diff-index:*",
11665
+ "git:for-each-ref",
11666
+ "git:for-each-ref:*",
11667
+ "git:merge-base",
11668
+ "git:merge-base:*",
11669
+ "git:name-rev",
11670
+ "git:name-rev:*",
11671
+ "git:count-objects",
11672
+ "git:count-objects:*",
11673
+ "git:verify-commit",
11674
+ "git:verify-commit:*",
11675
+ "git:verify-tag",
11676
+ "git:verify-tag:*",
11677
+ "git:check-ignore",
11678
+ "git:check-ignore:*",
11679
+ "git:check-attr",
11680
+ "git:check-attr:*",
11681
+ "git:stash:list",
11682
+ "git:stash:show",
11683
+ "git:stash:show:*",
11684
+ "git:worktree:list",
11685
+ "git:worktree:list:*",
11686
+ "git:notes:list",
11687
+ "git:notes:show",
11688
+ "git:notes:show:*",
11644
11689
  "git:--version",
11645
11690
  "git:help",
11646
11691
  "git:help:*",
11692
+ // GitHub CLI (gh) read-only operations
11693
+ "gh:--version",
11694
+ "gh:help",
11695
+ "gh:help:*",
11696
+ "gh:status",
11697
+ "gh:auth:status",
11698
+ "gh:auth:status:*",
11699
+ "gh:issue:list",
11700
+ "gh:issue:list:*",
11701
+ "gh:issue:view",
11702
+ "gh:issue:view:*",
11703
+ "gh:issue:status",
11704
+ "gh:issue:status:*",
11705
+ "gh:pr:list",
11706
+ "gh:pr:list:*",
11707
+ "gh:pr:view",
11708
+ "gh:pr:view:*",
11709
+ "gh:pr:status",
11710
+ "gh:pr:status:*",
11711
+ "gh:pr:diff",
11712
+ "gh:pr:diff:*",
11713
+ "gh:pr:checks",
11714
+ "gh:pr:checks:*",
11715
+ "gh:repo:list",
11716
+ "gh:repo:list:*",
11717
+ "gh:repo:view",
11718
+ "gh:repo:view:*",
11719
+ "gh:release:list",
11720
+ "gh:release:list:*",
11721
+ "gh:release:view",
11722
+ "gh:release:view:*",
11723
+ "gh:run:list",
11724
+ "gh:run:list:*",
11725
+ "gh:run:view",
11726
+ "gh:run:view:*",
11727
+ "gh:workflow:list",
11728
+ "gh:workflow:list:*",
11729
+ "gh:workflow:view",
11730
+ "gh:workflow:view:*",
11731
+ "gh:gist:list",
11732
+ "gh:gist:list:*",
11733
+ "gh:gist:view",
11734
+ "gh:gist:view:*",
11735
+ "gh:search:issues",
11736
+ "gh:search:issues:*",
11737
+ "gh:search:prs",
11738
+ "gh:search:prs:*",
11739
+ "gh:search:repos",
11740
+ "gh:search:repos:*",
11741
+ "gh:search:code",
11742
+ "gh:search:code:*",
11743
+ "gh:search:commits",
11744
+ "gh:search:commits:*",
11745
+ "gh:api",
11746
+ "gh:api:*",
11647
11747
  // Package managers (information only)
11648
11748
  "npm:list",
11649
11749
  "npm:ls",
@@ -11954,14 +12054,132 @@ var init_bashDefaults = __esm({
11954
12054
  "git:push",
11955
12055
  "git:push:*",
11956
12056
  "git:force",
11957
- "git:reset:--hard:*",
11958
- "git:clean:-fd",
12057
+ "git:reset",
12058
+ "git:reset:*",
12059
+ "git:clean",
12060
+ "git:clean:*",
12061
+ "git:rm",
11959
12062
  "git:rm:*",
11960
12063
  "git:commit",
12064
+ "git:commit:*",
11961
12065
  "git:merge",
12066
+ "git:merge:*",
11962
12067
  "git:rebase",
12068
+ "git:rebase:*",
11963
12069
  "git:cherry-pick",
12070
+ "git:cherry-pick:*",
11964
12071
  "git:stash:drop",
12072
+ "git:stash:drop:*",
12073
+ "git:stash:pop",
12074
+ "git:stash:pop:*",
12075
+ "git:stash:push",
12076
+ "git:stash:push:*",
12077
+ "git:stash:clear",
12078
+ "git:branch:-d",
12079
+ "git:branch:-d:*",
12080
+ "git:branch:-D",
12081
+ "git:branch:-D:*",
12082
+ "git:branch:--delete",
12083
+ "git:branch:--delete:*",
12084
+ "git:tag:-d",
12085
+ "git:tag:-d:*",
12086
+ "git:tag:--delete",
12087
+ "git:tag:--delete:*",
12088
+ "git:remote:remove",
12089
+ "git:remote:remove:*",
12090
+ "git:remote:rm",
12091
+ "git:remote:rm:*",
12092
+ "git:checkout:--force",
12093
+ "git:checkout:--force:*",
12094
+ "git:checkout:-f",
12095
+ "git:checkout:-f:*",
12096
+ "git:submodule:deinit",
12097
+ "git:submodule:deinit:*",
12098
+ "git:notes:add",
12099
+ "git:notes:add:*",
12100
+ "git:notes:remove",
12101
+ "git:notes:remove:*",
12102
+ "git:worktree:add",
12103
+ "git:worktree:add:*",
12104
+ "git:worktree:remove",
12105
+ "git:worktree:remove:*",
12106
+ // Dangerous GitHub CLI (gh) write operations
12107
+ "gh:issue:create",
12108
+ "gh:issue:create:*",
12109
+ "gh:issue:close",
12110
+ "gh:issue:close:*",
12111
+ "gh:issue:delete",
12112
+ "gh:issue:delete:*",
12113
+ "gh:issue:edit",
12114
+ "gh:issue:edit:*",
12115
+ "gh:issue:reopen",
12116
+ "gh:issue:reopen:*",
12117
+ "gh:issue:comment",
12118
+ "gh:issue:comment:*",
12119
+ "gh:pr:create",
12120
+ "gh:pr:create:*",
12121
+ "gh:pr:close",
12122
+ "gh:pr:close:*",
12123
+ "gh:pr:merge",
12124
+ "gh:pr:merge:*",
12125
+ "gh:pr:edit",
12126
+ "gh:pr:edit:*",
12127
+ "gh:pr:reopen",
12128
+ "gh:pr:reopen:*",
12129
+ "gh:pr:review",
12130
+ "gh:pr:review:*",
12131
+ "gh:pr:comment",
12132
+ "gh:pr:comment:*",
12133
+ "gh:repo:create",
12134
+ "gh:repo:create:*",
12135
+ "gh:repo:delete",
12136
+ "gh:repo:delete:*",
12137
+ "gh:repo:fork",
12138
+ "gh:repo:fork:*",
12139
+ "gh:repo:rename",
12140
+ "gh:repo:rename:*",
12141
+ "gh:repo:archive",
12142
+ "gh:repo:archive:*",
12143
+ "gh:repo:clone",
12144
+ "gh:repo:clone:*",
12145
+ "gh:release:create",
12146
+ "gh:release:create:*",
12147
+ "gh:release:delete",
12148
+ "gh:release:delete:*",
12149
+ "gh:release:edit",
12150
+ "gh:release:edit:*",
12151
+ "gh:run:cancel",
12152
+ "gh:run:cancel:*",
12153
+ "gh:run:rerun",
12154
+ "gh:run:rerun:*",
12155
+ "gh:workflow:run",
12156
+ "gh:workflow:run:*",
12157
+ "gh:workflow:enable",
12158
+ "gh:workflow:enable:*",
12159
+ "gh:workflow:disable",
12160
+ "gh:workflow:disable:*",
12161
+ "gh:gist:create",
12162
+ "gh:gist:create:*",
12163
+ "gh:gist:delete",
12164
+ "gh:gist:delete:*",
12165
+ "gh:gist:edit",
12166
+ "gh:gist:edit:*",
12167
+ "gh:secret:set",
12168
+ "gh:secret:set:*",
12169
+ "gh:secret:delete",
12170
+ "gh:secret:delete:*",
12171
+ "gh:variable:set",
12172
+ "gh:variable:set:*",
12173
+ "gh:variable:delete",
12174
+ "gh:variable:delete:*",
12175
+ "gh:label:create",
12176
+ "gh:label:create:*",
12177
+ "gh:label:delete",
12178
+ "gh:label:delete:*",
12179
+ "gh:ssh-key:add",
12180
+ "gh:ssh-key:add:*",
12181
+ "gh:ssh-key:delete",
12182
+ "gh:ssh-key:delete:*",
11965
12183
  // File system mounting and partitioning
11966
12184
  "mount",
11967
12185
  "mount:*",
@@ -69576,6 +69794,7 @@ __export(schemaUtils_exports, {
69576
69794
  replaceMermaidDiagramsInMarkdown: () => replaceMermaidDiagramsInMarkdown,
69577
69795
  sanitizeMarkdownEscapesInJson: () => sanitizeMarkdownEscapesInJson,
69578
69796
  tryAutoWrapForSimpleSchema: () => tryAutoWrapForSimpleSchema,
69797
+ tryExtractValidJsonPrefix: () => tryExtractValidJsonPrefix,
69579
69798
  tryMaidAutoFix: () => tryMaidAutoFix,
69580
69799
  validateAndFixMermaidResponse: () => validateAndFixMermaidResponse,
69581
69800
  validateJsonResponse: () => validateJsonResponse,
@@ -69962,6 +70181,13 @@ function validateJsonResponse(response, options = {}) {
69962
70181
  errorPosition = response.indexOf(problematicToken);
69963
70182
  }
69964
70183
  }
70184
+ const prefixResult = tryExtractValidJsonPrefix(responseToValidate, { schema, debug });
70185
+ if (prefixResult && prefixResult.isValid) {
70186
+ if (debug) {
70187
+ console.log(`[DEBUG] JSON validation: Recovered valid JSON prefix (${prefixResult.extracted.length} chars) from response with trailing content`);
70188
+ }
70189
+ return { isValid: true, parsed: prefixResult.parsed };
70190
+ }
69965
70191
  let enhancedError = error.message;
69966
70192
  let errorContext = null;
69967
70193
  if (errorPosition !== null && errorPosition >= 0 && response && response.length > 0) {
@@ -70012,6 +70238,84 @@ ${errorContext.pointer}`);
70012
70238
  };
70013
70239
  }
70014
70240
  }
70241
+ function tryExtractValidJsonPrefix(response, options = {}) {
70242
+ const { schema = null, debug = false } = options;
70243
+ if (!response || typeof response !== "string") {
70244
+ return null;
70245
+ }
70246
+ const trimmed = response.trim();
70247
+ if (trimmed.length === 0) {
70248
+ return null;
70249
+ }
70250
+ const firstChar = trimmed[0];
70251
+ if (firstChar !== "{" && firstChar !== "[") {
70252
+ return null;
70253
+ }
70254
+ try {
70255
+ JSON.parse(trimmed);
70256
+ return null;
70257
+ } catch {
70258
+ }
70259
+ const openChar = firstChar;
70260
+ const closeChar = openChar === "{" ? "}" : "]";
70261
+ let depth = 0;
70262
+ let inString = false;
70263
+ let escapeNext = false;
70264
+ let endPos = -1;
70265
+ for (let i = 0; i < trimmed.length; i++) {
70266
+ const char = trimmed[i];
70267
+ if (escapeNext) {
70268
+ escapeNext = false;
70269
+ continue;
70270
+ }
70271
+ if (char === "\\" && inString) {
70272
+ escapeNext = true;
70273
+ continue;
70274
+ }
70275
+ if (char === '"') {
70276
+ inString = !inString;
70277
+ continue;
70278
+ }
70279
+ if (inString) {
70280
+ continue;
70281
+ }
70282
+ if (char === openChar) {
70283
+ depth++;
70284
+ } else if (char === closeChar) {
70285
+ depth--;
70286
+ if (depth === 0) {
70287
+ endPos = i + 1;
70288
+ break;
70289
+ }
70290
+ }
70291
+ }
70292
+ if (endPos <= 0 || endPos >= trimmed.length) {
70293
+ return null;
70294
+ }
70295
+ const remainder = trimmed.substring(endPos).trim();
70296
+ if (remainder.length === 0) {
70297
+ return null;
70298
+ }
70299
+ const prefix = trimmed.substring(0, endPos);
70300
+ try {
70301
+ const parsed = JSON.parse(prefix);
70302
+ if (debug) {
70303
+ console.log(`[DEBUG] tryExtractValidJsonPrefix: Extracted valid JSON prefix (${prefix.length} chars), stripped trailing content (${remainder.length} chars)`);
70304
+ }
70305
+ if (schema) {
70306
+ const schemaValidation = validateJsonResponse(prefix, { debug, schema });
70307
+ if (!schemaValidation.isValid) {
70308
+ if (debug) {
70309
+ console.log(`[DEBUG] tryExtractValidJsonPrefix: Prefix is valid JSON but fails schema validation: ${schemaValidation.error}`);
70310
+ }
70311
+ return null;
70312
+ }
70313
+ }
70314
+ return { isValid: true, parsed, extracted: prefix };
70315
+ } catch {
70316
+ return null;
70317
+ }
70318
+ }
70015
70319
  function validateXmlResponse(response) {
70016
70320
  const xmlPattern = /<\/?[\w\s="'.-]+>/g;
70017
70321
  const tags = response.match(xmlPattern);
@@ -72113,7 +72417,7 @@ function parseXmlMcpToolCall(xmlString, mcpToolNames = []) {
72113
72417
  let match2;
72114
72418
  while ((match2 = paramPattern.exec(content)) !== null) {
72115
72419
  const [, paramName, paramValue] = match2;
72116
- params[paramName] = paramValue.trim();
72420
+ params[paramName] = unescapeXmlEntities(paramValue.trim());
72117
72421
  }
72118
72422
  }
72119
72423
  return { toolName, params };
@@ -72163,7 +72467,7 @@ function parseNativeXmlTool(xmlString, toolName) {
72163
72467
  while ((match2 = paramPattern.exec(content)) !== null) {
72164
72468
  const [, paramName, paramValue] = match2;
72165
72469
  if (paramName !== "params") {
72166
- params[paramName] = paramValue.trim();
72470
+ params[paramName] = unescapeXmlEntities(paramValue.trim());
72167
72471
  }
72168
72472
  }
72169
72473
  if (Object.keys(params).length > 0) {
@@ -72178,6 +72482,7 @@ var init_xmlBridge = __esm({
72178
72482
  init_client();
72179
72483
  init_config();
72180
72484
  init_xmlParsingUtils();
72485
+ init_common();
72181
72486
  MCPXmlBridge = class {
72182
72487
  constructor(options = {}) {
72183
72488
  this.debug = options.debug || false;
@@ -84802,8 +85107,8 @@ You are working with a workspace. Available paths: ${workspaceDesc}
84802
85107
  let currentIteration = 0;
84803
85108
  let completionAttempted = false;
84804
85109
  let finalResult = "I was unable to complete your request due to reaching the maximum number of tool iterations.";
84805
- const baseMaxIterations = this.maxIterations || MAX_TOOL_ITERATIONS;
84806
- const maxIterations = options.schema ? baseMaxIterations + 4 : baseMaxIterations;
85110
+ const baseMaxIterations = options._maxIterationsOverride || this.maxIterations || MAX_TOOL_ITERATIONS;
85111
+ const maxIterations = options._maxIterationsOverride ? baseMaxIterations : options.schema ? baseMaxIterations + 4 : baseMaxIterations;
84807
85112
  const isClaudeCode = this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true";
84808
85113
  const isCodex = this.clientApiProvider === "codex" || process.env.USE_CODEX === "true";
84809
85114
  if (isClaudeCode) {
@@ -86040,13 +86345,16 @@ Convert your previous response content into actual JSON data that follows this s
86040
86345
  options.schema,
86041
86346
  0
86042
86347
  );
86348
+ const { schema: _unusedSchema1, ...schemaDefCorrectionOptions } = options;
86043
86349
  finalResult = await this.answer(schemaDefinitionPrompt, [], {
86044
- ...options,
86350
+ ...schemaDefCorrectionOptions,
86045
86351
  _schemaFormatted: true,
86046
86352
  _skipValidation: true,
86047
86353
  // Skip validation in recursive correction calls to prevent loops
86048
- _completionPromptProcessed: true
86354
+ _completionPromptProcessed: true,
86049
86355
  // Prevent cascading completion prompts in retry calls
86356
+ _maxIterationsOverride: 3
86357
+ // Correction should complete in 1-2 iterations (issue #447)
86050
86358
  });
86051
86359
  finalResult = cleanSchemaResponse(finalResult);
86052
86360
  validation = validateJsonResponse(finalResult);
@@ -86094,15 +86402,18 @@ Convert your previous response content into actual JSON data that follows this s
86094
86402
  retryCount
86095
86403
  );
86096
86404
  }
86405
+ const { schema: _unusedSchema2, ...correctionOptions } = options;
86097
86406
  finalResult = await this.answer(correctionPrompt, [], {
86098
- ...options,
86407
+ ...correctionOptions,
86099
86408
  _schemaFormatted: true,
86100
86409
  _skipValidation: true,
86101
86410
  // Skip validation in recursive correction calls to prevent loops
86102
86411
  _disableTools: true,
86103
86412
  // Only allow attempt_completion - prevent AI from using search/query tools
86104
- _completionPromptProcessed: true
86413
+ _completionPromptProcessed: true,
86105
86414
  // Prevent cascading completion prompts in retry calls
86415
+ _maxIterationsOverride: 3
86416
+ // Correction should complete in 1-2 iterations (issue #447)
86106
86417
  });
86107
86418
  finalResult = cleanSchemaResponse(finalResult);
86108
86419
  validation = validateJsonResponse(finalResult, { debug: this.debug });
@@ -87721,7 +88032,7 @@ Please reformat your previous response to match this schema exactly. Only return
87721
88032
  if (!validation.isValid) {
87722
88033
  const correctionPrompt = createJsonCorrectionPrompt(result, schema, validation.error);
87723
88034
  try {
87724
- result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true });
88035
+ result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true, _maxIterationsOverride: 3 });
87725
88036
  result = cleanSchemaResponse(result);
87726
88037
  const finalValidation = validateJsonResponse(result);
87727
88038
  if (!finalValidation.isValid && args.debug) {
@@ -88012,11 +88323,11 @@ Please reformat your previous response to match this schema exactly. Only return
88012
88323
  if (appTracer) {
88013
88324
  result = await appTracer.withSpan(
88014
88325
  "agent.json_correction",
88015
- () => agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true }),
88326
+ () => agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true, _maxIterationsOverride: 3 }),
88016
88327
  { "original_error": validation.error }
88017
88328
  );
88018
88329
  } else {
88019
- result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true });
88330
+ result = await agent.answer(correctionPrompt, [], { schema, _schemaFormatted: true, _disableTools: true, _maxIterationsOverride: 3 });
88020
88331
  }
88021
88332
  result = cleanSchemaResponse(result);
88022
88333
  const finalValidation = validateJsonResponse(result);