@microfox/ai-worker 1.0.3 → 1.0.5

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 (69) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +22 -0
  3. package/dist/chainMapDefaults.d.mts +21 -0
  4. package/dist/chainMapDefaults.d.ts +21 -0
  5. package/dist/chainMapDefaults.js +59 -0
  6. package/dist/chainMapDefaults.js.map +1 -0
  7. package/dist/chainMapDefaults.mjs +10 -0
  8. package/dist/chainMapDefaults.mjs.map +1 -0
  9. package/dist/chunk-BCRJIFKB.mjs +9 -0
  10. package/dist/chunk-BCRJIFKB.mjs.map +1 -0
  11. package/dist/{chunk-72XGFZCE.mjs → chunk-CILTGUUQ.mjs} +14 -3
  12. package/dist/chunk-CILTGUUQ.mjs.map +1 -0
  13. package/dist/{chunk-7LQNS2SG.mjs → chunk-QHX55IML.mjs} +442 -56
  14. package/dist/chunk-QHX55IML.mjs.map +1 -0
  15. package/dist/chunk-SQB5FQCZ.mjs +21 -0
  16. package/dist/chunk-SQB5FQCZ.mjs.map +1 -0
  17. package/dist/{chunk-AOXGONGI.mjs → chunk-T7DRPKR6.mjs} +7 -5
  18. package/dist/chunk-T7DRPKR6.mjs.map +1 -0
  19. package/dist/chunk-XCKWV2WZ.mjs +34 -0
  20. package/dist/chunk-XCKWV2WZ.mjs.map +1 -0
  21. package/dist/chunk-ZW4PNCDH.mjs +17 -0
  22. package/dist/chunk-ZW4PNCDH.mjs.map +1 -0
  23. package/dist/client.d.mts +148 -2
  24. package/dist/client.d.ts +148 -2
  25. package/dist/client.js +13 -2
  26. package/dist/client.js.map +1 -1
  27. package/dist/client.mjs +1 -1
  28. package/dist/handler.d.mts +121 -23
  29. package/dist/handler.d.ts +121 -23
  30. package/dist/handler.js +450 -58
  31. package/dist/handler.js.map +1 -1
  32. package/dist/handler.mjs +5 -2
  33. package/dist/hitlConfig.d.mts +46 -0
  34. package/dist/hitlConfig.d.ts +46 -0
  35. package/dist/hitlConfig.js +33 -0
  36. package/dist/hitlConfig.js.map +1 -0
  37. package/dist/hitlConfig.mjs +8 -0
  38. package/dist/hitlConfig.mjs.map +1 -0
  39. package/dist/index.d.mts +28 -4
  40. package/dist/index.d.ts +28 -4
  41. package/dist/index.js +575 -74
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +78 -20
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/queue-B5n6YVQV.d.ts +306 -0
  46. package/dist/queue-DaR2UuZi.d.mts +306 -0
  47. package/dist/queue.d.mts +3 -0
  48. package/dist/queue.d.ts +3 -0
  49. package/dist/queue.js +47 -0
  50. package/dist/queue.js.map +1 -0
  51. package/dist/queue.mjs +12 -0
  52. package/dist/queue.mjs.map +1 -0
  53. package/dist/queueInputEnvelope.d.mts +31 -0
  54. package/dist/queueInputEnvelope.d.ts +31 -0
  55. package/dist/queueInputEnvelope.js +42 -0
  56. package/dist/queueInputEnvelope.js.map +1 -0
  57. package/dist/queueInputEnvelope.mjs +10 -0
  58. package/dist/queueInputEnvelope.mjs.map +1 -0
  59. package/dist/queueJobStore.d.mts +3 -2
  60. package/dist/queueJobStore.d.ts +3 -2
  61. package/dist/queueJobStore.js +6 -4
  62. package/dist/queueJobStore.js.map +1 -1
  63. package/dist/queueJobStore.mjs +1 -1
  64. package/package.json +7 -2
  65. package/dist/chunk-72XGFZCE.mjs.map +0 -1
  66. package/dist/chunk-7LQNS2SG.mjs.map +0 -1
  67. package/dist/chunk-AOXGONGI.mjs.map +0 -1
  68. package/dist/client-BqSJQ9mZ.d.mts +0 -183
  69. package/dist/client-BqSJQ9mZ.d.ts +0 -183
@@ -0,0 +1,306 @@
1
+ import { HitlStepConfig } from './hitlConfig.js';
2
+
3
+ /**
4
+ * Smart retry configuration for workers.
5
+ * Retries execute in-process (same Lambda invocation) so error context is preserved
6
+ * between attempts and the job remains in `running` state throughout.
7
+ */
8
+ interface RetryContext {
9
+ /** Current attempt number (1-indexed). 2 = first retry, 3 = second retry, etc. */
10
+ attempt: number;
11
+ /** Total max attempts configured. */
12
+ maxAttempts: number;
13
+ /** Error from the previous attempt — use to self-correct (e.g. inject into prompt). */
14
+ lastError: {
15
+ message: string;
16
+ name: string;
17
+ stack?: string;
18
+ /** HTTP status code or error code if present on the error object. */
19
+ code?: string | number;
20
+ };
21
+ }
22
+ type BuiltInRetryPattern = 'rate-limit' | 'json-parse' | 'overloaded' | 'server-error';
23
+ interface CustomRetryPattern {
24
+ /** Regex test against error.message, or a predicate receiving the full error object. */
25
+ match: RegExp | ((err: Error & Record<string, any>) => boolean);
26
+ /** Delay in ms before the retry. A function receives the retry attempt number (1 = first retry). */
27
+ delayMs?: number | ((attempt: number) => number);
28
+ /** When true, populates ctx.retryContext.lastError so the handler can self-correct. Built-ins set this per pattern. */
29
+ injectContext?: boolean;
30
+ }
31
+ type RetryPattern = BuiltInRetryPattern | CustomRetryPattern;
32
+ interface SmartRetryConfig {
33
+ /** Maximum total attempts, including the first (default: 3). */
34
+ maxAttempts?: number;
35
+ /** Error patterns that trigger a retry. Non-matching errors fail immediately. */
36
+ on: RetryPattern[];
37
+ }
38
+ interface MatchResult {
39
+ matched: boolean;
40
+ delayMs: number;
41
+ injectContext: boolean;
42
+ }
43
+ declare function matchesRetryPattern(err: Error, patterns: RetryPattern[],
44
+ /** 1-indexed retry number (1 = first retry, i.e. second execution). */
45
+ attempt: number): MatchResult;
46
+ /**
47
+ * Executes `fn` with in-process smart retry.
48
+ * `fn` receives `RetryContext | undefined` (undefined on first attempt).
49
+ * `TokenBudgetExceededError` is never retried regardless of config.
50
+ */
51
+ declare function executeWithRetry<T>(fn: (retryCtx: RetryContext | undefined) => Promise<T>, config: SmartRetryConfig, onRetry?: (retryCtx: RetryContext, delayMs: number) => void): Promise<T>;
52
+
53
+ /**
54
+ * Queue definition and context types for worker queues.
55
+ *
56
+ * ## Human-in-the-loop (HITL) pause / resume
57
+ *
58
+ * **Pause (`awaiting_approval`)** — After a step completes, if the **next** step has
59
+ * `requiresApproval: true`, the runtime calls the step's `chain` function (if any),
60
+ * stores the result as the pending input for that step, marks it `awaiting_approval`,
61
+ * and does **not** dispatch the worker until a human approves.
62
+ *
63
+ * **Resume (`POST .../approve`)** — The app route calls `dispatchWorker` for that step
64
+ * with `__hitlInput` (reviewer form payload) attached. The `wrapHandlerForQueue` runtime
65
+ * calls the step's `resume` function (or merges inputs by default) to produce the final
66
+ * domain input, then strips all envelope keys before the user handler receives it.
67
+ *
68
+ * Workers **do not** need to accept any `__workerQueue` / `__hitlPending` / `__hitlInput`
69
+ * keys in their Zod schemas — the runtime strips them automatically.
70
+ */
71
+ /** Output from one completed step, available to subsequent steps via ChainContext / HitlResumeContext. */
72
+ interface QueueStepOutput {
73
+ stepIndex: number;
74
+ workerId: string;
75
+ output: unknown;
76
+ }
77
+ /**
78
+ * Context passed to a step's {@link WorkerQueueStep.chain} function when the queue
79
+ * advances normally (previous step completed without HITL).
80
+ */
81
+ interface ChainContext {
82
+ /** Original input passed to `dispatchQueue` (the first step's input). */
83
+ initialInput: unknown;
84
+ /**
85
+ * Outputs from all previous steps in order.
86
+ * `previousOutputs[0]` = step 0 output; last entry = most recent.
87
+ */
88
+ previousOutputs: QueueStepOutput[];
89
+ }
90
+ /**
91
+ * Context passed to a step's {@link WorkerQueueStep.resume} function when a human has
92
+ * approved the HITL pause and the step is being re-dispatched.
93
+ *
94
+ * @template T - Shape of the reviewer / UI form payload.
95
+ * Derive it from your `hitl.inputSchema` if defined:
96
+ * `HitlResumeContext<z.infer<typeof reviewerSchema>>`.
97
+ */
98
+ interface HitlResumeContext<T = unknown> {
99
+ /** Original input passed to `dispatchQueue` (the first step's input). */
100
+ initialInput: unknown;
101
+ /**
102
+ * Outputs from all previous steps in order.
103
+ * `previousOutputs[0]` = step 0 output; last entry = most recent.
104
+ */
105
+ previousOutputs: QueueStepOutput[];
106
+ /** Reviewer / UI form payload submitted via `POST .../approve` (`input` body field). */
107
+ reviewerInput: T;
108
+ /**
109
+ * The computed next-step input that was stored pending approval (domain fields only;
110
+ * all `__workerQueue` / `__hitlPending` / `hitl` envelope keys are stripped).
111
+ * This is what the `chain` function produced before the step was paused.
112
+ */
113
+ pendingInput: Record<string, unknown>;
114
+ }
115
+ /** Internal envelope keys injected by the queue runtime. Never passed to user handlers. */
116
+ declare const QUEUE_ORCHESTRATION_KEYS: readonly ["__workerQueue", "__hitlInput", "__hitlDecision", "__hitlPending", "hitl"];
117
+ interface WorkerQueueStep {
118
+ /** Worker ID for this step. Must match an existing registered worker. */
119
+ workerId: string;
120
+ /**
121
+ * Optional delay (in seconds) before this step is executed.
122
+ * Implemented via SQS DelaySeconds (max 900).
123
+ */
124
+ delaySeconds?: number;
125
+ /**
126
+ * Called when the queue advances to this step after the previous step completes
127
+ * normally (no HITL). Receives a {@link ChainContext} and must return the input
128
+ * object for this worker.
129
+ *
130
+ * **Built-in shortcuts** (use a string instead of a function):
131
+ * - `'passthrough'` — pass the previous step's output directly as this step's input.
132
+ * - `'continueFromPrevious'` — extract `{ current, history }` from the previous
133
+ * output and build a `{ mode: 'continue', ... }` payload (useful for multi-round sessions).
134
+ *
135
+ * When omitted, the previous step's output is used as-is (equivalent to `'passthrough'`).
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * chain: (ctx) => ({
140
+ * mode: 'review' as const,
141
+ * data: ctx.previousOutputs[ctx.previousOutputs.length - 1]?.output,
142
+ * }),
143
+ * ```
144
+ */
145
+ chain?: ((ctx: ChainContext) => unknown) | 'passthrough' | 'continueFromPrevious';
146
+ /**
147
+ * Called when this step resumes after a human approves a HITL pause.
148
+ * Receives a {@link HitlResumeContext} with the reviewer's form payload and the
149
+ * stored pending input, and must return the final domain input for this worker.
150
+ *
151
+ * When omitted, a shallow merge of `pendingInput` + `reviewerInput` is used as the
152
+ * default (suitable for simple cases where reviewer fields override pending fields).
153
+ *
154
+ * @example
155
+ * ```ts
156
+ * resume: (ctx: HitlResumeContext<ReviewerSchema>) => ({
157
+ * ...ctx.pendingInput,
158
+ * overriddenField: ctx.reviewerInput.overriddenField,
159
+ * }),
160
+ * ```
161
+ */
162
+ resume?: (ctx: HitlResumeContext<any>) => unknown;
163
+ /**
164
+ * When `true`, queue execution pauses before dispatching this step.
165
+ * The step waits until a human calls `POST .../approve` (or `POST .../reject`).
166
+ * Define a `resume` function to control how the reviewer's payload is merged with
167
+ * the pending input.
168
+ */
169
+ requiresApproval?: boolean;
170
+ /**
171
+ * Optional HITL UI/metadata for this step (consumed by app UI and tooling).
172
+ * Use {@link defineHitlConfig} for type-safe authoring.
173
+ * The worker runtime uses only `requiresApproval` — this field is UI-only.
174
+ */
175
+ hitl?: HitlStepConfig;
176
+ /**
177
+ * Smart retry configuration for this queue step.
178
+ * Overrides any retry config on the worker definition for this step only.
179
+ * Retries run in-process (same Lambda invocation); ctx.retryContext is populated
180
+ * on each retry so the handler can self-correct (e.g. inject error into prompt).
181
+ *
182
+ * @example
183
+ * ```ts
184
+ * retry: { maxAttempts: 3, on: ['rate-limit', 'json-parse'] }
185
+ * ```
186
+ */
187
+ retry?: SmartRetryConfig;
188
+ /**
189
+ * When defined, evaluated after each run of this step to decide whether to
190
+ * re-run it (another iteration) instead of advancing to the next step.
191
+ *
192
+ * Combine with `requiresApproval: true` for HITL-gated loops where the
193
+ * reviewer's decision (e.g. a `continueLoop` field in their payload)
194
+ * controls whether another round starts.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * // Loop continues until the worker returns { finalized: true }
199
+ * loop: {
200
+ * shouldContinue: ({ output }) => !(output as { finalized?: boolean }).finalized,
201
+ * maxIterations: 20,
202
+ * }
203
+ * ```
204
+ */
205
+ loop?: {
206
+ /** Return true to run this step again; false to advance to the next step. */
207
+ shouldContinue: (ctx: LoopContext) => boolean | Promise<boolean>;
208
+ /**
209
+ * Hard cap on total iterations (including the first run).
210
+ * Prevents runaway loops. Default: 50.
211
+ */
212
+ maxIterations?: number;
213
+ };
214
+ }
215
+ interface WorkerQueueConfig<InitialInput = any, StepOutput = any> {
216
+ /** Stable queue identifier, e.g. `"cost-review"`. */
217
+ id: string;
218
+ /** Ordered list of steps forming the queue pipeline. */
219
+ steps: WorkerQueueStep[];
220
+ /**
221
+ * Optional schedule for the queue (cron or rate expression).
222
+ * When set, the CLI generates a queue-starter Lambda triggered by this schedule.
223
+ * @example `'cron(0 3 * * ? *)'` — daily at 03:00 UTC.
224
+ */
225
+ schedule?: string | {
226
+ rate: string;
227
+ enabled?: boolean;
228
+ input?: Record<string, any>;
229
+ };
230
+ _initialInputType?: InitialInput;
231
+ _stepOutputType?: StepOutput;
232
+ }
233
+ /**
234
+ * Context passed to a step's {@link WorkerQueueStep.loop | loop.shouldContinue} function
235
+ * after each iteration of a looping step.
236
+ */
237
+ interface LoopContext {
238
+ /** Output returned by the worker for this iteration. */
239
+ output: unknown;
240
+ /** Step definition index (stable; does not change across iterations). */
241
+ stepIndex: number;
242
+ /** 0-based count of how many times this step has already run (0 = first run). */
243
+ iterationCount: number;
244
+ /** Original input passed to `dispatchQueue`. */
245
+ initialInput: unknown;
246
+ /** Outputs from all previous steps (and previous iterations of this step). */
247
+ previousOutputs: QueueStepOutput[];
248
+ }
249
+ /**
250
+ * Queue execution context embedded into job input so queue-aware wrappers
251
+ * know their position in the pipeline. Injected automatically by the runtime.
252
+ */
253
+ interface WorkerQueueContext<InitialInput = any> {
254
+ id: string;
255
+ /** Queue definition step index — used to look up chain/resume/loop config. Stays fixed across loop iterations. */
256
+ stepIndex: number;
257
+ /**
258
+ * Actual array position of this step in the job's steps[] store.
259
+ * Differs from stepIndex when the same step has looped multiple times
260
+ * (each iteration is appended as a new entry). Defaults to stepIndex when absent.
261
+ */
262
+ arrayStepIndex?: number;
263
+ initialInput: InitialInput;
264
+ /** Queue job ID for progress tracking (same as first worker's jobId). */
265
+ queueJobId?: string;
266
+ /** How many times this step has already run (used by looping steps). */
267
+ iterationCount?: number;
268
+ }
269
+ /**
270
+ * Repeat a step definition `count` times, calling `factory(index)` for each repetition.
271
+ * Eliminates copy-paste for multi-round HITL workflows.
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * const queue = defineWorkerQueue({
276
+ * id: 'multi-review',
277
+ * steps: [
278
+ * { workerId: 'ingest' },
279
+ * ...repeatStep(3, (i) => ({
280
+ * workerId: 'review',
281
+ * chain: chainFromPrev,
282
+ * resume: resumeFromHitl,
283
+ * requiresApproval: true,
284
+ * hitl: defineHitlConfig({ taskKey: `review-r${i + 1}`, ui: { type: 'schema-form', title: `Round ${i + 1}` } }),
285
+ * })),
286
+ * ],
287
+ * });
288
+ * ```
289
+ */
290
+ declare function repeatStep(count: number, factory: (index: number) => WorkerQueueStep): WorkerQueueStep[];
291
+ /**
292
+ * Identity helper for defining worker queues in `.queue.ts` files.
293
+ * Use `satisfies WorkerQueueConfig<InitialInput, StepOutput>` for phantom-type docs.
294
+ *
295
+ * @example
296
+ * ```ts
297
+ * const q = defineWorkerQueue({
298
+ * id: 'my-queue',
299
+ * steps: [ ... ],
300
+ * }) satisfies WorkerQueueConfig<MyInit, MyOutput>;
301
+ * export default q;
302
+ * ```
303
+ */
304
+ declare function defineWorkerQueue<T extends WorkerQueueConfig>(config: T): T;
305
+
306
+ export { type BuiltInRetryPattern as B, type CustomRetryPattern as C, type HitlResumeContext as H, type LoopContext as L, type QueueStepOutput as Q, type RetryContext as R, type SmartRetryConfig as S, type WorkerQueueStep as W, type RetryPattern as a, type ChainContext as b, QUEUE_ORCHESTRATION_KEYS as c, type WorkerQueueConfig as d, type WorkerQueueContext as e, defineWorkerQueue as f, executeWithRetry as g, matchesRetryPattern as m, repeatStep as r };
@@ -0,0 +1,306 @@
1
+ import { HitlStepConfig } from './hitlConfig.mjs';
2
+
3
+ /**
4
+ * Smart retry configuration for workers.
5
+ * Retries execute in-process (same Lambda invocation) so error context is preserved
6
+ * between attempts and the job remains in `running` state throughout.
7
+ */
8
+ interface RetryContext {
9
+ /** Current attempt number (1-indexed). 2 = first retry, 3 = second retry, etc. */
10
+ attempt: number;
11
+ /** Total max attempts configured. */
12
+ maxAttempts: number;
13
+ /** Error from the previous attempt — use to self-correct (e.g. inject into prompt). */
14
+ lastError: {
15
+ message: string;
16
+ name: string;
17
+ stack?: string;
18
+ /** HTTP status code or error code if present on the error object. */
19
+ code?: string | number;
20
+ };
21
+ }
22
+ type BuiltInRetryPattern = 'rate-limit' | 'json-parse' | 'overloaded' | 'server-error';
23
+ interface CustomRetryPattern {
24
+ /** Regex test against error.message, or a predicate receiving the full error object. */
25
+ match: RegExp | ((err: Error & Record<string, any>) => boolean);
26
+ /** Delay in ms before the retry. A function receives the retry attempt number (1 = first retry). */
27
+ delayMs?: number | ((attempt: number) => number);
28
+ /** When true, populates ctx.retryContext.lastError so the handler can self-correct. Built-ins set this per pattern. */
29
+ injectContext?: boolean;
30
+ }
31
+ type RetryPattern = BuiltInRetryPattern | CustomRetryPattern;
32
+ interface SmartRetryConfig {
33
+ /** Maximum total attempts, including the first (default: 3). */
34
+ maxAttempts?: number;
35
+ /** Error patterns that trigger a retry. Non-matching errors fail immediately. */
36
+ on: RetryPattern[];
37
+ }
38
+ interface MatchResult {
39
+ matched: boolean;
40
+ delayMs: number;
41
+ injectContext: boolean;
42
+ }
43
+ declare function matchesRetryPattern(err: Error, patterns: RetryPattern[],
44
+ /** 1-indexed retry number (1 = first retry, i.e. second execution). */
45
+ attempt: number): MatchResult;
46
+ /**
47
+ * Executes `fn` with in-process smart retry.
48
+ * `fn` receives `RetryContext | undefined` (undefined on first attempt).
49
+ * `TokenBudgetExceededError` is never retried regardless of config.
50
+ */
51
+ declare function executeWithRetry<T>(fn: (retryCtx: RetryContext | undefined) => Promise<T>, config: SmartRetryConfig, onRetry?: (retryCtx: RetryContext, delayMs: number) => void): Promise<T>;
52
+
53
+ /**
54
+ * Queue definition and context types for worker queues.
55
+ *
56
+ * ## Human-in-the-loop (HITL) pause / resume
57
+ *
58
+ * **Pause (`awaiting_approval`)** — After a step completes, if the **next** step has
59
+ * `requiresApproval: true`, the runtime calls the step's `chain` function (if any),
60
+ * stores the result as the pending input for that step, marks it `awaiting_approval`,
61
+ * and does **not** dispatch the worker until a human approves.
62
+ *
63
+ * **Resume (`POST .../approve`)** — The app route calls `dispatchWorker` for that step
64
+ * with `__hitlInput` (reviewer form payload) attached. The `wrapHandlerForQueue` runtime
65
+ * calls the step's `resume` function (or merges inputs by default) to produce the final
66
+ * domain input, then strips all envelope keys before the user handler receives it.
67
+ *
68
+ * Workers **do not** need to accept any `__workerQueue` / `__hitlPending` / `__hitlInput`
69
+ * keys in their Zod schemas — the runtime strips them automatically.
70
+ */
71
+ /** Output from one completed step, available to subsequent steps via ChainContext / HitlResumeContext. */
72
+ interface QueueStepOutput {
73
+ stepIndex: number;
74
+ workerId: string;
75
+ output: unknown;
76
+ }
77
+ /**
78
+ * Context passed to a step's {@link WorkerQueueStep.chain} function when the queue
79
+ * advances normally (previous step completed without HITL).
80
+ */
81
+ interface ChainContext {
82
+ /** Original input passed to `dispatchQueue` (the first step's input). */
83
+ initialInput: unknown;
84
+ /**
85
+ * Outputs from all previous steps in order.
86
+ * `previousOutputs[0]` = step 0 output; last entry = most recent.
87
+ */
88
+ previousOutputs: QueueStepOutput[];
89
+ }
90
+ /**
91
+ * Context passed to a step's {@link WorkerQueueStep.resume} function when a human has
92
+ * approved the HITL pause and the step is being re-dispatched.
93
+ *
94
+ * @template T - Shape of the reviewer / UI form payload.
95
+ * Derive it from your `hitl.inputSchema` if defined:
96
+ * `HitlResumeContext<z.infer<typeof reviewerSchema>>`.
97
+ */
98
+ interface HitlResumeContext<T = unknown> {
99
+ /** Original input passed to `dispatchQueue` (the first step's input). */
100
+ initialInput: unknown;
101
+ /**
102
+ * Outputs from all previous steps in order.
103
+ * `previousOutputs[0]` = step 0 output; last entry = most recent.
104
+ */
105
+ previousOutputs: QueueStepOutput[];
106
+ /** Reviewer / UI form payload submitted via `POST .../approve` (`input` body field). */
107
+ reviewerInput: T;
108
+ /**
109
+ * The computed next-step input that was stored pending approval (domain fields only;
110
+ * all `__workerQueue` / `__hitlPending` / `hitl` envelope keys are stripped).
111
+ * This is what the `chain` function produced before the step was paused.
112
+ */
113
+ pendingInput: Record<string, unknown>;
114
+ }
115
+ /** Internal envelope keys injected by the queue runtime. Never passed to user handlers. */
116
+ declare const QUEUE_ORCHESTRATION_KEYS: readonly ["__workerQueue", "__hitlInput", "__hitlDecision", "__hitlPending", "hitl"];
117
+ interface WorkerQueueStep {
118
+ /** Worker ID for this step. Must match an existing registered worker. */
119
+ workerId: string;
120
+ /**
121
+ * Optional delay (in seconds) before this step is executed.
122
+ * Implemented via SQS DelaySeconds (max 900).
123
+ */
124
+ delaySeconds?: number;
125
+ /**
126
+ * Called when the queue advances to this step after the previous step completes
127
+ * normally (no HITL). Receives a {@link ChainContext} and must return the input
128
+ * object for this worker.
129
+ *
130
+ * **Built-in shortcuts** (use a string instead of a function):
131
+ * - `'passthrough'` — pass the previous step's output directly as this step's input.
132
+ * - `'continueFromPrevious'` — extract `{ current, history }` from the previous
133
+ * output and build a `{ mode: 'continue', ... }` payload (useful for multi-round sessions).
134
+ *
135
+ * When omitted, the previous step's output is used as-is (equivalent to `'passthrough'`).
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * chain: (ctx) => ({
140
+ * mode: 'review' as const,
141
+ * data: ctx.previousOutputs[ctx.previousOutputs.length - 1]?.output,
142
+ * }),
143
+ * ```
144
+ */
145
+ chain?: ((ctx: ChainContext) => unknown) | 'passthrough' | 'continueFromPrevious';
146
+ /**
147
+ * Called when this step resumes after a human approves a HITL pause.
148
+ * Receives a {@link HitlResumeContext} with the reviewer's form payload and the
149
+ * stored pending input, and must return the final domain input for this worker.
150
+ *
151
+ * When omitted, a shallow merge of `pendingInput` + `reviewerInput` is used as the
152
+ * default (suitable for simple cases where reviewer fields override pending fields).
153
+ *
154
+ * @example
155
+ * ```ts
156
+ * resume: (ctx: HitlResumeContext<ReviewerSchema>) => ({
157
+ * ...ctx.pendingInput,
158
+ * overriddenField: ctx.reviewerInput.overriddenField,
159
+ * }),
160
+ * ```
161
+ */
162
+ resume?: (ctx: HitlResumeContext<any>) => unknown;
163
+ /**
164
+ * When `true`, queue execution pauses before dispatching this step.
165
+ * The step waits until a human calls `POST .../approve` (or `POST .../reject`).
166
+ * Define a `resume` function to control how the reviewer's payload is merged with
167
+ * the pending input.
168
+ */
169
+ requiresApproval?: boolean;
170
+ /**
171
+ * Optional HITL UI/metadata for this step (consumed by app UI and tooling).
172
+ * Use {@link defineHitlConfig} for type-safe authoring.
173
+ * The worker runtime uses only `requiresApproval` — this field is UI-only.
174
+ */
175
+ hitl?: HitlStepConfig;
176
+ /**
177
+ * Smart retry configuration for this queue step.
178
+ * Overrides any retry config on the worker definition for this step only.
179
+ * Retries run in-process (same Lambda invocation); ctx.retryContext is populated
180
+ * on each retry so the handler can self-correct (e.g. inject error into prompt).
181
+ *
182
+ * @example
183
+ * ```ts
184
+ * retry: { maxAttempts: 3, on: ['rate-limit', 'json-parse'] }
185
+ * ```
186
+ */
187
+ retry?: SmartRetryConfig;
188
+ /**
189
+ * When defined, evaluated after each run of this step to decide whether to
190
+ * re-run it (another iteration) instead of advancing to the next step.
191
+ *
192
+ * Combine with `requiresApproval: true` for HITL-gated loops where the
193
+ * reviewer's decision (e.g. a `continueLoop` field in their payload)
194
+ * controls whether another round starts.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * // Loop continues until the worker returns { finalized: true }
199
+ * loop: {
200
+ * shouldContinue: ({ output }) => !(output as { finalized?: boolean }).finalized,
201
+ * maxIterations: 20,
202
+ * }
203
+ * ```
204
+ */
205
+ loop?: {
206
+ /** Return true to run this step again; false to advance to the next step. */
207
+ shouldContinue: (ctx: LoopContext) => boolean | Promise<boolean>;
208
+ /**
209
+ * Hard cap on total iterations (including the first run).
210
+ * Prevents runaway loops. Default: 50.
211
+ */
212
+ maxIterations?: number;
213
+ };
214
+ }
215
+ interface WorkerQueueConfig<InitialInput = any, StepOutput = any> {
216
+ /** Stable queue identifier, e.g. `"cost-review"`. */
217
+ id: string;
218
+ /** Ordered list of steps forming the queue pipeline. */
219
+ steps: WorkerQueueStep[];
220
+ /**
221
+ * Optional schedule for the queue (cron or rate expression).
222
+ * When set, the CLI generates a queue-starter Lambda triggered by this schedule.
223
+ * @example `'cron(0 3 * * ? *)'` — daily at 03:00 UTC.
224
+ */
225
+ schedule?: string | {
226
+ rate: string;
227
+ enabled?: boolean;
228
+ input?: Record<string, any>;
229
+ };
230
+ _initialInputType?: InitialInput;
231
+ _stepOutputType?: StepOutput;
232
+ }
233
+ /**
234
+ * Context passed to a step's {@link WorkerQueueStep.loop | loop.shouldContinue} function
235
+ * after each iteration of a looping step.
236
+ */
237
+ interface LoopContext {
238
+ /** Output returned by the worker for this iteration. */
239
+ output: unknown;
240
+ /** Step definition index (stable; does not change across iterations). */
241
+ stepIndex: number;
242
+ /** 0-based count of how many times this step has already run (0 = first run). */
243
+ iterationCount: number;
244
+ /** Original input passed to `dispatchQueue`. */
245
+ initialInput: unknown;
246
+ /** Outputs from all previous steps (and previous iterations of this step). */
247
+ previousOutputs: QueueStepOutput[];
248
+ }
249
+ /**
250
+ * Queue execution context embedded into job input so queue-aware wrappers
251
+ * know their position in the pipeline. Injected automatically by the runtime.
252
+ */
253
+ interface WorkerQueueContext<InitialInput = any> {
254
+ id: string;
255
+ /** Queue definition step index — used to look up chain/resume/loop config. Stays fixed across loop iterations. */
256
+ stepIndex: number;
257
+ /**
258
+ * Actual array position of this step in the job's steps[] store.
259
+ * Differs from stepIndex when the same step has looped multiple times
260
+ * (each iteration is appended as a new entry). Defaults to stepIndex when absent.
261
+ */
262
+ arrayStepIndex?: number;
263
+ initialInput: InitialInput;
264
+ /** Queue job ID for progress tracking (same as first worker's jobId). */
265
+ queueJobId?: string;
266
+ /** How many times this step has already run (used by looping steps). */
267
+ iterationCount?: number;
268
+ }
269
+ /**
270
+ * Repeat a step definition `count` times, calling `factory(index)` for each repetition.
271
+ * Eliminates copy-paste for multi-round HITL workflows.
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * const queue = defineWorkerQueue({
276
+ * id: 'multi-review',
277
+ * steps: [
278
+ * { workerId: 'ingest' },
279
+ * ...repeatStep(3, (i) => ({
280
+ * workerId: 'review',
281
+ * chain: chainFromPrev,
282
+ * resume: resumeFromHitl,
283
+ * requiresApproval: true,
284
+ * hitl: defineHitlConfig({ taskKey: `review-r${i + 1}`, ui: { type: 'schema-form', title: `Round ${i + 1}` } }),
285
+ * })),
286
+ * ],
287
+ * });
288
+ * ```
289
+ */
290
+ declare function repeatStep(count: number, factory: (index: number) => WorkerQueueStep): WorkerQueueStep[];
291
+ /**
292
+ * Identity helper for defining worker queues in `.queue.ts` files.
293
+ * Use `satisfies WorkerQueueConfig<InitialInput, StepOutput>` for phantom-type docs.
294
+ *
295
+ * @example
296
+ * ```ts
297
+ * const q = defineWorkerQueue({
298
+ * id: 'my-queue',
299
+ * steps: [ ... ],
300
+ * }) satisfies WorkerQueueConfig<MyInit, MyOutput>;
301
+ * export default q;
302
+ * ```
303
+ */
304
+ declare function defineWorkerQueue<T extends WorkerQueueConfig>(config: T): T;
305
+
306
+ export { type BuiltInRetryPattern as B, type CustomRetryPattern as C, type HitlResumeContext as H, type LoopContext as L, type QueueStepOutput as Q, type RetryContext as R, type SmartRetryConfig as S, type WorkerQueueStep as W, type RetryPattern as a, type ChainContext as b, QUEUE_ORCHESTRATION_KEYS as c, type WorkerQueueConfig as d, type WorkerQueueContext as e, defineWorkerQueue as f, executeWithRetry as g, matchesRetryPattern as m, repeatStep as r };
@@ -0,0 +1,3 @@
1
+ import './hitlConfig.mjs';
2
+ export { b as ChainContext, H as HitlResumeContext, L as LoopContext, c as QUEUE_ORCHESTRATION_KEYS, Q as QueueStepOutput, d as WorkerQueueConfig, e as WorkerQueueContext, W as WorkerQueueStep, f as defineWorkerQueue, r as repeatStep } from './queue-DaR2UuZi.mjs';
3
+ import 'zod';
@@ -0,0 +1,3 @@
1
+ import './hitlConfig.js';
2
+ export { b as ChainContext, H as HitlResumeContext, L as LoopContext, c as QUEUE_ORCHESTRATION_KEYS, Q as QueueStepOutput, d as WorkerQueueConfig, e as WorkerQueueContext, W as WorkerQueueStep, f as defineWorkerQueue, r as repeatStep } from './queue-B5n6YVQV.js';
3
+ import 'zod';
package/dist/queue.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/queue.ts
21
+ var queue_exports = {};
22
+ __export(queue_exports, {
23
+ QUEUE_ORCHESTRATION_KEYS: () => QUEUE_ORCHESTRATION_KEYS,
24
+ defineWorkerQueue: () => defineWorkerQueue,
25
+ repeatStep: () => repeatStep
26
+ });
27
+ module.exports = __toCommonJS(queue_exports);
28
+ var QUEUE_ORCHESTRATION_KEYS = [
29
+ "__workerQueue",
30
+ "__hitlInput",
31
+ "__hitlDecision",
32
+ "__hitlPending",
33
+ "hitl"
34
+ ];
35
+ function repeatStep(count, factory) {
36
+ return Array.from({ length: count }, (_, i) => factory(i));
37
+ }
38
+ function defineWorkerQueue(config) {
39
+ return config;
40
+ }
41
+ // Annotate the CommonJS export names for ESM import in node:
42
+ 0 && (module.exports = {
43
+ QUEUE_ORCHESTRATION_KEYS,
44
+ defineWorkerQueue,
45
+ repeatStep
46
+ });
47
+ //# sourceMappingURL=queue.js.map