@lostgradient/weft 0.8.0 → 0.10.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.
Files changed (155) hide show
  1. package/README.md +9 -5
  2. package/dist/alerting/alert-manager.d.ts +3 -1
  3. package/dist/alerting/alert-manager.js +5 -2
  4. package/dist/cli/generated/operation-client.generated.d.ts +1 -0
  5. package/dist/cli-main.js +78 -78
  6. package/dist/core/context/durable-operations.js +1 -1
  7. package/dist/core/context/index.d.ts +3 -1
  8. package/dist/core/context/index.js +10 -0
  9. package/dist/core/context/operation-request.d.ts +4 -0
  10. package/dist/core/context/parallel-cache-entry.d.ts +1 -1
  11. package/dist/core/context/parallel-cache-entry.js +12 -8
  12. package/dist/core/context/parallel-operations.d.ts +1 -1
  13. package/dist/core/context/parallel-operations.js +50 -8
  14. package/dist/core/context/run-operation.js +3 -2
  15. package/dist/core/context/speculative-child.js +1 -0
  16. package/dist/core/context/types.d.ts +1 -0
  17. package/dist/core/engine/activity-heartbeat-tracking.d.ts +1 -1
  18. package/dist/core/engine/activity-heartbeat-tracking.js +5 -1
  19. package/dist/core/engine/anonymous-signal-sequence.js +0 -2
  20. package/dist/core/engine/async-activity-completion.d.ts +24 -54
  21. package/dist/core/engine/async-activity-completion.js +25 -90
  22. package/dist/core/engine/async-activity-records.d.ts +106 -0
  23. package/dist/core/engine/async-activity-records.js +124 -0
  24. package/dist/core/engine/bulk-operations-purge.js +2 -1
  25. package/dist/core/engine/bulk-operations.js +10 -29
  26. package/dist/core/engine/callback-creators-bundles.js +1 -1
  27. package/dist/core/engine/callback-creators-core.js +1 -0
  28. package/dist/core/engine/construction.d.ts +1 -3
  29. package/dist/core/engine/construction.js +2 -5
  30. package/dist/core/engine/deferred-consume-envelope.d.ts +10 -1
  31. package/dist/core/engine/deferred-consume-envelope.js +9 -1
  32. package/dist/core/engine/disposal.js +1 -0
  33. package/dist/core/engine/engine-internal-types.d.ts +2 -0
  34. package/dist/core/engine/engine-runtime-helpers.d.ts +8 -0
  35. package/dist/core/engine/engine-runtime-helpers.js +9 -0
  36. package/dist/core/engine/errors.js +1 -1
  37. package/dist/core/engine/index.d.ts +12 -2
  38. package/dist/core/engine/index.js +35 -16
  39. package/dist/core/engine/inline-launch-queue.js +1 -1
  40. package/dist/core/engine/internals.d.ts +25 -3
  41. package/dist/core/engine/lifecycle/fork-helpers.js +1 -0
  42. package/dist/core/engine/lifecycle/recovered-services.d.ts +4 -2
  43. package/dist/core/engine/lifecycle/recovered-services.js +37 -7
  44. package/dist/core/engine/lifecycle/resume.d.ts +2 -2
  45. package/dist/core/engine/lifecycle/resume.js +45 -7
  46. package/dist/core/engine/lifecycle/shared.d.ts +34 -0
  47. package/dist/core/engine/lifecycle/start-exec.d.ts +2 -2
  48. package/dist/core/engine/lifecycle/start-exec.js +6 -4
  49. package/dist/core/engine/lifecycle/start.js +1 -0
  50. package/dist/core/engine/lifecycle/transition.d.ts +1 -1
  51. package/dist/core/engine/lifecycle/transition.js +9 -3
  52. package/dist/core/engine/lifecycle.d.ts +1 -1
  53. package/dist/core/engine/memo-durable-activity.js +8 -10
  54. package/dist/core/engine/operations-activity.d.ts +1 -1
  55. package/dist/core/engine/operations-activity.js +8 -6
  56. package/dist/core/engine/operations-coordination.d.ts +15 -1
  57. package/dist/core/engine/operations-coordination.js +43 -10
  58. package/dist/core/engine/operations-time.d.ts +2 -2
  59. package/dist/core/engine/operations-time.js +40 -6
  60. package/dist/core/engine/ownership-options.d.ts +1 -0
  61. package/dist/core/engine/ownership-options.js +14 -0
  62. package/dist/core/engine/retention.js +4 -0
  63. package/dist/core/engine/schedule-run-metadata.d.ts +3 -0
  64. package/dist/core/engine/schedule-run-metadata.js +29 -0
  65. package/dist/core/engine/schedule-run.js +19 -4
  66. package/dist/core/engine/schedules.js +7 -3
  67. package/dist/core/engine/sub-operation.js +6 -13
  68. package/dist/core/engine/termination/cleanup.js +18 -14
  69. package/dist/core/engine/termination/finalizer-activity.d.ts +1 -1
  70. package/dist/core/engine/termination/finalizer-activity.js +5 -1
  71. package/dist/core/engine/termination/finalizer.js +1 -1
  72. package/dist/core/engine/validation/schedule-options.d.ts +9 -0
  73. package/dist/core/engine/validation/schedule-options.js +59 -0
  74. package/dist/core/engine/validation/schedule.d.ts +3 -8
  75. package/dist/core/engine/validation/schedule.js +40 -56
  76. package/dist/core/engine/validation.js +1 -0
  77. package/dist/core/execution-strategy.d.ts +1 -0
  78. package/dist/core/inline-execution-strategy.context-options.d.ts +1 -0
  79. package/dist/core/inline-execution-strategy.context-options.js +3 -0
  80. package/dist/core/types/activity.d.ts +11 -0
  81. package/dist/core/types/checkpoint.d.ts +1 -0
  82. package/dist/core/types/options.d.ts +12 -0
  83. package/dist/core/types/schedules.d.ts +10 -0
  84. package/dist/core/types/services-resolution.d.ts +8 -3
  85. package/dist/core/types/state.d.ts +6 -0
  86. package/dist/core/types/workflow-builder.d.ts +2 -2
  87. package/dist/core/types/workflow-context.d.ts +40 -0
  88. package/dist/core/worker-execution-strategy.d.ts +1 -0
  89. package/dist/core/worker-inbound-message.d.ts +1 -0
  90. package/dist/core/worker-inbound-message.js +3 -0
  91. package/dist/index.d.ts +2 -2
  92. package/dist/json-schema.js +2 -2
  93. package/dist/mcp/cli.js +32 -32
  94. package/dist/observability/index.js +2 -2
  95. package/dist/runtime/portable.d.ts +1 -1
  96. package/dist/server/authorization.d.ts +3 -3
  97. package/dist/server/fault-to-json-rpc.d.ts +2 -1
  98. package/dist/server/handler.js +28 -28
  99. package/dist/server/index.d.ts +2 -0
  100. package/dist/server/index.js +30 -30
  101. package/dist/server/json-rpc-dispatch.d.ts +2 -2
  102. package/dist/server/json-rpc-parse.d.ts +1 -1
  103. package/dist/server/json-rpc-protocol.d.ts +2 -2
  104. package/dist/server/json-rpc-websocket.d.ts +1 -1
  105. package/dist/server/operation-fault.d.ts +3 -1
  106. package/dist/server/operations/async-activity.js +2 -2
  107. package/dist/server/operations/create-schedule.d.ts +2 -0
  108. package/dist/server/operations/create-schedule.js +13 -2
  109. package/dist/server/principal.d.ts +2 -2
  110. package/dist/server/rest-binding.d.ts +1 -1
  111. package/dist/server/runtime/task-dispatch.js +6 -0
  112. package/dist/server/runtime/task-polling.js +9 -1
  113. package/dist/server/runtime/task-reconciliation.js +2 -1
  114. package/dist/server/stdio-session.d.ts +4 -4
  115. package/dist/server/task-queue-types.d.ts +2 -0
  116. package/dist/server/task-state.d.ts +4 -0
  117. package/dist/service-worker/index.d.ts +15 -14
  118. package/dist/service-worker/index.js +28 -28
  119. package/dist/service-worker/scheduler.d.ts +41 -1
  120. package/dist/storage/auto.d.ts +36 -18
  121. package/dist/storage/auto.js +1 -1
  122. package/dist/storage/compressed-storage.js +1 -1
  123. package/dist/storage/http.js +2 -2
  124. package/dist/storage/index.d.ts +1 -0
  125. package/dist/storage/indexeddb.d.ts +6 -1
  126. package/dist/storage/indexeddb.js +1 -1
  127. package/dist/storage/interface.d.ts +1 -0
  128. package/dist/storage/interface.js +1 -1
  129. package/dist/storage/lmdb.js +1 -1
  130. package/dist/storage/memory.js +1 -1
  131. package/dist/storage/neon.js +1 -1
  132. package/dist/storage/resolve.js +1 -1
  133. package/dist/storage/scoped-storage.js +1 -1
  134. package/dist/storage/testing.js +1 -1
  135. package/dist/storage/turso.js +1 -1
  136. package/dist/storage/typed-storage.js +1 -1
  137. package/dist/storage/web-extension.d.ts +1 -1
  138. package/dist/storage/web-extension.js +1 -1
  139. package/dist/testing/index.js +33 -33
  140. package/dist/version.d.ts +1 -1
  141. package/dist/version.js +1 -1
  142. package/dist/worker/execute-with-interceptors.d.ts +9 -3
  143. package/dist/worker/execute-with-interceptors.js +14 -2
  144. package/dist/worker/long-poll.d.ts +2 -1
  145. package/dist/worker/long-poll.js +1 -1
  146. package/dist/worker/protocol-messages.d.ts +2 -0
  147. package/dist/worker/protocol-schemas.d.ts +8 -0
  148. package/dist/worker/protocol-schemas.js +1 -0
  149. package/dist/worker/protocol.js +1 -1
  150. package/dist/worker/remote-activity-context.d.ts +2 -0
  151. package/dist/workers/activity-runner.d.ts +2 -0
  152. package/dist/workers/activity-runner.js +9 -1
  153. package/dist/workers/workflow-runner.d.ts +2 -1
  154. package/dist/workers/workflow-runner.js +1 -0
  155. package/package.json +2 -2
@@ -5,8 +5,8 @@
5
5
  * body, resolves each request via `executeOperation`, and produces the
6
6
  * wire-level response shape.
7
7
  *
8
- * Track 8 design decision 13: batches dispatch SEQUENTIALLY in request
9
- * order. Response order matches request order by construction —
8
+ * The stable JSON-RPC operation-catalog contract mandates sequential dispatch
9
+ * in request order. Response order matches request order by construction —
10
10
  * notifications are dropped from the response array, so the returned
11
11
  * indices are the non-notification request indices.
12
12
  *
@@ -3,7 +3,7 @@
3
3
  * parsed JSON) and returns a discriminated-union `ParseResult` that
4
4
  * describes what the transport should dispatch.
5
5
  *
6
- * Track 8 design decisions this parser enforces:
6
+ * The stable JSON-RPC operation-catalog contract enforces:
7
7
  * - `params` MUST be absent or a JSON object. Array-form positional
8
8
  * params are rejected with `InvalidRequest` (-32600). This matches
9
9
  * OpenRPC's `paramStructure: "by-name"` contract and eliminates a
@@ -10,8 +10,8 @@
10
10
  * - Runtime stdio session (`stdio-session.ts`, Phase 13)
11
11
  *
12
12
  * Reserved-spec error codes (-32700..-32603) keep their JSON-RPC 2.0
13
- * meanings. Weft domain codes live in the -32010..-32099 band per
14
- * Track 8 design decision 4.
13
+ * meanings. Weft domain codes live in the -32010..-32099 band; this stable
14
+ * error-code allocation preserves compatibility across JSON-RPC transports.
15
15
  */
16
16
  /** Literal `"2.0"` — the only `jsonrpc` version this runtime accepts. */
17
17
  export declare const JSON_RPC_VERSION: "2.0";
@@ -5,7 +5,7 @@
5
5
  * that binds the authenticated principal at upgrade time and reuses it
6
6
  * for every frame. The session:
7
7
  * - Parses incoming frames as single JSON-RPC requests (batches over
8
- * WS are rejected per Track 8 design decision 13).
8
+ * WS are rejected per stable operation-catalog contract).
9
9
  * - Dispatches `weft.workflows.subscribe` / `weft.workflows.unsubscribe`
10
10
  * as first-class session primitives against the `WorkflowEventFeed`.
11
11
  * - Delegates all other methods to the standard `dispatchJsonRpc`.
@@ -30,7 +30,9 @@
30
30
  * adapters never branch on `data === undefined`. This uniformity is what
31
31
  * lets the exhaustive switch in `extractFaultDataPayload` stay small.
32
32
  *
33
- * See Track 8 design decision 4.
33
+ * The stable fault model with transport-neutral code, message, and typed
34
+ * `data` payload forms the basis of cross-transport parity: every fault is
35
+ * serialized consistently across REST and JSON-RPC transports.
34
36
  */
35
37
  import type { FaultCode } from '../core/fault-code.ts';
36
38
  import type { WeftErrorCode } from '../core/weft-error.ts';
@@ -41,7 +41,7 @@ export const completeAsyncActivityOperation = defineOperation({
41
41
  name: "weft.activities.complete",
42
42
  mcpExposable: !1,
43
43
  summary: "Complete a deferred activity by task token",
44
- description: 'Resolve an out-of-band ("async") activity with a result, resuming its parked workflow as though the activity had returned that result inline. Requires the durable task token announced through the `activity:async-pending` event. Faults with NotFound when the token is unknown or already completed/failed (tokens are single-use), and InvalidParams when the result exceeds the payload size limit.',
44
+ description: 'Resolve an out-of-band ("async") activity with a result, resuming its parked workflow as though the activity had returned that result inline. Requires the durable task token announced through the `activity:async-pending` event. Faults with NotFound when the token is unknown or already completed/failed (tokens are single-use), and InvalidParams when the result exceeds the payload size limit. ' + "A success response is durable \u2014 the completion is persisted before the operation " + "returns, and a crash afterward cannot lose it. A failed call leaves the token completable, so treat storage-side faults as retryable.",
45
45
  destructive: !0,
46
46
  tags: ["Activities"],
47
47
  inputSchema: completeAsyncActivityInput,
@@ -63,7 +63,7 @@ export const completeAsyncActivityOperation = defineOperation({
63
63
  name: "weft.activities.fail",
64
64
  mcpExposable: !1,
65
65
  summary: "Fail a deferred activity by task token",
66
- description: 'Fail an out-of-band ("async") activity, throwing the supplied error into its ' + "parked workflow at the deferred step \u2014 identical to an inline activity that threw, " + "so the workflow\u2019s own try/catch and retry policy apply unchanged. Requires the " + "durable task token from the `activity:async-pending` event. Faults with NotFound when the token is unknown or already completed/failed (tokens are single-use), and InvalidParams when the failure message exceeds the payload size limit.",
66
+ description: 'Fail an out-of-band ("async") activity, throwing the supplied error into its ' + "parked workflow at the deferred step \u2014 identical to an inline activity that threw, " + "so the workflow\u2019s own try/catch and retry policy apply unchanged. Requires the " + "durable task token from the `activity:async-pending` event. Faults with NotFound when the token is unknown or already completed/failed (tokens are single-use), and InvalidParams when the failure message exceeds the payload size limit. " + "A success response is durable \u2014 the failure outcome is persisted before the " + "operation returns, and a crash afterward cannot lose it. A failed call leaves the token completable, so treat storage-side faults as retryable.",
67
67
  destructive: !0,
68
68
  tags: ["Activities"],
69
69
  inputSchema: failAsyncActivityInput,
@@ -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
@@ -9,12 +9,12 @@
9
9
  * Credential *validation* (signature verification, expiry, revocation, format
10
10
  * checks) is the transport edge's responsibility — these factories assume the
11
11
  * inputs they receive describe a credential that has already been accepted.
12
+ * This stable principal model ensures consistent authentication across all
13
+ * transport layers.
12
14
  *
13
15
  * The discriminator string for API keys is `'api-key'` (kebab-case) to match
14
16
  * the existing `AuthMethod` literal in `authentication.ts`. Keep them aligned;
15
17
  * the bridge from `AuthResult` to `Principal` relies on byte-identical strings.
16
- *
17
- * See Track 8 design decisions 3 and 10.
18
18
  */
19
19
  import { type AuthorizationScope } from './authorization-scope.ts';
20
20
  /**
@@ -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, not a transitional shim.
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({ ...task, workerId: claim.workerId, attemptToken: claim.attemptToken });
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;
@@ -2,10 +2,10 @@
2
2
  * Runtime JSON-RPC stdio session.
3
3
  *
4
4
  * `runStdioSession({ input, output, admission, registry, engine, feed, ... })`
5
- * drives the `weft rpc-stdio` CLI subcommand (Track 8 design decision
6
- * 19). It reads newline-delimited JSON frames from `input`, runs each
7
- * through the same `createJsonRpcWebSocketSession` session the WS
8
- * adapter uses, and writes responses to `output`.
5
+ * drives the `weft rpc-stdio` CLI subcommand. It implements the stable
6
+ * JSON-RPC stdio transport: reading newline-delimited JSON frames from
7
+ * `input`, running each through the JSON-RPC dispatcher, and writing
8
+ * responses to `output`.
9
9
  *
10
10
  * Admission is mandatory:
11
11
  * - `{ kind: 'startup-token', token }` — the first frame must be a
@@ -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
- * // In your Service Worker (with a scheduler from the runtime that imports it):
86
- * declare const scheduler: { tick(): Promise<void> };
87
- * const handler = createPeriodicSyncHandler(
88
- * scheduler as Parameters<typeof createPeriodicSyncHandler>[0],
89
- * 'weft-timers',
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
  * ```