@ai-setting/roy-agent-core 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/dist/index.js +99145 -0
  2. package/package.json +114 -0
  3. package/src/config/config-component.test.ts +627 -0
  4. package/src/config/config-component.ts +906 -0
  5. package/src/config/config-parser.test.ts +319 -0
  6. package/src/config/config-parser.ts +203 -0
  7. package/src/config/decentralized-config.test.ts +740 -0
  8. package/src/config/env-key.ts +210 -0
  9. package/src/config/env-source.test.ts +252 -0
  10. package/src/config/env-source.ts +301 -0
  11. package/src/config/file-source.test.ts +357 -0
  12. package/src/config/file-source.ts +421 -0
  13. package/src/config/index.ts +24 -0
  14. package/src/config/protocol-resolver.test.ts +217 -0
  15. package/src/config/protocol-resolver.ts +228 -0
  16. package/src/env/agent/agent-component.abort.test.ts +511 -0
  17. package/src/env/agent/agent-component.record-session.test.ts +349 -0
  18. package/src/env/agent/agent-component.test.ts +1389 -0
  19. package/src/env/agent/agent-component.tool-error.test.ts +327 -0
  20. package/src/env/agent/agent-component.ts +1711 -0
  21. package/src/env/agent/agent-config-registration.test.ts +226 -0
  22. package/src/env/agent/agent-config-registration.ts +46 -0
  23. package/src/env/agent/agent-reminder-plugin.integration.test.ts +243 -0
  24. package/src/env/agent/index.ts +10 -0
  25. package/src/env/agent/summary-agent.parse-hint.test.ts +360 -0
  26. package/src/env/agent/summary-agent.ts +508 -0
  27. package/src/env/agent/types.ts +536 -0
  28. package/src/env/commands/commands-component.test.ts +364 -0
  29. package/src/env/commands/commands-component.ts +604 -0
  30. package/src/env/commands/commands-config-registration.test.ts +198 -0
  31. package/src/env/commands/commands-config-registration.ts +38 -0
  32. package/src/env/commands/index.ts +21 -0
  33. package/src/env/commands/parser.test.ts +203 -0
  34. package/src/env/commands/parser.ts +115 -0
  35. package/src/env/commands/types.ts +184 -0
  36. package/src/env/commands-prompt-integration.test.ts +243 -0
  37. package/src/env/component-env.test.ts +119 -0
  38. package/src/env/component.ts +335 -0
  39. package/src/env/constants.test.ts +72 -0
  40. package/src/env/constants.ts +123 -0
  41. package/src/env/debug/debug-component.test.ts +114 -0
  42. package/src/env/debug/debug-component.ts +547 -0
  43. package/src/env/debug/formatters/index.ts +9 -0
  44. package/src/env/debug/formatters/repl-formatter.test.ts +139 -0
  45. package/src/env/debug/formatters/repl-formatter.ts +358 -0
  46. package/src/env/debug/formatters/trace-formatter.test.ts +119 -0
  47. package/src/env/debug/formatters/trace-formatter.ts +191 -0
  48. package/src/env/debug/formatters/tree-formatter.test.ts +107 -0
  49. package/src/env/debug/formatters/tree-formatter.ts +325 -0
  50. package/src/env/debug/index.ts +38 -0
  51. package/src/env/debug/parser/regex-parser.test.ts +201 -0
  52. package/src/env/debug/parser/regex-parser.ts +196 -0
  53. package/src/env/debug/parser/span-builder.test.ts +241 -0
  54. package/src/env/debug/parser/span-builder.ts +386 -0
  55. package/src/env/debug/reader/log-reader.test.ts +170 -0
  56. package/src/env/debug/reader/log-reader.ts +186 -0
  57. package/src/env/debug/reader/span-db-reader.test.ts +118 -0
  58. package/src/env/debug/reader/span-db-reader.ts +201 -0
  59. package/src/env/debug/types.test.ts +187 -0
  60. package/src/env/debug/types.ts +171 -0
  61. package/src/env/environment-init.test.ts +183 -0
  62. package/src/env/environment-lifecycle.test.ts +516 -0
  63. package/src/env/environment-service.test.ts +332 -0
  64. package/src/env/environment.handle-query.test.ts +96 -0
  65. package/src/env/environment.test.ts +232 -0
  66. package/src/env/environment.ts +708 -0
  67. package/src/env/errors.test.ts +165 -0
  68. package/src/env/errors.ts +157 -0
  69. package/src/env/event-source/event-source-agent-handler.test.ts +193 -0
  70. package/src/env/event-source/event-source-agent-handler.ts +111 -0
  71. package/src/env/event-source/event-source-component.process-cleanup.test.ts +236 -0
  72. package/src/env/event-source/event-source-component.stop.test.ts +346 -0
  73. package/src/env/event-source/event-source-component.test.ts +1207 -0
  74. package/src/env/event-source/event-source-component.ts +1379 -0
  75. package/src/env/event-source/event-source-config-registration.test.ts +242 -0
  76. package/src/env/event-source/event-source-config-registration.ts +37 -0
  77. package/src/env/event-source/event-source-integration.test.ts +320 -0
  78. package/src/env/event-source/event-source-platform.test.ts +630 -0
  79. package/src/env/event-source/types.ts +298 -0
  80. package/src/env/hook/global-hook-manager.ts +162 -0
  81. package/src/env/hook/hook-manager.test.ts +374 -0
  82. package/src/env/hook/hook-manager.ts +309 -0
  83. package/src/env/hook/index.ts +38 -0
  84. package/src/env/hook/types.ts +138 -0
  85. package/src/env/index.ts +144 -0
  86. package/src/env/interface.ts +203 -0
  87. package/src/env/llm/hooks.test.ts +293 -0
  88. package/src/env/llm/hooks.ts +316 -0
  89. package/src/env/llm/index.ts +61 -0
  90. package/src/env/llm/invoke-threshold-check.test.ts +88 -0
  91. package/src/env/llm/invoke-timeout.test.ts +54 -0
  92. package/src/env/llm/invoke.test.ts +71 -0
  93. package/src/env/llm/invoke.ts +1039 -0
  94. package/src/env/llm/llm-config.test.ts +523 -0
  95. package/src/env/llm/llm.test.ts +233 -0
  96. package/src/env/llm/llm.ts +568 -0
  97. package/src/env/llm/provider.test.ts +182 -0
  98. package/src/env/llm/provider.ts +108 -0
  99. package/src/env/llm/transform.test.ts +251 -0
  100. package/src/env/llm/transform.ts +286 -0
  101. package/src/env/llm/types.test.ts +580 -0
  102. package/src/env/llm/types.ts +424 -0
  103. package/src/env/log-trace/decorator-otel.test.ts +182 -0
  104. package/src/env/log-trace/decorator.ts +230 -0
  105. package/src/env/log-trace/index.ts +79 -0
  106. package/src/env/log-trace/log-trace-component.test.ts +242 -0
  107. package/src/env/log-trace/log-trace-component.ts +497 -0
  108. package/src/env/log-trace/log-trace-config-registration.test.ts +348 -0
  109. package/src/env/log-trace/log-trace-config-registration.ts +45 -0
  110. package/src/env/log-trace/logger.test.ts +149 -0
  111. package/src/env/log-trace/logger.ts +522 -0
  112. package/src/env/log-trace/opentelemetry/cli-propagation.test.ts +147 -0
  113. package/src/env/log-trace/opentelemetry/cli-propagation.ts +194 -0
  114. package/src/env/log-trace/opentelemetry/integration.test.ts +668 -0
  115. package/src/env/log-trace/opentelemetry/mod.ts +25 -0
  116. package/src/env/log-trace/opentelemetry/propagation-env.test.ts +181 -0
  117. package/src/env/log-trace/opentelemetry/propagation-env.ts +136 -0
  118. package/src/env/log-trace/opentelemetry/propagation.test.ts +259 -0
  119. package/src/env/log-trace/opentelemetry/propagation.ts +215 -0
  120. package/src/env/log-trace/opentelemetry/tracer-provider-context.test.ts +166 -0
  121. package/src/env/log-trace/opentelemetry/tracer-provider.test.ts +379 -0
  122. package/src/env/log-trace/opentelemetry/tracer-provider.ts +612 -0
  123. package/src/env/log-trace/span-storage.test.ts +145 -0
  124. package/src/env/log-trace/span-storage.ts +230 -0
  125. package/src/env/log-trace/trace-context.test.ts +187 -0
  126. package/src/env/log-trace/trace-context.ts +162 -0
  127. package/src/env/log-trace/types.test.ts +63 -0
  128. package/src/env/log-trace/types.ts +172 -0
  129. package/src/env/mcp/README.md +244 -0
  130. package/src/env/mcp/__integration__/mcp-component.integration.test.ts +373 -0
  131. package/src/env/mcp/config.test.ts +74 -0
  132. package/src/env/mcp/config.ts +116 -0
  133. package/src/env/mcp/index.ts +41 -0
  134. package/src/env/mcp/loader.test.ts +161 -0
  135. package/src/env/mcp/loader.ts +209 -0
  136. package/src/env/mcp/mcp-component.test.ts +111 -0
  137. package/src/env/mcp/mcp-component.ts +358 -0
  138. package/src/env/mcp/mcp-config-registration.test.ts +304 -0
  139. package/src/env/mcp/mcp-config-registration.ts +50 -0
  140. package/src/env/mcp/scanner.test.ts +170 -0
  141. package/src/env/mcp/scanner.ts +246 -0
  142. package/src/env/mcp/tool/adapter.test.ts +520 -0
  143. package/src/env/mcp/tool/adapter.ts +521 -0
  144. package/src/env/mcp/tool/index.ts +5 -0
  145. package/src/env/mcp/types.test.ts +171 -0
  146. package/src/env/mcp/types.ts +79 -0
  147. package/src/env/memory/README.md +177 -0
  148. package/src/env/memory/built-in/index.ts +59 -0
  149. package/src/env/memory/built-in/recall-memory.ts +103 -0
  150. package/src/env/memory/built-in/record-memory.ts +148 -0
  151. package/src/env/memory/index.ts +20 -0
  152. package/src/env/memory/memory-component.test.ts +239 -0
  153. package/src/env/memory/memory-component.ts +503 -0
  154. package/src/env/memory/memory-config-registration.test.ts +67 -0
  155. package/src/env/memory/memory-config-registration.ts +48 -0
  156. package/src/env/memory/memory-config.ts +45 -0
  157. package/src/env/memory/memory-file.test.ts +268 -0
  158. package/src/env/memory/plugin/index.ts +48 -0
  159. package/src/env/memory/plugin/memory-agent.test.ts +249 -0
  160. package/src/env/memory/plugin/memory-agent.ts +365 -0
  161. package/src/env/memory/plugin/memory-manager.ts +198 -0
  162. package/src/env/memory/plugin/memory-plugin-agent.test.ts +145 -0
  163. package/src/env/memory/plugin/memory-plugin.ts +210 -0
  164. package/src/env/memory/plugin/plugin-simplified.test.ts +51 -0
  165. package/src/env/memory/plugin/recall-memory.test.ts +106 -0
  166. package/src/env/memory/plugin/recall-memory.ts +53 -0
  167. package/src/env/memory/plugin/types.ts +101 -0
  168. package/src/env/memory/tools/memory-agent-tools.ts +228 -0
  169. package/src/env/memory/types.ts +85 -0
  170. package/src/env/paths.ts +118 -0
  171. package/src/env/prompt/index.ts +18 -0
  172. package/src/env/prompt/memory-prompts.test.ts +91 -0
  173. package/src/env/prompt/prompt-component.test.ts +491 -0
  174. package/src/env/prompt/prompt-component.ts +619 -0
  175. package/src/env/prompt/prompt-config-registration.test.ts +213 -0
  176. package/src/env/prompt/prompt-config-registration.ts +39 -0
  177. package/src/env/prompt/prompts-index.ts +504 -0
  178. package/src/env/prompt/renderer.ts +67 -0
  179. package/src/env/prompt/types.ts +136 -0
  180. package/src/env/session/hooks.ts +18 -0
  181. package/src/env/session/index.ts +37 -0
  182. package/src/env/session/search-query-parser.test.ts +425 -0
  183. package/src/env/session/search-query-parser.ts +171 -0
  184. package/src/env/session/session-checkpoint.test.ts +523 -0
  185. package/src/env/session/session-component.extract-recent-messages.test.ts +209 -0
  186. package/src/env/session/session-component.test.ts +132 -0
  187. package/src/env/session/session-component.ts +1249 -0
  188. package/src/env/session/session-config-registration.test.ts +138 -0
  189. package/src/env/session/session-config-registration.ts +52 -0
  190. package/src/env/session/session-message-converter.test.ts +763 -0
  191. package/src/env/session/session-message-converter.ts +415 -0
  192. package/src/env/session/session-message-e2e.test.ts +448 -0
  193. package/src/env/session/session-search.test.ts +391 -0
  194. package/src/env/session/session-store.test.ts +362 -0
  195. package/src/env/session/session-store.ts +141 -0
  196. package/src/env/session/storage/index.ts +6 -0
  197. package/src/env/session/storage/memory.ts +502 -0
  198. package/src/env/session/storage/sqlite.ts +794 -0
  199. package/src/env/session/types.ts +742 -0
  200. package/src/env/skill/config.ts +39 -0
  201. package/src/env/skill/index.ts +6 -0
  202. package/src/env/skill/parser.test.ts +116 -0
  203. package/src/env/skill/parser.ts +77 -0
  204. package/src/env/skill/scanner.test.ts +211 -0
  205. package/src/env/skill/scanner.ts +119 -0
  206. package/src/env/skill/skill-component.test.ts +234 -0
  207. package/src/env/skill/skill-component.ts +352 -0
  208. package/src/env/skill/skill-config-registration.test.ts +60 -0
  209. package/src/env/skill/skill-config-registration.ts +43 -0
  210. package/src/env/skill/tool/index.ts +1 -0
  211. package/src/env/skill/tool/skill-tool.test.ts +100 -0
  212. package/src/env/skill/tool/skill-tool.ts +72 -0
  213. package/src/env/skill/types.ts +64 -0
  214. package/src/env/task/delegate/delegate-tool.test.ts +498 -0
  215. package/src/env/task/delegate/delegate-tool.ts +1014 -0
  216. package/src/env/task/delegate/index.ts +18 -0
  217. package/src/env/task/delegate/stop-tool.test.ts +140 -0
  218. package/src/env/task/delegate/stop-tool.ts +119 -0
  219. package/src/env/task/delegate/task-events.test.ts +178 -0
  220. package/src/env/task/delegate/task-events.ts +143 -0
  221. package/src/env/task/hooks/contexts.test.ts +92 -0
  222. package/src/env/task/hooks/contexts.ts +192 -0
  223. package/src/env/task/hooks/index.ts +23 -0
  224. package/src/env/task/hooks/task-hook-points.test.ts +32 -0
  225. package/src/env/task/hooks/task-hook-points.ts +54 -0
  226. package/src/env/task/index.ts +7 -0
  227. package/src/env/task/plugins/index.ts +13 -0
  228. package/src/env/task/plugins/task-plugin.test.ts +74 -0
  229. package/src/env/task/plugins/task-plugin.ts +89 -0
  230. package/src/env/task/plugins/task-tag-plugin.test.ts +377 -0
  231. package/src/env/task/plugins/task-tag-plugin.ts +319 -0
  232. package/src/env/task/plugins/task-workflow-extractor.integration.test.ts +226 -0
  233. package/src/env/task/plugins/workflow-extractor-agent.test.ts +107 -0
  234. package/src/env/task/plugins/workflow-extractor-agent.ts +225 -0
  235. package/src/env/task/storage/index.ts +6 -0
  236. package/src/env/task/storage/sqlite-task-store.test.ts +283 -0
  237. package/src/env/task/storage/sqlite-task-store.ts +903 -0
  238. package/src/env/task/storage/task-search.test.ts +291 -0
  239. package/src/env/task/tag-service.test.ts +198 -0
  240. package/src/env/task/tag-service.ts +264 -0
  241. package/src/env/task/task-component.test.ts +193 -0
  242. package/src/env/task/task-component.ts +658 -0
  243. package/src/env/task/task-config-registration.test.ts +57 -0
  244. package/src/env/task/task-config-registration.ts +37 -0
  245. package/src/env/task/task-types.test.ts +137 -0
  246. package/src/env/task/tools/complete-tool.ts +44 -0
  247. package/src/env/task/tools/create-tool.ts +49 -0
  248. package/src/env/task/tools/delete-tool.ts +43 -0
  249. package/src/env/task/tools/get-tool.ts +59 -0
  250. package/src/env/task/tools/index.ts +10 -0
  251. package/src/env/task/tools/list-tool.ts +40 -0
  252. package/src/env/task/tools/operation/create-tool.ts +48 -0
  253. package/src/env/task/tools/operation/delete-tool.ts +43 -0
  254. package/src/env/task/tools/operation/get-tool.ts +43 -0
  255. package/src/env/task/tools/operation/index.ts +9 -0
  256. package/src/env/task/tools/operation/list-tool.ts +40 -0
  257. package/src/env/task/tools/operation/operation-tools.test.ts +274 -0
  258. package/src/env/task/tools/operation/operation-types.ts +75 -0
  259. package/src/env/task/tools/operation/update-tool.ts +47 -0
  260. package/src/env/task/tools/task-tools.test.ts +203 -0
  261. package/src/env/task/tools/task-types.test.ts +75 -0
  262. package/src/env/task/tools/task-types.ts +68 -0
  263. package/src/env/task/tools/update-tool.ts +70 -0
  264. package/src/env/task/types.ts +160 -0
  265. package/src/env/tool/built-in/bash.ts +201 -0
  266. package/src/env/tool/built-in/echo.ts +29 -0
  267. package/src/env/tool/built-in/edit-file.test.ts +136 -0
  268. package/src/env/tool/built-in/edit-file.ts +92 -0
  269. package/src/env/tool/built-in/glob.test.ts +94 -0
  270. package/src/env/tool/built-in/glob.ts +65 -0
  271. package/src/env/tool/built-in/grep.test.ts +122 -0
  272. package/src/env/tool/built-in/grep.ts +108 -0
  273. package/src/env/tool/built-in/index.ts +44 -0
  274. package/src/env/tool/built-in/read-file.test.ts +84 -0
  275. package/src/env/tool/built-in/read-file.ts +75 -0
  276. package/src/env/tool/built-in/write-file.test.ts +119 -0
  277. package/src/env/tool/built-in/write-file.ts +68 -0
  278. package/src/env/tool/index.ts +24 -0
  279. package/src/env/tool/registry.test.ts +257 -0
  280. package/src/env/tool/registry.ts +167 -0
  281. package/src/env/tool/tool-component.test.ts +559 -0
  282. package/src/env/tool/tool-component.ts +563 -0
  283. package/src/env/tool/tool-config-registration.test.ts +249 -0
  284. package/src/env/tool/tool-config-registration.ts +46 -0
  285. package/src/env/tool/types.ts +267 -0
  286. package/src/env/tool/validator.test.ts +143 -0
  287. package/src/env/tool/validator.ts +44 -0
  288. package/src/env/types.ts +180 -0
  289. package/src/env/workflow/ask-user-tool-registration.test.ts +216 -0
  290. package/src/env/workflow/complex-workflow.integration.test.ts +1900 -0
  291. package/src/env/workflow/decorators/decorator-node.ts +229 -0
  292. package/src/env/workflow/decorators/decorator.test.ts +196 -0
  293. package/src/env/workflow/decorators/edge.ts +82 -0
  294. package/src/env/workflow/decorators/index.ts +31 -0
  295. package/src/env/workflow/decorators/node-as.ts +98 -0
  296. package/src/env/workflow/decorators/workflow.ts +54 -0
  297. package/src/env/workflow/engine/dag-manager.test.ts +570 -0
  298. package/src/env/workflow/engine/dag-manager.ts +594 -0
  299. package/src/env/workflow/engine/engine.ts +1422 -0
  300. package/src/env/workflow/engine/event-bus.test.ts +359 -0
  301. package/src/env/workflow/engine/event-bus.ts +156 -0
  302. package/src/env/workflow/engine/executor-agent-session.test.ts +84 -0
  303. package/src/env/workflow/engine/executor.test.ts +619 -0
  304. package/src/env/workflow/engine/executor.ts +593 -0
  305. package/src/env/workflow/engine/index.ts +24 -0
  306. package/src/env/workflow/engine/node-registry.test.ts +560 -0
  307. package/src/env/workflow/engine/node-registry.ts +289 -0
  308. package/src/env/workflow/engine/resume-removed.test.ts +22 -0
  309. package/src/env/workflow/engine/scheduler.test.ts +715 -0
  310. package/src/env/workflow/engine/scheduler.ts +318 -0
  311. package/src/env/workflow/engine/workflow-engine.test.ts +815 -0
  312. package/src/env/workflow/extractor/workflow-converter.ts +306 -0
  313. package/src/env/workflow/fixtures.ts +380 -0
  314. package/src/env/workflow/index.ts +38 -0
  315. package/src/env/workflow/integration/run-resume-unified.test.ts +186 -0
  316. package/src/env/workflow/integration/service-integration.test.ts +267 -0
  317. package/src/env/workflow/metadata/keys.ts +12 -0
  318. package/src/env/workflow/nodes/agent-component-adapter.test.ts +318 -0
  319. package/src/env/workflow/nodes/agent-component-adapter.ts +448 -0
  320. package/src/env/workflow/nodes/agent-node.test.ts +371 -0
  321. package/src/env/workflow/nodes/agent-node.ts +598 -0
  322. package/src/env/workflow/nodes/ask-user-node.ts +113 -0
  323. package/src/env/workflow/nodes/condition-node.ts +200 -0
  324. package/src/env/workflow/nodes/index.ts +9 -0
  325. package/src/env/workflow/nodes/merge-node.ts +141 -0
  326. package/src/env/workflow/nodes/skill-node.test.ts +253 -0
  327. package/src/env/workflow/nodes/skill-node.ts +393 -0
  328. package/src/env/workflow/nodes/tool-node.test.ts +251 -0
  329. package/src/env/workflow/nodes/tool-node.ts +493 -0
  330. package/src/env/workflow/nodes/workflow-llm-history.test.ts +455 -0
  331. package/src/env/workflow/nodes/workflow-node.test.ts +315 -0
  332. package/src/env/workflow/nodes/workflow-node.ts +311 -0
  333. package/src/env/workflow/service/index.ts +27 -0
  334. package/src/env/workflow/service/registry.test.ts +133 -0
  335. package/src/env/workflow/service/registry.ts +71 -0
  336. package/src/env/workflow/service/workflow-service.test.ts +310 -0
  337. package/src/env/workflow/service/workflow-service.ts +393 -0
  338. package/src/env/workflow/storage/index.ts +28 -0
  339. package/src/env/workflow/storage/mock-repositories.ts +385 -0
  340. package/src/env/workflow/storage/sqlite.test.ts +179 -0
  341. package/src/env/workflow/storage/sqlite.ts +163 -0
  342. package/src/env/workflow/storage/workflow-repo.test.ts +780 -0
  343. package/src/env/workflow/storage/workflow-repo.ts +342 -0
  344. package/src/env/workflow/tools/ask-user-tool.ts +82 -0
  345. package/src/env/workflow/tools/index.ts +26 -0
  346. package/src/env/workflow/tools/run-workflow.test.ts +352 -0
  347. package/src/env/workflow/tools/run-workflow.ts +214 -0
  348. package/src/env/workflow/types/context.ts +18 -0
  349. package/src/env/workflow/types/decorators-types.ts +198 -0
  350. package/src/env/workflow/types/event.test.ts +515 -0
  351. package/src/env/workflow/types/event.ts +193 -0
  352. package/src/env/workflow/types/index.ts +49 -0
  353. package/src/env/workflow/types/run.test.ts +437 -0
  354. package/src/env/workflow/types/run.ts +173 -0
  355. package/src/env/workflow/types/workflow-hil.ts +114 -0
  356. package/src/env/workflow/types/workflow-message.test.ts +138 -0
  357. package/src/env/workflow/types/workflow-message.ts +196 -0
  358. package/src/env/workflow/types/workflow-session.test.ts +95 -0
  359. package/src/env/workflow/types/workflow-session.ts +59 -0
  360. package/src/env/workflow/types/workflow.test.ts +495 -0
  361. package/src/env/workflow/types/workflow.ts +195 -0
  362. package/src/env/workflow/types_compat.ts +51 -0
  363. package/src/env/workflow/utils/create-workflow.ts +47 -0
  364. package/src/env/workflow/utils/execution-state.ts +245 -0
  365. package/src/env/workflow/utils/index.ts +18 -0
  366. package/src/env/workflow/utils/node-registry-helper.ts +58 -0
  367. package/src/env/workflow/utils/recovery-validator.test.ts +460 -0
  368. package/src/env/workflow/utils/recovery-validator.ts +377 -0
  369. package/src/env/workflow/utils/session-parser.test.ts +111 -0
  370. package/src/env/workflow/utils/session-parser.ts +94 -0
  371. package/src/env/workflow/utils/session-recovery.test.ts +334 -0
  372. package/src/env/workflow/utils/session-recovery.ts +188 -0
  373. package/src/env/workflow/utils/template-resolver.test.ts +258 -0
  374. package/src/env/workflow/utils/template-resolver.ts +436 -0
  375. package/src/env/workflow/utils/validation-rules.ts +149 -0
  376. package/src/env/workflow/workflow-component.ts +544 -0
  377. package/src/index.ts +422 -0
  378. package/src/utils/id.ts +21 -0
@@ -0,0 +1,107 @@
1
+ import { describe, test, expect } from 'bun:test';
2
+ import { TreeFormatter } from './tree-formatter';
3
+ import type { TraceTreeNode, TraceEntry } from '../types';
4
+
5
+ describe('TreeFormatter', () => {
6
+ const formatter = new TreeFormatter();
7
+
8
+ const mockRootNode: TraceTreeNode = {
9
+ traceId: 'trace-001',
10
+ function: 'agent.execute',
11
+ startTime: '2026-04-08T10:00:00.000',
12
+ endTime: '2026-04-08T10:00:05.000',
13
+ durationMs: 5000,
14
+ children: [
15
+ {
16
+ traceId: 'trace-001',
17
+ function: 'llm.component.invoke',
18
+ startTime: '2026-04-08T10:00:01.000',
19
+ endTime: '2026-04-08T10:00:03.000',
20
+ durationMs: 2000,
21
+ children: [],
22
+ entry: {} as TraceEntry,
23
+ },
24
+ {
25
+ traceId: 'trace-001',
26
+ function: 'tool.execute',
27
+ startTime: '2026-04-08T10:00:03.000',
28
+ endTime: '2026-04-08T10:00:04.000',
29
+ durationMs: 1000,
30
+ children: [],
31
+ entry: {} as TraceEntry,
32
+ },
33
+ ],
34
+ entry: {} as TraceEntry,
35
+ };
36
+
37
+ test('formatTree - should format tree with proper indentation', () => {
38
+ const result = formatter.formatTree(mockRootNode);
39
+
40
+ // Should show root function
41
+ expect(result).toContain('agent.execute');
42
+ // Should show duration (5s because it's > 1000ms)
43
+ expect(result).toContain('5.00s');
44
+ // Should have tree branch connectors
45
+ expect(result).toContain('├──');
46
+ expect(result).toContain('└──');
47
+ });
48
+
49
+ test('formatTree - should show children with correct markers', () => {
50
+ const result = formatter.formatTree(mockRootNode);
51
+
52
+ // Should show children
53
+ expect(result).toContain('llm.component.invoke');
54
+ expect(result).toContain('tool.execute');
55
+ });
56
+
57
+ test('formatTree - should handle empty children', () => {
58
+ const leafNode: TraceTreeNode = {
59
+ traceId: 'trace-001',
60
+ function: 'leaf.function',
61
+ startTime: '2026-04-08T10:00:00.000',
62
+ children: [],
63
+ entry: {} as TraceEntry,
64
+ };
65
+
66
+ const result = formatter.formatTree(leafNode);
67
+ expect(result).toContain('leaf.function');
68
+ expect(result).not.toContain('children');
69
+ });
70
+
71
+ test('formatTree - should format duration', () => {
72
+ const result = formatter.formatTree(mockRootNode);
73
+
74
+ // Duration should be visible (formatted as seconds for values >= 1000ms)
75
+ expect(result).toContain('5.00s'); // 5000ms
76
+ expect(result).toContain('2.00s'); // 2000ms
77
+ expect(result).toContain('1.00s'); // 1000ms
78
+ });
79
+
80
+ test('formatTrees - should format multiple trees', () => {
81
+ const node2: TraceTreeNode = {
82
+ ...mockRootNode,
83
+ traceId: 'trace-002',
84
+ function: 'another.function',
85
+ };
86
+
87
+ const result = formatter.formatTrees([mockRootNode, node2]);
88
+
89
+ // Should have two separate trees
90
+ expect(result.split('\n\n')).toHaveLength(2);
91
+ expect(result).toContain('agent.execute');
92
+ expect(result).toContain('another.function');
93
+ });
94
+
95
+ test('formatTrees - should handle empty array', () => {
96
+ const result = formatter.formatTrees([]);
97
+ expect(result).toBe('No trace trees');
98
+ });
99
+
100
+ test('toJSON - should output valid JSON', () => {
101
+ const result = formatter.toJSON([mockRootNode]);
102
+ const parsed = JSON.parse(result);
103
+
104
+ expect(parsed).toHaveLength(1);
105
+ expect(parsed[0].function).toBe('agent.execute');
106
+ });
107
+ });
@@ -0,0 +1,325 @@
1
+ /**
2
+ * @fileoverview Tree Formatter
3
+ *
4
+ * Formats trace call trees for console output with:
5
+ * - ANSI color support
6
+ * - Duration display with percentage
7
+ * - Time bar visualization
8
+ * - Proper indentation
9
+ */
10
+
11
+ import type { TraceTreeNode } from '../types';
12
+
13
+ /**
14
+ * ANSI color codes
15
+ */
16
+ const Colors = {
17
+ reset: '\x1b[0m',
18
+ bold: '\x1b[1m',
19
+ dim: '\x1b[2m',
20
+ red: '\x1b[31m',
21
+ green: '\x1b[32m',
22
+ yellow: '\x1b[33m',
23
+ cyan: '\x1b[36m',
24
+ white: '\x1b[37m',
25
+ };
26
+
27
+ /**
28
+ * Apply color to text
29
+ */
30
+ function color(text: string, colorCode: string): string {
31
+ return `${colorCode}${text}${Colors.reset}`;
32
+ }
33
+
34
+ /**
35
+ * Tree drawing characters
36
+ */
37
+ const CHARS = {
38
+ VERTICAL: '│',
39
+ VERTICAL_CONNECTOR: '├──',
40
+ LAST_CONNECTOR: '└──',
41
+ SPACE: ' ',
42
+ BAR: '█',
43
+ EMPTY: '░',
44
+ DASH: '─',
45
+ };
46
+
47
+ /**
48
+ * Options for tree formatting
49
+ */
50
+ export interface TreeFormatOptions {
51
+ /** Show duration percentage (default: true) */
52
+ showPercent?: boolean;
53
+ /** Show time bar (default: false) */
54
+ showTimeBar?: boolean;
55
+ /** Width of time bar (default: 10) */
56
+ barWidth?: number;
57
+ }
58
+
59
+ /**
60
+ * Formats trace call trees for human-readable output
61
+ */
62
+ export class TreeFormatter {
63
+ private options: TreeFormatOptions;
64
+
65
+ constructor(options: TreeFormatOptions = {}) {
66
+ this.options = {
67
+ showPercent: true,
68
+ showTimeBar: false, // Default off, use --bar flag to enable
69
+ barWidth: 10,
70
+ ...options,
71
+ };
72
+ }
73
+
74
+ /**
75
+ * Color function based on percentage
76
+ */
77
+ private colorByPercent(percent: number): string {
78
+ if (percent >= 80) return Colors.red;
79
+ if (percent >= 50) return Colors.yellow;
80
+ if (percent >= 20) return Colors.cyan;
81
+ return Colors.dim;
82
+ }
83
+
84
+ /**
85
+ * Format a single trace tree
86
+ */
87
+ formatTree(node: TraceTreeNode): string {
88
+ const lines: string[] = [];
89
+ const totalDuration = node.durationMs || 0;
90
+ // Use sum of direct children for percentage base (better for virtual root nodes)
91
+ const percentBase = node.children.reduce((sum, c) => sum + (c.durationMs || 0), 0) || totalDuration;
92
+
93
+ // Root node line
94
+ lines.push(this.formatNode(node, totalDuration, percentBase, '', true, true));
95
+
96
+ // Process children recursively
97
+ this.formatChildren(node.children, '', lines, totalDuration, percentBase);
98
+
99
+ return lines.join('\n');
100
+ }
101
+
102
+ /**
103
+ * Format a single node
104
+ */
105
+ private formatNode(
106
+ node: TraceTreeNode,
107
+ totalDuration: number,
108
+ percentBase: number,
109
+ prefix: string,
110
+ isLast: boolean,
111
+ isRoot: boolean
112
+ ): string {
113
+ // Tree connector
114
+ const connector = isRoot ? '' : (isLast ? CHARS.LAST_CONNECTOR : CHARS.VERTICAL_CONNECTOR);
115
+ const prefixStr = isRoot ? '' : prefix;
116
+
117
+ let line = `${prefixStr}${connector} ${node.function}`;
118
+
119
+ // Duration
120
+ if (node.durationMs !== undefined) {
121
+ line += color(` (${this.formatDuration(node.durationMs)})`, Colors.dim);
122
+ }
123
+
124
+ // Percentage - skip for:
125
+ // 1. Virtual root nodes (function is '(root)')
126
+ // 2. Actual root of tree (isRoot=true) - root is 100% by definition
127
+ if (this.options.showPercent && percentBase > 0 && node.durationMs !== undefined &&
128
+ node.function !== '(root)' && !isRoot) {
129
+ const percent = Math.round((node.durationMs / percentBase) * 100);
130
+ const percentStr = ` [${percent}%]`;
131
+ line += color(percentStr, this.colorByPercent(percent));
132
+ }
133
+
134
+ // Time bar - only show for nested spans where totalDuration is meaningful
135
+ if (this.options.showTimeBar && node.durationMs !== undefined && totalDuration > 0 && !isRoot) {
136
+ line += ' ' + this.renderTimeBar(node.durationMs, totalDuration);
137
+ }
138
+
139
+ return isRoot ? color(line, Colors.bold) : line;
140
+ }
141
+
142
+ /**
143
+ * Recursively format children
144
+ */
145
+ private formatChildren(
146
+ children: TraceTreeNode[],
147
+ prefix: string,
148
+ lines: string[],
149
+ totalDuration: number,
150
+ percentBase: number
151
+ ): void {
152
+ children.forEach((child, index) => {
153
+ const isLast = index === children.length - 1;
154
+ const newPrefix = prefix + (isLast ? ' ' : `${CHARS.VERTICAL} `);
155
+
156
+ lines.push(this.formatNode(child, totalDuration, percentBase, prefix, isLast, false));
157
+
158
+ if (child.children.length > 0) {
159
+ this.formatChildren(child.children, newPrefix, lines, totalDuration, percentBase);
160
+ }
161
+ });
162
+ }
163
+
164
+ /**
165
+ * Render a time bar showing relative duration
166
+ */
167
+ private renderTimeBar(duration: number, total: number): string {
168
+ const width = this.options.barWidth || 10;
169
+ const filledWidth = Math.round((duration / total) * width);
170
+ const emptyWidth = width - filledWidth;
171
+
172
+ const bar = CHARS.BAR.repeat(filledWidth) + CHARS.EMPTY.repeat(emptyWidth);
173
+ return color(`[${bar}]`, Colors.dim);
174
+ }
175
+
176
+ /**
177
+ * Format duration in human-readable form
178
+ */
179
+ private formatDuration(ms: number): string {
180
+ if (ms < 1000) {
181
+ return `${ms}ms`;
182
+ } else if (ms < 60000) {
183
+ return `${(ms / 1000).toFixed(2)}s`;
184
+ } else if (ms < 3600000) { // < 1 hour
185
+ const mins = Math.floor(ms / 60000);
186
+ const secs = Math.round((ms % 60000) / 1000);
187
+ return `${mins}m ${secs}s`;
188
+ } else {
189
+ const hours = Math.floor(ms / 3600000);
190
+ const mins = Math.floor((ms % 3600000) / 60000);
191
+ return `${hours}h ${mins}m`;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Format multiple trace trees
197
+ */
198
+ formatTrees(trees: TraceTreeNode[]): string {
199
+ if (trees.length === 0) {
200
+ return 'No trace trees';
201
+ }
202
+
203
+ return trees.map(tree => this.formatTree(tree)).join('\n\n');
204
+ }
205
+
206
+ /**
207
+ * Output as JSON
208
+ */
209
+ toJSON(trees: TraceTreeNode[]): string {
210
+ return JSON.stringify(trees, null, 2);
211
+ }
212
+
213
+ /**
214
+ * Generate a summary table of all spans sorted by duration
215
+ */
216
+ formatSummary(node: TraceTreeNode): string {
217
+ const rows: { func: string; duration: number; percent: number; depth: number }[] = [];
218
+ // For virtual root nodes with multiple children, use the root's own duration
219
+ // which is calculated from children's time span
220
+ const total = node.durationMs || 0;
221
+
222
+ // Calculate sum of direct children durations for percentage base
223
+ const childrenTotal = node.children.reduce((sum, c) => sum + (c.durationMs || 0), 0);
224
+ const percentBase = total > 0 ? total : childrenTotal;
225
+
226
+ const collect = (n: TraceTreeNode, depth: number): void => {
227
+ if (n.durationMs !== undefined) {
228
+ rows.push({
229
+ func: n.function,
230
+ duration: n.durationMs,
231
+ percent: percentBase > 0 ? Math.round((n.durationMs / percentBase) * 100) : 0,
232
+ depth,
233
+ });
234
+ }
235
+ n.children.forEach(child => collect(child, depth + 1));
236
+ };
237
+
238
+ collect(node, 0);
239
+
240
+ // Sort by duration descending
241
+ rows.sort((a, b) => b.duration - a.duration);
242
+
243
+ const lines: string[] = [];
244
+ lines.push(color('\n=== Duration Summary ===', Colors.bold));
245
+ lines.push(color('(sorted by time consumption)\n', Colors.dim));
246
+
247
+ // Table header
248
+ lines.push(color(` ${'─'.repeat(65)}`, Colors.dim));
249
+ lines.push(color(` ${'FUNCTION'.padEnd(35)} ${'TIME'.padEnd(12)} %`, Colors.dim));
250
+ lines.push(color(` ${'─'.repeat(65)}`, Colors.dim));
251
+
252
+ for (const row of rows) {
253
+ const indent = ' '.repeat(row.depth);
254
+ const funcDisplay = row.depth > 0 ? '└─ '.repeat(row.depth) + row.func : row.func;
255
+
256
+ const percentStr = String(row.percent).padStart(3) + '%';
257
+ const percentColor = row.percent >= 50 ? Colors.red :
258
+ row.percent >= 20 ? Colors.yellow :
259
+ Colors.dim;
260
+
261
+ lines.push(
262
+ ` ${indent}${funcDisplay.substring(0, 35).padEnd(35)}${this.formatDuration(row.duration).padEnd(12)} ${color(percentStr, percentColor)}`
263
+ );
264
+ }
265
+
266
+ return lines.join('\n');
267
+ }
268
+
269
+ /**
270
+ * Format tree with timeline visualization
271
+ */
272
+ formatTimeline(node: TraceTreeNode): string {
273
+ const lines: string[] = [];
274
+ const totalDuration = node.durationMs || 0;
275
+
276
+ lines.push(color(`\n=== Timeline: ${node.function} ===`, Colors.bold));
277
+ lines.push(color(`Total: ${this.formatDuration(totalDuration)}\n`, Colors.dim));
278
+
279
+ // Build timeline
280
+ const timeline = this.buildTimeline(node, totalDuration, 0, 0);
281
+ lines.push(...timeline);
282
+
283
+ return lines.join('\n');
284
+ }
285
+
286
+ /**
287
+ * Build timeline visualization with absolute positioning
288
+ */
289
+ private buildTimeline(
290
+ node: TraceTreeNode,
291
+ totalDuration: number,
292
+ absoluteOffset: number,
293
+ depth: number
294
+ ): string[] {
295
+ const lines: string[] = [];
296
+ const width = 40;
297
+
298
+ // Calculate position based on absolute offset
299
+ const startPos = Math.round((absoluteOffset / totalDuration) * width);
300
+ const durationWidth = node.durationMs !== undefined
301
+ ? Math.max(2, Math.round((node.durationMs / totalDuration) * width))
302
+ : 2;
303
+
304
+ // Build the bar with proper positioning
305
+ const bar = ' '.repeat(Math.max(0, startPos)) + CHARS.BAR.repeat(durationWidth);
306
+
307
+ // Format line
308
+ const indent = ' '.repeat(depth);
309
+ const funcName = node.function.length > 25 ? '...' + node.function.slice(-22) : node.function;
310
+ const time = node.durationMs !== undefined ? this.formatDuration(node.durationMs) : '-';
311
+ const percent = node.durationMs !== undefined
312
+ ? ` [${Math.round((node.durationMs / totalDuration) * 100)}%]`
313
+ : '';
314
+ lines.push(`${indent}${funcName.padEnd(25)} ${bar} ${color(time + percent, Colors.dim)}`);
315
+
316
+ // Process children with absolute offset within this node
317
+ let childOffset = absoluteOffset;
318
+ for (const child of node.children) {
319
+ lines.push(...this.buildTimeline(child, totalDuration, childOffset, depth + 1));
320
+ childOffset += child.durationMs || 0;
321
+ }
322
+
323
+ return lines;
324
+ }
325
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @fileoverview Debug Component Index
3
+ *
4
+ * Export all debug-related types and classes.
5
+ */
6
+
7
+ // Types
8
+ export type {
9
+ TraceEntry,
10
+ TraceTreeNode,
11
+ ParserOptions,
12
+ LogDiscoveryOptions,
13
+ ParsedLogLine,
14
+ TraceIdInfo,
15
+ TraceSummary,
16
+ FormatOptions,
17
+ TraceAction,
18
+ LogLevel,
19
+ } from './types';
20
+
21
+ // Data source types (defined in debug-component.ts)
22
+ export type { TraceDataSource, TraceParserOptions } from './debug-component';
23
+
24
+ // Components
25
+ export { DebugComponent } from './debug-component';
26
+
27
+ // Reader
28
+ export { LogReader } from './reader/log-reader';
29
+ export { SpanDbReader } from './reader/span-db-reader';
30
+
31
+ // Parser
32
+ export { RegexParser } from './parser/regex-parser';
33
+ export { SpanBuilder } from './parser/span-builder';
34
+
35
+ // Formatters
36
+ export { TraceFormatter } from './formatters/trace-formatter';
37
+ export { TreeFormatter } from './formatters/tree-formatter';
38
+ export { ReplFormatter } from './formatters/repl-formatter';
@@ -0,0 +1,201 @@
1
+ import { describe, expect, test, beforeEach } from 'bun:test';
2
+ import { RegexParser } from './regex-parser';
3
+
4
+ describe('RegexParser', () => {
5
+ let parser: RegexParser;
6
+
7
+ beforeEach(() => {
8
+ parser = new RegexParser();
9
+ });
10
+
11
+ describe('parseLogLine', () => {
12
+ test('should parse enter trace line', () => {
13
+ const line = '2026-04-08 19:12:36.134 [INFO] [cli/src/bin/roy.js:80752][traced:llm.component.invoke] [TRACE] >>> llm.component.invoke enter: [{\"messages\":[{\"role\":\"user\"}]},{\"providerId\":\"minimax\"}]';
14
+
15
+ const result = parser.parseLogLine(line);
16
+
17
+ expect(result).not.toBeNull();
18
+ expect(result!.timestamp).toBe('2026-04-08T19:12:36.134'); // ISO format with T
19
+ expect(result!.level).toBe('INFO');
20
+ expect(result!.source).toBe('cli/src/bin/roy.js:80752');
21
+ expect(result!.category).toBe('traced:llm.component.invoke');
22
+ expect(result!.action).toBe('>>>');
23
+ expect(result!.method).toBe('llm.component.invoke');
24
+ expect(result!.actionType).toBe('enter');
25
+ });
26
+
27
+ test('should parse quit trace line', () => {
28
+ const line = '2026-04-08 19:12:39.213 [INFO] [cli/src/bin/roy.js:80752][traced:llm.component.invoke] [TRACE] <<< llm.component.invoke quit: {\"output\":{\"content\":\"Hello\"}}';
29
+
30
+ const result = parser.parseLogLine(line);
31
+
32
+ expect(result).not.toBeNull();
33
+ expect(result!.action).toBe('<<<');
34
+ expect(result!.actionType).toBe('quit');
35
+ });
36
+
37
+ test('should parse error trace line', () => {
38
+ const line = '2026-04-08 19:12:39.213 [ERROR] [cli/src/bin/roy.js:80752][traced:llm.component.invoke] [TRACE] !!! llm.component.invoke error: Connection timeout';
39
+
40
+ const result = parser.parseLogLine(line);
41
+
42
+ expect(result).not.toBeNull();
43
+ expect(result!.action).toBe('!!!');
44
+ expect(result!.actionType).toBe('error');
45
+ expect(result!.level).toBe('ERROR');
46
+ });
47
+
48
+ test('should return null for non-trace lines', () => {
49
+ const line = '2026-04-08 19:12:36.134 [INFO] Some regular log message';
50
+
51
+ const result = parser.parseLogLine(line);
52
+
53
+ expect(result).toBeNull();
54
+ });
55
+
56
+ test('should return null for malformed trace lines', () => {
57
+ const line = '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> invalid line';
58
+
59
+ const result = parser.parseLogLine(line);
60
+
61
+ expect(result).toBeNull();
62
+ });
63
+
64
+ test('should parse line with method name', () => {
65
+ // Note: The requestId is extracted separately via extractTraceId
66
+ const line = '2026-04-08 19:12:36.134 [INFO] [cli/src/bin/roy.js:80752][traced:llm.component.invoke] [TRACE] >>> llm.component.invoke enter: [{}]';
67
+
68
+ const result = parser.parseLogLine(line);
69
+
70
+ expect(result).not.toBeNull();
71
+ expect(result!.method).toBe('llm.component.invoke');
72
+ });
73
+ });
74
+
75
+ describe('parseArgs', () => {
76
+ test('should parse JSON array args', () => {
77
+ const raw = '[{\"messages\":[{\"role\":\"user\"}]},{\"providerId\":\"minimax\"}]';
78
+
79
+ const result = parser.parseArgs(raw);
80
+
81
+ expect(Array.isArray(result)).toBe(true);
82
+ expect(result).toHaveLength(2);
83
+ expect(result[0]).toEqual({ messages: [{ role: 'user' }] });
84
+ expect(result[1]).toEqual({ providerId: 'minimax' });
85
+ });
86
+
87
+ test('should parse JSON object args', () => {
88
+ const raw = '{\"name\":\"test\",\"value\":123}';
89
+
90
+ const result = parser.parseArgs(raw);
91
+
92
+ expect(result).toEqual({ name: 'test', value: 123 });
93
+ });
94
+
95
+ test('should parse simple string args', () => {
96
+ const raw = 'simple string argument';
97
+
98
+ const result = parser.parseArgs(raw);
99
+
100
+ expect(result).toBe('simple string argument');
101
+ });
102
+
103
+ test('should handle empty args', () => {
104
+ const raw = '';
105
+
106
+ const result = parser.parseArgs(raw);
107
+
108
+ expect(result).toBeNull();
109
+ });
110
+
111
+ test('should handle malformed JSON gracefully', () => {
112
+ const raw = '{invalid json}';
113
+
114
+ const result = parser.parseArgs(raw);
115
+
116
+ expect(result).toBe(raw); // Return raw string on parse failure
117
+ });
118
+ });
119
+
120
+ describe('isTraceLine', () => {
121
+ test('should return true for trace lines', () => {
122
+ const line = '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> method enter: [{}]';
123
+ expect(parser.isTraceLine(line)).toBe(true);
124
+ });
125
+
126
+ test('should return false for non-trace lines', () => {
127
+ const line = '2026-04-08 19:12:36.134 [INFO] Regular log message';
128
+ expect(parser.isTraceLine(line)).toBe(false);
129
+ });
130
+ });
131
+
132
+ describe('filterByLevel', () => {
133
+ test('should filter by info level', () => {
134
+ const lines = [
135
+ '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> method enter: [{}]',
136
+ '2026-04-08 19:12:36.134 [DEBUG] [TRACE] >>> method enter: [{}]',
137
+ '2026-04-08 19:12:36.134 [ERROR] [TRACE] >>> method enter: [{}]',
138
+ ];
139
+
140
+ const filtered = parser.filterByLevel(lines, 'info');
141
+
142
+ expect(filtered).toHaveLength(1);
143
+ expect(filtered[0]).toContain('[INFO]');
144
+ });
145
+
146
+ test('should return all lines if no level specified', () => {
147
+ const lines = [
148
+ '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> method enter: [{}]',
149
+ '2026-04-08 19:12:36.134 [DEBUG] [TRACE] >>> method enter: [{}]',
150
+ ];
151
+
152
+ const filtered = parser.filterByLevel(lines);
153
+
154
+ expect(filtered).toHaveLength(2);
155
+ });
156
+ });
157
+
158
+ describe('filterByFunction', () => {
159
+ test('should filter by function name', () => {
160
+ const lines = [
161
+ '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> llm.invoke enter: [{}]',
162
+ '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> tool.execute enter: [{}]',
163
+ '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> db.query enter: [{}]',
164
+ ];
165
+
166
+ const filtered = parser.filterByFunction(lines, 'llm');
167
+
168
+ expect(filtered).toHaveLength(1);
169
+ expect(filtered[0]).toContain('llm.invoke');
170
+ });
171
+
172
+ test('should return all lines if no function specified', () => {
173
+ const lines = [
174
+ '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> llm.invoke enter: [{}]',
175
+ '2026-04-08 19:12:36.134 [INFO] [TRACE] >>> tool.execute enter: [{}]',
176
+ ];
177
+
178
+ const filtered = parser.filterByFunction(lines);
179
+
180
+ expect(filtered).toHaveLength(2);
181
+ });
182
+ });
183
+
184
+ describe('extractTraceId', () => {
185
+ test('should extract traceId from category', () => {
186
+ const line = '2026-04-08 19:12:36.134 [INFO] [source][requestId=req_123] [TRACE] >>> method enter: [{}]';
187
+
188
+ const traceId = parser.extractTraceId(line);
189
+
190
+ expect(traceId).toBe('req_123');
191
+ });
192
+
193
+ test('should return null if no traceId found', () => {
194
+ const line = '2026-04-08 19:12:36.134 [INFO] [source] [TRACE] >>> method enter: [{}]';
195
+
196
+ const traceId = parser.extractTraceId(line);
197
+
198
+ expect(traceId).toBeNull();
199
+ });
200
+ });
201
+ });