@pikku/core 0.12.2 → 0.12.4

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 (282) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/crypto-utils.d.ts +10 -0
  3. package/dist/crypto-utils.js +62 -0
  4. package/dist/function/function-runner.js +4 -4
  5. package/dist/function/functions.types.d.ts +26 -1
  6. package/dist/function/functions.types.js +16 -0
  7. package/dist/handle-error.d.ts +1 -1
  8. package/dist/handle-error.js +7 -3
  9. package/dist/index.d.ts +14 -2
  10. package/dist/index.js +1 -1
  11. package/dist/pikku-state.js +3 -1
  12. package/dist/schema.js +1 -1
  13. package/dist/services/in-memory-workflow-service.d.ts +22 -3
  14. package/dist/services/in-memory-workflow-service.js +77 -1
  15. package/dist/services/workflow-service.d.ts +8 -2
  16. package/dist/testing/index.d.ts +2 -0
  17. package/dist/testing/index.js +1 -0
  18. package/dist/testing/service-tests.d.ts +31 -0
  19. package/dist/testing/service-tests.js +598 -0
  20. package/dist/types/core.types.d.ts +9 -1
  21. package/dist/types/state.types.d.ts +4 -2
  22. package/dist/utils/hash.d.ts +2 -0
  23. package/dist/utils/hash.js +23 -0
  24. package/dist/wirings/ai-agent/agent-dynamic-workflow.d.ts +6 -0
  25. package/dist/wirings/ai-agent/agent-dynamic-workflow.js +348 -0
  26. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +1 -1
  27. package/dist/wirings/ai-agent/ai-agent-memory.js +6 -5
  28. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -7
  29. package/dist/wirings/ai-agent/ai-agent-prepare.js +127 -47
  30. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +4 -0
  31. package/dist/wirings/ai-agent/ai-agent-runner.js +381 -27
  32. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +7 -2
  33. package/dist/wirings/ai-agent/ai-agent-stream.js +109 -46
  34. package/dist/wirings/ai-agent/ai-agent.types.d.ts +22 -1
  35. package/dist/wirings/ai-agent/index.d.ts +1 -2
  36. package/dist/wirings/ai-agent/index.js +1 -2
  37. package/dist/wirings/channel/channel-handler.js +5 -1
  38. package/dist/wirings/channel/channel.types.d.ts +1 -7
  39. package/dist/wirings/channel/local/local-channel-handler.d.ts +1 -1
  40. package/dist/wirings/channel/local/local-channel-handler.js +5 -3
  41. package/dist/wirings/channel/local/local-channel-runner.js +14 -4
  42. package/dist/wirings/channel/serverless/serverless-channel-runner.js +4 -1
  43. package/dist/wirings/cli/cli-runner.js +10 -2
  44. package/dist/wirings/cli/cli.types.d.ts +1 -0
  45. package/dist/wirings/http/http-routes.js +0 -1
  46. package/dist/wirings/http/http-runner.d.ts +1 -1
  47. package/dist/wirings/http/http-runner.js +25 -3
  48. package/dist/wirings/http/http.types.d.ts +3 -11
  49. package/dist/wirings/http/index.d.ts +2 -1
  50. package/dist/wirings/http/index.js +1 -0
  51. package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -0
  52. package/dist/wirings/http/pikku-fetch-http-request.js +3 -0
  53. package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
  54. package/dist/wirings/http/pikku-fetch-http-response.js +4 -4
  55. package/dist/wirings/http/web-request.d.ts +12 -0
  56. package/dist/wirings/http/web-request.js +85 -0
  57. package/dist/wirings/mcp/mcp-endpoint-registry.js +1 -1
  58. package/dist/wirings/mcp/mcp-runner.js +13 -1
  59. package/dist/wirings/rpc/rpc-runner.d.ts +30 -6
  60. package/dist/wirings/rpc/rpc-runner.js +36 -14
  61. package/dist/wirings/rpc/rpc-types.d.ts +6 -1
  62. package/dist/wirings/rpc/wire-addon.d.ts +1 -0
  63. package/dist/wirings/rpc/wire-addon.js +1 -1
  64. package/dist/wirings/scheduler/scheduler-runner.js +1 -0
  65. package/dist/wirings/workflow/graph/graph-validation.d.ts +3 -0
  66. package/dist/wirings/workflow/graph/graph-validation.js +175 -0
  67. package/dist/wirings/workflow/graph/index.d.ts +1 -0
  68. package/dist/wirings/workflow/graph/index.js +1 -0
  69. package/dist/wirings/workflow/index.d.ts +1 -1
  70. package/dist/wirings/workflow/pikku-workflow-service.d.ts +8 -2
  71. package/dist/wirings/workflow/pikku-workflow-service.js +1 -2
  72. package/dist/wirings/workflow/workflow.types.d.ts +10 -1
  73. package/lcov.info +18891 -0
  74. package/package.json +4 -2
  75. package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +0 -5
  76. package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +0 -168
  77. package/src/crypto-utils.test.ts +0 -116
  78. package/src/crypto-utils.ts +0 -99
  79. package/src/errors/error-handler.ts +0 -62
  80. package/src/errors/error.test.ts +0 -195
  81. package/src/errors/errors.ts +0 -374
  82. package/src/errors/index.ts +0 -2
  83. package/src/factory-functions.test.ts +0 -109
  84. package/src/function/function-runner.test.ts +0 -536
  85. package/src/function/function-runner.ts +0 -365
  86. package/src/function/functions.types.ts +0 -267
  87. package/src/function/index.ts +0 -5
  88. package/src/handle-error.test.ts +0 -361
  89. package/src/handle-error.ts +0 -65
  90. package/src/index.ts +0 -104
  91. package/src/internal.ts +0 -6
  92. package/src/middleware/auth-apikey.test.ts +0 -363
  93. package/src/middleware/auth-apikey.ts +0 -47
  94. package/src/middleware/auth-bearer.test.ts +0 -450
  95. package/src/middleware/auth-bearer.ts +0 -72
  96. package/src/middleware/auth-cookie.test.ts +0 -528
  97. package/src/middleware/auth-cookie.ts +0 -80
  98. package/src/middleware/cors.test.ts +0 -424
  99. package/src/middleware/cors.ts +0 -104
  100. package/src/middleware/index.ts +0 -5
  101. package/src/middleware/remote-auth.test.ts +0 -488
  102. package/src/middleware/remote-auth.ts +0 -68
  103. package/src/middleware/timeout.ts +0 -15
  104. package/src/middleware-runner.test.ts +0 -418
  105. package/src/middleware-runner.ts +0 -234
  106. package/src/permissions.test.ts +0 -434
  107. package/src/permissions.ts +0 -319
  108. package/src/pikku-request.ts +0 -23
  109. package/src/pikku-response.ts +0 -5
  110. package/src/pikku-state.test.ts +0 -224
  111. package/src/pikku-state.ts +0 -214
  112. package/src/run-tests-script.test.ts +0 -49
  113. package/src/schema.test.ts +0 -249
  114. package/src/schema.ts +0 -151
  115. package/src/services/ai-agent-runner-service.ts +0 -41
  116. package/src/services/ai-run-state-service.ts +0 -20
  117. package/src/services/ai-storage-service.ts +0 -39
  118. package/src/services/content-service.ts +0 -76
  119. package/src/services/deployment-service.ts +0 -22
  120. package/src/services/gateway-service.ts +0 -20
  121. package/src/services/gopass-secrets.ts +0 -98
  122. package/src/services/in-memory-ai-run-state-service.ts +0 -73
  123. package/src/services/in-memory-trigger-service.ts +0 -64
  124. package/src/services/in-memory-workflow-service.test.ts +0 -351
  125. package/src/services/in-memory-workflow-service.ts +0 -395
  126. package/src/services/index.ts +0 -56
  127. package/src/services/jwt-service.ts +0 -30
  128. package/src/services/local-content.ts +0 -120
  129. package/src/services/local-gateway-service.ts +0 -62
  130. package/src/services/local-secrets.test.ts +0 -80
  131. package/src/services/local-secrets.ts +0 -94
  132. package/src/services/local-variables.test.ts +0 -61
  133. package/src/services/local-variables.ts +0 -39
  134. package/src/services/logger-console.test.ts +0 -118
  135. package/src/services/logger-console.ts +0 -98
  136. package/src/services/logger.ts +0 -57
  137. package/src/services/scheduler-service.ts +0 -86
  138. package/src/services/schema-service.ts +0 -33
  139. package/src/services/scoped-secret-service.test.ts +0 -74
  140. package/src/services/scoped-secret-service.ts +0 -41
  141. package/src/services/secret-service.ts +0 -38
  142. package/src/services/trigger-service.ts +0 -17
  143. package/src/services/typed-secret-service.test.ts +0 -93
  144. package/src/services/typed-secret-service.ts +0 -70
  145. package/src/services/typed-variables-service.test.ts +0 -73
  146. package/src/services/typed-variables-service.ts +0 -81
  147. package/src/services/user-session-service.test.ts +0 -113
  148. package/src/services/user-session-service.ts +0 -86
  149. package/src/services/variables-service.ts +0 -11
  150. package/src/services/workflow-service.ts +0 -84
  151. package/src/time-utils.test.ts +0 -56
  152. package/src/time-utils.ts +0 -107
  153. package/src/types/core.types.ts +0 -470
  154. package/src/types/state.types.ts +0 -186
  155. package/src/utils.test.ts +0 -350
  156. package/src/utils.ts +0 -129
  157. package/src/version.test.ts +0 -80
  158. package/src/version.ts +0 -25
  159. package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +0 -363
  160. package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +0 -238
  161. package/src/wirings/ai-agent/ai-agent-helpers.test.ts +0 -152
  162. package/src/wirings/ai-agent/ai-agent-helpers.ts +0 -76
  163. package/src/wirings/ai-agent/ai-agent-memory.ts +0 -309
  164. package/src/wirings/ai-agent/ai-agent-model-config.test.ts +0 -115
  165. package/src/wirings/ai-agent/ai-agent-model-config.ts +0 -43
  166. package/src/wirings/ai-agent/ai-agent-prepare.ts +0 -522
  167. package/src/wirings/ai-agent/ai-agent-registry.test.ts +0 -37
  168. package/src/wirings/ai-agent/ai-agent-registry.ts +0 -82
  169. package/src/wirings/ai-agent/ai-agent-runner.test.ts +0 -317
  170. package/src/wirings/ai-agent/ai-agent-runner.ts +0 -251
  171. package/src/wirings/ai-agent/ai-agent-stream.test.ts +0 -652
  172. package/src/wirings/ai-agent/ai-agent-stream.ts +0 -1060
  173. package/src/wirings/ai-agent/ai-agent.types.ts +0 -360
  174. package/src/wirings/ai-agent/index.ts +0 -41
  175. package/src/wirings/channel/channel-common.ts +0 -90
  176. package/src/wirings/channel/channel-handler.ts +0 -241
  177. package/src/wirings/channel/channel-middleware-runner.ts +0 -120
  178. package/src/wirings/channel/channel-runner.ts +0 -166
  179. package/src/wirings/channel/channel-store.ts +0 -29
  180. package/src/wirings/channel/channel.types.ts +0 -178
  181. package/src/wirings/channel/define-channel-routes.ts +0 -25
  182. package/src/wirings/channel/eventhub-service.ts +0 -34
  183. package/src/wirings/channel/eventhub-store.ts +0 -13
  184. package/src/wirings/channel/index.ts +0 -24
  185. package/src/wirings/channel/local/index.ts +0 -3
  186. package/src/wirings/channel/local/local-channel-handler.ts +0 -79
  187. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -215
  188. package/src/wirings/channel/local/local-channel-runner.ts +0 -200
  189. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -95
  190. package/src/wirings/channel/local/local-eventhub-service.ts +0 -101
  191. package/src/wirings/channel/log-channels.ts +0 -20
  192. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +0 -54
  193. package/src/wirings/channel/pikku-abstract-channel-handler.ts +0 -45
  194. package/src/wirings/channel/serverless/index.ts +0 -5
  195. package/src/wirings/channel/serverless/serverless-channel-runner.ts +0 -286
  196. package/src/wirings/cli/channel/cli-channel-runner.ts +0 -136
  197. package/src/wirings/cli/channel/index.ts +0 -1
  198. package/src/wirings/cli/cli-runner.test.ts +0 -403
  199. package/src/wirings/cli/cli-runner.ts +0 -519
  200. package/src/wirings/cli/cli.types.ts +0 -357
  201. package/src/wirings/cli/command-parser.test.ts +0 -445
  202. package/src/wirings/cli/command-parser.ts +0 -504
  203. package/src/wirings/cli/define-cli-commands.ts +0 -24
  204. package/src/wirings/cli/index.ts +0 -19
  205. package/src/wirings/gateway/gateway-runner.test.ts +0 -474
  206. package/src/wirings/gateway/gateway-runner.ts +0 -411
  207. package/src/wirings/gateway/gateway.types.ts +0 -149
  208. package/src/wirings/gateway/index.ts +0 -13
  209. package/src/wirings/http/http-routes.test.ts +0 -322
  210. package/src/wirings/http/http-routes.ts +0 -198
  211. package/src/wirings/http/http-runner.test.ts +0 -144
  212. package/src/wirings/http/http-runner.ts +0 -563
  213. package/src/wirings/http/http.types.ts +0 -378
  214. package/src/wirings/http/index.ts +0 -25
  215. package/src/wirings/http/log-http-routes.ts +0 -22
  216. package/src/wirings/http/pikku-fetch-http-request.test.ts +0 -237
  217. package/src/wirings/http/pikku-fetch-http-request.ts +0 -166
  218. package/src/wirings/http/pikku-fetch-http-response.test.ts +0 -82
  219. package/src/wirings/http/pikku-fetch-http-response.ts +0 -147
  220. package/src/wirings/http/routers/http-router.ts +0 -13
  221. package/src/wirings/http/routers/path-to-regex.test.ts +0 -319
  222. package/src/wirings/http/routers/path-to-regex.ts +0 -126
  223. package/src/wirings/mcp/index.ts +0 -27
  224. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -389
  225. package/src/wirings/mcp/mcp-endpoint-registry.ts +0 -159
  226. package/src/wirings/mcp/mcp-runner.ts +0 -305
  227. package/src/wirings/mcp/mcp.types.ts +0 -216
  228. package/src/wirings/node/index.ts +0 -2
  229. package/src/wirings/node/node.types.ts +0 -23
  230. package/src/wirings/oauth2/index.ts +0 -3
  231. package/src/wirings/oauth2/oauth2-client.test.ts +0 -929
  232. package/src/wirings/oauth2/oauth2-client.ts +0 -335
  233. package/src/wirings/oauth2/oauth2.types.ts +0 -69
  234. package/src/wirings/oauth2/wire-oauth2-credential.ts +0 -23
  235. package/src/wirings/queue/index.ts +0 -31
  236. package/src/wirings/queue/queue-runner.test.ts +0 -710
  237. package/src/wirings/queue/queue-runner.ts +0 -192
  238. package/src/wirings/queue/queue.types.ts +0 -189
  239. package/src/wirings/queue/register-queue-helper.ts +0 -60
  240. package/src/wirings/queue/validate-worker-config.test.ts +0 -108
  241. package/src/wirings/queue/validate-worker-config.ts +0 -116
  242. package/src/wirings/rpc/index.ts +0 -4
  243. package/src/wirings/rpc/rpc-runner.ts +0 -439
  244. package/src/wirings/rpc/rpc-types.ts +0 -51
  245. package/src/wirings/rpc/wire-addon.ts +0 -20
  246. package/src/wirings/scheduler/index.ts +0 -11
  247. package/src/wirings/scheduler/log-schedulers.ts +0 -20
  248. package/src/wirings/scheduler/scheduler-runner.test.ts +0 -660
  249. package/src/wirings/scheduler/scheduler-runner.ts +0 -132
  250. package/src/wirings/scheduler/scheduler.types.ts +0 -53
  251. package/src/wirings/secret/index.ts +0 -9
  252. package/src/wirings/secret/secret.types.ts +0 -32
  253. package/src/wirings/secret/validate-secret-definitions.test.ts +0 -140
  254. package/src/wirings/secret/validate-secret-definitions.ts +0 -82
  255. package/src/wirings/trigger/index.ts +0 -10
  256. package/src/wirings/trigger/pikku-trigger-service.ts +0 -112
  257. package/src/wirings/trigger/trigger-runner.test.ts +0 -79
  258. package/src/wirings/trigger/trigger-runner.ts +0 -135
  259. package/src/wirings/trigger/trigger.types.ts +0 -178
  260. package/src/wirings/variable/index.ts +0 -8
  261. package/src/wirings/variable/validate-variable-definitions.test.ts +0 -91
  262. package/src/wirings/variable/validate-variable-definitions.ts +0 -69
  263. package/src/wirings/variable/variable.types.ts +0 -22
  264. package/src/wirings/workflow/dsl/index.ts +0 -31
  265. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +0 -320
  266. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -28
  267. package/src/wirings/workflow/graph/graph-node.ts +0 -222
  268. package/src/wirings/workflow/graph/graph-runner.test.ts +0 -487
  269. package/src/wirings/workflow/graph/graph-runner.ts +0 -816
  270. package/src/wirings/workflow/graph/index.ts +0 -14
  271. package/src/wirings/workflow/graph/template.test.ts +0 -49
  272. package/src/wirings/workflow/graph/template.ts +0 -42
  273. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -29
  274. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -104
  275. package/src/wirings/workflow/index.ts +0 -81
  276. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -200
  277. package/src/wirings/workflow/pikku-workflow-service.ts +0 -1165
  278. package/src/wirings/workflow/workflow-helpers.test.ts +0 -129
  279. package/src/wirings/workflow/workflow-helpers.ts +0 -79
  280. package/src/wirings/workflow/workflow.types.ts +0 -266
  281. package/tsconfig.json +0 -14
  282. package/tsconfig.tsbuildinfo +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  ## 0.12.0
2
2
 
3
+ ## 0.12.4
4
+
5
+ ### Patch Changes
6
+
7
+ - InMemoryWorkflowService now implements WorkflowRunService interface (listRuns, getRunSteps, getDistinctWorkflowNames, deleteRun)
8
+
9
+ ## 0.12.3
10
+
11
+ ### Patch Changes
12
+
13
+ - 387b2ee: Add approval descriptions, rename requiresApproval to approvalRequired, export all service interfaces, add exposeErrors option to HTTP runner, promote addons to top-level state, add packageName to CommonWireMeta, add errors to function config, and improve agent runner streaming
14
+ - 32ed003: Add envelope encryption utilities and database-backed secret services with KEK rotation support
15
+ - 7d369f3: Fix agent sub-agent tool execution failures: use UUID for sub-agent thread IDs (was exceeding varchar(36) DB column), and synthesize error results for failed tool calls in non-streaming run() to prevent "Tool result is missing" cascading errors.
16
+ - 508a796: Fix MCP server not exposing addon tools: resolve namespaced function IDs in MCP runner, load addon schemas after schema generation, and use resolveFunctionMeta for MCP JSON serialization
17
+ - ffe83af: Add Web Response passthrough support and fix close() flushing
18
+
19
+ - HTTP runner detects when a function returns a Web `Response` object and applies it directly via `applyWebResponse()`, enabling seamless integration with libraries like Auth.js
20
+ - Add `send()` method to `PikkuHTTPResponse` for setting body without Content-Type headers
21
+ - Add `headers()` method to `PikkuHTTPRequest` for retrieving all headers as a record
22
+ - Add `toWebRequest()` and `applyWebResponse()` utilities for Web Request/Response conversion
23
+ - Fix `close()` in Express, Fastify, and UWS responses to flush buffered status/headers/body before ending the connection
24
+
25
+ - c7ff141: Add WorkflowVersionStatus type with draft→active lifecycle for AI-generated workflows, type all DB status fields with proper unions instead of plain strings
26
+
3
27
  ## 0.12.2
4
28
 
5
29
  ### Patch Changes
@@ -1,2 +1,12 @@
1
1
  export declare const encryptJSON: (secret: string, value: unknown) => Promise<string>;
2
2
  export declare const decryptJSON: <T>(secret: string, token: string) => Promise<T>;
3
+ export declare const generateDEK: () => Promise<string>;
4
+ export declare const wrapDEK: (kek: string, plaintextDEK: string) => Promise<string>;
5
+ export declare const unwrapDEK: (kek: string, wrappedDEK: string) => Promise<string>;
6
+ export interface EnvelopeEncryptResult {
7
+ ciphertext: string;
8
+ wrappedDEK: string;
9
+ }
10
+ export declare const envelopeEncrypt: (kek: string, value: unknown) => Promise<EnvelopeEncryptResult>;
11
+ export declare const envelopeDecrypt: <T>(kek: string, ciphertext: string, wrappedDEK: string) => Promise<T>;
12
+ export declare const envelopeRewrap: (oldKEK: string, newKEK: string, wrappedDEK: string) => Promise<string>;
@@ -76,3 +76,65 @@ export const decryptJSON = async (secret, token) => {
76
76
  const decrypted = await subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
77
77
  return JSON.parse(decoder.decode(new Uint8Array(decrypted)));
78
78
  };
79
+ /**
80
+ * Envelope encryption utilities.
81
+ *
82
+ * Each secret gets its own random DEK (data encryption key).
83
+ * The DEK is wrapped (encrypted) by a KEK (key encryption key) — typically an env var.
84
+ * The actual secret is encrypted with the DEK.
85
+ *
86
+ * KEK rotation only re-wraps the DEK, never touches the ciphertext.
87
+ */
88
+ const importRawKey = async (rawBytes) => {
89
+ const subtle = getSubtle();
90
+ return subtle.importKey('raw', rawBytes.buffer, { name: 'AES-GCM' }, true, ['encrypt', 'decrypt']);
91
+ };
92
+ export const generateDEK = async () => {
93
+ const raw = globalThis.crypto.getRandomValues(new Uint8Array(32));
94
+ return toBase64Url(raw);
95
+ };
96
+ export const wrapDEK = async (kek, plaintextDEK) => {
97
+ return encryptJSON(kek, plaintextDEK);
98
+ };
99
+ export const unwrapDEK = async (kek, wrappedDEK) => {
100
+ return decryptJSON(kek, wrappedDEK);
101
+ };
102
+ const encryptWithDEK = async (dekBase64, value) => {
103
+ const crypto = globalThis.crypto;
104
+ const subtle = getSubtle();
105
+ const iv = crypto.getRandomValues(new Uint8Array(12));
106
+ const key = await importRawKey(fromBase64Url(dekBase64));
107
+ const plaintext = encoder.encode(JSON.stringify(value));
108
+ const encrypted = await subtle.encrypt({ name: 'AES-GCM', iv }, key, plaintext);
109
+ const cipherBytes = new Uint8Array(encrypted);
110
+ const out = new Uint8Array(iv.length + cipherBytes.length);
111
+ out.set(iv, 0);
112
+ out.set(cipherBytes, iv.length);
113
+ return toBase64Url(out);
114
+ };
115
+ const decryptWithDEK = async (dekBase64, token) => {
116
+ const subtle = getSubtle();
117
+ const data = fromBase64Url(token);
118
+ if (data.length < 13) {
119
+ throw new Error('Invalid encrypted payload');
120
+ }
121
+ const iv = data.slice(0, 12);
122
+ const ciphertext = data.slice(12);
123
+ const key = await importRawKey(fromBase64Url(dekBase64));
124
+ const decrypted = await subtle.decrypt({ name: 'AES-GCM', iv }, key, ciphertext);
125
+ return JSON.parse(decoder.decode(new Uint8Array(decrypted)));
126
+ };
127
+ export const envelopeEncrypt = async (kek, value) => {
128
+ const dek = await generateDEK();
129
+ const ciphertext = await encryptWithDEK(dek, value);
130
+ const wrappedDEK = await wrapDEK(kek, dek);
131
+ return { ciphertext, wrappedDEK };
132
+ };
133
+ export const envelopeDecrypt = async (kek, ciphertext, wrappedDEK) => {
134
+ const dek = await unwrapDEK(kek, wrappedDEK);
135
+ return decryptWithDEK(dek, ciphertext);
136
+ };
137
+ export const envelopeRewrap = async (oldKEK, newKEK, wrappedDEK) => {
138
+ const dek = await unwrapDEK(oldKEK, wrappedDEK);
139
+ return wrapDEK(newKEK, dek);
140
+ };
@@ -50,7 +50,7 @@ export const getAllFunctionNames = () => {
50
50
  const functions = [];
51
51
  const mainFunctionsMeta = pikkuState(null, 'function', 'meta');
52
52
  functions.push(...Object.keys(mainFunctionsMeta));
53
- const addons = pikkuState(null, 'rpc', 'addons');
53
+ const addons = pikkuState(null, 'addons', 'packages');
54
54
  for (const [namespace, config] of addons) {
55
55
  const packageFunctionsMeta = pikkuState(config.package, 'function', 'meta');
56
56
  for (const funcName of Object.keys(packageFunctionsMeta)) {
@@ -166,12 +166,12 @@ export const runPikkuFunc = async (wireType, wireId, funcName, { singletonServic
166
166
  // Validate and coerce data if schema is defined
167
167
  const inputSchemaName = funcMeta.inputSchemaName;
168
168
  if (inputSchemaName) {
169
- // Validate request data against the defined schema, if any
170
- await validateSchema(resolvedSingletonServices.logger, resolvedSingletonServices.schema, inputSchemaName, actualData, packageName);
171
- // Coerce (top level) query string parameters or date objects if specified by the schema
169
+ // Coerce (top level) data types before validation (e.g. string→array, string→date)
172
170
  if (coerceDataFromSchema) {
173
171
  coerceTopLevelDataFromSchema(inputSchemaName, actualData, packageName);
174
172
  }
173
+ // Validate request data against the defined schema, if any
174
+ await validateSchema(resolvedSingletonServices.logger, resolvedSingletonServices.schema, inputSchemaName, actualData, packageName);
175
175
  }
176
176
  if (mergedInheritedPermissions.length > 0 ||
177
177
  wirePermissions ||
@@ -1,5 +1,6 @@
1
1
  import type { CoreServices, CoreSingletonServices, CoreUserSession, CorePikkuMiddleware, PikkuWire, PickRequired } from '../types/core.types.js';
2
2
  import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+ import type { PikkuError } from '../errors/error-handler.js';
3
4
  import type { CoreNodeConfig } from '../wirings/node/node.types.js';
4
5
  /**
5
6
  * @deprecated Use StandardSchemaV1 from @standard-schema/spec instead.
@@ -103,6 +104,28 @@ export type CorePikkuPermissionFactory<In = any, Services extends CoreSingletonS
103
104
  * ```
104
105
  */
105
106
  export declare const pikkuPermissionFactory: <In = any>(factory: CorePikkuPermissionFactory<In>) => CorePikkuPermissionFactory<In>;
107
+ /**
108
+ * A function that generates a human-readable description of a pending approval action.
109
+ * Used by AI agents to show meaningful approval prompts instead of raw tool arguments.
110
+ *
111
+ * @template In - The input type (same as the function it describes).
112
+ * @template Services - The services type, defaults to `CoreSingletonServices`.
113
+ */
114
+ export type CorePikkuApprovalDescription<In = any, Services extends CoreSingletonServices = CoreSingletonServices> = (services: Services, data: In) => Promise<string>;
115
+ /**
116
+ * Factory function for creating approval description functions with tree-shaking support.
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * export const deleteTodoApproval = pikkuApprovalDescription(
121
+ * async ({ todoStore }, { id }) => {
122
+ * const todo = await todoStore.get(id)
123
+ * return `Delete todo: "${todo.title}"`
124
+ * }
125
+ * )
126
+ * ```
127
+ */
128
+ export declare const pikkuApprovalDescription: <In = any, Services extends CoreSingletonServices = CoreSingletonServices>(fn: CorePikkuApprovalDescription<In, Services>) => CorePikkuApprovalDescription<In, Services>;
106
129
  export type CorePikkuAuth<Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = (services: Services, session: Session) => Promise<boolean> | boolean;
107
130
  export type CorePikkuAuthConfig<Services extends CoreSingletonServices = CoreServices, Session extends CoreUserSession = CoreUserSession> = {
108
131
  func: CorePikkuAuth<Services, Session>;
@@ -123,7 +146,8 @@ export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any,
123
146
  remote?: boolean;
124
147
  mcp?: boolean;
125
148
  readonly?: boolean;
126
- requiresApproval?: boolean;
149
+ approvalRequired?: boolean;
150
+ approvalDescription?: any;
127
151
  func: PikkuFunction;
128
152
  auth?: boolean;
129
153
  permissions?: CorePermissionGroup<PikkuPermission>;
@@ -131,4 +155,5 @@ export type CorePikkuFunctionConfig<PikkuFunction extends CorePikkuFunction<any,
131
155
  input?: InputSchema;
132
156
  output?: OutputSchema;
133
157
  node?: CoreNodeConfig;
158
+ errors?: Array<typeof PikkuError>;
134
159
  };
@@ -49,6 +49,22 @@ export const pikkuPermission = (permission) => {
49
49
  export const pikkuPermissionFactory = (factory) => {
50
50
  return factory;
51
51
  };
52
+ /**
53
+ * Factory function for creating approval description functions with tree-shaking support.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * export const deleteTodoApproval = pikkuApprovalDescription(
58
+ * async ({ todoStore }, { id }) => {
59
+ * const todo = await todoStore.get(id)
60
+ * return `Delete todo: "${todo.title}"`
61
+ * }
62
+ * )
63
+ * ```
64
+ */
65
+ export const pikkuApprovalDescription = (fn) => {
66
+ return fn;
67
+ };
52
68
  export const pikkuAuth = (auth) => {
53
69
  const fn = typeof auth === 'function' ? auth : auth.func;
54
70
  const wrapper = async (services, _data, wire) => {
@@ -11,4 +11,4 @@ import type { PikkuHTTP } from './wirings/http/http.types.js';
11
11
  * @param {boolean} respondWith404 - Whether to respond with 404 for NotFoundError
12
12
  * @param {boolean} bubbleError - Whether to throw the error after handling
13
13
  */
14
- export declare const handleHTTPError: (e: any, http: PikkuHTTP | undefined, trackerId: string | undefined, logger: Logger, logWarningsForStatusCodes: number[], respondWith404: boolean, bubbleError: boolean) => void;
14
+ export declare const handleHTTPError: (e: any, http: PikkuHTTP | undefined, trackerId: string | undefined, logger: Logger, logWarningsForStatusCodes: number[], respondWith404: boolean, bubbleError: boolean, exposeErrors?: boolean) => void;
@@ -11,7 +11,7 @@ import { NotFoundError } from './errors/errors.js';
11
11
  * @param {boolean} respondWith404 - Whether to respond with 404 for NotFoundError
12
12
  * @param {boolean} bubbleError - Whether to throw the error after handling
13
13
  */
14
- export const handleHTTPError = (e, http, trackerId, logger, logWarningsForStatusCodes, respondWith404, bubbleError) => {
14
+ export const handleHTTPError = (e, http, trackerId, logger, logWarningsForStatusCodes, respondWith404, bubbleError, exposeErrors = false) => {
15
15
  // Skip 404 handling if configured to do so
16
16
  if (e instanceof NotFoundError && !respondWith404) {
17
17
  return;
@@ -40,11 +40,15 @@ export const handleHTTPError = (e, http, trackerId, logger, logWarningsForStatus
40
40
  http?.response?.status(500);
41
41
  if (trackerId) {
42
42
  logger.warn(`Error id: ${trackerId}`);
43
- http?.response?.json({ errorId: trackerId });
43
+ const errorBody = { errorId: trackerId };
44
+ if (exposeErrors && e instanceof Error) {
45
+ errorBody.message = e.message;
46
+ errorBody.stack = e.stack;
47
+ }
48
+ http?.response?.json(errorBody);
44
49
  }
45
50
  }
46
51
  if (bubbleError) {
47
52
  throw e;
48
53
  }
49
- http?.response?.close?.();
50
54
  };
package/dist/index.d.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  */
4
4
  export type { CommonWireMeta, CoreConfig, CorePikkuMiddleware, CorePikkuMiddlewareConfig, CorePikkuMiddlewareFactory, CorePikkuMiddlewareGroup, CoreServices, CoreSingletonServices, CoreUserSession, CreateConfig, FunctionMeta, FunctionRuntimeMeta, FunctionServicesMeta, FunctionWiresMeta, FunctionsMeta, FunctionsRuntimeMeta, JSONPrimitive, JSONValue, MakeRequired, MiddlewareMetadata, PermissionMetadata, PickOptional, PickRequired, PikkuAIMiddlewareHooks, PikkuWire, PikkuWiringTypes, RequireAtLeastOne, SerializedError, WireServices, } from './types/core.types.js';
5
5
  export { pikkuAIMiddleware, pikkuChannelMiddleware, pikkuChannelMiddlewareFactory, pikkuMiddleware, pikkuMiddlewareFactory, } from './types/core.types.js';
6
- export type { CorePikkuAuth, CorePikkuAuthConfig, CorePikkuFunction, CorePikkuFunctionConfig, CorePikkuPermission, CorePikkuPermissionConfig, CorePikkuPermissionFactory, CorePermissionGroup, ZodLike, } from './function/functions.types.js';
7
- export { pikkuAuth, pikkuPermission, pikkuPermissionFactory, } from './function/functions.types.js';
6
+ export type { CorePikkuAuth, CorePikkuAuthConfig, CorePikkuFunction, CorePikkuFunctionConfig, CorePikkuPermission, CorePikkuPermissionConfig, CorePikkuPermissionFactory, CorePikkuApprovalDescription, CorePermissionGroup, ZodLike, } from './function/functions.types.js';
7
+ export { pikkuAuth, pikkuPermission, pikkuPermissionFactory, pikkuApprovalDescription, } from './function/functions.types.js';
8
8
  export { addFunction, getAllFunctionNames } from './function/index.js';
9
9
  export { PikkuRequest } from './pikku-request.js';
10
10
  export { getRelativeTimeOffsetFromNow, parseDurationString, } from './time-utils.js';
@@ -21,6 +21,18 @@ export { NotFoundError } from './errors/errors.js';
21
21
  export type { EventHubService } from './wirings/channel/eventhub-service.js';
22
22
  export type { QueueService } from './wirings/queue/queue.types.js';
23
23
  export type { JWTService } from './services/jwt-service.js';
24
+ export type { SecretService } from './services/secret-service.js';
25
+ export type { VariablesService } from './services/variables-service.js';
26
+ export type { ContentService } from './services/content-service.js';
27
+ export type { DeploymentService } from './services/deployment-service.js';
28
+ export type { WorkflowService } from './services/workflow-service.js';
29
+ export type { GatewayService } from './services/gateway-service.js';
30
+ export type { TriggerService } from './services/trigger-service.js';
31
+ export type { SchemaService } from './services/schema-service.js';
32
+ export type { SessionService } from './services/user-session-service.js';
33
+ export type { AIAgentRunnerService } from './services/ai-agent-runner-service.js';
34
+ export type { AIRunStateService } from './services/ai-run-state-service.js';
35
+ export type { AIStorageService } from './services/ai-storage-service.js';
24
36
  export type { HTTPMethod } from './wirings/http/http.types.js';
25
37
  export type { GraphNodeConfig } from './wirings/workflow/graph/workflow-graph.types.js';
26
38
  export { createGraph } from './wirings/workflow/graph/graph-node.js';
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { pikkuAIMiddleware, pikkuChannelMiddleware, pikkuChannelMiddlewareFactory, pikkuMiddleware, pikkuMiddlewareFactory, } from './types/core.types.js';
2
- export { pikkuAuth, pikkuPermission, pikkuPermissionFactory, } from './function/functions.types.js';
2
+ export { pikkuAuth, pikkuPermission, pikkuPermissionFactory, pikkuApprovalDescription, } from './function/functions.types.js';
3
3
  export { addFunction, getAllFunctionNames } from './function/index.js';
4
4
  export { PikkuRequest } from './pikku-request.js';
5
5
  export { getRelativeTimeOffsetFromNow, parseDurationString, } from './time-utils.js';
@@ -42,7 +42,9 @@ const createEmptyPackageState = () => ({
42
42
  rpc: {
43
43
  meta: {},
44
44
  files: new Map(),
45
- addons: new Map(),
45
+ },
46
+ addons: {
47
+ packages: new Map(),
46
48
  },
47
49
  http: {
48
50
  middleware: new Map(),
package/dist/schema.js CHANGED
@@ -104,6 +104,6 @@ export const validateSchema = async (logger, schemaService, schemaName, data, pa
104
104
  throw new MissingSchemaError(`Schema '${schemaName}' not found. Ensure schema generation has been run.`);
105
105
  }
106
106
  await schemaService.compileSchema(key, schema);
107
- await schemaService.validateSchema(key, data);
107
+ await schemaService.validateSchema(key, data ?? {});
108
108
  }
109
109
  };
@@ -1,6 +1,6 @@
1
1
  import { PikkuWorkflowService } from '../wirings/workflow/pikku-workflow-service.js';
2
2
  import type { SerializedError } from '../types/core.types.js';
3
- import type { WorkflowRun, WorkflowRunWire, StepState, WorkflowStatus, WorkflowStepOptions } from '../wirings/workflow/workflow.types.js';
3
+ import type { WorkflowRun, WorkflowRunService, WorkflowRunWire, StepState, WorkflowStatus, WorkflowVersionStatus, WorkflowStepOptions } from '../wirings/workflow/workflow.types.js';
4
4
  /**
5
5
  * In-memory implementation of WorkflowService for inline-only execution
6
6
  *
@@ -16,7 +16,7 @@ import type { WorkflowRun, WorkflowRunWire, StepState, WorkflowStatus, WorkflowS
16
16
  * await workflowService.startWorkflow('myWorkflow', input, { type: 'cli' }, rpc, { inline: true })
17
17
  * ```
18
18
  */
19
- export declare class InMemoryWorkflowService extends PikkuWorkflowService {
19
+ export declare class InMemoryWorkflowService extends PikkuWorkflowService implements WorkflowRunService {
20
20
  private runs;
21
21
  private steps;
22
22
  private stepData;
@@ -37,6 +37,19 @@ export declare class InMemoryWorkflowService extends PikkuWorkflowService {
37
37
  setStepResult(stepId: string, result: any): Promise<void>;
38
38
  setStepError(stepId: string, error: Error): Promise<void>;
39
39
  createRetryAttempt(failedStepId: string, status: 'pending' | 'running'): Promise<StepState>;
40
+ listRuns(options?: {
41
+ workflowName?: string;
42
+ status?: string;
43
+ limit?: number;
44
+ offset?: number;
45
+ }): Promise<WorkflowRun[]>;
46
+ getRunSteps(runId: string): Promise<Array<StepState & {
47
+ stepName: string;
48
+ rpcName?: string;
49
+ data?: any;
50
+ }>>;
51
+ getDistinctWorkflowNames(): Promise<string[]>;
52
+ deleteRun(id: string): Promise<boolean>;
40
53
  withRunLock<T>(_id: string, fn: () => Promise<T>): Promise<T>;
41
54
  withStepLock<T>(_runId: string, _stepName: string, fn: () => Promise<T>): Promise<T>;
42
55
  close(): Promise<void>;
@@ -51,9 +64,15 @@ export declare class InMemoryWorkflowService extends PikkuWorkflowService {
51
64
  setBranchTaken(stepId: string, branchKey: string): Promise<void>;
52
65
  updateRunState(runId: string, name: string, value: unknown): Promise<void>;
53
66
  getRunState(runId: string): Promise<Record<string, unknown>>;
54
- upsertWorkflowVersion(name: string, graphHash: string, graph: any, source: string): Promise<void>;
67
+ upsertWorkflowVersion(name: string, graphHash: string, graph: any, source: string, status?: WorkflowVersionStatus): Promise<void>;
68
+ updateWorkflowVersionStatus(name: string, graphHash: string, status: WorkflowVersionStatus): Promise<void>;
55
69
  getWorkflowVersion(name: string, graphHash: string): Promise<{
56
70
  graph: any;
57
71
  source: string;
58
72
  } | null>;
73
+ getAIGeneratedWorkflows(agentName?: string): Promise<Array<{
74
+ workflowName: string;
75
+ graphHash: string;
76
+ graph: any;
77
+ }>>;
59
78
  }
@@ -187,6 +187,55 @@ export class InMemoryWorkflowService extends PikkuWorkflowService {
187
187
  this.stepHistory.set(runId, history);
188
188
  return newStep;
189
189
  }
190
+ async listRuns(options) {
191
+ let runs = Array.from(this.runs.values());
192
+ if (options?.workflowName) {
193
+ runs = runs.filter((r) => r.workflow === options.workflowName);
194
+ }
195
+ if (options?.status) {
196
+ runs = runs.filter((r) => r.status === options.status);
197
+ }
198
+ runs.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
199
+ const offset = options?.offset ?? 0;
200
+ const limit = options?.limit ?? runs.length;
201
+ return runs.slice(offset, offset + limit);
202
+ }
203
+ async getRunSteps(runId) {
204
+ const history = this.stepHistory.get(runId) || [];
205
+ return history.map((step) => {
206
+ const stepDataEntry = this.stepData.get(step.stepId);
207
+ return {
208
+ ...step,
209
+ rpcName: stepDataEntry?.rpcName ?? undefined,
210
+ data: stepDataEntry?.data,
211
+ };
212
+ });
213
+ }
214
+ async getDistinctWorkflowNames() {
215
+ const names = new Set();
216
+ for (const run of this.runs.values()) {
217
+ names.add(run.workflow);
218
+ }
219
+ return Array.from(names);
220
+ }
221
+ async deleteRun(id) {
222
+ const existed = this.runs.has(id);
223
+ this.runs.delete(id);
224
+ this.stepHistory.delete(id);
225
+ this.runState.delete(id);
226
+ const prefix = `${id}:`;
227
+ for (const key of this.steps.keys()) {
228
+ if (key.startsWith(prefix)) {
229
+ const step = this.steps.get(key);
230
+ if (step) {
231
+ this.stepData.delete(step.stepId);
232
+ this.branchKeys.delete(step.stepId);
233
+ }
234
+ this.steps.delete(key);
235
+ }
236
+ }
237
+ return existed;
238
+ }
190
239
  async withRunLock(_id, fn) {
191
240
  // In-memory service doesn't need locking for inline execution
192
241
  return fn();
@@ -272,16 +321,43 @@ export class InMemoryWorkflowService extends PikkuWorkflowService {
272
321
  async getRunState(runId) {
273
322
  return this.runState.get(runId) || {};
274
323
  }
275
- async upsertWorkflowVersion(name, graphHash, graph, source) {
324
+ async upsertWorkflowVersion(name, graphHash, graph, source, status) {
276
325
  this.workflowVersions.set(`${name}:${graphHash}`, {
277
326
  graph,
278
327
  source,
328
+ status: status ?? 'active',
279
329
  });
280
330
  }
331
+ async updateWorkflowVersionStatus(name, graphHash, status) {
332
+ const key = `${name}:${graphHash}`;
333
+ const version = this.workflowVersions.get(key);
334
+ if (version) {
335
+ version.status = status;
336
+ }
337
+ }
281
338
  async getWorkflowVersion(name, graphHash) {
282
339
  const version = this.workflowVersions.get(`${name}:${graphHash}`);
283
340
  if (!version)
284
341
  return null;
285
342
  return { graph: version.graph, source: version.source };
286
343
  }
344
+ async getAIGeneratedWorkflows(agentName) {
345
+ const results = [];
346
+ const prefix = agentName ? `ai:${agentName}:` : 'ai:';
347
+ for (const [key, value] of this.workflowVersions) {
348
+ if (value.source !== 'ai-agent' || value.status !== 'active')
349
+ continue;
350
+ const separatorIdx = key.lastIndexOf(':');
351
+ const wfName = key.substring(0, separatorIdx);
352
+ const hash = key.substring(separatorIdx + 1);
353
+ if (wfName.startsWith(prefix)) {
354
+ results.push({
355
+ workflowName: wfName,
356
+ graphHash: hash,
357
+ graph: value.graph,
358
+ });
359
+ }
360
+ }
361
+ return results;
362
+ }
287
363
  }
@@ -1,5 +1,5 @@
1
1
  import type { SerializedError } from '../types/core.types.js';
2
- import type { WorkflowRun, WorkflowRunWire, StepState, WorkflowStatus } from '../wirings/workflow/workflow.types.js';
2
+ import type { WorkflowRun, WorkflowRunWire, StepState, WorkflowStatus, WorkflowVersionStatus } from '../wirings/workflow/workflow.types.js';
3
3
  /**
4
4
  * Interface for workflow orchestration
5
5
  * Handles workflow execution, replay, orchestration logic, and run-level state
@@ -34,9 +34,15 @@ export interface WorkflowService {
34
34
  setStepError(stepId: string, error: Error): Promise<void>;
35
35
  createRetryAttempt(stepId: string, status: 'pending' | 'running'): Promise<StepState>;
36
36
  executeWorkflowStep(runId: string, stepName: string, rpcName: string | null, data: any, rpcService: any): Promise<void>;
37
- upsertWorkflowVersion(name: string, graphHash: string, graph: any, source: string): Promise<void>;
37
+ upsertWorkflowVersion(name: string, graphHash: string, graph: any, source: string, status?: WorkflowVersionStatus): Promise<void>;
38
+ updateWorkflowVersionStatus(name: string, graphHash: string, status: WorkflowVersionStatus): Promise<void>;
38
39
  getWorkflowVersion(name: string, graphHash: string): Promise<{
39
40
  graph: any;
40
41
  source: string;
41
42
  } | null>;
43
+ getAIGeneratedWorkflows(agentName?: string): Promise<Array<{
44
+ workflowName: string;
45
+ graphHash: string;
46
+ graph: any;
47
+ }>>;
42
48
  }
@@ -0,0 +1,2 @@
1
+ export { defineServiceTests } from './service-tests.js';
2
+ export type { ServiceTestConfig } from './service-tests.js';
@@ -0,0 +1 @@
1
+ export { defineServiceTests } from './service-tests.js';
@@ -0,0 +1,31 @@
1
+ import type { ChannelStore } from '../wirings/channel/channel-store.js';
2
+ import type { EventHubStore } from '../wirings/channel/eventhub-store.js';
3
+ import type { PikkuWorkflowService } from '../wirings/workflow/pikku-workflow-service.js';
4
+ import type { WorkflowRunService } from '../wirings/workflow/workflow.types.js';
5
+ import type { DeploymentService } from '../services/deployment-service.js';
6
+ import type { AIStorageService } from '../services/ai-storage-service.js';
7
+ import type { AIRunStateService } from '../services/ai-run-state-service.js';
8
+ import type { SecretService } from '../services/secret-service.js';
9
+ import type { AgentRunService } from '../wirings/ai-agent/ai-agent.types.js';
10
+ export interface ServiceTestConfig {
11
+ name: string;
12
+ services: {
13
+ channelStore?: () => Promise<ChannelStore>;
14
+ eventHubStore?: () => Promise<EventHubStore<Record<string, any>>>;
15
+ workflowService?: () => Promise<PikkuWorkflowService>;
16
+ workflowRunService?: () => Promise<WorkflowRunService>;
17
+ deploymentService?: () => Promise<DeploymentService & {
18
+ stop(): Promise<void>;
19
+ }>;
20
+ aiStorageService?: () => Promise<AIStorageService & AIRunStateService>;
21
+ agentRunService?: () => Promise<AgentRunService>;
22
+ secretService?: (config: {
23
+ key: string;
24
+ keyVersion?: number;
25
+ previousKey?: string;
26
+ }) => Promise<SecretService & {
27
+ rotateKEK?(): Promise<number>;
28
+ }>;
29
+ };
30
+ }
31
+ export declare function defineServiceTests(config: ServiceTestConfig): void;