@lostgradient/weft 0.7.0 → 0.9.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 +9 -3
- package/dist/cli/generated/operation-client.generated.d.ts +1 -0
- package/dist/cli-main.js +78 -78
- package/dist/core/context/activity-retry-state.d.ts +6 -5
- package/dist/core/context/activity-retry-state.js +31 -21
- package/dist/core/context/durable-activity.d.ts +117 -0
- package/dist/core/context/durable-activity.js +79 -0
- package/dist/core/context/durable-operations.js +1 -1
- package/dist/core/context/index.d.ts +1 -0
- package/dist/core/context/index.js +2 -0
- package/dist/core/context/operation-request.d.ts +17 -0
- package/dist/core/context/parallel-operations.js +1 -0
- package/dist/core/context/run-operation-cached-request.d.ts +8 -0
- package/dist/core/context/run-operation-cached-request.js +59 -0
- package/dist/core/context/run-operation.d.ts +23 -5
- package/dist/core/context/run-operation.js +63 -47
- package/dist/core/context/speculative-child.js +1 -0
- package/dist/core/context/types.d.ts +1 -0
- package/dist/core/engine/activity-heartbeat-tracking.d.ts +8 -17
- package/dist/core/engine/activity-heartbeat-tracking.js +12 -2
- package/dist/core/engine/activity-reconciliation.d.ts +1 -0
- package/dist/core/engine/activity-reconciliation.js +7 -2
- package/dist/core/engine/anonymous-signal-sequence.js +6 -6
- package/dist/core/engine/async-activity-completion.d.ts +5 -7
- package/dist/core/engine/async-activity-completion.js +13 -9
- package/dist/core/engine/bulk-operations-purge.js +2 -1
- package/dist/core/engine/bulk-operations.js +18 -36
- package/dist/core/engine/callback-checkpoint-persistence.d.ts +3 -0
- package/dist/core/engine/callback-checkpoint-persistence.js +25 -0
- package/dist/core/engine/callback-creators-bundles.js +5 -2
- package/dist/core/engine/checkpoint-io.d.ts +4 -1
- package/dist/core/engine/checkpoint-io.js +19 -10
- package/dist/core/engine/completed-review-storage.d.ts +2 -1
- package/dist/core/engine/completed-review-storage.js +4 -3
- package/dist/core/engine/disposal.js +1 -0
- package/dist/core/engine/engine-internal-types.d.ts +1 -0
- package/dist/core/engine/index.d.ts +31 -0
- package/dist/core/engine/index.js +19 -10
- package/dist/core/engine/inline-launch-queue.js +1 -1
- package/dist/core/engine/internals.d.ts +25 -2
- package/dist/core/engine/lease-manager.js +2 -2
- package/dist/core/engine/lifecycle/fork-helpers.js +1 -0
- package/dist/core/engine/lifecycle/resume.js +6 -0
- package/dist/core/engine/lifecycle/start-exec.d.ts +2 -2
- package/dist/core/engine/lifecycle/start-exec.js +6 -4
- package/dist/core/engine/lifecycle/start.js +1 -0
- package/dist/core/engine/lifecycle/transition.js +6 -0
- package/dist/core/engine/memo-durable-activity.d.ts +11 -0
- package/dist/core/engine/memo-durable-activity.js +282 -0
- package/dist/core/engine/operations-activity.d.ts +6 -2
- package/dist/core/engine/operations-activity.js +24 -10
- package/dist/core/engine/operations-data.d.ts +4 -1
- package/dist/core/engine/operations-data.js +3 -3
- package/dist/core/engine/operations-time.d.ts +2 -2
- package/dist/core/engine/operations-time.js +40 -6
- package/dist/core/engine/reviews.js +7 -4
- package/dist/core/engine/schedule-timer.js +2 -0
- package/dist/core/engine/schedules.js +3 -0
- package/dist/core/engine/storage-io.js +1 -1
- package/dist/core/engine/termination/cleanup.js +15 -13
- package/dist/core/engine/termination/finalizer-activity.d.ts +1 -1
- package/dist/core/engine/termination/finalizer-activity.js +5 -1
- package/dist/core/engine/termination/finalizer.js +1 -1
- package/dist/core/engine/validation/schedule-options.d.ts +9 -0
- package/dist/core/engine/validation/schedule-options.js +59 -0
- package/dist/core/engine/validation/schedule.d.ts +3 -8
- package/dist/core/engine/validation/schedule.js +40 -56
- package/dist/core/engine/validation.js +1 -0
- package/dist/core/execution-strategy.d.ts +1 -0
- package/dist/core/inline-execution-strategy.context-options.d.ts +1 -0
- package/dist/core/inline-execution-strategy.context-options.js +3 -0
- package/dist/core/json.js +1 -1
- package/dist/core/types/activity.d.ts +11 -0
- package/dist/core/types/checkpoint.d.ts +1 -0
- package/dist/core/types/schedules.d.ts +10 -0
- package/dist/core/types/state.d.ts +6 -0
- package/dist/core/types/workflow-context.d.ts +13 -0
- package/dist/core/weft-error.d.ts +1 -1
- package/dist/core/weft-error.js +2 -0
- package/dist/core/worker-execution-strategy.d.ts +1 -0
- package/dist/core/worker-inbound-message.d.ts +1 -0
- package/dist/core/worker-inbound-message.js +3 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +6 -0
- package/dist/json-schema.js +2 -2
- package/dist/mcp/cli.js +32 -32
- package/dist/observability/index.js +2 -2
- package/dist/runtime/portable.d.ts +1 -1
- package/dist/server/handler.js +27 -27
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +32 -32
- package/dist/server/operations/create-schedule.d.ts +2 -0
- package/dist/server/operations/create-schedule.js +13 -2
- package/dist/server/rest-binding.d.ts +1 -1
- package/dist/server/runtime/task-dispatch.js +6 -0
- package/dist/server/runtime/task-polling.js +9 -1
- package/dist/server/runtime/task-reconciliation.js +2 -1
- package/dist/server/runtime/websocket-worker.js +7 -2
- package/dist/server/serve-internals.d.ts +28 -0
- package/dist/server/serve-internals.js +4 -2
- package/dist/server/task-queue-types.d.ts +2 -0
- package/dist/server/task-state.d.ts +4 -0
- package/dist/service-worker/index.d.ts +15 -14
- package/dist/service-worker/index.js +28 -28
- package/dist/service-worker/scheduler.d.ts +41 -1
- package/dist/service-worker/setup.d.ts +18 -1
- package/dist/service-worker/setup.js +7 -4
- package/dist/storage/auto.d.ts +36 -18
- package/dist/storage/auto.js +1 -1
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/indexeddb.d.ts +6 -1
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.js +1 -1
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.js +1 -1
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/testing.js +1 -1
- package/dist/storage/turso.js +1 -1
- package/dist/storage/typed-storage.d.ts +1 -1
- package/dist/storage/typed-storage.js +1 -1
- package/dist/storage/web-extension.d.ts +1 -1
- package/dist/storage/web-extension.js +1 -1
- package/dist/testing/index.js +32 -32
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/execute-with-interceptors.d.ts +9 -3
- package/dist/worker/execute-with-interceptors.js +14 -2
- package/dist/worker/long-poll.d.ts +2 -1
- package/dist/worker/long-poll.js +1 -1
- package/dist/worker/protocol-messages.d.ts +2 -0
- package/dist/worker/protocol-schemas.d.ts +8 -0
- package/dist/worker/protocol-schemas.js +1 -0
- package/dist/worker/protocol.js +1 -1
- package/dist/worker/remote-activity-context.d.ts +2 -0
- package/dist/workers/activity-runner.d.ts +2 -0
- package/dist/workers/activity-runner.js +9 -1
- package/dist/workers/workflow-runner.d.ts +2 -1
- package/dist/workers/workflow-runner.js +1 -0
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ declare const createScheduleInput: z.ZodObject<{
|
|
|
6
6
|
every: z.ZodOptional<z.ZodUnknown>;
|
|
7
7
|
input: z.ZodOptional<z.ZodUnknown>;
|
|
8
8
|
id: z.ZodOptional<z.ZodUnknown>;
|
|
9
|
+
description: z.ZodOptional<z.ZodUnknown>;
|
|
9
10
|
overlap: z.ZodOptional<z.ZodUnknown>;
|
|
10
11
|
backfill: z.ZodOptional<z.ZodUnknown>;
|
|
11
12
|
jitter: z.ZodOptional<z.ZodUnknown>;
|
|
@@ -21,6 +22,7 @@ export declare const createScheduleOperation: import("../operation-catalog.ts").
|
|
|
21
22
|
every?: unknown;
|
|
22
23
|
input?: unknown;
|
|
23
24
|
id?: unknown;
|
|
25
|
+
description?: unknown;
|
|
24
26
|
overlap?: unknown;
|
|
25
27
|
backfill?: unknown;
|
|
26
28
|
jitter?: unknown;
|
|
@@ -14,6 +14,7 @@ const VALID_SCHEDULE_OVERLAP_POLICIES = new Set([
|
|
|
14
14
|
every: z.unknown().optional().describe("Interval period (duration string or milliseconds). Supply exactly one of cronExpression or every."),
|
|
15
15
|
input: z.unknown().optional(),
|
|
16
16
|
id: z.unknown().optional(),
|
|
17
|
+
description: z.unknown().optional().describe("Operator-facing schedule description. Runtime validation requires a string."),
|
|
17
18
|
overlap: z.unknown().optional(),
|
|
18
19
|
backfill: z.unknown().optional(),
|
|
19
20
|
jitter: z.unknown().optional()
|
|
@@ -32,6 +33,12 @@ function validateOptionalScheduleFields(input) {
|
|
|
32
33
|
throw invalidParamsFault('Field "id" must be a non-empty string');
|
|
33
34
|
validatedId = input.id;
|
|
34
35
|
}
|
|
36
|
+
let validatedDescription;
|
|
37
|
+
if (input.description !== void 0) {
|
|
38
|
+
if (typeof input.description !== "string")
|
|
39
|
+
throw invalidParamsFault('Field "description" must be a string');
|
|
40
|
+
validatedDescription = input.description;
|
|
41
|
+
}
|
|
35
42
|
let validatedOverlap;
|
|
36
43
|
if (input.overlap !== void 0) {
|
|
37
44
|
if (typeof input.overlap !== "string" || !isScheduleOverlapPolicy(input.overlap))
|
|
@@ -52,14 +59,15 @@ function validateOptionalScheduleFields(input) {
|
|
|
52
59
|
}
|
|
53
60
|
return {
|
|
54
61
|
id: validatedId,
|
|
62
|
+
description: validatedDescription,
|
|
55
63
|
overlap: validatedOverlap,
|
|
56
64
|
backfill: validatedBackfill,
|
|
57
65
|
jitter: validatedJitter
|
|
58
66
|
};
|
|
59
67
|
}
|
|
60
68
|
function validateCreateScheduleInput(input) {
|
|
61
|
-
const { type, spec } = validateRequiredScheduleFields(input), { id, overlap, backfill, jitter } = validateOptionalScheduleFields(input);
|
|
62
|
-
return { type, spec, id, overlap, backfill, jitter };
|
|
69
|
+
const { type, spec } = validateRequiredScheduleFields(input), { id, description, overlap, backfill, jitter } = validateOptionalScheduleFields(input);
|
|
70
|
+
return { type, spec, id, description, overlap, backfill, jitter };
|
|
63
71
|
}
|
|
64
72
|
export const createScheduleOperation = defineOperation({
|
|
65
73
|
name: "weft.schedules.create",
|
|
@@ -77,6 +85,7 @@ export const createScheduleOperation = defineOperation({
|
|
|
77
85
|
invoke: async ({ input, engine }) => {
|
|
78
86
|
const typedEngine = engine, validated = validateCreateScheduleInput(input), options = {
|
|
79
87
|
...validated.id !== void 0 ? { id: validated.id } : {},
|
|
88
|
+
...validated.description !== void 0 ? { description: validated.description } : {},
|
|
80
89
|
...validated.overlap !== void 0 ? { overlap: validated.overlap } : {},
|
|
81
90
|
...validated.backfill !== void 0 ? { backfill: validated.backfill } : {},
|
|
82
91
|
...validated.jitter !== void 0 ? { jitter: validated.jitter } : {}
|
|
@@ -102,6 +111,7 @@ export const createScheduleRestBinding = {
|
|
|
102
111
|
every: { kind: "body-field", bodyField: "every" },
|
|
103
112
|
input: { kind: "body-field", bodyField: "input" },
|
|
104
113
|
id: { kind: "body-field", bodyField: "id" },
|
|
114
|
+
description: { kind: "body-field", bodyField: "description" },
|
|
105
115
|
overlap: { kind: "body-field", bodyField: "overlap" },
|
|
106
116
|
backfill: { kind: "body-field", bodyField: "backfill" },
|
|
107
117
|
jitter: { kind: "body-field", bodyField: "jitter" }
|
|
@@ -124,6 +134,7 @@ export const createScheduleRestBinding = {
|
|
|
124
134
|
every: Object.hasOwn(record, "every") ? record.every : void 0,
|
|
125
135
|
input: record.input,
|
|
126
136
|
id: record.id,
|
|
137
|
+
description: record.description,
|
|
127
138
|
overlap: record.overlap,
|
|
128
139
|
backfill: record.backfill,
|
|
129
140
|
jitter: record.jitter
|
|
@@ -131,7 +131,7 @@ export type RestBinding<Input, Output> = {
|
|
|
131
131
|
* detail (for example, `get-workflow-result` returns the custom message
|
|
132
132
|
* `"Timeout waiting for workflow result"` on a `Timeout`, and `get-stream-chunks`
|
|
133
133
|
* handles `InvalidParams` inline). This per-operation hook is the current
|
|
134
|
-
* contract
|
|
134
|
+
* contract.
|
|
135
135
|
*/
|
|
136
136
|
readonly shapeFault?: (fault: OperationFault) => Response;
|
|
137
137
|
};
|
|
@@ -74,6 +74,7 @@ async function selectAndReserveWorker(context, options, task, queue, visibilityT
|
|
|
74
74
|
visibilityTimeout,
|
|
75
75
|
retryPolicy: task.retryPolicy,
|
|
76
76
|
workflowId: task.workflowId,
|
|
77
|
+
workflowExecutionToken: task.workflowExecutionToken,
|
|
77
78
|
attemptToken
|
|
78
79
|
}, normalizedInflightRecord = await transitionQueuedToInflight(options.engine.storage, task.operationId, inflightRecord, {
|
|
79
80
|
queuedRecord: existingQueuedRecord,
|
|
@@ -86,6 +87,9 @@ async function selectAndReserveWorker(context, options, task, queue, visibilityT
|
|
|
86
87
|
input: task.input === void 0 ? null : task.input,
|
|
87
88
|
attempt: task.attempt ?? 1,
|
|
88
89
|
attemptToken,
|
|
90
|
+
...task.workflowExecutionToken !== void 0 && {
|
|
91
|
+
workflowExecutionToken: task.workflowExecutionToken
|
|
92
|
+
},
|
|
89
93
|
...task.headers ? { headers: task.headers } : {}
|
|
90
94
|
}));
|
|
91
95
|
recordTaskQueueLatencyMetric(context.metricsCollector, normalizedInflightRecord);
|
|
@@ -116,6 +120,7 @@ async function enqueueTaskForLongPoll(context, options, task, queue, visibilityT
|
|
|
116
120
|
retryPolicy: task.retryPolicy,
|
|
117
121
|
queuedAt: Date.now(),
|
|
118
122
|
workflowId: task.workflowId,
|
|
123
|
+
workflowExecutionToken: task.workflowExecutionToken,
|
|
119
124
|
retryCount: Math.max(0, attempt - 1),
|
|
120
125
|
requeueCount: 0
|
|
121
126
|
}, existingQueuedRecord = await readQueuedRecord(options.engine.storage, task.operationId), normalizedQueuedRecord = await markQueued(options.engine.storage, mergeQueuedRecordLifecycle(freshRecord, existingQueuedRecord)), enqueued = context.taskQueue.enqueue(queue, {
|
|
@@ -126,6 +131,7 @@ async function enqueueTaskForLongPoll(context, options, task, queue, visibilityT
|
|
|
126
131
|
retryPolicy: task.retryPolicy,
|
|
127
132
|
visibilityTimeout,
|
|
128
133
|
workflowId: task.workflowId,
|
|
134
|
+
workflowExecutionToken: task.workflowExecutionToken,
|
|
129
135
|
firstQueuedAt: normalizedQueuedRecord.firstQueuedAt,
|
|
130
136
|
lastQueuedAt: normalizedQueuedRecord.lastQueuedAt,
|
|
131
137
|
lastDispatchedAt: normalizedQueuedRecord.lastDispatchedAt,
|
|
@@ -98,6 +98,7 @@ export function createLongPollInflightRecord(queue, task) {
|
|
|
98
98
|
visibilityTimeout,
|
|
99
99
|
retryPolicy: task.retryPolicy,
|
|
100
100
|
workflowId: task.workflowId,
|
|
101
|
+
workflowExecutionToken: task.workflowExecutionToken,
|
|
101
102
|
attemptToken: crypto.randomUUID(),
|
|
102
103
|
firstQueuedAt: task.firstQueuedAt ?? task.enqueuedAt ?? now,
|
|
103
104
|
lastQueuedAt: task.lastQueuedAt ?? task.enqueuedAt ?? now,
|
|
@@ -139,7 +140,14 @@ export async function handleTaskPollRequest(context, options, request, url, prin
|
|
|
139
140
|
const rawTimeout = url.searchParams.get("timeout"), timeout = rawTimeout !== null ? Math.min(Math.max(0, Number(rawTimeout)), MAX_POLL_TIMEOUT) : DEFAULT_POLL_TIMEOUT, task = await context.taskQueue.poll(queue, activities, timeout, request.signal);
|
|
140
141
|
if (task !== null) {
|
|
141
142
|
const claim = await markTaskClaimedByLongPollWorker(context, options, queue, task);
|
|
142
|
-
return Response.json({
|
|
143
|
+
return Response.json({
|
|
144
|
+
...task,
|
|
145
|
+
workerId: claim.workerId,
|
|
146
|
+
attemptToken: claim.attemptToken,
|
|
147
|
+
...task.workflowExecutionToken !== void 0 && {
|
|
148
|
+
workflowExecutionToken: task.workflowExecutionToken
|
|
149
|
+
}
|
|
150
|
+
});
|
|
143
151
|
}
|
|
144
152
|
return new Response(null, { status: 204 });
|
|
145
153
|
}
|
|
@@ -68,7 +68,8 @@ function createRequeuedTaskDispatch(record, nextAttempt) {
|
|
|
68
68
|
queue: record.queue,
|
|
69
69
|
attempt: nextAttempt,
|
|
70
70
|
visibilityTimeout: record.visibilityTimeout,
|
|
71
|
-
workflowId: record.workflowId
|
|
71
|
+
workflowId: record.workflowId,
|
|
72
|
+
workflowExecutionToken: record.workflowExecutionToken
|
|
72
73
|
};
|
|
73
74
|
if (record.retryPolicy !== void 0)
|
|
74
75
|
taskDispatch.retryPolicy = record.retryPolicy;
|
|
@@ -74,11 +74,16 @@ function registerWorker(context, options, ws, message) {
|
|
|
74
74
|
rejectRegistration(ws, "invalid_registration", "Worker registration requires the workers:write scope", message.protocolVersion);
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
|
-
const rawConcurrency = message.concurrency ?? DEFAULT_WORKER_CONCURRENCY, clampedConcurrency = Math.min(Math.max(1, Math.floor(rawConcurrency)), MAX_WORKER_CONCURRENCY), queue = ws.data.queue ?? "default", pendingRequeue = context.pendingWorkerRequeues.get(message.workerId);
|
|
78
|
-
if (
|
|
77
|
+
const rawConcurrency = message.concurrency ?? DEFAULT_WORKER_CONCURRENCY, clampedConcurrency = Math.min(Math.max(1, Math.floor(rawConcurrency)), MAX_WORKER_CONCURRENCY), queue = ws.data.queue ?? "default", pendingRequeue = context.pendingWorkerRequeues.get(message.workerId), isGracePeriodReconnect = pendingRequeue !== void 0;
|
|
78
|
+
if (isGracePeriodReconnect) {
|
|
79
79
|
clearTimeout(pendingRequeue);
|
|
80
80
|
context.pendingWorkerRequeues.delete(message.workerId);
|
|
81
81
|
}
|
|
82
|
+
const existingSocket = context.workerSockets.get(message.workerId);
|
|
83
|
+
if (!isGracePeriodReconnect && existingSocket !== void 0 && existingSocket !== ws) {
|
|
84
|
+
rejectRegistration(ws, "invalid_registration", "workerId is already registered to an active connection", message.protocolVersion);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
82
87
|
ws.data.workerId = message.workerId;
|
|
83
88
|
ws.data.workerRegistered = !0;
|
|
84
89
|
ws.data.workerProtocolVersion = message.protocolVersion;
|
|
@@ -11,6 +11,27 @@ import type { WebSocketData } from './json-rpc-websocket-runtime.ts';
|
|
|
11
11
|
import { createServerWebSocketHandlers } from './runtime/authentication-bridge.ts';
|
|
12
12
|
import type { ServerContext } from './runtime/context.ts';
|
|
13
13
|
import { type EventBroadcastingHandle } from './runtime/event-broadcasting.ts';
|
|
14
|
+
/**
|
|
15
|
+
* Hard ceiling on the raw WebSocket frame size for every connection (worker
|
|
16
|
+
* stream, `/watch`, token `/stream`, and JSON-RPC). Bun's default is 16 MiB;
|
|
17
|
+
* this caps the frame at the transport layer before any JSON parse, so a
|
|
18
|
+
* malicious peer cannot force a 16 MiB parse per message. A bounded 4 MiB parse
|
|
19
|
+
* is not a CPU-burn, so this constant ceiling fully closes the DoS on its own.
|
|
20
|
+
*
|
|
21
|
+
* This is deliberately NOT derived from `payloadSize.maxBytes`. That option is
|
|
22
|
+
* an application-level admission policy measured on the codec-encoded (msgpack)
|
|
23
|
+
* byte length of the bare value, whereas `maxPayloadLength` bounds the raw
|
|
24
|
+
* UTF-8 JSON frame (envelope plus JSON-serialized value) — different units.
|
|
25
|
+
* Tightening the frame limit down to a smaller `payloadSize.maxBytes` would
|
|
26
|
+
* reject legitimate frames whose value is within the admission cap (JSON and
|
|
27
|
+
* envelope overhead inflate the frame past the msgpack value size) with an
|
|
28
|
+
* opaque transport close instead of a clean `PayloadSizeExceededError`, across
|
|
29
|
+
* every shared WebSocket endpoint — for no additional DoS protection. Value
|
|
30
|
+
* size stays enforced by the post-parse admission check.
|
|
31
|
+
*
|
|
32
|
+
* @internal Exported only for test assertions.
|
|
33
|
+
*/
|
|
34
|
+
export declare const WEBSOCKET_MAX_PAYLOAD_BYTES: number;
|
|
14
35
|
/**
|
|
15
36
|
* @internal
|
|
16
37
|
*
|
|
@@ -77,6 +98,13 @@ export declare function cleanupWorkflowIndex(context: ServerContext, operationId
|
|
|
77
98
|
/**
|
|
78
99
|
* Assembles the `Bun.serve()` options object. Separating this avoids a
|
|
79
100
|
* conditional spread (`...(tlsOptions ? { tls } : {})`) inside `serve()`.
|
|
101
|
+
*
|
|
102
|
+
* Sets a constant `maxPayloadLength` of `WEBSOCKET_MAX_PAYLOAD_BYTES` (4 MiB)
|
|
103
|
+
* so Bun rejects oversized frames at the transport layer before any JSON parse
|
|
104
|
+
* occurs. The cap is intentionally a fixed transport-safety ceiling, not
|
|
105
|
+
* derived from `payloadSize.maxBytes` (see that constant's docs for why mixing
|
|
106
|
+
* the raw-frame limit with the application value-size policy would cause false
|
|
107
|
+
* rejections in the wrong unit).
|
|
80
108
|
*/
|
|
81
109
|
export declare function buildBunServeConfig(port: number, hostname: string, development: boolean, routes: Bun.Serve.Routes<WebSocketData, string>, tlsOptions: ReturnType<typeof buildTLSOptions>, fetchHandler: (request: Request) => Promise<Response | undefined>, websocketCallbacks: ReturnType<typeof createServerWebSocketHandlers>): Parameters<typeof Bun.serve<WebSocketData>>[0];
|
|
82
110
|
/**
|
|
@@ -30,7 +30,9 @@ import { DEFAULT_MAX_STREAM_CONNECTIONS_PER_WORKFLOW } from "./runtime/websocket
|
|
|
30
30
|
import { isInflightRecord, withRetry } from "./runtime/websocket-worker.js";
|
|
31
31
|
import { TaskQueue } from "./task-queue.js";
|
|
32
32
|
import { createWorkflowEventFeed } from "./workflow-event-feed.js";
|
|
33
|
-
const RECONCILIATION_MULTIPLIER = 12, DEFAULT_WORKER_RECONNECT_GRACE_PERIOD_MS = 2000, MAX_WORKER_RECONNECT_GRACE_PERIOD_MS = 5000
|
|
33
|
+
const RECONCILIATION_MULTIPLIER = 12, DEFAULT_WORKER_RECONNECT_GRACE_PERIOD_MS = 2000, MAX_WORKER_RECONNECT_GRACE_PERIOD_MS = 5000;
|
|
34
|
+
export const WEBSOCKET_MAX_PAYLOAD_BYTES = 4194304;
|
|
35
|
+
const AUTHENTICATION_REQUIRED_ENVIRONMENT_VARIABLE = "WEFT_SERVER_AUTHENTICATION_REQUIRED";
|
|
34
36
|
export const NO_AUTHENTICATION_WARNING = '[weft] WARNING: server started with NO authentication; all non-public operations are publicly accessible. Configure serve({ auth }) to lock down, or set unauthenticatedAccess: "reject" in production to fail closed.', MCP_ORIGIN_CONFIGURATION_WARNING = '[weft] WARNING: MCP HTTP transport is enabled without publicOrigin or trustedHosts. Cross-origin /mcp requests are rejected, and discovery routes that emit absolute URLs return 503. Configure serve({ publicOrigin: "https://api.example.com" }) or serve({ trustedHosts: ["api.example.com"] }) before exposing the server through a browser or reverse proxy.';
|
|
35
37
|
const NO_AUTHENTICATION_REJECT_ERROR = '[weft] Refusing to start server with no authentication. Configure serve({ auth }) or set unauthenticatedAccess: "allow" only for trusted local development.', NO_AUTHENTICATION_ENVIRONMENT_ERROR = "[weft] Refusing to start server with no authentication because WEFT_SERVER_AUTHENTICATION_REQUIRED requires authentication. Configure serve({ auth }) or unset WEFT_SERVER_AUTHENTICATION_REQUIRED only for trusted local development.", TRUTHY_AUTHENTICATION_REQUIREMENT_VALUES = new Set(["1", "true", "yes", "on"]), FALSY_AUTHENTICATION_REQUIREMENT_VALUES = new Set(["0", "false", "no", "off"]);
|
|
36
38
|
export function clampWorkerReconnectGracePeriod(value) {
|
|
@@ -149,7 +151,7 @@ export function buildBunServeConfig(port, hostname, development, routes, tlsOpti
|
|
|
149
151
|
development,
|
|
150
152
|
routes,
|
|
151
153
|
fetch: fetchHandler,
|
|
152
|
-
websocket: websocketCallbacks
|
|
154
|
+
websocket: { ...websocketCallbacks, maxPayloadLength: WEBSOCKET_MAX_PAYLOAD_BYTES }
|
|
153
155
|
};
|
|
154
156
|
if (tlsOptions)
|
|
155
157
|
config.tls = tlsOptions;
|
|
@@ -13,6 +13,8 @@ export interface PendingTask extends TaskLifecycleFields {
|
|
|
13
13
|
headers?: Record<string, string> | undefined;
|
|
14
14
|
/** Workflow that dispatched this activity. Present when the dispatch included a workflowId. */
|
|
15
15
|
workflowId?: string | undefined;
|
|
16
|
+
/** Durable token for the workflow run that dispatched this activity, when known. */
|
|
17
|
+
workflowExecutionToken?: string | undefined;
|
|
16
18
|
/**
|
|
17
19
|
* Task priority. Higher values are dequeued first. Tasks with equal priority
|
|
18
20
|
* maintain FIFO order. Default: 0. Agent workflow tasks use priority 10.
|
|
@@ -55,6 +55,8 @@ export interface QueuedRecord extends TaskLifecycleFields {
|
|
|
55
55
|
queuedAt: number;
|
|
56
56
|
/** Workflow that dispatched this activity. Present when the dispatch included a workflowId. */
|
|
57
57
|
workflowId?: string | undefined;
|
|
58
|
+
/** Durable token for the workflow run that dispatched this activity, when known. */
|
|
59
|
+
workflowExecutionToken?: string | undefined;
|
|
58
60
|
}
|
|
59
61
|
/** Persisted record for a task in the inflight state. */
|
|
60
62
|
export interface InflightRecord extends TaskLifecycleFields {
|
|
@@ -69,6 +71,8 @@ export interface InflightRecord extends TaskLifecycleFields {
|
|
|
69
71
|
retryPolicy?: RetryPolicy | undefined;
|
|
70
72
|
/** Workflow that dispatched this activity. Present when the dispatch included a workflowId. */
|
|
71
73
|
workflowId?: string | undefined;
|
|
74
|
+
/** Durable token for the workflow run that dispatched this activity, when known. */
|
|
75
|
+
workflowExecutionToken?: string | undefined;
|
|
72
76
|
/**
|
|
73
77
|
* Unique, unguessable token identifying this dispatch attempt. Rotated on every
|
|
74
78
|
* (re-)dispatch because each dispatch writes a fresh InflightRecord. The
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
* @module service-worker
|
|
8
8
|
*/
|
|
9
9
|
import type { Engine } from '../core/engine';
|
|
10
|
-
import type { ServiceWorkerScheduler } from './scheduler';
|
|
10
|
+
import type { ServiceWorkerScheduler } from './scheduler.ts';
|
|
11
11
|
import type { MinimalExtendableEvent, MinimalFetchEvent, MinimalPeriodicSyncEvent } from './shared.ts';
|
|
12
|
+
export { ServiceWorkerScheduler } from './scheduler.ts';
|
|
13
|
+
export type { ServiceWorkerSchedulerOptions } from './scheduler.ts';
|
|
12
14
|
export { buildDelegatedRequest, DEFAULT_PERIODIC_SYNC_TAG, normalizePathPrefix } from './shared.ts';
|
|
13
15
|
export type { MinimalExtendableEvent, MinimalFetchEvent, MinimalPeriodicSyncEvent, } from './shared.ts';
|
|
14
16
|
/**
|
|
@@ -73,21 +75,20 @@ export declare function createFetchHandler(options: ServiceWorkerOptions): (even
|
|
|
73
75
|
* `event.waitUntil(...)` so the sync extends until the tick promise
|
|
74
76
|
* resolves.
|
|
75
77
|
*
|
|
76
|
-
* Note: `ServiceWorkerScheduler` is the parameter type but is not currently
|
|
77
|
-
* re-exported from `@lostgradient/weft/service-worker` — construct the scheduler in the
|
|
78
|
-
* module that imports it directly (e.g. the dashboard runtime) and pass
|
|
79
|
-
* the instance to this factory.
|
|
80
|
-
*
|
|
81
78
|
* @example
|
|
82
79
|
* ```ts
|
|
83
|
-
* import { createPeriodicSyncHandler } from '@lostgradient/weft/service-worker';
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* )
|
|
80
|
+
* import { ServiceWorkerScheduler, createPeriodicSyncHandler } from '@lostgradient/weft/service-worker';
|
|
81
|
+
* import { MemoryStorage } from '@lostgradient/weft';
|
|
82
|
+
*
|
|
83
|
+
* const storage = new MemoryStorage();
|
|
84
|
+
*
|
|
85
|
+
* const scheduler = new ServiceWorkerScheduler({
|
|
86
|
+
* storage,
|
|
87
|
+
* onTimerFired: (entry) => {
|
|
88
|
+
* console.log(`Timer ${entry.id} fired.`);
|
|
89
|
+
* },
|
|
90
|
+
* });
|
|
91
|
+
* const handler = createPeriodicSyncHandler(scheduler, 'weft-timers');
|
|
91
92
|
* // self.addEventListener('periodicsync', handler);
|
|
92
93
|
* console.log(typeof handler); // 'function'
|
|
93
94
|
* ```
|