@pikku/core 0.12.1 → 0.12.3

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 (165) hide show
  1. package/CHANGELOG.md +34 -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/middleware-runner.js +1 -0
  12. package/dist/permissions.js +1 -0
  13. package/dist/pikku-state.js +7 -1
  14. package/dist/schema.js +1 -1
  15. package/dist/services/gateway-service.d.ts +19 -0
  16. package/dist/services/gateway-service.js +1 -0
  17. package/dist/services/in-memory-workflow-service.d.ts +8 -2
  18. package/dist/services/in-memory-workflow-service.js +28 -1
  19. package/dist/services/index.d.ts +2 -0
  20. package/dist/services/index.js +1 -0
  21. package/dist/services/local-gateway-service.d.ts +22 -0
  22. package/dist/services/local-gateway-service.js +51 -0
  23. package/dist/services/workflow-service.d.ts +8 -2
  24. package/dist/testing/index.d.ts +2 -0
  25. package/dist/testing/index.js +1 -0
  26. package/dist/testing/service-tests.d.ts +31 -0
  27. package/dist/testing/service-tests.js +598 -0
  28. package/dist/types/core.types.d.ts +12 -2
  29. package/dist/types/state.types.d.ts +9 -2
  30. package/dist/utils/hash.d.ts +2 -0
  31. package/dist/utils/hash.js +23 -0
  32. package/dist/utils.js +1 -1
  33. package/dist/wirings/ai-agent/agent-dynamic-workflow.d.ts +6 -0
  34. package/dist/wirings/ai-agent/agent-dynamic-workflow.js +348 -0
  35. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +1 -1
  36. package/dist/wirings/ai-agent/ai-agent-memory.js +19 -7
  37. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -7
  38. package/dist/wirings/ai-agent/ai-agent-prepare.js +141 -48
  39. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +4 -0
  40. package/dist/wirings/ai-agent/ai-agent-runner.js +381 -27
  41. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +7 -2
  42. package/dist/wirings/ai-agent/ai-agent-stream.js +126 -48
  43. package/dist/wirings/ai-agent/ai-agent.types.d.ts +57 -3
  44. package/dist/wirings/ai-agent/index.d.ts +2 -3
  45. package/dist/wirings/ai-agent/index.js +1 -2
  46. package/dist/wirings/channel/channel-handler.d.ts +5 -2
  47. package/dist/wirings/channel/channel-handler.js +16 -2
  48. package/dist/wirings/channel/channel-middleware-runner.js +1 -0
  49. package/dist/wirings/channel/channel.types.d.ts +7 -7
  50. package/dist/wirings/channel/index.d.ts +1 -1
  51. package/dist/wirings/channel/local/local-channel-handler.d.ts +8 -1
  52. package/dist/wirings/channel/local/local-channel-handler.js +22 -3
  53. package/dist/wirings/channel/local/local-channel-runner.js +28 -5
  54. package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +2 -1
  55. package/dist/wirings/channel/pikku-abstract-channel-handler.js +1 -0
  56. package/dist/wirings/channel/serverless/serverless-channel-runner.js +5 -2
  57. package/dist/wirings/cli/cli-runner.js +13 -2
  58. package/dist/wirings/cli/cli.types.d.ts +1 -0
  59. package/dist/wirings/gateway/gateway-runner.d.ts +24 -0
  60. package/dist/wirings/gateway/gateway-runner.js +325 -0
  61. package/dist/wirings/gateway/gateway.types.d.ts +127 -0
  62. package/dist/wirings/gateway/gateway.types.js +1 -0
  63. package/dist/wirings/gateway/index.d.ts +2 -0
  64. package/dist/wirings/gateway/index.js +1 -0
  65. package/dist/wirings/http/http-routes.js +0 -1
  66. package/dist/wirings/http/http-runner.d.ts +1 -1
  67. package/dist/wirings/http/http-runner.js +28 -3
  68. package/dist/wirings/http/http.types.d.ts +3 -11
  69. package/dist/wirings/http/index.d.ts +2 -1
  70. package/dist/wirings/http/index.js +1 -0
  71. package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -0
  72. package/dist/wirings/http/pikku-fetch-http-request.js +3 -0
  73. package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
  74. package/dist/wirings/http/pikku-fetch-http-response.js +4 -4
  75. package/dist/wirings/http/web-request.d.ts +12 -0
  76. package/dist/wirings/http/web-request.js +85 -0
  77. package/dist/wirings/mcp/mcp-endpoint-registry.js +1 -1
  78. package/dist/wirings/mcp/mcp-runner.js +13 -1
  79. package/dist/wirings/rpc/rpc-runner.d.ts +30 -6
  80. package/dist/wirings/rpc/rpc-runner.js +36 -14
  81. package/dist/wirings/rpc/rpc-types.d.ts +6 -1
  82. package/dist/wirings/rpc/wire-addon.d.ts +1 -0
  83. package/dist/wirings/rpc/wire-addon.js +1 -1
  84. package/dist/wirings/scheduler/scheduler-runner.js +1 -0
  85. package/dist/wirings/workflow/graph/graph-validation.d.ts +3 -0
  86. package/dist/wirings/workflow/graph/graph-validation.js +175 -0
  87. package/dist/wirings/workflow/graph/index.d.ts +1 -0
  88. package/dist/wirings/workflow/graph/index.js +1 -0
  89. package/dist/wirings/workflow/index.d.ts +1 -1
  90. package/dist/wirings/workflow/pikku-workflow-service.d.ts +8 -2
  91. package/dist/wirings/workflow/pikku-workflow-service.js +1 -2
  92. package/dist/wirings/workflow/workflow.types.d.ts +10 -1
  93. package/package.json +6 -3
  94. package/src/crypto-utils.test.ts +99 -1
  95. package/src/crypto-utils.ts +114 -0
  96. package/src/function/function-runner.ts +5 -5
  97. package/src/function/functions.types.ts +38 -1
  98. package/src/handle-error.test.ts +65 -2
  99. package/src/handle-error.ts +8 -4
  100. package/src/index.ts +14 -0
  101. package/src/middleware-runner.ts +1 -0
  102. package/src/permissions.ts +1 -0
  103. package/src/pikku-state.ts +8 -1
  104. package/src/schema.ts +1 -1
  105. package/src/services/gateway-service.ts +20 -0
  106. package/src/services/in-memory-workflow-service.ts +45 -2
  107. package/src/services/index.ts +2 -0
  108. package/src/services/local-gateway-service.ts +62 -0
  109. package/src/services/workflow-service.ts +12 -1
  110. package/src/testing/index.ts +2 -0
  111. package/src/testing/service-tests.ts +873 -0
  112. package/src/types/core.types.ts +12 -1
  113. package/src/types/state.types.ts +12 -2
  114. package/src/utils/hash.test.ts +68 -0
  115. package/src/utils/hash.ts +26 -0
  116. package/src/utils.ts +1 -1
  117. package/src/wirings/ai-agent/agent-dynamic-workflow.ts +469 -0
  118. package/src/wirings/ai-agent/ai-agent-memory.ts +17 -7
  119. package/src/wirings/ai-agent/ai-agent-prepare.ts +194 -62
  120. package/src/wirings/ai-agent/ai-agent-runner.test.ts +3 -1
  121. package/src/wirings/ai-agent/ai-agent-runner.ts +553 -31
  122. package/src/wirings/ai-agent/ai-agent-stream.test.ts +209 -2
  123. package/src/wirings/ai-agent/ai-agent-stream.ts +195 -91
  124. package/src/wirings/ai-agent/ai-agent.types.ts +57 -3
  125. package/src/wirings/ai-agent/index.ts +3 -5
  126. package/src/wirings/channel/channel-handler.ts +41 -4
  127. package/src/wirings/channel/channel-middleware-runner.ts +1 -0
  128. package/src/wirings/channel/channel.types.ts +12 -7
  129. package/src/wirings/channel/index.ts +1 -0
  130. package/src/wirings/channel/local/local-channel-handler.ts +31 -3
  131. package/src/wirings/channel/local/local-channel-runner.ts +32 -8
  132. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +2 -0
  133. package/src/wirings/channel/pikku-abstract-channel-handler.ts +8 -1
  134. package/src/wirings/channel/serverless/serverless-channel-runner.ts +5 -2
  135. package/src/wirings/cli/cli-runner.ts +15 -2
  136. package/src/wirings/cli/cli.types.ts +1 -0
  137. package/src/wirings/gateway/gateway-runner.test.ts +474 -0
  138. package/src/wirings/gateway/gateway-runner.ts +411 -0
  139. package/src/wirings/gateway/gateway.types.ts +149 -0
  140. package/src/wirings/gateway/index.ts +13 -0
  141. package/src/wirings/http/http-routes.ts +0 -1
  142. package/src/wirings/http/http-runner.ts +38 -10
  143. package/src/wirings/http/http.types.ts +3 -12
  144. package/src/wirings/http/index.ts +3 -0
  145. package/src/wirings/http/pikku-fetch-http-request.ts +4 -0
  146. package/src/wirings/http/pikku-fetch-http-response.ts +4 -4
  147. package/src/wirings/http/web-request.test.ts +236 -0
  148. package/src/wirings/http/web-request.ts +104 -0
  149. package/src/wirings/mcp/mcp-endpoint-registry.ts +1 -1
  150. package/src/wirings/mcp/mcp-runner.ts +30 -12
  151. package/src/wirings/rpc/rpc-runner.ts +45 -24
  152. package/src/wirings/rpc/rpc-types.ts +6 -1
  153. package/src/wirings/rpc/wire-addon.ts +2 -1
  154. package/src/wirings/scheduler/scheduler-runner.ts +1 -0
  155. package/src/wirings/workflow/graph/graph-validation.test.ts +170 -0
  156. package/src/wirings/workflow/graph/graph-validation.ts +237 -0
  157. package/src/wirings/workflow/graph/index.ts +5 -0
  158. package/src/wirings/workflow/index.ts +1 -0
  159. package/src/wirings/workflow/pikku-workflow-service.ts +14 -3
  160. package/src/wirings/workflow/workflow.types.ts +9 -1
  161. package/tsconfig.tsbuildinfo +1 -1
  162. package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +0 -5
  163. package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +0 -146
  164. package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +0 -363
  165. package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +0 -214
@@ -94,7 +94,12 @@ describe('streamAIAgent', () => {
94
94
  {}
95
95
  )
96
96
 
97
- assert.deepEqual(updates, [{ runId: 'run-1', patch: { status: 'failed' } }])
97
+ assert.deepEqual(updates, [
98
+ {
99
+ runId: 'run-1',
100
+ patch: { status: 'failed', errorMessage: 'stream failed' },
101
+ },
102
+ ])
98
103
  assert.deepEqual(
99
104
  events.map((event) => event.type),
100
105
  ['step-start', 'error', 'done']
@@ -198,7 +203,7 @@ describe('streamAIAgent', () => {
198
203
  pikkuState(null, 'rpc', 'meta')['tool-x'] = 'tool-x'
199
204
  pikkuState(null, 'function', 'meta')['tool-x'] = {
200
205
  description: 'test tool',
201
- requiresApproval: true,
206
+ approvalRequired: true,
202
207
  }
203
208
  pikkuState(null, 'misc', 'schemas').set('ToolXInput', {
204
209
  type: 'object',
@@ -260,6 +265,208 @@ describe('streamAIAgent', () => {
260
265
  )
261
266
  })
262
267
 
268
+ test('suspends run when multiple tool calls need approval (explicit policy)', async () => {
269
+ addTestAgent('multi-approval-agent')
270
+
271
+ const updates: Array<{ runId: string; patch: unknown }> = []
272
+ const events: AIStreamEvent[] = []
273
+
274
+ const mockServices = {
275
+ logger: {
276
+ info: () => {},
277
+ warn: () => {},
278
+ error: () => {},
279
+ debug: () => {},
280
+ },
281
+ aiAgentRunner: {
282
+ stream: async (): Promise<AIAgentStepResult> => {
283
+ // Simulate LLM returning 3 addTodo calls in one step
284
+ return makeStepResult({
285
+ toolCalls: [
286
+ {
287
+ toolCallId: 'tc-1',
288
+ toolName: 'todos__addTodo',
289
+ args: { title: 'todo 1' },
290
+ },
291
+ {
292
+ toolCallId: 'tc-2',
293
+ toolName: 'todos__addTodo',
294
+ args: { title: 'todo 2' },
295
+ },
296
+ {
297
+ toolCallId: 'tc-3',
298
+ toolName: 'todos__addTodo',
299
+ args: { title: 'todo 3' },
300
+ },
301
+ ],
302
+ // No toolResults since tools have no execute (needsApproval)
303
+ })
304
+ },
305
+ },
306
+ aiRunState: {
307
+ createRun: async () => 'run-multi-approval',
308
+ updateRun: async (runId: string, patch: unknown) => {
309
+ updates.push({ runId, patch })
310
+ },
311
+ },
312
+ } as any
313
+
314
+ pikkuState(null, 'package', 'singletonServices', mockServices)
315
+
316
+ const agentName = 'multi-approval-agent'
317
+ pikkuState(null, 'agent', 'agentsMeta')[agentName].tools = [
318
+ 'todos__addTodo',
319
+ ]
320
+ pikkuState(null, 'rpc', 'meta')['todos__addTodo'] = 'addTodo'
321
+ pikkuState(null, 'function', 'meta')['addTodo'] = {
322
+ description: 'Add a todo',
323
+ approvalRequired: true,
324
+ inputSchemaName: 'AddTodoInput',
325
+ }
326
+ pikkuState(null, 'misc', 'schemas').set('AddTodoInput', {
327
+ type: 'object',
328
+ properties: { title: { type: 'string' } },
329
+ })
330
+
331
+ await streamAIAgent(
332
+ agentName,
333
+ {
334
+ message: 'create 3 todos',
335
+ threadId: 'thread-multi-approval',
336
+ resourceId: 'resource-multi-approval',
337
+ },
338
+ {
339
+ channelId: 'channel-multi-approval',
340
+ openingData: undefined,
341
+ state: 'open',
342
+ send: (event: AIStreamEvent) => {
343
+ events.push(event)
344
+ },
345
+ close: () => {},
346
+ },
347
+ {}
348
+ // No options → defaults to requiresToolApproval: 'explicit'
349
+ )
350
+
351
+ // Should suspend on first tool call
352
+ const approvalEvent = events.find(
353
+ (e) => e.type === 'approval-request'
354
+ ) as any
355
+ assert.ok(approvalEvent, 'Should have an approval-request event')
356
+ assert.equal(approvalEvent.toolCallId, 'tc-1')
357
+ assert.equal(approvalEvent.toolName, 'todos__addTodo')
358
+
359
+ // Run should be suspended
360
+ assert.ok(
361
+ updates.some((u) => (u.patch as any).status === 'suspended'),
362
+ 'Run should be suspended for approval'
363
+ )
364
+
365
+ assert.ok(events.some((e) => e.type === 'done'))
366
+ })
367
+
368
+ test('suspends run for addon tools using namespaced resolution (explicit policy)', async () => {
369
+ addTestAgent('addon-approval-agent')
370
+
371
+ const updates: Array<{ runId: string; patch: unknown }> = []
372
+ const events: AIStreamEvent[] = []
373
+
374
+ const mockServices = {
375
+ logger: {
376
+ info: () => {},
377
+ warn: () => {},
378
+ error: () => {},
379
+ debug: () => {},
380
+ },
381
+ aiAgentRunner: {
382
+ stream: async (params: any): Promise<AIAgentStepResult> => {
383
+ // Verify the tool was built with needsApproval
384
+ const addTodoTool = params.tools.find(
385
+ (t: any) => t.name === 'todos__addTodo'
386
+ )
387
+ assert.ok(addTodoTool, 'Tool todos__addTodo should exist')
388
+ assert.equal(
389
+ addTodoTool.needsApproval,
390
+ true,
391
+ 'Tool should have needsApproval=true'
392
+ )
393
+
394
+ // Simulate LLM calling the tool
395
+ return makeStepResult({
396
+ toolCalls: [
397
+ {
398
+ toolCallId: 'tc-1',
399
+ toolName: 'todos__addTodo',
400
+ args: { title: 'new todo' },
401
+ },
402
+ ],
403
+ })
404
+ },
405
+ },
406
+ aiRunState: {
407
+ createRun: async () => 'run-addon-approval',
408
+ updateRun: async (runId: string, patch: unknown) => {
409
+ updates.push({ runId, patch })
410
+ },
411
+ },
412
+ } as any
413
+
414
+ pikkuState(null, 'package', 'singletonServices', mockServices)
415
+
416
+ // Register addon package
417
+ pikkuState(null, 'addons', 'packages').set('todos', {
418
+ package: '@test/addon-todos',
419
+ })
420
+
421
+ // Set up addon package's function metadata
422
+ pikkuState('@test/addon-todos', 'function', 'meta')['addTodo'] = {
423
+ description: 'Add a todo',
424
+ approvalRequired: true,
425
+ inputSchemaName: 'AddTodoInput',
426
+ }
427
+ pikkuState('@test/addon-todos', 'misc', 'schemas').set('AddTodoInput', {
428
+ type: 'object',
429
+ properties: { title: { type: 'string' } },
430
+ })
431
+
432
+ // Set up agent with namespaced tool
433
+ const agentName = 'addon-approval-agent'
434
+ pikkuState(null, 'agent', 'agentsMeta')[agentName].tools = ['todos:addTodo']
435
+
436
+ await streamAIAgent(
437
+ agentName,
438
+ {
439
+ message: 'add a todo',
440
+ threadId: 'thread-addon-approval',
441
+ resourceId: 'resource-addon-approval',
442
+ },
443
+ {
444
+ channelId: 'channel-addon-approval',
445
+ openingData: undefined,
446
+ state: 'open',
447
+ send: (event: AIStreamEvent) => {
448
+ events.push(event)
449
+ },
450
+ close: () => {},
451
+ },
452
+ {}
453
+ )
454
+
455
+ // Should suspend on the tool call
456
+ const approvalEvent = events.find(
457
+ (e) => e.type === 'approval-request'
458
+ ) as any
459
+ assert.ok(approvalEvent, 'Should have an approval-request event')
460
+ assert.equal(approvalEvent.toolCallId, 'tc-1')
461
+ assert.equal(approvalEvent.toolName, 'todos__addTodo')
462
+
463
+ // Run should be suspended
464
+ assert.ok(
465
+ updates.some((u) => (u.patch as any).status === 'suspended'),
466
+ 'Run should be suspended for approval'
467
+ )
468
+ })
469
+
263
470
  test('suspends with agent-call type when sub-agent returns approval sentinel', async () => {
264
471
  addTestAgent('parent-agent')
265
472