@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,162 @@
1
+ /**
2
+ * Integration tests for binary extractor
3
+ * These tests verify the extractor works with real archives
4
+ */
5
+
6
+ import { jest } from '@jest/globals';
7
+ import fs from 'fs-extra';
8
+ import path from 'path';
9
+ import os from 'os';
10
+
11
+ describe('Extractor Integration Tests', () => {
12
+ describe('Platform Detection Logic', () => {
13
+ test('should map Node.js platform to correct binary platform string', () => {
14
+ const platform = os.platform();
15
+ const arch = os.arch();
16
+
17
+ let expectedPlatform;
18
+ let expectedExtension;
19
+
20
+ if (platform === 'linux') {
21
+ expectedExtension = 'tar.gz';
22
+ if (arch === 'x64') {
23
+ expectedPlatform = 'x86_64-unknown-linux-musl';
24
+ } else if (arch === 'arm64') {
25
+ expectedPlatform = 'aarch64-unknown-linux-musl';
26
+ }
27
+ } else if (platform === 'darwin') {
28
+ expectedExtension = 'tar.gz';
29
+ if (arch === 'x64') {
30
+ expectedPlatform = 'x86_64-apple-darwin';
31
+ } else if (arch === 'arm64') {
32
+ expectedPlatform = 'aarch64-apple-darwin';
33
+ }
34
+ } else if (platform === 'win32') {
35
+ expectedExtension = 'zip';
36
+ if (arch === 'x64') {
37
+ expectedPlatform = 'x86_64-pc-windows-msvc';
38
+ }
39
+ }
40
+
41
+ // Verify we got a platform (not running on unsupported platform)
42
+ if (expectedPlatform) {
43
+ expect(expectedPlatform).toBeDefined();
44
+ expect(expectedExtension).toBeDefined();
45
+ }
46
+ });
47
+ });
48
+
49
+ describe('Path Traversal Security', () => {
50
+ test('should detect path traversal with ../ sequences', () => {
51
+ const testCases = [
52
+ { path: '../../../etc/passwd', expected: 'unsafe' },
53
+ { path: '../../secrets.txt', expected: 'unsafe' },
54
+ { path: 'subdir/../../outside.txt', expected: 'safe or unsafe depending on resolution' },
55
+ { path: 'normal/file.txt', expected: 'safe' },
56
+ { path: '/absolute/path', expected: 'unsafe' }
57
+ ];
58
+
59
+ testCases.forEach(({ path: testPath, expected }) => {
60
+ // This demonstrates the security check logic
61
+ const containsTraversal = testPath.includes('..');
62
+ const isAbsolute = path.isAbsolute(testPath);
63
+
64
+ if (expected === 'unsafe') {
65
+ expect(containsTraversal || isAbsolute).toBe(true);
66
+ }
67
+ });
68
+ });
69
+
70
+ test('should validate relative path correctly', () => {
71
+ const baseDir = '/safe/extraction/dir';
72
+ const safePath = path.join(baseDir, 'subdir', 'file.txt');
73
+ const unsafePath = path.join(baseDir, '..', '..', 'etc', 'passwd');
74
+
75
+ const safeRelative = path.relative(baseDir, safePath);
76
+ const unsafeRelative = path.relative(baseDir, unsafePath);
77
+
78
+ // Safe path should not start with ..
79
+ expect(safeRelative.startsWith('..')).toBe(false);
80
+
81
+ // Unsafe path should start with ..
82
+ expect(unsafeRelative.startsWith('..')).toBe(true);
83
+ });
84
+ });
85
+
86
+ describe('Archive Naming Convention', () => {
87
+ test('should construct correct archive names for all platforms', () => {
88
+ const version = '1.0.0';
89
+
90
+ const platforms = [
91
+ { os: 'linux', arch: 'x64', name: 'x86_64-unknown-linux-musl', ext: 'tar.gz' },
92
+ { os: 'linux', arch: 'arm64', name: 'aarch64-unknown-linux-musl', ext: 'tar.gz' },
93
+ { os: 'darwin', arch: 'x64', name: 'x86_64-apple-darwin', ext: 'tar.gz' },
94
+ { os: 'darwin', arch: 'arm64', name: 'aarch64-apple-darwin', ext: 'tar.gz' },
95
+ { os: 'win32', arch: 'x64', name: 'x86_64-pc-windows-msvc', ext: 'zip' }
96
+ ];
97
+
98
+ platforms.forEach(({ name, ext }) => {
99
+ const expectedName = `probe-v${version}-${name}.${ext}`;
100
+ expect(expectedName).toMatch(/^probe-v\d+\.\d+\.\d+(-\w+)?-.+\.(tar\.gz|zip)$/);
101
+ });
102
+ });
103
+ });
104
+
105
+ describe('Binary Name Detection', () => {
106
+ test('should use correct binary name for each platform', () => {
107
+ const isWindows = os.platform() === 'win32';
108
+ const expectedName = isWindows ? 'probe.exe' : 'probe-binary';
109
+
110
+ expect(expectedName).toBeDefined();
111
+ if (isWindows) {
112
+ expect(expectedName).toBe('probe.exe');
113
+ } else {
114
+ expect(expectedName).toBe('probe-binary');
115
+ }
116
+ });
117
+ });
118
+ });
119
+
120
+ describe('Security Validations', () => {
121
+ test('isPathSafe logic - prevents directory traversal', () => {
122
+ const baseDir = path.normalize('/safe/dir');
123
+
124
+ const testPaths = [
125
+ { input: path.join(baseDir, 'file.txt'), safe: true },
126
+ { input: path.join(baseDir, 'sub', 'file.txt'), safe: true },
127
+ { input: path.join(baseDir, '..', 'outside.txt'), safe: false },
128
+ { input: '/etc/passwd', safe: false },
129
+ { input: path.join(baseDir, '..', '..', 'etc', 'passwd'), safe: false }
130
+ ];
131
+
132
+ testPaths.forEach(({ input, safe }) => {
133
+ const normalizedPath = path.normalize(input);
134
+ const relativePath = path.relative(baseDir, normalizedPath);
135
+
136
+ const isActuallySafe = !relativePath.startsWith('..') && !path.isAbsolute(relativePath);
137
+
138
+ expect(isActuallySafe).toBe(safe);
139
+ });
140
+ });
141
+
142
+ test('validates paths before extraction', () => {
143
+ // This test documents the security approach
144
+ const extractDir = '/tmp/extract';
145
+ const entries = [
146
+ { name: 'probe', safe: true },
147
+ { name: 'README.md', safe: true },
148
+ { name: '../../../etc/passwd', safe: false },
149
+ { name: '../../secrets.txt', safe: false }
150
+ ];
151
+
152
+ entries.forEach(({ name, safe }) => {
153
+ const fullPath = path.join(extractDir, name);
154
+ const normalized = path.normalize(fullPath);
155
+ const relative = path.relative(extractDir, normalized);
156
+
157
+ const isPathSafe = !relative.startsWith('..') && !path.isAbsolute(relative);
158
+
159
+ expect(isPathSafe).toBe(safe);
160
+ });
161
+ });
162
+ });
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Tests for binary extractor module
3
+ */
4
+
5
+ import { jest } from '@jest/globals';
6
+ import fs from 'fs-extra';
7
+ import path from 'path';
8
+ import os from 'os';
9
+ import tar from 'tar';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ // Import AdmZip dynamically when needed since it may not be installed during initial test run
13
+ let AdmZip;
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = path.dirname(__filename);
17
+
18
+ // Import the functions we need to test
19
+ // Note: We'll need to expose internal functions for testing or test through the public API
20
+ import { extractBundledBinary } from '../src/extractor.js';
21
+
22
+ describe('extractBundledBinary', () => {
23
+ let tempDir;
24
+ let binariesDir;
25
+ let binDir;
26
+
27
+ beforeEach(async () => {
28
+ // Create temporary directories for testing
29
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'extractor-test-'));
30
+ binariesDir = path.join(tempDir, 'bin', 'binaries');
31
+ binDir = path.join(tempDir, 'bin');
32
+ await fs.ensureDir(binariesDir);
33
+ await fs.ensureDir(binDir);
34
+ });
35
+
36
+ afterEach(async () => {
37
+ // Clean up temporary directories
38
+ await fs.remove(tempDir);
39
+ });
40
+
41
+ describe('Platform Detection', () => {
42
+ test('should look for correct platform-specific archive', async () => {
43
+ const platform = os.platform();
44
+ const arch = os.arch();
45
+ const version = '1.0.0';
46
+
47
+ // Determine expected artifact naming from current platform
48
+ let platformString;
49
+ let ext;
50
+ if (platform === 'linux' && arch === 'x64') {
51
+ platformString = 'x86_64-unknown-linux-musl';
52
+ ext = 'tar.gz';
53
+ } else if (platform === 'linux' && arch === 'arm64') {
54
+ platformString = 'aarch64-unknown-linux-musl';
55
+ ext = 'tar.gz';
56
+ } else if (platform === 'darwin' && arch === 'x64') {
57
+ platformString = 'x86_64-apple-darwin';
58
+ ext = 'tar.gz';
59
+ } else if (platform === 'darwin' && arch === 'arm64') {
60
+ platformString = 'aarch64-apple-darwin';
61
+ ext = 'tar.gz';
62
+ } else if (platform === 'win32' && arch === 'x64') {
63
+ platformString = 'x86_64-pc-windows-msvc';
64
+ ext = 'zip';
65
+ } else {
66
+ // Skip on unsupported combos for this repository
67
+ return;
68
+ }
69
+
70
+ const binariesDirOnDisk = path.resolve(__dirname, '..', 'bin', 'binaries');
71
+ const expectedArchive = `probe-v${version}-${platformString}.${ext}`;
72
+ const expectedPath = path.join(binariesDirOnDisk, expectedArchive);
73
+
74
+ // Spy and force negative existence to avoid relying on real files
75
+ const pathExistsSpy = jest.spyOn(fs, 'pathExists').mockResolvedValue(false);
76
+
77
+ await expect(extractBundledBinary(version)).rejects.toThrow('Bundled binary not found');
78
+
79
+ expect(pathExistsSpy).toHaveBeenCalledWith(expectedPath);
80
+ pathExistsSpy.mockRestore();
81
+ });
82
+
83
+ test('should throw error for unsupported platform', async () => {
84
+ // Mock os.platform to return unsupported value
85
+ const originalPlatform = os.platform;
86
+ jest.spyOn(os, 'platform').mockReturnValue('unsupported');
87
+
88
+ await expect(extractBundledBinary('1.0.0')).rejects.toThrow('Unsupported operating system');
89
+
90
+ os.platform = originalPlatform;
91
+ });
92
+ });
93
+
94
+ describe('Archive Extraction - tar.gz', () => {
95
+ test('should extract tar.gz archive successfully', async () => {
96
+ const version = '1.0.0';
97
+ const platform = os.platform();
98
+ const arch = os.arch();
99
+
100
+ // Determine expected platform string
101
+ let platformString;
102
+ if (platform === 'darwin' && arch === 'arm64') {
103
+ platformString = 'aarch64-apple-darwin';
104
+ } else if (platform === 'darwin' && arch === 'x64') {
105
+ platformString = 'x86_64-apple-darwin';
106
+ } else if (platform === 'linux' && arch === 'x64') {
107
+ platformString = 'x86_64-unknown-linux-musl';
108
+ } else if (platform === 'linux' && arch === 'arm64') {
109
+ platformString = 'aarch64-unknown-linux-musl';
110
+ } else {
111
+ // Skip test on unsupported platforms
112
+ return;
113
+ }
114
+
115
+ // Create a mock binary file
116
+ const mockBinaryContent = 'mock binary content';
117
+ const archiveName = `probe-v${version}-${platformString}.tar.gz`;
118
+ const archivePath = path.join(binariesDir, archiveName);
119
+
120
+ // Create a temporary directory with the binary
121
+ const tempArchiveDir = path.join(tempDir, 'archive-content');
122
+ const innerDir = path.join(tempArchiveDir, `probe-v${version}-${platformString}`);
123
+ await fs.ensureDir(innerDir);
124
+ await fs.writeFile(path.join(innerDir, 'probe'), mockBinaryContent);
125
+
126
+ // Create tar.gz archive
127
+ await tar.create({
128
+ gzip: true,
129
+ file: archivePath,
130
+ cwd: tempArchiveDir
131
+ }, [`probe-v${version}-${platformString}`]);
132
+
133
+ // Mock the __dirname to point to our temp directory
134
+ // This is tricky - we need to actually copy the extractor or mock it differently
135
+ // For now, we'll test that the archive exists
136
+ expect(await fs.pathExists(archivePath)).toBe(true);
137
+ });
138
+
139
+ test('should reject archive with path traversal attempt', async () => {
140
+ // Create a malicious tar.gz with ../ in paths
141
+ const version = '1.0.0';
142
+ const platform = os.platform();
143
+ const arch = os.arch();
144
+
145
+ let platformString;
146
+ if (platform === 'darwin' && arch === 'arm64') {
147
+ platformString = 'aarch64-apple-darwin';
148
+ } else {
149
+ // Skip on other platforms for brevity
150
+ return;
151
+ }
152
+
153
+ const archiveName = `probe-v${version}-${platformString}.tar.gz`;
154
+ const archivePath = path.join(binariesDir, archiveName);
155
+
156
+ // Create malicious archive
157
+ const tempArchiveDir = path.join(tempDir, 'malicious-archive');
158
+ await fs.ensureDir(tempArchiveDir);
159
+
160
+ // Try to create a file with path traversal
161
+ const maliciousDir = path.join(tempArchiveDir, '..');
162
+ await fs.ensureDir(path.join(tempArchiveDir, 'normal'));
163
+ await fs.writeFile(path.join(tempArchiveDir, 'normal', 'probe'), 'safe');
164
+
165
+ // This test verifies the security mechanism works
166
+ // Actual implementation would need the full extractor setup
167
+ });
168
+ });
169
+
170
+ describe('Archive Extraction - ZIP', () => {
171
+ test('should extract zip archive successfully on Windows', async () => {
172
+ if (os.platform() !== 'win32') {
173
+ // Skip on non-Windows
174
+ return;
175
+ }
176
+
177
+ // Dynamically import AdmZip
178
+ if (!AdmZip) {
179
+ AdmZip = (await import('adm-zip')).default;
180
+ }
181
+
182
+ const version = '1.0.0';
183
+ const platformString = 'x86_64-pc-windows-msvc';
184
+ const archiveName = `probe-v${version}-${platformString}.zip`;
185
+ const archivePath = path.join(binariesDir, archiveName);
186
+
187
+ // Create a mock binary
188
+ const zip = new AdmZip();
189
+ const mockBinaryContent = Buffer.from('mock binary content');
190
+ zip.addFile(`probe-v${version}-${platformString}/probe.exe`, mockBinaryContent);
191
+ zip.writeZip(archivePath);
192
+
193
+ expect(await fs.pathExists(archivePath)).toBe(true);
194
+ });
195
+
196
+ test('should reject zip with path traversal attempt', async () => {
197
+ const version = '1.0.0';
198
+
199
+ // Dynamically import AdmZip
200
+ if (!AdmZip) {
201
+ AdmZip = (await import('adm-zip')).default;
202
+ }
203
+
204
+ // Create a malicious ZIP
205
+ const zip = new AdmZip();
206
+
207
+ // Try to add a file with path traversal
208
+ zip.addFile('../../../evil.exe', Buffer.from('malicious'));
209
+
210
+ const archivePath = path.join(tempDir, 'malicious.zip');
211
+ zip.writeZip(archivePath);
212
+
213
+ // Verify the security mechanism would catch this
214
+ // Full test would require mocking the extractor
215
+ expect(await fs.pathExists(archivePath)).toBe(true);
216
+ });
217
+ });
218
+
219
+ describe('Error Handling', () => {
220
+ test('should throw error when binary archive not found', async () => {
221
+ const version = '1.0.0';
222
+
223
+ // Don't create any archive
224
+ await expect(extractBundledBinary(version)).rejects.toThrow('Bundled binary not found');
225
+ });
226
+
227
+ test('should throw error when binary not found in archive', async () => {
228
+ const version = '1.0.0';
229
+ const platform = os.platform();
230
+ const arch = os.arch();
231
+
232
+ let platformString;
233
+ if (platform === 'darwin' && arch === 'arm64') {
234
+ platformString = 'aarch64-apple-darwin';
235
+ } else if (platform === 'linux' && arch === 'x64') {
236
+ platformString = 'x86_64-unknown-linux-musl';
237
+ } else {
238
+ return; // Skip on other platforms
239
+ }
240
+
241
+ const archiveName = `probe-v${version}-${platformString}.tar.gz`;
242
+ const archivePath = path.join(binariesDir, archiveName);
243
+
244
+ // Create archive without the binary
245
+ const tempArchiveDir = path.join(tempDir, 'empty-archive');
246
+ const innerDir = path.join(tempArchiveDir, `probe-v${version}-${platformString}`);
247
+ await fs.ensureDir(innerDir);
248
+ await fs.writeFile(path.join(innerDir, 'README.md'), 'No binary here');
249
+
250
+ await tar.create({
251
+ gzip: true,
252
+ file: archivePath,
253
+ cwd: tempArchiveDir
254
+ }, [`probe-v${version}-${platformString}`]);
255
+
256
+ // This would throw if we could properly inject the binariesDir
257
+ // For now, we verify the archive was created
258
+ expect(await fs.pathExists(archivePath)).toBe(true);
259
+ });
260
+
261
+ test('should provide helpful error message for unsupported platform', async () => {
262
+ const originalPlatform = os.platform;
263
+ const originalArch = os.arch;
264
+
265
+ jest.spyOn(os, 'platform').mockReturnValue('freebsd');
266
+ jest.spyOn(os, 'arch').mockReturnValue('x64');
267
+
268
+ await expect(extractBundledBinary('1.0.0')).rejects.toThrow(/Unsupported operating system/);
269
+
270
+ os.platform = originalPlatform;
271
+ os.arch = originalArch;
272
+ });
273
+ });
274
+ });
275
+
276
+ describe('Path Safety (Security)', () => {
277
+ // These tests verify the path traversal protection
278
+ // Since isPathSafe is not exported, we test it through extraction
279
+
280
+ test('should reject paths with .. segments', () => {
281
+ const baseDir = '/safe/dir';
282
+ const maliciousPath = '/safe/dir/../../../etc/passwd';
283
+
284
+ const normalizedBase = path.normalize(baseDir);
285
+ const normalizedPath = path.normalize(maliciousPath);
286
+ const relativePath = path.relative(normalizedBase, normalizedPath);
287
+
288
+ // This should start with '..' which indicates path traversal
289
+ expect(relativePath.startsWith('..')).toBe(true);
290
+ });
291
+
292
+ test('should accept safe paths within base directory', () => {
293
+ const baseDir = '/safe/dir';
294
+ const safePath = '/safe/dir/subdir/file.txt';
295
+
296
+ const normalizedBase = path.normalize(baseDir);
297
+ const normalizedPath = path.normalize(safePath);
298
+ const relativePath = path.relative(normalizedBase, normalizedPath);
299
+
300
+ // This should NOT start with '..'
301
+ expect(relativePath.startsWith('..')).toBe(false);
302
+ expect(path.isAbsolute(relativePath)).toBe(false);
303
+ });
304
+
305
+ test('should reject absolute paths', () => {
306
+ const baseDir = '/safe/dir';
307
+ const absolutePath = '/etc/passwd';
308
+
309
+ const normalizedBase = path.normalize(baseDir);
310
+ const normalizedPath = path.normalize(absolutePath);
311
+ const relativePath = path.relative(normalizedBase, normalizedPath);
312
+
313
+ // Absolute path or escapes base dir
314
+ const isSafe = !relativePath.startsWith('..') && !path.isAbsolute(relativePath);
315
+ expect(isSafe).toBe(false);
316
+ });
317
+ });