@crownpeak/dqm-react-component-dev-mcp 1.2.0

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 (444) hide show
  1. package/README.md +138 -0
  2. package/data/.env.example +22 -0
  3. package/data/.gitattributes +47 -0
  4. package/data/.glfrc.json +7 -0
  5. package/data/.husky/pre-commit +5 -0
  6. package/data/.nvmrc +1 -0
  7. package/data/CHANGELOG.md +75 -0
  8. package/data/CODE_OF_CONDUCT.md +129 -0
  9. package/data/CONTRIBUTING.md +203 -0
  10. package/data/DOCS-STRUCTURE.md +307 -0
  11. package/data/I18N.md +292 -0
  12. package/data/LICENSE +22 -0
  13. package/data/README.md +315 -0
  14. package/data/SECURITY.md +125 -0
  15. package/data/WIKI-DEPLOYMENT.md +348 -0
  16. package/data/docs/AI-FEATURES.md +610 -0
  17. package/data/docs/API-REFERENCE.md +1022 -0
  18. package/data/docs/AUTHENTICATION.md +301 -0
  19. package/data/docs/BACKEND-API.md +468 -0
  20. package/data/docs/DEVELOPMENT.md +375 -0
  21. package/data/docs/EXAMPLES.md +622 -0
  22. package/data/docs/MCP-SERVER.md +307 -0
  23. package/data/docs/MIGRATION-GUIDE.md +367 -0
  24. package/data/docs/NPM-PUBLISH.md +193 -0
  25. package/data/docs/QUICKSTART.md +206 -0
  26. package/data/docs/REDIS-SETUP.md +162 -0
  27. package/data/docs/SERVER.md +228 -0
  28. package/data/docs/TROUBLESHOOTING.md +657 -0
  29. package/data/docs/WIDGET-GUIDE.md +638 -0
  30. package/data/docs/WIKI-HOME.md +58 -0
  31. package/data/docs/WIKI-SIDEBAR.md +39 -0
  32. package/data/package.json +171 -0
  33. package/data/playwright.config.ts +64 -0
  34. package/data/probe/.cargo/config.toml +10 -0
  35. package/data/probe/.claude/commands/performance-review.md +15 -0
  36. package/data/probe/.clinerules +288 -0
  37. package/data/probe/.dockerignore +57 -0
  38. package/data/probe/.githooks/post-commit +11 -0
  39. package/data/probe/.githooks/pre-commit +99 -0
  40. package/data/probe/.githooks/pre-commit-vow +9 -0
  41. package/data/probe/.prompts/engineer.md +41 -0
  42. package/data/probe/.roomodes +28 -0
  43. package/data/probe/.windsurfrules +0 -0
  44. package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
  45. package/data/probe/BENCHMARKING.md +256 -0
  46. package/data/probe/CLAUDE.md +226 -0
  47. package/data/probe/CODE_OF_CONDUCT.md +128 -0
  48. package/data/probe/CONTRIBUTING.md +193 -0
  49. package/data/probe/Cargo.toml +120 -0
  50. package/data/probe/Cross.toml +10 -0
  51. package/data/probe/DOCKER-README.md +224 -0
  52. package/data/probe/Dockerfile +32 -0
  53. package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
  54. package/data/probe/LICENSE +201 -0
  55. package/data/probe/Makefile +210 -0
  56. package/data/probe/README.md +824 -0
  57. package/data/probe/SECURITY.md +67 -0
  58. package/data/probe/WINDOWS-GUIDE.md +294 -0
  59. package/data/probe/benches/parsing_benchmarks.rs +370 -0
  60. package/data/probe/benches/search_benchmarks.rs +599 -0
  61. package/data/probe/benches/simd_benchmarks.rs +372 -0
  62. package/data/probe/benches/timing_benchmarks.rs +287 -0
  63. package/data/probe/build-windows.bat +229 -0
  64. package/data/probe/codex-config/config.toml +6 -0
  65. package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
  66. package/data/probe/examples/cache_demo.rs +46 -0
  67. package/data/probe/examples/chat/.dockerignore +37 -0
  68. package/data/probe/examples/chat/ChatSessionManager.js +295 -0
  69. package/data/probe/examples/chat/Dockerfile +98 -0
  70. package/data/probe/examples/chat/LICENSE +201 -0
  71. package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
  72. package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
  73. package/data/probe/examples/chat/README.md +338 -0
  74. package/data/probe/examples/chat/TRACING.md +226 -0
  75. package/data/probe/examples/chat/appTracer.js +968 -0
  76. package/data/probe/examples/chat/auth.js +76 -0
  77. package/data/probe/examples/chat/bin/probe-chat.js +13 -0
  78. package/data/probe/examples/chat/build.js +104 -0
  79. package/data/probe/examples/chat/cancelRequest.js +84 -0
  80. package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
  81. package/data/probe/examples/chat/demo-local-images.js +128 -0
  82. package/data/probe/examples/chat/fileSpanExporter.js +181 -0
  83. package/data/probe/examples/chat/implement/README.md +228 -0
  84. package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
  85. package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
  86. package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
  87. package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
  88. package/data/probe/examples/chat/implement/backends/registry.js +85 -0
  89. package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
  90. package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
  91. package/data/probe/examples/chat/implement/core/config.js +428 -0
  92. package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
  93. package/data/probe/examples/chat/implement/core/utils.js +496 -0
  94. package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
  95. package/data/probe/examples/chat/index.js +669 -0
  96. package/data/probe/examples/chat/mcpServer.js +341 -0
  97. package/data/probe/examples/chat/npm/LICENSE +15 -0
  98. package/data/probe/examples/chat/npm/README.md +168 -0
  99. package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
  100. package/data/probe/examples/chat/npm/index.js +259 -0
  101. package/data/probe/examples/chat/npm/package.json +54 -0
  102. package/data/probe/examples/chat/package.json +102 -0
  103. package/data/probe/examples/chat/probeChat.js +456 -0
  104. package/data/probe/examples/chat/probeTool.js +491 -0
  105. package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
  106. package/data/probe/examples/chat/telemetry.js +281 -0
  107. package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
  108. package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
  109. package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
  110. package/data/probe/examples/chat/test/test-backends.js +90 -0
  111. package/data/probe/examples/chat/test/testUtils.js +530 -0
  112. package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
  113. package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
  114. package/data/probe/examples/chat/test/verify-tests.js +118 -0
  115. package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
  116. package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
  117. package/data/probe/examples/chat/test-chat-tracing.js +38 -0
  118. package/data/probe/examples/chat/test-direct-function.js +49 -0
  119. package/data/probe/examples/chat/test-file-size-validation.js +103 -0
  120. package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
  121. package/data/probe/examples/chat/test-github-context.txt +12 -0
  122. package/data/probe/examples/chat/test-hierarchy.js +203 -0
  123. package/data/probe/examples/chat/test-image-spans.js +37 -0
  124. package/data/probe/examples/chat/test-local-image-reading.js +176 -0
  125. package/data/probe/examples/chat/test-mcp-integration.js +136 -0
  126. package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
  127. package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
  128. package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
  129. package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
  130. package/data/probe/examples/chat/test-security-validation.js +145 -0
  131. package/data/probe/examples/chat/test-simple-tracing.js +32 -0
  132. package/data/probe/examples/chat/test-trace-verification.js +235 -0
  133. package/data/probe/examples/chat/test-tracing.js +114 -0
  134. package/data/probe/examples/chat/tokenCounter.js +419 -0
  135. package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
  136. package/data/probe/examples/chat/webServer.js +1103 -0
  137. package/data/probe/examples/reranker/Cargo.toml +33 -0
  138. package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
  139. package/data/probe/examples/reranker/MODELS.md +66 -0
  140. package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
  141. package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
  142. package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
  143. package/data/probe/examples/reranker/README.md +347 -0
  144. package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
  145. package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
  146. package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
  147. package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
  148. package/data/probe/examples/reranker/debug_scoring.py +189 -0
  149. package/data/probe/examples/reranker/debug_tokenization.py +154 -0
  150. package/data/probe/examples/reranker/download_models.sh +73 -0
  151. package/data/probe/examples/reranker/requirements.txt +13 -0
  152. package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
  153. package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
  154. package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
  155. package/data/probe/examples/reranker/simple_test.py +50 -0
  156. package/data/probe/examples/reranker/test_all_models.sh +63 -0
  157. package/data/probe/examples/reranker/test_bert_results.sh +44 -0
  158. package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
  159. package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
  160. package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
  161. package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
  162. package/data/probe/examples/reranker/test_scores.py +132 -0
  163. package/data/probe/install.ps1 +508 -0
  164. package/data/probe/install.sh +460 -0
  165. package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
  166. package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
  167. package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
  168. package/data/probe/npm/MAID_INTEGRATION.md +313 -0
  169. package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
  170. package/data/probe/npm/README.md +824 -0
  171. package/data/probe/npm/bin/.gitignore +7 -0
  172. package/data/probe/npm/bin/.gitkeep +0 -0
  173. package/data/probe/npm/bin/README.md +12 -0
  174. package/data/probe/npm/bin/probe +167 -0
  175. package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
  176. package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
  177. package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
  178. package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
  179. package/data/probe/npm/example-usage.js +335 -0
  180. package/data/probe/npm/examples/multi-engine-demo.js +117 -0
  181. package/data/probe/npm/examples/probe-agent-cli.js +113 -0
  182. package/data/probe/npm/examples/test-agent-edit.js +114 -0
  183. package/data/probe/npm/examples/test-edit-create.js +120 -0
  184. package/data/probe/npm/examples/test-edit-direct.js +114 -0
  185. package/data/probe/npm/index.d.ts +744 -0
  186. package/data/probe/npm/jest.config.js +52 -0
  187. package/data/probe/npm/package.json +117 -0
  188. package/data/probe/npm/scripts/build-agent.cjs +75 -0
  189. package/data/probe/npm/scripts/build-cjs.js +124 -0
  190. package/data/probe/npm/scripts/build-mcp.cjs +36 -0
  191. package/data/probe/npm/scripts/postinstall.js +216 -0
  192. package/data/probe/npm/test-codex-e2e.js +78 -0
  193. package/data/probe/npm/test-download-lock.js +109 -0
  194. package/data/probe/npm/test-grep-security.js +94 -0
  195. package/data/probe/npm/test-grep-simplified.js +63 -0
  196. package/data/probe/npm/test-grep.js +51 -0
  197. package/data/probe/npm/tests/README.md +96 -0
  198. package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
  199. package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
  200. package/data/probe/npm/tests/contextCompactor.test.js +498 -0
  201. package/data/probe/npm/tests/delegate-config.test.js +353 -0
  202. package/data/probe/npm/tests/delegate-integration.test.js +348 -0
  203. package/data/probe/npm/tests/extractor-integration.test.js +162 -0
  204. package/data/probe/npm/tests/extractor.test.js +317 -0
  205. package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
  206. package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
  207. package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
  208. package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
  209. package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
  210. package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
  211. package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
  212. package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
  213. package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
  214. package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
  215. package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
  216. package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
  217. package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
  218. package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
  219. package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
  220. package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
  221. package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
  222. package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
  223. package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
  224. package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
  225. package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
  226. package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
  227. package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
  228. package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
  229. package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
  230. package/data/probe/npm/tests/setup.js +46 -0
  231. package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
  232. package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
  233. package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
  234. package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
  235. package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
  236. package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
  237. package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
  238. package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
  239. package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
  240. package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
  241. package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
  242. package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
  243. package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
  244. package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
  245. package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
  246. package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
  247. package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
  248. package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
  249. package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
  250. package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
  251. package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
  252. package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
  253. package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
  254. package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
  255. package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
  256. package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
  257. package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
  258. package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
  259. package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
  260. package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
  261. package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
  262. package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
  263. package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
  264. package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
  265. package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
  266. package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
  267. package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
  268. package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
  269. package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
  270. package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
  271. package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
  272. package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
  273. package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
  274. package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
  275. package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
  276. package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
  277. package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
  278. package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
  279. package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
  280. package/data/probe/npm/tsconfig.json +21 -0
  281. package/data/probe/result1.txt +19 -0
  282. package/data/probe/result2.txt +26 -0
  283. package/data/probe/scripts/benchmark.sh +270 -0
  284. package/data/probe/scripts/cache_memory_analysis.rs +844 -0
  285. package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
  286. package/data/probe/site/.env.example +10 -0
  287. package/data/probe/site/DEPLOYMENT.md +86 -0
  288. package/data/probe/site/README.md +183 -0
  289. package/data/probe/site/adding-languages.md +135 -0
  290. package/data/probe/site/ai-chat.md +427 -0
  291. package/data/probe/site/ai-integration.md +1488 -0
  292. package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
  293. package/data/probe/site/blog/index.md +118 -0
  294. package/data/probe/site/blog/v0.6.0-release.md +426 -0
  295. package/data/probe/site/blog.md +8 -0
  296. package/data/probe/site/changelog.md +200 -0
  297. package/data/probe/site/cli-mode.md +437 -0
  298. package/data/probe/site/code-extraction.md +436 -0
  299. package/data/probe/site/contributing/README.md +9 -0
  300. package/data/probe/site/contributing/documentation-cross-references.md +215 -0
  301. package/data/probe/site/contributing/documentation-maintenance.md +275 -0
  302. package/data/probe/site/contributing/documentation-structure.md +75 -0
  303. package/data/probe/site/documentation-cross-references.md +215 -0
  304. package/data/probe/site/documentation-guide.md +132 -0
  305. package/data/probe/site/documentation-maintenance.md +275 -0
  306. package/data/probe/site/features.md +147 -0
  307. package/data/probe/site/how-it-works.md +118 -0
  308. package/data/probe/site/index.md +175 -0
  309. package/data/probe/site/index.md.bak +133 -0
  310. package/data/probe/site/installation.md +235 -0
  311. package/data/probe/site/integrations/docker.md +248 -0
  312. package/data/probe/site/integrations/github-actions.md +413 -0
  313. package/data/probe/site/language-support-overview.md +168 -0
  314. package/data/probe/site/mcp-integration.md +587 -0
  315. package/data/probe/site/mcp-server.md +304 -0
  316. package/data/probe/site/navigation-structure.md +76 -0
  317. package/data/probe/site/nodejs-sdk.md +798 -0
  318. package/data/probe/site/output-formats.md +625 -0
  319. package/data/probe/site/package.json +21 -0
  320. package/data/probe/site/public/_headers +28 -0
  321. package/data/probe/site/public/_redirects +11 -0
  322. package/data/probe/site/quick-start.md +289 -0
  323. package/data/probe/site/search-functionality.md +291 -0
  324. package/data/probe/site/search-reference.md +291 -0
  325. package/data/probe/site/supported-languages.md +215 -0
  326. package/data/probe/site/use-cases/README.md +8 -0
  327. package/data/probe/site/use-cases/advanced-cli.md +253 -0
  328. package/data/probe/site/use-cases/ai-code-editors.md +239 -0
  329. package/data/probe/site/use-cases/building-ai-tools.md +529 -0
  330. package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
  331. package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
  332. package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
  333. package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
  334. package/data/probe/site/use-cases/team-chat.md +350 -0
  335. package/data/probe/site/web-interface.md +434 -0
  336. package/data/probe/site/wrangler.toml +9 -0
  337. package/data/probe/test-api-key.sh +1 -0
  338. package/data/probe/test-probe-implementation/hello.js +7 -0
  339. package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
  340. package/data/probe/test_cases/early_termination_issues.rs +533 -0
  341. package/data/probe/test_data/test_nested_struct.go +26 -0
  342. package/data/probe/tests/README.md +286 -0
  343. package/data/probe/tests/README_search_determinism_tests.md +116 -0
  344. package/data/probe/tests/adjacent_comment_test.rs +152 -0
  345. package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
  346. package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
  347. package/data/probe/tests/block_merging_tests.rs +396 -0
  348. package/data/probe/tests/c_outline_format_tests.rs +2179 -0
  349. package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
  350. package/data/probe/tests/cache_order_tests.rs +147 -0
  351. package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
  352. package/data/probe/tests/cli_tests.rs +680 -0
  353. package/data/probe/tests/comment_context_integration_test.rs +240 -0
  354. package/data/probe/tests/common.rs +33 -0
  355. package/data/probe/tests/complex_block_merging_tests.rs +599 -0
  356. package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
  357. package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
  358. package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
  359. package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
  360. package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
  361. package/data/probe/tests/extract_command_tests.rs +1848 -0
  362. package/data/probe/tests/extract_deduplication_tests.rs +146 -0
  363. package/data/probe/tests/extract_input_file_tests.rs +84 -0
  364. package/data/probe/tests/extract_prompt_tests.rs +102 -0
  365. package/data/probe/tests/filename_search_tests.rs +96 -0
  366. package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
  367. package/data/probe/tests/github_extract_tests.rs +234 -0
  368. package/data/probe/tests/go_comment_test.rs +253 -0
  369. package/data/probe/tests/go_outline_format_tests.rs +2587 -0
  370. package/data/probe/tests/go_path_resolver_tests.rs +96 -0
  371. package/data/probe/tests/html_outline_format_tests.rs +637 -0
  372. package/data/probe/tests/integration_tests.rs +837 -0
  373. package/data/probe/tests/ip_whitelist_test.rs +148 -0
  374. package/data/probe/tests/java_outline_format_tests.rs +1611 -0
  375. package/data/probe/tests/javascript_extract_tests.rs +315 -0
  376. package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
  377. package/data/probe/tests/json_format_tests.rs +436 -0
  378. package/data/probe/tests/json_schema_validation_tests.rs +450 -0
  379. package/data/probe/tests/lib_usage.rs +60 -0
  380. package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
  381. package/data/probe/tests/line_map_cache_tests.rs +114 -0
  382. package/data/probe/tests/markdown_integration_tests.rs +190 -0
  383. package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
  384. package/data/probe/tests/mocks/test_object.js +27 -0
  385. package/data/probe/tests/mocks/test_struct.go +50 -0
  386. package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
  387. package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
  388. package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
  389. package/data/probe/tests/negative_compound_word_tests.rs +246 -0
  390. package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
  391. package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
  392. package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
  393. package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
  394. package/data/probe/tests/parallel_extraction_tests.rs +178 -0
  395. package/data/probe/tests/parallel_search_tests.rs +355 -0
  396. package/data/probe/tests/path_resolver_tests.rs +698 -0
  397. package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
  398. package/data/probe/tests/php_outline_format_tests.rs +768 -0
  399. package/data/probe/tests/property_tests.proptest-regressions +9 -0
  400. package/data/probe/tests/property_tests.rs +118 -0
  401. package/data/probe/tests/python_outline_format_tests.rs +1538 -0
  402. package/data/probe/tests/query_command_json_tests.rs +438 -0
  403. package/data/probe/tests/query_command_tests.rs +232 -0
  404. package/data/probe/tests/query_command_xml_tests.rs +569 -0
  405. package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
  406. package/data/probe/tests/required_terms_filename_tests.rs +116 -0
  407. package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
  408. package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
  409. package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
  410. package/data/probe/tests/rust_outline_format_tests.rs +843 -0
  411. package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
  412. package/data/probe/tests/search_determinism_tests.rs +451 -0
  413. package/data/probe/tests/search_hints_tests.rs +253 -0
  414. package/data/probe/tests/special_character_escaping_tests.rs +417 -0
  415. package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
  416. package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
  417. package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
  418. package/data/probe/tests/symbols_tests.rs +166 -0
  419. package/data/probe/tests/test_file.rs +45 -0
  420. package/data/probe/tests/test_tokenize.rs +28 -0
  421. package/data/probe/tests/timeout_tests.rs +82 -0
  422. package/data/probe/tests/tokenization_tests.rs +195 -0
  423. package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
  424. package/data/probe/tests/typescript_extract_tests.rs +214 -0
  425. package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
  426. package/data/probe/tests/xml_format_tests.rs +568 -0
  427. package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
  428. package/data/scripts/postinstall.mjs +9 -0
  429. package/data/scripts/set-version.js +0 -0
  430. package/data/scripts/wiki-build.sh +111 -0
  431. package/data/scripts/wiki-deploy.sh +73 -0
  432. package/data/serve.json +12 -0
  433. package/data/test/demo-dynamic.html +134 -0
  434. package/data/test/demo-esm.html +105 -0
  435. package/data/test/demo-iife.html +78 -0
  436. package/data/tsconfig.json +7 -0
  437. package/data/vite.server.ts +483 -0
  438. package/data/vitest.config.ts +40 -0
  439. package/data/wiki/Home.md +58 -0
  440. package/data/wiki/_Sidebar.md +39 -0
  441. package/docs-mcp.config.json +20 -0
  442. package/package.json +56 -0
  443. package/src/config.js +111 -0
  444. package/src/index.js +395 -0
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Integration tests for Retry + Fallback together
3
+ */
4
+
5
+ import { describe, test, expect, jest, beforeEach } from '@jest/globals';
6
+ import { RetryManager } from '../../src/agent/RetryManager.js';
7
+ import { FallbackManager } from '../../src/agent/FallbackManager.js';
8
+
9
+ describe('Retry and Fallback Integration', () => {
10
+ beforeEach(() => {
11
+ jest.clearAllMocks();
12
+ });
13
+
14
+ describe('Combined retry and fallback flow', () => {
15
+ test('should retry on each provider before falling back', async () => {
16
+ const retry = new RetryManager({
17
+ maxRetries: 2,
18
+ initialDelay: 10,
19
+ debug: false
20
+ });
21
+
22
+ const fallback = new FallbackManager({
23
+ strategy: 'custom',
24
+ providers: [
25
+ { provider: 'anthropic', apiKey: 'key1' },
26
+ { provider: 'openai', apiKey: 'key2' },
27
+ { provider: 'google', apiKey: 'key3' }
28
+ ],
29
+ debug: false
30
+ });
31
+
32
+ const callLog = [];
33
+
34
+ // Mock function that tracks which provider is being used
35
+ const mockFn = jest.fn().mockImplementation((provider, model, config) => {
36
+ callLog.push(config.provider);
37
+
38
+ // First provider (anthropic) fails 3 times (1 initial + 2 retries)
39
+ if (config.provider === 'anthropic') {
40
+ return retry.executeWithRetry(() => {
41
+ throw new Error('Overloaded');
42
+ }, { provider: 'anthropic' });
43
+ }
44
+
45
+ // Second provider (openai) fails 3 times
46
+ if (config.provider === 'openai') {
47
+ return retry.executeWithRetry(() => {
48
+ throw new Error('Overloaded');
49
+ }, { provider: 'openai' });
50
+ }
51
+
52
+ // Third provider (google) succeeds on second retry
53
+ if (config.provider === 'google') {
54
+ let attempts = 0;
55
+ return retry.executeWithRetry(() => {
56
+ attempts++;
57
+ if (attempts < 2) {
58
+ throw new Error('Overloaded');
59
+ }
60
+ return 'success from google';
61
+ }, { provider: 'google' });
62
+ }
63
+ });
64
+
65
+ const result = await fallback.executeWithFallback(mockFn);
66
+
67
+ expect(result).toBe('success from google');
68
+ expect(callLog).toEqual(['anthropic', 'openai', 'google']);
69
+
70
+ // Verify fallback stats
71
+ const fallbackStats = fallback.getStats();
72
+ expect(fallbackStats.totalAttempts).toBe(3);
73
+ expect(fallbackStats.successfulProvider).toContain('google');
74
+ expect(fallbackStats.failedProviders.length).toBe(2);
75
+ });
76
+
77
+ test('should handle all providers exhausting retries', async () => {
78
+ const retry = new RetryManager({
79
+ maxRetries: 1,
80
+ initialDelay: 5,
81
+ debug: false
82
+ });
83
+
84
+ const fallback = new FallbackManager({
85
+ strategy: 'custom',
86
+ providers: [
87
+ { provider: 'anthropic', apiKey: 'key1' },
88
+ { provider: 'openai', apiKey: 'key2' }
89
+ ],
90
+ debug: false
91
+ });
92
+
93
+ const mockFn = jest.fn().mockImplementation((provider, model, config) => {
94
+ return retry.executeWithRetry(() => {
95
+ throw new Error('Overloaded');
96
+ }, { provider: config.provider });
97
+ });
98
+
99
+ await expect(fallback.executeWithFallback(mockFn)).rejects.toThrow();
100
+
101
+ // All providers should have been attempted
102
+ expect(mockFn).toHaveBeenCalledTimes(2);
103
+
104
+ const fallbackStats = fallback.getStats();
105
+ expect(fallbackStats.totalAttempts).toBe(2);
106
+ expect(fallbackStats.successfulProvider).toBeNull();
107
+ expect(fallbackStats.failedProviders.length).toBe(2);
108
+ });
109
+ });
110
+
111
+ describe('Real-world scenarios', () => {
112
+ test('should handle Azure Claude -> Bedrock fallback scenario', async () => {
113
+ const retry = new RetryManager({
114
+ maxRetries: 3,
115
+ initialDelay: 10,
116
+ debug: false
117
+ });
118
+
119
+ const fallback = new FallbackManager({
120
+ strategy: 'custom',
121
+ providers: [
122
+ {
123
+ provider: 'anthropic',
124
+ apiKey: 'azure-key',
125
+ baseURL: 'https://azure-endpoint.com',
126
+ model: 'claude-3-7-sonnet-20250219'
127
+ },
128
+ {
129
+ provider: 'bedrock',
130
+ region: 'us-west-2',
131
+ apiKey: 'bedrock-key',
132
+ model: 'anthropic.claude-sonnet-4-20250514-v1:0'
133
+ }
134
+ ],
135
+ debug: false
136
+ });
137
+
138
+ let azureAttempts = 0;
139
+ const mockFn = jest.fn().mockImplementation((provider, model, config) => {
140
+ return retry.executeWithRetry(() => {
141
+ // Azure fails with overloaded
142
+ if (config.baseURL?.includes('azure')) {
143
+ azureAttempts++;
144
+ throw new Error('Overloaded');
145
+ }
146
+
147
+ // Bedrock succeeds
148
+ return `success with ${model}`;
149
+ }, { provider: config.provider, model });
150
+ });
151
+
152
+ const result = await fallback.executeWithFallback(mockFn);
153
+
154
+ expect(result).toContain('anthropic.claude-sonnet');
155
+ expect(azureAttempts).toBe(4); // 1 initial + 3 retries
156
+
157
+ const stats = fallback.getStats();
158
+ expect(stats.successfulProvider).toContain('bedrock');
159
+ });
160
+
161
+ test('should handle mixed retryable and non-retryable errors', async () => {
162
+ const retry = new RetryManager({
163
+ maxRetries: 2,
164
+ initialDelay: 10,
165
+ debug: false
166
+ });
167
+
168
+ const fallback = new FallbackManager({
169
+ strategy: 'custom',
170
+ providers: [
171
+ { provider: 'anthropic', apiKey: 'key1' },
172
+ { provider: 'openai', apiKey: 'key2' }
173
+ ],
174
+ debug: false
175
+ });
176
+
177
+ const mockFn = jest.fn().mockImplementation((provider, model, config) => {
178
+ return retry.executeWithRetry(() => {
179
+ // First provider: non-retryable error (invalid API key)
180
+ if (config.provider === 'anthropic') {
181
+ throw new Error('Invalid API key');
182
+ }
183
+
184
+ // Second provider: succeeds
185
+ return 'success';
186
+ }, { provider: config.provider });
187
+ });
188
+
189
+ const result = await fallback.executeWithFallback(mockFn);
190
+
191
+ expect(result).toBe('success');
192
+
193
+ // Anthropic should only be attempted once (non-retryable)
194
+ // OpenAI should succeed on first attempt
195
+ expect(mockFn).toHaveBeenCalledTimes(2);
196
+ });
197
+
198
+ test('should respect maxTotalAttempts across providers', async () => {
199
+ const retry = new RetryManager({
200
+ maxRetries: 5,
201
+ initialDelay: 5,
202
+ debug: false
203
+ });
204
+
205
+ const fallback = new FallbackManager({
206
+ strategy: 'custom',
207
+ providers: [
208
+ { provider: 'anthropic', apiKey: 'key1' },
209
+ { provider: 'openai', apiKey: 'key2' },
210
+ { provider: 'google', apiKey: 'key3' },
211
+ { provider: 'bedrock', apiKey: 'key4' }
212
+ ],
213
+ maxTotalAttempts: 2, // Only allow 2 provider attempts total
214
+ debug: false
215
+ });
216
+
217
+ const mockFn = jest.fn().mockImplementation((provider, model, config) => {
218
+ return retry.executeWithRetry(() => {
219
+ throw new Error('Overloaded');
220
+ }, { provider: config.provider });
221
+ });
222
+
223
+ await expect(fallback.executeWithFallback(mockFn)).rejects.toThrow();
224
+
225
+ // Should only attempt 2 providers
226
+ expect(mockFn).toHaveBeenCalledTimes(2);
227
+ });
228
+ });
229
+
230
+ describe('Statistics and monitoring', () => {
231
+ test('should track detailed statistics across retry and fallback', async () => {
232
+ const retry = new RetryManager({
233
+ maxRetries: 2,
234
+ initialDelay: 5,
235
+ debug: false
236
+ });
237
+
238
+ const fallback = new FallbackManager({
239
+ strategy: 'custom',
240
+ providers: [
241
+ { provider: 'anthropic', apiKey: 'key1' },
242
+ { provider: 'openai', apiKey: 'key2' }
243
+ ],
244
+ debug: false
245
+ });
246
+
247
+ let anthropicAttempts = 0;
248
+ const mockFn = jest.fn().mockImplementation((provider, model, config) => {
249
+ if (config.provider === 'anthropic') {
250
+ return retry.executeWithRetry(() => {
251
+ anthropicAttempts++;
252
+ throw new Error('Overloaded');
253
+ }, { provider: 'anthropic' });
254
+ }
255
+
256
+ return retry.executeWithRetry(() => 'success', { provider: 'openai' });
257
+ });
258
+
259
+ await fallback.executeWithFallback(mockFn);
260
+
261
+ // Check fallback stats
262
+ const fallbackStats = fallback.getStats();
263
+ expect(fallbackStats.totalAttempts).toBe(2);
264
+ expect(fallbackStats.failedProviders.length).toBe(1);
265
+ expect(fallbackStats.successfulProvider).toContain('openai');
266
+
267
+ // Anthropic should have 3 total attempts (1 + 2 retries)
268
+ expect(anthropicAttempts).toBe(3);
269
+ });
270
+ });
271
+
272
+ describe('Edge cases', () => {
273
+ test('should handle empty provider list gracefully', async () => {
274
+ const fallback = new FallbackManager({
275
+ strategy: 'any',
276
+ providers: []
277
+ });
278
+
279
+ await expect(fallback.executeWithFallback(() => {})).rejects.toThrow('No providers configured');
280
+ });
281
+
282
+ test('should handle provider creation failures', async () => {
283
+ const fallback = new FallbackManager({
284
+ strategy: 'custom',
285
+ providers: [
286
+ { provider: 'anthropic', apiKey: 'test-key-1' },
287
+ { provider: 'openai', apiKey: 'valid-key' }
288
+ ],
289
+ debug: false
290
+ });
291
+
292
+ const mockFn = jest.fn().mockImplementation((provider, model, config) => {
293
+ // First provider throws error during execution
294
+ if (config.provider === 'anthropic') {
295
+ throw new Error('Provider creation failed');
296
+ }
297
+ // Second provider succeeds
298
+ return 'success';
299
+ });
300
+
301
+ // Should fallback to second provider
302
+ const result = await fallback.executeWithFallback(mockFn);
303
+ expect(result).toBe('success');
304
+ expect(mockFn).toHaveBeenCalledTimes(2);
305
+ });
306
+
307
+ test('should handle AbortSignal in retry manager', async () => {
308
+ const retry = new RetryManager({
309
+ maxRetries: 10,
310
+ initialDelay: 100,
311
+ debug: false
312
+ });
313
+
314
+ const controller = new AbortController();
315
+
316
+ // Abort after first attempt
317
+ setTimeout(() => controller.abort(), 50);
318
+
319
+ const mockFn = jest.fn().mockImplementation(() => {
320
+ throw new Error('Overloaded');
321
+ });
322
+
323
+ await expect(
324
+ retry.executeWithRetry(mockFn, { signal: controller.signal })
325
+ ).rejects.toThrow('Operation aborted');
326
+
327
+ // Should not exhaust all retries
328
+ expect(mockFn.mock.calls.length).toBeLessThan(10);
329
+ });
330
+ });
331
+
332
+ describe('Performance', () => {
333
+ test('should complete fallback reasonably quickly with fast retries', async () => {
334
+ const retry = new RetryManager({
335
+ maxRetries: 2,
336
+ initialDelay: 1, // 1ms
337
+ maxDelay: 10,
338
+ debug: false
339
+ });
340
+
341
+ const fallback = new FallbackManager({
342
+ strategy: 'custom',
343
+ providers: [
344
+ { provider: 'anthropic', apiKey: 'key1' },
345
+ { provider: 'openai', apiKey: 'key2' }
346
+ ],
347
+ debug: false
348
+ });
349
+
350
+ const mockFn = jest.fn().mockImplementation((provider, model, config) => {
351
+ if (config.provider === 'anthropic') {
352
+ return retry.executeWithRetry(() => {
353
+ throw new Error('Overloaded');
354
+ }, { provider: 'anthropic' });
355
+ }
356
+ return retry.executeWithRetry(() => 'success', { provider: 'openai' });
357
+ });
358
+
359
+ const startTime = Date.now();
360
+ await fallback.executeWithFallback(mockFn);
361
+ const duration = Date.now() - startTime;
362
+
363
+ // Should complete in less than 500ms (with some margin for test execution)
364
+ // 3 retries * ~2ms delay = ~6ms for anthropic, then openai succeeds immediately
365
+ expect(duration).toBeLessThan(500);
366
+ });
367
+ });
368
+ });
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Integration test for the JSON schema validation loop bug fix
3
+ *
4
+ * This test validates that schema instructions are added to the INITIAL user message,
5
+ * preventing the validation loop that occurred when the AI responded with plain text
6
+ * and then received correction prompts.
7
+ *
8
+ * Bug: https://github.com/probelabs/probe/issues/XXX
9
+ * Fix: Schema instructions prepended to user message before AI sees it
10
+ */
11
+
12
+ import { describe, test, expect } from '@jest/globals';
13
+ import { generateExampleFromSchema } from '../../src/agent/schemaUtils.js';
14
+
15
+ describe('Schema in Initial Message - Bug Fix Integration Test', () => {
16
+
17
+ describe('generateExampleFromSchema - Used in Initial Message', () => {
18
+ test('should generate valid JSON example for Visor refine schema', () => {
19
+ // This is the exact schema from the bug report that caused the validation loop
20
+ const visorRefineSchema = {
21
+ type: 'object',
22
+ additionalProperties: false,
23
+ properties: {
24
+ refined: {
25
+ type: 'boolean',
26
+ description: 'true if the task description is clear and actionable, false if clarification is needed'
27
+ },
28
+ text: {
29
+ type: 'string',
30
+ description: 'If refined=true, confirmation message. If refined=false, specific questions to ask.'
31
+ }
32
+ },
33
+ required: ['refined', 'text']
34
+ };
35
+
36
+ const example = generateExampleFromSchema(visorRefineSchema);
37
+
38
+ // Should generate a valid example
39
+ expect(example).toBeDefined();
40
+ expect(example).not.toBeNull();
41
+
42
+ // Should have the correct structure
43
+ expect(example).toHaveProperty('refined');
44
+ expect(example).toHaveProperty('text');
45
+
46
+ // Should use correct types
47
+ expect(typeof example.refined).toBe('boolean');
48
+ expect(typeof example.text).toBe('string');
49
+
50
+ // Should be valid JSON when stringified
51
+ const jsonString = JSON.stringify(example);
52
+ expect(() => JSON.parse(jsonString)).not.toThrow();
53
+
54
+ // The example should match what the AI is expected to generate
55
+ expect(example).toEqual({
56
+ refined: false,
57
+ text: 'If refined=true, confirmation message. If refined=false, specific questions to ask.'
58
+ });
59
+ });
60
+
61
+ test('should create a complete schema instruction message', () => {
62
+ const schema = {
63
+ type: 'object',
64
+ properties: {
65
+ status: { type: 'string', description: 'Operation status' },
66
+ count: { type: 'number' }
67
+ }
68
+ };
69
+
70
+ const example = generateExampleFromSchema(schema);
71
+
72
+ // Simulate how the message would be constructed in ProbeAgent
73
+ const userMessage = 'Please analyze this code';
74
+ const schemaInstructions = `\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n${JSON.stringify(schema, null, 2)}\n\nExample:\n<attempt_completion>\n${JSON.stringify(example, null, 2)}\n</attempt_completion>\n\nYour response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.`;
75
+
76
+ const fullMessage = userMessage + schemaInstructions;
77
+
78
+ // Should contain the original message
79
+ expect(fullMessage).toContain('Please analyze this code');
80
+
81
+ // Should contain clear JSON requirement
82
+ expect(fullMessage).toContain('IMPORTANT');
83
+ expect(fullMessage).toContain('you MUST format it as valid JSON');
84
+
85
+ // Should contain the schema
86
+ expect(fullMessage).toContain('"type": "object"');
87
+ expect(fullMessage).toContain('"status"');
88
+ expect(fullMessage).toContain('"count"');
89
+
90
+ // Should contain a concrete example
91
+ expect(fullMessage).toContain('Example:');
92
+ expect(fullMessage).toContain('<attempt_completion>');
93
+ expect(fullMessage).toContain('"status": "Operation status"');
94
+ expect(fullMessage).toContain('"count": 0');
95
+
96
+ // Should contain explicit restrictions
97
+ expect(fullMessage).toContain('ONLY valid JSON');
98
+ expect(fullMessage).toContain('no plain text');
99
+ expect(fullMessage).toContain('no explanations');
100
+ expect(fullMessage).toContain('no markdown');
101
+ });
102
+
103
+ test('should handle schema as JSON string (common in Visor)', () => {
104
+ const schemaString = JSON.stringify({
105
+ type: 'object',
106
+ properties: {
107
+ result: { type: 'string' }
108
+ }
109
+ });
110
+
111
+ const example = generateExampleFromSchema(schemaString);
112
+
113
+ expect(example).toBeDefined();
114
+ expect(example).toHaveProperty('result');
115
+ expect(typeof example.result).toBe('string');
116
+ });
117
+
118
+ test('should gracefully handle invalid schema without crashing', () => {
119
+ const invalidSchema = 'not valid json {';
120
+
121
+ const example = generateExampleFromSchema(invalidSchema);
122
+
123
+ // Should return null for invalid schema
124
+ expect(example).toBeNull();
125
+
126
+ // This ensures the user message construction doesn't crash
127
+ // even if schema parsing fails
128
+ });
129
+ });
130
+
131
+ describe('Bug Prevention - Validation Loop Scenario', () => {
132
+ test('should document the bug scenario that is now prevented', () => {
133
+ // BEFORE THE FIX:
134
+ // 1. User message: "Hi! Just checking"
135
+ // 2. Schema: {refined: boolean, text: string}
136
+ // 3. AI receives ONLY: "Hi! Just checking" (no schema info)
137
+ // 4. AI responds: "Hello! I'm ready to help..." (plain text)
138
+ // 5. System tries to parse as JSON -> FAILS
139
+ // 6. System sends correction: "CRITICAL JSON ERROR..."
140
+ // 7. AI still responds with plain text -> LOOP continues for 3 attempts
141
+ // 8. Total time: 100+ seconds, 30+ API calls
142
+
143
+ // AFTER THE FIX:
144
+ // 1. User message: "Hi! Just checking"
145
+ // 2. Schema: {refined: boolean, text: string}
146
+ const schema = {
147
+ type: 'object',
148
+ properties: {
149
+ refined: { type: 'boolean' },
150
+ text: { type: 'string' }
151
+ }
152
+ };
153
+
154
+ // 3. System generates example
155
+ const example = generateExampleFromSchema(schema);
156
+
157
+ // 4. AI receives enriched message with schema instructions
158
+ const userMessage = 'Hi! Just checking';
159
+ const enrichedMessage = userMessage + `\n\nIMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:\n\n${JSON.stringify(schema, null, 2)}\n\nExample:\n<attempt_completion>\n${JSON.stringify(example, null, 2)}\n</attempt_completion>\n\nYour response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.`;
160
+
161
+ // 5. AI now knows to respond with JSON from the start
162
+ // 6. AI responds: <attempt_completion>{"refined": false, "text": "..."}</attempt_completion>
163
+ // 7. System parses JSON -> SUCCESS on first try
164
+ // 8. Total time: 4 seconds, 1 API call
165
+
166
+ // Verify the fix is in place
167
+ expect(enrichedMessage).toContain('you MUST format it as valid JSON');
168
+ expect(enrichedMessage).toContain(JSON.stringify(example, null, 2));
169
+ expect(enrichedMessage).not.toContain('CRITICAL JSON ERROR'); // No correction needed!
170
+ });
171
+
172
+ test('should prevent the specific Gemini 2.5 Pro issue', () => {
173
+ // The bug was specifically observed with Google Gemini 2.5 Pro
174
+ // which would respond with plain text or <task> XML tags
175
+
176
+ const visorSchema = {
177
+ type: 'object',
178
+ additionalProperties: false,
179
+ properties: {
180
+ refined: { type: 'boolean' },
181
+ text: { type: 'string' }
182
+ },
183
+ required: ['refined', 'text']
184
+ };
185
+
186
+ const example = generateExampleFromSchema(visorSchema);
187
+
188
+ // The example should be immediately usable by the AI
189
+ expect(JSON.stringify(example)).toBe(
190
+ '{"refined":false,"text":"your answer here"}'
191
+ );
192
+
193
+ // This is what the AI should see upfront, preventing confusion
194
+ const instructions = `IMPORTANT: When you provide your final answer using attempt_completion, you MUST format it as valid JSON matching this schema:
195
+
196
+ ${JSON.stringify(visorSchema, null, 2)}
197
+
198
+ Example:
199
+ <attempt_completion>
200
+ ${JSON.stringify(example, null, 2)}
201
+ </attempt_completion>
202
+
203
+ Your response inside attempt_completion must be ONLY valid JSON - no plain text, no explanations, no markdown.`;
204
+
205
+ // Should be crystal clear to the AI
206
+ expect(instructions).toContain('MUST format it as valid JSON');
207
+ expect(instructions).toContain('Example:');
208
+ expect(instructions).toContain('ONLY valid JSON');
209
+ expect(instructions).toContain('no plain text');
210
+ });
211
+ });
212
+
213
+ describe('Edge Cases', () => {
214
+ test('should handle schema with deeply nested objects', () => {
215
+ const nestedSchema = {
216
+ type: 'object',
217
+ properties: {
218
+ user: {
219
+ type: 'object',
220
+ properties: {
221
+ profile: {
222
+ type: 'object',
223
+ properties: {
224
+ name: { type: 'string' }
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ };
231
+
232
+ const example = generateExampleFromSchema(nestedSchema);
233
+
234
+ // Should handle nesting
235
+ expect(example).toHaveProperty('user');
236
+ expect(typeof example.user).toBe('object');
237
+
238
+ // Inner objects default to empty
239
+ expect(example.user).toEqual({});
240
+ });
241
+
242
+ test('should handle schema with all primitive types', () => {
243
+ const allTypesSchema = {
244
+ type: 'object',
245
+ properties: {
246
+ str: { type: 'string', description: 'A string' },
247
+ num: { type: 'number' },
248
+ bool: { type: 'boolean' },
249
+ arr: { type: 'array' },
250
+ obj: { type: 'object' }
251
+ }
252
+ };
253
+
254
+ const example = generateExampleFromSchema(allTypesSchema);
255
+
256
+ expect(example).toEqual({
257
+ str: 'A string',
258
+ num: 0,
259
+ bool: false,
260
+ arr: [],
261
+ obj: {}
262
+ });
263
+
264
+ // Should be valid JSON
265
+ expect(() => JSON.parse(JSON.stringify(example))).not.toThrow();
266
+ });
267
+
268
+ test('should use description as example value for strings', () => {
269
+ const schema = {
270
+ type: 'object',
271
+ properties: {
272
+ greeting: { type: 'string', description: 'Hello, World!' },
273
+ noDesc: { type: 'string' }
274
+ }
275
+ };
276
+
277
+ const example = generateExampleFromSchema(schema);
278
+
279
+ // Description should be used as the example value
280
+ expect(example.greeting).toBe('Hello, World!');
281
+
282
+ // Without description, default placeholder
283
+ expect(example.noDesc).toBe('your answer here');
284
+ });
285
+ });
286
+
287
+ describe('Performance - Bug Fix Impact', () => {
288
+ test('should prevent wasted iterations (regression test)', () => {
289
+ // Before fix: 30+ iterations (tool loop + 3 correction attempts each)
290
+ // After fix: 1 iteration (AI gets it right on first try)
291
+
292
+ const schema = {
293
+ type: 'object',
294
+ properties: {
295
+ refined: { type: 'boolean' },
296
+ text: { type: 'string' }
297
+ }
298
+ };
299
+
300
+ const startTime = Date.now();
301
+
302
+ // Generate example (happens once per request)
303
+ const example = generateExampleFromSchema(schema);
304
+
305
+ const endTime = Date.now();
306
+ const generationTime = endTime - startTime;
307
+
308
+ // Should be very fast (< 10ms)
309
+ expect(generationTime).toBeLessThan(10);
310
+
311
+ // Should produce valid output
312
+ expect(example).toBeDefined();
313
+ expect(() => JSON.parse(JSON.stringify(example))).not.toThrow();
314
+
315
+ // This small cost (< 10ms) saves 100+ seconds of validation loops
316
+ });
317
+ });
318
+ });