@gguf/coder 0.2.9 → 0.3.1

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 (439) hide show
  1. package/.editorconfig +16 -0
  2. package/.env.example +63 -0
  3. package/.gitattributes +1 -0
  4. package/.semgrepignore +19 -0
  5. package/coder-dummy-file.ts +52 -0
  6. package/coder.config.example.json +59 -0
  7. package/coder.config.json +13 -0
  8. package/color_picker.html +36 -0
  9. package/dist/tools/execute-bash.js +3 -3
  10. package/dist/tools/execute-bash.js.map +1 -1
  11. package/dist/tools/fetch-url.js +3 -3
  12. package/dist/tools/fetch-url.js.map +1 -1
  13. package/dist/tools/find-files.d.ts.map +1 -1
  14. package/dist/tools/find-files.js +1 -1
  15. package/dist/tools/find-files.js.map +1 -1
  16. package/dist/tools/lsp-get-diagnostics.js +1 -1
  17. package/dist/tools/lsp-get-diagnostics.js.map +1 -1
  18. package/dist/tools/read-file.d.ts.map +1 -1
  19. package/dist/tools/read-file.js +6 -6
  20. package/dist/tools/read-file.js.map +1 -1
  21. package/dist/tools/search-file-contents.d.ts.map +1 -1
  22. package/dist/tools/search-file-contents.js +1 -1
  23. package/dist/tools/search-file-contents.js.map +1 -1
  24. package/dist/tools/string-replace.js +11 -11
  25. package/dist/tools/string-replace.js.map +1 -1
  26. package/dist/tools/web-search.d.ts.map +1 -1
  27. package/dist/tools/web-search.js +3 -3
  28. package/dist/tools/web-search.js.map +1 -1
  29. package/dist/tools/write-file.js +4 -4
  30. package/dist/tools/write-file.js.map +1 -1
  31. package/dist/utils/tool-result-display.d.ts.map +1 -1
  32. package/dist/utils/tool-result-display.js +3 -3
  33. package/dist/utils/tool-result-display.js.map +1 -1
  34. package/package.json +2 -14
  35. package/scripts/extract-changelog.js +73 -0
  36. package/scripts/fetch-models.js +143 -0
  37. package/scripts/test.sh +40 -0
  38. package/scripts/update-homebrew-formula.sh +125 -0
  39. package/scripts/update-nix-version.sh +157 -0
  40. package/source/ai-sdk-client/AISDKClient.spec.ts +117 -0
  41. package/source/ai-sdk-client/AISDKClient.ts +155 -0
  42. package/source/ai-sdk-client/chat/chat-handler.spec.ts +121 -0
  43. package/source/ai-sdk-client/chat/chat-handler.ts +276 -0
  44. package/source/ai-sdk-client/chat/streaming-handler.spec.ts +173 -0
  45. package/source/ai-sdk-client/chat/streaming-handler.ts +110 -0
  46. package/source/ai-sdk-client/chat/tool-processor.spec.ts +92 -0
  47. package/source/ai-sdk-client/chat/tool-processor.ts +70 -0
  48. package/source/ai-sdk-client/converters/message-converter.spec.ts +220 -0
  49. package/source/ai-sdk-client/converters/message-converter.ts +113 -0
  50. package/source/ai-sdk-client/converters/tool-converter.spec.ts +90 -0
  51. package/source/ai-sdk-client/converters/tool-converter.ts +46 -0
  52. package/source/ai-sdk-client/error-handling/error-extractor.spec.ts +55 -0
  53. package/source/ai-sdk-client/error-handling/error-extractor.ts +15 -0
  54. package/source/ai-sdk-client/error-handling/error-parser.spec.ts +169 -0
  55. package/source/ai-sdk-client/error-handling/error-parser.ts +161 -0
  56. package/source/ai-sdk-client/index.ts +7 -0
  57. package/source/ai-sdk-client/providers/provider-factory.spec.ts +71 -0
  58. package/source/ai-sdk-client/providers/provider-factory.ts +41 -0
  59. package/source/ai-sdk-client/types.ts +9 -0
  60. package/source/ai-sdk-client-empty-message.spec.ts +141 -0
  61. package/source/ai-sdk-client-error-handling.spec.ts +186 -0
  62. package/source/ai-sdk-client-maxretries.spec.ts +114 -0
  63. package/source/ai-sdk-client-preparestep.spec.ts +279 -0
  64. package/source/app/App.spec.tsx +32 -0
  65. package/source/app/App.tsx +480 -0
  66. package/source/app/components/AppContainer.spec.tsx +96 -0
  67. package/source/app/components/AppContainer.tsx +56 -0
  68. package/source/app/components/ChatInterface.spec.tsx +163 -0
  69. package/source/app/components/ChatInterface.tsx +144 -0
  70. package/source/app/components/ModalSelectors.spec.tsx +141 -0
  71. package/source/app/components/ModalSelectors.tsx +135 -0
  72. package/source/app/helpers.spec.ts +97 -0
  73. package/source/app/helpers.ts +63 -0
  74. package/source/app/index.ts +4 -0
  75. package/source/app/types.ts +39 -0
  76. package/source/app/utils/appUtils.ts +294 -0
  77. package/source/app/utils/conversationState.ts +310 -0
  78. package/source/app.spec.tsx +244 -0
  79. package/source/cli.spec.ts +73 -0
  80. package/source/cli.tsx +51 -0
  81. package/source/client-factory.spec.ts +48 -0
  82. package/source/client-factory.ts +178 -0
  83. package/source/command-parser.spec.ts +127 -0
  84. package/source/command-parser.ts +36 -0
  85. package/source/commands/checkpoint.spec.tsx +277 -0
  86. package/source/commands/checkpoint.tsx +366 -0
  87. package/source/commands/clear.tsx +22 -0
  88. package/source/commands/custom-commands.tsx +121 -0
  89. package/source/commands/exit.ts +21 -0
  90. package/source/commands/export.spec.tsx +131 -0
  91. package/source/commands/export.tsx +79 -0
  92. package/source/commands/help.tsx +120 -0
  93. package/source/commands/index.ts +17 -0
  94. package/source/commands/init.tsx +339 -0
  95. package/source/commands/lsp-command.spec.tsx +281 -0
  96. package/source/commands/lsp.tsx +120 -0
  97. package/source/commands/mcp-command.spec.tsx +313 -0
  98. package/source/commands/mcp.tsx +162 -0
  99. package/source/commands/model-database.spec.tsx +758 -0
  100. package/source/commands/model-database.tsx +418 -0
  101. package/source/commands/model.ts +12 -0
  102. package/source/commands/provider.ts +12 -0
  103. package/source/commands/setup-config.tsx +16 -0
  104. package/source/commands/simple-commands.spec.tsx +175 -0
  105. package/source/commands/status.ts +12 -0
  106. package/source/commands/theme.ts +12 -0
  107. package/source/commands/update.spec.tsx +261 -0
  108. package/source/commands/update.tsx +201 -0
  109. package/source/commands/usage.spec.tsx +495 -0
  110. package/source/commands/usage.tsx +100 -0
  111. package/source/commands.spec.ts +436 -0
  112. package/source/commands.ts +83 -0
  113. package/source/components/assistant-message.spec.tsx +796 -0
  114. package/source/components/assistant-message.tsx +34 -0
  115. package/source/components/bash-execution-indicator.tsx +21 -0
  116. package/source/components/cancelling-indicator.tsx +16 -0
  117. package/source/components/chat-queue.spec.tsx +83 -0
  118. package/source/components/chat-queue.tsx +36 -0
  119. package/source/components/checkpoint-display.spec.tsx +219 -0
  120. package/source/components/checkpoint-display.tsx +126 -0
  121. package/source/components/checkpoint-selector.spec.tsx +173 -0
  122. package/source/components/checkpoint-selector.tsx +173 -0
  123. package/source/components/development-mode-indicator.spec.tsx +268 -0
  124. package/source/components/development-mode-indicator.tsx +38 -0
  125. package/source/components/message-box.spec.tsx +427 -0
  126. package/source/components/message-box.tsx +87 -0
  127. package/source/components/model-selector.tsx +132 -0
  128. package/source/components/provider-selector.tsx +75 -0
  129. package/source/components/random-spinner.tsx +19 -0
  130. package/source/components/security-disclaimer.tsx +73 -0
  131. package/source/components/status-connection-display.spec.tsx +133 -0
  132. package/source/components/status.tsx +267 -0
  133. package/source/components/theme-selector.tsx +126 -0
  134. package/source/components/tool-confirmation.tsx +190 -0
  135. package/source/components/tool-execution-indicator.tsx +33 -0
  136. package/source/components/tool-message.tsx +85 -0
  137. package/source/components/ui/titled-box.spec.tsx +207 -0
  138. package/source/components/ui/titled-box.tsx +57 -0
  139. package/source/components/usage/progress-bar.spec.tsx +398 -0
  140. package/source/components/usage/progress-bar.tsx +30 -0
  141. package/source/components/usage/usage-display.spec.tsx +780 -0
  142. package/source/components/usage/usage-display.tsx +291 -0
  143. package/source/components/user-input.spec.tsx +327 -0
  144. package/source/components/user-input.tsx +533 -0
  145. package/source/components/user-message.spec.tsx +230 -0
  146. package/source/components/user-message.tsx +84 -0
  147. package/source/components/welcome-message.tsx +76 -0
  148. package/source/config/env-substitution.ts +65 -0
  149. package/source/config/index.spec.ts +171 -0
  150. package/source/config/index.ts +154 -0
  151. package/source/config/paths.spec.ts +241 -0
  152. package/source/config/paths.ts +55 -0
  153. package/source/config/preferences.ts +51 -0
  154. package/source/config/themes.ts +315 -0
  155. package/source/constants.ts +130 -0
  156. package/source/context/mode-context.spec.ts +79 -0
  157. package/source/context/mode-context.ts +24 -0
  158. package/source/custom-commands/executor.spec.ts +142 -0
  159. package/source/custom-commands/executor.ts +64 -0
  160. package/source/custom-commands/loader.spec.ts +314 -0
  161. package/source/custom-commands/loader.ts +153 -0
  162. package/source/custom-commands/parser.ts +196 -0
  163. package/source/hooks/chat-handler/conversation/conversation-loop.spec.ts +39 -0
  164. package/source/hooks/chat-handler/conversation/conversation-loop.tsx +511 -0
  165. package/source/hooks/chat-handler/conversation/tool-executor.spec.ts +50 -0
  166. package/source/hooks/chat-handler/conversation/tool-executor.tsx +109 -0
  167. package/source/hooks/chat-handler/index.ts +12 -0
  168. package/source/hooks/chat-handler/state/streaming-state.spec.ts +26 -0
  169. package/source/hooks/chat-handler/state/streaming-state.ts +19 -0
  170. package/source/hooks/chat-handler/types.ts +38 -0
  171. package/source/hooks/chat-handler/useChatHandler.spec.tsx +321 -0
  172. package/source/hooks/chat-handler/useChatHandler.tsx +194 -0
  173. package/source/hooks/chat-handler/utils/context-checker.spec.ts +60 -0
  174. package/source/hooks/chat-handler/utils/context-checker.tsx +73 -0
  175. package/source/hooks/chat-handler/utils/message-helpers.spec.ts +42 -0
  176. package/source/hooks/chat-handler/utils/message-helpers.tsx +36 -0
  177. package/source/hooks/chat-handler/utils/tool-filters.spec.ts +109 -0
  178. package/source/hooks/chat-handler/utils/tool-filters.ts +64 -0
  179. package/source/hooks/useAppHandlers.tsx +291 -0
  180. package/source/hooks/useAppInitialization.tsx +422 -0
  181. package/source/hooks/useAppState.tsx +311 -0
  182. package/source/hooks/useDirectoryTrust.tsx +98 -0
  183. package/source/hooks/useInputState.ts +414 -0
  184. package/source/hooks/useModeHandlers.tsx +302 -0
  185. package/source/hooks/useNonInteractiveMode.ts +140 -0
  186. package/source/hooks/useTerminalWidth.tsx +81 -0
  187. package/source/hooks/useTheme.ts +18 -0
  188. package/source/hooks/useToolHandler.tsx +349 -0
  189. package/source/hooks/useUIState.ts +61 -0
  190. package/source/init/agents-template-generator.ts +421 -0
  191. package/source/init/existing-rules-extractor.ts +319 -0
  192. package/source/init/file-scanner.spec.ts +227 -0
  193. package/source/init/file-scanner.ts +238 -0
  194. package/source/init/framework-detector.ts +382 -0
  195. package/source/init/language-detector.ts +269 -0
  196. package/source/init/project-analyzer.spec.ts +231 -0
  197. package/source/init/project-analyzer.ts +458 -0
  198. package/source/lsp/index.ts +31 -0
  199. package/source/lsp/lsp-client.spec.ts +508 -0
  200. package/source/lsp/lsp-client.ts +487 -0
  201. package/source/lsp/lsp-manager.spec.ts +477 -0
  202. package/source/lsp/lsp-manager.ts +419 -0
  203. package/source/lsp/protocol.spec.ts +502 -0
  204. package/source/lsp/protocol.ts +360 -0
  205. package/source/lsp/server-discovery.spec.ts +654 -0
  206. package/source/lsp/server-discovery.ts +515 -0
  207. package/source/markdown-parser/html-entities.spec.ts +88 -0
  208. package/source/markdown-parser/html-entities.ts +45 -0
  209. package/source/markdown-parser/index.spec.ts +281 -0
  210. package/source/markdown-parser/index.ts +126 -0
  211. package/source/markdown-parser/table-parser.spec.ts +133 -0
  212. package/source/markdown-parser/table-parser.ts +114 -0
  213. package/source/markdown-parser/utils.spec.ts +70 -0
  214. package/source/markdown-parser/utils.ts +13 -0
  215. package/source/mcp/mcp-client.spec.ts +81 -0
  216. package/source/mcp/mcp-client.ts +625 -0
  217. package/source/mcp/transport-factory.spec.ts +406 -0
  218. package/source/mcp/transport-factory.ts +312 -0
  219. package/source/message-handler.ts +67 -0
  220. package/source/model-database/database-engine.spec.ts +494 -0
  221. package/source/model-database/database-engine.ts +50 -0
  222. package/source/model-database/model-database.spec.ts +363 -0
  223. package/source/model-database/model-database.ts +91 -0
  224. package/source/model-database/model-engine.spec.ts +447 -0
  225. package/source/model-database/model-engine.ts +65 -0
  226. package/source/model-database/model-fetcher.spec.ts +583 -0
  227. package/source/model-database/model-fetcher.ts +330 -0
  228. package/source/models/index.ts +1 -0
  229. package/source/models/models-cache.spec.ts +214 -0
  230. package/source/models/models-cache.ts +78 -0
  231. package/source/models/models-dev-client.spec.ts +379 -0
  232. package/source/models/models-dev-client.ts +329 -0
  233. package/source/models/models-types.ts +68 -0
  234. package/source/prompt-history.ts +155 -0
  235. package/source/security/command-injection.spec.ts +240 -0
  236. package/source/services/checkpoint-manager.spec.ts +523 -0
  237. package/source/services/checkpoint-manager.ts +466 -0
  238. package/source/services/file-snapshot.spec.ts +569 -0
  239. package/source/services/file-snapshot.ts +220 -0
  240. package/source/test-utils/render-with-theme.tsx +48 -0
  241. package/source/tokenization/index.ts +1 -0
  242. package/source/tokenization/tokenizer-factory.spec.ts +170 -0
  243. package/source/tokenization/tokenizer-factory.ts +125 -0
  244. package/source/tokenization/tokenizers/anthropic-tokenizer.spec.ts +200 -0
  245. package/source/tokenization/tokenizers/anthropic-tokenizer.ts +43 -0
  246. package/source/tokenization/tokenizers/fallback-tokenizer.spec.ts +236 -0
  247. package/source/tokenization/tokenizers/fallback-tokenizer.ts +26 -0
  248. package/source/tokenization/tokenizers/llama-tokenizer.spec.ts +224 -0
  249. package/source/tokenization/tokenizers/llama-tokenizer.ts +41 -0
  250. package/source/tokenization/tokenizers/openai-tokenizer.spec.ts +184 -0
  251. package/source/tokenization/tokenizers/openai-tokenizer.ts +57 -0
  252. package/source/tool-calling/index.ts +5 -0
  253. package/source/tool-calling/json-parser.spec.ts +639 -0
  254. package/source/tool-calling/json-parser.ts +247 -0
  255. package/source/tool-calling/tool-parser.spec.ts +395 -0
  256. package/source/tool-calling/tool-parser.ts +120 -0
  257. package/source/tool-calling/xml-parser.spec.ts +662 -0
  258. package/source/tool-calling/xml-parser.ts +289 -0
  259. package/source/tools/execute-bash.spec.tsx +353 -0
  260. package/source/tools/execute-bash.tsx +219 -0
  261. package/source/tools/execute-function.spec.ts +130 -0
  262. package/source/tools/fetch-url.spec.tsx +342 -0
  263. package/source/tools/fetch-url.tsx +172 -0
  264. package/source/tools/find-files.spec.tsx +924 -0
  265. package/source/tools/find-files.tsx +293 -0
  266. package/source/tools/index.ts +102 -0
  267. package/source/tools/lsp-get-diagnostics.tsx +192 -0
  268. package/source/tools/needs-approval.spec.ts +282 -0
  269. package/source/tools/read-file.spec.tsx +801 -0
  270. package/source/tools/read-file.tsx +387 -0
  271. package/source/tools/search-file-contents.spec.tsx +1273 -0
  272. package/source/tools/search-file-contents.tsx +293 -0
  273. package/source/tools/string-replace.spec.tsx +730 -0
  274. package/source/tools/string-replace.tsx +548 -0
  275. package/source/tools/tool-manager.ts +210 -0
  276. package/source/tools/tool-registry.spec.ts +415 -0
  277. package/source/tools/tool-registry.ts +228 -0
  278. package/source/tools/web-search.tsx +223 -0
  279. package/source/tools/write-file.spec.tsx +559 -0
  280. package/source/tools/write-file.tsx +228 -0
  281. package/source/types/app.ts +37 -0
  282. package/source/types/checkpoint.ts +48 -0
  283. package/source/types/commands.ts +46 -0
  284. package/source/types/components.ts +27 -0
  285. package/source/types/config.ts +103 -0
  286. package/source/types/core-connection-status.spec.ts +67 -0
  287. package/source/types/core.ts +181 -0
  288. package/source/types/hooks.ts +50 -0
  289. package/source/types/index.ts +12 -0
  290. package/source/types/markdown-parser.ts +11 -0
  291. package/source/types/mcp.ts +52 -0
  292. package/source/types/system.ts +16 -0
  293. package/source/types/tokenization.ts +41 -0
  294. package/source/types/ui.ts +40 -0
  295. package/source/types/usage.ts +58 -0
  296. package/source/types/utils.ts +16 -0
  297. package/source/usage/calculator.spec.ts +385 -0
  298. package/source/usage/calculator.ts +104 -0
  299. package/source/usage/storage.spec.ts +703 -0
  300. package/source/usage/storage.ts +238 -0
  301. package/source/usage/tracker.spec.ts +456 -0
  302. package/source/usage/tracker.ts +102 -0
  303. package/source/utils/atomic-deletion.spec.ts +194 -0
  304. package/source/utils/atomic-deletion.ts +127 -0
  305. package/source/utils/bounded-map.spec.ts +300 -0
  306. package/source/utils/bounded-map.ts +193 -0
  307. package/source/utils/checkpoint-utils.spec.ts +222 -0
  308. package/source/utils/checkpoint-utils.ts +92 -0
  309. package/source/utils/error-formatter.spec.ts +169 -0
  310. package/source/utils/error-formatter.ts +194 -0
  311. package/source/utils/file-autocomplete.spec.ts +173 -0
  312. package/source/utils/file-autocomplete.ts +196 -0
  313. package/source/utils/file-cache.spec.ts +309 -0
  314. package/source/utils/file-cache.ts +195 -0
  315. package/source/utils/file-content-loader.spec.ts +180 -0
  316. package/source/utils/file-content-loader.ts +179 -0
  317. package/source/utils/file-mention-handler.spec.ts +261 -0
  318. package/source/utils/file-mention-handler.ts +84 -0
  319. package/source/utils/file-mention-parser.spec.ts +182 -0
  320. package/source/utils/file-mention-parser.ts +170 -0
  321. package/source/utils/fuzzy-matching.spec.ts +149 -0
  322. package/source/utils/fuzzy-matching.ts +146 -0
  323. package/source/utils/indentation-normalizer.spec.ts +216 -0
  324. package/source/utils/indentation-normalizer.ts +76 -0
  325. package/source/utils/installation-detector.spec.ts +178 -0
  326. package/source/utils/installation-detector.ts +153 -0
  327. package/source/utils/logging/config.spec.ts +311 -0
  328. package/source/utils/logging/config.ts +210 -0
  329. package/source/utils/logging/console-facade.spec.ts +184 -0
  330. package/source/utils/logging/console-facade.ts +384 -0
  331. package/source/utils/logging/correlation.spec.ts +679 -0
  332. package/source/utils/logging/correlation.ts +474 -0
  333. package/source/utils/logging/formatters.spec.ts +464 -0
  334. package/source/utils/logging/formatters.ts +207 -0
  335. package/source/utils/logging/health-monitor/alerts/alert-manager.spec.ts +93 -0
  336. package/source/utils/logging/health-monitor/alerts/alert-manager.ts +79 -0
  337. package/source/utils/logging/health-monitor/checks/configuration-check.spec.ts +56 -0
  338. package/source/utils/logging/health-monitor/checks/configuration-check.ts +43 -0
  339. package/source/utils/logging/health-monitor/checks/logging-check.spec.ts +56 -0
  340. package/source/utils/logging/health-monitor/checks/logging-check.ts +58 -0
  341. package/source/utils/logging/health-monitor/checks/memory-check.spec.ts +100 -0
  342. package/source/utils/logging/health-monitor/checks/memory-check.ts +78 -0
  343. package/source/utils/logging/health-monitor/checks/performance-check.spec.ts +56 -0
  344. package/source/utils/logging/health-monitor/checks/performance-check.ts +56 -0
  345. package/source/utils/logging/health-monitor/checks/request-check.spec.ts +56 -0
  346. package/source/utils/logging/health-monitor/checks/request-check.ts +76 -0
  347. package/source/utils/logging/health-monitor/core/health-check-runner.spec.ts +70 -0
  348. package/source/utils/logging/health-monitor/core/health-check-runner.ts +138 -0
  349. package/source/utils/logging/health-monitor/core/health-monitor.spec.ts +58 -0
  350. package/source/utils/logging/health-monitor/core/health-monitor.ts +344 -0
  351. package/source/utils/logging/health-monitor/core/scoring.spec.ts +65 -0
  352. package/source/utils/logging/health-monitor/core/scoring.ts +91 -0
  353. package/source/utils/logging/health-monitor/index.ts +15 -0
  354. package/source/utils/logging/health-monitor/instances.ts +48 -0
  355. package/source/utils/logging/health-monitor/middleware/http-middleware.spec.ts +141 -0
  356. package/source/utils/logging/health-monitor/middleware/http-middleware.ts +75 -0
  357. package/source/utils/logging/health-monitor/types.ts +126 -0
  358. package/source/utils/logging/index.spec.ts +284 -0
  359. package/source/utils/logging/index.ts +236 -0
  360. package/source/utils/logging/integration.spec.ts +441 -0
  361. package/source/utils/logging/log-method-factory.spec.ts +573 -0
  362. package/source/utils/logging/log-method-factory.ts +233 -0
  363. package/source/utils/logging/log-query/aggregation/aggregator.spec.ts +277 -0
  364. package/source/utils/logging/log-query/aggregation/aggregator.ts +159 -0
  365. package/source/utils/logging/log-query/aggregation/facet-generator.spec.ts +159 -0
  366. package/source/utils/logging/log-query/aggregation/facet-generator.ts +47 -0
  367. package/source/utils/logging/log-query/index.ts +23 -0
  368. package/source/utils/logging/log-query/query/filter-predicates.spec.ts +247 -0
  369. package/source/utils/logging/log-query/query/filter-predicates.ts +154 -0
  370. package/source/utils/logging/log-query/query/query-builder.spec.ts +182 -0
  371. package/source/utils/logging/log-query/query/query-builder.ts +151 -0
  372. package/source/utils/logging/log-query/query/query-engine.spec.ts +214 -0
  373. package/source/utils/logging/log-query/query/query-engine.ts +45 -0
  374. package/source/utils/logging/log-query/storage/circular-buffer.spec.ts +143 -0
  375. package/source/utils/logging/log-query/storage/circular-buffer.ts +75 -0
  376. package/source/utils/logging/log-query/storage/index-manager.spec.ts +150 -0
  377. package/source/utils/logging/log-query/storage/index-manager.ts +71 -0
  378. package/source/utils/logging/log-query/storage/log-storage.spec.ts +257 -0
  379. package/source/utils/logging/log-query/storage/log-storage.ts +80 -0
  380. package/source/utils/logging/log-query/types.ts +163 -0
  381. package/source/utils/logging/log-query/utils/helpers.spec.ts +263 -0
  382. package/source/utils/logging/log-query/utils/helpers.ts +72 -0
  383. package/source/utils/logging/log-query/utils/sorting.spec.ts +182 -0
  384. package/source/utils/logging/log-query/utils/sorting.ts +61 -0
  385. package/source/utils/logging/logger-provider.spec.ts +262 -0
  386. package/source/utils/logging/logger-provider.ts +362 -0
  387. package/source/utils/logging/performance.spec.ts +209 -0
  388. package/source/utils/logging/performance.ts +757 -0
  389. package/source/utils/logging/pino-logger.spec.ts +425 -0
  390. package/source/utils/logging/pino-logger.ts +514 -0
  391. package/source/utils/logging/redaction.spec.ts +490 -0
  392. package/source/utils/logging/redaction.ts +267 -0
  393. package/source/utils/logging/request-tracker.spec.ts +1198 -0
  394. package/source/utils/logging/request-tracker.ts +803 -0
  395. package/source/utils/logging/transports.spec.ts +505 -0
  396. package/source/utils/logging/transports.ts +305 -0
  397. package/source/utils/logging/types.ts +216 -0
  398. package/source/utils/message-builder.spec.ts +179 -0
  399. package/source/utils/message-builder.ts +101 -0
  400. package/source/utils/message-queue.tsx +486 -0
  401. package/source/utils/paste-detection.spec.ts +69 -0
  402. package/source/utils/paste-detection.ts +124 -0
  403. package/source/utils/paste-roundtrip.spec.ts +442 -0
  404. package/source/utils/paste-utils.spec.ts +128 -0
  405. package/source/utils/paste-utils.ts +52 -0
  406. package/source/utils/programming-language-helper.spec.ts +74 -0
  407. package/source/utils/programming-language-helper.ts +32 -0
  408. package/source/utils/prompt-assembly.spec.ts +221 -0
  409. package/source/utils/prompt-processor.ts +173 -0
  410. package/source/utils/tool-args-parser.spec.ts +136 -0
  411. package/source/utils/tool-args-parser.ts +54 -0
  412. package/source/utils/tool-cancellation.spec.ts +230 -0
  413. package/source/utils/tool-cancellation.ts +28 -0
  414. package/source/utils/tool-result-display.spec.tsx +469 -0
  415. package/source/utils/tool-result-display.tsx +90 -0
  416. package/source/utils/update-checker.spec.ts +383 -0
  417. package/source/utils/update-checker.ts +183 -0
  418. package/source/wizard/config-wizard.spec.tsx +103 -0
  419. package/source/wizard/config-wizard.tsx +382 -0
  420. package/source/wizard/steps/location-step.spec.tsx +186 -0
  421. package/source/wizard/steps/location-step.tsx +147 -0
  422. package/source/wizard/steps/mcp-step.spec.tsx +607 -0
  423. package/source/wizard/steps/mcp-step.tsx +632 -0
  424. package/source/wizard/steps/provider-step.spec.tsx +342 -0
  425. package/source/wizard/steps/provider-step.tsx +957 -0
  426. package/source/wizard/steps/summary-step.spec.tsx +749 -0
  427. package/source/wizard/steps/summary-step.tsx +228 -0
  428. package/source/wizard/templates/mcp-templates.spec.ts +613 -0
  429. package/source/wizard/templates/mcp-templates.ts +570 -0
  430. package/source/wizard/templates/provider-templates.spec.ts +152 -0
  431. package/source/wizard/templates/provider-templates.ts +485 -0
  432. package/source/wizard/utils/fetch-cloud-models.spec.ts +428 -0
  433. package/source/wizard/utils/fetch-cloud-models.ts +223 -0
  434. package/source/wizard/utils/fetch-local-models.spec.ts +297 -0
  435. package/source/wizard/utils/fetch-local-models.ts +192 -0
  436. package/source/wizard/validation-array.spec.ts +264 -0
  437. package/source/wizard/validation.spec.ts +373 -0
  438. package/source/wizard/validation.ts +232 -0
  439. package/source/app/prompts/main-prompt.md +0 -122
@@ -0,0 +1,679 @@
1
+ import {existsSync, mkdirSync, rmSync} from 'fs';
2
+ import {tmpdir} from 'os';
3
+ import {join} from 'path';
4
+ import test from 'ava';
5
+
6
+ console.log(`\nlogging/correlation.spec.ts`);
7
+
8
+ // Import correlation functions
9
+ import {
10
+ checkCorrelationHealth,
11
+ correlationMiddleware,
12
+ createCorrelationContext,
13
+ createCorrelationContextWithId,
14
+ createCorrelationFromHeaders,
15
+ extractCorrelationId,
16
+ formatCorrelationForLog,
17
+ generateCorrelationId,
18
+ generateShortCorrelationId,
19
+ getCorrelationHeader,
20
+ getCorrelationId,
21
+ getCorrelationMetadata,
22
+ getCorrelationMonitoring,
23
+ getCurrentCorrelationContext,
24
+ isCorrelationEnabled,
25
+ resetCorrelationMonitoring,
26
+ withCorrelation,
27
+ withCorrelationContext,
28
+ withNewCorrelationContext,
29
+ } from './correlation.js';
30
+
31
+ // Import types
32
+ import type {CorrelationContext, CorrelationMetadata} from './types.js';
33
+
34
+ // Create a temporary test directory
35
+ const testDir = join(tmpdir(), `coder-correlation-test-${Date.now()}`);
36
+
37
+ test.before(() => {
38
+ mkdirSync(testDir, {recursive: true});
39
+ });
40
+
41
+ test.after.always(() => {
42
+ // Clean up test directory
43
+ if (existsSync(testDir)) {
44
+ rmSync(testDir, {recursive: true, force: true});
45
+ }
46
+ });
47
+
48
+ test('generateCorrelationId creates valid correlation ID', t => {
49
+ const id1 = generateCorrelationId();
50
+ const id2 = generateCorrelationId();
51
+
52
+ t.is(typeof id1, 'string', 'Should return string');
53
+ t.is(typeof id2, 'string', 'Should return string');
54
+ t.true(id1.length > 0, 'Should not be empty');
55
+ t.true(id2.length > 0, 'Should not be empty');
56
+ t.not(id1, id2, 'Should generate unique IDs');
57
+ });
58
+
59
+ test('generateShortCorrelationId creates short IDs', t => {
60
+ const shortId = generateShortCorrelationId();
61
+ const fullId = generateCorrelationId();
62
+
63
+ t.is(typeof shortId, 'string', 'Should return string');
64
+ t.true(shortId.length > 0, 'Should not be empty');
65
+ t.true(
66
+ shortId.length < fullId.length,
67
+ 'Short ID should be shorter than full ID',
68
+ );
69
+ });
70
+
71
+ test('correlation context management works', t => {
72
+ const context: CorrelationContext = {
73
+ id: 'test-123',
74
+ parentId: 'parent-456',
75
+ metadata: {
76
+ source: 'test',
77
+ version: '1.0.0',
78
+ },
79
+ };
80
+
81
+ // Use withCorrelationContext for proper async context management
82
+ withCorrelationContext(context, () => {
83
+ // Get current context
84
+ const current = getCurrentCorrelationContext();
85
+ t.truthy(current, 'Should return context');
86
+ t.is(current!.id, context.id, 'Should match ID');
87
+ t.is(current!.parentId, context.parentId, 'Should match parent ID');
88
+ t.is(
89
+ current!.metadata?.source,
90
+ context.metadata?.source,
91
+ 'Should match metadata',
92
+ );
93
+ });
94
+
95
+ // Context should be cleared automatically after withCorrelationContext completes
96
+ const cleared = getCurrentCorrelationContext();
97
+ t.falsy(cleared, 'Should be cleared');
98
+ });
99
+
100
+ test('createCorrelationContext creates valid context', t => {
101
+ const context = createCorrelationContext('parent-123', {
102
+ source: 'test',
103
+ version: '1.0.0',
104
+ });
105
+
106
+ t.is(typeof context.id, 'string', 'Should have ID');
107
+ t.is(context.parentId, 'parent-123', 'Should set parent ID');
108
+ t.is(context.metadata?.source, 'test', 'Should set metadata source');
109
+ t.is(context.metadata?.version, '1.0.0', 'Should set metadata version');
110
+ });
111
+
112
+ test('withCorrelationContext executes function with context', t => {
113
+ const context: CorrelationContext = {
114
+ id: 'test-123',
115
+ parentId: 'parent-456',
116
+ metadata: {source: 'test'},
117
+ };
118
+
119
+ let executedContext: CorrelationContext | null = null;
120
+
121
+ withCorrelationContext(context, () => {
122
+ executedContext = getCurrentCorrelationContext();
123
+ });
124
+
125
+ t.truthy(executedContext, 'Should have context during execution');
126
+ t.is(executedContext!.id, context.id, 'Should have correct ID');
127
+ t.is(
128
+ executedContext!.parentId,
129
+ context.parentId,
130
+ 'Should have correct parent ID',
131
+ );
132
+
133
+ // Context should be cleared after execution
134
+ const afterContext = getCurrentCorrelationContext();
135
+ t.falsy(afterContext, 'Context should be cleared after execution');
136
+ });
137
+
138
+ test('withNewCorrelationContext creates new context', t => {
139
+ let correlationId: string | undefined = undefined;
140
+
141
+ withNewCorrelationContext(
142
+ () => {
143
+ const context = getCurrentCorrelationContext();
144
+ if (context) {
145
+ correlationId = context.id;
146
+ }
147
+ },
148
+ 'parent-123',
149
+ {source: 'test'},
150
+ );
151
+
152
+ t.truthy(correlationId, 'Should generate correlation ID');
153
+ t.is(typeof correlationId!, 'string', 'Should be string');
154
+ t.true(correlationId!.length > 0, 'Should not be empty');
155
+ });
156
+
157
+ test('getCorrelationId returns current ID', t => {
158
+ const context: CorrelationContext = {
159
+ id: 'test-123',
160
+ parentId: 'parent-456',
161
+ };
162
+
163
+ withCorrelationContext(context, () => {
164
+ const id = getCorrelationId();
165
+ t.is(id, 'test-123', 'Should return current correlation ID');
166
+ });
167
+
168
+ // Context should be cleared automatically after withCorrelationContext completes
169
+ const clearedId = getCorrelationId();
170
+ t.falsy(clearedId, 'Should return undefined when no context');
171
+ });
172
+
173
+ test('isCorrelationEnabled checks if correlation is active', t => {
174
+ // isCorrelationEnabled checks process.env, not the current context
175
+ // so this behavior may need to be adjusted based on the actual implementation
176
+ const context = getCurrentCorrelationContext();
177
+ t.is(context, null, 'Context should be null initially');
178
+
179
+ withCorrelationContext(createCorrelationContext(), () => {
180
+ const contextAfterSet = getCurrentCorrelationContext();
181
+ t.truthy(contextAfterSet, 'Context should not be null after setting');
182
+ });
183
+
184
+ // Context should be cleared automatically after withCorrelationContext completes
185
+ });
186
+
187
+ test('getCorrelationHeader returns header value', t => {
188
+ const context: CorrelationContext = {
189
+ id: 'test-123',
190
+ parentId: 'parent-456',
191
+ };
192
+
193
+ withCorrelationContext(context, () => {
194
+ const header = getCorrelationHeader();
195
+ t.truthy(header, 'Should return header');
196
+ t.is(typeof header, 'object', 'Should be object');
197
+ t.deepEqual(
198
+ header,
199
+ {'X-Correlation-ID': 'test-123'},
200
+ 'Should return correct header',
201
+ );
202
+ });
203
+
204
+ // Context should be cleared automatically after withCorrelationContext completes
205
+ const noHeader = getCorrelationHeader();
206
+ t.deepEqual(noHeader, {}, 'Should return empty object when no context');
207
+ });
208
+
209
+ test('extractCorrelationId extracts from various sources', t => {
210
+ // Test with correlation header
211
+ const header = 'test-123';
212
+ t.is(
213
+ extractCorrelationId({'x-correlation-id': header}),
214
+ header,
215
+ 'Should extract from header',
216
+ );
217
+
218
+ // Test with request ID
219
+ const requestId = 'req-456';
220
+ t.is(
221
+ extractCorrelationId({'x-request-id': requestId}),
222
+ requestId,
223
+ 'Should extract from request ID',
224
+ );
225
+
226
+ // Test with trace ID
227
+ const traceId = 'trace-789';
228
+ t.is(
229
+ extractCorrelationId({'x-trace-id': traceId}),
230
+ traceId,
231
+ 'Should extract from trace ID',
232
+ );
233
+
234
+ // Test with no headers
235
+ t.falsy(extractCorrelationId({}), 'Should return undefined with no headers');
236
+ });
237
+
238
+ test('createCorrelationFromHeaders creates context from headers', t => {
239
+ const headers = {
240
+ 'x-correlation-id': 'corr-123',
241
+ 'x-trace-id': 'trace-456',
242
+ 'x-span-id': 'span-789',
243
+ 'x-user-id': 'user-123',
244
+ 'x-session-id': 'session-456',
245
+ };
246
+
247
+ const context = createCorrelationFromHeaders(headers);
248
+
249
+ t.truthy(context, 'Should create context');
250
+ t.is(context!.id, 'corr-123', 'Should set correlation ID');
251
+ });
252
+
253
+ test('correlation metadata management', t => {
254
+ const metadata: CorrelationMetadata = {
255
+ source: 'api-server',
256
+ version: '2.1.0',
257
+ environment: 'production',
258
+ };
259
+
260
+ const context: CorrelationContext = {
261
+ id: 'test-456',
262
+ metadata,
263
+ };
264
+
265
+ withCorrelationContext(context, () => {
266
+ // Get metadata
267
+ const retrieved = getCorrelationMetadata() as CorrelationMetadata;
268
+ t.truthy(retrieved, 'Should return metadata');
269
+ t.is(retrieved.source, metadata.source, 'Should match source');
270
+ t.is(retrieved.version, metadata.version, 'Should match version');
271
+ t.is(
272
+ retrieved.environment,
273
+ metadata.environment,
274
+ 'Should match environment',
275
+ );
276
+ });
277
+
278
+ // Context should be cleared automatically after withCorrelationContext completes
279
+ });
280
+
281
+ test('formatCorrelationForLog formats for logging', t => {
282
+ const context: CorrelationContext = {
283
+ id: 'test-123',
284
+ parentId: 'parent-456',
285
+ metadata: {source: 'test'},
286
+ };
287
+
288
+ withCorrelationContext(context, () => {
289
+ const formatted = formatCorrelationForLog();
290
+ t.is(typeof formatted, 'object', 'Should return object');
291
+ t.is(formatted.correlationId, 'test-123', 'Should include correlation ID');
292
+ });
293
+
294
+ // Context should be cleared automatically after withCorrelationContext completes
295
+ });
296
+
297
+ test('correlationMiddleware creates middleware function', t => {
298
+ const middleware = correlationMiddleware();
299
+
300
+ t.is(typeof middleware, 'function', 'Should return middleware function');
301
+
302
+ // Test middleware execution
303
+ const mockRequest = {
304
+ headers: {
305
+ 'x-correlation-id': 'test-123',
306
+ },
307
+ };
308
+
309
+ const mockResponse = {};
310
+ const mockNext = () => {};
311
+
312
+ t.notThrows(() => {
313
+ middleware(mockRequest, mockResponse, mockNext);
314
+ }, 'Middleware should execute without errors');
315
+ });
316
+
317
+ test('withCorrelation decorator works with async functions', async t => {
318
+ const mockFunction = async (...args: unknown[]) => {
319
+ const input = args[0] as string;
320
+ const context = getCurrentCorrelationContext();
321
+ return `${input}-${context?.id || 'no-context'}`;
322
+ };
323
+
324
+ const decoratedFunction = withCorrelation(mockFunction);
325
+
326
+ const result = await decoratedFunction('test');
327
+ t.is(typeof result, 'string', 'Should return string');
328
+ t.true((result as string).includes('test-'), 'Should include input');
329
+ });
330
+
331
+ test('context isolation between concurrent operations', async t => {
332
+ const results: string[] = [];
333
+
334
+ const operation1 = withNewCorrelationContext(
335
+ async () => {
336
+ await new Promise(resolve => setTimeout(resolve, 10));
337
+ const context = getCurrentCorrelationContext();
338
+ results.push(`op1-${context?.metadata?.userId}`);
339
+ },
340
+ 'parent-1',
341
+ {userId: 'user-1'},
342
+ );
343
+
344
+ const operation2 = withNewCorrelationContext(
345
+ async () => {
346
+ await new Promise(resolve => setTimeout(resolve, 5));
347
+ const context = getCurrentCorrelationContext();
348
+ results.push(`op2-${context?.metadata?.userId}`);
349
+ },
350
+ 'parent-2',
351
+ {userId: 'user-2'},
352
+ );
353
+
354
+ await Promise.all([operation1, operation2]);
355
+
356
+ t.is(results.length, 2, 'Should have both results');
357
+ t.true(
358
+ results.some(r => r.includes('user-1')),
359
+ 'Should have user-1 result',
360
+ );
361
+ t.true(
362
+ results.some(r => r.includes('user-2')),
363
+ 'Should have user-2 result',
364
+ );
365
+ });
366
+
367
+ test('error handling in correlation functions', t => {
368
+ // Test with malformed headers
369
+ const malformedHeaders = {
370
+ 'x-correlation-id': null,
371
+ 'x-trace-id': undefined,
372
+ 'x-user-id': 123,
373
+ };
374
+
375
+ t.notThrows(() => {
376
+ createCorrelationFromHeaders(malformedHeaders as any);
377
+ }, 'Should handle malformed headers');
378
+ });
379
+
380
+ test('correlation ID format validation', t => {
381
+ const validId = generateCorrelationId();
382
+
383
+ t.regex(validId, /^[a-zA-Z0-9_-]+$/, 'Should contain only valid characters');
384
+ t.true(validId.length >= 8, 'Should be at least 8 characters');
385
+ t.true(validId.length <= 64, 'Should not exceed 64 characters');
386
+ });
387
+
388
+ /**
389
+ * Test AsyncLocalStorage-only mode (legacy context disabled)
390
+ * This test verifies that the system works correctly without legacy context fallback
391
+ */
392
+ test('AsyncLocalStorage-only mode works without legacy context', t => {
393
+ // Save original environment variable
394
+ const originalEnv = process.env.CODER_CORRELATION_LEGACY_FALLBACK;
395
+
396
+ try {
397
+ // Disable legacy context
398
+ process.env.CODER_CORRELATION_LEGACY_FALLBACK = 'false';
399
+
400
+ // Test that AsyncLocalStorage still works
401
+ const testId = generateCorrelationId();
402
+ const testMetadata = {source: 'test', version: '1.0.0'};
403
+
404
+ const result = withNewCorrelationContext(
405
+ (context: CorrelationContext) => {
406
+ // Verify context is created correctly
407
+ t.truthy(context, 'Should have context');
408
+ t.is(context.id, testId, 'Should have correct ID');
409
+ t.deepEqual(
410
+ context.metadata,
411
+ testMetadata,
412
+ 'Should have correct metadata',
413
+ );
414
+
415
+ // Verify context is accessible within AsyncLocalStorage
416
+ t.is(getCorrelationId(), testId, 'Should get correct ID');
417
+ t.deepEqual(
418
+ getCorrelationMetadata(),
419
+ testMetadata,
420
+ 'Should get correct metadata',
421
+ );
422
+
423
+ // Verify legacy context is not used
424
+ t.is(
425
+ getCurrentCorrelationContext(),
426
+ context,
427
+ 'Should use AsyncLocalStorage context',
428
+ );
429
+
430
+ return 'success';
431
+ },
432
+ testId,
433
+ testMetadata,
434
+ );
435
+
436
+ t.is(result, 'success', 'Should execute successfully');
437
+
438
+ // Verify no legacy context was used
439
+ const asyncOnlyResult = withNewCorrelationContext(
440
+ (context: CorrelationContext) => {
441
+ // In AsyncLocalStorage-only mode, legacy context should not interfere
442
+ const current = getCurrentCorrelationContext();
443
+ t.truthy(current, 'Should have AsyncLocalStorage context');
444
+ t.is(current!.id, context.id, 'Should match current context');
445
+
446
+ // Format for logging should work
447
+ const formatted = formatCorrelationForLog();
448
+ t.truthy(formatted.correlationId, 'Should format for logging');
449
+
450
+ return true;
451
+ },
452
+ );
453
+
454
+ t.true(asyncOnlyResult, 'Should work without legacy context');
455
+ } finally {
456
+ // Restore original environment variable
457
+ if (originalEnv === undefined) {
458
+ delete process.env.CODER_CORRELATION_LEGACY_FALLBACK;
459
+ } else {
460
+ process.env.CODER_CORRELATION_LEGACY_FALLBACK = originalEnv;
461
+ }
462
+ }
463
+ });
464
+
465
+ /**
466
+ * Test concurrent operations with AsyncLocalStorage
467
+ * Verifies that correlation contexts don't interfere with each other
468
+ */
469
+ test('Concurrent operations maintain isolated correlation contexts', async t => {
470
+ const results = await Promise.all([
471
+ withNewCorrelationContext(
472
+ async (context1: CorrelationContext) => {
473
+ await new Promise(resolve => setTimeout(resolve, 10));
474
+ return {id: context1.id, metadata: context1.metadata};
475
+ },
476
+ 'context-1',
477
+ {source: 'test1'},
478
+ ),
479
+
480
+ withNewCorrelationContext(
481
+ async (context2: CorrelationContext) => {
482
+ await new Promise(resolve => setTimeout(resolve, 10));
483
+ return {id: context2.id, metadata: context2.metadata};
484
+ },
485
+ 'context-2',
486
+ {source: 'test2'},
487
+ ),
488
+
489
+ withNewCorrelationContext(
490
+ async (context3: CorrelationContext) => {
491
+ await new Promise(resolve => setTimeout(resolve, 10));
492
+ return {id: context3.id, metadata: context3.metadata};
493
+ },
494
+ 'context-3',
495
+ {source: 'test3'},
496
+ ),
497
+ ]);
498
+
499
+ // Verify all contexts are different
500
+ t.is(results.length, 3, 'Should have 3 results');
501
+ t.not(results[0].id, results[1].id, 'Context 1 and 2 should be different');
502
+ t.not(results[0].id, results[2].id, 'Context 1 and 3 should be different');
503
+ t.not(results[1].id, results[2].id, 'Context 2 and 3 should be different');
504
+
505
+ // Verify metadata is correct
506
+ t.deepEqual(
507
+ results[0].metadata,
508
+ {source: 'test1'},
509
+ 'Context 1 should have correct metadata',
510
+ );
511
+ t.deepEqual(
512
+ results[1].metadata,
513
+ {source: 'test2'},
514
+ 'Context 2 should have correct metadata',
515
+ );
516
+ t.deepEqual(
517
+ results[2].metadata,
518
+ {source: 'test3'},
519
+ 'Context 3 should have correct metadata',
520
+ );
521
+ });
522
+
523
+ /**
524
+ * Test correlation context persistence across async boundaries
525
+ */
526
+ test('Correlation context persists across async boundaries', async t => {
527
+ const testId = generateCorrelationId();
528
+ const testMetadata = {async: 'test', boundary: 'test'};
529
+
530
+ const result = await withNewCorrelationContext(
531
+ async (context: CorrelationContext) => {
532
+ // Verify context in first async operation
533
+ t.is(getCorrelationId(), testId, 'Should have context in first async op');
534
+
535
+ // Wait and verify context persists
536
+ await new Promise(resolve => setTimeout(resolve, 20));
537
+ t.is(getCorrelationId(), testId, 'Should persist after timeout');
538
+
539
+ // Nested async operation
540
+ const nestedResult = await new Promise(resolve => {
541
+ setTimeout(() => {
542
+ t.is(getCorrelationId(), testId, 'Should persist in nested async');
543
+ resolve('nested-success');
544
+ }, 10);
545
+ });
546
+
547
+ // Final verification
548
+ t.is(getCorrelationId(), testId, 'Should persist to end');
549
+
550
+ return nestedResult;
551
+ },
552
+ testId,
553
+ testMetadata,
554
+ );
555
+
556
+ t.is(result, 'nested-success', 'Should complete successfully');
557
+ });
558
+
559
+ /**
560
+ * Test error handling with correlation context
561
+ */
562
+ test('Correlation context preserved in error scenarios', async t => {
563
+ const testId = generateCorrelationId();
564
+
565
+ try {
566
+ await withNewCorrelationContext(async (context: CorrelationContext) => {
567
+ t.is(getCorrelationId(), testId, 'Should have context before error');
568
+
569
+ // Simulate error
570
+ throw new Error('Test error');
571
+ }, testId);
572
+
573
+ t.fail('Should have thrown error');
574
+ } catch (error) {
575
+ // Error should be thrown, but we can't access context here
576
+ t.is((error as Error).message, 'Test error', 'Should throw correct error');
577
+ }
578
+
579
+ // Context should not leak after error
580
+ const afterError = getCurrentCorrelationContext();
581
+ t.falsy(afterError, 'Context should not leak after error');
582
+ });
583
+
584
+ test('metadata merging works correctly', t => {
585
+ const metadata = {
586
+ source: 'api',
587
+ version: '1.0.0',
588
+ environment: 'production',
589
+ requestId: 'req-123',
590
+ };
591
+
592
+ const context: CorrelationContext = {
593
+ id: 'test-123',
594
+ metadata,
595
+ };
596
+
597
+ withCorrelationContext(context, () => {
598
+ const merged = getCorrelationMetadata() as CorrelationMetadata;
599
+
600
+ t.is(merged.source, 'api', 'Should preserve initial metadata');
601
+ t.is(merged.version, '1.0.0', 'Should preserve initial version');
602
+ t.is(
603
+ merged.environment,
604
+ 'production',
605
+ 'Should include additional metadata',
606
+ );
607
+ t.is(merged.requestId, 'req-123', 'Should include additional request ID');
608
+ });
609
+
610
+ // Context should be cleared automatically after withCorrelationContext completes
611
+ });
612
+
613
+ /**
614
+ * Test correlation monitoring functionality
615
+ */
616
+ test('correlation monitoring tracks context usage', t => {
617
+ // Reset monitoring to start fresh
618
+ resetCorrelationMonitoring();
619
+
620
+ // Initial state
621
+ const initialMetrics = getCorrelationMonitoring();
622
+ t.is(
623
+ initialMetrics.contextsCreated,
624
+ 0,
625
+ 'Should start with 0 contexts created',
626
+ );
627
+ t.is(initialMetrics.activeContexts, 0, 'Should start with 0 active contexts');
628
+ t.is(initialMetrics.errors, 0, 'Should start with 0 errors');
629
+
630
+ // Create some contexts
631
+ withNewCorrelationContext(() => 'test1');
632
+ withNewCorrelationContext(() => 'test2');
633
+
634
+ // Check metrics after context creation
635
+ const afterMetrics = getCorrelationMonitoring();
636
+ t.is(afterMetrics.contextsCreated, 2, 'Should track 2 contexts created');
637
+ t.is(
638
+ afterMetrics.activeContexts,
639
+ 0,
640
+ 'Should have 0 active contexts after completion',
641
+ );
642
+ t.is(afterMetrics.errors, 0, 'Should still have 0 errors');
643
+
644
+ // Test health check
645
+ const health = checkCorrelationHealth();
646
+ t.true(health.healthy, 'Health check should pass');
647
+ t.is(
648
+ health.message,
649
+ 'Correlation context system is healthy',
650
+ 'Should report healthy status',
651
+ );
652
+ });
653
+
654
+ /**
655
+ * Test correlation monitoring error tracking
656
+ */
657
+ test('correlation monitoring tracks errors', t => {
658
+ // Reset monitoring to start fresh
659
+ resetCorrelationMonitoring();
660
+
661
+ // Create a context that throws an error
662
+ try {
663
+ withNewCorrelationContext(() => {
664
+ throw new Error('Test error for monitoring');
665
+ });
666
+ } catch {
667
+ // Expected to catch the error
668
+ }
669
+
670
+ // Check error tracking
671
+ const metrics = getCorrelationMonitoring();
672
+ t.is(metrics.errors, 1, 'Should track 1 error');
673
+ t.truthy(metrics.lastError, 'Should have last error recorded');
674
+ t.is(
675
+ metrics.lastErrorTime,
676
+ metrics.lastErrorTime,
677
+ 'Should have error timestamp',
678
+ );
679
+ });