@pikku/core 0.11.2 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (436) hide show
  1. package/CHANGELOG.md +57 -2
  2. package/dist/crypto-utils.d.ts +2 -0
  3. package/dist/crypto-utils.js +78 -0
  4. package/dist/errors/errors.d.ts +14 -0
  5. package/dist/errors/errors.js +26 -0
  6. package/dist/errors/index.d.ts +1 -1
  7. package/dist/errors/index.js +1 -1
  8. package/dist/function/function-runner.d.ts +10 -4
  9. package/dist/function/function-runner.js +126 -45
  10. package/dist/function/functions.types.d.ts +32 -87
  11. package/dist/function/functions.types.js +16 -46
  12. package/dist/function/index.d.ts +2 -2
  13. package/dist/function/index.js +1 -2
  14. package/dist/handle-error.d.ts +2 -2
  15. package/dist/handle-error.js +3 -12
  16. package/dist/index.d.ts +30 -26
  17. package/dist/index.js +19 -29
  18. package/dist/internal.d.ts +3 -0
  19. package/dist/internal.js +2 -0
  20. package/dist/middleware/auth-apikey.d.ts +2 -2
  21. package/dist/middleware/auth-apikey.js +3 -3
  22. package/dist/middleware/auth-bearer.d.ts +3 -3
  23. package/dist/middleware/auth-bearer.js +4 -7
  24. package/dist/middleware/auth-cookie.d.ts +4 -4
  25. package/dist/middleware/auth-cookie.js +7 -9
  26. package/dist/middleware/cors.d.ts +46 -0
  27. package/dist/middleware/cors.js +81 -0
  28. package/dist/middleware/index.d.ts +5 -3
  29. package/dist/middleware/index.js +5 -3
  30. package/dist/middleware/remote-auth.d.ts +5 -0
  31. package/dist/middleware/remote-auth.js +55 -0
  32. package/dist/middleware/timeout.d.ts +2 -2
  33. package/dist/middleware-runner.d.ts +1 -1
  34. package/dist/middleware-runner.js +8 -10
  35. package/dist/permissions.d.ts +2 -2
  36. package/dist/permissions.js +11 -15
  37. package/dist/pikku-state.d.ts +10 -8
  38. package/dist/pikku-state.js +48 -25
  39. package/dist/schema.d.ts +4 -4
  40. package/dist/schema.js +20 -15
  41. package/dist/services/ai-agent-runner-service.d.ts +43 -0
  42. package/dist/services/ai-agent-runner-service.js +1 -0
  43. package/dist/services/ai-run-state-service.d.ts +13 -0
  44. package/dist/services/ai-run-state-service.js +1 -0
  45. package/dist/services/ai-storage-service.d.ts +18 -0
  46. package/dist/services/ai-storage-service.js +1 -0
  47. package/dist/services/content-service.d.ts +6 -0
  48. package/dist/services/deployment-service.d.ts +19 -0
  49. package/dist/services/deployment-service.js +1 -0
  50. package/dist/services/gopass-secrets.d.ts +47 -0
  51. package/dist/services/gopass-secrets.js +97 -0
  52. package/dist/services/in-memory-ai-run-state-service.d.ts +15 -0
  53. package/dist/services/in-memory-ai-run-state-service.js +44 -0
  54. package/dist/services/in-memory-trigger-service.d.ts +22 -0
  55. package/dist/services/in-memory-trigger-service.js +48 -0
  56. package/dist/services/in-memory-workflow-service.d.ts +59 -0
  57. package/dist/services/in-memory-workflow-service.js +287 -0
  58. package/dist/services/index.d.ts +26 -11
  59. package/dist/services/index.js +11 -13
  60. package/dist/services/local-content.d.ts +2 -1
  61. package/dist/services/local-content.js +6 -1
  62. package/dist/services/local-secrets.d.ts +25 -2
  63. package/dist/services/local-secrets.js +45 -0
  64. package/dist/services/local-variables.d.ts +6 -1
  65. package/dist/services/local-variables.js +18 -0
  66. package/dist/services/logger-console.d.ts +2 -1
  67. package/dist/services/scheduler-service.d.ts +9 -1
  68. package/dist/services/scheduler-service.js +8 -0
  69. package/dist/services/schema-service.d.ts +6 -0
  70. package/dist/services/scoped-secret-service.d.ts +16 -0
  71. package/dist/services/scoped-secret-service.js +35 -0
  72. package/dist/services/secret-service.d.ts +25 -4
  73. package/dist/services/trigger-service.d.ts +16 -0
  74. package/dist/services/trigger-service.js +1 -0
  75. package/dist/services/typed-secret-service.d.ts +30 -0
  76. package/dist/services/typed-secret-service.js +40 -0
  77. package/dist/services/typed-variables-service.d.ts +27 -0
  78. package/dist/services/typed-variables-service.js +46 -0
  79. package/dist/services/user-session-service.d.ts +15 -2
  80. package/dist/services/user-session-service.js +17 -0
  81. package/dist/services/variables-service.d.ts +5 -0
  82. package/dist/services/workflow-service.d.ts +9 -5
  83. package/dist/types/core.types.d.ts +67 -25
  84. package/dist/types/core.types.js +8 -1
  85. package/dist/types/state.types.d.ts +53 -59
  86. package/dist/utils.d.ts +7 -6
  87. package/dist/utils.js +27 -12
  88. package/dist/version.d.ts +6 -0
  89. package/dist/version.js +19 -0
  90. package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +5 -0
  91. package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +146 -0
  92. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +28 -0
  93. package/dist/wirings/ai-agent/ai-agent-helpers.js +40 -0
  94. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +29 -0
  95. package/dist/wirings/ai-agent/ai-agent-memory.js +199 -0
  96. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +9 -0
  97. package/dist/wirings/ai-agent/ai-agent-model-config.js +36 -0
  98. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +59 -0
  99. package/dist/wirings/ai-agent/ai-agent-prepare.js +348 -0
  100. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +15 -0
  101. package/dist/wirings/ai-agent/ai-agent-registry.js +47 -0
  102. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +3 -0
  103. package/dist/wirings/ai-agent/ai-agent-runner.js +195 -0
  104. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +12 -0
  105. package/dist/wirings/ai-agent/ai-agent-stream.js +662 -0
  106. package/dist/wirings/ai-agent/ai-agent.types.d.ts +313 -0
  107. package/dist/wirings/ai-agent/ai-agent.types.js +1 -0
  108. package/dist/wirings/ai-agent/index.d.ts +7 -0
  109. package/dist/wirings/ai-agent/index.js +6 -0
  110. package/dist/wirings/channel/channel-common.d.ts +8 -5
  111. package/dist/wirings/channel/channel-common.js +15 -8
  112. package/dist/wirings/channel/channel-handler.d.ts +3 -3
  113. package/dist/wirings/channel/channel-handler.js +15 -6
  114. package/dist/wirings/channel/channel-middleware-runner.d.ts +9 -0
  115. package/dist/wirings/channel/channel-middleware-runner.js +73 -0
  116. package/dist/wirings/channel/channel-runner.d.ts +5 -5
  117. package/dist/wirings/channel/channel-runner.js +10 -9
  118. package/dist/wirings/channel/channel-store.d.ts +1 -1
  119. package/dist/wirings/channel/channel.types.d.ts +9 -7
  120. package/dist/wirings/channel/define-channel-routes.d.ts +21 -0
  121. package/dist/wirings/channel/define-channel-routes.js +23 -0
  122. package/dist/wirings/channel/index.d.ts +10 -8
  123. package/dist/wirings/channel/index.js +7 -8
  124. package/dist/wirings/channel/local/index.d.ts +3 -3
  125. package/dist/wirings/channel/local/index.js +3 -3
  126. package/dist/wirings/channel/local/local-channel-runner.d.ts +7 -2
  127. package/dist/wirings/channel/local/local-channel-runner.js +22 -9
  128. package/dist/wirings/channel/local/local-eventhub-service.d.ts +2 -2
  129. package/dist/wirings/channel/log-channels.d.ts +1 -1
  130. package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +1 -1
  131. package/dist/wirings/channel/serverless/index.d.ts +1 -1
  132. package/dist/wirings/channel/serverless/index.js +1 -1
  133. package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +4 -4
  134. package/dist/wirings/channel/serverless/serverless-channel-runner.js +40 -23
  135. package/dist/wirings/cli/channel/cli-channel-runner.d.ts +1 -1
  136. package/dist/wirings/cli/channel/index.d.ts +1 -1
  137. package/dist/wirings/cli/channel/index.js +1 -1
  138. package/dist/wirings/cli/cli-runner.d.ts +3 -3
  139. package/dist/wirings/cli/cli-runner.js +12 -8
  140. package/dist/wirings/cli/cli.types.d.ts +9 -9
  141. package/dist/wirings/cli/command-parser.d.ts +1 -1
  142. package/dist/wirings/cli/define-cli-commands.d.ts +19 -0
  143. package/dist/wirings/cli/define-cli-commands.js +20 -0
  144. package/dist/wirings/cli/index.d.ts +2 -3
  145. package/dist/wirings/cli/index.js +1 -3
  146. package/dist/wirings/http/http-routes.d.ts +69 -0
  147. package/dist/wirings/http/http-routes.js +139 -0
  148. package/dist/wirings/http/http-runner.d.ts +9 -9
  149. package/dist/wirings/http/http-runner.js +79 -34
  150. package/dist/wirings/http/http.types.d.ts +77 -41
  151. package/dist/wirings/http/index.d.ts +5 -4
  152. package/dist/wirings/http/index.js +4 -3
  153. package/dist/wirings/http/log-http-routes.d.ts +1 -1
  154. package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -1
  155. package/dist/wirings/http/pikku-fetch-http-response.d.ts +2 -2
  156. package/dist/wirings/http/pikku-fetch-http-response.js +6 -1
  157. package/dist/wirings/http/routers/http-router.d.ts +1 -1
  158. package/dist/wirings/http/routers/path-to-regex.d.ts +2 -2
  159. package/dist/wirings/mcp/index.d.ts +4 -3
  160. package/dist/wirings/mcp/index.js +3 -3
  161. package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +1 -1
  162. package/dist/wirings/mcp/mcp-runner.d.ts +1 -6
  163. package/dist/wirings/mcp/mcp-runner.js +28 -40
  164. package/dist/wirings/mcp/mcp.types.d.ts +5 -5
  165. package/dist/wirings/node/index.d.ts +2 -0
  166. package/dist/wirings/node/index.js +1 -0
  167. package/dist/wirings/node/node.types.d.ts +20 -0
  168. package/dist/wirings/node/node.types.js +1 -0
  169. package/dist/wirings/oauth2/index.d.ts +3 -0
  170. package/dist/wirings/oauth2/index.js +2 -0
  171. package/dist/wirings/oauth2/oauth2-client.d.ts +47 -0
  172. package/dist/wirings/oauth2/oauth2-client.js +267 -0
  173. package/dist/wirings/oauth2/oauth2.types.d.ts +65 -0
  174. package/dist/wirings/oauth2/oauth2.types.js +4 -0
  175. package/dist/wirings/oauth2/wire-oauth2-credential.d.ts +20 -0
  176. package/dist/wirings/oauth2/wire-oauth2-credential.js +21 -0
  177. package/dist/wirings/queue/index.d.ts +1 -1
  178. package/dist/wirings/queue/queue-runner.d.ts +1 -5
  179. package/dist/wirings/queue/queue-runner.js +11 -8
  180. package/dist/wirings/queue/queue.types.d.ts +5 -5
  181. package/dist/wirings/queue/register-queue-helper.d.ts +2 -2
  182. package/dist/wirings/queue/register-queue-helper.js +1 -1
  183. package/dist/wirings/queue/validate-worker-config.d.ts +1 -1
  184. package/dist/wirings/rpc/index.d.ts +3 -1
  185. package/dist/wirings/rpc/index.js +2 -1
  186. package/dist/wirings/rpc/rpc-runner.d.ts +58 -8
  187. package/dist/wirings/rpc/rpc-runner.js +177 -31
  188. package/dist/wirings/rpc/rpc-types.d.ts +20 -4
  189. package/dist/wirings/rpc/wire-addon.d.ts +10 -0
  190. package/dist/wirings/rpc/wire-addon.js +9 -0
  191. package/dist/wirings/scheduler/index.d.ts +2 -2
  192. package/dist/wirings/scheduler/index.js +1 -2
  193. package/dist/wirings/scheduler/log-schedulers.d.ts +1 -1
  194. package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -5
  195. package/dist/wirings/scheduler/scheduler-runner.js +11 -14
  196. package/dist/wirings/scheduler/scheduler.types.d.ts +2 -2
  197. package/dist/wirings/secret/index.d.ts +3 -0
  198. package/dist/wirings/secret/index.js +2 -0
  199. package/dist/wirings/secret/secret.types.d.ts +27 -0
  200. package/dist/wirings/secret/secret.types.js +1 -0
  201. package/dist/wirings/secret/validate-secret-definitions.d.ts +6 -0
  202. package/dist/wirings/secret/validate-secret-definitions.js +55 -0
  203. package/dist/wirings/trigger/index.d.ts +3 -2
  204. package/dist/wirings/trigger/index.js +2 -2
  205. package/dist/wirings/trigger/pikku-trigger-service.d.ts +22 -0
  206. package/dist/wirings/trigger/pikku-trigger-service.js +70 -0
  207. package/dist/wirings/trigger/trigger-runner.d.ts +18 -9
  208. package/dist/wirings/trigger/trigger-runner.js +48 -19
  209. package/dist/wirings/trigger/trigger.types.d.ts +99 -11
  210. package/dist/wirings/trigger/trigger.types.js +40 -1
  211. package/dist/wirings/variable/index.d.ts +3 -0
  212. package/dist/wirings/variable/index.js +2 -0
  213. package/dist/wirings/variable/validate-variable-definitions.d.ts +6 -0
  214. package/dist/wirings/variable/validate-variable-definitions.js +45 -0
  215. package/dist/wirings/variable/variable.types.d.ts +18 -0
  216. package/dist/wirings/variable/variable.types.js +1 -0
  217. package/dist/wirings/workflow/dsl/index.d.ts +1 -1
  218. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +7 -1
  219. package/dist/wirings/workflow/dsl/workflow-runner.js +3 -2
  220. package/dist/wirings/workflow/graph/graph-node.d.ts +1 -6
  221. package/dist/wirings/workflow/graph/graph-runner.d.ts +5 -31
  222. package/dist/wirings/workflow/graph/graph-runner.js +384 -296
  223. package/dist/wirings/workflow/graph/index.d.ts +4 -3
  224. package/dist/wirings/workflow/graph/index.js +3 -3
  225. package/dist/wirings/workflow/graph/template.d.ts +15 -0
  226. package/dist/wirings/workflow/graph/template.js +27 -0
  227. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +15 -0
  228. package/dist/wirings/workflow/graph/wire-workflow-graph.js +8 -0
  229. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -13
  230. package/dist/wirings/workflow/index.d.ts +6 -6
  231. package/dist/wirings/workflow/index.js +6 -4
  232. package/dist/wirings/workflow/pikku-workflow-service.d.ts +29 -19
  233. package/dist/wirings/workflow/pikku-workflow-service.js +217 -82
  234. package/dist/wirings/workflow/workflow-helpers.d.ts +36 -0
  235. package/dist/wirings/workflow/workflow-helpers.js +38 -0
  236. package/dist/wirings/workflow/workflow.types.d.ts +42 -95
  237. package/package.json +14 -15
  238. package/run-tests.sh +4 -1
  239. package/src/crypto-utils.test.ts +116 -0
  240. package/src/crypto-utils.ts +99 -0
  241. package/src/errors/error.test.ts +143 -2
  242. package/src/errors/errors.ts +27 -0
  243. package/src/errors/index.ts +1 -1
  244. package/src/factory-functions.test.ts +42 -2
  245. package/src/function/function-runner.test.ts +6 -13
  246. package/src/function/function-runner.ts +161 -53
  247. package/src/function/functions.types.ts +63 -132
  248. package/src/function/index.ts +5 -2
  249. package/src/handle-error.test.ts +361 -0
  250. package/src/handle-error.ts +6 -14
  251. package/src/index.ts +97 -30
  252. package/src/internal.ts +6 -0
  253. package/src/middleware/auth-apikey.test.ts +16 -13
  254. package/src/middleware/auth-apikey.ts +3 -3
  255. package/src/middleware/auth-bearer.test.ts +18 -15
  256. package/src/middleware/auth-bearer.ts +27 -32
  257. package/src/middleware/auth-cookie.test.ts +17 -14
  258. package/src/middleware/auth-cookie.ts +9 -13
  259. package/src/middleware/cors.test.ts +424 -0
  260. package/src/middleware/cors.ts +104 -0
  261. package/src/middleware/index.ts +5 -3
  262. package/src/middleware/remote-auth.test.ts +488 -0
  263. package/src/middleware/remote-auth.ts +68 -0
  264. package/src/middleware-runner.test.ts +123 -1
  265. package/src/middleware-runner.ts +13 -13
  266. package/src/permissions.test.ts +83 -9
  267. package/src/permissions.ts +17 -19
  268. package/src/pikku-state.test.ts +224 -0
  269. package/src/pikku-state.ts +59 -35
  270. package/src/run-tests-script.test.ts +49 -0
  271. package/src/schema.test.ts +198 -6
  272. package/src/schema.ts +28 -21
  273. package/src/services/ai-agent-runner-service.ts +41 -0
  274. package/src/services/ai-run-state-service.ts +20 -0
  275. package/src/services/ai-storage-service.ts +39 -0
  276. package/src/services/content-service.ts +7 -0
  277. package/src/services/deployment-service.ts +22 -0
  278. package/src/services/gopass-secrets.ts +98 -0
  279. package/src/services/in-memory-ai-run-state-service.ts +73 -0
  280. package/src/services/in-memory-trigger-service.ts +64 -0
  281. package/src/services/in-memory-workflow-service.test.ts +351 -0
  282. package/src/services/in-memory-workflow-service.ts +395 -0
  283. package/src/services/index.ts +50 -14
  284. package/src/services/local-content.ts +9 -3
  285. package/src/services/local-secrets.test.ts +80 -0
  286. package/src/services/local-secrets.ts +53 -2
  287. package/src/services/local-variables.test.ts +61 -0
  288. package/src/services/local-variables.ts +23 -1
  289. package/src/services/logger-console.test.ts +118 -0
  290. package/src/services/logger-console.ts +2 -1
  291. package/src/services/scheduler-service.ts +11 -1
  292. package/src/services/schema-service.ts +7 -0
  293. package/src/services/scoped-secret-service.test.ts +74 -0
  294. package/src/services/scoped-secret-service.ts +41 -0
  295. package/src/services/secret-service.ts +25 -4
  296. package/src/services/trigger-service.ts +17 -0
  297. package/src/services/typed-secret-service.test.ts +93 -0
  298. package/src/services/typed-secret-service.ts +70 -0
  299. package/src/services/typed-variables-service.test.ts +73 -0
  300. package/src/services/typed-variables-service.ts +81 -0
  301. package/src/services/user-session-service.test.ts +113 -0
  302. package/src/services/user-session-service.ts +25 -2
  303. package/src/services/variables-service.ts +5 -0
  304. package/src/services/workflow-service.ts +23 -13
  305. package/src/time-utils.test.ts +1 -1
  306. package/src/types/core.types.ts +95 -24
  307. package/src/types/state.types.ts +56 -73
  308. package/src/utils.test.ts +350 -0
  309. package/src/utils.ts +33 -18
  310. package/src/version.test.ts +80 -0
  311. package/src/version.ts +25 -0
  312. package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +363 -0
  313. package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +214 -0
  314. package/src/wirings/ai-agent/ai-agent-helpers.test.ts +152 -0
  315. package/src/wirings/ai-agent/ai-agent-helpers.ts +76 -0
  316. package/src/wirings/ai-agent/ai-agent-memory.ts +300 -0
  317. package/src/wirings/ai-agent/ai-agent-model-config.test.ts +115 -0
  318. package/src/wirings/ai-agent/ai-agent-model-config.ts +43 -0
  319. package/src/wirings/ai-agent/ai-agent-prepare.ts +504 -0
  320. package/src/wirings/ai-agent/ai-agent-registry.test.ts +37 -0
  321. package/src/wirings/ai-agent/ai-agent-registry.ts +82 -0
  322. package/src/wirings/ai-agent/ai-agent-runner.test.ts +317 -0
  323. package/src/wirings/ai-agent/ai-agent-runner.ts +251 -0
  324. package/src/wirings/ai-agent/ai-agent-stream.test.ts +652 -0
  325. package/src/wirings/ai-agent/ai-agent-stream.ts +1049 -0
  326. package/src/wirings/ai-agent/ai-agent.types.ts +328 -0
  327. package/src/wirings/ai-agent/index.ts +39 -0
  328. package/src/wirings/channel/channel-common.ts +33 -20
  329. package/src/wirings/channel/channel-handler.ts +26 -9
  330. package/src/wirings/channel/channel-middleware-runner.ts +119 -0
  331. package/src/wirings/channel/channel-runner.ts +15 -16
  332. package/src/wirings/channel/channel-store.ts +1 -1
  333. package/src/wirings/channel/channel.types.ts +21 -9
  334. package/src/wirings/channel/define-channel-routes.ts +25 -0
  335. package/src/wirings/channel/index.ts +23 -8
  336. package/src/wirings/channel/local/index.ts +3 -3
  337. package/src/wirings/channel/local/local-channel-runner.test.ts +57 -7
  338. package/src/wirings/channel/local/local-channel-runner.ts +40 -19
  339. package/src/wirings/channel/local/local-eventhub-service.test.ts +2 -2
  340. package/src/wirings/channel/local/local-eventhub-service.ts +2 -2
  341. package/src/wirings/channel/log-channels.ts +1 -1
  342. package/src/wirings/channel/pikku-abstract-channel-handler.ts +1 -1
  343. package/src/wirings/channel/serverless/index.ts +5 -1
  344. package/src/wirings/channel/serverless/serverless-channel-runner.ts +57 -36
  345. package/src/wirings/cli/channel/cli-channel-runner.ts +1 -1
  346. package/src/wirings/cli/channel/index.ts +1 -1
  347. package/src/wirings/cli/cli-runner.test.ts +10 -10
  348. package/src/wirings/cli/cli-runner.ts +28 -14
  349. package/src/wirings/cli/cli.types.ts +14 -14
  350. package/src/wirings/cli/command-parser.test.ts +9 -9
  351. package/src/wirings/cli/command-parser.ts +1 -1
  352. package/src/wirings/cli/define-cli-commands.ts +24 -0
  353. package/src/wirings/cli/index.ts +10 -4
  354. package/src/wirings/http/http-routes.test.ts +322 -0
  355. package/src/wirings/http/http-routes.ts +198 -0
  356. package/src/wirings/http/http-runner.test.ts +12 -20
  357. package/src/wirings/http/http-runner.ts +101 -51
  358. package/src/wirings/http/http.types.ts +119 -48
  359. package/src/wirings/http/index.ts +16 -4
  360. package/src/wirings/http/log-http-routes.ts +1 -1
  361. package/src/wirings/http/pikku-fetch-http-request.ts +1 -1
  362. package/src/wirings/http/pikku-fetch-http-response.ts +12 -5
  363. package/src/wirings/http/routers/http-router.ts +1 -1
  364. package/src/wirings/http/routers/path-to-regex.test.ts +1 -1
  365. package/src/wirings/http/routers/path-to-regex.ts +4 -3
  366. package/src/wirings/mcp/index.ts +27 -3
  367. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +3 -3
  368. package/src/wirings/mcp/mcp-endpoint-registry.ts +5 -1
  369. package/src/wirings/mcp/mcp-runner.ts +48 -65
  370. package/src/wirings/mcp/mcp.types.ts +5 -5
  371. package/src/wirings/node/index.ts +2 -0
  372. package/src/wirings/node/node.types.ts +23 -0
  373. package/src/wirings/oauth2/index.ts +3 -0
  374. package/src/wirings/oauth2/oauth2-client.test.ts +929 -0
  375. package/src/wirings/oauth2/oauth2-client.ts +335 -0
  376. package/src/wirings/oauth2/oauth2.types.ts +69 -0
  377. package/src/wirings/oauth2/wire-oauth2-credential.ts +23 -0
  378. package/src/wirings/queue/index.ts +13 -2
  379. package/src/wirings/queue/queue-runner.test.ts +142 -73
  380. package/src/wirings/queue/queue-runner.ts +18 -14
  381. package/src/wirings/queue/queue.types.ts +5 -5
  382. package/src/wirings/queue/register-queue-helper.ts +3 -5
  383. package/src/wirings/queue/validate-worker-config.test.ts +108 -0
  384. package/src/wirings/queue/validate-worker-config.ts +4 -1
  385. package/src/wirings/rpc/index.ts +3 -1
  386. package/src/wirings/rpc/rpc-runner.ts +254 -41
  387. package/src/wirings/rpc/rpc-types.ts +28 -4
  388. package/src/wirings/rpc/wire-addon.ts +20 -0
  389. package/src/wirings/scheduler/index.ts +6 -4
  390. package/src/wirings/scheduler/log-schedulers.ts +1 -1
  391. package/src/wirings/scheduler/scheduler-runner.test.ts +78 -45
  392. package/src/wirings/scheduler/scheduler-runner.ts +20 -27
  393. package/src/wirings/scheduler/scheduler.types.ts +2 -2
  394. package/src/wirings/secret/index.ts +9 -0
  395. package/src/wirings/secret/secret.types.ts +32 -0
  396. package/src/wirings/secret/validate-secret-definitions.test.ts +140 -0
  397. package/src/wirings/secret/validate-secret-definitions.ts +82 -0
  398. package/src/wirings/trigger/index.ts +10 -2
  399. package/src/wirings/trigger/pikku-trigger-service.ts +112 -0
  400. package/src/wirings/trigger/trigger-runner.test.ts +79 -0
  401. package/src/wirings/trigger/trigger-runner.ts +80 -41
  402. package/src/wirings/trigger/trigger.types.ts +144 -22
  403. package/src/wirings/variable/index.ts +8 -0
  404. package/src/wirings/variable/validate-variable-definitions.test.ts +91 -0
  405. package/src/wirings/variable/validate-variable-definitions.ts +69 -0
  406. package/src/wirings/variable/variable.types.ts +22 -0
  407. package/src/wirings/workflow/dsl/index.ts +1 -0
  408. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +9 -1
  409. package/src/wirings/workflow/dsl/workflow-runner.ts +4 -3
  410. package/src/wirings/workflow/graph/graph-node.ts +1 -6
  411. package/src/wirings/workflow/graph/graph-runner.test.ts +487 -0
  412. package/src/wirings/workflow/graph/graph-runner.ts +496 -374
  413. package/src/wirings/workflow/graph/index.ts +14 -3
  414. package/src/wirings/workflow/graph/template.test.ts +49 -0
  415. package/src/wirings/workflow/graph/template.ts +42 -0
  416. package/src/wirings/workflow/graph/wire-workflow-graph.ts +29 -0
  417. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -22
  418. package/src/wirings/workflow/index.ts +21 -10
  419. package/src/wirings/workflow/pikku-workflow-service.test.ts +200 -0
  420. package/src/wirings/workflow/pikku-workflow-service.ts +308 -105
  421. package/src/wirings/workflow/workflow-helpers.test.ts +129 -0
  422. package/src/wirings/workflow/workflow-helpers.ts +79 -0
  423. package/src/wirings/workflow/workflow.types.ts +47 -92
  424. package/tsconfig.tsbuildinfo +1 -1
  425. package/dist/wirings/forge-node/forge-node.types.d.ts +0 -120
  426. package/dist/wirings/forge-node/forge-node.types.js +0 -38
  427. package/dist/wirings/forge-node/index.d.ts +0 -1
  428. package/dist/wirings/forge-node/index.js +0 -1
  429. package/dist/wirings/workflow/wire-workflow.d.ts +0 -42
  430. package/dist/wirings/workflow/wire-workflow.js +0 -53
  431. package/dist/wirings/workflow/workflow-utils.d.ts +0 -23
  432. package/dist/wirings/workflow/workflow-utils.js +0 -66
  433. package/src/wirings/forge-node/forge-node.types.ts +0 -135
  434. package/src/wirings/forge-node/index.ts +0 -1
  435. package/src/wirings/workflow/wire-workflow.ts +0 -94
  436. package/src/wirings/workflow/workflow-utils.ts +0 -120
@@ -0,0 +1,504 @@
1
+ import type { PikkuWire, CoreUserSession } from '../../types/core.types.js'
2
+ import type {
3
+ CoreAIAgent,
4
+ AIAgentInput,
5
+ AIAgentToolDef,
6
+ AIMessage,
7
+ AIStreamChannel,
8
+ AIStreamEvent,
9
+ PikkuAIMiddlewareHooks,
10
+ } from './ai-agent.types.js'
11
+ import type { AIAgentRunnerParams } from '../../services/ai-agent-runner-service.js'
12
+ import { PikkuError } from '../../errors/error-handler.js'
13
+ import {
14
+ pikkuState,
15
+ getSingletonServices,
16
+ getCreateWireServices,
17
+ } from '../../pikku-state.js'
18
+ import { runPikkuFunc } from '../../function/function-runner.js'
19
+ import { createMiddlewareSessionWireProps } from '../../services/user-session-service.js'
20
+ import type { SessionService } from '../../services/user-session-service.js'
21
+ import { randomUUID } from 'crypto'
22
+
23
+ import {
24
+ resolveMemoryServices,
25
+ loadContextMessages,
26
+ trimMessages,
27
+ } from './ai-agent-memory.js'
28
+ import { resolveModelConfig } from './ai-agent-model-config.js'
29
+
30
+ export type RunAIAgentParams = {
31
+ sessionService?: SessionService<CoreUserSession>
32
+ }
33
+
34
+ export type StreamAIAgentOptions = {
35
+ requiresToolApproval?: 'all' | 'explicit' | false
36
+ }
37
+
38
+ export class ToolApprovalRequired extends PikkuError {
39
+ public readonly toolCallId: string
40
+ public readonly toolName: string
41
+ public readonly args: unknown
42
+ public readonly reason?: string
43
+ public readonly displayToolName?: string
44
+ public readonly displayArgs?: unknown
45
+ public readonly agentRunId?: string
46
+
47
+ constructor(
48
+ toolCallId: string,
49
+ toolName: string,
50
+ args: unknown,
51
+ reason?: string,
52
+ displayToolName?: string,
53
+ displayArgs?: unknown,
54
+ agentRunId?: string
55
+ ) {
56
+ super(`Tool '${displayToolName ?? toolName}' requires approval`)
57
+ this.toolCallId = toolCallId
58
+ this.toolName = toolName
59
+ this.args = args
60
+ this.reason = reason
61
+ this.displayToolName = displayToolName
62
+ this.displayArgs = displayArgs
63
+ this.agentRunId = agentRunId
64
+ }
65
+ }
66
+
67
+ export type StreamContext = {
68
+ channel: AIStreamChannel
69
+ options?: StreamAIAgentOptions
70
+ }
71
+
72
+ export const resolveAgent = (
73
+ agentName: string
74
+ ): { agent: CoreAIAgent; packageName: string | null; resolvedName: string } => {
75
+ const mainAgent = pikkuState(null, 'agent', 'agents').get(agentName)
76
+ if (mainAgent) {
77
+ return { agent: mainAgent, packageName: null, resolvedName: agentName }
78
+ }
79
+
80
+ const colonIndex = agentName.indexOf(':')
81
+ if (colonIndex !== -1) {
82
+ const namespace = agentName.substring(0, colonIndex)
83
+ const localName = agentName.substring(colonIndex + 1)
84
+ const addons = pikkuState(null, 'rpc', 'addons')
85
+ const pkgConfig = addons.get(namespace)
86
+ if (pkgConfig) {
87
+ const extAgent = pikkuState(pkgConfig.package, 'agent', 'agents').get(
88
+ localName
89
+ )
90
+ if (extAgent) {
91
+ return {
92
+ agent: extAgent,
93
+ packageName: pkgConfig.package,
94
+ resolvedName: localName,
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ throw new Error(`AI agent not found: ${agentName}`)
101
+ }
102
+
103
+ export function buildInstructions(
104
+ agentName: string,
105
+ packageName: string | null
106
+ ): string {
107
+ const meta = pikkuState(packageName, 'agent', 'agentsMeta')[agentName]
108
+ const instructions = meta?.instructions ?? ''
109
+ const baseInstructions = Array.isArray(instructions)
110
+ ? instructions.join('\n')
111
+ : instructions
112
+
113
+ return meta?.agents?.length
114
+ ? baseInstructions +
115
+ '\n\nWhen calling a sub-agent, provide a short session name that describes the task. ' +
116
+ 'Use the same session name to continue a previous conversation with that agent. ' +
117
+ 'Use a new session name for a new independent task.'
118
+ : baseInstructions
119
+ }
120
+
121
+ export type ScopedChannel = AIStreamChannel & {
122
+ approval: {
123
+ toolCallId: string
124
+ toolName: string
125
+ args: unknown
126
+ runId: string
127
+ } | null
128
+ }
129
+
130
+ export function createScopedChannel(
131
+ parent: AIStreamChannel,
132
+ agentName: string,
133
+ session: string
134
+ ): ScopedChannel {
135
+ let capturedApproval: ScopedChannel['approval'] = null
136
+
137
+ return {
138
+ channelId: `${parent.channelId}:${agentName}:${session}`,
139
+ openingData: parent.openingData,
140
+ get state() {
141
+ return parent.state
142
+ },
143
+ get approval() {
144
+ return capturedApproval
145
+ },
146
+ close: () => {},
147
+ send: (event: AIStreamEvent) => {
148
+ if (event.type === 'done') return
149
+ if (event.type === 'approval-request') {
150
+ capturedApproval = {
151
+ toolCallId: event.toolCallId,
152
+ toolName: event.toolName,
153
+ args: event.args,
154
+ runId: (event as any).runId,
155
+ }
156
+ return
157
+ }
158
+ if (
159
+ event.type === 'step-start' ||
160
+ event.type === 'text-delta' ||
161
+ event.type === 'reasoning-delta' ||
162
+ event.type === 'tool-call' ||
163
+ event.type === 'tool-result' ||
164
+ event.type === 'usage' ||
165
+ event.type === 'error'
166
+ ) {
167
+ parent.send({ ...event, agent: agentName, session } as AIStreamEvent)
168
+ } else {
169
+ parent.send(event)
170
+ }
171
+ },
172
+ }
173
+ }
174
+
175
+ export function buildToolDefs(
176
+ params: RunAIAgentParams,
177
+ agentSessionMap: Map<string, string>,
178
+ resourceId: string,
179
+ agentName: string,
180
+ packageName: string | null,
181
+ streamContext?: StreamContext,
182
+ aiMiddlewares?: PikkuAIMiddlewareHooks[]
183
+ ): { tools: AIAgentToolDef[]; missingRpcs: string[] } {
184
+ const singletonServices = getSingletonServices()
185
+ const tools: AIAgentToolDef[] = []
186
+ const missingRpcs: string[] = []
187
+ const approvalPolicy =
188
+ streamContext?.options?.requiresToolApproval ?? 'explicit'
189
+
190
+ const meta = pikkuState(packageName, 'agent', 'agentsMeta')[agentName]
191
+ if (!meta) return { tools, missingRpcs }
192
+
193
+ const metaTools = meta.tools
194
+ const metaAgents = meta.agents
195
+
196
+ if (metaTools?.length) {
197
+ const functionMeta = pikkuState(null, 'function', 'meta')
198
+ const schemas = pikkuState(null, 'misc', 'schemas')
199
+
200
+ for (const toolName of metaTools) {
201
+ const rpcMeta = pikkuState(null, 'rpc', 'meta')
202
+ const pikkuFuncId = rpcMeta[toolName]
203
+ if (!pikkuFuncId) {
204
+ missingRpcs.push(toolName)
205
+ continue
206
+ }
207
+
208
+ const fnMeta = functionMeta[pikkuFuncId]
209
+ const inputSchemaName = fnMeta?.inputSchemaName
210
+ let inputSchema = inputSchemaName
211
+ ? schemas.get(inputSchemaName)
212
+ : undefined
213
+ if (
214
+ !inputSchema ||
215
+ (typeof inputSchema === 'object' &&
216
+ inputSchema.type === 'object' &&
217
+ !inputSchema.properties)
218
+ ) {
219
+ inputSchema = { type: 'object', properties: {} }
220
+ }
221
+
222
+ const needsApproval =
223
+ approvalPolicy === 'all' ||
224
+ (approvalPolicy === 'explicit' && fnMeta?.requiresApproval)
225
+
226
+ tools.push({
227
+ name: pikkuFuncId,
228
+ description: fnMeta?.description || fnMeta?.title || toolName,
229
+ inputSchema,
230
+ needsApproval: needsApproval || undefined,
231
+ execute: async (toolInput: unknown) => {
232
+ const wire: PikkuWire = params.sessionService
233
+ ? { ...createMiddlewareSessionWireProps(params.sessionService) }
234
+ : {}
235
+ return runPikkuFunc('agent', `tool:${pikkuFuncId}`, pikkuFuncId, {
236
+ singletonServices,
237
+ createWireServices: getCreateWireServices(),
238
+ data: () => toolInput,
239
+ wire,
240
+ sessionService: params.sessionService,
241
+ })
242
+ },
243
+ })
244
+ }
245
+ }
246
+
247
+ if (metaAgents?.length) {
248
+ const allAgentsMeta = pikkuState(null, 'agent', 'agentsMeta')
249
+
250
+ for (const subAgentName of metaAgents) {
251
+ const subMeta = allAgentsMeta[subAgentName]
252
+ if (!subMeta) {
253
+ singletonServices.logger.warn(
254
+ `Sub-agent '${subAgentName}' not found in agent registry`
255
+ )
256
+ continue
257
+ }
258
+
259
+ tools.push({
260
+ name: subAgentName,
261
+ description: subMeta.description,
262
+ inputSchema: {
263
+ type: 'object',
264
+ properties: {
265
+ message: { type: 'string' },
266
+ session: {
267
+ type: 'string',
268
+ description: 'Short session label for thread continuity',
269
+ },
270
+ },
271
+ required: ['message', 'session'],
272
+ },
273
+ execute: async (toolInput: unknown) => {
274
+ const { message, session } = toolInput as {
275
+ message: string
276
+ session: string
277
+ }
278
+ const sessionKey = `${subAgentName}::${session}`
279
+ let threadId = agentSessionMap.get(sessionKey)
280
+ if (!threadId) {
281
+ threadId = `${subAgentName}-${session}-${Date.now()}`
282
+ agentSessionMap.set(sessionKey, threadId)
283
+ }
284
+
285
+ if (streamContext) {
286
+ const { streamAIAgent } = await import('./ai-agent-stream.js')
287
+ const { channel } = streamContext
288
+ channel.send({
289
+ type: 'agent-call',
290
+ agentName: subAgentName,
291
+ session,
292
+ input: message,
293
+ })
294
+ const subChannel = createScopedChannel(
295
+ channel,
296
+ subAgentName,
297
+ session
298
+ )
299
+ await streamAIAgent(
300
+ subAgentName,
301
+ { message, threadId, resourceId },
302
+ subChannel,
303
+ params,
304
+ agentSessionMap,
305
+ streamContext.options
306
+ )
307
+ if (subChannel.approval) {
308
+ return {
309
+ __approvalRequired: true,
310
+ toolName: subAgentName,
311
+ args: toolInput,
312
+ displayToolName: subChannel.approval.toolName,
313
+ displayArgs: subChannel.approval.args,
314
+ agentRunId: subChannel.approval.runId,
315
+ }
316
+ }
317
+ channel.send({
318
+ type: 'agent-result',
319
+ agentName: subAgentName,
320
+ session,
321
+ result: null,
322
+ })
323
+ return null
324
+ }
325
+
326
+ const { runAIAgent } = await import('./ai-agent-runner.js')
327
+ const result = await runAIAgent(
328
+ subAgentName,
329
+ { message, threadId, resourceId },
330
+ params,
331
+ agentSessionMap
332
+ )
333
+ return result.object ?? result.text
334
+ },
335
+ })
336
+ }
337
+ }
338
+
339
+ const hasToolHooks = aiMiddlewares?.some(
340
+ (mw) => mw.beforeToolCall || mw.afterToolCall
341
+ )
342
+ if (hasToolHooks) {
343
+ for (const tool of tools) {
344
+ const originalExecute = tool.execute
345
+ tool.execute = async (toolInput: unknown) => {
346
+ const toolCallId = randomUUID()
347
+ let args = (toolInput ?? {}) as Record<string, unknown>
348
+
349
+ for (const mw of aiMiddlewares!) {
350
+ if (mw.beforeToolCall) {
351
+ const beforeResult = await mw.beforeToolCall(singletonServices, {
352
+ toolName: tool.name,
353
+ toolCallId,
354
+ args,
355
+ })
356
+ if (beforeResult && 'args' in beforeResult) {
357
+ args = beforeResult.args
358
+ }
359
+ }
360
+ }
361
+
362
+ const startTime = Date.now()
363
+ let result: unknown
364
+ let execError: unknown
365
+ try {
366
+ result = await originalExecute(args)
367
+ } catch (err) {
368
+ execError = err
369
+ result = err instanceof Error ? err.message : String(err)
370
+ }
371
+ const durationMs = Date.now() - startTime
372
+
373
+ for (let i = aiMiddlewares!.length - 1; i >= 0; i--) {
374
+ const mw = aiMiddlewares![i]
375
+ if (mw.afterToolCall) {
376
+ const afterResult = await mw.afterToolCall(singletonServices, {
377
+ toolName: tool.name,
378
+ toolCallId,
379
+ args,
380
+ result,
381
+ durationMs,
382
+ })
383
+ if (afterResult && 'result' in afterResult) {
384
+ result = afterResult.result
385
+ }
386
+ }
387
+ }
388
+
389
+ if (execError) throw execError
390
+ return result
391
+ }
392
+ }
393
+ }
394
+
395
+ return { tools, missingRpcs }
396
+ }
397
+
398
+ export async function prepareAgentRun(
399
+ agentName: string,
400
+ input: AIAgentInput,
401
+ params: RunAIAgentParams,
402
+ agentSessionMap: Map<string, string>,
403
+ streamContext?: StreamContext
404
+ ) {
405
+ const singletonServices = getSingletonServices()
406
+ const { agent, packageName, resolvedName } = resolveAgent(agentName)
407
+
408
+ const agentRunner = singletonServices.aiAgentRunner
409
+ if (!agentRunner) {
410
+ throw new Error('AIAgentRunnerService not available in singletonServices')
411
+ }
412
+
413
+ const { storage } = resolveMemoryServices(agent, singletonServices)
414
+ const memoryConfig = agent.memory
415
+ const threadId = input.threadId
416
+
417
+ const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta')
418
+ const meta = agentsMeta[resolvedName]
419
+ const outputSchemaName = meta?.outputSchema
420
+ const outputSchema = outputSchemaName
421
+ ? pikkuState(packageName, 'misc', 'schemas').get(outputSchemaName)
422
+ : undefined
423
+
424
+ const workingMemorySchemaName = meta?.workingMemorySchema ?? null
425
+ const workingMemoryJsonSchema = workingMemorySchemaName
426
+ ? pikkuState(packageName, 'misc', 'schemas').get(workingMemorySchemaName)
427
+ : undefined
428
+
429
+ if (storage) {
430
+ try {
431
+ await storage.getThread(threadId)
432
+ } catch {
433
+ await storage.createThread(input.resourceId, { threadId })
434
+ }
435
+ }
436
+
437
+ let messages: AIMessage[] = []
438
+ if (storage) {
439
+ messages = await storage.getMessages(threadId, {
440
+ lastN: memoryConfig?.lastMessages ?? 20,
441
+ })
442
+ }
443
+
444
+ const contextMessages = await loadContextMessages(
445
+ memoryConfig,
446
+ storage,
447
+ input,
448
+ workingMemoryJsonSchema
449
+ )
450
+
451
+ const userMessage: AIMessage = {
452
+ id: randomUUID(),
453
+ role: 'user',
454
+ content: input.message,
455
+ createdAt: new Date(),
456
+ }
457
+
458
+ const allMessages = [...contextMessages, ...messages, userMessage]
459
+ const trimmedMessages = trimMessages(allMessages)
460
+
461
+ const aiMiddlewares: PikkuAIMiddlewareHooks[] = agent.aiMiddleware ?? []
462
+
463
+ const { tools, missingRpcs } = buildToolDefs(
464
+ params,
465
+ agentSessionMap,
466
+ input.resourceId,
467
+ resolvedName,
468
+ packageName,
469
+ streamContext,
470
+ aiMiddlewares
471
+ )
472
+
473
+ const instructions = buildInstructions(resolvedName, packageName)
474
+
475
+ const resolved = resolveModelConfig(resolvedName, agent)
476
+ const maxSteps = resolved.maxSteps ?? 10
477
+
478
+ const runnerParams: AIAgentRunnerParams = {
479
+ model: resolved.model,
480
+ temperature: resolved.temperature,
481
+ instructions,
482
+ messages: trimmedMessages,
483
+ tools,
484
+ maxSteps: 1,
485
+ toolChoice: agent.toolChoice ?? 'auto',
486
+ outputSchema,
487
+ }
488
+
489
+ return {
490
+ agent,
491
+ packageName,
492
+ resolvedName,
493
+ agentRunner,
494
+ storage,
495
+ memoryConfig,
496
+ threadId,
497
+ userMessage,
498
+ runnerParams,
499
+ maxSteps,
500
+ missingRpcs,
501
+ workingMemoryJsonSchema,
502
+ workingMemorySchemaName,
503
+ }
504
+ }
@@ -0,0 +1,37 @@
1
+ import { describe, test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+
4
+ import { approveAIAgent } from './ai-agent-registry.js'
5
+
6
+ describe('approveAIAgent', () => {
7
+ test('rejects approval when run agent does not match expected agent', async () => {
8
+ const aiRunState = {
9
+ getRun: async () => ({
10
+ runId: 'run-1',
11
+ agentName: 'internal-agent',
12
+ threadId: 'thread-1',
13
+ resourceId: 'resource-1',
14
+ status: 'suspended',
15
+ pendingApprovals: [],
16
+ usage: { inputTokens: 0, outputTokens: 0, model: 'test-model' },
17
+ createdAt: new Date(),
18
+ updatedAt: new Date(),
19
+ }),
20
+ updateRun: async () => {},
21
+ } as any
22
+
23
+ await assert.rejects(
24
+ () =>
25
+ approveAIAgent(
26
+ aiRunState,
27
+ 'run-1',
28
+ [{ toolCallId: 'call-1', approved: true }],
29
+ 'public-agent'
30
+ ),
31
+ {
32
+ message:
33
+ "Run run-1 belongs to agent 'internal-agent', not 'public-agent'",
34
+ }
35
+ )
36
+ })
37
+ })
@@ -0,0 +1,82 @@
1
+ import type { CoreAIAgent, AgentRunState } from './ai-agent.types.js'
2
+ import { pikkuState } from '../../pikku-state.js'
3
+ import type { AIRunStateService } from '../../services/ai-run-state-service.js'
4
+ import { PikkuMissingMetaError } from '../../errors/errors.js'
5
+
6
+ export const addAIAgent = (
7
+ agentName: string,
8
+ agent: CoreAIAgent<any, any>,
9
+ packageName: string | null = null
10
+ ) => {
11
+ const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta')
12
+ const agentMeta = agentsMeta[agentName]
13
+ if (!agentMeta) {
14
+ throw new PikkuMissingMetaError(
15
+ `Missing generated metadata for AI agent '${agentName}'`
16
+ )
17
+ }
18
+ const agents = pikkuState(packageName, 'agent', 'agents')
19
+ if (agents.has(agentName)) {
20
+ throw new Error(`AI agent already exists: ${agentName}`)
21
+ }
22
+ agents.set(agentName, agent)
23
+ }
24
+
25
+ export async function approveAIAgent(
26
+ aiRunState: AIRunStateService,
27
+ runId: string,
28
+ approvals: { toolCallId: string; approved: boolean }[],
29
+ expectedAgentName?: string
30
+ ): Promise<{
31
+ status: 'resumed' | 'suspended'
32
+ runId: string
33
+ approved: string[]
34
+ rejected: string[]
35
+ remainingApprovals: number
36
+ }> {
37
+ if (!aiRunState) throw new Error('AIRunStateService not available')
38
+
39
+ const run = await aiRunState.getRun(runId)
40
+ if (!run) throw new Error('Run not found: ' + runId)
41
+ if (expectedAgentName && run.agentName !== expectedAgentName) {
42
+ throw new Error(
43
+ `Run ${runId} belongs to agent '${run.agentName}', not '${expectedAgentName}'`
44
+ )
45
+ }
46
+ if (run.status !== 'suspended')
47
+ throw new Error('Run is not suspended: ' + run.status)
48
+
49
+ const approvedIds = new Set(
50
+ approvals.filter((a) => a.approved).map((a) => a.toolCallId)
51
+ )
52
+ const rejectedIds = new Set(
53
+ approvals.filter((a) => !a.approved).map((a) => a.toolCallId)
54
+ )
55
+
56
+ const remaining = (run.pendingApprovals ?? []).filter(
57
+ (p: NonNullable<AgentRunState['pendingApprovals']>[number]) =>
58
+ !approvedIds.has(p.toolCallId) && !rejectedIds.has(p.toolCallId)
59
+ )
60
+
61
+ const hasApproved = approvedIds.size > 0
62
+ await aiRunState.updateRun(runId, {
63
+ status: hasApproved ? 'running' : 'suspended',
64
+ pendingApprovals: remaining.length > 0 ? remaining : undefined,
65
+ })
66
+
67
+ return {
68
+ status: hasApproved ? 'resumed' : 'suspended',
69
+ runId,
70
+ approved: [...approvedIds],
71
+ rejected: [...rejectedIds],
72
+ remainingApprovals: remaining.length,
73
+ }
74
+ }
75
+
76
+ export const getAIAgents = () => {
77
+ return pikkuState(null, 'agent', 'agents')
78
+ }
79
+
80
+ export const getAIAgentsMeta = () => {
81
+ return pikkuState(null, 'agent', 'agentsMeta')
82
+ }