@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,377 @@
1
+ /**
2
+ * RecoveryValidator - 分层恢复验证框架
3
+ *
4
+ * 遵循保守策略,严格验证状态完整性
5
+ */
6
+
7
+ import { TracedAs } from '../../log-trace/decorator';
8
+ import { WorkflowDefinition } from '../types';
9
+ import { SessionMessage } from '../../session/types';
10
+ import {
11
+ ValidationError,
12
+ ValidationResult,
13
+ RecoveryPlan,
14
+ ValidationErrorType,
15
+ SuggestedAction,
16
+ } from './validation-rules';
17
+ import { ExecutionStateBuilder } from './execution-state';
18
+ import type { ExecutionState } from './validation-rules';
19
+
20
+ /**
21
+ * RecoveryValidator - 分层恢复验证框架
22
+ *
23
+ * 遵循保守策略,严格验证状态完整性
24
+ */
25
+ export class RecoveryValidator {
26
+ private stateBuilder: ExecutionStateBuilder;
27
+
28
+ constructor() {
29
+ this.stateBuilder = new ExecutionStateBuilder();
30
+ }
31
+
32
+ @TracedAs("recovery.validator.validate", { recordParams: true, recordResult: true, log: true })
33
+ async validate(
34
+ messages: SessionMessage[],
35
+ definition: WorkflowDefinition
36
+ ): Promise<ValidationResult> {
37
+ // 构建执行状态
38
+ const state = this.stateBuilder.build(messages, definition);
39
+
40
+ const errors: ValidationError[] = [];
41
+ const warnings: string[] = [];
42
+
43
+ // 1. 状态完整性验证
44
+ errors.push(...this.validateStateIntegrity(state, definition));
45
+
46
+ // 2. 并行分支验证
47
+ errors.push(...this.validateParallelBranches(state, definition));
48
+
49
+ // 3. 条件分支验证
50
+ errors.push(...this.validateConditionBranches(state, definition));
51
+
52
+ // 4. 循环状态验证
53
+ errors.push(...this.validateLoopState(state, definition));
54
+
55
+ // 5. 嵌套 Workflow 验证
56
+ errors.push(...this.validateNestedWorkflows(state, definition));
57
+
58
+ return {
59
+ isValid: errors.length === 0,
60
+ errors,
61
+ warnings,
62
+ };
63
+ }
64
+
65
+ @TracedAs("recovery.generate.plan", { recordParams: true, recordResult: true, log: true })
66
+ async generatePlan(
67
+ messages: SessionMessage[],
68
+ definition: WorkflowDefinition
69
+ ): Promise<RecoveryPlan> {
70
+ const state = this.stateBuilder.build(messages, definition);
71
+ const validationResult = await this.validate(messages, definition);
72
+
73
+ const pendingNodes = Array.from(state.pendingNodes);
74
+ const completedNodes = Array.from(state.completedNodes);
75
+
76
+ // 确定恢复点
77
+ const resumePoint = this.determineResumePoint(state, definition);
78
+
79
+ // 生成摘要
80
+ const summary = this.generateSummary(state, validationResult);
81
+
82
+ return {
83
+ canResume: validationResult.isValid,
84
+ resumePoint,
85
+ completedNodes,
86
+ pendingNodes,
87
+ skippedNodes: [],
88
+ validationErrors: validationResult.errors,
89
+ summary,
90
+ };
91
+ }
92
+
93
+ // === 私有验证方法 ===
94
+
95
+ @TracedAs("recovery.validator.validateStateIntegrity", { recordParams: true, recordResult: true, log: true })
96
+ private validateStateIntegrity(
97
+ state: ExecutionState,
98
+ definition: WorkflowDefinition
99
+ ): ValidationError[] {
100
+ const errors: ValidationError[] = [];
101
+
102
+ // 检查待执行节点的变量依赖
103
+ for (const nodeId of state.pendingNodes) {
104
+ const node = definition.nodes?.find(n => n.id === nodeId);
105
+ if (!node?.config) continue;
106
+
107
+ // 解析输入中的变量引用 {{var}}
108
+ const variableRefs = this.extractVariableRefs(node.config);
109
+
110
+ for (const varRef of variableRefs) {
111
+ if (!state.nodeOutputs.has(varRef) && !state.variables.has(varRef)) {
112
+ errors.push({
113
+ type: ValidationErrorType.MISSING_VARIABLE,
114
+ nodeId,
115
+ description: `变量 ${varRef} 不存在,需要重新运行`,
116
+ suggestedAction: SuggestedAction.RE_RUN,
117
+ context: { variable: varRef, nodeConfig: node.config },
118
+ });
119
+ }
120
+ }
121
+ }
122
+
123
+ return errors;
124
+ }
125
+
126
+ @TracedAs("recovery.validator.validateParallel", { recordParams: true, recordResult: true, log: true })
127
+ private validateParallelBranches(
128
+ state: ExecutionState,
129
+ definition: WorkflowDefinition
130
+ ): ValidationError[] {
131
+ const errors: ValidationError[] = [];
132
+
133
+ // 识别并行分支(同一个 source,多个 target)
134
+ const parallelGroups = this.identifyParallelGroups(definition);
135
+
136
+ for (const group of parallelGroups) {
137
+ const completedInGroup = group.filter(id => state.completedNodes.has(id));
138
+ const inProgressInGroup = group.filter(id => state.inProgressNodes.has(id));
139
+
140
+ // 如果有节点正在执行或未完成
141
+ if (inProgressInGroup.length > 0 || completedInGroup.length < group.length) {
142
+ // 检查合并节点是否应该等待
143
+ const mergeNode = this.findMergeNodeForParallel(group, definition);
144
+
145
+ if (mergeNode && !state.completedNodes.has(mergeNode)) {
146
+ const incomplete = group.filter(id => !state.completedNodes.has(id));
147
+ errors.push({
148
+ type: ValidationErrorType.INCOMPLETE_PARALLEL,
149
+ nodeId: mergeNode,
150
+ description: `并行分支 ${incomplete.join(', ')} 未完成`,
151
+ suggestedAction: SuggestedAction.RE_RUN,
152
+ context: { incompleteBranches: incomplete, mergeNode },
153
+ });
154
+ }
155
+ }
156
+ }
157
+
158
+ return errors;
159
+ }
160
+
161
+ @TracedAs("recovery.validator.validateCondition", { recordParams: true, recordResult: true, log: true })
162
+ private validateConditionBranches(
163
+ state: ExecutionState,
164
+ definition: WorkflowDefinition
165
+ ): ValidationError[] {
166
+ const errors: ValidationError[] = [];
167
+
168
+ // 查找有条件边的节点
169
+ const edges = (definition as any).edges || (definition as any).connections || [];
170
+ const conditionalEdges = edges.filter((e: any) => e.condition);
171
+
172
+ for (const edge of conditionalEdges) {
173
+ // 检查条件表达式中的变量是否存在
174
+ const conditionVars = this.extractVariableRefs(edge.condition);
175
+
176
+ for (const varRef of conditionVars) {
177
+ if (!state.nodeOutputs.has(varRef) && !state.variables.has(varRef)) {
178
+ errors.push({
179
+ type: ValidationErrorType.AMBIGUOUS_BRANCH,
180
+ nodeId: edge.target || edge.to,
181
+ description: `条件分支无法确定:变量 ${varRef} 不存在`,
182
+ suggestedAction: SuggestedAction.CONFIRM,
183
+ context: { variable: varRef, condition: edge.condition },
184
+ });
185
+ }
186
+ }
187
+ }
188
+
189
+ return errors;
190
+ }
191
+
192
+ @TracedAs("recovery.validator.validateLoop", { recordParams: true, recordResult: true, log: true })
193
+ private validateLoopState(
194
+ state: ExecutionState,
195
+ definition: WorkflowDefinition
196
+ ): ValidationError[] {
197
+ const errors: ValidationError[] = [];
198
+
199
+ // 识别循环结构(回边)
200
+ const loops = this.identifyLoops(definition);
201
+
202
+ for (const loop of loops) {
203
+ // 检查循环计数器是否保持
204
+ const loopCounter = `loop_count_${loop.header}`;
205
+
206
+ if (!state.nodeOutputs.has(loopCounter) && state.pendingNodes.has(loop.header)) {
207
+ errors.push({
208
+ type: ValidationErrorType.LOOP_STATE_LOST,
209
+ nodeId: loop.header,
210
+ description: `循环状态丢失,循环计数器 ${loopCounter} 不存在`,
211
+ suggestedAction: SuggestedAction.RE_RUN,
212
+ context: { loopHeader: loop.header },
213
+ });
214
+ }
215
+ }
216
+
217
+ return errors;
218
+ }
219
+
220
+ @TracedAs("recovery.validator.validateNested", { recordParams: true, recordResult: true, log: true })
221
+ private validateNestedWorkflows(
222
+ state: ExecutionState,
223
+ definition: WorkflowDefinition
224
+ ): ValidationError[] {
225
+ const errors: ValidationError[] = [];
226
+
227
+ // 查找 workflow 节点
228
+ const workflowNodes = (definition.nodes || []).filter(n => n.type === 'workflow');
229
+
230
+ for (const node of workflowNodes) {
231
+ const nodeOutput = state.nodeOutputs.get(node.id) as Record<string, unknown> | undefined;
232
+ const subSessionId = nodeOutput?.sessionId as string | undefined;
233
+
234
+ if (subSessionId && state.pendingNodes.has(node.id)) {
235
+ // TODO: 检查子 session 状态 - 需要集成 SessionComponent
236
+ // This requires integration with SessionComponent to check sub-session status
237
+ }
238
+ }
239
+
240
+ return errors;
241
+ }
242
+
243
+ // === 辅助方法 ===
244
+
245
+ private extractVariableRefs(obj: unknown): string[] {
246
+ const refs: string[] = [];
247
+ if (!obj) return refs;
248
+
249
+ const str = JSON.stringify(obj);
250
+ const regex = /\{\{([^}]+)\}\}/g;
251
+ let match;
252
+ while ((match = regex.exec(str)) !== null) {
253
+ refs.push(match[1].trim());
254
+ }
255
+ return refs;
256
+ }
257
+
258
+ private identifyParallelGroups(definition: WorkflowDefinition): string[][] {
259
+ // 识别并行分支
260
+ const groups: string[][] = [];
261
+ const sources = new Map<string, string[]>();
262
+
263
+ const edges = (definition as any).edges || (definition as any).connections || [];
264
+
265
+ for (const edge of edges) {
266
+ const source = edge.source || edge.from;
267
+ const target = edge.target || edge.to;
268
+ const targets = sources.get(source) || [];
269
+ targets.push(target);
270
+ sources.set(source, targets);
271
+ }
272
+
273
+ for (const [_source, targets] of sources) {
274
+ if (targets.length > 1) {
275
+ groups.push(targets);
276
+ }
277
+ }
278
+
279
+ return groups;
280
+ }
281
+
282
+ private findMergeNodeForParallel(parallelIds: string[], definition: WorkflowDefinition): string | null {
283
+ // 找到汇聚节点
284
+ const edges = (definition as any).edges || (definition as any).connections || [];
285
+
286
+ for (const edge of edges) {
287
+ const target = edge.target || edge.to;
288
+ const source = edge.source || edge.from;
289
+ const allSourcesFromParallel = parallelIds.includes(source);
290
+ const hasIncomingFromParallel = parallelIds.some(id =>
291
+ edges.some((e: any) => (e.source || e.from) === id && (e.target || e.to) === target)
292
+ );
293
+
294
+ if (allSourcesFromParallel && hasIncomingFromParallel) {
295
+ return target;
296
+ }
297
+ }
298
+
299
+ return null;
300
+ }
301
+
302
+ private identifyLoops(definition: WorkflowDefinition): { header: string; body: string[] }[] {
303
+ // 简化实现:查找回边
304
+ const loops: { header: string; body: string[] }[] = [];
305
+ const visited = new Set<string>();
306
+ const recStack = new Set<string>();
307
+
308
+ const edges = (definition as any).edges || (definition as any).connections || [];
309
+
310
+ const getChildren = (nodeId: string): string[] => {
311
+ return edges
312
+ .filter((e: any) => (e.source || e.from) === nodeId)
313
+ .map((e: any) => e.target || e.to);
314
+ };
315
+
316
+ const dfs = (nodeId: string, path: string[]): void => {
317
+ visited.add(nodeId);
318
+ recStack.add(nodeId);
319
+
320
+ const outgoing = getChildren(nodeId);
321
+ for (const childId of outgoing) {
322
+ if (!visited.has(childId)) {
323
+ dfs(childId, [...path, childId]);
324
+ } else if (recStack.has(childId)) {
325
+ // 发现回边
326
+ const loopStart = path.indexOf(childId);
327
+ if (loopStart !== -1) {
328
+ loops.push({
329
+ header: childId,
330
+ body: path.slice(loopStart),
331
+ });
332
+ }
333
+ }
334
+ }
335
+
336
+ recStack.delete(nodeId);
337
+ };
338
+
339
+ for (const node of definition.nodes || []) {
340
+ if (!visited.has(node.id)) {
341
+ dfs(node.id, [node.id]);
342
+ }
343
+ }
344
+
345
+ return loops;
346
+ }
347
+
348
+ private determineResumePoint(state: ExecutionState, definition: WorkflowDefinition): string {
349
+ // 优先从中断节点恢复
350
+ const inProgress = Array.from(state.inProgressNodes);
351
+ if (inProgress.length > 0) {
352
+ return inProgress[0];
353
+ }
354
+
355
+ // 否则从第一个待执行节点恢复
356
+ const pending = Array.from(state.pendingNodes);
357
+ if (pending.length > 0) {
358
+ return pending[0];
359
+ }
360
+
361
+ // 返回 entry
362
+ const entry = definition.entry;
363
+ if (Array.isArray(entry)) {
364
+ return entry[0] || '';
365
+ }
366
+ return entry || '';
367
+ }
368
+
369
+ private generateSummary(state: ExecutionState, result: ValidationResult): string {
370
+ if (result.isValid) {
371
+ return `恢复验证通过。已完成 ${state.completedNodes.size} 个节点,待执行 ${state.pendingNodes.size} 个节点。`;
372
+ }
373
+
374
+ const errorTypes = result.errors.map(e => e.type).join(', ');
375
+ return `恢复验证失败:${errorTypes}。${result.errors.length} 个错误需要处理。`;
376
+ }
377
+ }
@@ -0,0 +1,111 @@
1
+ import { describe, it, expect } from 'bun:test';
2
+ import {
3
+ findLastInterruptMessage,
4
+ parseNodeOutputs,
5
+ getNextPendingNode,
6
+ getAgentSessionIdFromInterrupt,
7
+ isWaitingForUser,
8
+ } from './session-parser';
9
+ import type { SessionMessage } from '../../session/types';
10
+
11
+ describe('session-parser', () => {
12
+ const createMessage = (metadata: any, content = '{}'): SessionMessage => ({
13
+ id: `msg_${Math.random()}`,
14
+ sessionID: 'workflow_test',
15
+ role: 'user' as any,
16
+ content,
17
+ timestamp: Date.now(),
18
+ metadata,
19
+ });
20
+
21
+ describe('findLastInterruptMessage', () => {
22
+ it('should return last interrupt message', () => {
23
+ const messages: SessionMessage[] = [
24
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n1' }),
25
+ createMessage({ type: 'workflow.node.result', workflowNodeId: 'n1' }),
26
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n2' }),
27
+ createMessage({ type: 'workflow.node.interrupt', workflowNodeId: 'n2', query: 'Q1' }),
28
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n3' }),
29
+ createMessage({ type: 'workflow.node.interrupt', workflowNodeId: 'n3', query: 'Q2' }),
30
+ ];
31
+
32
+ const result = findLastInterruptMessage(messages);
33
+ expect(result?.metadata?.workflowNodeId).toBe('n3');
34
+ });
35
+
36
+ it('should return null if no interrupt', () => {
37
+ const messages: SessionMessage[] = [
38
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n1' }),
39
+ createMessage({ type: 'workflow.node.result', workflowNodeId: 'n1' }),
40
+ ];
41
+
42
+ expect(findLastInterruptMessage(messages)).toBeNull();
43
+ });
44
+ });
45
+
46
+ describe('parseNodeOutputs', () => {
47
+ it('should parse all node outputs', () => {
48
+ const messages: SessionMessage[] = [
49
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n1' }),
50
+ createMessage({ type: 'workflow.node.result', workflowNodeId: 'n1' }, '{"result":"output1"}'),
51
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n2' }),
52
+ createMessage({ type: 'workflow.node.result', workflowNodeId: 'n2' }, '{"result":"output2"}'),
53
+ ];
54
+
55
+ const outputs = parseNodeOutputs(messages);
56
+ expect(outputs.get('n1')).toEqual({ result: 'output1' });
57
+ expect(outputs.get('n2')).toEqual({ result: 'output2' });
58
+ });
59
+ });
60
+
61
+ describe('getNextPendingNode', () => {
62
+ it('should return last incomplete node', () => {
63
+ const messages: SessionMessage[] = [
64
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n1' }),
65
+ createMessage({ type: 'workflow.node.result', workflowNodeId: 'n1' }, '{"o":"1"}'),
66
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n2' }),
67
+ // n2 没有 result,所以是 pending
68
+ ];
69
+
70
+ expect(getNextPendingNode(messages)).toBe('n2');
71
+ });
72
+ });
73
+
74
+ describe('getAgentSessionIdFromInterrupt', () => {
75
+ it('should return agentSessionId from interrupt', () => {
76
+ const msg = createMessage({
77
+ type: 'workflow.node.interrupt',
78
+ workflowNodeId: 'n1',
79
+ agentSessionId: 'agent_123',
80
+ });
81
+
82
+ expect(getAgentSessionIdFromInterrupt(msg)).toBe('agent_123');
83
+ });
84
+
85
+ it('should return undefined if not interrupt', () => {
86
+ const msg = createMessage({ type: 'workflow.node.call' });
87
+ expect(getAgentSessionIdFromInterrupt(msg)).toBeUndefined();
88
+ });
89
+ });
90
+
91
+ describe('isWaitingForUser', () => {
92
+ it('should return true if interrupt without resume', () => {
93
+ const messages: SessionMessage[] = [
94
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n1' }),
95
+ createMessage({ type: 'workflow.node.interrupt', workflowNodeId: 'n1' }),
96
+ ];
97
+
98
+ expect(isWaitingForUser(messages)).toBe(true);
99
+ });
100
+
101
+ it('should return false if resume exists', () => {
102
+ const messages: SessionMessage[] = [
103
+ createMessage({ type: 'workflow.node.call', workflowNodeId: 'n1' }),
104
+ createMessage({ type: 'workflow.node.interrupt', workflowNodeId: 'n1' }),
105
+ createMessage({ type: 'workflow.node.resume' }),
106
+ ];
107
+
108
+ expect(isWaitingForUser(messages)).toBe(false);
109
+ });
110
+ });
111
+ });
@@ -0,0 +1,94 @@
1
+ import type { SessionMessage } from '../../session/types';
2
+ import type {
3
+ WorkflowNodeCallMetadata,
4
+ WorkflowNodeInterruptMetadata,
5
+ } from '../types/workflow-message';
6
+
7
+ /**
8
+ * 查找最后一个 workflow.node.interrupt 消息
9
+ */
10
+ export function findLastInterruptMessage(
11
+ messages: SessionMessage[]
12
+ ): SessionMessage | null {
13
+ const interrupts = messages.filter(
14
+ m => (m.metadata as any)?.type === 'workflow.node.interrupt'
15
+ );
16
+ return interrupts[interrupts.length - 1] || null;
17
+ }
18
+
19
+ /**
20
+ * 解析节点输出
21
+ */
22
+ export function parseNodeOutputs(
23
+ messages: SessionMessage[]
24
+ ): Map<string, unknown> {
25
+ const outputs = new Map<string, unknown>();
26
+ let lastCallNodeId: string | null = null;
27
+
28
+ for (const msg of messages) {
29
+ if ((msg.metadata as any)?.type === 'workflow.node.call') {
30
+ const metadata = msg.metadata as unknown as WorkflowNodeCallMetadata;
31
+ lastCallNodeId = metadata.workflowNodeId;
32
+ } else if ((msg.metadata as any)?.type === 'workflow.node.result') {
33
+ if (lastCallNodeId) {
34
+ try {
35
+ outputs.set(lastCallNodeId, JSON.parse(msg.content));
36
+ } catch {
37
+ outputs.set(lastCallNodeId, msg.content);
38
+ }
39
+ }
40
+ lastCallNodeId = null;
41
+ }
42
+ }
43
+
44
+ return outputs;
45
+ }
46
+
47
+ /**
48
+ * 获取下一个待执行的节点
49
+ */
50
+ export function getNextPendingNode(
51
+ messages: SessionMessage[]
52
+ ): string | null {
53
+ const outputs = parseNodeOutputs(messages);
54
+ const completedNodes = new Set(outputs.keys());
55
+
56
+ for (let i = messages.length - 1; i >= 0; i--) {
57
+ const msg = messages[i];
58
+ if ((msg.metadata as any)?.type === 'workflow.node.call') {
59
+ const metadata = msg.metadata as unknown as WorkflowNodeCallMetadata;
60
+ const nodeId = metadata.workflowNodeId;
61
+ if (!completedNodes.has(nodeId)) {
62
+ return nodeId;
63
+ }
64
+ }
65
+ }
66
+
67
+ return null;
68
+ }
69
+
70
+ /**
71
+ * 从 interrupt 消息获取 agentSessionId
72
+ */
73
+ export function getAgentSessionIdFromInterrupt(
74
+ interruptMessage: SessionMessage
75
+ ): string | undefined {
76
+ if ((interruptMessage.metadata as any)?.type === 'workflow.node.interrupt') {
77
+ const metadata = interruptMessage.metadata as unknown as WorkflowNodeInterruptMetadata;
78
+ return metadata.agentSessionId;
79
+ }
80
+ return undefined;
81
+ }
82
+
83
+ /**
84
+ * 检查 session 是否在等待用户
85
+ */
86
+ export function isWaitingForUser(messages: SessionMessage[]): boolean {
87
+ const lastInterrupt = findLastInterruptMessage(messages);
88
+ if (!lastInterrupt) return false;
89
+
90
+ const interruptIndex = messages.indexOf(lastInterrupt);
91
+ const afterInterrupt = messages.slice(interruptIndex + 1);
92
+
93
+ return !afterInterrupt.some(m => (m.metadata as any)?.type === 'workflow.node.resume');
94
+ }