@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.
- package/README.md +9 -5
- package/dist/alerting/alert-manager.d.ts +3 -1
- package/dist/alerting/alert-manager.js +5 -2
- package/dist/cli/generated/operation-client.generated.d.ts +1 -0
- package/dist/cli-main.js +78 -78
- package/dist/core/context/durable-operations.js +1 -1
- package/dist/core/context/index.d.ts +3 -1
- package/dist/core/context/index.js +10 -0
- package/dist/core/context/operation-request.d.ts +4 -0
- package/dist/core/context/parallel-cache-entry.d.ts +1 -1
- package/dist/core/context/parallel-cache-entry.js +12 -8
- package/dist/core/context/parallel-operations.d.ts +1 -1
- package/dist/core/context/parallel-operations.js +50 -8
- package/dist/core/context/run-operation.js +3 -2
- 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 +1 -1
- package/dist/core/engine/activity-heartbeat-tracking.js +5 -1
- package/dist/core/engine/anonymous-signal-sequence.js +0 -2
- package/dist/core/engine/async-activity-completion.d.ts +24 -54
- package/dist/core/engine/async-activity-completion.js +25 -90
- package/dist/core/engine/async-activity-records.d.ts +106 -0
- package/dist/core/engine/async-activity-records.js +124 -0
- package/dist/core/engine/bulk-operations-purge.js +2 -1
- package/dist/core/engine/bulk-operations.js +10 -29
- package/dist/core/engine/callback-creators-bundles.js +1 -1
- package/dist/core/engine/callback-creators-core.js +1 -0
- package/dist/core/engine/construction.d.ts +1 -3
- package/dist/core/engine/construction.js +2 -5
- package/dist/core/engine/deferred-consume-envelope.d.ts +10 -1
- package/dist/core/engine/deferred-consume-envelope.js +9 -1
- package/dist/core/engine/disposal.js +1 -0
- package/dist/core/engine/engine-internal-types.d.ts +2 -0
- package/dist/core/engine/engine-runtime-helpers.d.ts +8 -0
- package/dist/core/engine/engine-runtime-helpers.js +9 -0
- package/dist/core/engine/errors.js +1 -1
- package/dist/core/engine/index.d.ts +12 -2
- package/dist/core/engine/index.js +35 -16
- package/dist/core/engine/inline-launch-queue.js +1 -1
- package/dist/core/engine/internals.d.ts +25 -3
- package/dist/core/engine/lifecycle/fork-helpers.js +1 -0
- package/dist/core/engine/lifecycle/recovered-services.d.ts +4 -2
- package/dist/core/engine/lifecycle/recovered-services.js +37 -7
- package/dist/core/engine/lifecycle/resume.d.ts +2 -2
- package/dist/core/engine/lifecycle/resume.js +45 -7
- package/dist/core/engine/lifecycle/shared.d.ts +34 -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.d.ts +1 -1
- package/dist/core/engine/lifecycle/transition.js +9 -3
- package/dist/core/engine/lifecycle.d.ts +1 -1
- package/dist/core/engine/memo-durable-activity.js +8 -10
- package/dist/core/engine/operations-activity.d.ts +1 -1
- package/dist/core/engine/operations-activity.js +8 -6
- package/dist/core/engine/operations-coordination.d.ts +15 -1
- package/dist/core/engine/operations-coordination.js +43 -10
- package/dist/core/engine/operations-time.d.ts +2 -2
- package/dist/core/engine/operations-time.js +40 -6
- package/dist/core/engine/ownership-options.d.ts +1 -0
- package/dist/core/engine/ownership-options.js +14 -0
- package/dist/core/engine/retention.js +4 -0
- package/dist/core/engine/schedule-run-metadata.d.ts +3 -0
- package/dist/core/engine/schedule-run-metadata.js +29 -0
- package/dist/core/engine/schedule-run.js +19 -4
- package/dist/core/engine/schedules.js +7 -3
- package/dist/core/engine/sub-operation.js +6 -13
- package/dist/core/engine/termination/cleanup.js +18 -14
- 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/types/activity.d.ts +11 -0
- package/dist/core/types/checkpoint.d.ts +1 -0
- package/dist/core/types/options.d.ts +12 -0
- package/dist/core/types/schedules.d.ts +10 -0
- package/dist/core/types/services-resolution.d.ts +8 -3
- package/dist/core/types/state.d.ts +6 -0
- package/dist/core/types/workflow-builder.d.ts +2 -2
- package/dist/core/types/workflow-context.d.ts +40 -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 -2
- 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/authorization.d.ts +3 -3
- package/dist/server/fault-to-json-rpc.d.ts +2 -1
- package/dist/server/handler.js +28 -28
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +30 -30
- package/dist/server/json-rpc-dispatch.d.ts +2 -2
- package/dist/server/json-rpc-parse.d.ts +1 -1
- package/dist/server/json-rpc-protocol.d.ts +2 -2
- package/dist/server/json-rpc-websocket.d.ts +1 -1
- package/dist/server/operation-fault.d.ts +3 -1
- package/dist/server/operations/async-activity.js +2 -2
- package/dist/server/operations/create-schedule.d.ts +2 -0
- package/dist/server/operations/create-schedule.js +13 -2
- package/dist/server/principal.d.ts +2 -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/stdio-session.d.ts +4 -4
- 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/storage/auto.d.ts +36 -18
- package/dist/storage/auto.js +1 -1
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/http.js +2 -2
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/indexeddb.d.ts +6 -1
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.d.ts +1 -0
- 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.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 +33 -33
- 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 +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Weft
|
|
2
2
|
|
|
3
|
-
A Bun-native durable execution engine. Current release: `0.
|
|
3
|
+
A Bun-native durable execution engine. Current release: `0.10.0`.
|
|
4
4
|
|
|
5
5
|
Install the library from npm as `@lostgradient/weft`:
|
|
6
6
|
|
|
@@ -63,7 +63,7 @@ Weft's durability promise is checkpoint-level and explicit:
|
|
|
63
63
|
- Every `yield*` boundary is persisted before the workflow advances to the next durable step.
|
|
64
64
|
- `Engine.create()` recovers by default after registering workflow definitions, so fresh processes resume persisted running workflows without a separate boot hook.
|
|
65
65
|
- Recovery resumes from the last checkpoint position instead of replaying the workflow from the beginning.
|
|
66
|
-
- External activity side effects still need idempotency keys, provider lookup, or
|
|
66
|
+
- External activity side effects still need idempotency keys, provider lookup, verifier logic, or external write fencing. Without that, a crash after the external side effect but before Weft commits the activity result can dispatch the activity again. Weft exposes `workflowExecutionToken` and per-attempt `activityAttemptToken` values so databases you control can reject stale writes from older attempts or replaced runs.
|
|
67
67
|
|
|
68
68
|
The full [Durability Guarantee](documentation/architecture/durability-guarantee.md) separates what is guaranteed today from the Tier-0 activity-reconciliation work that narrows the remaining crash window.
|
|
69
69
|
|
|
@@ -113,7 +113,7 @@ When a workflow needs a live host capability that cannot be checkpointed, pass i
|
|
|
113
113
|
const handle = await engine.start('welcome', { name: 'Steve' }, { services: { crmClient } });
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
Inside inline workflows, read that value from `ctx.services` and narrow it to your application type. Weft never writes the service object into checkpoints; it persists only a presence marker so `Engine.create({ resolveWorkflowServices })` can rebuild the service value during fresh-process recovery before the generator advances. Do not use `services` for durable data, and do not pass it in Worker execution mode — non-serializable values cannot cross to a Worker.
|
|
116
|
+
Inside inline workflows, read that value from `ctx.services` and narrow it to your application type. Weft never writes the service object into checkpoints; it persists only a presence marker so `Engine.create({ resolveWorkflowServices })` can rebuild the service value during fresh-process recovery before the generator advances. Scheduled runs also carry `schedule.id` and, when the grid timestamp is retained, `schedule.occurrence` into the resolver across recovery, so host services can branch on schedule origin without duplicating that identity in workflow input. Do not use `services` for durable data, and do not pass it in Worker execution mode — non-serializable values cannot cross to a Worker.
|
|
117
117
|
|
|
118
118
|
> [!NOTE]
|
|
119
119
|
> The chained builder also accepts `.signals({...})`, `.updates({...})`, `.queries({...})`, and `.searchAttributes({...})`. Each can be called at most once before `.execute(fn)`; the type system flips a phantom flag so a duplicate call fails to typecheck, and the runtime mirrors the same invariant. These maps don't introduce new runtime gating — they're type hints that thread into `ctx.run()`, `ctx.waitForSignal()`, `ctx.waitForUpdate()`, and friends so your editor autocompletes and your code typechecks. The underlying dispatch paths are unchanged.
|
|
@@ -147,7 +147,7 @@ Because recovery never re-executes the workflow from the beginning, your workflo
|
|
|
147
147
|
|
|
148
148
|
### Durable Workflows
|
|
149
149
|
|
|
150
|
-
Generator functions with automatic checkpointing at every `yield*` boundary. Activities, sleeps, signals, condition gates with `ctx.waitUntil()`, queries, updates, structured logs with `ctx.log`, parallel execution via `ctx.all()`, race semantics via `ctx.race()`, memoization via `ctx.memo()`, sagas via `ctx.saga()`, child workflows, and forks. Plain async helpers called from inline `ctx.memo()` callbacks can use `durableActivity()` for activity-level retry, heartbeat, reconciliation, and observability without converting the helper stack to generators. `ctx.all()` and `ctx.race()` can branch over activities, sleeps, and signal waits; use `ctx.race([ctx.waitForSignal(name), ctx.sleep(timeout)])` for signal timeouts instead of placing an unbounded signal wait directly in `ctx.all()`.
|
|
150
|
+
Generator functions with automatic checkpointing at every `yield*` boundary. Activities, sleeps, signals, condition gates with `ctx.waitUntil()`, queries, updates, structured logs with `ctx.log`, parallel execution via `ctx.all()`, race semantics via `ctx.race()`, memoization via `ctx.memo()`, sagas via `ctx.saga()`, child workflows, and forks. Plain async helpers called from inline `ctx.memo()` callbacks can use `durableActivity()` for activity-level retry, heartbeat, reconciliation, and observability without converting the helper stack to generators. `ctx.sleep()` uses replay-stable durable timer keys, so a workflow that crashes while parked on a sleep resumes the same timer instead of orphaning the old one. `ctx.all()` and `ctx.race()` can branch over activities, sleeps, and signal waits; use `ctx.race([ctx.waitForSignal(name), ctx.sleep(timeout)])` for signal timeouts instead of placing an unbounded signal wait directly in `ctx.all()`.
|
|
151
151
|
|
|
152
152
|
Every workflow context exposes `ctx.workflowId` and `ctx.workflowType`. `workflowType` is the registered name from `workflow({ name })`, so shared workflow code can log, tag, or branch on the current workflow type without closing over definition-site state.
|
|
153
153
|
|
|
@@ -342,6 +342,8 @@ A small `Storage` interface over string keys and `Uint8Array` values: five requi
|
|
|
342
342
|
|
|
343
343
|
Bring your own backend by implementing the interface—five methods is enough.
|
|
344
344
|
|
|
345
|
+
For demos and local-first prototypes, `resolveDefaultStorage()` from `@lostgradient/weft/storage/auto` picks a durable default for the current runtime: SQLite under Bun or Node, `WebExtensionStorage` in extension contexts, and `IndexedDBStorage` in browsers and Service Workers. It deliberately throws instead of falling back to `MemoryStorage`, so a "default" engine does not silently lose checkpoints after a restart. Use `resolveStorage({ type: 'auto' })` only when an ephemeral fallback is acceptable.
|
|
346
|
+
|
|
345
347
|
Production recovery needs one engine process per durable store. Use a local durable adapter (`SQLiteStorage` or `LMDBStorage`) when the service owns its disk, or `NeonStorage` when the deployment wants managed Postgres durability and point-in-time restore. In either case, validate the store at boot with `assertDurableStorageForRecovery()` and enforce the singleton topology in infrastructure; the [singleton service deployment guide](documentation/guides/singleton-service-deployment.md) covers the checklist and the optional warn-only second-instance detector.
|
|
346
348
|
|
|
347
349
|
For long-running workflows, `history.retentionWindow` can compact old event-log records behind the latest checkpoint while preserving verification through a durable watermark. `history.maxEvents` remains a lifetime circuit breaker even after compaction. Use `payloadSize.maxBytes` when operators need an admission-time cap on workflow inputs, signal payloads, and activity results before those values reach storage.
|
|
@@ -386,7 +388,9 @@ await worker.connect();
|
|
|
386
388
|
|
|
387
389
|
### Browser Support
|
|
388
390
|
|
|
389
|
-
The core engine runs inside a Web Worker, with a Service Worker acting as the durable persistence layer over `IndexedDB`. Browser-compatible workflow logic ships across server and browser without modification—useful for offline-first apps that need durable client-side workflows. Activities, storage adapters, and other environment-bound pieces still need browser-safe implementations: use `IndexedDBStorage` or `
|
|
391
|
+
The core engine runs inside a Web Worker, with a Service Worker acting as the durable persistence layer over `IndexedDB`. Browser-compatible workflow logic ships across server and browser without modification—useful for offline-first apps that need durable client-side workflows. Activities, storage adapters, and other environment-bound pieces still need browser-safe implementations: use `IndexedDBStorage`, `WebExtensionStorage`, or `resolveDefaultStorage()` instead of SQLite storage, swap server-only activities for `fetch`-based equivalents, and so on.
|
|
392
|
+
|
|
393
|
+
Service Worker deployments can import `ServiceWorkerScheduler` from `@lostgradient/weft/service-worker` and wire timer wakeups through `onTimerFired: (entry) => engine.fireTimer(entry)`. See the [Service Worker guide](documentation/guides/service-worker.md) for the browser runtime wiring and Periodic Background Sync fallback pattern.
|
|
390
394
|
|
|
391
395
|
### Observability
|
|
392
396
|
|
|
@@ -35,7 +35,9 @@ import type { AlertState, AlertingOptions } from './types';
|
|
|
35
35
|
*/
|
|
36
36
|
export declare class AlertManager implements Disposable {
|
|
37
37
|
#private;
|
|
38
|
-
constructor(target: EventTarget, options: AlertingOptions, getNow?: () => number);
|
|
38
|
+
constructor(target: EventTarget, options: AlertingOptions, getNow?: () => number, startBackgroundTick?: boolean);
|
|
39
|
+
/** Re-evaluate every rule once, for hosts that drive maintenance explicitly. */
|
|
40
|
+
tick(): void;
|
|
39
41
|
/** Get current state of all alert rules (for debugging/testing). */
|
|
40
42
|
get states(): readonly AlertState[];
|
|
41
43
|
[Symbol.dispose](): void;
|
|
@@ -18,7 +18,7 @@ export class AlertManager {
|
|
|
18
18
|
#pendingWebhooks;
|
|
19
19
|
#getNow;
|
|
20
20
|
#tickInterval;
|
|
21
|
-
constructor(target, options, getNow = Date.now) {
|
|
21
|
+
constructor(target, options, getNow = Date.now, startBackgroundTick = !0) {
|
|
22
22
|
this.#target = target;
|
|
23
23
|
this.#options = options;
|
|
24
24
|
this.#getNow = getNow;
|
|
@@ -41,7 +41,10 @@ export class AlertManager {
|
|
|
41
41
|
this.#windows.set(i, new HistogramWindow(windowMs));
|
|
42
42
|
}
|
|
43
43
|
this.#subscribeToEvents();
|
|
44
|
-
this.#tickInterval = setInterval(this.#evaluateAll.bind(this), TICK_INTERVAL_MS);
|
|
44
|
+
this.#tickInterval = startBackgroundTick ? setInterval(this.#evaluateAll.bind(this), TICK_INTERVAL_MS) : null;
|
|
45
|
+
}
|
|
46
|
+
tick() {
|
|
47
|
+
this.#evaluateAll();
|
|
45
48
|
}
|
|
46
49
|
#evaluateAll() {
|
|
47
50
|
for (let i = 0;i < this.#options.rules.length; i++)
|
|
@@ -124,6 +124,7 @@ export type CatalogOperationTypes = {
|
|
|
124
124
|
readonly input: {
|
|
125
125
|
readonly backfill?: unknown;
|
|
126
126
|
readonly cronExpression?: unknown;
|
|
127
|
+
readonly description?: unknown;
|
|
127
128
|
readonly every?: unknown;
|
|
128
129
|
readonly id?: unknown;
|
|
129
130
|
readonly input?: unknown;
|