@pikku/core 0.12.0 → 0.12.2

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 (290) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/errors/errors.d.ts +6 -0
  3. package/dist/errors/errors.js +10 -0
  4. package/dist/errors/index.d.ts +1 -0
  5. package/dist/errors/index.js +1 -0
  6. package/dist/function/function-runner.d.ts +3 -3
  7. package/dist/function/function-runner.js +66 -44
  8. package/dist/function/functions.types.d.ts +1 -0
  9. package/dist/handle-error.d.ts +2 -2
  10. package/dist/handle-error.js +2 -2
  11. package/dist/index.d.ts +5 -3
  12. package/dist/index.js +2 -1
  13. package/dist/internal.d.ts +3 -0
  14. package/dist/internal.js +2 -0
  15. package/dist/middleware/auth-bearer.d.ts +1 -1
  16. package/dist/middleware/auth-bearer.js +1 -1
  17. package/dist/middleware/auth-cookie.d.ts +2 -2
  18. package/dist/middleware/auth-cookie.js +1 -1
  19. package/dist/middleware/cors.d.ts +2 -2
  20. package/dist/middleware/cors.js +45 -37
  21. package/dist/middleware-runner.d.ts +1 -1
  22. package/dist/middleware-runner.js +1 -0
  23. package/dist/permissions.d.ts +2 -2
  24. package/dist/permissions.js +1 -0
  25. package/dist/pikku-state.d.ts +9 -8
  26. package/dist/pikku-state.js +34 -17
  27. package/dist/schema.d.ts +4 -4
  28. package/dist/schema.js +9 -5
  29. package/dist/services/ai-agent-runner-service.d.ts +22 -3
  30. package/dist/services/ai-run-state-service.d.ts +1 -1
  31. package/dist/services/ai-storage-service.d.ts +1 -1
  32. package/dist/services/content-service.d.ts +6 -0
  33. package/dist/services/gateway-service.d.ts +19 -0
  34. package/dist/services/gopass-secrets.d.ts +1 -1
  35. package/dist/services/gopass-secrets.js +3 -0
  36. package/dist/services/in-memory-ai-run-state-service.d.ts +15 -0
  37. package/dist/services/in-memory-ai-run-state-service.js +44 -0
  38. package/dist/services/in-memory-trigger-service.d.ts +0 -1
  39. package/dist/services/in-memory-trigger-service.js +6 -8
  40. package/dist/services/index.d.ts +5 -2
  41. package/dist/services/index.js +2 -0
  42. package/dist/services/local-content.d.ts +2 -1
  43. package/dist/services/local-content.js +6 -1
  44. package/dist/services/local-gateway-service.d.ts +22 -0
  45. package/dist/services/local-gateway-service.js +51 -0
  46. package/dist/services/local-secrets.d.ts +2 -2
  47. package/dist/services/local-variables.d.ts +1 -1
  48. package/dist/services/logger-console.d.ts +2 -1
  49. package/dist/services/scheduler-service.d.ts +0 -12
  50. package/dist/services/scheduler-service.js +0 -6
  51. package/dist/services/scoped-secret-service.d.ts +1 -1
  52. package/dist/services/trigger-service.d.ts +0 -7
  53. package/dist/services/user-session-service.d.ts +3 -3
  54. package/dist/services/workflow-service.d.ts +2 -3
  55. package/dist/types/core.types.d.ts +27 -19
  56. package/dist/types/state.types.d.ts +22 -15
  57. package/dist/utils.d.ts +5 -5
  58. package/dist/utils.js +12 -9
  59. package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +5 -0
  60. package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +168 -0
  61. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +28 -0
  62. package/dist/wirings/ai-agent/ai-agent-helpers.js +40 -0
  63. package/dist/wirings/ai-agent/ai-agent-memory.js +13 -2
  64. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +4 -5
  65. package/dist/wirings/ai-agent/ai-agent-prepare.js +80 -31
  66. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +1 -1
  67. package/dist/wirings/ai-agent/ai-agent-runner.js +107 -8
  68. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +2 -1
  69. package/dist/wirings/ai-agent/ai-agent-stream.js +263 -89
  70. package/dist/wirings/ai-agent/ai-agent.types.d.ts +96 -4
  71. package/dist/wirings/ai-agent/index.d.ts +3 -1
  72. package/dist/wirings/ai-agent/index.js +2 -0
  73. package/dist/wirings/channel/channel-common.d.ts +2 -2
  74. package/dist/wirings/channel/channel-handler.d.ts +7 -4
  75. package/dist/wirings/channel/channel-handler.js +15 -5
  76. package/dist/wirings/channel/channel-middleware-runner.js +1 -0
  77. package/dist/wirings/channel/channel-runner.d.ts +5 -5
  78. package/dist/wirings/channel/channel-runner.js +3 -2
  79. package/dist/wirings/channel/channel-store.d.ts +1 -1
  80. package/dist/wirings/channel/channel.types.d.ts +10 -6
  81. package/dist/wirings/channel/index.d.ts +1 -1
  82. package/dist/wirings/channel/local/local-channel-handler.d.ts +7 -0
  83. package/dist/wirings/channel/local/local-channel-handler.js +17 -0
  84. package/dist/wirings/channel/local/local-channel-runner.d.ts +7 -2
  85. package/dist/wirings/channel/local/local-channel-runner.js +18 -4
  86. package/dist/wirings/channel/local/local-eventhub-service.d.ts +2 -2
  87. package/dist/wirings/channel/log-channels.d.ts +1 -1
  88. package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +2 -1
  89. package/dist/wirings/channel/pikku-abstract-channel-handler.js +1 -0
  90. package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +4 -4
  91. package/dist/wirings/channel/serverless/serverless-channel-runner.js +26 -20
  92. package/dist/wirings/cli/channel/cli-channel-runner.d.ts +1 -1
  93. package/dist/wirings/cli/cli-runner.d.ts +2 -2
  94. package/dist/wirings/cli/cli-runner.js +3 -0
  95. package/dist/wirings/cli/cli.types.d.ts +3 -3
  96. package/dist/wirings/cli/command-parser.d.ts +1 -1
  97. package/dist/wirings/gateway/gateway-runner.d.ts +24 -0
  98. package/dist/wirings/gateway/gateway-runner.js +325 -0
  99. package/dist/wirings/gateway/gateway.types.d.ts +127 -0
  100. package/dist/wirings/gateway/index.d.ts +2 -0
  101. package/dist/wirings/gateway/index.js +1 -0
  102. package/dist/wirings/http/http-runner.d.ts +9 -9
  103. package/dist/wirings/http/http-runner.js +36 -14
  104. package/dist/wirings/http/http.types.d.ts +2 -6
  105. package/dist/wirings/http/log-http-routes.d.ts +1 -1
  106. package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -1
  107. package/dist/wirings/http/pikku-fetch-http-response.d.ts +2 -2
  108. package/dist/wirings/http/pikku-fetch-http-response.js +6 -1
  109. package/dist/wirings/http/routers/http-router.d.ts +1 -1
  110. package/dist/wirings/http/routers/path-to-regex.d.ts +2 -2
  111. package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +1 -1
  112. package/dist/wirings/mcp/mcp-runner.d.ts +0 -3
  113. package/dist/wirings/mcp/mcp-runner.js +4 -2
  114. package/dist/wirings/mcp/mcp.types.d.ts +2 -2
  115. package/dist/wirings/oauth2/oauth2-client.d.ts +3 -3
  116. package/dist/wirings/oauth2/wire-oauth2-credential.d.ts +1 -1
  117. package/dist/wirings/queue/index.d.ts +1 -1
  118. package/dist/wirings/queue/index.js +1 -1
  119. package/dist/wirings/queue/queue-runner.d.ts +1 -12
  120. package/dist/wirings/queue/queue-runner.js +4 -12
  121. package/dist/wirings/queue/queue.types.d.ts +3 -9
  122. package/dist/wirings/queue/register-queue-helper.d.ts +2 -2
  123. package/dist/wirings/queue/register-queue-helper.js +1 -1
  124. package/dist/wirings/queue/validate-worker-config.d.ts +1 -1
  125. package/dist/wirings/rpc/index.d.ts +2 -0
  126. package/dist/wirings/rpc/index.js +1 -0
  127. package/dist/wirings/rpc/rpc-runner.d.ts +36 -14
  128. package/dist/wirings/rpc/rpc-runner.js +56 -28
  129. package/dist/wirings/rpc/rpc-types.d.ts +14 -2
  130. package/dist/wirings/rpc/wire-addon.d.ts +10 -0
  131. package/dist/wirings/rpc/wire-addon.js +9 -0
  132. package/dist/wirings/scheduler/index.d.ts +1 -1
  133. package/dist/wirings/scheduler/index.js +1 -1
  134. package/dist/wirings/scheduler/log-schedulers.d.ts +1 -1
  135. package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -10
  136. package/dist/wirings/scheduler/scheduler-runner.js +4 -25
  137. package/dist/wirings/scheduler/scheduler.types.d.ts +2 -2
  138. package/dist/wirings/trigger/pikku-trigger-service.d.ts +2 -6
  139. package/dist/wirings/trigger/pikku-trigger-service.js +11 -16
  140. package/dist/wirings/trigger/trigger-runner.d.ts +1 -5
  141. package/dist/wirings/trigger/trigger-runner.js +4 -3
  142. package/dist/wirings/workflow/pikku-workflow-service.d.ts +2 -6
  143. package/dist/wirings/workflow/pikku-workflow-service.js +20 -29
  144. package/dist/wirings/workflow/workflow.types.d.ts +2 -2
  145. package/package.json +4 -2
  146. package/src/crypto-utils.test.ts +116 -0
  147. package/src/errors/error.test.ts +143 -2
  148. package/src/errors/errors.ts +10 -0
  149. package/src/errors/index.ts +1 -0
  150. package/src/function/function-runner.test.ts +2 -2
  151. package/src/function/function-runner.ts +72 -49
  152. package/src/function/functions.types.ts +1 -0
  153. package/src/handle-error.test.ts +361 -0
  154. package/src/handle-error.ts +4 -4
  155. package/src/index.ts +3 -10
  156. package/src/internal.ts +6 -0
  157. package/src/middleware/auth-apikey.test.ts +1 -1
  158. package/src/middleware/auth-bearer.test.ts +1 -1
  159. package/src/middleware/auth-bearer.ts +2 -5
  160. package/src/middleware/auth-cookie.test.ts +1 -1
  161. package/src/middleware/auth-cookie.ts +3 -5
  162. package/src/middleware/cors.test.ts +424 -0
  163. package/src/middleware/cors.ts +14 -6
  164. package/src/middleware/remote-auth.test.ts +488 -0
  165. package/src/middleware-runner.test.ts +1 -1
  166. package/src/middleware-runner.ts +2 -1
  167. package/src/permissions.test.ts +2 -2
  168. package/src/permissions.ts +3 -2
  169. package/src/pikku-state.test.ts +224 -0
  170. package/src/pikku-state.ts +45 -28
  171. package/src/schema.test.ts +198 -6
  172. package/src/schema.ts +11 -7
  173. package/src/services/ai-agent-runner-service.ts +15 -3
  174. package/src/services/ai-run-state-service.ts +1 -1
  175. package/src/services/ai-storage-service.ts +1 -1
  176. package/src/services/content-service.ts +7 -0
  177. package/src/services/gateway-service.ts +20 -0
  178. package/src/services/gopass-secrets.ts +4 -1
  179. package/src/services/in-memory-ai-run-state-service.ts +73 -0
  180. package/src/services/in-memory-trigger-service.ts +6 -10
  181. package/src/services/in-memory-workflow-service.test.ts +351 -0
  182. package/src/services/index.ts +4 -1
  183. package/src/services/local-content.ts +9 -3
  184. package/src/services/local-gateway-service.ts +62 -0
  185. package/src/services/local-secrets.test.ts +80 -0
  186. package/src/services/local-secrets.ts +2 -2
  187. package/src/services/local-variables.test.ts +61 -0
  188. package/src/services/local-variables.ts +1 -1
  189. package/src/services/logger-console.test.ts +118 -0
  190. package/src/services/logger-console.ts +2 -1
  191. package/src/services/scheduler-service.ts +0 -18
  192. package/src/services/scoped-secret-service.test.ts +74 -0
  193. package/src/services/scoped-secret-service.ts +1 -1
  194. package/src/services/trigger-service.ts +0 -21
  195. package/src/services/typed-secret-service.test.ts +93 -0
  196. package/src/services/typed-variables-service.test.ts +73 -0
  197. package/src/services/user-session-service.test.ts +113 -0
  198. package/src/services/user-session-service.ts +3 -3
  199. package/src/services/workflow-service.ts +2 -12
  200. package/src/time-utils.test.ts +1 -1
  201. package/src/types/core.types.ts +28 -19
  202. package/src/types/state.types.ts +32 -15
  203. package/src/utils.test.ts +350 -0
  204. package/src/utils.ts +14 -13
  205. package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +363 -0
  206. package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +238 -0
  207. package/src/wirings/ai-agent/ai-agent-helpers.test.ts +152 -0
  208. package/src/wirings/ai-agent/ai-agent-helpers.ts +76 -0
  209. package/src/wirings/ai-agent/ai-agent-memory.ts +10 -1
  210. package/src/wirings/ai-agent/ai-agent-model-config.test.ts +115 -0
  211. package/src/wirings/ai-agent/ai-agent-prepare.ts +98 -46
  212. package/src/wirings/ai-agent/ai-agent-registry.ts +1 -1
  213. package/src/wirings/ai-agent/ai-agent-runner.test.ts +245 -3
  214. package/src/wirings/ai-agent/ai-agent-runner.ts +121 -7
  215. package/src/wirings/ai-agent/ai-agent-stream.test.ts +430 -24
  216. package/src/wirings/ai-agent/ai-agent-stream.ts +390 -104
  217. package/src/wirings/ai-agent/ai-agent.types.ts +91 -4
  218. package/src/wirings/ai-agent/index.ts +13 -0
  219. package/src/wirings/channel/channel-common.ts +2 -2
  220. package/src/wirings/channel/channel-handler.ts +43 -11
  221. package/src/wirings/channel/channel-middleware-runner.ts +1 -0
  222. package/src/wirings/channel/channel-runner.ts +6 -6
  223. package/src/wirings/channel/channel-store.ts +1 -1
  224. package/src/wirings/channel/channel.types.ts +15 -8
  225. package/src/wirings/channel/index.ts +1 -0
  226. package/src/wirings/channel/local/local-channel-handler.ts +26 -0
  227. package/src/wirings/channel/local/local-channel-runner.test.ts +19 -12
  228. package/src/wirings/channel/local/local-channel-runner.ts +33 -14
  229. package/src/wirings/channel/local/local-eventhub-service.test.ts +2 -2
  230. package/src/wirings/channel/local/local-eventhub-service.ts +2 -2
  231. package/src/wirings/channel/log-channels.ts +1 -1
  232. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +2 -0
  233. package/src/wirings/channel/pikku-abstract-channel-handler.ts +8 -1
  234. package/src/wirings/channel/serverless/serverless-channel-runner.ts +38 -33
  235. package/src/wirings/cli/channel/cli-channel-runner.ts +1 -1
  236. package/src/wirings/cli/cli-runner.test.ts +1 -1
  237. package/src/wirings/cli/cli-runner.ts +14 -4
  238. package/src/wirings/cli/cli.types.ts +3 -3
  239. package/src/wirings/cli/command-parser.test.ts +1 -1
  240. package/src/wirings/cli/command-parser.ts +1 -1
  241. package/src/wirings/gateway/gateway-runner.test.ts +474 -0
  242. package/src/wirings/gateway/gateway-runner.ts +411 -0
  243. package/src/wirings/gateway/gateway.types.ts +149 -0
  244. package/src/wirings/gateway/index.ts +13 -0
  245. package/src/wirings/http/http-routes.test.ts +1 -1
  246. package/src/wirings/http/http-runner.test.ts +9 -17
  247. package/src/wirings/http/http-runner.ts +46 -27
  248. package/src/wirings/http/http.types.ts +1 -14
  249. package/src/wirings/http/log-http-routes.ts +1 -1
  250. package/src/wirings/http/pikku-fetch-http-request.ts +1 -1
  251. package/src/wirings/http/pikku-fetch-http-response.ts +12 -5
  252. package/src/wirings/http/routers/http-router.ts +1 -1
  253. package/src/wirings/http/routers/path-to-regex.test.ts +1 -1
  254. package/src/wirings/http/routers/path-to-regex.ts +4 -3
  255. package/src/wirings/mcp/mcp-endpoint-registry.ts +5 -1
  256. package/src/wirings/mcp/mcp-runner.ts +9 -15
  257. package/src/wirings/mcp/mcp.types.ts +2 -2
  258. package/src/wirings/oauth2/oauth2-client.ts +3 -3
  259. package/src/wirings/oauth2/wire-oauth2-credential.ts +1 -1
  260. package/src/wirings/queue/index.ts +0 -1
  261. package/src/wirings/queue/queue-runner.test.ts +52 -25
  262. package/src/wirings/queue/queue-runner.ts +8 -30
  263. package/src/wirings/queue/queue.types.ts +3 -13
  264. package/src/wirings/queue/register-queue-helper.ts +3 -5
  265. package/src/wirings/queue/validate-worker-config.test.ts +108 -0
  266. package/src/wirings/queue/validate-worker-config.ts +4 -1
  267. package/src/wirings/rpc/index.ts +2 -0
  268. package/src/wirings/rpc/rpc-runner.ts +92 -49
  269. package/src/wirings/rpc/rpc-types.ts +17 -2
  270. package/src/wirings/rpc/wire-addon.ts +20 -0
  271. package/src/wirings/scheduler/index.ts +0 -1
  272. package/src/wirings/scheduler/log-schedulers.ts +1 -1
  273. package/src/wirings/scheduler/scheduler-runner.test.ts +49 -60
  274. package/src/wirings/scheduler/scheduler-runner.ts +9 -56
  275. package/src/wirings/scheduler/scheduler.types.ts +2 -2
  276. package/src/wirings/secret/validate-secret-definitions.test.ts +140 -0
  277. package/src/wirings/trigger/pikku-trigger-service.ts +17 -39
  278. package/src/wirings/trigger/trigger-runner.test.ts +79 -0
  279. package/src/wirings/trigger/trigger-runner.ts +8 -11
  280. package/src/wirings/variable/validate-variable-definitions.test.ts +91 -0
  281. package/src/wirings/workflow/graph/graph-runner.test.ts +14 -22
  282. package/src/wirings/workflow/graph/template.test.ts +49 -0
  283. package/src/wirings/workflow/pikku-workflow-service.test.ts +15 -27
  284. package/src/wirings/workflow/pikku-workflow-service.ts +29 -45
  285. package/src/wirings/workflow/workflow-helpers.test.ts +129 -0
  286. package/src/wirings/workflow/workflow.types.ts +2 -2
  287. package/tsconfig.tsbuildinfo +1 -1
  288. package/src/wirings/workflow/workflow-utils.ts +0 -0
  289. /package/dist/{wirings/workflow/workflow-utils.d.ts → services/gateway-service.js} +0 -0
  290. /package/dist/wirings/{workflow/workflow-utils.js → gateway/gateway.types.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { PikkuError } from '../../errors/error-handler.js';
2
- import { pikkuState } from '../../pikku-state.js';
2
+ import { pikkuState, getSingletonServices, getCreateWireServices, } from '../../pikku-state.js';
3
3
  import { runPikkuFunc } from '../../function/function-runner.js';
4
4
  import { createMiddlewareSessionWireProps } from '../../services/user-session-service.js';
5
5
  import { randomUUID } from 'crypto';
@@ -33,8 +33,8 @@ export const resolveAgent = (agentName) => {
33
33
  if (colonIndex !== -1) {
34
34
  const namespace = agentName.substring(0, colonIndex);
35
35
  const localName = agentName.substring(colonIndex + 1);
36
- const externalPackages = pikkuState(null, 'rpc', 'externalPackages');
37
- const pkgConfig = externalPackages.get(namespace);
36
+ const addons = pikkuState(null, 'rpc', 'addons');
37
+ const pkgConfig = addons.get(namespace);
38
38
  if (pkgConfig) {
39
39
  const extAgent = pikkuState(pkgConfig.package, 'agent', 'agents').get(localName);
40
40
  if (extAgent) {
@@ -73,6 +73,7 @@ export function createScopedChannel(parent, agentName, session) {
73
73
  return capturedApproval;
74
74
  },
75
75
  close: () => { },
76
+ sendBinary: (data) => parent.sendBinary(data),
76
77
  send: (event) => {
77
78
  if (event.type === 'done')
78
79
  return;
@@ -85,7 +86,8 @@ export function createScopedChannel(parent, agentName, session) {
85
86
  };
86
87
  return;
87
88
  }
88
- if (event.type === 'text-delta' ||
89
+ if (event.type === 'step-start' ||
90
+ event.type === 'text-delta' ||
89
91
  event.type === 'reasoning-delta' ||
90
92
  event.type === 'tool-call' ||
91
93
  event.type === 'tool-result' ||
@@ -99,7 +101,8 @@ export function createScopedChannel(parent, agentName, session) {
99
101
  },
100
102
  };
101
103
  }
102
- export function buildToolDefs(singletonServices, params, agentSessionMap, resourceId, agentName, packageName, streamContext) {
104
+ export function buildToolDefs(params, agentSessionMap, resourceId, agentName, packageName, streamContext, aiMiddlewares) {
105
+ const singletonServices = getSingletonServices();
103
106
  const tools = [];
104
107
  const missingRpcs = [];
105
108
  const approvalPolicy = streamContext?.options?.requiresToolApproval ?? 'explicit';
@@ -131,38 +134,18 @@ export function buildToolDefs(singletonServices, params, agentSessionMap, resour
131
134
  }
132
135
  const needsApproval = approvalPolicy === 'all' ||
133
136
  (approvalPolicy === 'explicit' && fnMeta?.requiresApproval);
134
- if (needsApproval) {
135
- inputSchema = {
136
- ...inputSchema,
137
- properties: {
138
- ...(inputSchema.properties || {}),
139
- toolApprovalReason: {
140
- type: 'string',
141
- description: 'Brief explanation of why this action is needed',
142
- },
143
- },
144
- };
145
- }
146
137
  tools.push({
147
138
  name: pikkuFuncId,
148
139
  description: fnMeta?.description || fnMeta?.title || toolName,
149
140
  inputSchema,
141
+ needsApproval: needsApproval || undefined,
150
142
  execute: async (toolInput) => {
151
- if (needsApproval) {
152
- const { toolApprovalReason, ...cleanArgs } = toolInput;
153
- return {
154
- __approvalRequired: true,
155
- toolName: pikkuFuncId,
156
- args: cleanArgs,
157
- reason: toolApprovalReason,
158
- };
159
- }
160
143
  const wire = params.sessionService
161
144
  ? { ...createMiddlewareSessionWireProps(params.sessionService) }
162
145
  : {};
163
146
  return runPikkuFunc('agent', `tool:${pikkuFuncId}`, pikkuFuncId, {
164
147
  singletonServices,
165
- createWireServices: params.createWireServices,
148
+ createWireServices: getCreateWireServices(),
166
149
  data: () => toolInput,
167
150
  wire,
168
151
  sessionService: params.sessionService,
@@ -237,10 +220,61 @@ export function buildToolDefs(singletonServices, params, agentSessionMap, resour
237
220
  });
238
221
  }
239
222
  }
223
+ const hasToolHooks = aiMiddlewares?.some((mw) => mw.beforeToolCall || mw.afterToolCall);
224
+ if (hasToolHooks) {
225
+ for (const tool of tools) {
226
+ const originalExecute = tool.execute;
227
+ tool.execute = async (toolInput) => {
228
+ const toolCallId = randomUUID();
229
+ let args = (toolInput ?? {});
230
+ for (const mw of aiMiddlewares) {
231
+ if (mw.beforeToolCall) {
232
+ const beforeResult = await mw.beforeToolCall(singletonServices, {
233
+ toolName: tool.name,
234
+ toolCallId,
235
+ args,
236
+ });
237
+ if (beforeResult && 'args' in beforeResult) {
238
+ args = beforeResult.args;
239
+ }
240
+ }
241
+ }
242
+ const startTime = Date.now();
243
+ let result;
244
+ let execError;
245
+ try {
246
+ result = await originalExecute(args);
247
+ }
248
+ catch (err) {
249
+ execError = err;
250
+ result = err instanceof Error ? err.message : String(err);
251
+ }
252
+ const durationMs = Date.now() - startTime;
253
+ for (let i = aiMiddlewares.length - 1; i >= 0; i--) {
254
+ const mw = aiMiddlewares[i];
255
+ if (mw.afterToolCall) {
256
+ const afterResult = await mw.afterToolCall(singletonServices, {
257
+ toolName: tool.name,
258
+ toolCallId,
259
+ args,
260
+ result,
261
+ durationMs,
262
+ });
263
+ if (afterResult && 'result' in afterResult) {
264
+ result = afterResult.result;
265
+ }
266
+ }
267
+ }
268
+ if (execError)
269
+ throw execError;
270
+ return result;
271
+ };
272
+ }
273
+ }
240
274
  return { tools, missingRpcs };
241
275
  }
242
276
  export async function prepareAgentRun(agentName, input, params, agentSessionMap, streamContext) {
243
- const { singletonServices } = params;
277
+ const singletonServices = getSingletonServices();
244
278
  const { agent, packageName, resolvedName } = resolveAgent(agentName);
245
279
  const agentRunner = singletonServices.aiAgentRunner;
246
280
  if (!agentRunner) {
@@ -274,24 +308,38 @@ export async function prepareAgentRun(agentName, input, params, agentSessionMap,
274
308
  });
275
309
  }
276
310
  const contextMessages = await loadContextMessages(memoryConfig, storage, input, workingMemoryJsonSchema);
311
+ const userContent = input.attachments?.length
312
+ ? [
313
+ { type: 'text', text: input.message },
314
+ ...input.attachments.map((a) => ({
315
+ type: a.type,
316
+ data: a.data,
317
+ url: a.url,
318
+ mediaType: a.mediaType,
319
+ ...(a.filename ? { filename: a.filename } : {}),
320
+ })),
321
+ ]
322
+ : input.message;
277
323
  const userMessage = {
278
324
  id: randomUUID(),
279
325
  role: 'user',
280
- content: input.message,
326
+ content: userContent,
281
327
  createdAt: new Date(),
282
328
  };
283
329
  const allMessages = [...contextMessages, ...messages, userMessage];
284
330
  const trimmedMessages = trimMessages(allMessages);
285
- const { tools, missingRpcs } = buildToolDefs(singletonServices, params, agentSessionMap, input.resourceId, resolvedName, packageName, streamContext);
331
+ const aiMiddlewares = agent.aiMiddleware ?? [];
332
+ const { tools, missingRpcs } = buildToolDefs(params, agentSessionMap, input.resourceId, resolvedName, packageName, streamContext, aiMiddlewares);
286
333
  const instructions = buildInstructions(resolvedName, packageName);
287
334
  const resolved = resolveModelConfig(resolvedName, agent);
335
+ const maxSteps = resolved.maxSteps ?? 10;
288
336
  const runnerParams = {
289
337
  model: resolved.model,
290
338
  temperature: resolved.temperature,
291
339
  instructions,
292
340
  messages: trimmedMessages,
293
341
  tools,
294
- maxSteps: resolved.maxSteps ?? 10,
342
+ maxSteps: 1,
295
343
  toolChoice: agent.toolChoice ?? 'auto',
296
344
  outputSchema,
297
345
  };
@@ -305,6 +353,7 @@ export async function prepareAgentRun(agentName, input, params, agentSessionMap,
305
353
  threadId,
306
354
  userMessage,
307
355
  runnerParams,
356
+ maxSteps,
308
357
  missingRpcs,
309
358
  workingMemoryJsonSchema,
310
359
  workingMemorySchemaName,
@@ -1,5 +1,5 @@
1
1
  import type { CoreAIAgent } from './ai-agent.types.js';
2
- import { AIRunStateService } from '../../services/ai-run-state-service.js';
2
+ import type { AIRunStateService } from '../../services/ai-run-state-service.js';
3
3
  export declare const addAIAgent: (agentName: string, agent: CoreAIAgent<any, any>, packageName?: string | null) => void;
4
4
  export declare function approveAIAgent(aiRunState: AIRunStateService, runId: string, approvals: {
5
5
  toolCallId: string;
@@ -1,9 +1,11 @@
1
1
  import { saveMessages } from './ai-agent-memory.js';
2
2
  import { prepareAgentRun } from './ai-agent-prepare.js';
3
+ import { getSingletonServices } from '../../pikku-state.js';
4
+ import { randomUUID } from 'crypto';
3
5
  export async function runAIAgent(agentName, input, params, agentSessionMap) {
4
6
  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 { agent, agentRunner, storage, memoryConfig, threadId, userMessage, runnerParams, maxSteps, missingRpcs, workingMemoryJsonSchema, workingMemorySchemaName, } = await prepareAgentRun(agentName, input, params, sessionMap);
8
+ const singletonServices = getSingletonServices();
7
9
  const { aiRunState } = singletonServices;
8
10
  if (!aiRunState) {
9
11
  throw new Error('AIRunStateService not available in singletonServices');
@@ -53,7 +55,90 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
53
55
  updatedAt: new Date(),
54
56
  });
55
57
  try {
56
- const result = await agentRunner.run(runnerParams);
58
+ const accumulatedSteps = [];
59
+ const totalUsage = { inputTokens: 0, outputTokens: 0 };
60
+ let lastStepResult = null;
61
+ for (let step = 0; step < maxSteps; step++) {
62
+ if (agent.prepareStep) {
63
+ let stopped = false;
64
+ await agent.prepareStep({
65
+ stepNumber: step,
66
+ messages: runnerParams.messages,
67
+ tools: runnerParams.tools,
68
+ toolChoice: runnerParams.toolChoice,
69
+ model: runnerParams.model,
70
+ stop: () => {
71
+ stopped = true;
72
+ },
73
+ });
74
+ if (stopped)
75
+ break;
76
+ }
77
+ const stepResult = await agentRunner.run(runnerParams);
78
+ lastStepResult = stepResult;
79
+ totalUsage.inputTokens += stepResult.usage.inputTokens;
80
+ totalUsage.outputTokens += stepResult.usage.outputTokens;
81
+ for (const mw of aiMiddlewares) {
82
+ if (mw.afterStep) {
83
+ await mw.afterStep(singletonServices, {
84
+ stepNumber: step,
85
+ text: stepResult.text,
86
+ toolCalls: stepResult.toolCalls,
87
+ toolResults: stepResult.toolResults,
88
+ usage: stepResult.usage,
89
+ finishReason: stepResult.finishReason,
90
+ });
91
+ }
92
+ }
93
+ accumulatedSteps.push({
94
+ usage: stepResult.usage,
95
+ toolCalls: stepResult.toolCalls.map((tc) => {
96
+ const tr = stepResult.toolResults.find((r) => r.toolCallId === tc.toolCallId);
97
+ return {
98
+ name: tc.toolName,
99
+ args: tc.args,
100
+ result: typeof tr?.result === 'string'
101
+ ? tr.result
102
+ : JSON.stringify(tr?.result ?? ''),
103
+ };
104
+ }),
105
+ });
106
+ if (stepResult.toolCalls.length === 0)
107
+ break;
108
+ const assistantMsg = {
109
+ id: randomUUID(),
110
+ role: 'assistant',
111
+ content: stepResult.text || undefined,
112
+ toolCalls: stepResult.toolCalls.map((tc) => ({
113
+ id: tc.toolCallId,
114
+ name: tc.toolName,
115
+ args: tc.args,
116
+ })),
117
+ createdAt: new Date(),
118
+ };
119
+ runnerParams.messages.push(assistantMsg);
120
+ if (stepResult.toolResults.length > 0) {
121
+ const toolMsg = {
122
+ id: randomUUID(),
123
+ role: 'tool',
124
+ toolResults: stepResult.toolResults.map((tr) => ({
125
+ id: tr.toolCallId,
126
+ name: tr.toolName,
127
+ result: typeof tr.result === 'string'
128
+ ? tr.result
129
+ : JSON.stringify(tr.result),
130
+ })),
131
+ createdAt: new Date(),
132
+ };
133
+ runnerParams.messages.push(toolMsg);
134
+ }
135
+ }
136
+ const finalText = lastStepResult?.text ?? '';
137
+ const finalObject = lastStepResult?.object;
138
+ const result = {
139
+ text: finalText,
140
+ steps: accumulatedSteps,
141
+ };
57
142
  const responseText = await saveMessages(storage, threadId, input.resourceId, memoryConfig, userMessage, result, {
58
143
  workingMemoryJsonSchema,
59
144
  workingMemorySchemaName,
@@ -68,7 +153,7 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
68
153
  const modResult = await mw.modifyOutput(singletonServices, {
69
154
  text: outputText,
70
155
  messages: outputMessages,
71
- usage: result.usage,
156
+ usage: totalUsage,
72
157
  });
73
158
  outputText = modResult.text;
74
159
  outputMessages = modResult.messages;
@@ -76,18 +161,32 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
76
161
  }
77
162
  await aiRunState.updateRun(runId, {
78
163
  status: 'completed',
79
- usage: { ...result.usage, model: agent.model },
164
+ usage: { ...totalUsage, model: agent.model },
80
165
  });
81
166
  return {
82
167
  runId,
83
168
  text: outputText,
84
- object: result.object,
169
+ object: finalObject,
85
170
  threadId,
86
- steps: result.steps,
87
- usage: result.usage,
171
+ steps: accumulatedSteps,
172
+ usage: totalUsage,
88
173
  };
89
174
  }
90
175
  catch (error) {
176
+ for (const mw of aiMiddlewares) {
177
+ if (mw.onError) {
178
+ try {
179
+ await mw.onError(singletonServices, {
180
+ error: error instanceof Error ? error : new Error(String(error)),
181
+ stepNumber: -1,
182
+ messages: runnerParams.messages,
183
+ });
184
+ }
185
+ catch {
186
+ // onError hooks must not affect error flow
187
+ }
188
+ }
189
+ }
91
190
  await aiRunState.updateRun(runId, {
92
191
  status: 'failed',
93
192
  });
@@ -4,8 +4,9 @@ export declare function streamAIAgent(agentName: string, input: {
4
4
  message: string;
5
5
  threadId: string;
6
6
  resourceId: string;
7
- }, channel: AIStreamChannel, params: RunAIAgentParams, agentSessionMap?: Map<string, string>, options?: StreamAIAgentOptions): Promise<void>;
7
+ } | Record<string, unknown>, channel: AIStreamChannel, params: RunAIAgentParams, agentSessionMap?: Map<string, string>, options?: StreamAIAgentOptions): Promise<void>;
8
8
  export declare function resumeAIAgent(input: {
9
+ runId: string;
9
10
  toolCallId: string;
10
11
  approved: boolean;
11
12
  }, channel: AIStreamChannel, params: RunAIAgentParams, options?: StreamAIAgentOptions): Promise<void>;