experimental-ash 0.22.2 → 0.24.0
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.
- package/CHANGELOG.md +36 -0
- package/dist/docs/internals/hooks.md +13 -16
- package/dist/docs/internals/message-runtime.md +1 -1
- package/dist/docs/public/auth-and-route-protection.md +3 -3
- package/dist/docs/public/faqs.md +67 -0
- package/dist/docs/public/meta.json +1 -0
- package/dist/docs/public/schedules.md +11 -0
- package/dist/docs/public/session-context.md +46 -89
- package/dist/docs/public/skills.md +13 -0
- package/dist/docs/public/subagents.md +12 -6
- package/dist/docs/public/tools.md +9 -13
- package/dist/docs/public/typescript-api.md +4 -4
- package/dist/src/channel/types.d.ts +10 -12
- package/dist/src/chunks/{client-CKsU8Li3.js → client-nshDsWNF.js} +1 -1
- package/dist/src/chunks/{dev-authored-source-watcher-BLzYWh05.js → dev-authored-source-watcher-B4PaZGUr.js} +1 -1
- package/dist/src/chunks/host-DsW72Q-w.js +65 -0
- package/dist/src/chunks/paths-OknjaYR8.js +89 -0
- package/dist/src/chunks/prewarm-B4YblQ5m.js +6 -0
- package/dist/src/cli/commands/info.js +1 -1
- package/dist/src/cli/dev/repl.js +2 -2
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/session.js +8 -0
- package/dist/src/client/types.d.ts +12 -1
- package/dist/src/compiled/.vendor-stamp.json +3 -3
- package/dist/src/compiled/@workflow/core/_ms.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/_workflow-serde.d.ts +5 -0
- package/dist/src/compiled/@workflow/core/_workflow-utils.d.ts +8 -0
- package/dist/src/compiled/@workflow/core/_workflow-world.d.ts +59 -0
- package/dist/src/compiled/@workflow/core/capabilities.d.ts +45 -0
- package/dist/src/compiled/@workflow/core/capture-stack.d.ts +16 -0
- package/dist/src/compiled/@workflow/core/class-serialization.d.ts +31 -0
- package/dist/src/compiled/@workflow/core/classify-error.d.ts +20 -0
- package/dist/src/compiled/@workflow/core/context-errors.d.ts +27 -0
- package/dist/src/compiled/@workflow/core/context-violation-error.d.ts +97 -0
- package/dist/src/compiled/@workflow/core/create-hook.d.ts +179 -0
- package/dist/src/compiled/@workflow/core/define-hook.d.ts +68 -0
- package/dist/src/compiled/@workflow/core/describe-error.d.ts +70 -0
- package/dist/src/compiled/@workflow/core/encryption.d.ts +51 -0
- package/dist/src/compiled/@workflow/core/events-consumer.d.ts +64 -0
- package/dist/src/compiled/@workflow/core/flushable-stream.d.ts +82 -0
- package/dist/src/compiled/@workflow/core/global.d.ts +48 -0
- package/dist/src/compiled/@workflow/core/index.d.ts +19 -38
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/log-format.d.ts +25 -0
- package/dist/src/compiled/@workflow/core/logger.d.ts +29 -0
- package/dist/src/compiled/@workflow/core/package.json +1 -1
- package/dist/src/compiled/@workflow/core/private.d.ts +59 -10
- package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +51 -0
- package/dist/src/compiled/@workflow/core/runtime/get-port-lazy.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/runtime/get-world-lazy.d.ts +32 -0
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +97 -0
- package/dist/src/compiled/@workflow/core/runtime/replay-budget.d.ts +98 -0
- package/dist/src/compiled/@workflow/core/runtime/resume-hook.d.ts +77 -0
- package/dist/src/compiled/@workflow/core/runtime/run.d.ts +134 -0
- package/dist/src/compiled/@workflow/core/runtime/runs.d.ts +50 -0
- package/dist/src/compiled/@workflow/core/runtime/start.d.ts +59 -0
- package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +40 -0
- package/dist/src/compiled/@workflow/core/runtime/step-handler.d.ts +2 -0
- package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +42 -0
- package/dist/src/compiled/@workflow/core/runtime/world-init.d.ts +75 -0
- package/dist/src/compiled/@workflow/core/runtime/world.d.ts +32 -0
- package/dist/src/compiled/@workflow/core/runtime.d.ts +22 -67
- package/dist/src/compiled/@workflow/core/runtime.js +27 -27
- package/dist/src/compiled/@workflow/core/schemas.d.ts +15 -0
- package/dist/src/compiled/@workflow/core/serialization/client.d.ts +17 -0
- package/dist/src/compiled/@workflow/core/serialization/codec-devalue.d.ts +14 -0
- package/dist/src/compiled/@workflow/core/serialization/codec.d.ts +90 -0
- package/dist/src/compiled/@workflow/core/serialization/encryption.d.ts +32 -0
- package/dist/src/compiled/@workflow/core/serialization/errors.d.ts +21 -0
- package/dist/src/compiled/@workflow/core/serialization/format.d.ts +60 -0
- package/dist/src/compiled/@workflow/core/serialization/index.d.ts +18 -0
- package/dist/src/compiled/@workflow/core/serialization/reducers/class.d.ts +11 -0
- package/dist/src/compiled/@workflow/core/serialization/reducers/common.d.ts +16 -0
- package/dist/src/compiled/@workflow/core/serialization/reducers/step-function.d.ts +35 -0
- package/dist/src/compiled/@workflow/core/serialization/step.d.ts +17 -0
- package/dist/src/compiled/@workflow/core/serialization/types.d.ts +215 -0
- package/dist/src/compiled/@workflow/core/serialization/workflow.d.ts +29 -0
- package/dist/src/compiled/@workflow/core/serialization-format.d.ts +171 -0
- package/dist/src/compiled/@workflow/core/serialization.d.ts +337 -0
- package/dist/src/compiled/@workflow/core/sleep.d.ts +33 -0
- package/dist/src/compiled/@workflow/core/source-map.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +13 -0
- package/dist/src/compiled/@workflow/core/step/get-closure-vars.d.ts +9 -0
- package/dist/src/compiled/@workflow/core/step/get-step-metadata.d.ts +42 -0
- package/dist/src/compiled/@workflow/core/step/get-workflow-metadata.d.ts +7 -0
- package/dist/src/compiled/@workflow/core/step/writable-stream.d.ts +22 -0
- package/dist/src/compiled/@workflow/core/step.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/symbols.d.ts +36 -0
- package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +283 -0
- package/dist/src/compiled/@workflow/core/telemetry.d.ts +53 -0
- package/dist/src/compiled/@workflow/core/types.d.ts +14 -0
- package/dist/src/compiled/@workflow/core/util.d.ts +40 -0
- package/dist/src/compiled/@workflow/core/version.d.ts +2 -0
- package/dist/src/compiled/@workflow/core/vm/index.d.ts +17 -0
- package/dist/src/compiled/@workflow/core/vm/uint8array-base64.d.ts +21 -0
- package/dist/src/compiled/@workflow/core/vm/uuid.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/workflow/abort-controller.d.ts +65 -0
- package/dist/src/compiled/@workflow/core/workflow/create-hook.d.ts +7 -0
- package/dist/src/compiled/@workflow/core/workflow/define-hook.d.ts +10 -0
- package/dist/src/compiled/@workflow/core/workflow/get-workflow-metadata.d.ts +32 -0
- package/dist/src/compiled/@workflow/core/workflow/hook.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/workflow/index.d.ts +11 -0
- package/dist/src/compiled/@workflow/core/workflow/sleep.d.ts +4 -0
- package/dist/src/compiled/@workflow/core/workflow/world-init-stub.d.ts +15 -0
- package/dist/src/compiled/@workflow/core/workflow/writable-stream.d.ts +3 -0
- package/dist/src/compiled/@workflow/core/workflow.d.ts +1 -38
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/errors/error-codes.d.ts +5 -1
- package/dist/src/compiled/@workflow/errors/index.d.ts +15 -1
- package/dist/src/compiled/@workflow/errors/index.js +1 -1
- package/dist/src/compiled/@workflow/errors/package.json +1 -1
- package/dist/src/compiled/_chunks/workflow/{context-errors-zbKocOyk.js → context-errors-Bbvvp-li.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/{dist-0iNBqPYp.js → dist-C7wPwOI9.js} +2 -2
- package/dist/src/compiled/_chunks/workflow/{dist-D774SUM4.js → dist-C_oiE-l7.js} +1 -1
- package/dist/src/compiled/_chunks/workflow/resume-hook-C3VWUPii.js +12 -0
- package/dist/src/compiled/_chunks/workflow/sleep-QTkC1VFe.js +1 -0
- package/dist/src/compiled/_chunks/workflow/{symbols-D-4tVV8x.js → symbols-QezhMuLg.js} +1 -1
- package/dist/src/evals/cli/eval.js +1 -1
- package/dist/src/execution/await-authorization-orchestrator.d.ts +2 -1
- package/dist/src/execution/await-authorization-orchestrator.js +4 -0
- package/dist/src/execution/connection-auth-steps.d.ts +4 -0
- package/dist/src/execution/connection-auth-steps.js +9 -11
- package/dist/src/execution/node-step.d.ts +4 -5
- package/dist/src/execution/subagent-adapter.d.ts +0 -27
- package/dist/src/execution/subagent-adapter.js +2 -66
- package/dist/src/execution/subagent-hitl-proxy.d.ts +2 -2
- package/dist/src/execution/subagent-hitl-proxy.js +2 -2
- package/dist/src/execution/task-mode.d.ts +3 -3
- package/dist/src/execution/task-mode.js +3 -3
- package/dist/src/execution/turn-workflow.d.ts +41 -0
- package/dist/src/execution/turn-workflow.js +96 -0
- package/dist/src/execution/workflow-entry.js +77 -87
- package/dist/src/execution/workflow-errors.d.ts +14 -0
- package/dist/src/execution/workflow-errors.js +54 -0
- package/dist/src/execution/workflow-runtime.d.ts +34 -3
- package/dist/src/execution/workflow-runtime.js +52 -10
- package/dist/src/execution/workflow-steps.d.ts +27 -2
- package/dist/src/execution/workflow-steps.js +31 -26
- package/dist/src/harness/instrumentation-config.js +14 -7
- package/dist/src/harness/messages.d.ts +7 -7
- package/dist/src/harness/messages.js +4 -4
- package/dist/src/harness/runtime-actions.d.ts +4 -4
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/workflow-bundle/workflow-builders.d.ts +1 -1
- package/dist/src/internal/workflow-bundle/workflow-builders.js +20 -8
- package/dist/src/internal/workflow-bundle/workflow-transformer.d.ts +13 -0
- package/dist/src/internal/workflow-bundle/workflow-transformer.js +10 -4
- package/dist/src/protocol/message.d.ts +6 -1
- package/dist/src/public/channels/ash.js +50 -3
- package/dist/src/public/context/index.d.ts +4 -7
- package/dist/src/public/context/index.js +4 -5
- package/dist/src/public/definitions/state.d.ts +33 -0
- package/dist/src/public/definitions/state.js +34 -0
- package/dist/src/public/next/index.d.ts +7 -0
- package/dist/src/public/next/index.js +2 -0
- package/dist/src/public/next/vercel-json.d.ts +1 -0
- package/dist/src/public/next/vercel-json.js +1 -0
- package/dist/src/react/index.d.ts +1 -1
- package/dist/src/react/use-ash-agent.d.ts +8 -0
- package/dist/src/react/use-ash-agent.js +26 -4
- package/dist/src/services/dev-client.d.ts +4 -1
- package/dist/src/services/dev-client.js +1 -0
- package/package.json +4 -4
- package/dist/src/chunks/host-DREC8e8Z.js +0 -65
- package/dist/src/chunks/paths-C6sp4T2U.js +0 -88
- package/dist/src/chunks/prewarm-hz8p2jlZ.js +0 -6
- package/dist/src/compiled/_chunks/workflow/resume-hook-CL8Ed91K.js +0 -12
- package/dist/src/compiled/_chunks/workflow/sleep-Dn3i9nxI.js +0 -1
- package/dist/src/execution/continuous-entry.d.ts +0 -59
- package/dist/src/execution/continuous-entry.js +0 -487
- package/dist/src/execution/continuous-runtime.d.ts +0 -17
- package/dist/src/execution/continuous-runtime.js +0 -123
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Event, HealthCheckPayload, ValidQueueName, WorkflowRun, World } from '../_workflow-world.js';
|
|
2
|
+
import { type CryptoKey } from '../encryption.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validates a workflow name and returns the corresponding queue name.
|
|
5
|
+
* Ensures the workflow name only contains safe characters before
|
|
6
|
+
* interpolating it into the queue name string.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getWorkflowQueueName(workflowName: string): ValidQueueName;
|
|
9
|
+
/**
|
|
10
|
+
* Result of a health check operation.
|
|
11
|
+
*/
|
|
12
|
+
export interface HealthCheckResult {
|
|
13
|
+
healthy: boolean;
|
|
14
|
+
/** Error message if health check failed */
|
|
15
|
+
error?: string;
|
|
16
|
+
/** Latency if the health check was successful */
|
|
17
|
+
latencyMs?: number;
|
|
18
|
+
/** Spec version of the responding deployment */
|
|
19
|
+
specVersion?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Checks if the given message is a health check payload.
|
|
23
|
+
* If so, returns the parsed payload. Otherwise returns undefined.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseHealthCheckPayload(message: unknown): HealthCheckPayload | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Handles a health check message by writing the result to the world's stream.
|
|
28
|
+
* The caller can listen to this stream to get the health check response.
|
|
29
|
+
*
|
|
30
|
+
* @param healthCheck - The parsed health check payload
|
|
31
|
+
* @param endpoint - Which endpoint is responding ('workflow' or 'step')
|
|
32
|
+
*/
|
|
33
|
+
export declare function handleHealthCheckMessage(healthCheck: HealthCheckPayload, endpoint: 'workflow' | 'step', worldSpecVersion?: number): Promise<void>;
|
|
34
|
+
export type HealthCheckEndpoint = 'workflow' | 'step';
|
|
35
|
+
export interface HealthCheckOptions {
|
|
36
|
+
/** Timeout in milliseconds to wait for health check response. Default: 30000 (30s) */
|
|
37
|
+
timeout?: number;
|
|
38
|
+
/** Deployment ID to send the health check to. Falls back to process.env.VERCEL_DEPLOYMENT_ID. */
|
|
39
|
+
deploymentId?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function healthCheck(world: World, endpoint: HealthCheckEndpoint, options?: HealthCheckOptions): Promise<HealthCheckResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Loads workflow run events by iterating through all pages of paginated
|
|
44
|
+
* results. Events are returned in chronological (ascending) order for
|
|
45
|
+
* deterministic workflow replay.
|
|
46
|
+
*
|
|
47
|
+
* @param runId - The workflow run ID.
|
|
48
|
+
* @param afterCursor - If provided, only events after this cursor are
|
|
49
|
+
* returned (incremental load). If omitted, all events are returned.
|
|
50
|
+
* The returned cursor can be passed back in on a subsequent call for
|
|
51
|
+
* incremental loading.
|
|
52
|
+
*/
|
|
53
|
+
export declare function loadWorkflowRunEvents(runId: string, afterCursor?: string): Promise<{
|
|
54
|
+
events: Event[];
|
|
55
|
+
cursor: string | null;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Wraps a request/response handler and adds a health check "mode"
|
|
59
|
+
* based on the presence of a `__health` query parameter.
|
|
60
|
+
*/
|
|
61
|
+
export declare function withHealthCheck(handler: (req: Request) => Promise<Response>, worldSpecVersion?: number): (req: Request) => Promise<Response>;
|
|
62
|
+
/**
|
|
63
|
+
* Queues a message to the specified queue with tracing.
|
|
64
|
+
*/
|
|
65
|
+
export declare function queueMessage(world: World, ...args: Parameters<typeof world.queue>): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Calculates the queue overhead time in milliseconds for a given message.
|
|
68
|
+
*/
|
|
69
|
+
export declare function getQueueOverhead(message: {
|
|
70
|
+
requestedAt?: Date;
|
|
71
|
+
}): {
|
|
72
|
+
[k: string]: number;
|
|
73
|
+
} | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Returns a memoized accessor for the per-run AES-256 encryption key.
|
|
76
|
+
*
|
|
77
|
+
* The first call resolves the key via `world.getEncryptionKeyForRun` (which
|
|
78
|
+
* may do HKDF derivation locally on Vercel, or a network fetch from
|
|
79
|
+
* external contexts) and imports it as a `CryptoKey`; subsequent calls
|
|
80
|
+
* await the same cached promise. If the world doesn't support encryption
|
|
81
|
+
* or the run has no key configured, the cached value is `undefined`.
|
|
82
|
+
*
|
|
83
|
+
* Used by step / workflow handlers to defer the (potentially expensive)
|
|
84
|
+
* key fetch until the first code path that actually needs it — typically
|
|
85
|
+
* input hydration on the success path, or error dehydration on a failure
|
|
86
|
+
* path. Both paths can race-call the accessor without triggering duplicate
|
|
87
|
+
* fetches.
|
|
88
|
+
*
|
|
89
|
+
* Errors thrown by `getEncryptionKeyForRun` propagate to every caller
|
|
90
|
+
* (the cached promise rejects). This is intentional: when encryption is
|
|
91
|
+
* configured, we never want to silently fall back to plaintext
|
|
92
|
+
* serialization. A propagated error in an event-emission path leaves the
|
|
93
|
+
* outer try/catch to log and surface the issue; the queue's redelivery
|
|
94
|
+
* semantics will retry the key fetch on the next attempt.
|
|
95
|
+
*/
|
|
96
|
+
export declare function memoizeEncryptionKey(world: World, runOrId: WorkflowRun | string): () => Promise<CryptoKey | undefined>;
|
|
97
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-invocation accounting of the *non-step* portion of a workflow
|
|
3
|
+
* handler run: deterministic event-log replay, workflow-VM execution
|
|
4
|
+
* between step boundaries, suspension handling, queue round-trips, etc.
|
|
5
|
+
* Inline step bodies (`"use step"` functions invoked via `executeStep`)
|
|
6
|
+
* are intentionally excluded — they are bounded by the platform's
|
|
7
|
+
* function `maxDuration` and the `NO_INLINE_REPLAY_AFTER_MS` early-return
|
|
8
|
+
* guard.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const budget = new ReplayBudget();
|
|
14
|
+
* // …non-step work happens here, accumulates against the budget…
|
|
15
|
+
* budget.pause();
|
|
16
|
+
* try {
|
|
17
|
+
* await executeStep(...); // not charged
|
|
18
|
+
* } finally {
|
|
19
|
+
* budget.resume();
|
|
20
|
+
* }
|
|
21
|
+
* // back to charging
|
|
22
|
+
* if (budget.isExhausted()) { ... }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* Implementation notes:
|
|
26
|
+
*
|
|
27
|
+
* - `pause()` and `resume()` are idempotent: calling `pause()` while
|
|
28
|
+
* already paused (or `resume()` while already resumed) is a no-op.
|
|
29
|
+
* This protects against double-counting in future refactors that nest
|
|
30
|
+
* step execution or take an early-return path between a `pause()` and
|
|
31
|
+
* the matching `resume()`.
|
|
32
|
+
* - `isExhausted()` is checked at loop boundaries by the caller — the
|
|
33
|
+
* budget itself does not arm any timers. This means an in-flight
|
|
34
|
+
* pathological `runWorkflow` call (e.g. a huge event-log replay) can
|
|
35
|
+
* overshoot the budget by up to one iteration's worth of work before
|
|
36
|
+
* the next check fires. In practice the 20s headroom built into
|
|
37
|
+
* `MAX_REPLAY_TIMEOUT_MS` (and the function `maxDuration` ceiling)
|
|
38
|
+
* gives us slack; the old `setTimeout`-based approach also ultimately
|
|
39
|
+
* relied on the platform SIGTERM as the hard backstop.
|
|
40
|
+
*/
|
|
41
|
+
export declare class ReplayBudget {
|
|
42
|
+
private readonly limitMs;
|
|
43
|
+
private elapsedMs;
|
|
44
|
+
private intervalStart;
|
|
45
|
+
constructor(limitMs?: number);
|
|
46
|
+
/**
|
|
47
|
+
* The configured replay-timeout limit, in ms. Useful for log messages.
|
|
48
|
+
*/
|
|
49
|
+
get configuredLimitMs(): number;
|
|
50
|
+
/**
|
|
51
|
+
* Total non-step time accumulated so far, in ms. Includes the
|
|
52
|
+
* currently-active interval if the budget is not paused.
|
|
53
|
+
*/
|
|
54
|
+
elapsed(): number;
|
|
55
|
+
/**
|
|
56
|
+
* Stop counting elapsed time toward the budget. Idempotent — safe to
|
|
57
|
+
* call multiple times in a row; subsequent calls are no-ops until
|
|
58
|
+
* `resume()` reopens an interval.
|
|
59
|
+
*/
|
|
60
|
+
pause(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Resume counting elapsed time toward the budget. Idempotent — safe to
|
|
63
|
+
* call multiple times in a row; subsequent calls re-anchor the
|
|
64
|
+
* interval start to `now()`, which is fine because no time accrues
|
|
65
|
+
* between back-to-back `resume()` calls.
|
|
66
|
+
*/
|
|
67
|
+
resume(): void;
|
|
68
|
+
/**
|
|
69
|
+
* True if the budget has been exhausted (`elapsed() >= limitMs`).
|
|
70
|
+
* Callers should invoke `handleExhausted(...)` afterward and return
|
|
71
|
+
* from the handler.
|
|
72
|
+
*/
|
|
73
|
+
isExhausted(): boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fail the run (or retry, on early attempts) when the replay budget is
|
|
77
|
+
* exhausted. The handling depends on whether the underlying World
|
|
78
|
+
* supports `process.exit(1)` as a queue redelivery signal (see
|
|
79
|
+
* `World.processExitTriggersQueueRedelivery`):
|
|
80
|
+
*
|
|
81
|
+
* - **Managed-platform Worlds** (`world-vercel`): on attempts <=
|
|
82
|
+
* `REPLAY_TIMEOUT_MAX_RETRIES` exit the process so the platform fails
|
|
83
|
+
* the invocation and the queue redelivers; on the next attempt write
|
|
84
|
+
* `run_failed` with `RUN_ERROR_CODES.REPLAY_TIMEOUT` and exit.
|
|
85
|
+
*
|
|
86
|
+
* - **In-process Worlds** (`world-local`, dev servers): calling
|
|
87
|
+
* `process.exit()` would terminate the host (e.g. `pnpm dev`), so
|
|
88
|
+
* instead log a warning, write `run_failed` best-effort, and return.
|
|
89
|
+
* The framework completes the request normally.
|
|
90
|
+
*/
|
|
91
|
+
export declare function handleReplayBudgetExhausted(args: {
|
|
92
|
+
runId: string;
|
|
93
|
+
workflowName: string;
|
|
94
|
+
requestId: string | undefined;
|
|
95
|
+
attempt: number;
|
|
96
|
+
limitMs: number;
|
|
97
|
+
}): Promise<void>;
|
|
98
|
+
//# sourceMappingURL=replay-budget.d.ts.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type Hook } from '../_workflow-world.js';
|
|
2
|
+
import { type CryptoKey } from '../encryption.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get the hook by token to find the associated workflow run,
|
|
5
|
+
* and hydrate the `metadata` property if it was set from within
|
|
6
|
+
* the workflow run.
|
|
7
|
+
*
|
|
8
|
+
* @param token - The unique token identifying the hook
|
|
9
|
+
*/
|
|
10
|
+
export declare function getHookByToken(token: string): Promise<Hook>;
|
|
11
|
+
/**
|
|
12
|
+
* Resumes a workflow run by sending a payload to a hook identified by its token.
|
|
13
|
+
*
|
|
14
|
+
* This function is called externally (e.g., from an API route or server action)
|
|
15
|
+
* to send data to a hook and resume the associated workflow run.
|
|
16
|
+
*
|
|
17
|
+
* @param tokenOrHook - The unique token identifying the hook, or the hook object itself
|
|
18
|
+
* @param payload - The data payload to send to the hook
|
|
19
|
+
* @returns Promise resolving to the hook
|
|
20
|
+
* @throws Error if the hook is not found or if there's an error during the process
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* // In an API route
|
|
26
|
+
* import { resumeHook } from '@workflow/core/runtime';
|
|
27
|
+
*
|
|
28
|
+
* export async function POST(request: Request) {
|
|
29
|
+
* const { token, data } = await request.json();
|
|
30
|
+
*
|
|
31
|
+
* try {
|
|
32
|
+
* const hook = await resumeHook(token, data);
|
|
33
|
+
* return Response.json({ runId: hook.runId });
|
|
34
|
+
* } catch (error) {
|
|
35
|
+
* return new Response('Hook not found', { status: 404 });
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function resumeHook<T = any>(tokenOrHook: string | Hook, payload: T, encryptionKeyOverride?: CryptoKey): Promise<Hook>;
|
|
41
|
+
/**
|
|
42
|
+
* Resumes a webhook by sending a {@link https://developer.mozilla.org/en-US/docs/Web/API/Request | Request}
|
|
43
|
+
* object to a hook identified by its token.
|
|
44
|
+
*
|
|
45
|
+
* This function is called externally (e.g., from an API route or server action)
|
|
46
|
+
* to send a request to a webhook and resume the associated workflow run.
|
|
47
|
+
*
|
|
48
|
+
* @param token - The unique token identifying the hook
|
|
49
|
+
* @param request - The request to send to the hook
|
|
50
|
+
* @returns Promise resolving to the response
|
|
51
|
+
* @throws Error if the hook is not found or if there's an error during the process
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
*
|
|
55
|
+
* ```ts
|
|
56
|
+
* // In an API route
|
|
57
|
+
* import { resumeWebhook } from '@workflow/core/runtime';
|
|
58
|
+
*
|
|
59
|
+
* export async function POST(request: Request) {
|
|
60
|
+
* const url = new URL(request.url);
|
|
61
|
+
* const token = url.searchParams.get('token');
|
|
62
|
+
*
|
|
63
|
+
* if (!token) {
|
|
64
|
+
* return new Response('Missing token', { status: 400 });
|
|
65
|
+
* }
|
|
66
|
+
*
|
|
67
|
+
* try {
|
|
68
|
+
* const response = await resumeWebhook(token, request);
|
|
69
|
+
* return response;
|
|
70
|
+
* } catch (error) {
|
|
71
|
+
* return new Response('Webhook not found', { status: 404 });
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function resumeWebhook(token: string, request: Request): Promise<Response>;
|
|
77
|
+
//# sourceMappingURL=resume-hook.d.ts.map
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from '../_workflow-serde.js';
|
|
2
|
+
import { type WorkflowRunStatus } from '../_workflow-world.js';
|
|
3
|
+
import { type StopSleepOptions, type StopSleepResult } from './runs.js';
|
|
4
|
+
/**
|
|
5
|
+
* A `ReadableStream` extended with workflow-specific helpers.
|
|
6
|
+
*/
|
|
7
|
+
export type WorkflowReadableStream<R = any> = ReadableStream<R> & {
|
|
8
|
+
/**
|
|
9
|
+
* Returns the tail index (index of the last known chunk, 0-based) of the
|
|
10
|
+
* underlying workflow stream. Useful for resolving a negative `startIndex`
|
|
11
|
+
* into an absolute position — for example, when building reconnection
|
|
12
|
+
* endpoints that need to inform the client where the stream starts.
|
|
13
|
+
*
|
|
14
|
+
* Returns `-1` when no chunks have been written yet.
|
|
15
|
+
*/
|
|
16
|
+
getTailIndex(): Promise<number>;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Options for configuring a workflow's readable stream.
|
|
20
|
+
*/
|
|
21
|
+
export interface WorkflowReadableStreamOptions {
|
|
22
|
+
/**
|
|
23
|
+
* An optional namespace to distinguish between multiple streams associated
|
|
24
|
+
* with the same workflow run.
|
|
25
|
+
*/
|
|
26
|
+
namespace?: string;
|
|
27
|
+
/**
|
|
28
|
+
* The index number of the starting chunk to begin reading the stream from.
|
|
29
|
+
* Negative values start from the end (e.g. -3 reads the last 3 chunks).
|
|
30
|
+
*/
|
|
31
|
+
startIndex?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Any asynchronous operations that need to be performed before the execution
|
|
34
|
+
* environment is paused / terminated
|
|
35
|
+
* (i.e. using [`waitUntil()`](https://developer.mozilla.org/docs/Web/API/ExtendableEvent/waitUntil) or similar).
|
|
36
|
+
*/
|
|
37
|
+
ops?: Promise<any>[];
|
|
38
|
+
/**
|
|
39
|
+
* The global object to use for hydrating types from the global scope.
|
|
40
|
+
*
|
|
41
|
+
* Defaults to {@link [`globalThis`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/globalThis)}.
|
|
42
|
+
*/
|
|
43
|
+
global?: Record<string, any>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A handler class for a workflow run.
|
|
47
|
+
*/
|
|
48
|
+
export declare class Run<TResult> {
|
|
49
|
+
#private;
|
|
50
|
+
static [WORKFLOW_SERIALIZE](instance: Run<unknown>): {
|
|
51
|
+
runId: string;
|
|
52
|
+
resilientStart: boolean;
|
|
53
|
+
};
|
|
54
|
+
static [WORKFLOW_DESERIALIZE](data: {
|
|
55
|
+
runId: string;
|
|
56
|
+
resilientStart?: boolean;
|
|
57
|
+
}): Run<unknown>;
|
|
58
|
+
/**
|
|
59
|
+
* The ID of the workflow run.
|
|
60
|
+
*/
|
|
61
|
+
runId: string;
|
|
62
|
+
constructor(runId: string, opts?: {
|
|
63
|
+
resilientStart?: boolean;
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Interrupts pending `sleep()` calls, resuming the workflow early.
|
|
67
|
+
*
|
|
68
|
+
* @param options - Optional settings to target specific sleep calls by correlation ID.
|
|
69
|
+
* If not provided, all pending sleep calls will be interrupted.
|
|
70
|
+
* @returns A {@link StopSleepResult} object containing the number of sleep calls that were interrupted.
|
|
71
|
+
*/
|
|
72
|
+
wakeUp(options?: StopSleepOptions): Promise<StopSleepResult>;
|
|
73
|
+
/**
|
|
74
|
+
* Cancels the workflow run.
|
|
75
|
+
*/
|
|
76
|
+
cancel(): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Whether the workflow run exists.
|
|
79
|
+
*/
|
|
80
|
+
get exists(): Promise<boolean>;
|
|
81
|
+
/**
|
|
82
|
+
* The status of the workflow run.
|
|
83
|
+
*/
|
|
84
|
+
get status(): Promise<WorkflowRunStatus>;
|
|
85
|
+
/**
|
|
86
|
+
* The return value of the workflow run.
|
|
87
|
+
* Polls the workflow return value until it is completed.
|
|
88
|
+
*/
|
|
89
|
+
get returnValue(): Promise<TResult>;
|
|
90
|
+
/**
|
|
91
|
+
* The name of the workflow.
|
|
92
|
+
*/
|
|
93
|
+
get workflowName(): Promise<string>;
|
|
94
|
+
/**
|
|
95
|
+
* The timestamp when the workflow run was created.
|
|
96
|
+
*/
|
|
97
|
+
get createdAt(): Promise<Date>;
|
|
98
|
+
/**
|
|
99
|
+
* The timestamp when the workflow run started execution.
|
|
100
|
+
* Returns undefined if the workflow has not started yet.
|
|
101
|
+
*/
|
|
102
|
+
get startedAt(): Promise<Date | undefined>;
|
|
103
|
+
/**
|
|
104
|
+
* The timestamp when the workflow run completed.
|
|
105
|
+
* Returns undefined if the workflow has not completed yet.
|
|
106
|
+
*/
|
|
107
|
+
get completedAt(): Promise<Date | undefined>;
|
|
108
|
+
/**
|
|
109
|
+
* The readable stream of the workflow run.
|
|
110
|
+
*/
|
|
111
|
+
get readable(): WorkflowReadableStream;
|
|
112
|
+
/**
|
|
113
|
+
* Retrieves the workflow run's default readable stream, which reads chunks
|
|
114
|
+
* written to the corresponding writable stream {@link getWritable}.
|
|
115
|
+
*
|
|
116
|
+
* The returned stream has an additional {@link WorkflowReadableStream.getTailIndex | getTailIndex()}
|
|
117
|
+
* helper that returns the index of the last known chunk. This is useful when
|
|
118
|
+
* building reconnection endpoints that need to inform clients where the
|
|
119
|
+
* stream starts.
|
|
120
|
+
*
|
|
121
|
+
* @param options - The options for the readable stream.
|
|
122
|
+
* @returns A `WorkflowReadableStream` for the workflow run.
|
|
123
|
+
*/
|
|
124
|
+
getReadable<R = any>(options?: WorkflowReadableStreamOptions): WorkflowReadableStream<R>;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Retrieves a `Run` object for a given run ID.
|
|
128
|
+
*
|
|
129
|
+
* @param runId - The workflow run ID obtained from {@link start}.
|
|
130
|
+
* @returns A `Run` object.
|
|
131
|
+
* @throws WorkflowRunNotFoundError if the run ID is not found.
|
|
132
|
+
*/
|
|
133
|
+
export declare function getRun<TResult>(runId: string): Run<TResult>;
|
|
134
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type World } from '../_workflow-world.js';
|
|
2
|
+
export interface RecreateRunOptions {
|
|
3
|
+
deploymentId?: string;
|
|
4
|
+
specVersion?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface StopSleepResult {
|
|
7
|
+
/** Number of pending sleeps that were stopped */
|
|
8
|
+
stoppedCount: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ReadStreamOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The index to start reading from. Defaults to 0.
|
|
13
|
+
* Negative values start from the end (e.g. -3 reads the last 3 chunks).
|
|
14
|
+
*/
|
|
15
|
+
startIndex?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface StopSleepOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Optional list of specific correlation IDs to target.
|
|
20
|
+
* If provided, only these sleep calls will be interrupted.
|
|
21
|
+
* If not provided, all pending sleep calls will be interrupted.
|
|
22
|
+
*/
|
|
23
|
+
correlationIds?: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Start a new workflow run based on an existing run.
|
|
27
|
+
*/
|
|
28
|
+
export declare function recreateRunFromExisting(world: World, runId: string, options?: RecreateRunOptions): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Cancel a workflow run.
|
|
31
|
+
*/
|
|
32
|
+
export declare function cancelRun(world: World, runId: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Re-enqueue a workflow run.
|
|
35
|
+
*/
|
|
36
|
+
export declare function reenqueueRun(world: World, runId: string): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Wake up a workflow run by interrupting pending sleep() calls.
|
|
39
|
+
*/
|
|
40
|
+
export declare function wakeUpRun(world: World, runId: string, options?: StopSleepOptions): Promise<StopSleepResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Read from a stream by stream ID.
|
|
43
|
+
* Returns a ReadableStream of Uint8Array chunks.
|
|
44
|
+
*/
|
|
45
|
+
export declare function readStream(world: World, runId: string, streamId: string, options?: ReadStreamOptions): Promise<ReadableStream<Uint8Array>>;
|
|
46
|
+
/**
|
|
47
|
+
* List all stream IDs for a workflow run.
|
|
48
|
+
*/
|
|
49
|
+
export declare function listStreams(world: World, runId: string): Promise<string[]>;
|
|
50
|
+
//# sourceMappingURL=runs.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { World } from '../_workflow-world.js';
|
|
2
|
+
import { Run } from './run.js';
|
|
3
|
+
export interface StartOptionsBase {
|
|
4
|
+
/**
|
|
5
|
+
* The world to use for the workflow run creation,
|
|
6
|
+
* by default the world is inferred from the environment variables.
|
|
7
|
+
*/
|
|
8
|
+
world?: World;
|
|
9
|
+
/**
|
|
10
|
+
* The spec version to use for the workflow run. Defaults to the latest version.
|
|
11
|
+
*/
|
|
12
|
+
specVersion?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface StartOptionsWithDeploymentId extends StartOptionsBase {
|
|
15
|
+
/**
|
|
16
|
+
* The deployment ID to use for the workflow run.
|
|
17
|
+
*
|
|
18
|
+
* By default, this is automatically inferred from environment variables
|
|
19
|
+
* when deploying to Vercel.
|
|
20
|
+
*
|
|
21
|
+
* Set to `'latest'` to automatically resolve the most recent deployment
|
|
22
|
+
* for the current environment (same production target or git branch).
|
|
23
|
+
* This is currently a Vercel-specific feature.
|
|
24
|
+
*
|
|
25
|
+
* **Note:** When `deploymentId` is provided, the argument and return types become `unknown`
|
|
26
|
+
* since there is no guarantee the types will be consistent across deployments.
|
|
27
|
+
*/
|
|
28
|
+
deploymentId: 'latest' | (string & {});
|
|
29
|
+
}
|
|
30
|
+
export interface StartOptionsWithoutDeploymentId extends StartOptionsBase {
|
|
31
|
+
deploymentId?: undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Options for starting a workflow run.
|
|
35
|
+
*/
|
|
36
|
+
export type StartOptions = StartOptionsWithDeploymentId | StartOptionsWithoutDeploymentId;
|
|
37
|
+
/**
|
|
38
|
+
* Represents an imported workflow function.
|
|
39
|
+
*/
|
|
40
|
+
export type WorkflowFunction<TArgs extends unknown[], TResult> = (...args: TArgs) => Promise<TResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Represents the generated metadata of a workflow function.
|
|
43
|
+
*/
|
|
44
|
+
export type WorkflowMetadata = {
|
|
45
|
+
workflowId: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Starts a workflow run.
|
|
49
|
+
*
|
|
50
|
+
* @param workflow - The imported workflow function to start.
|
|
51
|
+
* @param args - The arguments to pass to the workflow (optional).
|
|
52
|
+
* @param options - The options for the workflow run (optional).
|
|
53
|
+
* @returns The unique run ID for the newly started workflow invocation.
|
|
54
|
+
*/
|
|
55
|
+
export declare function start<TArgs extends unknown[], TResult>(workflow: WorkflowFunction<TArgs, TResult> | WorkflowMetadata, args: unknown[], options: StartOptionsWithDeploymentId): Promise<Run<unknown>>;
|
|
56
|
+
export declare function start<TResult>(workflow: WorkflowFunction<[], TResult> | WorkflowMetadata, options: StartOptionsWithDeploymentId): Promise<Run<unknown>>;
|
|
57
|
+
export declare function start<TArgs extends unknown[], TResult>(workflow: WorkflowFunction<TArgs, TResult> | WorkflowMetadata, args: TArgs, options?: StartOptionsWithoutDeploymentId): Promise<Run<TResult>>;
|
|
58
|
+
export declare function start<TResult>(workflow: WorkflowFunction<[], TResult> | WorkflowMetadata, options?: StartOptionsWithoutDeploymentId): Promise<Run<TResult>>;
|
|
59
|
+
//# sourceMappingURL=start.d.ts.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { World } from '../_workflow-world.js';
|
|
2
|
+
import type { CryptoKey } from '../encryption.js';
|
|
3
|
+
export interface StepExecutorParams {
|
|
4
|
+
world: World;
|
|
5
|
+
workflowRunId: string;
|
|
6
|
+
workflowName: string;
|
|
7
|
+
workflowStartedAt: number;
|
|
8
|
+
stepId: string;
|
|
9
|
+
stepName: string;
|
|
10
|
+
encryptionKey?: CryptoKey;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of a step execution attempt. The caller decides what to do
|
|
14
|
+
* based on the result type (e.g., queue workflow continuation, replay inline, etc.).
|
|
15
|
+
*/
|
|
16
|
+
export type StepExecutionResult = {
|
|
17
|
+
type: 'completed';
|
|
18
|
+
hasPendingOps?: boolean;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'failed';
|
|
21
|
+
} | {
|
|
22
|
+
type: 'retry';
|
|
23
|
+
timeoutSeconds: number;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'skipped';
|
|
26
|
+
} | {
|
|
27
|
+
type: 'gone';
|
|
28
|
+
} | {
|
|
29
|
+
type: 'throttled';
|
|
30
|
+
timeoutSeconds: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Executes a single step: creates step_started event, hydrates input,
|
|
34
|
+
* runs the step function, creates step_completed/step_failed/step_retrying events.
|
|
35
|
+
*
|
|
36
|
+
* Does NOT queue workflow continuation messages — the caller decides what to do next.
|
|
37
|
+
* Used by both the V1 step handler and the V2 combined handler.
|
|
38
|
+
*/
|
|
39
|
+
export declare function executeStep(params: StepExecutorParams): Promise<StepExecutionResult>;
|
|
40
|
+
//# sourceMappingURL=step-executor.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Span } from '#compiled/@opentelemetry/api/index.js';
|
|
2
|
+
import { type WorkflowRun, type World } from '../_workflow-world.js';
|
|
3
|
+
import type { StepInvocationQueueItem, WorkflowSuspension } from '../global.js';
|
|
4
|
+
export interface SuspensionHandlerParams {
|
|
5
|
+
suspension: WorkflowSuspension;
|
|
6
|
+
world: World;
|
|
7
|
+
run: WorkflowRun;
|
|
8
|
+
span?: Span;
|
|
9
|
+
requestId?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Result of handling a suspension. Returns pending step items so the caller
|
|
13
|
+
* can decide which to execute inline vs queue to background.
|
|
14
|
+
*/
|
|
15
|
+
export interface SuspensionHandlerResult {
|
|
16
|
+
/** Pending step items with events created but NOT queued */
|
|
17
|
+
pendingSteps: StepInvocationQueueItem[];
|
|
18
|
+
/**
|
|
19
|
+
* Correlation IDs for which this suspension call actually wrote the
|
|
20
|
+
* step_created event (as opposed to catching EntityConflictError because
|
|
21
|
+
* a concurrent handler wrote it first). Only the handler that wrote the
|
|
22
|
+
* step_created event should queue / inline-execute the step — this
|
|
23
|
+
* guarantees a single owner per step, even when multiple handlers race
|
|
24
|
+
* into the same batch boundary.
|
|
25
|
+
*/
|
|
26
|
+
createdStepCorrelationIds: Set<string>;
|
|
27
|
+
/** Timeout from waits, if any */
|
|
28
|
+
timeoutSeconds?: number;
|
|
29
|
+
/** Whether a hook conflict was detected (should re-invoke immediately) */
|
|
30
|
+
hasHookConflict: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
|
|
34
|
+
* Creates events for all operations but does NOT queue step messages — returns the pending
|
|
35
|
+
* steps so the caller can decide which to execute inline vs queue to background.
|
|
36
|
+
*
|
|
37
|
+
* Processing order:
|
|
38
|
+
* 1. Hooks are processed first to prevent race conditions with webhook receivers
|
|
39
|
+
* 2. Step events and wait events are created in parallel
|
|
40
|
+
*/
|
|
41
|
+
export declare function handleSuspension({ suspension, world, run, span, requestId, }: SuspensionHandlerParams): Promise<SuspensionHandlerResult>;
|
|
42
|
+
//# sourceMappingURL=suspension-handler.d.ts.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-only side-effect module that ensures `world.ts` is loaded so its
|
|
3
|
+
* module-load side effect — `globalThis[GetWorldFnKey] ??= getWorld` —
|
|
4
|
+
* fires in host bundles.
|
|
5
|
+
*
|
|
6
|
+
* # Why this exists
|
|
7
|
+
*
|
|
8
|
+
* `getWorldLazy()` in `./get-world-lazy.ts` checks the globalThis cache
|
|
9
|
+
* (populated by `world.ts`'s module-load side effect) before falling back
|
|
10
|
+
* to a runtime-built dynamic `import('./world.js')`. When a server route
|
|
11
|
+
* only consumes a single helper that goes through `getWorldLazy` — most
|
|
12
|
+
* commonly `start` from `workflow/api` — webpack/turbopack tree-shake the
|
|
13
|
+
* named import `{ getWorld } from './runtime/world.js'` out of
|
|
14
|
+
* `runtime.ts`, taking `world.ts`'s module evaluation with it. The
|
|
15
|
+
* globalThis registration never fires.
|
|
16
|
+
*
|
|
17
|
+
* `getWorldLazy` then falls through to its dynamic-import fallback, which
|
|
18
|
+
* itself fails: webpack inlines `get-world-lazy.js` into the bundled route
|
|
19
|
+
* file, so the relative specifier `./world.js` resolves against
|
|
20
|
+
* `/var/task/<app>/.next/server/app/<...>/route.js` — where no sibling
|
|
21
|
+
* `world.js` exists — and Node throws `MODULE_NOT_FOUND`. The symptom is a
|
|
22
|
+
* cold-start regression: the very first user request that goes through
|
|
23
|
+
* `start()` fails until some other code path (typically the queue-driven
|
|
24
|
+
* `/.well-known/workflow/v1/flow` route, which uses `getWorld` directly
|
|
25
|
+
* via `workflowEntrypoint`) has loaded `world.ts` and populated the
|
|
26
|
+
* cache.
|
|
27
|
+
*
|
|
28
|
+
* Importing this module for its side effect — exactly once, from the
|
|
29
|
+
* host-side `workflow/api` (`packages/workflow/src/api.ts`) — guarantees
|
|
30
|
+
* `world.ts` enters the bundle, the global is registered at module load,
|
|
31
|
+
* and `getWorldLazy()` short-circuits to the registered function on the
|
|
32
|
+
* first call.
|
|
33
|
+
*
|
|
34
|
+
* # Why a separate module instead of importing `./world.js` directly
|
|
35
|
+
*
|
|
36
|
+
* `world.ts` is internal to `@workflow/core` and not part of the public
|
|
37
|
+
* exports surface. Adding a dedicated public init entry (this file)
|
|
38
|
+
* keeps the side-effect intent obvious to anyone reading
|
|
39
|
+
* `packages/workflow/src/api.ts`, and lets the `workflow` export
|
|
40
|
+
* condition route to a stub for VM/step bundles (see below).
|
|
41
|
+
*
|
|
42
|
+
* # Why this doesn't break VM/step bundles
|
|
43
|
+
*
|
|
44
|
+
* The `@workflow/core/runtime/world-init` export resolves via the
|
|
45
|
+
* `workflow` condition to `./dist/workflow/world-init-stub.js`, an empty
|
|
46
|
+
* module. Esbuild runs the workflow VM and step bundlers with the
|
|
47
|
+
* `workflow` condition active, so they pick up the stub and never reach
|
|
48
|
+
* `world.ts`. Host bundlers (webpack, turbopack, Node.js) use the
|
|
49
|
+
* `default` (or `node`) condition and pick up this file, loading
|
|
50
|
+
* `world.ts` as intended. The split keeps `@workflow/world-vercel`,
|
|
51
|
+
* `@workflow/world-local`, `cbor-x`, and other server-only deps out of
|
|
52
|
+
* the workflow sandbox bundle.
|
|
53
|
+
*
|
|
54
|
+
* # Why we keep the `getWorldLazy` dynamic-import fallback
|
|
55
|
+
*
|
|
56
|
+
* The fallback remains in `./get-world-lazy.ts` as a defense-in-depth for
|
|
57
|
+
* environments we haven't accounted for (CJS test runners, scripts that
|
|
58
|
+
* import `start` without going through `workflow/api`, future bundlers
|
|
59
|
+
* with stricter tree-shaking). With this init module in place, the
|
|
60
|
+
* fallback should never fire in normal use — but if it does, the
|
|
61
|
+
* dynamic-import branch still resolves correctly when `world.js` is
|
|
62
|
+
* physically adjacent on disk (e.g., direct Node.js execution of
|
|
63
|
+
* unbundled source).
|
|
64
|
+
*
|
|
65
|
+
* # Maintenance notes
|
|
66
|
+
*
|
|
67
|
+
* If you add another `getWorldLazy()` consumer that's reachable from a
|
|
68
|
+
* host route without going through `workflow/api` (e.g., a new helper in
|
|
69
|
+
* `workflow/runtime`), make sure that entry also imports this module —
|
|
70
|
+
* or that it transitively reaches `world.ts` via a non-tree-shakeable
|
|
71
|
+
* path. Adding a regression test in `world-init.test.ts` is preferred to
|
|
72
|
+
* relying on careful manual tracing.
|
|
73
|
+
*/
|
|
74
|
+
import './world.js';
|
|
75
|
+
//# sourceMappingURL=world-init.d.ts.map
|