@pikku/core 0.11.2 → 0.12.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 (344) hide show
  1. package/CHANGELOG.md +33 -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 +8 -0
  5. package/dist/errors/errors.js +16 -0
  6. package/dist/errors/index.d.ts +0 -1
  7. package/dist/errors/index.js +0 -1
  8. package/dist/function/function-runner.d.ts +7 -1
  9. package/dist/function/function-runner.js +82 -23
  10. package/dist/function/functions.types.d.ts +31 -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.js +1 -10
  15. package/dist/index.d.ts +28 -26
  16. package/dist/index.js +18 -29
  17. package/dist/middleware/auth-apikey.d.ts +2 -2
  18. package/dist/middleware/auth-apikey.js +3 -3
  19. package/dist/middleware/auth-bearer.d.ts +2 -2
  20. package/dist/middleware/auth-bearer.js +3 -6
  21. package/dist/middleware/auth-cookie.d.ts +2 -2
  22. package/dist/middleware/auth-cookie.js +6 -8
  23. package/dist/middleware/cors.d.ts +46 -0
  24. package/dist/middleware/cors.js +73 -0
  25. package/dist/middleware/index.d.ts +5 -3
  26. package/dist/middleware/index.js +5 -3
  27. package/dist/middleware/remote-auth.d.ts +5 -0
  28. package/dist/middleware/remote-auth.js +55 -0
  29. package/dist/middleware/timeout.d.ts +2 -2
  30. package/dist/middleware-runner.js +8 -10
  31. package/dist/permissions.js +11 -15
  32. package/dist/pikku-state.d.ts +1 -0
  33. package/dist/pikku-state.js +18 -8
  34. package/dist/schema.js +12 -11
  35. package/dist/services/ai-agent-runner-service.d.ts +24 -0
  36. package/dist/services/ai-agent-runner-service.js +1 -0
  37. package/dist/services/ai-run-state-service.d.ts +13 -0
  38. package/dist/services/ai-run-state-service.js +1 -0
  39. package/dist/services/ai-storage-service.d.ts +18 -0
  40. package/dist/services/ai-storage-service.js +1 -0
  41. package/dist/services/deployment-service.d.ts +19 -0
  42. package/dist/services/deployment-service.js +1 -0
  43. package/dist/services/gopass-secrets.d.ts +47 -0
  44. package/dist/services/gopass-secrets.js +94 -0
  45. package/dist/services/in-memory-trigger-service.d.ts +23 -0
  46. package/dist/services/in-memory-trigger-service.js +50 -0
  47. package/dist/services/in-memory-workflow-service.d.ts +59 -0
  48. package/dist/services/in-memory-workflow-service.js +287 -0
  49. package/dist/services/index.d.ts +25 -11
  50. package/dist/services/index.js +10 -13
  51. package/dist/services/local-secrets.d.ts +23 -0
  52. package/dist/services/local-secrets.js +45 -0
  53. package/dist/services/local-variables.d.ts +5 -0
  54. package/dist/services/local-variables.js +18 -0
  55. package/dist/services/scheduler-service.d.ts +21 -1
  56. package/dist/services/scheduler-service.js +14 -0
  57. package/dist/services/schema-service.d.ts +6 -0
  58. package/dist/services/scoped-secret-service.d.ts +16 -0
  59. package/dist/services/scoped-secret-service.js +35 -0
  60. package/dist/services/secret-service.d.ts +25 -4
  61. package/dist/services/trigger-service.d.ts +23 -0
  62. package/dist/services/trigger-service.js +1 -0
  63. package/dist/services/typed-secret-service.d.ts +30 -0
  64. package/dist/services/typed-secret-service.js +40 -0
  65. package/dist/services/typed-variables-service.d.ts +27 -0
  66. package/dist/services/typed-variables-service.js +46 -0
  67. package/dist/services/user-session-service.d.ts +13 -0
  68. package/dist/services/user-session-service.js +17 -0
  69. package/dist/services/variables-service.d.ts +5 -0
  70. package/dist/services/workflow-service.d.ts +9 -4
  71. package/dist/types/core.types.d.ts +48 -12
  72. package/dist/types/core.types.js +8 -1
  73. package/dist/types/state.types.d.ts +43 -51
  74. package/dist/utils.d.ts +3 -2
  75. package/dist/utils.js +15 -3
  76. package/dist/version.d.ts +6 -0
  77. package/dist/version.js +19 -0
  78. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +29 -0
  79. package/dist/wirings/ai-agent/ai-agent-memory.js +199 -0
  80. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +9 -0
  81. package/dist/wirings/ai-agent/ai-agent-model-config.js +36 -0
  82. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +60 -0
  83. package/dist/wirings/ai-agent/ai-agent-prepare.js +312 -0
  84. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +15 -0
  85. package/dist/wirings/ai-agent/ai-agent-registry.js +47 -0
  86. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +3 -0
  87. package/dist/wirings/ai-agent/ai-agent-runner.js +96 -0
  88. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +11 -0
  89. package/dist/wirings/ai-agent/ai-agent-stream.js +503 -0
  90. package/dist/wirings/ai-agent/ai-agent.types.d.ts +254 -0
  91. package/dist/wirings/ai-agent/ai-agent.types.js +1 -0
  92. package/dist/wirings/ai-agent/index.d.ts +5 -0
  93. package/dist/wirings/ai-agent/index.js +4 -0
  94. package/dist/wirings/channel/channel-common.d.ts +7 -4
  95. package/dist/wirings/channel/channel-common.js +15 -8
  96. package/dist/wirings/channel/channel-handler.js +12 -3
  97. package/dist/wirings/channel/channel-middleware-runner.d.ts +9 -0
  98. package/dist/wirings/channel/channel-middleware-runner.js +73 -0
  99. package/dist/wirings/channel/channel-runner.js +7 -7
  100. package/dist/wirings/channel/channel.types.d.ts +5 -1
  101. package/dist/wirings/channel/define-channel-routes.d.ts +21 -0
  102. package/dist/wirings/channel/define-channel-routes.js +23 -0
  103. package/dist/wirings/channel/index.d.ts +10 -8
  104. package/dist/wirings/channel/index.js +7 -8
  105. package/dist/wirings/channel/local/index.d.ts +3 -3
  106. package/dist/wirings/channel/local/index.js +3 -3
  107. package/dist/wirings/channel/local/local-channel-runner.js +18 -6
  108. package/dist/wirings/channel/serverless/index.d.ts +1 -1
  109. package/dist/wirings/channel/serverless/index.js +1 -1
  110. package/dist/wirings/channel/serverless/serverless-channel-runner.js +15 -4
  111. package/dist/wirings/cli/channel/index.d.ts +1 -1
  112. package/dist/wirings/cli/channel/index.js +1 -1
  113. package/dist/wirings/cli/cli-runner.d.ts +1 -1
  114. package/dist/wirings/cli/cli-runner.js +12 -8
  115. package/dist/wirings/cli/cli.types.d.ts +6 -6
  116. package/dist/wirings/cli/define-cli-commands.d.ts +19 -0
  117. package/dist/wirings/cli/define-cli-commands.js +20 -0
  118. package/dist/wirings/cli/index.d.ts +2 -3
  119. package/dist/wirings/cli/index.js +1 -3
  120. package/dist/wirings/http/http-routes.d.ts +69 -0
  121. package/dist/wirings/http/http-routes.js +139 -0
  122. package/dist/wirings/http/http-runner.js +49 -23
  123. package/dist/wirings/http/http.types.d.ts +78 -38
  124. package/dist/wirings/http/index.d.ts +5 -4
  125. package/dist/wirings/http/index.js +4 -3
  126. package/dist/wirings/mcp/index.d.ts +4 -3
  127. package/dist/wirings/mcp/index.js +3 -3
  128. package/dist/wirings/mcp/mcp-runner.d.ts +1 -3
  129. package/dist/wirings/mcp/mcp-runner.js +25 -39
  130. package/dist/wirings/mcp/mcp.types.d.ts +3 -3
  131. package/dist/wirings/node/index.d.ts +2 -0
  132. package/dist/wirings/node/index.js +1 -0
  133. package/dist/wirings/node/node.types.d.ts +20 -0
  134. package/dist/wirings/node/node.types.js +1 -0
  135. package/dist/wirings/oauth2/index.d.ts +3 -0
  136. package/dist/wirings/oauth2/index.js +2 -0
  137. package/dist/wirings/oauth2/oauth2-client.d.ts +47 -0
  138. package/dist/wirings/oauth2/oauth2-client.js +267 -0
  139. package/dist/wirings/oauth2/oauth2.types.d.ts +65 -0
  140. package/dist/wirings/oauth2/oauth2.types.js +4 -0
  141. package/dist/wirings/oauth2/wire-oauth2-credential.d.ts +20 -0
  142. package/dist/wirings/oauth2/wire-oauth2-credential.js +21 -0
  143. package/dist/wirings/queue/index.d.ts +2 -2
  144. package/dist/wirings/queue/index.js +1 -1
  145. package/dist/wirings/queue/queue-runner.d.ts +7 -0
  146. package/dist/wirings/queue/queue-runner.js +17 -6
  147. package/dist/wirings/queue/queue.types.d.ts +8 -2
  148. package/dist/wirings/rpc/index.d.ts +1 -1
  149. package/dist/wirings/rpc/index.js +1 -1
  150. package/dist/wirings/rpc/rpc-runner.d.ts +33 -5
  151. package/dist/wirings/rpc/rpc-runner.js +134 -16
  152. package/dist/wirings/rpc/rpc-types.d.ts +8 -4
  153. package/dist/wirings/scheduler/index.d.ts +3 -3
  154. package/dist/wirings/scheduler/index.js +2 -3
  155. package/dist/wirings/scheduler/scheduler-runner.d.ts +5 -0
  156. package/dist/wirings/scheduler/scheduler-runner.js +23 -5
  157. package/dist/wirings/secret/index.d.ts +3 -0
  158. package/dist/wirings/secret/index.js +2 -0
  159. package/dist/wirings/secret/secret.types.d.ts +27 -0
  160. package/dist/wirings/secret/secret.types.js +1 -0
  161. package/dist/wirings/secret/validate-secret-definitions.d.ts +6 -0
  162. package/dist/wirings/secret/validate-secret-definitions.js +55 -0
  163. package/dist/wirings/trigger/index.d.ts +3 -2
  164. package/dist/wirings/trigger/index.js +2 -2
  165. package/dist/wirings/trigger/pikku-trigger-service.d.ts +26 -0
  166. package/dist/wirings/trigger/pikku-trigger-service.js +75 -0
  167. package/dist/wirings/trigger/trigger-runner.d.ts +21 -8
  168. package/dist/wirings/trigger/trigger-runner.js +46 -18
  169. package/dist/wirings/trigger/trigger.types.d.ts +99 -11
  170. package/dist/wirings/trigger/trigger.types.js +40 -1
  171. package/dist/wirings/variable/index.d.ts +3 -0
  172. package/dist/wirings/variable/index.js +2 -0
  173. package/dist/wirings/variable/validate-variable-definitions.d.ts +6 -0
  174. package/dist/wirings/variable/validate-variable-definitions.js +45 -0
  175. package/dist/wirings/variable/variable.types.d.ts +18 -0
  176. package/dist/wirings/variable/variable.types.js +1 -0
  177. package/dist/wirings/workflow/dsl/index.d.ts +1 -1
  178. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +7 -1
  179. package/dist/wirings/workflow/dsl/workflow-runner.js +3 -2
  180. package/dist/wirings/workflow/graph/graph-node.d.ts +1 -6
  181. package/dist/wirings/workflow/graph/graph-runner.d.ts +5 -31
  182. package/dist/wirings/workflow/graph/graph-runner.js +384 -296
  183. package/dist/wirings/workflow/graph/index.d.ts +4 -3
  184. package/dist/wirings/workflow/graph/index.js +3 -3
  185. package/dist/wirings/workflow/graph/template.d.ts +15 -0
  186. package/dist/wirings/workflow/graph/template.js +27 -0
  187. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +15 -0
  188. package/dist/wirings/workflow/graph/wire-workflow-graph.js +8 -0
  189. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -13
  190. package/dist/wirings/workflow/index.d.ts +6 -6
  191. package/dist/wirings/workflow/index.js +6 -4
  192. package/dist/wirings/workflow/pikku-workflow-service.d.ts +28 -14
  193. package/dist/wirings/workflow/pikku-workflow-service.js +200 -56
  194. package/dist/wirings/workflow/workflow-helpers.d.ts +36 -0
  195. package/dist/wirings/workflow/workflow-helpers.js +38 -0
  196. package/dist/wirings/workflow/workflow-utils.d.ts +1 -23
  197. package/dist/wirings/workflow/workflow-utils.js +1 -66
  198. package/dist/wirings/workflow/workflow.types.d.ts +40 -93
  199. package/package.json +13 -15
  200. package/run-tests.sh +4 -1
  201. package/src/crypto-utils.ts +99 -0
  202. package/src/errors/errors.ts +17 -0
  203. package/src/errors/index.ts +0 -1
  204. package/src/factory-functions.test.ts +42 -2
  205. package/src/function/function-runner.test.ts +4 -11
  206. package/src/function/function-runner.ts +114 -29
  207. package/src/function/functions.types.ts +62 -132
  208. package/src/function/index.ts +5 -2
  209. package/src/handle-error.ts +2 -10
  210. package/src/index.ts +99 -25
  211. package/src/middleware/auth-apikey.test.ts +15 -12
  212. package/src/middleware/auth-apikey.ts +3 -3
  213. package/src/middleware/auth-bearer.test.ts +17 -14
  214. package/src/middleware/auth-bearer.ts +25 -27
  215. package/src/middleware/auth-cookie.test.ts +16 -13
  216. package/src/middleware/auth-cookie.ts +6 -8
  217. package/src/middleware/cors.ts +96 -0
  218. package/src/middleware/index.ts +5 -3
  219. package/src/middleware/remote-auth.ts +68 -0
  220. package/src/middleware-runner.test.ts +122 -0
  221. package/src/middleware-runner.ts +12 -12
  222. package/src/permissions.test.ts +81 -7
  223. package/src/permissions.ts +15 -17
  224. package/src/pikku-state.ts +20 -8
  225. package/src/run-tests-script.test.ts +49 -0
  226. package/src/schema.ts +18 -15
  227. package/src/services/ai-agent-runner-service.ts +29 -0
  228. package/src/services/ai-run-state-service.ts +20 -0
  229. package/src/services/ai-storage-service.ts +39 -0
  230. package/src/services/deployment-service.ts +22 -0
  231. package/src/services/gopass-secrets.ts +95 -0
  232. package/src/services/in-memory-trigger-service.ts +68 -0
  233. package/src/services/in-memory-workflow-service.ts +395 -0
  234. package/src/services/index.ts +49 -14
  235. package/src/services/local-secrets.ts +51 -0
  236. package/src/services/local-variables.ts +22 -0
  237. package/src/services/scheduler-service.ts +29 -1
  238. package/src/services/schema-service.ts +7 -0
  239. package/src/services/scoped-secret-service.ts +41 -0
  240. package/src/services/secret-service.ts +25 -4
  241. package/src/services/trigger-service.ts +38 -0
  242. package/src/services/typed-secret-service.ts +70 -0
  243. package/src/services/typed-variables-service.ts +81 -0
  244. package/src/services/user-session-service.ts +23 -0
  245. package/src/services/variables-service.ts +5 -0
  246. package/src/services/workflow-service.ts +22 -2
  247. package/src/types/core.types.ts +76 -11
  248. package/src/types/state.types.ts +37 -63
  249. package/src/utils.ts +20 -6
  250. package/src/version.test.ts +80 -0
  251. package/src/version.ts +25 -0
  252. package/src/wirings/ai-agent/ai-agent-memory.ts +300 -0
  253. package/src/wirings/ai-agent/ai-agent-model-config.ts +43 -0
  254. package/src/wirings/ai-agent/ai-agent-prepare.ts +470 -0
  255. package/src/wirings/ai-agent/ai-agent-registry.test.ts +37 -0
  256. package/src/wirings/ai-agent/ai-agent-registry.ts +82 -0
  257. package/src/wirings/ai-agent/ai-agent-runner.test.ts +75 -0
  258. package/src/wirings/ai-agent/ai-agent-runner.ts +137 -0
  259. package/src/wirings/ai-agent/ai-agent-stream.test.ts +246 -0
  260. package/src/wirings/ai-agent/ai-agent-stream.ts +774 -0
  261. package/src/wirings/ai-agent/ai-agent.types.ts +273 -0
  262. package/src/wirings/ai-agent/index.ts +28 -0
  263. package/src/wirings/channel/channel-common.ts +32 -19
  264. package/src/wirings/channel/channel-handler.ts +17 -4
  265. package/src/wirings/channel/channel-middleware-runner.ts +119 -0
  266. package/src/wirings/channel/channel-runner.ts +9 -10
  267. package/src/wirings/channel/channel.types.ts +17 -1
  268. package/src/wirings/channel/define-channel-routes.ts +25 -0
  269. package/src/wirings/channel/index.ts +23 -8
  270. package/src/wirings/channel/local/index.ts +3 -3
  271. package/src/wirings/channel/local/local-channel-runner.test.ts +44 -1
  272. package/src/wirings/channel/local/local-channel-runner.ts +22 -6
  273. package/src/wirings/channel/serverless/index.ts +5 -1
  274. package/src/wirings/channel/serverless/serverless-channel-runner.ts +20 -4
  275. package/src/wirings/cli/channel/index.ts +1 -1
  276. package/src/wirings/cli/cli-runner.test.ts +9 -9
  277. package/src/wirings/cli/cli-runner.ts +17 -10
  278. package/src/wirings/cli/cli.types.ts +11 -11
  279. package/src/wirings/cli/command-parser.test.ts +8 -8
  280. package/src/wirings/cli/define-cli-commands.ts +24 -0
  281. package/src/wirings/cli/index.ts +10 -4
  282. package/src/wirings/http/http-routes.test.ts +322 -0
  283. package/src/wirings/http/http-routes.ts +198 -0
  284. package/src/wirings/http/http-runner.test.ts +3 -3
  285. package/src/wirings/http/http-runner.ts +63 -29
  286. package/src/wirings/http/http.types.ts +121 -37
  287. package/src/wirings/http/index.ts +16 -4
  288. package/src/wirings/mcp/index.ts +27 -3
  289. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +3 -3
  290. package/src/wirings/mcp/mcp-runner.ts +39 -50
  291. package/src/wirings/mcp/mcp.types.ts +3 -3
  292. package/src/wirings/node/index.ts +2 -0
  293. package/src/wirings/node/node.types.ts +23 -0
  294. package/src/wirings/oauth2/index.ts +3 -0
  295. package/src/wirings/oauth2/oauth2-client.test.ts +929 -0
  296. package/src/wirings/oauth2/oauth2-client.ts +335 -0
  297. package/src/wirings/oauth2/oauth2.types.ts +69 -0
  298. package/src/wirings/oauth2/wire-oauth2-credential.ts +23 -0
  299. package/src/wirings/queue/index.ts +14 -2
  300. package/src/wirings/queue/queue-runner.test.ts +97 -55
  301. package/src/wirings/queue/queue-runner.ts +33 -7
  302. package/src/wirings/queue/queue.types.ts +12 -2
  303. package/src/wirings/rpc/index.ts +1 -1
  304. package/src/wirings/rpc/rpc-runner.ts +187 -17
  305. package/src/wirings/rpc/rpc-types.ts +13 -4
  306. package/src/wirings/scheduler/index.ts +7 -4
  307. package/src/wirings/scheduler/scheduler-runner.test.ts +70 -26
  308. package/src/wirings/scheduler/scheduler-runner.ts +45 -5
  309. package/src/wirings/secret/index.ts +9 -0
  310. package/src/wirings/secret/secret.types.ts +32 -0
  311. package/src/wirings/secret/validate-secret-definitions.ts +82 -0
  312. package/src/wirings/trigger/index.ts +10 -2
  313. package/src/wirings/trigger/pikku-trigger-service.ts +134 -0
  314. package/src/wirings/trigger/trigger-runner.ts +80 -38
  315. package/src/wirings/trigger/trigger.types.ts +144 -22
  316. package/src/wirings/variable/index.ts +8 -0
  317. package/src/wirings/variable/validate-variable-definitions.ts +69 -0
  318. package/src/wirings/variable/variable.types.ts +22 -0
  319. package/src/wirings/workflow/dsl/index.ts +1 -0
  320. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +9 -1
  321. package/src/wirings/workflow/dsl/workflow-runner.ts +4 -3
  322. package/src/wirings/workflow/graph/graph-node.ts +1 -6
  323. package/src/wirings/workflow/graph/graph-runner.test.ts +495 -0
  324. package/src/wirings/workflow/graph/graph-runner.ts +496 -374
  325. package/src/wirings/workflow/graph/index.ts +14 -3
  326. package/src/wirings/workflow/graph/template.ts +42 -0
  327. package/src/wirings/workflow/graph/wire-workflow-graph.ts +29 -0
  328. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -22
  329. package/src/wirings/workflow/index.ts +21 -10
  330. package/src/wirings/workflow/pikku-workflow-service.test.ts +212 -0
  331. package/src/wirings/workflow/pikku-workflow-service.ts +285 -66
  332. package/src/wirings/workflow/workflow-helpers.ts +79 -0
  333. package/src/wirings/workflow/workflow-utils.ts +0 -120
  334. package/src/wirings/workflow/workflow.types.ts +45 -90
  335. package/tsconfig.tsbuildinfo +1 -1
  336. package/dist/wirings/forge-node/forge-node.types.d.ts +0 -120
  337. package/dist/wirings/forge-node/forge-node.types.js +0 -38
  338. package/dist/wirings/forge-node/index.d.ts +0 -1
  339. package/dist/wirings/forge-node/index.js +0 -1
  340. package/dist/wirings/workflow/wire-workflow.d.ts +0 -42
  341. package/dist/wirings/workflow/wire-workflow.js +0 -53
  342. package/src/wirings/forge-node/forge-node.types.ts +0 -135
  343. package/src/wirings/forge-node/index.ts +0 -1
  344. package/src/wirings/workflow/wire-workflow.ts +0 -94
@@ -0,0 +1,15 @@
1
+ import type { CoreAIAgent } from './ai-agent.types.js';
2
+ import { AIRunStateService } from '../../services/ai-run-state-service.js';
3
+ export declare const addAIAgent: (agentName: string, agent: CoreAIAgent<any, any>, packageName?: string | null) => void;
4
+ export declare function approveAIAgent(aiRunState: AIRunStateService, runId: string, approvals: {
5
+ toolCallId: string;
6
+ approved: boolean;
7
+ }[], expectedAgentName?: string): Promise<{
8
+ status: 'resumed' | 'suspended';
9
+ runId: string;
10
+ approved: string[];
11
+ rejected: string[];
12
+ remainingApprovals: number;
13
+ }>;
14
+ export declare const getAIAgents: () => Map<string, CoreAIAgent>;
15
+ export declare const getAIAgentsMeta: () => import("./ai-agent.types.js").AIAgentMeta;
@@ -0,0 +1,47 @@
1
+ import { pikkuState } from '../../pikku-state.js';
2
+ import { PikkuMissingMetaError } from '../../errors/errors.js';
3
+ export const addAIAgent = (agentName, agent, packageName = null) => {
4
+ const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta');
5
+ const agentMeta = agentsMeta[agentName];
6
+ if (!agentMeta) {
7
+ throw new PikkuMissingMetaError(`Missing generated metadata for AI agent '${agentName}'`);
8
+ }
9
+ const agents = pikkuState(packageName, 'agent', 'agents');
10
+ if (agents.has(agentName)) {
11
+ throw new Error(`AI agent already exists: ${agentName}`);
12
+ }
13
+ agents.set(agentName, agent);
14
+ };
15
+ export async function approveAIAgent(aiRunState, runId, approvals, expectedAgentName) {
16
+ if (!aiRunState)
17
+ throw new Error('AIRunStateService not available');
18
+ const run = await aiRunState.getRun(runId);
19
+ if (!run)
20
+ throw new Error('Run not found: ' + runId);
21
+ if (expectedAgentName && run.agentName !== expectedAgentName) {
22
+ throw new Error(`Run ${runId} belongs to agent '${run.agentName}', not '${expectedAgentName}'`);
23
+ }
24
+ if (run.status !== 'suspended')
25
+ throw new Error('Run is not suspended: ' + run.status);
26
+ const approvedIds = new Set(approvals.filter((a) => a.approved).map((a) => a.toolCallId));
27
+ const rejectedIds = new Set(approvals.filter((a) => !a.approved).map((a) => a.toolCallId));
28
+ const remaining = (run.pendingApprovals ?? []).filter((p) => !approvedIds.has(p.toolCallId) && !rejectedIds.has(p.toolCallId));
29
+ const hasApproved = approvedIds.size > 0;
30
+ await aiRunState.updateRun(runId, {
31
+ status: hasApproved ? 'running' : 'suspended',
32
+ pendingApprovals: remaining.length > 0 ? remaining : undefined,
33
+ });
34
+ return {
35
+ status: hasApproved ? 'resumed' : 'suspended',
36
+ runId,
37
+ approved: [...approvedIds],
38
+ rejected: [...rejectedIds],
39
+ remainingApprovals: remaining.length,
40
+ };
41
+ }
42
+ export const getAIAgents = () => {
43
+ return pikkuState(null, 'agent', 'agents');
44
+ };
45
+ export const getAIAgentsMeta = () => {
46
+ return pikkuState(null, 'agent', 'agentsMeta');
47
+ };
@@ -0,0 +1,3 @@
1
+ import type { AIAgentInput, AIAgentOutput } from './ai-agent.types.js';
2
+ import { type RunAIAgentParams } from './ai-agent-prepare.js';
3
+ export declare function runAIAgent(agentName: string, input: AIAgentInput, params: RunAIAgentParams, agentSessionMap?: Map<string, string>): Promise<AIAgentOutput>;
@@ -0,0 +1,96 @@
1
+ import { saveMessages } from './ai-agent-memory.js';
2
+ import { prepareAgentRun } from './ai-agent-prepare.js';
3
+ export async function runAIAgent(agentName, input, params, agentSessionMap) {
4
+ const sessionMap = agentSessionMap ?? new Map();
5
+ const { agent, agentRunner, storage, memoryConfig, threadId, userMessage, runnerParams, missingRpcs, workingMemoryJsonSchema, workingMemorySchemaName, } = await prepareAgentRun(agentName, input, params, sessionMap);
6
+ const { singletonServices } = params;
7
+ const { aiRunState } = singletonServices;
8
+ if (!aiRunState) {
9
+ throw new Error('AIRunStateService not available in singletonServices');
10
+ }
11
+ if (missingRpcs.length > 0) {
12
+ const runId = await aiRunState.createRun({
13
+ agentName,
14
+ threadId,
15
+ resourceId: input.resourceId,
16
+ status: 'suspended',
17
+ suspendReason: 'rpc-missing',
18
+ missingRpcs,
19
+ usage: { inputTokens: 0, outputTokens: 0, model: agent.model },
20
+ createdAt: new Date(),
21
+ updatedAt: new Date(),
22
+ });
23
+ return {
24
+ runId,
25
+ text: '',
26
+ threadId,
27
+ steps: [],
28
+ usage: { inputTokens: 0, outputTokens: 0 },
29
+ };
30
+ }
31
+ const aiMiddlewares = agent.aiMiddleware ?? [];
32
+ let modifiedMessages = runnerParams.messages;
33
+ let modifiedInstructions = runnerParams.instructions;
34
+ for (const mw of aiMiddlewares) {
35
+ if (mw.modifyInput) {
36
+ const result = await mw.modifyInput(singletonServices, {
37
+ messages: modifiedMessages,
38
+ instructions: modifiedInstructions,
39
+ });
40
+ modifiedMessages = result.messages;
41
+ modifiedInstructions = result.instructions;
42
+ }
43
+ }
44
+ runnerParams.messages = modifiedMessages;
45
+ runnerParams.instructions = modifiedInstructions;
46
+ const runId = await aiRunState.createRun({
47
+ agentName,
48
+ threadId,
49
+ resourceId: input.resourceId,
50
+ status: 'running',
51
+ usage: { inputTokens: 0, outputTokens: 0, model: agent.model },
52
+ createdAt: new Date(),
53
+ updatedAt: new Date(),
54
+ });
55
+ try {
56
+ const result = await agentRunner.run(runnerParams);
57
+ const responseText = await saveMessages(storage, threadId, input.resourceId, memoryConfig, userMessage, result, {
58
+ workingMemoryJsonSchema,
59
+ workingMemorySchemaName,
60
+ logger: singletonServices.logger,
61
+ schemaService: singletonServices.schema,
62
+ });
63
+ let outputText = responseText;
64
+ let outputMessages = runnerParams.messages;
65
+ for (let i = aiMiddlewares.length - 1; i >= 0; i--) {
66
+ const mw = aiMiddlewares[i];
67
+ if (mw.modifyOutput) {
68
+ const modResult = await mw.modifyOutput(singletonServices, {
69
+ text: outputText,
70
+ messages: outputMessages,
71
+ usage: result.usage,
72
+ });
73
+ outputText = modResult.text;
74
+ outputMessages = modResult.messages;
75
+ }
76
+ }
77
+ await aiRunState.updateRun(runId, {
78
+ status: 'completed',
79
+ usage: { ...result.usage, model: agent.model },
80
+ });
81
+ return {
82
+ runId,
83
+ text: outputText,
84
+ object: result.object,
85
+ threadId,
86
+ steps: result.steps,
87
+ usage: result.usage,
88
+ };
89
+ }
90
+ catch (error) {
91
+ await aiRunState.updateRun(runId, {
92
+ status: 'failed',
93
+ });
94
+ throw error;
95
+ }
96
+ }
@@ -0,0 +1,11 @@
1
+ import type { AIStreamChannel } from './ai-agent.types.js';
2
+ import { type RunAIAgentParams, type StreamAIAgentOptions } from './ai-agent-prepare.js';
3
+ export declare function streamAIAgent(agentName: string, input: {
4
+ message: string;
5
+ threadId: string;
6
+ resourceId: string;
7
+ }, channel: AIStreamChannel, params: RunAIAgentParams, agentSessionMap?: Map<string, string>, options?: StreamAIAgentOptions): Promise<void>;
8
+ export declare function resumeAIAgent(input: {
9
+ toolCallId: string;
10
+ approved: boolean;
11
+ }, channel: AIStreamChannel, params: RunAIAgentParams, options?: StreamAIAgentOptions): Promise<void>;
@@ -0,0 +1,503 @@
1
+ import { pikkuState } from '../../pikku-state.js';
2
+ import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../channel/channel-middleware-runner.js';
3
+ import { randomUUID } from 'crypto';
4
+ import { parseWorkingMemory, deepMergeWorkingMemory, resolveMemoryServices, loadContextMessages, trimMessages, } from './ai-agent-memory.js';
5
+ import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, createScopedChannel, ToolApprovalRequired, } from './ai-agent-prepare.js';
6
+ import { resolveModelConfig } from './ai-agent-model-config.js';
7
+ function createPersistingChannel(parent, storage, threadId) {
8
+ let fullText = '';
9
+ let stepText = '';
10
+ let stepToolCalls = [];
11
+ let stepToolResults = [];
12
+ const flushStep = async () => {
13
+ if (!storage)
14
+ return;
15
+ const text = stepText;
16
+ const calls = stepToolCalls;
17
+ const results = stepToolResults;
18
+ stepText = '';
19
+ stepToolCalls = [];
20
+ stepToolResults = [];
21
+ if (text || calls.length > 0) {
22
+ const assistantMsg = {
23
+ id: randomUUID(),
24
+ role: 'assistant',
25
+ content: text || undefined,
26
+ toolCalls: calls.length > 0 ? calls : undefined,
27
+ createdAt: new Date(),
28
+ };
29
+ const messages = [assistantMsg];
30
+ if (results.length > 0) {
31
+ messages.push({
32
+ id: randomUUID(),
33
+ role: 'tool',
34
+ toolResults: results,
35
+ createdAt: new Date(),
36
+ });
37
+ }
38
+ await storage.saveMessages(threadId, messages);
39
+ }
40
+ };
41
+ const channel = {
42
+ channelId: parent.channelId,
43
+ openingData: parent.openingData,
44
+ get state() {
45
+ return parent.state;
46
+ },
47
+ get fullText() {
48
+ return fullText;
49
+ },
50
+ flush: flushStep,
51
+ close: () => parent.close(),
52
+ send: (event) => {
53
+ if (storage) {
54
+ switch (event.type) {
55
+ case 'text-delta':
56
+ stepText += event.text;
57
+ fullText += event.text;
58
+ break;
59
+ case 'tool-call':
60
+ stepToolCalls.push({
61
+ id: event.toolCallId,
62
+ name: event.toolName,
63
+ args: event.args,
64
+ });
65
+ break;
66
+ case 'tool-result':
67
+ stepToolResults.push({
68
+ id: event.toolCallId,
69
+ name: event.toolName,
70
+ result: typeof event.result === 'string'
71
+ ? event.result
72
+ : JSON.stringify(event.result),
73
+ });
74
+ break;
75
+ case 'usage':
76
+ flushStep();
77
+ break;
78
+ case 'done':
79
+ flushStep();
80
+ break;
81
+ }
82
+ }
83
+ parent.send(event);
84
+ },
85
+ };
86
+ return channel;
87
+ }
88
+ async function postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, storage, memoryConfig, threadId, workingMemorySchemaName, messages, aiRunState, runId) {
89
+ let outputText = persistingChannel.fullText;
90
+ let outputMessages = messages;
91
+ for (let i = aiMiddlewares.length - 1; i >= 0; i--) {
92
+ const mw = aiMiddlewares[i];
93
+ if (mw.modifyOutput) {
94
+ const result = await mw.modifyOutput(singletonServices, {
95
+ text: outputText,
96
+ messages: outputMessages,
97
+ usage: { inputTokens: 0, outputTokens: 0 },
98
+ });
99
+ outputText = result.text;
100
+ outputMessages = result.messages;
101
+ }
102
+ }
103
+ if (storage && memoryConfig?.workingMemory && outputText) {
104
+ const parsed = parseWorkingMemory(outputText);
105
+ if (parsed) {
106
+ const existing = (await storage.getWorkingMemory(threadId, 'thread')) ?? {};
107
+ const merged = deepMergeWorkingMemory(existing, parsed);
108
+ if (singletonServices.schema && workingMemorySchemaName) {
109
+ try {
110
+ await singletonServices.schema.validateSchema(workingMemorySchemaName, merged);
111
+ }
112
+ catch (err) {
113
+ singletonServices.logger.warn(`Working memory validation failed: ${err instanceof Error ? err.message : String(err)}`);
114
+ }
115
+ }
116
+ await storage.saveWorkingMemory(threadId, 'thread', merged);
117
+ }
118
+ }
119
+ await aiRunState.updateRun(runId, { status: 'completed' });
120
+ }
121
+ export async function streamAIAgent(agentName, input, channel, params, agentSessionMap, options) {
122
+ const sessionMap = agentSessionMap ?? new Map();
123
+ const streamContext = { channel, options };
124
+ const { agent, packageName, resolvedName, agentRunner, storage, memoryConfig, threadId, userMessage, runnerParams, missingRpcs, workingMemorySchemaName, } = await prepareAgentRun(agentName, input, params, sessionMap, streamContext);
125
+ const { singletonServices } = params;
126
+ const { aiRunState } = singletonServices;
127
+ if (!aiRunState) {
128
+ throw new Error('AIRunStateService not available in singletonServices');
129
+ }
130
+ if (missingRpcs.length > 0) {
131
+ await aiRunState.createRun({
132
+ agentName,
133
+ threadId,
134
+ resourceId: input.resourceId,
135
+ status: 'suspended',
136
+ suspendReason: 'rpc-missing',
137
+ missingRpcs,
138
+ usage: { inputTokens: 0, outputTokens: 0, model: agent.model },
139
+ createdAt: new Date(),
140
+ updatedAt: new Date(),
141
+ });
142
+ channel.send({ type: 'suspended', reason: 'rpc-missing', missingRpcs });
143
+ channel.send({ type: 'done' });
144
+ return;
145
+ }
146
+ const aiMiddlewares = agent.aiMiddleware ?? [];
147
+ let modifiedMessages = runnerParams.messages;
148
+ let modifiedInstructions = runnerParams.instructions;
149
+ for (const mw of aiMiddlewares) {
150
+ if (mw.modifyInput) {
151
+ const result = await mw.modifyInput(singletonServices, {
152
+ messages: modifiedMessages,
153
+ instructions: modifiedInstructions,
154
+ });
155
+ modifiedMessages = result.messages;
156
+ modifiedInstructions = result.instructions;
157
+ }
158
+ }
159
+ runnerParams.messages = modifiedMessages;
160
+ runnerParams.instructions = modifiedInstructions;
161
+ const runId = await aiRunState.createRun({
162
+ agentName,
163
+ threadId,
164
+ resourceId: input.resourceId,
165
+ status: 'running',
166
+ usage: { inputTokens: 0, outputTokens: 0, model: agent.model },
167
+ createdAt: new Date(),
168
+ updatedAt: new Date(),
169
+ });
170
+ if (storage) {
171
+ await storage.saveMessages(threadId, [userMessage]);
172
+ }
173
+ const streamMiddleware = aiMiddlewares
174
+ .filter((mw) => mw.modifyOutputStream)
175
+ .map((mw) => {
176
+ const state = {};
177
+ const allEvents = [];
178
+ return async (services, event, next) => {
179
+ allEvents.push(event);
180
+ const result = await mw.modifyOutputStream(services, {
181
+ event,
182
+ allEvents,
183
+ state,
184
+ });
185
+ if (result != null)
186
+ await next(result);
187
+ };
188
+ });
189
+ const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta');
190
+ const meta = agentsMeta[resolvedName];
191
+ const allChannelMiddleware = combineChannelMiddleware('agent', `stream:${agentName}`, {
192
+ wireInheritedChannelMiddleware: meta?.channelMiddleware,
193
+ wireChannelMiddleware: [
194
+ ...(agent.channelMiddleware ?? []),
195
+ ...streamMiddleware,
196
+ ],
197
+ });
198
+ const wrappedChannel = allChannelMiddleware.length > 0
199
+ ? wrapChannelWithMiddleware({ channel }, singletonServices, allChannelMiddleware).channel
200
+ : channel;
201
+ const persistingChannel = createPersistingChannel(wrappedChannel, storage, threadId);
202
+ try {
203
+ await agentRunner.stream(runnerParams, persistingChannel);
204
+ await postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, storage, memoryConfig, threadId, workingMemorySchemaName, runnerParams.messages, aiRunState, runId);
205
+ }
206
+ catch (err) {
207
+ if (err instanceof ToolApprovalRequired) {
208
+ await persistingChannel.flush();
209
+ const pendingApproval = err.agentRunId
210
+ ? {
211
+ type: 'agent-call',
212
+ toolCallId: err.toolCallId,
213
+ agentName: err.toolName,
214
+ agentRunId: err.agentRunId,
215
+ displayToolName: err.displayToolName ?? err.toolName,
216
+ displayArgs: err.displayArgs ?? err.args,
217
+ }
218
+ : {
219
+ type: 'tool-call',
220
+ toolCallId: err.toolCallId,
221
+ toolName: err.toolName,
222
+ args: err.args,
223
+ };
224
+ await aiRunState.updateRun(runId, {
225
+ status: 'suspended',
226
+ suspendReason: 'approval',
227
+ pendingApprovals: [pendingApproval],
228
+ });
229
+ const approvalEvent = {
230
+ type: 'approval-request',
231
+ toolCallId: err.toolCallId,
232
+ toolName: err.displayToolName ?? err.toolName,
233
+ args: err.displayArgs ?? err.args,
234
+ reason: err.reason,
235
+ runId,
236
+ };
237
+ channel.send(approvalEvent);
238
+ channel.send({ type: 'done' });
239
+ channel.close();
240
+ return;
241
+ }
242
+ await aiRunState.updateRun(runId, { status: 'failed' });
243
+ channel.send({
244
+ type: 'error',
245
+ message: err instanceof Error ? err.message : String(err),
246
+ });
247
+ channel.send({ type: 'done' });
248
+ channel.close();
249
+ }
250
+ }
251
+ export async function resumeAIAgent(input, channel, params, options) {
252
+ const { singletonServices } = params;
253
+ const { aiRunState } = singletonServices;
254
+ if (!aiRunState) {
255
+ throw new Error('AIRunStateService not available in singletonServices');
256
+ }
257
+ const found = await aiRunState.findRunByToolCallId(input.toolCallId);
258
+ if (!found) {
259
+ throw new Error(`No suspended run found for toolCallId ${input.toolCallId}`);
260
+ }
261
+ const { run, approval: pending } = found;
262
+ await aiRunState.resolveApproval(input.toolCallId, input.approved ? 'approved' : 'denied');
263
+ const { agent, packageName, resolvedName } = resolveAgent(run.agentName);
264
+ const { storage } = resolveMemoryServices(agent, singletonServices);
265
+ const memoryConfig = agent.memory;
266
+ const agentRunner = singletonServices.aiAgentRunner;
267
+ if (!agentRunner) {
268
+ throw new Error('AIAgentRunnerService not available in singletonServices');
269
+ }
270
+ if (!input.approved) {
271
+ if (pending.type === 'agent-call') {
272
+ await aiRunState.updateRun(pending.agentRunId, { status: 'failed' });
273
+ }
274
+ const denialResult = 'Tool call was not approved by the user';
275
+ if (storage) {
276
+ await storage.saveMessages(run.threadId, [
277
+ {
278
+ id: randomUUID(),
279
+ role: 'tool',
280
+ toolResults: [
281
+ {
282
+ id: input.toolCallId,
283
+ name: pending.type === 'tool-call'
284
+ ? pending.toolName
285
+ : pending.agentName,
286
+ result: denialResult,
287
+ },
288
+ ],
289
+ createdAt: new Date(),
290
+ },
291
+ ]);
292
+ }
293
+ await aiRunState.updateRun(run.runId, { status: 'running' });
294
+ await continueAfterToolResult(run, agent, packageName, resolvedName, storage, memoryConfig, agentRunner, channel, params, aiRunState, options);
295
+ return;
296
+ }
297
+ if (pending.type === 'agent-call') {
298
+ const subRun = await aiRunState.getRun(pending.agentRunId);
299
+ if (!subRun) {
300
+ throw new Error(`Sub-agent run not found: ${pending.agentRunId}`);
301
+ }
302
+ const subPending = subRun.pendingApprovals?.[0];
303
+ if (!subPending) {
304
+ throw new Error(`No pending approval on sub-agent run ${pending.agentRunId}`);
305
+ }
306
+ const subChannel = createScopedChannel(channel, subRun.agentName, 'resume');
307
+ channel.send({
308
+ type: 'agent-call',
309
+ agentName: subRun.agentName,
310
+ session: 'resume',
311
+ input: null,
312
+ });
313
+ await resumeAIAgent({ toolCallId: subPending.toolCallId, approved: true }, subChannel, params, options);
314
+ channel.send({
315
+ type: 'agent-result',
316
+ agentName: subRun.agentName,
317
+ session: 'resume',
318
+ result: null,
319
+ });
320
+ if (storage) {
321
+ await storage.saveMessages(run.threadId, [
322
+ {
323
+ id: randomUUID(),
324
+ role: 'tool',
325
+ toolResults: [
326
+ {
327
+ id: input.toolCallId,
328
+ name: pending.agentName,
329
+ result: 'Sub-agent completed successfully',
330
+ },
331
+ ],
332
+ createdAt: new Date(),
333
+ },
334
+ ]);
335
+ }
336
+ }
337
+ else {
338
+ const streamContext = {
339
+ channel,
340
+ options: { ...options, requiresToolApproval: false },
341
+ };
342
+ const { tools } = buildToolDefs(singletonServices, params, new Map(), run.resourceId, resolvedName, packageName, streamContext);
343
+ const matchingTool = tools.find((t) => t.name === pending.toolName);
344
+ if (!matchingTool) {
345
+ throw new Error(`Tool "${pending.toolName}" not found in agent definition`);
346
+ }
347
+ const toolArgs = typeof pending.args === 'string' ? JSON.parse(pending.args) : pending.args;
348
+ const { toolApprovalReason: _ignored, ...cleanArgs } = toolArgs;
349
+ let toolResult;
350
+ try {
351
+ toolResult = await matchingTool.execute(cleanArgs);
352
+ }
353
+ catch (execErr) {
354
+ toolResult = `Error: ${execErr instanceof Error ? execErr.message : String(execErr)}`;
355
+ }
356
+ const resultStr = typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult);
357
+ if (storage) {
358
+ await storage.saveMessages(run.threadId, [
359
+ {
360
+ id: randomUUID(),
361
+ role: 'tool',
362
+ toolResults: [
363
+ {
364
+ id: input.toolCallId,
365
+ name: pending.toolName,
366
+ result: resultStr,
367
+ },
368
+ ],
369
+ createdAt: new Date(),
370
+ },
371
+ ]);
372
+ }
373
+ channel.send({
374
+ type: 'tool-result',
375
+ toolCallId: input.toolCallId,
376
+ toolName: pending.toolName,
377
+ result: toolResult,
378
+ });
379
+ }
380
+ await aiRunState.updateRun(run.runId, { status: 'running' });
381
+ await continueAfterToolResult(run, agent, packageName, resolvedName, storage, memoryConfig, agentRunner, channel, params, aiRunState, options);
382
+ }
383
+ async function continueAfterToolResult(run, agent, packageName, resolvedName, storage, memoryConfig, agentRunner, channel, params, aiRunState, options) {
384
+ const { singletonServices } = params;
385
+ const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta');
386
+ const meta = agentsMeta[resolvedName];
387
+ const workingMemorySchemaName = meta?.workingMemorySchema ?? null;
388
+ const messages = storage
389
+ ? await storage.getMessages(run.threadId, {
390
+ lastN: memoryConfig?.lastMessages ?? 20,
391
+ })
392
+ : [];
393
+ const workingMemoryJsonSchema = workingMemorySchemaName
394
+ ? pikkuState(packageName, 'misc', 'schemas').get(workingMemorySchemaName)
395
+ : undefined;
396
+ const contextMessages = await loadContextMessages(memoryConfig, storage, { message: '', threadId: run.threadId, resourceId: run.resourceId }, workingMemoryJsonSchema);
397
+ const allMessages = [...contextMessages, ...messages];
398
+ const trimmedMessages = trimMessages(allMessages);
399
+ const instructions = buildInstructions(resolvedName, packageName);
400
+ const aiMiddlewares = agent.aiMiddleware ?? [];
401
+ let modifiedMessages = trimmedMessages;
402
+ let modifiedInstructions = instructions;
403
+ for (const mw of aiMiddlewares) {
404
+ if (mw.modifyInput) {
405
+ const result = await mw.modifyInput(singletonServices, {
406
+ messages: modifiedMessages,
407
+ instructions: modifiedInstructions,
408
+ });
409
+ modifiedMessages = result.messages;
410
+ modifiedInstructions = result.instructions;
411
+ }
412
+ }
413
+ const streamMiddleware = aiMiddlewares
414
+ .filter((mw) => mw.modifyOutputStream)
415
+ .map((mw) => {
416
+ const state = {};
417
+ const allEvents = [];
418
+ return async (services, event, next) => {
419
+ allEvents.push(event);
420
+ const result = await mw.modifyOutputStream(services, {
421
+ event,
422
+ allEvents,
423
+ state,
424
+ });
425
+ if (result != null)
426
+ await next(result);
427
+ };
428
+ });
429
+ const allChannelMiddleware = combineChannelMiddleware('agent', `stream:${run.agentName}`, {
430
+ wireInheritedChannelMiddleware: meta?.channelMiddleware,
431
+ wireChannelMiddleware: [
432
+ ...(agent.channelMiddleware ?? []),
433
+ ...streamMiddleware,
434
+ ],
435
+ });
436
+ const wrappedChannel = allChannelMiddleware.length > 0
437
+ ? wrapChannelWithMiddleware({ channel }, singletonServices, allChannelMiddleware).channel
438
+ : channel;
439
+ const persistingChannel = createPersistingChannel(wrappedChannel, storage, run.threadId);
440
+ const streamContext = { channel, options };
441
+ const resumeTools = buildToolDefs(singletonServices, params, new Map(), run.resourceId, resolvedName, packageName, streamContext).tools;
442
+ const resolved = resolveModelConfig(resolvedName, agent);
443
+ const runnerParams = {
444
+ model: resolved.model,
445
+ temperature: resolved.temperature,
446
+ instructions: modifiedInstructions,
447
+ messages: modifiedMessages,
448
+ tools: resumeTools,
449
+ maxSteps: resolved.maxSteps ?? 10,
450
+ toolChoice: (agent.toolChoice ?? 'auto'),
451
+ outputSchema: meta?.outputSchema
452
+ ? pikkuState(packageName, 'misc', 'schemas').get(meta.outputSchema)
453
+ : undefined,
454
+ };
455
+ try {
456
+ await agentRunner.stream(runnerParams, persistingChannel);
457
+ await postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, storage, memoryConfig, run.threadId, workingMemorySchemaName, runnerParams.messages, aiRunState, run.runId);
458
+ }
459
+ catch (err) {
460
+ if (err instanceof ToolApprovalRequired) {
461
+ await persistingChannel.flush();
462
+ const pendingApproval = err.agentRunId
463
+ ? {
464
+ type: 'agent-call',
465
+ toolCallId: err.toolCallId,
466
+ agentName: err.toolName,
467
+ agentRunId: err.agentRunId,
468
+ displayToolName: err.displayToolName ?? err.toolName,
469
+ displayArgs: err.displayArgs ?? err.args,
470
+ }
471
+ : {
472
+ type: 'tool-call',
473
+ toolCallId: err.toolCallId,
474
+ toolName: err.toolName,
475
+ args: err.args,
476
+ };
477
+ await aiRunState.updateRun(run.runId, {
478
+ status: 'suspended',
479
+ suspendReason: 'approval',
480
+ pendingApprovals: [pendingApproval],
481
+ });
482
+ const approvalEvent = {
483
+ type: 'approval-request',
484
+ toolCallId: err.toolCallId,
485
+ toolName: err.displayToolName ?? err.toolName,
486
+ args: err.displayArgs ?? err.args,
487
+ reason: err.reason,
488
+ runId: run.runId,
489
+ };
490
+ channel.send(approvalEvent);
491
+ channel.send({ type: 'done' });
492
+ channel.close();
493
+ return;
494
+ }
495
+ await aiRunState.updateRun(run.runId, { status: 'failed' });
496
+ channel.send({
497
+ type: 'error',
498
+ message: err instanceof Error ? err.message : String(err),
499
+ });
500
+ channel.send({ type: 'done' });
501
+ channel.close();
502
+ }
503
+ }