@lostgradient/weft 0.13.0 → 0.14.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/README.md +1 -1
- package/dist/cli/help-text.d.ts +3 -3
- package/dist/cli/help-text.js +4 -4
- package/dist/cli/operation-catalog-snapshot.d.ts +1 -1
- package/dist/cli/schedule.js +1 -3
- package/dist/cli/serve-registrations.d.ts +3 -3
- package/dist/cli/serve-registrations.js +2 -2
- package/dist/cli/shutdown.d.ts +11 -0
- package/dist/cli/shutdown.js +25 -0
- package/dist/cli/validate.d.ts +1 -1
- package/dist/cli/version-check.d.ts +1 -1
- package/dist/cli/version-check.js +1 -1
- package/dist/cli-main.js +10 -29
- package/dist/client/http-client-storage.js +7 -35
- package/dist/client/http-request.d.ts +8 -9
- package/dist/client/http-request.js +3 -25
- package/dist/core/context/parallel-operations.d.ts +0 -2
- package/dist/core/context/parallel-operations.js +0 -7
- package/dist/core/engine/callback-checkpoint-persistence.d.ts +2 -0
- package/dist/core/engine/callback-checkpoint-persistence.js +6 -3
- package/dist/core/engine/callback-creators.js +4 -22
- package/dist/core/engine/checkpoint-io.d.ts +1 -1
- package/dist/core/engine/operations-coordination.js +1 -1
- package/dist/core/engine/parallel-dispatch.d.ts +1 -1
- package/dist/core/engine/parallel-dispatch.js +1 -1
- package/dist/core/engine/review-list-entries.d.ts +1 -1
- package/dist/core/engine/review-list-entries.js +6 -30
- package/dist/core/engine/timeline-coordinator-detail.d.ts +1 -1
- package/dist/core/review/index.d.ts +87 -0
- package/dist/core/review/index.js +29 -0
- package/dist/diagnostics/validate.d.ts +9 -30
- package/dist/diagnostics/validate.js +83 -21
- package/dist/diagnostics/version-check.d.ts +2 -2
- package/dist/http.js +2 -2
- package/dist/server/openapi-error-responses.js +0 -14
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/raise-fault.d.ts +2 -1
- package/dist/server/operation-catalog/types.d.ts +2 -1
- package/dist/server/operation-fault.d.ts +1 -4
- package/dist/server/operation-fault.js +1 -1
- package/dist/server/operation-registry.d.ts +1 -1
- package/dist/server/operations/list-reviews.js +2 -19
- package/dist/server/operations/recover-all.js +1 -10
- package/dist/server/operations/single-workflow-control-operation.d.ts +2 -1
- package/dist/storage/bounded-ndjson-response.d.ts +5 -0
- package/dist/storage/bounded-ndjson-response.js +33 -0
- package/dist/storage/http.js +5 -37
- package/dist/storage/neon.d.ts +3 -16
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/cli/help-text.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export declare const HELP_TEXT = "\nweft - Bun-native durable execution engine\n\nUsage: weft [command] [options]\n\nCommands:\n serve Start the Weft server (default)\n doctor Run diagnostics on the Weft database\n conformance Run RemoteWorker protocol conformance checks\n schedule Manage recurring schedules\n timeline Inspect workflow timeline and replay history\n version:check Check workflow version compatibility\n validate Lint workflow
|
|
1
|
+
export declare const HELP_TEXT = "\nweft - Bun-native durable execution engine\n\nUsage: weft [command] [options]\n\nCommands:\n serve Start the Weft server (default)\n doctor Run diagnostics on the Weft database\n conformance Run RemoteWorker protocol conformance checks\n schedule Manage recurring schedules\n timeline Inspect workflow timeline and replay history\n version:check Check workflow version compatibility\n validate Lint workflow definitions for design-time anti-patterns\n codegen Generate TypeScript declarations from a registry snapshot\n api Inspect and invoke catalog operations on a running server\n server Inspect a running server's health and operation surface\n workflow List, inspect, start, signal, and cancel workflows on a server\n tail Stream a workflow's events as Server-Sent Events\n completions Generate or install shell completion scripts\n version Print the installed Weft version\n\nVersion (leading token only; a subcommand owns its own option line):\n weft version | weft --version | weft -v Print the installed Weft version\n\nServe Options:\n -p, --port <port> Server port (default: 7233)\n -d, --database <path> Database file path (default: ./weft.db)\n -s, --storage <backend> Storage backend: sqlite, lmdb, memory (default: sqlite)\n -w, --workflows <path> Path to workflow module to register on startup\n -h, --help Show this help message\n";
|
|
2
2
|
export declare const API_HELP_TEXT = "\nweft api - Inspect and invoke catalog operations on a running server\n\nUsage:\n weft api --list [options]\n weft api --describe <operation-name> [options]\n weft api <operation-name> [--input <json> | --input-file <path|->] [options]\n\nOptions:\n --server <url> Server URL (default: WEFT_ADDR, profile, run lockfile, or localhost)\n --token <token> Bearer token (default: WEFT_TOKEN)\n --profile <name> Profile from ~/.weft/config (default: WEFT_PROFILE or default_profile)\n --input <json> JSON object input for the operation\n --input-file <path> Read JSON object input from a file, or '-' for stdin\n --list List catalog operations\n --describe <name> Print one operation's schema and metadata\n --yes Confirm destructive operations without prompting\n -j, --json Emit machine-readable JSON output\n -h, --help Show this help message\n\nExit codes:\n 0 Success\n 1 Operation failed or destructive operation was not confirmed\n 2 Connection error\n 3 Usage or input validation error\n";
|
|
3
3
|
export declare const CONFORMANCE_HELP_TEXT = "\nweft conformance - Run RemoteWorker protocol conformance checks\n\nUsage: weft conformance [options] -- <worker-command> [args...]\n\nThe worker command receives:\n WEFT_WORKER_URL\n WEFT_WORKER_QUEUE\n WEFT_WORKER_ACTIVITIES\n WEFT_WORKER_PROTOCOL_VERSION\n\nOptions:\n --timeout <ms> Per-check timeout in milliseconds (default: 15000)\n -j, --json Output results as JSON\n -h, --help Show this help message\n";
|
|
4
4
|
export declare const DOCTOR_HELP_TEXT = "\nweft doctor - Run diagnostics on the Weft database\n\nUsage: weft doctor [options]\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n -j, --json Output results as JSON\n -h, --help Show this help message\n";
|
|
5
5
|
export declare const VERSION_CHECK_HELP_TEXT = "\nweft version:check - Check workflow version compatibility\n\nUsage: weft version:check [options]\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n -w, --workflows <path> Path to workflows module\n -j, --json Output results as JSON\n -h, --help Show this help message\n";
|
|
6
6
|
export declare const TIMELINE_HELP_TEXT = "\nweft timeline - Inspect workflow timeline and replay history\n\nUsage:\n weft timeline <workflowId> [options]\n weft timeline <workflowId> --diff <fromStep> <toStep> [options]\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n --step <step> Show replay details for one checkpoint step\n --diff Diff two checkpoint steps (requires two positional step numbers)\n -h, --help Show this help message\n";
|
|
7
|
-
export declare const SCHEDULE_HELP_TEXT = "\nweft schedule - Manage recurring schedules\n\nUsage:\n weft schedule list [options]\n weft schedule create <workflowType> <cronExpression> [options]\n weft schedule create <workflowType> --every <duration> [options]\n weft schedule pause <scheduleId> [options]\n weft schedule resume <scheduleId> [options]\n weft schedule cancel <scheduleId> [options]\n\nProvide a cron expression positional OR an --every interval (e.g. \"30s\", \"1h\"),\nbut not both. Interval schedules fire one period after creation, then every\nperiod after that.\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n -s, --storage <backend> Storage backend: sqlite, lmdb (default: sqlite)\n -w, --workflows <path> Path to workflow
|
|
8
|
-
export declare const VALIDATE_HELP_TEXT = "\nweft validate - Lint workflow
|
|
7
|
+
export declare const SCHEDULE_HELP_TEXT = "\nweft schedule - Manage recurring schedules\n\nUsage:\n weft schedule list [options]\n weft schedule create <workflowType> <cronExpression> [options]\n weft schedule create <workflowType> --every <duration> [options]\n weft schedule pause <scheduleId> [options]\n weft schedule resume <scheduleId> [options]\n weft schedule cancel <scheduleId> [options]\n\nProvide a cron expression positional OR an --every interval (e.g. \"30s\", \"1h\"),\nbut not both. Interval schedules fire one period after creation, then every\nperiod after that.\n\nOptions:\n -d, --database <path> Database file path (default: ./weft.db)\n -s, --storage <backend> Storage backend: sqlite, lmdb (default: sqlite)\n -w, --workflows <path> Path to workflow definitions module (required for create)\n --every <duration> Interval cadence for create (e.g. 30s, 5m, 1h); mutually exclusive with the cron positional\n --input <json> JSON input payload for create (default: null)\n --id <id> Custom schedule id for create\n --overlap <policy> Overlap policy: skip, queue, cancel-running, allow\n --backfill Run missed ticks on recovery\n --jitter <duration> Deterministic dispatch jitter for create (e.g. 30s, 5m)\n -j, --json Output results as JSON\n -h, --help Show this help message\n";
|
|
8
|
+
export declare const VALIDATE_HELP_TEXT = "\nweft validate - Lint workflow definitions for design-time anti-patterns\n\nUsage: weft validate <entry.ts>... [options]\n\nArguments:\n <entry.ts>... One or more TypeScript modules or glob patterns that\n resolve to workflow definitions and/or activity\n definitions.\n\nOptions:\n -j, --json Output results as JSON\n -h, --help Show this help message\n\nExit codes:\n 0 No errors (warnings may be present)\n 1 One or more errors detected\n 2 Entry file could not be loaded (takes precedence over validation errors)\n\nJSON output:\n { entries, valid, hasLoadErrors, hasValidationErrors }\n\nChecks performed:\n unbounded-retry Activity retry.maxAttempts is Infinity\n stateful-without-compensator Non-idempotent activity has no compensate fn\n";
|
|
9
9
|
export declare const SERVER_HELP_TEXT = "\nweft server - Inspect a running server's health and operation surface\n\nUsage:\n weft server health [options]\n weft server info [options]\n\nOptions:\n --server <url> Server URL (default: WEFT_ADDR, profile, run lockfile, or localhost)\n --token <token> Bearer token (default: WEFT_TOKEN)\n --profile <name> Profile from ~/.weft/config\n --wait (health) Poll until the server is reachable\n --wait-timeout <ms> (health) Maximum time to wait, in milliseconds (default: 30000)\n -j, --json Emit machine-readable JSON output\n -q, --quiet Suppress success/error text (use the exit code)\n -h, --help Show this help message\n\nExit codes:\n 0 Healthy\n 1 Unreachable / unhealthy\n 2 Connection error\n";
|
|
10
10
|
export declare const WORKFLOW_HELP_TEXT = "\nweft workflow - List, inspect, start, signal, and cancel workflows on a server\n\nUsage:\n weft workflow ls [--type <type>] [--status <status>] [--limit <n>] [options]\n weft workflow get <workflow-id> [options]\n weft workflow events <workflow-id> [options]\n weft workflow start <workflow-type> [--input <json> | --input-file <path|->] [--id <id>] [options]\n weft workflow cancel <workflow-id> [--yes] [--dry-run] [options]\n weft workflow signal <workflow-id> <signal-name> [--input <json> | --input-file <path|->] [options]\n\nOptions:\n --server <url> Server URL (default: WEFT_ADDR, profile, run lockfile, or localhost)\n --token <token> Bearer token (default: WEFT_TOKEN)\n --profile <name> Profile from ~/.weft/config\n --type <type> (ls) Filter by workflow type\n --status <status> (ls) Filter by workflow status\n --limit <n> (ls) Maximum number of rows\n --input <json> (start/signal) JSON input payload\n --input-file <path> (start/signal) Read JSON input from a file, or '-' for stdin\n --id <id> (start) Explicit workflow id\n -y, --yes (cancel) Confirm without prompting\n --dry-run (cancel) Print affected count without cancelling\n -j, --json Emit machine-readable output (NDJSON for lists)\n -q, --quiet Print ids only / suppress success text\n -h, --help Show this help message\n\nExit codes:\n 0 Success\n 1 Operation failed or destructive operation was not confirmed\n 2 Connection error\n 3 Usage or input error\n 4 Operation unavailable on this server (version skew)\n";
|
|
11
11
|
export declare const TAIL_HELP_TEXT = "\nweft tail - Stream a workflow's events as Server-Sent Events\n\nUsage:\n weft tail <workflow-id> [options]\n\nOptions:\n --server <url> Server URL (default: WEFT_ADDR, profile, run lockfile, or localhost)\n --token <token> Bearer token (default: WEFT_TOKEN)\n --profile <name> Profile from ~/.weft/config\n -j, --json Emit one JSON object per line (NDJSON)\n -q, --quiet Do not echo events to stdout\n -h, --help Show this help message\n\nPress Ctrl-C to stop tailing; the stream ends cleanly with exit code 0.\n";
|
package/dist/cli/help-text.js
CHANGED
|
@@ -10,7 +10,7 @@ Commands:
|
|
|
10
10
|
schedule Manage recurring schedules
|
|
11
11
|
timeline Inspect workflow timeline and replay history
|
|
12
12
|
version:check Check workflow version compatibility
|
|
13
|
-
validate Lint workflow
|
|
13
|
+
validate Lint workflow definitions for design-time anti-patterns
|
|
14
14
|
codegen Generate TypeScript declarations from a registry snapshot
|
|
15
15
|
api Inspect and invoke catalog operations on a running server
|
|
16
16
|
server Inspect a running server's health and operation surface
|
|
@@ -117,7 +117,7 @@ period after that.
|
|
|
117
117
|
Options:
|
|
118
118
|
-d, --database <path> Database file path (default: ./weft.db)
|
|
119
119
|
-s, --storage <backend> Storage backend: sqlite, lmdb (default: sqlite)
|
|
120
|
-
-w, --workflows <path> Path to workflow
|
|
120
|
+
-w, --workflows <path> Path to workflow definitions module (required for create)
|
|
121
121
|
--every <duration> Interval cadence for create (e.g. 30s, 5m, 1h); mutually exclusive with the cron positional
|
|
122
122
|
--input <json> JSON input payload for create (default: null)
|
|
123
123
|
--id <id> Custom schedule id for create
|
|
@@ -127,13 +127,13 @@ Options:
|
|
|
127
127
|
-j, --json Output results as JSON
|
|
128
128
|
-h, --help Show this help message
|
|
129
129
|
`, VALIDATE_HELP_TEXT = `
|
|
130
|
-
weft validate - Lint workflow
|
|
130
|
+
weft validate - Lint workflow definitions for design-time anti-patterns
|
|
131
131
|
|
|
132
132
|
Usage: weft validate <entry.ts>... [options]
|
|
133
133
|
|
|
134
134
|
Arguments:
|
|
135
135
|
<entry.ts>... One or more TypeScript modules or glob patterns that
|
|
136
|
-
resolve to workflow
|
|
136
|
+
resolve to workflow definitions and/or activity
|
|
137
137
|
definitions.
|
|
138
138
|
|
|
139
139
|
Options:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { FaultCode } from '../core/fault-code.ts';
|
|
1
2
|
import type { ErasedOperation, OperationKind, TransportAvailability } from '../server/operation-catalog.ts';
|
|
2
|
-
import type { FaultCode } from '../server/operation-fault.ts';
|
|
3
3
|
import type { ParamSource, ResponseShape } from '../server/rest-binding.ts';
|
|
4
4
|
export type CatalogRestBindingSnapshot = {
|
|
5
5
|
readonly method: string;
|
package/dist/cli/schedule.js
CHANGED
|
@@ -51,10 +51,8 @@ function parseScheduleInput(input) {
|
|
|
51
51
|
}
|
|
52
52
|
async function registerScheduleWorkflows(engine, workflowsPath, loadRegistrationsFromModule) {
|
|
53
53
|
const loaded = await loadRegistrationsFromModule(workflowsPath);
|
|
54
|
-
for (const
|
|
55
|
-
const definition = { ...registration, name: workflowType };
|
|
54
|
+
for (const definition of Object.values(loaded.registrations))
|
|
56
55
|
registerOnRuntimeEngine(runtimeWorkflowEngine(engine), definition);
|
|
57
|
-
}
|
|
58
56
|
}
|
|
59
57
|
async function executeScheduleCreate(options, engine, loadRegistrationsFromModule) {
|
|
60
58
|
const validationError = getScheduleCreateValidationError(options);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ActivityDefinition } from '../core/activity.ts';
|
|
2
2
|
import type { Engine } from '../core/engine.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { WorkflowDefinition } from '../core/types.ts';
|
|
4
4
|
/**
|
|
5
5
|
* Convert a plain-object `ActivityDefinition` into a callable function that
|
|
6
6
|
* satisfies the engine's `isActivityDefinition` check (which requires a
|
|
@@ -8,8 +8,8 @@ import type { WorkflowRegistration } from '../diagnostics/validate.ts';
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function toActivityCallable(definition: ActivityDefinition): (...args: unknown[]) => unknown;
|
|
10
10
|
/**
|
|
11
|
-
* Register a map of workflow
|
|
11
|
+
* Register a map of workflow definitions and a list of activity definitions
|
|
12
12
|
* on an engine instance. Plain-object activities are normalized to callables
|
|
13
13
|
* before registration.
|
|
14
14
|
*/
|
|
15
|
-
export declare function registerModuleExports(engine: Engine, registrations: Record<string,
|
|
15
|
+
export declare function registerModuleExports(engine: Engine, registrations: Record<string, WorkflowDefinition>, activities: ActivityDefinition[]): void;
|
|
@@ -13,8 +13,8 @@ export function toActivityCallable(definition) {
|
|
|
13
13
|
}
|
|
14
14
|
export function registerModuleExports(engine, registrations, activities) {
|
|
15
15
|
const runtime = runtimeWorkflowEngine(engine);
|
|
16
|
-
for (const
|
|
17
|
-
registerOnRuntimeEngine(runtime,
|
|
16
|
+
for (const definition of Object.values(registrations))
|
|
17
|
+
registerOnRuntimeEngine(runtime, definition);
|
|
18
18
|
for (const activity of activities)
|
|
19
19
|
if (typeof activity === "function")
|
|
20
20
|
engine.register(activity);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const CLI_SHUTDOWN_SIGNALS: readonly ["SIGINT", "SIGTERM"];
|
|
2
|
+
export type CliShutdownSignal = (typeof CLI_SHUTDOWN_SIGNALS)[number];
|
|
3
|
+
export type CliShutdownDependencies = {
|
|
4
|
+
readonly stopServer: () => Promise<void>;
|
|
5
|
+
readonly removeRunLockfile: () => Promise<void>;
|
|
6
|
+
readonly disposeStorage: () => void;
|
|
7
|
+
readonly log: (message: string) => void;
|
|
8
|
+
readonly reportError: (message: string, error: unknown) => void;
|
|
9
|
+
readonly exit: (code: 0 | 1) => void;
|
|
10
|
+
};
|
|
11
|
+
export declare function createCliShutdownHandler(dependencies: CliShutdownDependencies): (signal: CliShutdownSignal) => Promise<void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const CLI_SHUTDOWN_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
2
|
+
async function runCliShutdown(signal, dependencies) {
|
|
3
|
+
dependencies.log(`
|
|
4
|
+
Received ${signal}; shutting down...`);
|
|
5
|
+
try {
|
|
6
|
+
await dependencies.stopServer();
|
|
7
|
+
try {
|
|
8
|
+
await dependencies.removeRunLockfile();
|
|
9
|
+
} catch (error) {
|
|
10
|
+
dependencies.reportError("[weft] Failed to remove run lockfile:", error);
|
|
11
|
+
}
|
|
12
|
+
dependencies.disposeStorage();
|
|
13
|
+
dependencies.exit(0);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
dependencies.reportError("[weft] Shutdown error:", error);
|
|
16
|
+
dependencies.exit(1);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function createCliShutdownHandler(dependencies) {
|
|
20
|
+
let shutdownPromise;
|
|
21
|
+
return (signal) => {
|
|
22
|
+
shutdownPromise ??= runCliShutdown(signal, dependencies);
|
|
23
|
+
return shutdownPromise;
|
|
24
|
+
};
|
|
25
|
+
}
|
package/dist/cli/validate.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CommandOutput } from './types.ts';
|
|
2
|
-
/** Validates workflow
|
|
2
|
+
/** Validates workflow definition modules and reports load or design-time errors. */
|
|
3
3
|
export declare function executeValidate(options: {
|
|
4
4
|
entryPaths: string[];
|
|
5
5
|
json: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CommandOutput } from './types.ts';
|
|
2
|
-
/** Checks stored workflow history against the current workflow
|
|
2
|
+
/** Checks stored workflow history against the current workflow definitions. */
|
|
3
3
|
export declare function executeVersionCheck(options: {
|
|
4
4
|
database: string;
|
|
5
5
|
workflows: string;
|
|
@@ -8,7 +8,7 @@ export async function executeVersionCheck(options) {
|
|
|
8
8
|
};
|
|
9
9
|
const { runVersionCheck } = await import("../diagnostics/version-check.js"), { formatVersionCheckReport } = await import("../diagnostics/format.js"), { BunSQLiteStorage } = await import("../storage/bun-sql.js"), storage = new BunSQLiteStorage(options.database);
|
|
10
10
|
try {
|
|
11
|
-
const
|
|
11
|
+
const workflowsPath = resolve(process.cwd(), options.workflows), { loadRegistrationsFromModule } = await import("../diagnostics/validate.js"), { registrations } = await loadRegistrationsFromModule(workflowsPath), report = await runVersionCheck(storage, registrations);
|
|
12
12
|
return { stdout: options.json ? JSON.stringify(report, null, 2) : formatVersionCheckReport(report), exitCode: 0 };
|
|
13
13
|
} finally {
|
|
14
14
|
storage[Symbol.dispose]();
|
package/dist/cli-main.js
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
WORKFLOW_HELP_TEXT,
|
|
33
33
|
writeRunLockfile
|
|
34
34
|
} from "./cli/index.js";
|
|
35
|
+
import { CLI_SHUTDOWN_SIGNALS, createCliShutdownHandler } from "./cli/shutdown.js";
|
|
35
36
|
import { Engine } from "./core/engine.js";
|
|
36
37
|
import { serve } from "./server/index.js";
|
|
37
38
|
const parsedArguments = (() => {
|
|
@@ -67,36 +68,16 @@ if (parsedArguments.command === "version") {
|
|
|
67
68
|
console.log(`Health check: ${new URL("/v1/health", server.url).href}`);
|
|
68
69
|
console.log(`Storage: ${parsedArguments.storage}`);
|
|
69
70
|
console.log(`Database: ${parsedArguments.database}`);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
console.error("[weft] Failed to remove run lockfile:", error);
|
|
78
|
-
}
|
|
79
|
-
storage[Symbol.dispose]();
|
|
80
|
-
process.exit(0);
|
|
81
|
-
}).catch((error) => {
|
|
82
|
-
console.error("[weft] Shutdown error:", error);
|
|
83
|
-
process.exit(1);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
process.on("SIGTERM", () => {
|
|
87
|
-
server.stop().then(async () => {
|
|
88
|
-
try {
|
|
89
|
-
await removeRunLockfile(server.url);
|
|
90
|
-
} catch (error) {
|
|
91
|
-
console.error("[weft] Failed to remove run lockfile:", error);
|
|
92
|
-
}
|
|
93
|
-
storage[Symbol.dispose]();
|
|
94
|
-
process.exit(0);
|
|
95
|
-
}).catch((error) => {
|
|
96
|
-
console.error("[weft] Shutdown error:", error);
|
|
97
|
-
process.exit(1);
|
|
98
|
-
});
|
|
71
|
+
const shutdown = createCliShutdownHandler({
|
|
72
|
+
stopServer: () => server.stop(),
|
|
73
|
+
removeRunLockfile: () => removeRunLockfile(server.url),
|
|
74
|
+
disposeStorage: () => storage[Symbol.dispose](),
|
|
75
|
+
log: (message) => console.log(message),
|
|
76
|
+
reportError: (message, error) => console.error(message, error),
|
|
77
|
+
exit: (code) => process.exit(code)
|
|
99
78
|
});
|
|
79
|
+
for (const signal of CLI_SHUTDOWN_SIGNALS)
|
|
80
|
+
process.on(signal, () => void shutdown(signal));
|
|
100
81
|
} else if (parsedArguments.command === "doctor") {
|
|
101
82
|
if (parsedArguments.help) {
|
|
102
83
|
console.log(DOCTOR_HELP_TEXT);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readBoundedNdjsonResponse } from "../storage/bounded-ndjson-response.js";
|
|
1
2
|
import { decodeBase64ToBytes, encodeBytesToBase64, isRecord } from "../storage/byte-encoding.js";
|
|
2
3
|
import {
|
|
3
4
|
assertStorageBatchOperationCount
|
|
@@ -19,42 +20,13 @@ function scanEntry(value) {
|
|
|
19
20
|
throw Error("HttpClient storage scan response contained an invalid NDJSON entry.");
|
|
20
21
|
return [value.key, decodeBase64ToBytes(value.value)];
|
|
21
22
|
}
|
|
22
|
-
async function releaseScanReader(reader, reachedEndOfStream) {
|
|
23
|
-
if (!reachedEndOfStream)
|
|
24
|
-
try {
|
|
25
|
-
await reader.cancel();
|
|
26
|
-
} catch {}
|
|
27
|
-
reader.releaseLock();
|
|
28
|
-
}
|
|
29
23
|
async function* scanResponse(response) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const { done, value } = await reader.read();
|
|
37
|
-
if (done) {
|
|
38
|
-
reachedEndOfStream = !0;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
bytesRead += value.byteLength;
|
|
42
|
-
if (bytesRead > MAX_SCAN_RESPONSE_BYTES)
|
|
43
|
-
throw Error("HttpClient storage scan response exceeded the maximum allowed size.");
|
|
44
|
-
bufferedText += decoder.decode(value, { stream: !0 });
|
|
45
|
-
const lines = bufferedText.split(`
|
|
46
|
-
`);
|
|
47
|
-
bufferedText = lines.pop() ?? "";
|
|
48
|
-
for (const line of lines)
|
|
49
|
-
if (line.trim().length > 0)
|
|
50
|
-
yield scanEntry(JSON.parse(line));
|
|
51
|
-
}
|
|
52
|
-
bufferedText += decoder.decode();
|
|
53
|
-
if (bufferedText.trim().length > 0)
|
|
54
|
-
yield scanEntry(JSON.parse(bufferedText));
|
|
55
|
-
} finally {
|
|
56
|
-
await releaseScanReader(reader, reachedEndOfStream);
|
|
57
|
-
}
|
|
24
|
+
for await (const line of readBoundedNdjsonResponse(response, {
|
|
25
|
+
maximumBytes: MAX_SCAN_RESPONSE_BYTES,
|
|
26
|
+
sizeLimitError: () => Error("HttpClient storage scan response exceeded the maximum allowed size.")
|
|
27
|
+
}))
|
|
28
|
+
if (line.trim().length > 0)
|
|
29
|
+
yield scanEntry(JSON.parse(line));
|
|
58
30
|
}
|
|
59
31
|
export function createHttpClientStorage(baseUrl, headers) {
|
|
60
32
|
return {
|
|
@@ -63,7 +63,7 @@ export declare function resolveHttpClientConnection(options: HttpClientOptions):
|
|
|
63
63
|
/**
|
|
64
64
|
* Error thrown when the server returns a non-2xx response.
|
|
65
65
|
*
|
|
66
|
-
* When
|
|
66
|
+
* When a transport response carries a recognized coarse fault code, the wire
|
|
67
67
|
* value is surfaced as {@link HttpClientError.faultCode} with a derived
|
|
68
68
|
* {@link HttpClientError.category}, so callers can branch without
|
|
69
69
|
* string-matching `message`. Both are `undefined` for the production flat REST
|
|
@@ -96,8 +96,8 @@ export declare class HttpClientError extends WeftError<'HttpClientError'> {
|
|
|
96
96
|
/** HTTP status code of the failed response. */
|
|
97
97
|
readonly status: number;
|
|
98
98
|
/**
|
|
99
|
-
* The server's stable wire fault code, when the response carried a
|
|
100
|
-
*
|
|
99
|
+
* The server's stable wire fault code, when the transport response carried a
|
|
100
|
+
* recognized code. `undefined` for flat REST error bodies or unrecognized codes.
|
|
101
101
|
*/
|
|
102
102
|
readonly faultCode?: FaultCode | undefined;
|
|
103
103
|
/**
|
|
@@ -107,18 +107,17 @@ export declare class HttpClientError extends WeftError<'HttpClientError'> {
|
|
|
107
107
|
readonly category?: FailureCategory | undefined;
|
|
108
108
|
/**
|
|
109
109
|
* The fine-grained originating public {@link WeftErrorCode} the server
|
|
110
|
-
* attached (e.g. `WorkflowNotFoundError`), when the
|
|
111
|
-
*
|
|
110
|
+
* attached (e.g. `WorkflowNotFoundError`), when the response carried one.
|
|
111
|
+
* This is what makes cross-transport branching work: a producer can call
|
|
112
112
|
* `isWeftFault(error, 'WorkflowNotFoundError')` and have it match over HTTP
|
|
113
113
|
* exactly as it matches the in-process typed error. `undefined` when the fault
|
|
114
|
-
* carried only the coarse {@link faultCode} (most faults) or no
|
|
114
|
+
* carried only the coarse {@link faultCode} (most faults) or no recognized code.
|
|
115
115
|
*/
|
|
116
116
|
readonly weftCode?: WeftErrorCode | undefined;
|
|
117
117
|
/**
|
|
118
118
|
* The fault's wire `data` payload, when the response carried a structured
|
|
119
|
-
* body (`{ error, data }` for production REST
|
|
120
|
-
*
|
|
121
|
-
* fault-code-dependent — see {@link FaultCode} and the server's
|
|
119
|
+
* body (`{ error, data }` for production REST or `error.data` for JSON-RPC).
|
|
120
|
+
* Shape is fault-code-dependent — see {@link FaultCode} and the server's
|
|
122
121
|
* `OperationFault` per-code `data` union for what each code carries (e.g.
|
|
123
122
|
* `InvalidParams.data.issues`, `NotFound.data.resource`). `undefined` for
|
|
124
123
|
* plain-string error bodies, bodies with no `data` field, or a `data` field
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveConnection } from "../connection.js";
|
|
2
|
-
import { failureCategoryForFaultCode
|
|
2
|
+
import { failureCategoryForFaultCode } from "../core/fault-code.js";
|
|
3
3
|
import { isWeftErrorCode, WeftError } from "../core/weft-error.js";
|
|
4
4
|
export function resolveHttpClientConnection(options) {
|
|
5
5
|
const connection = resolveConnection({
|
|
@@ -49,34 +49,12 @@ function parseFlatErrorBody(body) {
|
|
|
49
49
|
...data === void 0 ? {} : { data }
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
function isStructuredErrorBody(value) {
|
|
53
|
-
if (value === null || typeof value !== "object")
|
|
54
|
-
return !1;
|
|
55
|
-
const error = value.error;
|
|
56
|
-
if (error === null || typeof error !== "object")
|
|
57
|
-
return !1;
|
|
58
|
-
return typeof error.message === "string";
|
|
59
|
-
}
|
|
60
|
-
function weftCodeFromData(data) {
|
|
61
|
-
if (data === null || typeof data !== "object")
|
|
62
|
-
return;
|
|
63
|
-
const candidate = data.weftCode;
|
|
64
|
-
return isWeftErrorCode(candidate) ? candidate : void 0;
|
|
65
|
-
}
|
|
66
52
|
function isRecord(value) {
|
|
67
53
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
68
54
|
}
|
|
69
55
|
async function parseErrorBody(response) {
|
|
70
56
|
try {
|
|
71
57
|
const body = await response.json();
|
|
72
|
-
if (isStructuredErrorBody(body)) {
|
|
73
|
-
const { code, message, data } = body.error, weftCode = weftCodeFromData(data), base = { message };
|
|
74
|
-
if (weftCode !== void 0)
|
|
75
|
-
base.weftCode = weftCode;
|
|
76
|
-
if (isRecord(data))
|
|
77
|
-
base.data = data;
|
|
78
|
-
return isFaultCode(code) ? { ...base, faultCode: code } : base;
|
|
79
|
-
}
|
|
80
58
|
if (isFlatErrorBody(body) && body.error)
|
|
81
59
|
return parseFlatErrorBody(body);
|
|
82
60
|
return { message: response.statusText };
|
|
@@ -97,8 +75,8 @@ export async function requestResponse(baseUrl, path, baseHeaders, options) {
|
|
|
97
75
|
if (response.status === 404 && (!options?.method || options.method === "GET"))
|
|
98
76
|
return null;
|
|
99
77
|
if (!response.ok) {
|
|
100
|
-
const { message,
|
|
101
|
-
throw new HttpClientError(response.status, message, {
|
|
78
|
+
const { message, weftCode, data } = await parseErrorBody(response);
|
|
79
|
+
throw new HttpClientError(response.status, message, { weftCode, data });
|
|
102
80
|
}
|
|
103
81
|
return response;
|
|
104
82
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { Context } from './index.ts';
|
|
2
2
|
import type { ContextInternals } from './internals.ts';
|
|
3
3
|
import type { ContextOperationRequest } from './operation-request.ts';
|
|
4
|
-
import { assertValidParallelOperationCacheEntry, BranchTopologyChangedError, createParallelOperationCacheEntry, isParallelOperationCacheEntry, type ParallelBranchSlot, type ParallelOperationCacheEntry } from './parallel-cache-entry.ts';
|
|
5
|
-
export { assertValidParallelOperationCacheEntry, BranchTopologyChangedError, createParallelOperationCacheEntry, isParallelOperationCacheEntry, type ParallelBranchSlot, type ParallelOperationCacheEntry, };
|
|
6
4
|
export declare function all(context: Context, internals: ContextInternals, operations: Generator<ContextOperationRequest, unknown, unknown>[]): Generator<ContextOperationRequest, unknown[], unknown>;
|
|
7
5
|
export declare function race(context: Context, internals: ContextInternals, operations: Generator<ContextOperationRequest, unknown, unknown>[], branchNames?: string[]): Generator<ContextOperationRequest, unknown, unknown>;
|
|
8
6
|
export declare function memo<T>(context: Context, internals: ContextInternals, key: string, fn: () => T | Promise<T>): Generator<ContextOperationRequest, T, unknown>;
|
|
@@ -6,13 +6,6 @@ import {
|
|
|
6
6
|
isParallelOperationCacheEntry
|
|
7
7
|
} from "./parallel-cache-entry.js";
|
|
8
8
|
import { captureCallerStack } from "./validation.js";
|
|
9
|
-
|
|
10
|
-
export {
|
|
11
|
-
assertValidParallelOperationCacheEntry,
|
|
12
|
-
BranchTopologyChangedError,
|
|
13
|
-
createParallelOperationCacheEntry,
|
|
14
|
-
isParallelOperationCacheEntry
|
|
15
|
-
};
|
|
16
9
|
function reconstructAllResult(entry) {
|
|
17
10
|
return entry.branches.map((slot) => {
|
|
18
11
|
if (slot.status !== "fulfilled")
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { ContextOperationRequest } from '../context.ts';
|
|
2
|
+
import { type PersistCheckpointCallbacks } from './checkpoint-io.ts';
|
|
2
3
|
import type { Engine } from './index.ts';
|
|
4
|
+
export declare function createCheckpointPersistenceCallbacks<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>): PersistCheckpointCallbacks;
|
|
3
5
|
export declare function persistCheckpointForDataOperation<TWorkflows extends object, TActivities extends object>(engine: Engine<TWorkflows, TActivities>, workflowId: string, operation: ContextOperationRequest): Promise<void>;
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
import { getInternals } from "./internals.js";
|
|
10
10
|
import { swallowPromiseRejection } from "./strategy-helpers.js";
|
|
11
11
|
import { terminateWorkflow } from "./termination.js";
|
|
12
|
-
export function
|
|
13
|
-
return
|
|
12
|
+
export function createCheckpointPersistenceCallbacks(engine) {
|
|
13
|
+
return {
|
|
14
14
|
appendTimelineBatchOperations: (id, checkpointOperation, step, timestamp, operations) => appendTimelineBatchOperations(getInternals(engine), id, checkpointOperation, step, timestamp, operations),
|
|
15
15
|
swallowPromiseRejection: (promise) => {
|
|
16
16
|
swallowPromiseRejection(promise);
|
|
@@ -21,5 +21,8 @@ export function persistCheckpointForDataOperation(engine, workflowId, operation)
|
|
|
21
21
|
engine.dispatchEvent(event);
|
|
22
22
|
},
|
|
23
23
|
enforceHistoryCircuitBreaker: (id) => terminateWorkflow(getInternals(engine), id, "timed-out", createTerminationCallbacks(engine), HISTORY_CIRCUIT_BREAKER_REASON)
|
|
24
|
-
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function persistCheckpointForDataOperation(engine, workflowId, operation) {
|
|
27
|
+
return persistCheckpoint(getInternals(engine), workflowId, operation, void 0, createCheckpointPersistenceCallbacks(engine), { timeline: "preserve-pending" });
|
|
25
28
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { KEYS } from "../../storage/interface.js";
|
|
2
|
-
import {
|
|
3
|
-
import { validateAttributeValueSizes } from "./attributes-tags.js";
|
|
2
|
+
import { createCheckpointPersistenceCallbacks } from "./callback-checkpoint-persistence.js";
|
|
4
3
|
import {
|
|
5
4
|
createConstraintCallbacks,
|
|
6
5
|
createLifecycleCallbacks,
|
|
@@ -8,12 +7,7 @@ import {
|
|
|
8
7
|
registerEnsureRetentionSweepInterval
|
|
9
8
|
} from "./callback-creators-core.js";
|
|
10
9
|
import { createOperationRouterCallbacks } from "./callback-creators-router.js";
|
|
11
|
-
import {
|
|
12
|
-
appendTimelineBatchOperations,
|
|
13
|
-
persistCheckpoint,
|
|
14
|
-
pruneCheckpointHistory,
|
|
15
|
-
validateDevelopmentCheckpoint
|
|
16
|
-
} from "./checkpoint-io.js";
|
|
10
|
+
import { persistCheckpoint, validateDevelopmentCheckpoint } from "./checkpoint-io.js";
|
|
17
11
|
import { evaluateConstraints } from "./constraints.js";
|
|
18
12
|
import {
|
|
19
13
|
getParkedWorkflowResumeDisposition,
|
|
@@ -30,8 +24,7 @@ import {
|
|
|
30
24
|
} from "./retention.js";
|
|
31
25
|
import { hasBufferedSignal } from "./signals.js";
|
|
32
26
|
import { loadWorkflowState, runSerializedWorkflowStateWrite } from "./storage-io.js";
|
|
33
|
-
import {
|
|
34
|
-
import { cleanupWaiters, terminateWorkflow } from "./termination.js";
|
|
27
|
+
import { cleanupWaiters } from "./termination.js";
|
|
35
28
|
export { createUpdateCallbacks } from "./callback-creators-bundles.js";
|
|
36
29
|
export {
|
|
37
30
|
createBroadcastCallbacks,
|
|
@@ -64,18 +57,7 @@ export function createInlineParkingCallbacks(engine) {
|
|
|
64
57
|
};
|
|
65
58
|
}
|
|
66
59
|
export function persistCheckpointForEngine(engine, workflowId, operation, workerCheckpointBytes) {
|
|
67
|
-
return persistCheckpoint(getInternals(engine), workflowId, operation, workerCheckpointBytes,
|
|
68
|
-
appendTimelineBatchOperations: (id, checkpointOperation, step, timestamp, operations) => appendTimelineBatchOperations(getInternals(engine), id, checkpointOperation, step, timestamp, operations),
|
|
69
|
-
swallowPromiseRejection: (promise) => {
|
|
70
|
-
swallowPromiseRejection(promise);
|
|
71
|
-
},
|
|
72
|
-
validateAttributeValueSizes,
|
|
73
|
-
pruneCheckpointHistory: (id, step) => pruneCheckpointHistory(getInternals(engine), id, step),
|
|
74
|
-
dispatchEvent: (event) => {
|
|
75
|
-
engine.dispatchEvent(event);
|
|
76
|
-
},
|
|
77
|
-
enforceHistoryCircuitBreaker: (id) => terminateWorkflow(getInternals(engine), id, "timed-out", createTerminationCallbacks(engine), HISTORY_CIRCUIT_BREAKER_REASON)
|
|
78
|
-
});
|
|
60
|
+
return persistCheckpoint(getInternals(engine), workflowId, operation, workerCheckpointBytes, createCheckpointPersistenceCallbacks(engine));
|
|
79
61
|
}
|
|
80
62
|
function ensureRetentionSweepIntervalForEngine(engine) {
|
|
81
63
|
ensureRetentionSweepInterval(getInternals(engine), {
|
|
@@ -9,7 +9,7 @@ type PendingTimelineEntryValue = {
|
|
|
9
9
|
export type PersistCheckpointOptions = {
|
|
10
10
|
timeline?: 'record-operation' | 'preserve-pending';
|
|
11
11
|
};
|
|
12
|
-
type PersistCheckpointCallbacks = {
|
|
12
|
+
export type PersistCheckpointCallbacks = {
|
|
13
13
|
appendTimelineBatchOperations: (workflowId: string, operation: ContextOperationRequest, step: number, timestamp: number, operations: BatchOperation[]) => PendingTimelineEntryValue;
|
|
14
14
|
swallowPromiseRejection: (promise: Promise<void>) => void;
|
|
15
15
|
validateAttributeValueSizes: (attributes: Record<string, SearchAttributeValue>) => void;
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* checkpoint-write machinery — see the `parallel-execution.md` guide
|
|
26
26
|
* for the precise durability contract.
|
|
27
27
|
*/
|
|
28
|
-
import type { ParallelBranchSlot, ParallelOperationCacheEntry } from '../context/parallel-
|
|
28
|
+
import type { ParallelBranchSlot, ParallelOperationCacheEntry } from '../context/parallel-cache-entry.ts';
|
|
29
29
|
export type ParallelDispatchResult = {
|
|
30
30
|
/** Final slot table — every entry is `fulfilled` or `rejected`. */
|
|
31
31
|
slots: ParallelBranchSlot[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createParallelOperationCacheEntry } from "../context/parallel-
|
|
1
|
+
import { createParallelOperationCacheEntry } from "../context/parallel-cache-entry.js";
|
|
2
2
|
export function createFirstRejectionCapture() {
|
|
3
3
|
return { hasFirstError: !1, firstError: void 0 };
|
|
4
4
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type HumanReviewResult, type ReviewRequest } from '../review/index.ts';
|
|
2
2
|
import type { CompletedReviewEntry, PendingReviewEntry } from '../types.ts';
|
|
3
3
|
export declare function toPendingReviewEntry(review: ReviewRequest): PendingReviewEntry;
|
|
4
4
|
export declare function parseStoredReviewRequest(value: Uint8Array): ReviewRequest | null;
|
|
@@ -1,32 +1,8 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
1
|
import { decode } from "../codec.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
reviewType: z.string(),
|
|
8
|
-
reviewers: z.array(z.string()),
|
|
9
|
-
allowPartial: z.boolean(),
|
|
10
|
-
timeout: z.number().optional(),
|
|
11
|
-
webhookUrl: z.string().optional(),
|
|
12
|
-
createdAt: z.number()
|
|
13
|
-
}), persistedCompletedReviewEntrySchema = z.object({
|
|
14
|
-
status: z.literal("completed"),
|
|
15
|
-
reviewId: z.string(),
|
|
16
|
-
workflowId: z.string(),
|
|
17
|
-
artifact: z.unknown().nonoptional(),
|
|
18
|
-
reviewType: z.string(),
|
|
19
|
-
reviewers: z.array(z.string()),
|
|
20
|
-
allowPartial: z.boolean(),
|
|
21
|
-
timeout: z.number().optional(),
|
|
22
|
-
webhookUrl: z.string().optional(),
|
|
23
|
-
createdAt: z.number(),
|
|
24
|
-
decision: z.enum(["approved", "rejected", "needs-changes"]),
|
|
25
|
-
reviewer: z.string(),
|
|
26
|
-
feedback: z.string().optional(),
|
|
27
|
-
sectionDecisions: z.record(z.string(), z.enum(["approved", "rejected"])).optional(),
|
|
28
|
-
timestamp: z.number()
|
|
29
|
-
});
|
|
2
|
+
import {
|
|
3
|
+
completedReviewEntrySchema,
|
|
4
|
+
reviewRequestSchema
|
|
5
|
+
} from "../review/index.js";
|
|
30
6
|
function assignWhenDefined(target, key, value) {
|
|
31
7
|
if (value !== void 0)
|
|
32
8
|
target[key] = value;
|
|
@@ -58,7 +34,7 @@ export function parseStoredReviewRequest(value) {
|
|
|
58
34
|
} catch {
|
|
59
35
|
return null;
|
|
60
36
|
}
|
|
61
|
-
const parsedReview =
|
|
37
|
+
const parsedReview = reviewRequestSchema.safeParse(decodedValue);
|
|
62
38
|
if (!parsedReview.success)
|
|
63
39
|
return null;
|
|
64
40
|
return normalizeStoredReviewRequest(parsedReview.data);
|
|
@@ -110,7 +86,7 @@ export function parseCompletedReviewEntry(value) {
|
|
|
110
86
|
} catch {
|
|
111
87
|
return null;
|
|
112
88
|
}
|
|
113
|
-
const parsedReview =
|
|
89
|
+
const parsedReview = completedReviewEntrySchema.safeParse(decodedValue);
|
|
114
90
|
if (!parsedReview.success)
|
|
115
91
|
return null;
|
|
116
92
|
return normalizeCompletedReviewEntry(parsedReview.data);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ContextOperationRequest } from '../context.ts';
|
|
2
|
-
import type { ParallelBranchSlot } from '../context/parallel-
|
|
2
|
+
import type { ParallelBranchSlot } from '../context/parallel-cache-entry.ts';
|
|
3
3
|
import type { WorkflowTimelineOperationDetail } from '../types.ts';
|
|
4
4
|
import type { EngineInternals } from './internals.ts';
|
|
5
5
|
export declare function operationTimelineDetail(operation: ContextOperationRequest, index: number, outcome: WorkflowTimelineOperationDetail['outcome'], options?: {
|