@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,151 @@
1
+ /**
2
+ * Unit tests for allow_tests default behavior in Vercel AI SDK tools
3
+ *
4
+ * Issue #323: allow_tests parameter has a documented default of true,
5
+ * but this default was not applied when AI tools omit the parameter.
6
+ *
7
+ * @module tests/allow-tests-default
8
+ */
9
+
10
+ import { jest, describe, test, expect, beforeEach } from '@jest/globals';
11
+
12
+ describe('allow_tests Default Behavior', () => {
13
+ describe('Zod Schema Defaults', () => {
14
+ test('querySchema should have allow_tests default to true', async () => {
15
+ const { querySchema } = await import('../src/tools/common.js');
16
+
17
+ // Parse an empty object - should get default value
18
+ const result = querySchema.parse({ pattern: 'test' });
19
+
20
+ expect(result.allow_tests).toBe(true);
21
+ });
22
+
23
+ test('extractSchema should have allow_tests default to true', async () => {
24
+ const { extractSchema } = await import('../src/tools/common.js');
25
+
26
+ // Parse with only required field
27
+ const result = extractSchema.parse({ targets: 'file.js' });
28
+
29
+ expect(result.allow_tests).toBe(true);
30
+ });
31
+
32
+ test('querySchema should respect explicit false value', async () => {
33
+ const { querySchema } = await import('../src/tools/common.js');
34
+
35
+ const result = querySchema.parse({ pattern: 'test', allow_tests: false });
36
+
37
+ expect(result.allow_tests).toBe(false);
38
+ });
39
+
40
+ test('extractSchema should respect explicit false value', async () => {
41
+ const { extractSchema } = await import('../src/tools/common.js');
42
+
43
+ const result = extractSchema.parse({ targets: 'file.js', allow_tests: false });
44
+
45
+ expect(result.allow_tests).toBe(false);
46
+ });
47
+ });
48
+
49
+ describe('Default Application Logic', () => {
50
+ /**
51
+ * Tests the default application logic that should be used in vercel.js tools.
52
+ * The fix uses nullish coalescing: allowTests: allow_tests ?? true
53
+ * This handles both undefined and null as "not specified"
54
+ */
55
+ function applyAllowTestsDefault(allow_tests) {
56
+ return allow_tests ?? true;
57
+ }
58
+
59
+ test('should return true when allow_tests is undefined', () => {
60
+ expect(applyAllowTestsDefault(undefined)).toBe(true);
61
+ });
62
+
63
+ test('should return true when allow_tests is explicitly true', () => {
64
+ expect(applyAllowTestsDefault(true)).toBe(true);
65
+ });
66
+
67
+ test('should return false when allow_tests is explicitly false', () => {
68
+ expect(applyAllowTestsDefault(false)).toBe(false);
69
+ });
70
+
71
+ test('should return true when allow_tests is null (treated as not specified)', () => {
72
+ // null should be treated the same as undefined - use default value
73
+ expect(applyAllowTestsDefault(null)).toBe(true);
74
+ });
75
+ });
76
+
77
+ describe('Vercel Tool Implementation Verification', () => {
78
+ /**
79
+ * Verify that the vercel.js file contains the correct default application pattern.
80
+ * This is a code inspection test to catch regressions.
81
+ */
82
+ test('searchTool should apply default for allowTests', async () => {
83
+ const fs = await import('fs');
84
+ const path = await import('path');
85
+ const { fileURLToPath } = await import('url');
86
+ const __dirname = path.default.dirname(fileURLToPath(import.meta.url));
87
+ const vercelPath = path.default.resolve(__dirname, '../src/tools/vercel.js');
88
+ const vercelSource = fs.default.readFileSync(vercelPath, 'utf-8');
89
+
90
+ // Check that the searchTool uses the nullish coalescing pattern
91
+ expect(vercelSource).toContain('allowTests: allow_tests ?? true');
92
+ });
93
+
94
+ test('queryTool should apply default for allowTests', async () => {
95
+ const fs = await import('fs');
96
+ const path = await import('path');
97
+ const { fileURLToPath } = await import('url');
98
+ const __dirname = path.default.dirname(fileURLToPath(import.meta.url));
99
+ const vercelPath = path.default.resolve(__dirname, '../src/tools/vercel.js');
100
+ const vercelSource = fs.default.readFileSync(vercelPath, 'utf-8');
101
+
102
+ // The queryTool should have the pattern somewhere in its implementation
103
+ // Count occurrences to ensure all tools have the fix
104
+ const matches = vercelSource.match(/allowTests: allow_tests \?\? true/g);
105
+ // Should have at least 4 occurrences (search, query, extract with targets, extract with input_content)
106
+ expect(matches).not.toBeNull();
107
+ expect(matches.length).toBeGreaterThanOrEqual(4);
108
+ });
109
+
110
+ test('extractTool should apply default for allowTests in both branches', async () => {
111
+ const fs = await import('fs');
112
+ const path = await import('path');
113
+ const { fileURLToPath } = await import('url');
114
+ const __dirname = path.default.dirname(fileURLToPath(import.meta.url));
115
+ const vercelPath = path.default.resolve(__dirname, '../src/tools/vercel.js');
116
+ const vercelSource = fs.default.readFileSync(vercelPath, 'utf-8');
117
+
118
+ // Extract tool has two places where allowTests is set (targets and input_content branches)
119
+ // Both should use the nullish coalescing pattern
120
+ const extractSection = vercelSource.slice(
121
+ vercelSource.indexOf('export const extractTool'),
122
+ vercelSource.indexOf('export const delegateTool')
123
+ );
124
+
125
+ const matches = extractSection.match(/allowTests: allow_tests \?\? true/g);
126
+ expect(matches).not.toBeNull();
127
+ expect(matches.length).toBe(2); // One for targets branch, one for input_content branch
128
+ });
129
+ });
130
+
131
+ describe('LangChain Tool Implementation Verification', () => {
132
+ /**
133
+ * Verify that the langchain.js file contains the correct default application pattern.
134
+ * This is a code inspection test to catch regressions.
135
+ */
136
+ test('LangChain tools should apply default for allowTests', async () => {
137
+ const fs = await import('fs');
138
+ const path = await import('path');
139
+ const { fileURLToPath } = await import('url');
140
+ const __dirname = path.default.dirname(fileURLToPath(import.meta.url));
141
+ const langchainPath = path.default.resolve(__dirname, '../src/tools/langchain.js');
142
+ const langchainSource = fs.default.readFileSync(langchainPath, 'utf-8');
143
+
144
+ // Count occurrences to ensure all tools have the fix
145
+ const matches = langchainSource.match(/allowTests: allow_tests \?\? true/g);
146
+ // Should have 3 occurrences (search, query, extract)
147
+ expect(matches).not.toBeNull();
148
+ expect(matches.length).toBe(3);
149
+ });
150
+ });
151
+ });
@@ -0,0 +1,498 @@
1
+ /**
2
+ * Tests for Context Compactor
3
+ */
4
+
5
+ import { jest } from '@jest/globals';
6
+ import {
7
+ isContextLimitError,
8
+ identifyMessageSegments,
9
+ compactMessages,
10
+ calculateCompactionStats,
11
+ handleContextLimitError
12
+ } from '../src/agent/contextCompactor.js';
13
+
14
+ describe('Context Compactor', () => {
15
+ describe('isContextLimitError', () => {
16
+ it('should detect Anthropic context length error', () => {
17
+ const error = new Error('prompt is too long: context_length_exceeded');
18
+ expect(isContextLimitError(error)).toBe(true);
19
+ });
20
+
21
+ it('should detect OpenAI context window error', () => {
22
+ const error = new Error('This model\'s maximum context length is 8192 tokens. However, your messages resulted in 10000 tokens.');
23
+ expect(isContextLimitError(error)).toBe(true);
24
+ });
25
+
26
+ it('should detect Gemini token limit error', () => {
27
+ const error = new Error('The input token count exceeds the maximum limit of 128000 tokens');
28
+ expect(isContextLimitError(error)).toBe(true);
29
+ });
30
+
31
+ it('should detect generic "too long" error', () => {
32
+ const error = new Error('The prompt is too long and exceeds the context window');
33
+ expect(isContextLimitError(error)).toBe(true);
34
+ });
35
+
36
+ it('should detect "over limit" variations', () => {
37
+ const error = new Error('Total tokens over the limit');
38
+ expect(isContextLimitError(error)).toBe(true);
39
+ });
40
+
41
+ it('should detect "maximum tokens" error', () => {
42
+ const error = new Error('Request exceeds maximum tokens allowed');
43
+ expect(isContextLimitError(error)).toBe(true);
44
+ });
45
+
46
+ it('should work with string error messages', () => {
47
+ const errorString = 'context window exceeded';
48
+ expect(isContextLimitError(errorString)).toBe(true);
49
+ });
50
+
51
+ it('should not match unrelated errors', () => {
52
+ const error = new Error('Network connection failed');
53
+ expect(isContextLimitError(error)).toBe(false);
54
+ });
55
+
56
+ it('should not match partial matches without overflow cues', () => {
57
+ const error = new Error('Using context from previous message');
58
+ expect(isContextLimitError(error)).toBe(false);
59
+ });
60
+ });
61
+
62
+ describe('identifyMessageSegments', () => {
63
+ it('should identify simple user-assistant-result segment', () => {
64
+ const messages = [
65
+ { role: 'system', content: 'You are an AI assistant' },
66
+ { role: 'user', content: 'Search for function definitions' },
67
+ { role: 'assistant', content: '<thinking>Let me search</thinking>\n<search>function</search>' },
68
+ { role: 'user', content: '<tool_result>Found 10 results</tool_result>' }
69
+ ];
70
+
71
+ const segments = identifyMessageSegments(messages);
72
+ expect(segments).toHaveLength(1);
73
+ expect(segments[0]).toEqual({
74
+ userIndex: 1,
75
+ monologueIndices: [2],
76
+ finalIndex: 3
77
+ });
78
+ });
79
+
80
+ it('should identify multiple segments', () => {
81
+ const messages = [
82
+ { role: 'system', content: 'System' },
83
+ { role: 'user', content: 'First query' },
84
+ { role: 'assistant', content: '<search>test</search>' },
85
+ { role: 'user', content: '<tool_result>Result 1</tool_result>' },
86
+ { role: 'user', content: 'Second query' },
87
+ { role: 'assistant', content: '<extract>file.js</extract>' },
88
+ { role: 'user', content: '<tool_result>Result 2</tool_result>' }
89
+ ];
90
+
91
+ const segments = identifyMessageSegments(messages);
92
+ expect(segments).toHaveLength(2);
93
+
94
+ expect(segments[0].userIndex).toBe(1);
95
+ expect(segments[0].finalIndex).toBe(3);
96
+
97
+ expect(segments[1].userIndex).toBe(4);
98
+ expect(segments[1].finalIndex).toBe(6);
99
+ });
100
+
101
+ it('should handle segment with multiple monologue messages', () => {
102
+ const messages = [
103
+ { role: 'user', content: 'Query' },
104
+ { role: 'assistant', content: '<thinking>First thought</thinking>' },
105
+ { role: 'assistant', content: '<thinking>Second thought</thinking>' },
106
+ { role: 'assistant', content: '<search>test</search>' },
107
+ { role: 'user', content: '<tool_result>Result</tool_result>' }
108
+ ];
109
+
110
+ const segments = identifyMessageSegments(messages);
111
+ expect(segments).toHaveLength(1);
112
+ expect(segments[0].monologueIndices).toEqual([1, 2, 3]);
113
+ });
114
+
115
+ it('should handle attempt_completion as segment end', () => {
116
+ const messages = [
117
+ { role: 'user', content: 'Query' },
118
+ { role: 'assistant', content: '<search>test</search>' },
119
+ { role: 'user', content: '<tool_result>Found results</tool_result>' },
120
+ { role: 'assistant', content: '<attempt_completion>Here is the answer</attempt_completion>' }
121
+ ];
122
+
123
+ const segments = identifyMessageSegments(messages);
124
+ expect(segments).toHaveLength(1);
125
+
126
+ // Segment includes all messages with final being attempt_completion
127
+ expect(segments[0].userIndex).toBe(0);
128
+ expect(segments[0].finalIndex).toBe(2); // tool_result is the final
129
+ });
130
+
131
+ it('should handle incomplete segment (no final answer)', () => {
132
+ const messages = [
133
+ { role: 'user', content: 'Query' },
134
+ { role: 'assistant', content: '<thinking>In progress...</thinking>' }
135
+ ];
136
+
137
+ const segments = identifyMessageSegments(messages);
138
+ expect(segments).toHaveLength(1);
139
+ expect(segments[0].finalIndex).toBe(null);
140
+ });
141
+
142
+ it('should skip system messages', () => {
143
+ const messages = [
144
+ { role: 'system', content: 'System message 1' },
145
+ { role: 'user', content: 'Query' },
146
+ { role: 'system', content: 'System message 2' },
147
+ { role: 'assistant', content: '<search>test</search>' }
148
+ ];
149
+
150
+ const segments = identifyMessageSegments(messages);
151
+ expect(segments).toHaveLength(1);
152
+ expect(segments[0].userIndex).toBe(1); // First user message
153
+ });
154
+ });
155
+
156
+ describe('compactMessages', () => {
157
+ it('should remove intermediate monologues from old segments', () => {
158
+ const messages = [
159
+ { role: 'system', content: 'System' },
160
+ // Segment 1 (old - should be compacted)
161
+ { role: 'user', content: 'First query' },
162
+ { role: 'assistant', content: '<thinking>Thought 1</thinking>' },
163
+ { role: 'assistant', content: '<search>test</search>' },
164
+ { role: 'user', content: '<tool_result>Result 1</tool_result>' },
165
+ // Segment 2 (old - should be compacted)
166
+ { role: 'user', content: 'Second query' },
167
+ { role: 'assistant', content: '<thinking>Thought 2</thinking>' },
168
+ { role: 'assistant', content: '<extract>file.js</extract>' },
169
+ { role: 'user', content: '<tool_result>Result 2</tool_result>' },
170
+ // Segment 3 (active - should be preserved)
171
+ { role: 'user', content: 'Third query' },
172
+ { role: 'assistant', content: '<thinking>Active thought</thinking>' }
173
+ ];
174
+
175
+ const compacted = compactMessages(messages, {
176
+ keepLastSegment: true,
177
+ minSegmentsToKeep: 1
178
+ });
179
+
180
+ // Should be fewer messages than original
181
+ expect(compacted.length).toBeLessThan(messages.length);
182
+
183
+ // Check system message preserved
184
+ expect(compacted[0].role).toBe('system');
185
+
186
+ // Check segment 1 and 2 compacted (only user and final)
187
+ const hasFirstQuery = compacted.some(m => m.content === 'First query');
188
+ const hasResult1 = compacted.some(m => m.content === '<tool_result>Result 1</tool_result>');
189
+ const hasThought1 = compacted.some(m => m.content && m.content.includes('Thought 1'));
190
+
191
+ const hasSecondQuery = compacted.some(m => m.content === 'Second query');
192
+ const hasResult2 = compacted.some(m => m.content === '<tool_result>Result 2</tool_result>');
193
+ const hasThought2 = compacted.some(m => m.content && m.content.includes('Thought 2'));
194
+
195
+ expect(hasFirstQuery).toBe(true);
196
+ expect(hasResult1).toBe(true);
197
+ expect(hasThought1).toBe(false); // Thought 1 should be removed
198
+
199
+ expect(hasSecondQuery).toBe(true);
200
+ expect(hasResult2).toBe(true);
201
+ expect(hasThought2).toBe(false); // Thought 2 should be removed
202
+
203
+ // Check segment 3 is fully preserved (active)
204
+ const hasActiveThought = compacted.some(m => m.content && m.content.includes('Active thought'));
205
+ expect(hasActiveThought).toBe(true);
206
+ });
207
+
208
+ it('should keep all system messages', () => {
209
+ const messages = [
210
+ { role: 'system', content: 'System 1' },
211
+ { role: 'user', content: 'Query' },
212
+ { role: 'system', content: 'System 2' },
213
+ { role: 'assistant', content: '<search>test</search>' },
214
+ { role: 'user', content: '<tool_result>Result</tool_result>' }
215
+ ];
216
+
217
+ const compacted = compactMessages(messages);
218
+
219
+ const systemMessages = compacted.filter(m => m.role === 'system');
220
+ expect(systemMessages).toHaveLength(2);
221
+ });
222
+
223
+ it('should handle empty message array', () => {
224
+ const compacted = compactMessages([]);
225
+ expect(compacted).toEqual([]);
226
+ });
227
+
228
+ it('should preserve segments when minSegmentsToKeep is high', () => {
229
+ const messages = [
230
+ { role: 'user', content: 'Query 1' },
231
+ { role: 'assistant', content: '<search>test</search>' },
232
+ { role: 'user', content: '<tool_result>Result 1</tool_result>' },
233
+ { role: 'user', content: 'Query 2' },
234
+ { role: 'assistant', content: '<extract>file</extract>' }
235
+ ];
236
+
237
+ const compacted = compactMessages(messages, {
238
+ minSegmentsToKeep: 5
239
+ });
240
+
241
+ // All segments should be preserved
242
+ expect(compacted).toEqual(messages);
243
+ });
244
+
245
+ it('should respect keepLastSegment option', () => {
246
+ const messages = [
247
+ { role: 'user', content: 'Query 1' },
248
+ { role: 'assistant', content: '<thinking>Old thought</thinking>' },
249
+ { role: 'assistant', content: '<search>test</search>' },
250
+ { role: 'user', content: '<tool_result>Result</tool_result>' },
251
+ { role: 'user', content: 'Query 2' },
252
+ { role: 'assistant', content: '<thinking>New thought</thinking>' }
253
+ ];
254
+
255
+ // With keepLastSegment=false and minSegmentsToKeep=1
256
+ const compacted = compactMessages(messages, {
257
+ keepLastSegment: false,
258
+ minSegmentsToKeep: 1
259
+ });
260
+
261
+ // Should only preserve the second-to-last segment fully
262
+ // Segment 1 should be compacted
263
+ const hasOldThought = compacted.some(m => m.content.includes('Old thought'));
264
+ const hasNewThought = compacted.some(m => m.content.includes('New thought'));
265
+
266
+ expect(hasOldThought).toBe(false);
267
+ expect(hasNewThought).toBe(true);
268
+ });
269
+
270
+ it('should handle segments without final answers', () => {
271
+ const messages = [
272
+ { role: 'user', content: 'Query 1' },
273
+ { role: 'assistant', content: '<thinking>Thought 1</thinking>' },
274
+ { role: 'user', content: '<tool_result>Result</tool_result>' },
275
+ { role: 'user', content: 'Query 2' },
276
+ { role: 'assistant', content: '<thinking>Thought 2</thinking>' }
277
+ // No final answer for segment 2
278
+ ];
279
+
280
+ const compacted = compactMessages(messages, {
281
+ minSegmentsToKeep: 1
282
+ });
283
+
284
+ // Should preserve the last incomplete segment
285
+ expect(compacted).toContain(messages[4]);
286
+ });
287
+ });
288
+
289
+ describe('calculateCompactionStats', () => {
290
+ it('should calculate correct statistics', () => {
291
+ const original = [
292
+ { role: 'user', content: 'A'.repeat(100) },
293
+ { role: 'assistant', content: 'B'.repeat(200) },
294
+ { role: 'assistant', content: 'C'.repeat(300) },
295
+ { role: 'user', content: 'D'.repeat(400) }
296
+ ];
297
+
298
+ const compacted = [
299
+ { role: 'user', content: 'A'.repeat(100) },
300
+ { role: 'user', content: 'D'.repeat(400) }
301
+ ];
302
+
303
+ const stats = calculateCompactionStats(original, compacted);
304
+
305
+ expect(stats.originalCount).toBe(4);
306
+ expect(stats.compactedCount).toBe(2);
307
+ expect(stats.removed).toBe(2);
308
+ expect(stats.reductionPercent).toBe(50.0);
309
+
310
+ // Check token estimation
311
+ expect(stats.originalTokens).toBeGreaterThan(0);
312
+ expect(stats.compactedTokens).toBeLessThan(stats.originalTokens);
313
+ expect(stats.tokensSaved).toBe(stats.originalTokens - stats.compactedTokens);
314
+ });
315
+
316
+ it('should handle empty arrays', () => {
317
+ const stats = calculateCompactionStats([], []);
318
+
319
+ expect(stats.originalCount).toBe(0);
320
+ expect(stats.compactedCount).toBe(0);
321
+ expect(stats.removed).toBe(0);
322
+ expect(stats.reductionPercent).toBe(0);
323
+ });
324
+
325
+ it('should handle no reduction', () => {
326
+ const messages = [
327
+ { role: 'user', content: 'Test' }
328
+ ];
329
+
330
+ const stats = calculateCompactionStats(messages, messages);
331
+
332
+ expect(stats.removed).toBe(0);
333
+ expect(stats.reductionPercent).toBe(0);
334
+ expect(stats.tokensSaved).toBe(0);
335
+ });
336
+
337
+ it('should estimate tokens correctly', () => {
338
+ const messages = [
339
+ { role: 'user', content: 'This is a test message with about 10 words in it' }
340
+ ];
341
+
342
+ const stats = calculateCompactionStats(messages, []);
343
+
344
+ // Rough estimate: ~50 chars / 4 = ~12-13 tokens
345
+ expect(stats.originalTokens).toBeGreaterThan(10);
346
+ expect(stats.originalTokens).toBeLessThan(20);
347
+ });
348
+ });
349
+
350
+ describe('handleContextLimitError', () => {
351
+ it('should compact messages on context limit error', () => {
352
+ const error = new Error('context length exceeded');
353
+ const messages = [
354
+ { role: 'user', content: 'Query 1' },
355
+ { role: 'assistant', content: '<thinking>Thought 1</thinking>' },
356
+ { role: 'assistant', content: '<search>test</search>' },
357
+ { role: 'user', content: '<tool_result>Result 1</tool_result>' },
358
+ { role: 'user', content: 'Query 2' },
359
+ { role: 'assistant', content: '<thinking>Thought 2</thinking>' },
360
+ { role: 'assistant', content: '<extract>file</extract>' }
361
+ ];
362
+
363
+ const result = handleContextLimitError(error, messages);
364
+
365
+ expect(result).not.toBe(null);
366
+ expect(result.compacted).toBe(true);
367
+ expect(result.messages.length).toBeLessThanOrEqual(messages.length);
368
+ expect(result.stats).toBeDefined();
369
+ });
370
+
371
+ it('should return null for non-context errors', () => {
372
+ const error = new Error('Network timeout');
373
+ const messages = [
374
+ { role: 'user', content: 'Test' }
375
+ ];
376
+
377
+ const result = handleContextLimitError(error, messages);
378
+
379
+ expect(result).toBe(null);
380
+ });
381
+
382
+ it('should pass options to compactMessages', () => {
383
+ const error = new Error('tokens exceed maximum');
384
+ const messages = [
385
+ { role: 'user', content: 'Query 1' },
386
+ { role: 'assistant', content: '<search>test</search>' },
387
+ { role: 'user', content: '<tool_result>Result</tool_result>' },
388
+ { role: 'user', content: 'Query 2' },
389
+ { role: 'assistant', content: '<extract>file</extract>' }
390
+ ];
391
+
392
+ const result = handleContextLimitError(error, messages, {
393
+ keepLastSegment: true,
394
+ minSegmentsToKeep: 3
395
+ });
396
+
397
+ expect(result).not.toBe(null);
398
+ expect(result.messages).toBeDefined();
399
+ });
400
+
401
+ it('should handle string error messages', () => {
402
+ const errorString = 'Input token count exceeds limit';
403
+ const messages = [
404
+ { role: 'user', content: 'Test' },
405
+ { role: 'assistant', content: 'Response' }
406
+ ];
407
+
408
+ const result = handleContextLimitError(errorString, messages);
409
+
410
+ expect(result).not.toBe(null);
411
+ expect(result.compacted).toBe(true);
412
+ });
413
+ });
414
+
415
+ describe('Real-world scenario', () => {
416
+ it('should handle complex multi-turn conversation', () => {
417
+ const messages = [
418
+ { role: 'system', content: 'You are a helpful assistant' },
419
+
420
+ // Turn 1 - Complete
421
+ { role: 'user', content: 'Search for all function definitions' },
422
+ { role: 'assistant', content: '<thinking>I need to search</thinking>' },
423
+ { role: 'assistant', content: '<search>function</search>' },
424
+ { role: 'user', content: '<tool_result>Found 50 functions</tool_result>' },
425
+
426
+ // Turn 2 - Complete
427
+ { role: 'user', content: 'Extract the first function' },
428
+ { role: 'assistant', content: '<thinking>Let me extract</thinking>' },
429
+ { role: 'assistant', content: '<extract>file.js:10</extract>' },
430
+ { role: 'user', content: '<tool_result>function code here</tool_result>' },
431
+
432
+ // Turn 3 - Complete
433
+ { role: 'user', content: 'Modify it to add error handling' },
434
+ { role: 'assistant', content: '<thinking>I will implement</thinking>' },
435
+ { role: 'assistant', content: '<implement>...</implement>' },
436
+ { role: 'user', content: '<tool_result>Success</tool_result>' },
437
+
438
+ // Turn 4 - Active
439
+ { role: 'user', content: 'Now test it' },
440
+ { role: 'assistant', content: '<thinking>Running tests</thinking>' },
441
+ { role: 'assistant', content: '<bash>npm test</bash>' }
442
+ ];
443
+
444
+ const compacted = compactMessages(messages, {
445
+ keepLastSegment: true,
446
+ minSegmentsToKeep: 1
447
+ });
448
+
449
+ // Should keep system + Turn 1 (user+final) + Turn 2 (user+final) + Turn 3 (user+final) + Turn 4 (all)
450
+ expect(compacted.length).toBeLessThan(messages.length);
451
+
452
+ // System message should be preserved
453
+ expect(compacted[0].role).toBe('system');
454
+
455
+ // All user messages should be preserved
456
+ const userMessages = compacted.filter(m => m.role === 'user' && !m.content.includes('tool_result'));
457
+ expect(userMessages.length).toBe(4);
458
+
459
+ // Turns 1-3 should have monologues removed
460
+ const hasThinking1 = compacted.some(m => m.content && m.content.includes('I need to search'));
461
+ const hasThinking2 = compacted.some(m => m.content && m.content.includes('Let me extract'));
462
+ const hasThinking3 = compacted.some(m => m.content && m.content.includes('I will implement'));
463
+
464
+ expect(hasThinking1).toBe(false);
465
+ expect(hasThinking2).toBe(false);
466
+ expect(hasThinking3).toBe(false);
467
+
468
+ // Active segment (Turn 4) should be fully preserved
469
+ const hasThinking4 = compacted.some(m => m.content && m.content.includes('Running tests'));
470
+ const hasBash = compacted.some(m => m.content && m.content.includes('bash'));
471
+
472
+ expect(hasThinking4).toBe(true);
473
+ expect(hasBash).toBe(true);
474
+ });
475
+
476
+ it('should provide meaningful statistics', () => {
477
+ const messages = Array.from({ length: 50 }, (_, i) => ({
478
+ role: i % 2 === 0 ? 'user' : 'assistant',
479
+ content: `Message ${i} with some content that takes up space`
480
+ }));
481
+
482
+ const compacted = compactMessages(messages, {
483
+ keepLastSegment: true,
484
+ minSegmentsToKeep: 5
485
+ });
486
+
487
+ const stats = calculateCompactionStats(messages, compacted);
488
+
489
+ expect(stats.originalCount).toBe(50);
490
+ expect(stats.compactedCount).toBeLessThan(50);
491
+ expect(stats.reductionPercent).toBeGreaterThan(0);
492
+ expect(stats.tokensSaved).toBeGreaterThan(0);
493
+
494
+ // Verify it's actually reducing
495
+ expect(stats.compactedCount).toBeLessThan(stats.originalCount);
496
+ });
497
+ });
498
+ });