@pikku/core 0.12.2 → 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 (131) hide show
  1. package/CHANGELOG.md +18 -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 +8 -2
  14. package/dist/services/in-memory-workflow-service.js +28 -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/package.json +4 -2
  74. package/src/crypto-utils.test.ts +99 -1
  75. package/src/crypto-utils.ts +114 -0
  76. package/src/function/function-runner.ts +5 -5
  77. package/src/function/functions.types.ts +38 -1
  78. package/src/handle-error.test.ts +65 -2
  79. package/src/handle-error.ts +8 -4
  80. package/src/index.ts +14 -0
  81. package/src/pikku-state.ts +3 -1
  82. package/src/schema.ts +1 -1
  83. package/src/services/in-memory-workflow-service.ts +45 -2
  84. package/src/services/workflow-service.ts +12 -1
  85. package/src/testing/index.ts +2 -0
  86. package/src/testing/service-tests.ts +873 -0
  87. package/src/types/core.types.ts +9 -1
  88. package/src/types/state.types.ts +4 -2
  89. package/src/utils/hash.test.ts +68 -0
  90. package/src/utils/hash.ts +26 -0
  91. package/src/wirings/ai-agent/agent-dynamic-workflow.ts +469 -0
  92. package/src/wirings/ai-agent/ai-agent-memory.ts +7 -6
  93. package/src/wirings/ai-agent/ai-agent-prepare.ts +175 -61
  94. package/src/wirings/ai-agent/ai-agent-runner.test.ts +3 -1
  95. package/src/wirings/ai-agent/ai-agent-runner.ts +553 -31
  96. package/src/wirings/ai-agent/ai-agent-stream.test.ts +209 -2
  97. package/src/wirings/ai-agent/ai-agent-stream.ts +182 -89
  98. package/src/wirings/ai-agent/ai-agent.types.ts +23 -1
  99. package/src/wirings/ai-agent/index.ts +1 -5
  100. package/src/wirings/channel/channel-handler.ts +11 -2
  101. package/src/wirings/channel/channel.types.ts +1 -7
  102. package/src/wirings/channel/local/local-channel-handler.ts +5 -3
  103. package/src/wirings/channel/local/local-channel-runner.ts +17 -7
  104. package/src/wirings/channel/serverless/serverless-channel-runner.ts +4 -1
  105. package/src/wirings/cli/cli-runner.ts +12 -2
  106. package/src/wirings/cli/cli.types.ts +1 -0
  107. package/src/wirings/http/http-routes.ts +0 -1
  108. package/src/wirings/http/http-runner.ts +35 -10
  109. package/src/wirings/http/http.types.ts +3 -12
  110. package/src/wirings/http/index.ts +3 -0
  111. package/src/wirings/http/pikku-fetch-http-request.ts +4 -0
  112. package/src/wirings/http/pikku-fetch-http-response.ts +4 -4
  113. package/src/wirings/http/web-request.test.ts +236 -0
  114. package/src/wirings/http/web-request.ts +104 -0
  115. package/src/wirings/mcp/mcp-endpoint-registry.ts +1 -1
  116. package/src/wirings/mcp/mcp-runner.ts +30 -12
  117. package/src/wirings/rpc/rpc-runner.ts +45 -24
  118. package/src/wirings/rpc/rpc-types.ts +6 -1
  119. package/src/wirings/rpc/wire-addon.ts +2 -1
  120. package/src/wirings/scheduler/scheduler-runner.ts +1 -0
  121. package/src/wirings/workflow/graph/graph-validation.test.ts +170 -0
  122. package/src/wirings/workflow/graph/graph-validation.ts +237 -0
  123. package/src/wirings/workflow/graph/index.ts +5 -0
  124. package/src/wirings/workflow/index.ts +1 -0
  125. package/src/wirings/workflow/pikku-workflow-service.ts +14 -3
  126. package/src/wirings/workflow/workflow.types.ts +9 -1
  127. package/tsconfig.tsbuildinfo +1 -1
  128. package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +0 -5
  129. package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +0 -168
  130. package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +0 -363
  131. package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +0 -238
@@ -267,7 +267,7 @@ describe('handleHTTPError', () => {
267
267
  // Should not throw
268
268
  })
269
269
 
270
- test('should call response.close when available', () => {
270
+ test('should not call response.close automatically', () => {
271
271
  const logger = createMockLogger()
272
272
  const http = createMockHTTP()
273
273
  const error = new BadRequestError('bad')
@@ -282,7 +282,7 @@ describe('handleHTTPError', () => {
282
282
  false
283
283
  )
284
284
 
285
- assert.strictEqual(http._state.closed, true)
285
+ assert.strictEqual(http._state.closed, false)
286
286
  })
287
287
 
288
288
  test('should handle undefined http gracefully', () => {
@@ -335,6 +335,69 @@ describe('handleHTTPError', () => {
335
335
  assert.ok(errors.some((e) => e.args[0] === 'just a string error'))
336
336
  })
337
337
 
338
+ test('should include message and stack when exposeErrors is true', () => {
339
+ const logger = createMockLogger()
340
+ const http = createMockHTTP()
341
+ const error = new Error('something unexpected')
342
+
343
+ handleHTTPError(
344
+ error,
345
+ http as any,
346
+ 'tracker-expose',
347
+ logger as any,
348
+ [],
349
+ true,
350
+ false,
351
+ true
352
+ )
353
+
354
+ assert.strictEqual(http._state.statusCode, 500)
355
+ assert.strictEqual(http._state.jsonBody.errorId, 'tracker-expose')
356
+ assert.strictEqual(http._state.jsonBody.message, 'something unexpected')
357
+ assert.ok(typeof http._state.jsonBody.stack === 'string')
358
+ })
359
+
360
+ test('should not include message and stack when exposeErrors is false', () => {
361
+ const logger = createMockLogger()
362
+ const http = createMockHTTP()
363
+ const error = new Error('something unexpected')
364
+
365
+ handleHTTPError(
366
+ error,
367
+ http as any,
368
+ 'tracker-no-expose',
369
+ logger as any,
370
+ [],
371
+ true,
372
+ false,
373
+ false
374
+ )
375
+
376
+ assert.strictEqual(http._state.statusCode, 500)
377
+ assert.deepStrictEqual(http._state.jsonBody, {
378
+ errorId: 'tracker-no-expose',
379
+ })
380
+ })
381
+
382
+ test('should not expose details for non-Error objects even when exposeErrors is true', () => {
383
+ const logger = createMockLogger()
384
+ const http = createMockHTTP()
385
+
386
+ handleHTTPError(
387
+ 'string error',
388
+ http as any,
389
+ 'tracker-str',
390
+ logger as any,
391
+ [],
392
+ true,
393
+ false,
394
+ true
395
+ )
396
+
397
+ assert.strictEqual(http._state.statusCode, 500)
398
+ assert.deepStrictEqual(http._state.jsonBody, { errorId: 'tracker-str' })
399
+ })
400
+
338
401
  test('should handle warning log without trackerId', () => {
339
402
  const logger = createMockLogger()
340
403
  const http = createMockHTTP()
@@ -21,7 +21,8 @@ export const handleHTTPError = (
21
21
  logger: Logger,
22
22
  logWarningsForStatusCodes: number[],
23
23
  respondWith404: boolean,
24
- bubbleError: boolean
24
+ bubbleError: boolean,
25
+ exposeErrors: boolean = false
25
26
  ) => {
26
27
  // Skip 404 handling if configured to do so
27
28
  if (e instanceof NotFoundError && !respondWith404) {
@@ -53,13 +54,16 @@ export const handleHTTPError = (
53
54
 
54
55
  if (trackerId) {
55
56
  logger.warn(`Error id: ${trackerId}`)
56
- http?.response?.json({ errorId: trackerId })
57
+ const errorBody: Record<string, unknown> = { errorId: trackerId }
58
+ if (exposeErrors && e instanceof Error) {
59
+ errorBody.message = e.message
60
+ errorBody.stack = e.stack
61
+ }
62
+ http?.response?.json(errorBody)
57
63
  }
58
64
  }
59
65
 
60
66
  if (bubbleError) {
61
67
  throw e
62
68
  }
63
-
64
- http?.response?.close?.()
65
69
  }
package/src/index.ts CHANGED
@@ -47,6 +47,7 @@ export type {
47
47
  CorePikkuPermission,
48
48
  CorePikkuPermissionConfig,
49
49
  CorePikkuPermissionFactory,
50
+ CorePikkuApprovalDescription,
50
51
  CorePermissionGroup,
51
52
  ZodLike,
52
53
  } from './function/functions.types.js'
@@ -54,6 +55,7 @@ export {
54
55
  pikkuAuth,
55
56
  pikkuPermission,
56
57
  pikkuPermissionFactory,
58
+ pikkuApprovalDescription,
57
59
  } from './function/functions.types.js'
58
60
  export { addFunction, getAllFunctionNames } from './function/index.js'
59
61
  export { PikkuRequest } from './pikku-request.js'
@@ -86,6 +88,18 @@ export { NotFoundError } from './errors/errors.js'
86
88
  export type { EventHubService } from './wirings/channel/eventhub-service.js'
87
89
  export type { QueueService } from './wirings/queue/queue.types.js'
88
90
  export type { JWTService } from './services/jwt-service.js'
91
+ export type { SecretService } from './services/secret-service.js'
92
+ export type { VariablesService } from './services/variables-service.js'
93
+ export type { ContentService } from './services/content-service.js'
94
+ export type { DeploymentService } from './services/deployment-service.js'
95
+ export type { WorkflowService } from './services/workflow-service.js'
96
+ export type { GatewayService } from './services/gateway-service.js'
97
+ export type { TriggerService } from './services/trigger-service.js'
98
+ export type { SchemaService } from './services/schema-service.js'
99
+ export type { SessionService } from './services/user-session-service.js'
100
+ export type { AIAgentRunnerService } from './services/ai-agent-runner-service.js'
101
+ export type { AIRunStateService } from './services/ai-run-state-service.js'
102
+ export type { AIStorageService } from './services/ai-storage-service.js'
89
103
  export type { HTTPMethod } from './wirings/http/http.types.js'
90
104
  export type { GraphNodeConfig } from './wirings/workflow/graph/workflow-graph.types.js'
91
105
  export { createGraph } from './wirings/workflow/graph/graph-node.js'
@@ -72,7 +72,9 @@ const createEmptyPackageState = (): PikkuPackageState => ({
72
72
  rpc: {
73
73
  meta: {},
74
74
  files: new Map(),
75
- addons: new Map(),
75
+ },
76
+ addons: {
77
+ packages: new Map(),
76
78
  },
77
79
  http: {
78
80
  middleware: new Map(),
package/src/schema.ts CHANGED
@@ -146,6 +146,6 @@ export const validateSchema = async (
146
146
  )
147
147
  }
148
148
  await schemaService.compileSchema(key, schema)
149
- await schemaService.validateSchema(key, data)
149
+ await schemaService.validateSchema(key, data ?? {})
150
150
  }
151
151
  }
@@ -6,6 +6,7 @@ import type {
6
6
  WorkflowRunWire,
7
7
  StepState,
8
8
  WorkflowStatus,
9
+ WorkflowVersionStatus,
9
10
  WorkflowStepOptions,
10
11
  } from '../wirings/workflow/workflow.types.js'
11
12
 
@@ -40,7 +41,10 @@ export class InMemoryWorkflowService extends PikkuWorkflowService {
40
41
  >() // keyed by runId
41
42
  private runState = new Map<string, Record<string, unknown>>() // keyed by runId
42
43
  private branchKeys = new Map<string, string>() // keyed by stepId
43
- private workflowVersions = new Map<string, { graph: any; source: string }>() // keyed by `${name}:${graphHash}`
44
+ private workflowVersions = new Map<
45
+ string,
46
+ { graph: any; source: string; status: WorkflowVersionStatus }
47
+ >() // keyed by `${name}:${graphHash}`
44
48
 
45
49
  async createRun(
46
50
  workflowName: string,
@@ -376,14 +380,28 @@ export class InMemoryWorkflowService extends PikkuWorkflowService {
376
380
  name: string,
377
381
  graphHash: string,
378
382
  graph: any,
379
- source: string
383
+ source: string,
384
+ status?: WorkflowVersionStatus
380
385
  ): Promise<void> {
381
386
  this.workflowVersions.set(`${name}:${graphHash}`, {
382
387
  graph,
383
388
  source,
389
+ status: status ?? 'active',
384
390
  })
385
391
  }
386
392
 
393
+ async updateWorkflowVersionStatus(
394
+ name: string,
395
+ graphHash: string,
396
+ status: WorkflowVersionStatus
397
+ ): Promise<void> {
398
+ const key = `${name}:${graphHash}`
399
+ const version = this.workflowVersions.get(key)
400
+ if (version) {
401
+ version.status = status
402
+ }
403
+ }
404
+
387
405
  async getWorkflowVersion(
388
406
  name: string,
389
407
  graphHash: string
@@ -392,4 +410,29 @@ export class InMemoryWorkflowService extends PikkuWorkflowService {
392
410
  if (!version) return null
393
411
  return { graph: version.graph, source: version.source }
394
412
  }
413
+
414
+ async getAIGeneratedWorkflows(
415
+ agentName?: string
416
+ ): Promise<Array<{ workflowName: string; graphHash: string; graph: any }>> {
417
+ const results: Array<{
418
+ workflowName: string
419
+ graphHash: string
420
+ graph: any
421
+ }> = []
422
+ const prefix = agentName ? `ai:${agentName}:` : 'ai:'
423
+ for (const [key, value] of this.workflowVersions) {
424
+ if (value.source !== 'ai-agent' || value.status !== 'active') continue
425
+ const separatorIdx = key.lastIndexOf(':')
426
+ const wfName = key.substring(0, separatorIdx)
427
+ const hash = key.substring(separatorIdx + 1)
428
+ if (wfName.startsWith(prefix)) {
429
+ results.push({
430
+ workflowName: wfName,
431
+ graphHash: hash,
432
+ graph: value.graph,
433
+ })
434
+ }
435
+ }
436
+ return results
437
+ }
395
438
  }
@@ -4,6 +4,7 @@ import type {
4
4
  WorkflowRunWire,
5
5
  StepState,
6
6
  WorkflowStatus,
7
+ WorkflowVersionStatus,
7
8
  } from '../wirings/workflow/workflow.types.js'
8
9
 
9
10
  /**
@@ -75,10 +76,20 @@ export interface WorkflowService {
75
76
  name: string,
76
77
  graphHash: string,
77
78
  graph: any,
78
- source: string
79
+ source: string,
80
+ status?: WorkflowVersionStatus
81
+ ): Promise<void>
82
+ updateWorkflowVersionStatus(
83
+ name: string,
84
+ graphHash: string,
85
+ status: WorkflowVersionStatus
79
86
  ): Promise<void>
80
87
  getWorkflowVersion(
81
88
  name: string,
82
89
  graphHash: string
83
90
  ): Promise<{ graph: any; source: string } | null>
91
+
92
+ getAIGeneratedWorkflows(
93
+ agentName?: string
94
+ ): Promise<Array<{ workflowName: string; graphHash: string; graph: any }>>
84
95
  }
@@ -0,0 +1,2 @@
1
+ export { defineServiceTests } from './service-tests.js'
2
+ export type { ServiceTestConfig } from './service-tests.js'