@pikku/core 0.12.39 → 0.12.41

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 (48) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/function/function-runner.d.ts +2 -2
  3. package/dist/function/functions.types.d.ts +6 -2
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +1 -1
  6. package/dist/services/credential-wire-service.d.ts +2 -2
  7. package/dist/services/in-memory-workflow-service.d.ts +1 -0
  8. package/dist/services/in-memory-workflow-service.js +3 -0
  9. package/dist/services/pikku-user-id.d.ts +2 -2
  10. package/dist/services/workflow-service.d.ts +1 -0
  11. package/dist/types/core.types.d.ts +24 -7
  12. package/dist/utils.d.ts +3 -1
  13. package/dist/utils.js +2 -0
  14. package/dist/wirings/channel/channel-middleware-runner.d.ts +2 -2
  15. package/dist/wirings/channel/local/local-eventhub-service.js +7 -4
  16. package/dist/wirings/rpc/rpc-runner.d.ts +4 -4
  17. package/dist/wirings/rpc/rpc-runner.js +0 -16
  18. package/dist/wirings/workflow/pikku-workflow-service.d.ts +5 -2
  19. package/dist/wirings/workflow/pikku-workflow-service.js +17 -17
  20. package/package.json +1 -1
  21. package/src/function/function-runner.ts +3 -2
  22. package/src/function/functions.types.ts +6 -2
  23. package/src/index.ts +7 -1
  24. package/src/services/credential-wire-service.ts +2 -2
  25. package/src/services/in-memory-workflow-service.test.ts +2 -2
  26. package/src/services/in-memory-workflow-service.ts +7 -1
  27. package/src/services/pikku-user-id.ts +2 -2
  28. package/src/services/workflow-service.ts +1 -0
  29. package/src/types/core.types.ts +28 -8
  30. package/src/utils.ts +12 -1
  31. package/src/wirings/ai-agent/ai-agent-prepare.ts +2 -2
  32. package/src/wirings/channel/channel-common.ts +8 -2
  33. package/src/wirings/channel/channel-middleware-runner.ts +3 -3
  34. package/src/wirings/channel/local/local-channel-runner.ts +7 -3
  35. package/src/wirings/channel/local/local-eventhub-service.ts +6 -3
  36. package/src/wirings/channel/serverless/serverless-channel-runner.ts +4 -4
  37. package/src/wirings/cli/cli-runner.ts +2 -2
  38. package/src/wirings/gateway/gateway-runner.ts +8 -2
  39. package/src/wirings/http/http-runner.ts +3 -2
  40. package/src/wirings/mcp/mcp-runner.ts +2 -2
  41. package/src/wirings/queue/queue-runner.ts +2 -2
  42. package/src/wirings/rpc/rpc-runner.ts +12 -24
  43. package/src/wirings/scheduler/scheduler-runner.ts +2 -2
  44. package/src/wirings/trigger/trigger-runner.ts +2 -2
  45. package/src/wirings/workflow/pikku-workflow-service.test.ts +16 -26
  46. package/src/wirings/workflow/pikku-workflow-service.ts +36 -24
  47. package/src/wirings/workflow/workflow-dispatch-durability.test.ts +3 -3
  48. package/tsconfig.tsbuildinfo +1 -1
@@ -144,7 +144,10 @@ export class WorkflowDispatchException extends Error {
144
144
  public readonly stepName: string,
145
145
  options?: { cause?: unknown }
146
146
  ) {
147
- super(`Failed to dispatch workflow step '${stepName}' (run ${runId})`, options)
147
+ super(
148
+ `Failed to dispatch workflow step '${stepName}' (run ${runId})`,
149
+ options
150
+ )
148
151
  this.name = 'WorkflowDispatchException'
149
152
  }
150
153
  }
@@ -184,6 +187,16 @@ addError(WorkflowRunFailedError, {
184
187
  message: 'Workflow run failed.',
185
188
  })
186
189
 
190
+ export class WorkflowRunCancelledError extends PikkuError {
191
+ constructor() {
192
+ super('Workflow was cancelled')
193
+ }
194
+ }
195
+ addError(WorkflowRunCancelledError, {
196
+ status: 409,
197
+ message: 'Workflow was cancelled.',
198
+ })
199
+
187
200
  export class WorkflowServiceNotInitialized extends Error {}
188
201
  export class WorkflowStepNameNotString extends Error {
189
202
  constructor(stepName: any) {
@@ -237,16 +250,13 @@ export abstract class PikkuWorkflowService implements WorkflowService {
237
250
  }
238
251
  }
239
252
 
240
- public rewireQueueWorkers(): void {
241
- this.wireQueueWorkers()
242
- }
243
-
244
253
  /**
245
254
  * Wire the queue-based orchestrator/step/sleeper workers.
246
255
  * Subclasses that orchestrate without queues (e.g. Durable Objects) should
247
256
  * pass `wireQueues: false` to the base constructor and skip this entirely.
257
+ * Call this explicitly after adding addons dynamically.
248
258
  */
249
- protected wireQueueWorkers(): void {
259
+ public wireQueueWorkers(): void {
250
260
  const functions = pikkuState(null, 'function', 'functions')
251
261
  const functionsMeta = pikkuState(null, 'function', 'meta')
252
262
 
@@ -426,7 +436,12 @@ export abstract class PikkuWorkflowService implements WorkflowService {
426
436
  // Build step summaries from history (latest attempt per step)
427
437
  const stepMap = new Map<
428
438
  string,
429
- { status: StepStatus; startedAt?: Date; completedAt?: Date; attempts: number }
439
+ {
440
+ status: StepStatus
441
+ startedAt?: Date
442
+ completedAt?: Date
443
+ attempts: number
444
+ }
430
445
  >()
431
446
  for (const step of history) {
432
447
  const existing = stepMap.get(step.stepName)
@@ -920,7 +935,9 @@ export abstract class PikkuWorkflowService implements WorkflowService {
920
935
  const queueService = this.verifyQueueService()
921
936
  await queueService.add(
922
937
  this.getStepWorkerQueueName(rpcName),
923
- JSON.parse(JSON.stringify({ runId, stepName, rpcName, data, fromStepName })),
938
+ JSON.parse(
939
+ JSON.stringify({ runId, stepName, rpcName, data, fromStepName })
940
+ ),
924
941
  this.resolveStepJobOptions(stepOptions)
925
942
  )
926
943
  }
@@ -982,29 +999,22 @@ export abstract class PikkuWorkflowService implements WorkflowService {
982
999
  stepOptions?: WorkflowStepOptions,
983
1000
  fromStepName?: string
984
1001
  ): Promise<boolean> {
985
- // Step execution is decided purely by the function's `inline` flag (default
986
- // true). Only a function explicitly marked `inline: false` dispatches via
987
- // the queue. The run-level inline state is intentionally NOT consulted
988
- // here: default steps run inline even inside a queue-dispatched run, so a
989
- // normally-started workflow executes its steps in one orchestrator-worker
990
- // pass instead of one queue round-trip per step.
1002
+ // Step execution is decided purely by the function's `workflowQueued` flag
1003
+ // (default false). Only a function explicitly marked `workflowQueued: true`
1004
+ // dispatches via the queue. If the queue service is not configured that is
1005
+ // a hard error there is no inline fallback.
991
1006
  const functionsMeta = pikkuState(null, 'function', 'meta')
992
1007
  const rpcFuncId = pikkuState(null, 'rpc', 'meta')[rpcName]
993
1008
  const rpcMeta =
994
1009
  typeof rpcFuncId === 'string' ? functionsMeta[rpcFuncId] : undefined
995
- const forceQueue = rpcMeta?.inline === false
1010
+ const forceQueue = rpcMeta?.workflowQueued === true
996
1011
  if (!forceQueue) {
997
1012
  return false
998
1013
  }
999
- // The function opted out of inline execution (`inline: false`) but no queue
1000
- // service is configured to dispatch it. Fall back to inline so the workflow
1001
- // still progresses, but warn loudly — silently swallowing this hides a real
1002
- // misconfiguration (the step won't get its own worker/retry isolation).
1003
1014
  if (!getSingletonServices()?.queueService) {
1004
- getSingletonServices()?.logger.warn(
1005
- `Workflow step '${stepName}' (function '${rpcName}') is marked 'inline: false' but no queue service is configured — running it inline instead of dispatching to a queue.`
1015
+ throw new Error(
1016
+ `Workflow step '${stepName}' (function '${rpcName}') is marked 'workflowQueued: true' but no queue service is configured.`
1006
1017
  )
1007
- return false
1008
1018
  }
1009
1019
  try {
1010
1020
  await getSingletonServices()!.queueService!.add(
@@ -1192,7 +1202,7 @@ export abstract class PikkuWorkflowService implements WorkflowService {
1192
1202
  throw new WorkflowRunFailedError(run.error?.message)
1193
1203
  }
1194
1204
  if (run.status === 'cancelled') {
1195
- throw new Error('Workflow was cancelled')
1205
+ throw new WorkflowRunCancelledError()
1196
1206
  }
1197
1207
  return run.output
1198
1208
  }
@@ -1844,7 +1854,9 @@ export abstract class PikkuWorkflowService implements WorkflowService {
1844
1854
  }
1845
1855
  if (WORKFLOW_END_STATES.has(childRun.status)) {
1846
1856
  if (childRun.status === 'failed') {
1847
- throw new Error(childRun.error?.message || 'Sub-workflow failed')
1857
+ throw new Error(
1858
+ childRun.error?.message || 'Sub-workflow failed'
1859
+ )
1848
1860
  }
1849
1861
  if (childRun.status === 'cancelled') {
1850
1862
  throw new Error('Sub-workflow was cancelled')
@@ -5,13 +5,13 @@ import { InMemoryWorkflowService } from '../../services/in-memory-workflow-servi
5
5
  import { pikkuState } from '../../pikku-state.js'
6
6
  import { WorkflowDispatchException } from './pikku-workflow-service.js'
7
7
 
8
- // Register an `inline: false` function so the workflow's `do()` routes the step
9
- // through the queue (dispatchStep) instead of running it inline.
8
+ // Register a `workflowQueued: true` function so the workflow's `do()` routes
9
+ // the step through the queue (dispatchStep) instead of running it inline.
10
10
  function registerDispatchedFn(rpcName: string): void {
11
11
  const funcId = `fn:${rpcName}`
12
12
  pikkuState(null, 'rpc', 'meta', { [rpcName]: funcId } as any)
13
13
  pikkuState(null, 'function', 'meta', {
14
- [funcId]: { inline: false },
14
+ [funcId]: { workflowQueued: true },
15
15
  } as any)
16
16
  }
17
17