@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,143 @@
1
+ /**
2
+ * Tests for circular buffer
3
+ */
4
+
5
+ import test from 'ava';
6
+ import {CircularBuffer} from './circular-buffer.js';
7
+ import type {LogEntry} from '../types.js';
8
+
9
+ // Helper to create a test log entry
10
+ function createLogEntry(id: number): LogEntry {
11
+ return {
12
+ timestamp: new Date(Date.now() + id * 1000).toISOString(),
13
+ level: 'info',
14
+ message: `Test message ${id}`,
15
+ };
16
+ }
17
+
18
+ test('CircularBuffer: constructor creates empty buffer', t => {
19
+ const buffer = new CircularBuffer(10);
20
+ t.is(buffer.getCount(), 0);
21
+ t.deepEqual(buffer.getAll(), []);
22
+ });
23
+
24
+ test('CircularBuffer: add single entry', t => {
25
+ const buffer = new CircularBuffer(10);
26
+ const entry = createLogEntry(1);
27
+
28
+ const removed = buffer.add(entry);
29
+
30
+ t.is(removed, undefined, 'Should not remove entry when buffer not full');
31
+ t.is(buffer.getCount(), 1);
32
+ t.deepEqual(buffer.getAll(), [entry]);
33
+ });
34
+
35
+ test('CircularBuffer: add multiple entries within capacity', t => {
36
+ const buffer = new CircularBuffer(10);
37
+ const entries = [createLogEntry(1), createLogEntry(2), createLogEntry(3)];
38
+
39
+ for (const entry of entries) {
40
+ buffer.add(entry);
41
+ }
42
+
43
+ t.is(buffer.getCount(), 3);
44
+ t.deepEqual(buffer.getAll(), entries);
45
+ });
46
+
47
+ test('CircularBuffer: add entries beyond capacity (wraparound)', t => {
48
+ const buffer = new CircularBuffer(3);
49
+ const entries = [
50
+ createLogEntry(1),
51
+ createLogEntry(2),
52
+ createLogEntry(3),
53
+ createLogEntry(4),
54
+ ];
55
+
56
+ buffer.add(entries[0]);
57
+ buffer.add(entries[1]);
58
+ buffer.add(entries[2]);
59
+
60
+ // Adding 4th entry should remove first entry
61
+ const removed = buffer.add(entries[3]);
62
+
63
+ t.deepEqual(removed, entries[0], 'Should remove oldest entry');
64
+ t.is(buffer.getCount(), 3, 'Count should stay at max capacity');
65
+ t.deepEqual(buffer.getAll(), [entries[1], entries[2], entries[3]]);
66
+ });
67
+
68
+ test('CircularBuffer: wraparound maintains order', t => {
69
+ const buffer = new CircularBuffer(3);
70
+
71
+ // Fill buffer
72
+ buffer.add(createLogEntry(1));
73
+ buffer.add(createLogEntry(2));
74
+ buffer.add(createLogEntry(3));
75
+
76
+ // Add more to cause wraparound
77
+ buffer.add(createLogEntry(4));
78
+ buffer.add(createLogEntry(5));
79
+
80
+ const all = buffer.getAll();
81
+ t.is(all.length, 3);
82
+ t.is(all[0]?.message, 'Test message 3');
83
+ t.is(all[1]?.message, 'Test message 4');
84
+ t.is(all[2]?.message, 'Test message 5');
85
+ });
86
+
87
+ test('CircularBuffer: clear resets buffer', t => {
88
+ const buffer = new CircularBuffer(10);
89
+
90
+ buffer.add(createLogEntry(1));
91
+ buffer.add(createLogEntry(2));
92
+ buffer.add(createLogEntry(3));
93
+
94
+ t.is(buffer.getCount(), 3);
95
+
96
+ buffer.clear();
97
+
98
+ t.is(buffer.getCount(), 0);
99
+ t.deepEqual(buffer.getAll(), []);
100
+ });
101
+
102
+ test('CircularBuffer: clear allows reuse', t => {
103
+ const buffer = new CircularBuffer(3);
104
+
105
+ buffer.add(createLogEntry(1));
106
+ buffer.add(createLogEntry(2));
107
+ buffer.clear();
108
+
109
+ const entry = createLogEntry(3);
110
+ buffer.add(entry);
111
+
112
+ t.is(buffer.getCount(), 1);
113
+ t.deepEqual(buffer.getAll(), [entry]);
114
+ });
115
+
116
+ test('CircularBuffer: getAll returns entries in order (oldest to newest)', t => {
117
+ const buffer = new CircularBuffer(5);
118
+
119
+ for (let i = 1; i <= 5; i++) {
120
+ buffer.add(createLogEntry(i));
121
+ }
122
+
123
+ const all = buffer.getAll();
124
+ t.is(all.length, 5);
125
+
126
+ for (let i = 0; i < 5; i++) {
127
+ t.is(all[i]?.message, `Test message ${i + 1}`);
128
+ }
129
+ });
130
+
131
+ test('CircularBuffer: handles single entry capacity', t => {
132
+ const buffer = new CircularBuffer(1);
133
+
134
+ const entry1 = createLogEntry(1);
135
+ const entry2 = createLogEntry(2);
136
+
137
+ buffer.add(entry1);
138
+ t.deepEqual(buffer.getAll(), [entry1]);
139
+
140
+ const removed = buffer.add(entry2);
141
+ t.deepEqual(removed, entry1);
142
+ t.deepEqual(buffer.getAll(), [entry2]);
143
+ });
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Circular buffer implementation for efficient log storage
3
+ */
4
+
5
+ import type {LogEntry} from '../types';
6
+
7
+ /**
8
+ * Circular buffer for storing log entries with O(1) add/remove
9
+ */
10
+ export class CircularBuffer {
11
+ private entries: (LogEntry | undefined)[];
12
+ private head: number = 0; // Index of oldest entry
13
+ private tail: number = 0; // Index where next entry goes
14
+ private count: number = 0; // Current number of entries
15
+ private maxEntries: number;
16
+
17
+ constructor(maxEntries: number) {
18
+ this.maxEntries = maxEntries;
19
+ this.entries = new Array(maxEntries); // Pre-allocate array
20
+ }
21
+
22
+ /**
23
+ * Add entry to buffer - O(1) operation
24
+ * Returns the removed entry if buffer was full, undefined otherwise
25
+ */
26
+ add(entry: LogEntry): LogEntry | undefined {
27
+ let removed: LogEntry | undefined;
28
+
29
+ // If buffer is full, remove oldest entry
30
+ if (this.count === this.maxEntries) {
31
+ removed = this.entries[this.head];
32
+ // Advance head (oldest entry pointer)
33
+ this.head = (this.head + 1) % this.maxEntries;
34
+ } else {
35
+ this.count++;
36
+ }
37
+
38
+ // Write new entry at tail position - O(1)
39
+ this.entries[this.tail] = entry;
40
+ this.tail = (this.tail + 1) % this.maxEntries;
41
+
42
+ return removed;
43
+ }
44
+
45
+ /**
46
+ * Get all entries as array (oldest to newest)
47
+ */
48
+ getAll(): LogEntry[] {
49
+ const result: LogEntry[] = [];
50
+ for (let i = 0; i < this.count; i++) {
51
+ const entry = this.entries[(this.head + i) % this.maxEntries];
52
+ if (entry) {
53
+ result.push(entry);
54
+ }
55
+ }
56
+ return result;
57
+ }
58
+
59
+ /**
60
+ * Get current count of entries
61
+ */
62
+ getCount(): number {
63
+ return this.count;
64
+ }
65
+
66
+ /**
67
+ * Clear all entries
68
+ */
69
+ clear(): void {
70
+ this.entries = new Array(this.maxEntries);
71
+ this.head = 0;
72
+ this.tail = 0;
73
+ this.count = 0;
74
+ }
75
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Tests for index manager
3
+ */
4
+
5
+ import test from 'ava';
6
+ import {IndexManager} from './index-manager.js';
7
+ import type {LogEntry} from '../types.js';
8
+
9
+ // Helper to create test log entry
10
+ function createLogEntry(
11
+ level: string,
12
+ correlationId?: string,
13
+ source?: string,
14
+ ): LogEntry {
15
+ return {
16
+ timestamp: new Date().toISOString(),
17
+ level,
18
+ message: 'Test message',
19
+ correlationId,
20
+ source,
21
+ };
22
+ }
23
+
24
+ test('IndexManager: starts with empty indexes', t => {
25
+ const manager = new IndexManager();
26
+
27
+ t.is(manager.getIndexValues('level'), undefined);
28
+ t.is(manager.getIndexValues('correlationId'), undefined);
29
+ t.is(manager.getIndexValues('source'), undefined);
30
+ });
31
+
32
+ test('IndexManager: adds level index', t => {
33
+ const manager = new IndexManager();
34
+ const entry = createLogEntry('error');
35
+
36
+ manager.updateIndexes(entry, true);
37
+
38
+ const levelIndex = manager.getIndexValues('level');
39
+ t.truthy(levelIndex);
40
+ t.true(levelIndex?.has('error'));
41
+ });
42
+
43
+ test('IndexManager: adds correlation ID index', t => {
44
+ const manager = new IndexManager();
45
+ const entry = createLogEntry('info', 'corr-123');
46
+
47
+ manager.updateIndexes(entry, true);
48
+
49
+ const corrIndex = manager.getIndexValues('correlationId');
50
+ t.truthy(corrIndex);
51
+ t.true(corrIndex?.has('corr-123'));
52
+ });
53
+
54
+ test('IndexManager: adds source index', t => {
55
+ const manager = new IndexManager();
56
+ const entry = createLogEntry('info', undefined, 'api-server');
57
+
58
+ manager.updateIndexes(entry, true);
59
+
60
+ const sourceIndex = manager.getIndexValues('source');
61
+ t.truthy(sourceIndex);
62
+ t.true(sourceIndex?.has('api-server'));
63
+ });
64
+
65
+ test('IndexManager: adds multiple entries to same index', t => {
66
+ const manager = new IndexManager();
67
+
68
+ manager.updateIndexes(createLogEntry('error'), true);
69
+ manager.updateIndexes(createLogEntry('warn'), true);
70
+ manager.updateIndexes(createLogEntry('info'), true);
71
+
72
+ const levelIndex = manager.getIndexValues('level');
73
+ t.is(levelIndex?.size, 3);
74
+ t.true(levelIndex?.has('error'));
75
+ t.true(levelIndex?.has('warn'));
76
+ t.true(levelIndex?.has('info'));
77
+ });
78
+
79
+ test('IndexManager: removes from level index', t => {
80
+ const manager = new IndexManager();
81
+ const entry = createLogEntry('error');
82
+
83
+ manager.updateIndexes(entry, true);
84
+ t.true(manager.getIndexValues('level')?.has('error'));
85
+
86
+ manager.updateIndexes(entry, false);
87
+ t.false(manager.getIndexValues('level')?.has('error'));
88
+ });
89
+
90
+ test('IndexManager: removes from correlation ID index', t => {
91
+ const manager = new IndexManager();
92
+ const entry = createLogEntry('info', 'corr-123');
93
+
94
+ manager.updateIndexes(entry, true);
95
+ t.true(manager.getIndexValues('correlationId')?.has('corr-123'));
96
+
97
+ manager.updateIndexes(entry, false);
98
+ t.false(manager.getIndexValues('correlationId')?.has('corr-123'));
99
+ });
100
+
101
+ test('IndexManager: removes from source index', t => {
102
+ const manager = new IndexManager();
103
+ const entry = createLogEntry('info', undefined, 'api-server');
104
+
105
+ manager.updateIndexes(entry, true);
106
+ t.true(manager.getIndexValues('source')?.has('api-server'));
107
+
108
+ manager.updateIndexes(entry, false);
109
+ t.false(manager.getIndexValues('source')?.has('api-server'));
110
+ });
111
+
112
+ test('IndexManager: clear removes all indexes', t => {
113
+ const manager = new IndexManager();
114
+
115
+ manager.updateIndexes(createLogEntry('error', 'corr-1', 'api'), true);
116
+ manager.updateIndexes(createLogEntry('warn', 'corr-2', 'db'), true);
117
+
118
+ t.truthy(manager.getIndexValues('level'));
119
+ t.truthy(manager.getIndexValues('correlationId'));
120
+ t.truthy(manager.getIndexValues('source'));
121
+
122
+ manager.clear();
123
+
124
+ t.is(manager.getIndexValues('level'), undefined);
125
+ t.is(manager.getIndexValues('correlationId'), undefined);
126
+ t.is(manager.getIndexValues('source'), undefined);
127
+ });
128
+
129
+ test('IndexManager: handles entries without optional fields', t => {
130
+ const manager = new IndexManager();
131
+ const entry = createLogEntry('info'); // No correlationId or source
132
+
133
+ manager.updateIndexes(entry, true);
134
+
135
+ t.truthy(manager.getIndexValues('level'));
136
+ t.is(manager.getIndexValues('correlationId'), undefined);
137
+ t.is(manager.getIndexValues('source'), undefined);
138
+ });
139
+
140
+ test('IndexManager: handles duplicate values correctly', t => {
141
+ const manager = new IndexManager();
142
+
143
+ manager.updateIndexes(createLogEntry('error'), true);
144
+ manager.updateIndexes(createLogEntry('error'), true);
145
+ manager.updateIndexes(createLogEntry('error'), true);
146
+
147
+ const levelIndex = manager.getIndexValues('level');
148
+ t.is(levelIndex?.size, 1); // Set should only have one 'error' entry
149
+ t.true(levelIndex?.has('error'));
150
+ });
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Index manager for efficient log entry lookups
3
+ */
4
+
5
+ import type {LogEntry} from '../types';
6
+
7
+ /**
8
+ * Manages indexes for log entries
9
+ */
10
+ export class IndexManager {
11
+ private indexes: Map<string, Set<string>> = new Map();
12
+
13
+ /**
14
+ * Update indexes when entry is added or removed
15
+ */
16
+ updateIndexes(entry: LogEntry, add: boolean): void {
17
+ // Update correlation ID index
18
+ if (entry.correlationId) {
19
+ if (!this.indexes.has('correlationId')) {
20
+ this.indexes.set('correlationId', new Set());
21
+ }
22
+ // biome-ignore lint/style/noNonNullAssertion: Index exists after set above
23
+ const index = this.indexes.get('correlationId')!;
24
+ if (add) {
25
+ index.add(entry.correlationId);
26
+ } else {
27
+ index.delete(entry.correlationId);
28
+ }
29
+ }
30
+
31
+ // Update source index
32
+ if (entry.source) {
33
+ if (!this.indexes.has('source')) {
34
+ this.indexes.set('source', new Set());
35
+ }
36
+ // biome-ignore lint/style/noNonNullAssertion: Index exists after set above
37
+ const index = this.indexes.get('source')!;
38
+ if (add) {
39
+ index.add(entry.source);
40
+ } else {
41
+ index.delete(entry.source);
42
+ }
43
+ }
44
+
45
+ // Update level index
46
+ if (!this.indexes.has('level')) {
47
+ this.indexes.set('level', new Set());
48
+ }
49
+ // biome-ignore lint/style/noNonNullAssertion: Index exists after set above
50
+ const levelIndex = this.indexes.get('level')!;
51
+ if (add) {
52
+ levelIndex.add(entry.level);
53
+ } else {
54
+ levelIndex.delete(entry.level);
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Clear all indexes
60
+ */
61
+ clear(): void {
62
+ this.indexes.clear();
63
+ }
64
+
65
+ /**
66
+ * Get all values for a specific index
67
+ */
68
+ getIndexValues(indexName: string): Set<string> | undefined {
69
+ return this.indexes.get(indexName);
70
+ }
71
+ }
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Tests for log storage
3
+ */
4
+
5
+ import test from 'ava';
6
+ import {LogStorage} from './log-storage.js';
7
+ import type {AggregationOptions, LogEntry, LogQuery} from '../types.js';
8
+
9
+ // Helper to create test log entry
10
+ function createLogEntry(overrides: Partial<LogEntry> = {}): LogEntry {
11
+ return {
12
+ timestamp: new Date().toISOString(),
13
+ level: 'info',
14
+ message: 'Test message',
15
+ ...overrides,
16
+ };
17
+ }
18
+
19
+ test('LogStorage: constructor creates empty storage', t => {
20
+ const storage = new LogStorage(10);
21
+
22
+ t.is(storage.getEntryCount(), 0);
23
+ });
24
+
25
+ test('LogStorage: addEntry adds entry to storage', t => {
26
+ const storage = new LogStorage(10);
27
+ const entry = createLogEntry();
28
+
29
+ storage.addEntry(entry);
30
+
31
+ t.is(storage.getEntryCount(), 1);
32
+ });
33
+
34
+ test('LogStorage: addEntry multiple entries', t => {
35
+ const storage = new LogStorage(10);
36
+
37
+ storage.addEntry(createLogEntry({message: '1'}));
38
+ storage.addEntry(createLogEntry({message: '2'}));
39
+ storage.addEntry(createLogEntry({message: '3'}));
40
+
41
+ t.is(storage.getEntryCount(), 3);
42
+ });
43
+
44
+ test('LogStorage: addEntry respects max capacity', t => {
45
+ const storage = new LogStorage(3);
46
+
47
+ storage.addEntry(createLogEntry({message: '1'}));
48
+ storage.addEntry(createLogEntry({message: '2'}));
49
+ storage.addEntry(createLogEntry({message: '3'}));
50
+ storage.addEntry(createLogEntry({message: '4'}));
51
+
52
+ t.is(storage.getEntryCount(), 3); // Should stay at max
53
+ });
54
+
55
+ test('LogStorage: query returns all entries', t => {
56
+ const storage = new LogStorage(10);
57
+
58
+ storage.addEntry(createLogEntry({level: 'error'}));
59
+ storage.addEntry(createLogEntry({level: 'info'}));
60
+ storage.addEntry(createLogEntry({level: 'warn'}));
61
+
62
+ const query: LogQuery = {};
63
+ const result = storage.query(query);
64
+
65
+ t.is(result.entries.length, 3);
66
+ t.is(result.totalCount, 3);
67
+ });
68
+
69
+ test('LogStorage: query filters by level', t => {
70
+ const storage = new LogStorage(10);
71
+
72
+ storage.addEntry(createLogEntry({level: 'error'}));
73
+ storage.addEntry(createLogEntry({level: 'info'}));
74
+ storage.addEntry(createLogEntry({level: 'error'}));
75
+
76
+ const query: LogQuery = {levels: ['error']};
77
+ const result = storage.query(query);
78
+
79
+ t.is(result.entries.length, 2);
80
+ t.is(result.filteredCount, 2);
81
+ t.is(result.totalCount, 3);
82
+ });
83
+
84
+ test('LogStorage: query applies pagination', t => {
85
+ const storage = new LogStorage(100);
86
+
87
+ for (let i = 0; i < 10; i++) {
88
+ storage.addEntry(createLogEntry({message: `Entry ${i}`}));
89
+ }
90
+
91
+ const query: LogQuery = {limit: 3, offset: 2};
92
+ const result = storage.query(query);
93
+
94
+ t.is(result.entries.length, 3);
95
+ t.is(result.filteredCount, 10);
96
+ t.true(result.hasMore);
97
+ });
98
+
99
+ test('LogStorage: query sorts entries', t => {
100
+ const storage = new LogStorage(10);
101
+
102
+ storage.addEntry(createLogEntry({timestamp: '2025-01-03T00:00:00Z'}));
103
+ storage.addEntry(createLogEntry({timestamp: '2025-01-01T00:00:00Z'}));
104
+ storage.addEntry(createLogEntry({timestamp: '2025-01-02T00:00:00Z'}));
105
+
106
+ const query: LogQuery = {sortBy: 'timestamp', sortOrder: 'asc'};
107
+ const result = storage.query(query);
108
+
109
+ t.is(result.entries[0]?.timestamp, '2025-01-01T00:00:00Z');
110
+ t.is(result.entries[1]?.timestamp, '2025-01-02T00:00:00Z');
111
+ t.is(result.entries[2]?.timestamp, '2025-01-03T00:00:00Z');
112
+ });
113
+
114
+ test('LogStorage: query generates facets', t => {
115
+ const storage = new LogStorage(10);
116
+
117
+ storage.addEntry(createLogEntry({level: 'error'}));
118
+ storage.addEntry(createLogEntry({level: 'error'}));
119
+ storage.addEntry(createLogEntry({level: 'info'}));
120
+
121
+ const result = storage.query({});
122
+
123
+ t.truthy(result.facets);
124
+ t.is(result.facets?.levels.error, 2);
125
+ t.is(result.facets?.levels.info, 1);
126
+ });
127
+
128
+ test('LogStorage: aggregate groups by level', t => {
129
+ const storage = new LogStorage(10);
130
+
131
+ storage.addEntry(createLogEntry({level: 'error'}));
132
+ storage.addEntry(createLogEntry({level: 'error'}));
133
+ storage.addEntry(createLogEntry({level: 'info'}));
134
+
135
+ const options: AggregationOptions = {
136
+ groupBy: 'level',
137
+ aggregations: ['count'],
138
+ };
139
+
140
+ const result = storage.aggregate(options);
141
+
142
+ t.is(result.totalGroups, 2);
143
+ t.is(result.groups.error?.count, 2);
144
+ t.is(result.groups.info?.count, 1);
145
+ });
146
+
147
+ test('LogStorage: aggregate calculates avgDuration', t => {
148
+ const storage = new LogStorage(10);
149
+
150
+ storage.addEntry(
151
+ createLogEntry({level: 'info', performance: {duration: 100}}),
152
+ );
153
+ storage.addEntry(
154
+ createLogEntry({level: 'info', performance: {duration: 200}}),
155
+ );
156
+ storage.addEntry(
157
+ createLogEntry({level: 'info', performance: {duration: 300}}),
158
+ );
159
+
160
+ const options: AggregationOptions = {
161
+ groupBy: 'level',
162
+ aggregations: ['avgDuration'],
163
+ };
164
+
165
+ const result = storage.aggregate(options);
166
+
167
+ t.is(result.groups.info?.avgDuration, 200);
168
+ });
169
+
170
+ test('LogStorage: clear removes all entries', t => {
171
+ const storage = new LogStorage(10);
172
+
173
+ storage.addEntry(createLogEntry());
174
+ storage.addEntry(createLogEntry());
175
+ storage.addEntry(createLogEntry());
176
+
177
+ t.is(storage.getEntryCount(), 3);
178
+
179
+ storage.clear();
180
+
181
+ t.is(storage.getEntryCount(), 0);
182
+ t.deepEqual(storage.query({}).entries, []);
183
+ });
184
+
185
+ test('LogStorage: integration test - full workflow', t => {
186
+ const storage = new LogStorage(100);
187
+
188
+ // Add various entries
189
+ storage.addEntry(
190
+ createLogEntry({
191
+ level: 'error',
192
+ message: 'Database error',
193
+ source: 'db-server',
194
+ timestamp: '2025-01-01T10:00:00Z',
195
+ performance: {duration: 1500},
196
+ }),
197
+ );
198
+ storage.addEntry(
199
+ createLogEntry({
200
+ level: 'error',
201
+ message: 'API timeout',
202
+ source: 'api-server',
203
+ timestamp: '2025-01-01T11:00:00Z',
204
+ performance: {duration: 3000},
205
+ }),
206
+ );
207
+ storage.addEntry(
208
+ createLogEntry({
209
+ level: 'info',
210
+ message: 'Request processed',
211
+ source: 'api-server',
212
+ timestamp: '2025-01-01T12:00:00Z',
213
+ performance: {duration: 200},
214
+ }),
215
+ );
216
+
217
+ // Query for errors
218
+ const errorQuery: LogQuery = {
219
+ levels: ['error'],
220
+ sortBy: 'duration',
221
+ sortOrder: 'desc',
222
+ };
223
+ const errorResult = storage.query(errorQuery);
224
+
225
+ t.is(errorResult.entries.length, 2);
226
+ t.is(errorResult.entries[0]?.message, 'API timeout'); // Longest duration
227
+ t.is(errorResult.entries[1]?.message, 'Database error');
228
+
229
+ // Aggregate by source
230
+ const aggOptions: AggregationOptions = {
231
+ groupBy: 'source',
232
+ aggregations: ['count', 'avgDuration'],
233
+ };
234
+ const aggResult = storage.aggregate(aggOptions);
235
+
236
+ t.is(aggResult.totalGroups, 2);
237
+ t.is(aggResult.groups['api-server']?.count, 2);
238
+ t.is(aggResult.groups['db-server']?.count, 1);
239
+ t.is(aggResult.groups['api-server']?.avgDuration, 1600); // (3000 + 200) / 2
240
+ });
241
+
242
+ test('LogStorage: handles wraparound in buffer', t => {
243
+ const storage = new LogStorage(3);
244
+
245
+ storage.addEntry(createLogEntry({message: '1'}));
246
+ storage.addEntry(createLogEntry({message: '2'}));
247
+ storage.addEntry(createLogEntry({message: '3'}));
248
+ storage.addEntry(createLogEntry({message: '4'})); // Should remove '1'
249
+
250
+ const result = storage.query({});
251
+
252
+ t.is(result.entries.length, 3);
253
+ t.is(result.totalCount, 3);
254
+ // First entry should be removed
255
+ t.false(result.entries.some(e => e.message === '1'));
256
+ t.true(result.entries.some(e => e.message === '4'));
257
+ });