@lostgradient/weft 0.13.0 → 0.15.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 +3 -8
- package/dist/cli/generated/operation-catalog.snapshot.json +977 -77
- package/dist/cli/generated/operation-client.generated.d.ts +14 -21
- 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/aggregate-validation.d.ts +2 -5
- package/dist/core/aggregate-validation.js +2 -10
- package/dist/core/atomic-state.js +21 -24
- 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/schedules.js +4 -1
- package/dist/core/engine/timeline-coordinator-detail.d.ts +1 -1
- package/dist/core/inline-execution-strategy.js +8 -46
- package/dist/core/list-filter-validation.d.ts +2 -5
- package/dist/core/list-filter-validation.js +2 -10
- package/dist/core/review/index.d.ts +87 -0
- package/dist/core/review/index.js +29 -0
- package/dist/core/types/schedules.d.ts +13 -31
- package/dist/core/validation-issues.d.ts +13 -0
- package/dist/core/validation-issues.js +9 -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/indexeddb.js +1 -1
- package/dist/mcp/session.js +2 -10
- package/dist/mcp/tools.js +2 -10
- package/dist/mcp/tuple-list-equality.d.ts +1 -0
- package/dist/mcp/tuple-list-equality.js +12 -0
- 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 +3 -2
- package/dist/server/operation-fault.d.ts +1 -4
- package/dist/server/operation-fault.js +1 -1
- package/dist/server/operation-registry.d.ts +2 -31
- package/dist/server/operations/bulk-filter-helpers.d.ts +17 -17
- package/dist/server/operations/bulk-filter-helpers.js +16 -37
- package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +27 -27
- package/dist/server/operations/bulk-signal-workflows.d.ts +26 -26
- package/dist/server/operations/create-schedule.js +7 -19
- package/dist/server/operations/event-stream-contracts.d.ts +20 -0
- package/dist/server/operations/event-stream-contracts.js +67 -0
- package/dist/server/operations/fleet-events-sse.js +21 -50
- package/dist/server/operations/fleet-events-subscription.js +8 -12
- package/dist/server/operations/list-reviews.js +2 -19
- package/dist/server/operations/list-workflows.d.ts +43 -43
- package/dist/server/operations/list-workflows.js +9 -30
- package/dist/server/operations/purge-workflows.d.ts +11 -11
- package/dist/server/operations/recover-all.js +1 -10
- package/dist/server/operations/schedule-rest-body.d.ts +11 -0
- package/dist/server/operations/schedule-rest-body.js +28 -0
- package/dist/server/operations/single-workflow-control-operation.d.ts +2 -1
- package/dist/server/operations/update-schedule.js +7 -19
- package/dist/server/operations/workflow-events-sse.js +29 -67
- package/dist/server/operations/workflow-events-subscription.js +9 -27
- package/dist/server/runtime/task-polling.js +3 -5
- package/dist/server/task-state.d.ts +2 -8
- package/dist/server/task-state.js +10 -7
- package/dist/storage/bounded-ndjson-response.d.ts +5 -0
- package/dist/storage/bounded-ndjson-response.js +33 -0
- package/dist/storage/bun-sql.js +52 -49
- package/dist/storage/conditional-batch-body.d.ts +7 -0
- package/dist/storage/conditional-batch-body.js +14 -0
- package/dist/storage/http.js +5 -37
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.d.ts +3 -16
- package/dist/storage/neon.js +2 -2
- package/dist/storage/node-sqlite-loader.d.ts +2 -2
- package/dist/storage/node-sqlite.js +32 -17
- package/dist/storage/postgres.js +1 -1
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/turso.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/web-extension.js +1 -1
- package/dist/worker/execute-with-interceptors.d.ts +1 -1
- package/dist/worker/execute-with-interceptors.js +2 -2
- package/dist/worker/index.js +5 -5
- package/dist/worker/long-poll.js +3 -4
- package/dist/worker/protocol-messages.d.ts +11 -19
- package/dist/worker/protocol-schemas.d.ts +8 -8
- package/dist/worker/protocol-schemas.js +4 -4
- package/dist/worker/protocol-task-result.d.ts +1 -0
- package/dist/worker/protocol-task-result.js +1 -3
- package/dist/worker/protocol.js +1 -1
- package/dist/worker/registry/types.d.ts +2 -7
- package/dist/worker/registry.d.ts +3 -9
- package/dist/worker/registry.js +2 -5
- package/package.json +1 -1
|
@@ -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);
|
|
@@ -100,7 +100,10 @@ async function hasCurrentScheduleTimer(internals, state) {
|
|
|
100
100
|
}
|
|
101
101
|
export function toScheduleSummary(state) {
|
|
102
102
|
const { input: _input, ...summary } = state;
|
|
103
|
-
return {
|
|
103
|
+
return {
|
|
104
|
+
...summary,
|
|
105
|
+
queuedRuns: summary.queuedRuns.map((queuedRun) => ({ ...queuedRun }))
|
|
106
|
+
};
|
|
104
107
|
}
|
|
105
108
|
export async function pauseSchedule(internals, scheduleId) {
|
|
106
109
|
const normalizedScheduleId = coerceScheduleId(scheduleId, "scheduleId"), state = await requireScheduleState(internals, normalizedScheduleId);
|
|
@@ -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?: {
|
|
@@ -128,11 +128,17 @@ export class InlineExecutionStrategy {
|
|
|
128
128
|
this[Symbol.dispose]();
|
|
129
129
|
}
|
|
130
130
|
#driveGenerator(workflowId, generator, lastResult) {
|
|
131
|
+
return this.#advanceGenerator(workflowId, () => generator.next(lastResult), void 0);
|
|
132
|
+
}
|
|
133
|
+
#throwIntoGenerator(workflowId, generator, error, operationFailureCategory) {
|
|
134
|
+
return this.#advanceGenerator(workflowId, () => generator.throw(error), operationFailureCategory);
|
|
135
|
+
}
|
|
136
|
+
#advanceGenerator(workflowId, advance, fallbackFailureCategory) {
|
|
131
137
|
return this.#trackWorkflowAdvance(workflowId, (async () => {
|
|
132
138
|
try {
|
|
133
139
|
if (this.#abortControllers.get(workflowId)?.signal.aborted)
|
|
134
140
|
return;
|
|
135
|
-
const iterationResult = await
|
|
141
|
+
const iterationResult = await advance();
|
|
136
142
|
if (iterationResult.done) {
|
|
137
143
|
this.#cleanup(workflowId, {
|
|
138
144
|
preserveTrackedAdvance: !0,
|
|
@@ -161,7 +167,7 @@ export class InlineExecutionStrategy {
|
|
|
161
167
|
type: "failed",
|
|
162
168
|
workflowId,
|
|
163
169
|
error: error instanceof Error ? error.message : String(error),
|
|
164
|
-
failureCategory: classifyErrorAsFailureCategory(error, {
|
|
170
|
+
failureCategory: fallbackFailureCategory ?? classifyErrorAsFailureCategory(error, {
|
|
165
171
|
defaultErrorCategory: "application"
|
|
166
172
|
})
|
|
167
173
|
};
|
|
@@ -171,50 +177,6 @@ export class InlineExecutionStrategy {
|
|
|
171
177
|
}
|
|
172
178
|
})());
|
|
173
179
|
}
|
|
174
|
-
#throwIntoGenerator(workflowId, generator, error, operationFailureCategory) {
|
|
175
|
-
return this.#trackWorkflowAdvance(workflowId, (async () => {
|
|
176
|
-
try {
|
|
177
|
-
if (this.#abortControllers.get(workflowId)?.signal.aborted)
|
|
178
|
-
return;
|
|
179
|
-
const iterationResult = await generator.throw(error);
|
|
180
|
-
if (iterationResult.done) {
|
|
181
|
-
this.#cleanup(workflowId, {
|
|
182
|
-
preserveTrackedAdvance: !0,
|
|
183
|
-
preserveTrackedTurn: !0
|
|
184
|
-
});
|
|
185
|
-
this.#emit({
|
|
186
|
-
type: "completed",
|
|
187
|
-
workflowId,
|
|
188
|
-
result: iterationResult.value
|
|
189
|
-
});
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
const operation = iterationResult.value;
|
|
193
|
-
this.#emit({
|
|
194
|
-
type: "checkpoint",
|
|
195
|
-
workflowId,
|
|
196
|
-
checkpoint: new ArrayBuffer(0),
|
|
197
|
-
operationRequest: operation
|
|
198
|
-
});
|
|
199
|
-
} catch (innerError) {
|
|
200
|
-
this.#cleanup(workflowId, {
|
|
201
|
-
preserveTrackedAdvance: !0,
|
|
202
|
-
preserveTrackedTurn: !0
|
|
203
|
-
});
|
|
204
|
-
const failedMessage = {
|
|
205
|
-
type: "failed",
|
|
206
|
-
workflowId,
|
|
207
|
-
error: innerError instanceof Error ? innerError.message : String(innerError),
|
|
208
|
-
failureCategory: operationFailureCategory ?? classifyErrorAsFailureCategory(innerError, {
|
|
209
|
-
defaultErrorCategory: "application"
|
|
210
|
-
})
|
|
211
|
-
};
|
|
212
|
-
if (innerError instanceof Error && innerError.stack !== void 0)
|
|
213
|
-
failedMessage.errorStack = innerError.stack;
|
|
214
|
-
this.#emit(failedMessage);
|
|
215
|
-
}
|
|
216
|
-
})());
|
|
217
|
-
}
|
|
218
180
|
#trackWorkflowAdvance(workflowId, pendingAdvance) {
|
|
219
181
|
const trackedAdvance = pendingAdvance.finally(() => {
|
|
220
182
|
if (this.#workflowAdvances.get(workflowId) === trackedAdvance)
|
|
@@ -12,6 +12,7 @@ import { z } from 'zod';
|
|
|
12
12
|
import { isFailureCategory } from './failure-categories.ts';
|
|
13
13
|
import type { FailureCategory, WorkflowStatus } from './types/identity.ts';
|
|
14
14
|
import type { ListFilter } from './types/list-options.ts';
|
|
15
|
+
import { type ValidationIssue } from './validation-issues.ts';
|
|
15
16
|
import { WeftError } from './weft-error.ts';
|
|
16
17
|
/**
|
|
17
18
|
* Concrete object schema for {@link ListFilter}. Supports `.omit()` and
|
|
@@ -56,11 +57,7 @@ export declare const listFilterObjectSchema: z.ZodObject<{
|
|
|
56
57
|
failureCategory: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<FailureCategory, unknown, z.core.$ZodTypeInternals<FailureCategory, unknown>>, z.ZodArray<z.ZodType<FailureCategory, unknown, z.core.$ZodTypeInternals<FailureCategory, unknown>>>]>>;
|
|
57
58
|
}, z.core.$strict>;
|
|
58
59
|
/** A flattened Zod issue suitable for cross-transport serialization. */
|
|
59
|
-
export type FilterValidationIssue =
|
|
60
|
-
readonly path: ReadonlyArray<string | number>;
|
|
61
|
-
readonly message: string;
|
|
62
|
-
readonly code: string;
|
|
63
|
-
};
|
|
60
|
+
export type FilterValidationIssue = ValidationIssue;
|
|
64
61
|
/**
|
|
65
62
|
* Thrown by {@link normalizeListFilter} when the input fails validation.
|
|
66
63
|
* Carries flattened Zod issues so transport adapters can map directly to the
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { FAILURE_CATEGORIES, isFailureCategory } from "./failure-categories.js";
|
|
3
|
+
import { flattenZodIssue } from "./validation-issues.js";
|
|
3
4
|
import { WeftError } from "./weft-error.js";
|
|
4
5
|
const WORKFLOW_STATUSES = [
|
|
5
6
|
"pending",
|
|
@@ -48,15 +49,6 @@ export const listFilterObjectSchema = z.object({
|
|
|
48
49
|
executionDeadline: timeRangeSchema.optional(),
|
|
49
50
|
failureCategory: z.union([failureCategorySchema, z.array(failureCategorySchema).min(1)]).optional()
|
|
50
51
|
}).strict();
|
|
51
|
-
function flattenIssue(issue) {
|
|
52
|
-
const path = [];
|
|
53
|
-
for (const segment of issue.path)
|
|
54
|
-
if (typeof segment === "string" || typeof segment === "number")
|
|
55
|
-
path.push(segment);
|
|
56
|
-
else
|
|
57
|
-
path.push(String(segment));
|
|
58
|
-
return { path, message: issue.message, code: issue.code };
|
|
59
|
-
}
|
|
60
52
|
|
|
61
53
|
export class ListFilterValidationError extends WeftError {
|
|
62
54
|
issues;
|
|
@@ -72,7 +64,7 @@ export class ListFilterValidationError extends WeftError {
|
|
|
72
64
|
export function normalizeListFilter(input) {
|
|
73
65
|
const result = listFilterObjectSchema.safeParse(input ?? {});
|
|
74
66
|
if (!result.success)
|
|
75
|
-
throw new ListFilterValidationError(result.error.issues.map(
|
|
67
|
+
throw new ListFilterValidationError(result.error.issues.map(flattenZodIssue));
|
|
76
68
|
if (result.data.parentWorkflowExecutionToken !== void 0 && result.data.parentWorkflowId === void 0)
|
|
77
69
|
throw new ListFilterValidationError([
|
|
78
70
|
{
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module human-review
|
|
8
8
|
*/
|
|
9
|
+
import { z } from 'zod';
|
|
9
10
|
import type { BatchOperation, Storage } from '../../storage/interface.ts';
|
|
10
11
|
import { WeftError } from '../weft-error.ts';
|
|
11
12
|
/**
|
|
@@ -51,6 +52,92 @@ export interface ReviewDecisionRecord {
|
|
|
51
52
|
sectionDecisions?: Record<string, 'approved' | 'rejected'>;
|
|
52
53
|
timestamp: number;
|
|
53
54
|
}
|
|
55
|
+
/** Canonical schema for a persisted review request without its storage envelope. */
|
|
56
|
+
export declare const reviewRequestSchema: z.ZodObject<{
|
|
57
|
+
reviewId: z.ZodString;
|
|
58
|
+
workflowId: z.ZodString;
|
|
59
|
+
artifact: z.ZodNonOptional<z.ZodUnknown>;
|
|
60
|
+
reviewType: z.ZodString;
|
|
61
|
+
reviewers: z.ZodArray<z.ZodString>;
|
|
62
|
+
allowPartial: z.ZodBoolean;
|
|
63
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
64
|
+
webhookUrl: z.ZodOptional<z.ZodString>;
|
|
65
|
+
createdAt: z.ZodNumber;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
/** Canonical schema for a pending review entry returned by review list surfaces. */
|
|
68
|
+
export declare const pendingReviewEntrySchema: z.ZodObject<{
|
|
69
|
+
reviewId: z.ZodString;
|
|
70
|
+
workflowId: z.ZodString;
|
|
71
|
+
artifact: z.ZodNonOptional<z.ZodUnknown>;
|
|
72
|
+
reviewType: z.ZodString;
|
|
73
|
+
reviewers: z.ZodArray<z.ZodString>;
|
|
74
|
+
allowPartial: z.ZodBoolean;
|
|
75
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
76
|
+
webhookUrl: z.ZodOptional<z.ZodString>;
|
|
77
|
+
createdAt: z.ZodNumber;
|
|
78
|
+
status: z.ZodLiteral<"pending">;
|
|
79
|
+
}, z.core.$strip>;
|
|
80
|
+
/** Canonical schema for a completed review entry returned by review list surfaces. */
|
|
81
|
+
export declare const completedReviewEntrySchema: z.ZodObject<{
|
|
82
|
+
decision: z.ZodEnum<{
|
|
83
|
+
approved: "approved";
|
|
84
|
+
rejected: "rejected";
|
|
85
|
+
"needs-changes": "needs-changes";
|
|
86
|
+
}>;
|
|
87
|
+
reviewer: z.ZodString;
|
|
88
|
+
feedback: z.ZodOptional<z.ZodString>;
|
|
89
|
+
sectionDecisions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
|
|
90
|
+
approved: "approved";
|
|
91
|
+
rejected: "rejected";
|
|
92
|
+
}>>>;
|
|
93
|
+
timestamp: z.ZodNumber;
|
|
94
|
+
reviewId: z.ZodString;
|
|
95
|
+
workflowId: z.ZodString;
|
|
96
|
+
artifact: z.ZodNonOptional<z.ZodUnknown>;
|
|
97
|
+
reviewType: z.ZodString;
|
|
98
|
+
reviewers: z.ZodArray<z.ZodString>;
|
|
99
|
+
allowPartial: z.ZodBoolean;
|
|
100
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
101
|
+
webhookUrl: z.ZodOptional<z.ZodString>;
|
|
102
|
+
createdAt: z.ZodNumber;
|
|
103
|
+
status: z.ZodLiteral<"completed">;
|
|
104
|
+
}, z.core.$strip>;
|
|
105
|
+
/** Canonical schema for the discriminated review list-entry union. */
|
|
106
|
+
export declare const reviewListEntrySchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
107
|
+
reviewId: z.ZodString;
|
|
108
|
+
workflowId: z.ZodString;
|
|
109
|
+
artifact: z.ZodNonOptional<z.ZodUnknown>;
|
|
110
|
+
reviewType: z.ZodString;
|
|
111
|
+
reviewers: z.ZodArray<z.ZodString>;
|
|
112
|
+
allowPartial: z.ZodBoolean;
|
|
113
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
114
|
+
webhookUrl: z.ZodOptional<z.ZodString>;
|
|
115
|
+
createdAt: z.ZodNumber;
|
|
116
|
+
status: z.ZodLiteral<"pending">;
|
|
117
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
118
|
+
decision: z.ZodEnum<{
|
|
119
|
+
approved: "approved";
|
|
120
|
+
rejected: "rejected";
|
|
121
|
+
"needs-changes": "needs-changes";
|
|
122
|
+
}>;
|
|
123
|
+
reviewer: z.ZodString;
|
|
124
|
+
feedback: z.ZodOptional<z.ZodString>;
|
|
125
|
+
sectionDecisions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEnum<{
|
|
126
|
+
approved: "approved";
|
|
127
|
+
rejected: "rejected";
|
|
128
|
+
}>>>;
|
|
129
|
+
timestamp: z.ZodNumber;
|
|
130
|
+
reviewId: z.ZodString;
|
|
131
|
+
workflowId: z.ZodString;
|
|
132
|
+
artifact: z.ZodNonOptional<z.ZodUnknown>;
|
|
133
|
+
reviewType: z.ZodString;
|
|
134
|
+
reviewers: z.ZodArray<z.ZodString>;
|
|
135
|
+
allowPartial: z.ZodBoolean;
|
|
136
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
137
|
+
webhookUrl: z.ZodOptional<z.ZodString>;
|
|
138
|
+
createdAt: z.ZodNumber;
|
|
139
|
+
status: z.ZodLiteral<"completed">;
|
|
140
|
+
}, z.core.$strip>]>;
|
|
54
141
|
/**
|
|
55
142
|
* One step in a {@link ReviewOptions.escalation} chain. Either reassigns the
|
|
56
143
|
* pending review to a new owner (`to`) or auto-decides it (`action`) after
|
|
@@ -1,7 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import { KEYS } from "../../storage/interface.js";
|
|
2
3
|
import { decode, encode } from "../codec.js";
|
|
3
4
|
import { WeftError } from "../weft-error.js";
|
|
4
5
|
import { ReviewRequestedEvent } from "./events.js";
|
|
6
|
+
const reviewRequestFields = {
|
|
7
|
+
reviewId: z.string(),
|
|
8
|
+
workflowId: z.string(),
|
|
9
|
+
artifact: z.unknown().nonoptional(),
|
|
10
|
+
reviewType: z.string(),
|
|
11
|
+
reviewers: z.array(z.string()),
|
|
12
|
+
allowPartial: z.boolean(),
|
|
13
|
+
timeout: z.number().optional(),
|
|
14
|
+
webhookUrl: z.string().optional(),
|
|
15
|
+
createdAt: z.number()
|
|
16
|
+
}, reviewDecisionFields = {
|
|
17
|
+
decision: z.enum(["approved", "rejected", "needs-changes"]),
|
|
18
|
+
reviewer: z.string(),
|
|
19
|
+
feedback: z.string().optional(),
|
|
20
|
+
sectionDecisions: z.record(z.string(), z.enum(["approved", "rejected"])).optional(),
|
|
21
|
+
timestamp: z.number()
|
|
22
|
+
};
|
|
23
|
+
export const reviewRequestSchema = z.object(reviewRequestFields), pendingReviewEntrySchema = z.object({
|
|
24
|
+
status: z.literal("pending"),
|
|
25
|
+
...reviewRequestFields
|
|
26
|
+
}), completedReviewEntrySchema = z.object({
|
|
27
|
+
status: z.literal("completed"),
|
|
28
|
+
...reviewRequestFields,
|
|
29
|
+
...reviewDecisionFields
|
|
30
|
+
}), reviewListEntrySchema = z.union([
|
|
31
|
+
pendingReviewEntrySchema,
|
|
32
|
+
completedReviewEntrySchema
|
|
33
|
+
]);
|
|
5
34
|
|
|
6
35
|
export class ReviewTimeoutError extends WeftError {
|
|
7
36
|
reviewId;
|
|
@@ -181,14 +181,13 @@ export type ScheduleDefinition<TInput = unknown> = ScheduleSpec & {
|
|
|
181
181
|
*/
|
|
182
182
|
export declare function schedule<TInput>(definition: ScheduleDefinition<TInput>): ScheduleDefinition<TInput>;
|
|
183
183
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
184
|
+
* Metadata shared by persisted schedule state and lightweight schedule summaries.
|
|
185
|
+
* Persisted state and summaries extend this contract so metadata cannot drift
|
|
186
|
+
* between durable records and public lightweight responses.
|
|
187
187
|
*/
|
|
188
|
-
export interface
|
|
188
|
+
export interface ScheduleMetadata {
|
|
189
189
|
id: string;
|
|
190
190
|
workflowType: string;
|
|
191
|
-
input: unknown;
|
|
192
191
|
/** Human-readable operator description stored with this schedule. */
|
|
193
192
|
description?: string;
|
|
194
193
|
/**
|
|
@@ -220,38 +219,21 @@ export interface ScheduleState {
|
|
|
220
219
|
/** Ordered durable occurrences waiting behind `currentWorkflowId`. */
|
|
221
220
|
queuedRuns: ScheduleQueuedRun[];
|
|
222
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Full persisted state of a recurring schedule. Returned by `engine.getSchedule(id)`.
|
|
224
|
+
* Use {@link ScheduleSummary} (returned by list operations and `engine.getSchedule()`)
|
|
225
|
+
* for the lightweight variant — it omits `input` to keep payloads small.
|
|
226
|
+
*/
|
|
227
|
+
export interface ScheduleState extends ScheduleMetadata {
|
|
228
|
+
input: unknown;
|
|
229
|
+
}
|
|
223
230
|
/**
|
|
224
231
|
* Lightweight summary of a recurring schedule returned by list operations.
|
|
225
232
|
* Contains cron expression, status, timing metadata, and the ID of the
|
|
226
233
|
* currently running workflow (if any). For the full record including the
|
|
227
234
|
* `input`, use {@link ScheduleState}.
|
|
228
235
|
*/
|
|
229
|
-
export interface ScheduleSummary {
|
|
230
|
-
id: string;
|
|
231
|
-
workflowType: string;
|
|
232
|
-
/** Human-readable operator description stored with this schedule. */
|
|
233
|
-
description?: string;
|
|
234
|
-
/** Cron expression for cron-based schedules; absent for interval schedules. */
|
|
235
|
-
cronExpression?: string;
|
|
236
|
-
/** Interval period in milliseconds for interval-based schedules; absent for cron schedules. */
|
|
237
|
-
intervalMs?: number;
|
|
238
|
-
status: ScheduleStatus;
|
|
239
|
-
overlap: ScheduleOverlapPolicy;
|
|
240
|
-
backfill: boolean;
|
|
241
|
-
/** Normalized deterministic jitter window in milliseconds. */
|
|
242
|
-
jitterMs?: number;
|
|
243
|
-
createdAt: number;
|
|
244
|
-
updatedAt: number;
|
|
245
|
-
/** Most recent occurrence that started a scheduled workflow. */
|
|
246
|
-
lastFireAt?: number;
|
|
247
|
-
/** Most recent occurrence skipped because a non-backfill timer was late. */
|
|
248
|
-
lastMissedFireAt?: number;
|
|
249
|
-
/** Lifetime count of occurrences skipped because a non-backfill timer was late. */
|
|
250
|
-
missedFireCount: number;
|
|
251
|
-
nextFireAt: number | null;
|
|
252
|
-
currentWorkflowId?: string;
|
|
253
|
-
/** Ordered durable occurrences waiting behind `currentWorkflowId`. */
|
|
254
|
-
queuedRuns: ScheduleQueuedRun[];
|
|
236
|
+
export interface ScheduleSummary extends ScheduleMetadata {
|
|
255
237
|
}
|
|
256
238
|
/**
|
|
257
239
|
* Filter criteria for `engine.listSchedules`. All fields are optional.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ZodIssue } from 'zod';
|
|
2
|
+
/** A flattened Zod issue suitable for cross-transport serialization. */
|
|
3
|
+
export type ValidationIssue = {
|
|
4
|
+
readonly path: ReadonlyArray<string | number>;
|
|
5
|
+
readonly message: string;
|
|
6
|
+
readonly code: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Convert a Zod issue into the stable diagnostic shape used by core validators.
|
|
10
|
+
* Path segments outside the JSON-friendly string and number forms are rendered
|
|
11
|
+
* with their string representation, preserving the original issue order.
|
|
12
|
+
*/
|
|
13
|
+
export declare function flattenZodIssue(issue: ZodIssue): ValidationIssue;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function flattenZodIssue(issue) {
|
|
2
|
+
const path = [];
|
|
3
|
+
for (const segment of issue.path)
|
|
4
|
+
if (typeof segment === "string" || typeof segment === "number")
|
|
5
|
+
path.push(segment);
|
|
6
|
+
else
|
|
7
|
+
path.push(String(segment));
|
|
8
|
+
return { path, message: issue.message, code: issue.code };
|
|
9
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Design-time workflow validation for `weft validate`.
|
|
3
3
|
*
|
|
4
|
-
* Analyses workflow
|
|
4
|
+
* Analyses workflow definitions for common anti-patterns:
|
|
5
5
|
*
|
|
6
6
|
* 1. **Unbounded retry policy** — an activity whose `retry.maxAttempts` is
|
|
7
7
|
* `Infinity` (or the workflow registration specifies `retry.maxAttempts`
|
|
@@ -21,27 +21,7 @@
|
|
|
21
21
|
*
|
|
22
22
|
* @module diagnostics/validate
|
|
23
23
|
*/
|
|
24
|
-
import type {
|
|
25
|
-
import type { ActivityDefinition, DefinitionSchema, RetentionPolicy, SearchAttributeSchema, WorkflowFunction } from '../core/types.ts';
|
|
26
|
-
/**
|
|
27
|
-
* Loosely-typed workflow registration shape used only by the `weft validate`
|
|
28
|
-
* and `weft schedule` CLIs when loading workflow modules from disk. This is
|
|
29
|
-
* intentionally separate from the public `WorkflowDefinition` type because
|
|
30
|
-
* loaded modules historically export bare `{ handler, ... }` objects that
|
|
31
|
-
* do not carry a `name` field — the registration key comes from the export
|
|
32
|
-
* key, not the object itself.
|
|
33
|
-
*/
|
|
34
|
-
export interface WorkflowRegistration<TInput = unknown, TOutput = unknown> {
|
|
35
|
-
version?: string;
|
|
36
|
-
description?: string;
|
|
37
|
-
tags?: ReadonlyArray<string>;
|
|
38
|
-
inputSchema?: DefinitionSchema<unknown, TInput>;
|
|
39
|
-
outputSchema?: DefinitionSchema<unknown, TOutput>;
|
|
40
|
-
handler: WorkflowFunction<TInput, TOutput>;
|
|
41
|
-
searchAttributes?: SearchAttributeSchema;
|
|
42
|
-
retention?: RetentionPolicy;
|
|
43
|
-
constraints?: ConstraintDefinition[];
|
|
44
|
-
}
|
|
24
|
+
import type { ActivityDefinition, WorkflowDefinition } from '../core/types.ts';
|
|
45
25
|
export type ValidationIssueSeverity = 'error' | 'warning';
|
|
46
26
|
export type ValidationIssueCode = 'unbounded-retry' | 'stateful-without-compensator' | 'non-serializable-input';
|
|
47
27
|
export interface ValidationIssue {
|
|
@@ -52,7 +32,7 @@ export interface ValidationIssue {
|
|
|
52
32
|
message: string;
|
|
53
33
|
}
|
|
54
34
|
export interface ValidationReport {
|
|
55
|
-
/** Total number of workflow
|
|
35
|
+
/** Total number of workflow definitions scanned. */
|
|
56
36
|
workflowCount: number;
|
|
57
37
|
/** All detected issues across all registrations. */
|
|
58
38
|
issues: ValidationIssue[];
|
|
@@ -60,16 +40,15 @@ export interface ValidationReport {
|
|
|
60
40
|
valid: boolean;
|
|
61
41
|
}
|
|
62
42
|
/**
|
|
63
|
-
* Validate a collection of workflow
|
|
43
|
+
* Validate a collection of workflow definitions for common anti-patterns.
|
|
64
44
|
*
|
|
65
|
-
* @param registrations A record of workflow type name
|
|
66
|
-
* @param activities Optional
|
|
67
|
-
*
|
|
68
|
-
* alone, so pass them explicitly when available.
|
|
45
|
+
* @param registrations A record of workflow type name to WorkflowDefinition.
|
|
46
|
+
* @param activities Optional standalone ActivityDefinition objects to check
|
|
47
|
+
* in addition to activities embedded in workflow definitions.
|
|
69
48
|
*/
|
|
70
|
-
export declare function validateRegistrations(registrations: Record<string,
|
|
49
|
+
export declare function validateRegistrations(registrations: Record<string, WorkflowDefinition>, activities?: ActivityDefinition[]): ValidationReport;
|
|
71
50
|
export declare function loadRegistrationsFromModule(modulePath: string): Promise<{
|
|
72
|
-
registrations: Record<string,
|
|
51
|
+
registrations: Record<string, WorkflowDefinition>;
|
|
73
52
|
activities: ActivityDefinition[];
|
|
74
53
|
}>;
|
|
75
54
|
/**
|