@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,198 @@
1
+ /**
2
+ * @fileoverview Commands Component 配置注册测试
3
+ *
4
+ * TDD: 先写测试,验证配置注册机制
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach } from "vitest";
8
+ import os from "os";
9
+ import path from "path";
10
+ import { ConfigComponent } from "../../config/config-component";
11
+ import { CommandsComponent } from "./commands-component";
12
+ import { COMMANDS_CONFIG_REGISTRATION, COMMANDS_DEFAULTS } from "./commands-config-registration";
13
+
14
+ describe("Commands Config Registration", () => {
15
+ let configComponent: ConfigComponent;
16
+ let component: CommandsComponent;
17
+
18
+ beforeEach(() => {
19
+ configComponent = new ConfigComponent();
20
+ component = new CommandsComponent();
21
+ });
22
+
23
+ describe("COMMANDS_CONFIG_REGISTRATION", () => {
24
+ it("应该包含正确的 name", () => {
25
+ expect(COMMANDS_CONFIG_REGISTRATION.name).toBe("command");
26
+ });
27
+
28
+ it("应该包含 env source 配置", () => {
29
+ const envSource = COMMANDS_CONFIG_REGISTRATION.sources.find(
30
+ (s) => s.type === "env"
31
+ );
32
+ expect(envSource).toBeDefined();
33
+ expect(envSource?.envPrefix).toBe("COMMAND");
34
+ expect(envSource?.priority).toBe(20);
35
+ });
36
+
37
+ it("应该包含所有配置 keys", () => {
38
+ const keys = COMMANDS_CONFIG_REGISTRATION.keys;
39
+ expect(keys).toContainEqual(
40
+ expect.objectContaining({ key: "command.userCommandsDir" })
41
+ );
42
+ expect(keys).toContainEqual(
43
+ expect.objectContaining({ key: "command.projectCommandsDir" })
44
+ );
45
+ expect(keys).toContainEqual(
46
+ expect.objectContaining({ key: "command.cacheDir" })
47
+ );
48
+ });
49
+ });
50
+
51
+ describe("COMMANDS_DEFAULTS", () => {
52
+ it("应该包含 userCommandsDir 键(动态默认值在 registerConfig 中设置)", () => {
53
+ expect("command.userCommandsDir" in COMMANDS_DEFAULTS).toBe(true);
54
+ });
55
+
56
+ it("应该包含 projectCommandsDir 键(动态默认值在 registerConfig 中设置)", () => {
57
+ expect("command.projectCommandsDir" in COMMANDS_DEFAULTS).toBe(true);
58
+ });
59
+
60
+ it("应该包含 cacheDir 键(动态默认值在 registerConfig 中设置)", () => {
61
+ expect("command.cacheDir" in COMMANDS_DEFAULTS).toBe(true);
62
+ });
63
+ });
64
+
65
+ describe("配置注册到 ConfigComponent", () => {
66
+ it("应该能够注册 COMMANDS_CONFIG_REGISTRATION", () => {
67
+ configComponent.registerComponent(COMMANDS_CONFIG_REGISTRATION);
68
+ expect(() => configComponent.registerComponent(COMMANDS_CONFIG_REGISTRATION)).not.toThrow();
69
+ });
70
+
71
+ // 注意:defaults 字段已被移除,默认值通过 configComponent.set() 在 registerConfig 中设置
72
+
73
+ it("注册后 keys 应该被注册(默认值需要通过 configComponent.set() 设置)", async () => {
74
+ configComponent.registerComponent(COMMANDS_CONFIG_REGISTRATION);
75
+ await configComponent.load();
76
+
77
+ // 注意:默认值需要通过 configComponent.set() 设置,不会自动加载
78
+ // 但 keys 已注册
79
+ expect(configComponent.get("command.userCommandsDir")).toBeUndefined();
80
+ });
81
+ });
82
+
83
+ describe("Component 配置加载", () => {
84
+ it("应该需要 ConfigComponent 初始化", async () => {
85
+ await expect(
86
+ component.init({
87
+ options: {},
88
+ } as any)
89
+ ).rejects.toThrow("ConfigComponent is required");
90
+ });
91
+
92
+ it("应该能够使用 ConfigComponent 初始化", async () => {
93
+ await component.init({
94
+ options: {
95
+ configComponent,
96
+ },
97
+ } as any);
98
+
99
+ expect(component.name).toBe("commands");
100
+ expect(component.version).toBe("2.0.0");
101
+ });
102
+
103
+ it("应该能够通过 config 对象传入配置", async () => {
104
+ // 使用 tmpdir 作为测试路径
105
+ const tmpDir = os.tmpdir();
106
+
107
+ await component.init({
108
+ options: {
109
+ configComponent,
110
+ config: {
111
+ userCommandsDir: path.join(tmpDir, "test-user-commands"),
112
+ projectCommandsDir: path.join(tmpDir, "test-project-commands"),
113
+ },
114
+ },
115
+ } as any);
116
+
117
+ expect(component.name).toBe("commands");
118
+ });
119
+ });
120
+
121
+ describe("环境变量覆盖", () => {
122
+ it("应该能够通过环境变量覆盖配置", async () => {
123
+ // 设置环境变量(使用有效的 tmp 路径)
124
+ const originalValue = process.env.COMMAND_COMMAND_USER_COMMANDS_DIR;
125
+ const tmpPath = path.join(os.tmpdir(), "test-env-path");
126
+ process.env.COMMAND_COMMAND_USER_COMMANDS_DIR = tmpPath;
127
+
128
+ try {
129
+ await component.init({
130
+ options: {
131
+ configComponent,
132
+ },
133
+ } as any);
134
+
135
+ expect(component.name).toBe("commands");
136
+ } finally {
137
+ // 恢复环境变量
138
+ if (originalValue !== undefined) {
139
+ process.env.COMMAND_COMMAND_USER_COMMANDS_DIR = originalValue;
140
+ } else {
141
+ delete process.env.COMMAND_COMMAND_USER_COMMANDS_DIR;
142
+ }
143
+ }
144
+ });
145
+
146
+ it("环境变量应该能够覆盖默认值", async () => {
147
+ const originalValue = process.env.COMMAND_COMMAND_USER_COMMANDS_DIR;
148
+ const tmpPath = path.join(os.tmpdir(), "env-override-test");
149
+ process.env.COMMAND_COMMAND_USER_COMMANDS_DIR = tmpPath;
150
+
151
+ try {
152
+ // 创建新 component 来使用新的环境变量
153
+ const newComponent = new CommandsComponent();
154
+ await newComponent.init({
155
+ options: {
156
+ configComponent,
157
+ },
158
+ } as any);
159
+
160
+ // 环境变量应该覆盖默认值
161
+ // 注意:在 CommandsComponent.init 中,registerConfig 会在 load 之后再次设置环境变量
162
+ expect(configComponent.get("command.userCommandsDir")).toBe(tmpPath);
163
+ } finally {
164
+ if (originalValue !== undefined) {
165
+ process.env.COMMAND_COMMAND_USER_COMMANDS_DIR = originalValue;
166
+ } else {
167
+ delete process.env.COMMAND_COMMAND_USER_COMMANDS_DIR;
168
+ }
169
+ }
170
+ });
171
+ });
172
+
173
+ describe("ConfigComponent.registerComponent 模式集成", () => {
174
+ it("初始化后 ConfigComponent 应该包含命令配置", async () => {
175
+ await component.init({
176
+ options: {
177
+ configComponent,
178
+ },
179
+ } as any);
180
+
181
+ // 验证 ConfigComponent 有命令相关配置
182
+ const value = configComponent.get("command.userCommandsDir");
183
+ expect(value).toBeDefined();
184
+ expect(typeof value).toBe("string");
185
+ });
186
+
187
+ it("registerComponent 注册后应该能通过 load 获取已配置的 keys", async () => {
188
+ // 直接使用 registerComponent 和 load 验证模式
189
+ configComponent.registerComponent(COMMANDS_CONFIG_REGISTRATION);
190
+ await configComponent.load("command");
191
+
192
+ // 注意:默认值不会自动加载,需要通过 configComponent.set() 设置
193
+ // 验证 keys 已注册(从 ConfigComponent 获取会返回 undefined)
194
+ const userDir = configComponent.get("command.userCommandsDir");
195
+ expect(userDir).toBeUndefined(); // 默认值未设置
196
+ });
197
+ });
198
+ });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @fileoverview Commands Component 配置注册
3
+ *
4
+ * 使用 ConfigComponent.registerComponent() 机制统一管理配置
5
+ */
6
+
7
+ import type { ComponentRegistration } from "../../config/config-component";
8
+
9
+ /**
10
+ * Commands Component 默认配置值(占位,实际值在 registerConfig 中动态设置)
11
+ *
12
+ * 注意:这些默认值在 CommandsComponent.registerConfig() 中
13
+ * 通过 configComponent.set() 设置到 ConfigComponent,使用基于 HOME 的绝对路径
14
+ */
15
+ export const COMMANDS_DEFAULTS: Record<string, unknown> = {
16
+ "command.userCommandsDir": undefined, // 动态设置:${HOME}/.roy-agent/commands
17
+ "command.projectCommandsDir": undefined, // 动态设置:${cwd}/.roy/commands
18
+ "command.cacheDir": undefined, // 动态设置:${HOME}/.cache/roy-agent/commands
19
+ };
20
+
21
+ /**
22
+ * Commands Component 配置注册常量
23
+ *
24
+ * 定义了所有 Commands 相关的配置项和来源
25
+ */
26
+ export const COMMANDS_CONFIG_REGISTRATION: ComponentRegistration = {
27
+ name: "command",
28
+
29
+ sources: [
30
+ { type: "env", envPrefix: "COMMAND", priority: 20, watch: false },
31
+ ],
32
+
33
+ keys: [
34
+ { key: "command.userCommandsDir", sources: ["env", "file"] },
35
+ { key: "command.projectCommandsDir", sources: ["env", "file"] },
36
+ { key: "command.cacheDir", sources: ["env", "file"] },
37
+ ],
38
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @fileoverview Commands Component Module
3
+ *
4
+ * 导出 CommandsComponent 及其类型
5
+ */
6
+
7
+ // Component
8
+ export { CommandsComponent } from "./commands-component";
9
+
10
+ // Types
11
+ export type {
12
+ CommandsComponentOptions,
13
+ CommandsComponentConfig,
14
+ CommandSource,
15
+ CommandIndex,
16
+ ScanResult,
17
+ DiscoverOptions,
18
+ AddCommandOptions,
19
+ RemoveCommandOptions,
20
+ ExecutionResult,
21
+ } from "./types";
@@ -0,0 +1,203 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import fs from "fs/promises";
3
+ import path from "path";
4
+ import os from "os";
5
+ import { parseFrontmatter, parseMetaFile, scanMetaFiles } from "./parser";
6
+
7
+ describe("parser", () => {
8
+ let tempDir: string;
9
+
10
+ beforeEach(async () => {
11
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "roy-commands-parser-test-"));
12
+ });
13
+
14
+ afterEach(async () => {
15
+ await fs.rm(tempDir, { recursive: true, force: true });
16
+ });
17
+
18
+ describe("parseFrontmatter", () => {
19
+ it("should parse simple key-value pairs", () => {
20
+ const text = `name: git
21
+ description: Git version control`;
22
+
23
+ const result = parseFrontmatter(text);
24
+
25
+ expect(result.name).toBe("git");
26
+ expect(result.description).toBe("Git version control");
27
+ });
28
+
29
+ it("should handle quoted values", () => {
30
+ const text = `name: "quoted name"
31
+ description: "with spaces"`;
32
+
33
+ const result = parseFrontmatter(text);
34
+
35
+ expect(result.name).toBe("quoted name");
36
+ expect(result.description).toBe("with spaces");
37
+ });
38
+
39
+ it("should handle empty text", () => {
40
+ const result = parseFrontmatter("");
41
+
42
+ expect(Object.keys(result)).toHaveLength(0);
43
+ });
44
+
45
+ it("should handle values with colons", () => {
46
+ const text = `name: git
47
+ description: Git version control: manage repositories`;
48
+
49
+ const result = parseFrontmatter(text);
50
+
51
+ expect(result.description).toBe("Git version control: manage repositories");
52
+ });
53
+
54
+ it("should handle single quoted values (kept as-is)", () => {
55
+ const text = `name: 'single quoted'
56
+ description: 'with content'`;
57
+
58
+ const result = parseFrontmatter(text);
59
+
60
+ // 当前实现只支持双引号,单引号会被保留
61
+ expect(result.name).toBe("'single quoted'");
62
+ expect(result.description).toBe("'with content'");
63
+ });
64
+
65
+ it("should skip lines without colon", () => {
66
+ const text = `name: git
67
+ this line has no colon
68
+ description: Git`;
69
+
70
+ const result = parseFrontmatter(text);
71
+
72
+ expect(result.name).toBe("git");
73
+ expect(result.description).toBe("Git");
74
+ expect((result as any)["this line has no colon"]).toBeUndefined();
75
+ });
76
+ });
77
+
78
+ describe("parseMetaFile", () => {
79
+ it("should parse valid meta.md file", async () => {
80
+ const metaPath = path.join(tempDir, "meta.md");
81
+ await fs.writeFile(metaPath, `---
82
+ name: git
83
+ description: Git version control
84
+ tips: Use --help to explore
85
+ source: user
86
+ ---
87
+
88
+ # Git Command`);
89
+
90
+ const result = await parseMetaFile(metaPath, "user");
91
+
92
+ expect(result).not.toBeNull();
93
+ expect(result!.name).toBe("git");
94
+ expect(result!.description).toBe("Git version control");
95
+ expect(result!.tips).toBe("Use --help to explore");
96
+ expect(result!.source).toBe("user");
97
+ });
98
+
99
+ it("should return null for missing frontmatter", async () => {
100
+ const metaPath = path.join(tempDir, "meta.md");
101
+ await fs.writeFile(metaPath, `# No frontmatter`);
102
+
103
+ const result = await parseMetaFile(metaPath, "user");
104
+
105
+ expect(result).toBeNull();
106
+ });
107
+
108
+ it("should return null for missing name", async () => {
109
+ const metaPath = path.join(tempDir, "meta.md");
110
+ await fs.writeFile(metaPath, `---
111
+ description: Only description
112
+ ---`);
113
+
114
+ const result = await parseMetaFile(metaPath, "user");
115
+
116
+ expect(result).toBeNull();
117
+ });
118
+
119
+ it("should return null for missing description", async () => {
120
+ const metaPath = path.join(tempDir, "meta.md");
121
+ await fs.writeFile(metaPath, `---
122
+ name: git
123
+ ---`);
124
+
125
+ const result = await parseMetaFile(metaPath, "user");
126
+
127
+ expect(result).toBeNull();
128
+ });
129
+
130
+ it("should handle meta with empty tips", async () => {
131
+ const metaPath = path.join(tempDir, "meta.md");
132
+ await fs.writeFile(metaPath, `---
133
+ name: git
134
+ description: Git version control
135
+ tips:
136
+ ---`);
137
+
138
+ const result = await parseMetaFile(metaPath, "user");
139
+
140
+ expect(result).not.toBeNull();
141
+ expect(result!.name).toBe("git");
142
+ // 空 tips 会被解析为空格(trim 后的结果)
143
+ expect(result!.tips?.trim()).toBe("");
144
+ });
145
+
146
+ it("should handle description with special characters", async () => {
147
+ const metaPath = path.join(tempDir, "meta.md");
148
+ await fs.writeFile(metaPath, `---
149
+ name: docker
150
+ description: Container management - build | run | push images
151
+ ---`);
152
+
153
+ const result = await parseMetaFile(metaPath, "user");
154
+
155
+ expect(result).not.toBeNull();
156
+ expect(result!.description).toBe("Container management - build | run | push images");
157
+ });
158
+ });
159
+
160
+ describe("scanMetaFiles", () => {
161
+ it("should scan meta.md in directory", async () => {
162
+ const metaPath = path.join(tempDir, "meta.md");
163
+ await fs.writeFile(metaPath, `---
164
+ name: git
165
+ description: Git version control
166
+ ---`);
167
+
168
+ const result = await scanMetaFiles(tempDir, "user");
169
+
170
+ expect(result).toHaveLength(1);
171
+ expect(result[0].name).toBe("git");
172
+ expect(result[0].description).toBe("Git version control");
173
+ expect(result[0].source).toBe("user");
174
+ });
175
+
176
+ it("should return empty array for non-existent directory", async () => {
177
+ const result = await scanMetaFiles("/non/existent/path", "user");
178
+
179
+ expect(result).toEqual([]);
180
+ });
181
+
182
+ it("should skip hidden files", async () => {
183
+ const hiddenPath = path.join(tempDir, ".hidden.md");
184
+ await fs.writeFile(hiddenPath, `---
185
+ name: should-not-appear
186
+ description: test
187
+ ---`);
188
+
189
+ const result = await scanMetaFiles(tempDir, "user");
190
+
191
+ expect(result).toHaveLength(0);
192
+ });
193
+
194
+ it("should skip non-meta files", async () => {
195
+ const readmePath = path.join(tempDir, "README.md");
196
+ await fs.writeFile(readmePath, `# Readme`);
197
+
198
+ const result = await scanMetaFiles(tempDir, "user");
199
+
200
+ expect(result).toHaveLength(0);
201
+ });
202
+ });
203
+ });
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @fileoverview Command Meta.md Parser
3
+ *
4
+ * 解析命令目录下的 meta.md 文件,提取 Frontmatter 元信息
5
+ */
6
+
7
+ import fs from "fs/promises";
8
+ import path from "path";
9
+ import { createLogger } from "../log-trace/logger";
10
+ import type { CommandMeta, CommandSource } from "./types";
11
+
12
+ const logger = createLogger("commands-parser");
13
+
14
+ /**
15
+ * 解析 frontmatter 文本
16
+ */
17
+ export function parseFrontmatter(text: string): Record<string, string> {
18
+ const result: Record<string, string> = {};
19
+ const lines = text.split("\n");
20
+
21
+ for (const line of lines) {
22
+ // 匹配 key: value 格式
23
+ const match = line.match(/^(\w+):\s*"?(.+?)"?\s*$/);
24
+ if (match) {
25
+ const key = match[1];
26
+ let value = match[2];
27
+ // 移除首尾引号
28
+ if (value.startsWith('"') && value.endsWith('"')) {
29
+ value = value.slice(1, -1);
30
+ }
31
+ result[key] = value;
32
+ }
33
+ }
34
+
35
+ return result;
36
+ }
37
+
38
+ /**
39
+ * 解析单个 meta.md 文件
40
+ */
41
+ export async function parseMetaFile(
42
+ filePath: string,
43
+ source: CommandSource
44
+ ): Promise<CommandMeta | null> {
45
+ try {
46
+ const content = await fs.readFile(filePath, "utf-8");
47
+
48
+ // 匹配 frontmatter: --- ... ---
49
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n?/);
50
+ if (!frontmatterMatch) {
51
+ logger.warn(`[Parser] Missing frontmatter in: ${filePath}`);
52
+ return null;
53
+ }
54
+
55
+ const frontmatter = parseFrontmatter(frontmatterMatch[1]);
56
+ const name = frontmatter.name;
57
+ const description = frontmatter.description;
58
+
59
+ if (!name) {
60
+ logger.warn(`[Parser] Missing name in frontmatter: ${filePath}`);
61
+ return null;
62
+ }
63
+
64
+ if (!description) {
65
+ logger.warn(`[Parser] Missing description in frontmatter: ${filePath}`);
66
+ return null;
67
+ }
68
+
69
+ return {
70
+ name,
71
+ description,
72
+ tips: frontmatter.tips,
73
+ filePath,
74
+ source,
75
+ };
76
+ } catch (error) {
77
+ logger.error(`[Parser] Failed to parse file: ${filePath}`, error);
78
+ return null;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * 扫描目录下的所有 meta.md 文件
84
+ */
85
+ export async function scanMetaFiles(
86
+ dirPath: string,
87
+ source: CommandSource
88
+ ): Promise<CommandMeta[]> {
89
+ try {
90
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
91
+ const metaList: CommandMeta[] = [];
92
+
93
+ for (const entry of entries) {
94
+ // 跳过隐藏文件和目录
95
+ if (entry.name.startsWith(".")) continue;
96
+
97
+ if (entry.isFile() && entry.name === "meta.md") {
98
+ const metaFilePath = path.join(dirPath, entry.name);
99
+ const meta = await parseMetaFile(metaFilePath, source);
100
+ if (meta) {
101
+ metaList.push(meta);
102
+ }
103
+ }
104
+ }
105
+
106
+ return metaList;
107
+ } catch (error) {
108
+ // 目录不存在时返回空数组
109
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
110
+ return [];
111
+ }
112
+ logger.error(`[Parser] Failed to scan directory: ${dirPath}`, error);
113
+ return [];
114
+ }
115
+ }