@lostgradient/weft 0.2.1 → 0.3.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 (188) hide show
  1. package/README.md +47 -22
  2. package/dist/cli/generated/operation-client.generated.d.ts +28 -1
  3. package/dist/cli/generated/operation-client.generated.js +2 -0
  4. package/dist/cli-main.js +79 -79
  5. package/dist/client/handle-delegation.d.ts +4 -0
  6. package/dist/client/handle-delegation.js +6 -0
  7. package/dist/client/http-client-requests.d.ts +2 -0
  8. package/dist/client/http-client-requests.js +3 -0
  9. package/dist/client/http-client.d.ts +4 -1
  10. package/dist/client/http-client.js +9 -1
  11. package/dist/client/interface.d.ts +57 -2
  12. package/dist/client/local.d.ts +4 -1
  13. package/dist/client/local.js +7 -0
  14. package/dist/client/start-body.d.ts +7 -1
  15. package/dist/client/start-body.js +13 -4
  16. package/dist/core/codec/extension-codec.js +4 -2
  17. package/dist/core/codec/index.d.ts +1 -0
  18. package/dist/core/codec/index.js +1 -0
  19. package/dist/core/codec/serializer-registry.d.ts +122 -0
  20. package/dist/core/codec/serializer-registry.js +51 -0
  21. package/dist/core/context/index.d.ts +9 -0
  22. package/dist/core/context/internals.d.ts +9 -0
  23. package/dist/core/context/internals.js +3 -0
  24. package/dist/core/context/run-operation.d.ts +16 -3
  25. package/dist/core/context/run-operation.js +16 -7
  26. package/dist/core/engine/bulk-operations.js +1 -1
  27. package/dist/core/engine/construction.d.ts +0 -1
  28. package/dist/core/engine/construction.js +10 -1
  29. package/dist/core/engine/disposal.js +12 -0
  30. package/dist/core/engine/engine-create-types.d.ts +0 -14
  31. package/dist/core/engine/engine-internal-types.d.ts +12 -0
  32. package/dist/core/engine/engine-leak-warnings.d.ts +6 -0
  33. package/dist/core/engine/engine-leak-warnings.js +4 -0
  34. package/dist/core/engine/engine-runtime-helpers.d.ts +17 -0
  35. package/dist/core/engine/engine-runtime-helpers.js +26 -5
  36. package/dist/core/engine/errors.d.ts +74 -0
  37. package/dist/core/engine/errors.js +25 -1
  38. package/dist/core/engine/handle-result.js +1 -1
  39. package/dist/core/engine/handles.d.ts +89 -40
  40. package/dist/core/engine/handles.js +25 -27
  41. package/dist/core/engine/index.d.ts +96 -4
  42. package/dist/core/engine/index.js +75 -4
  43. package/dist/core/engine/inline-launch-queue.d.ts +14 -0
  44. package/dist/core/engine/inline-launch-queue.js +32 -7
  45. package/dist/core/engine/internals.d.ts +18 -10
  46. package/dist/core/engine/lifecycle/fork-helpers.js +1 -7
  47. package/dist/core/engine/lifecycle/persist.js +5 -20
  48. package/dist/core/engine/lifecycle/resume.js +25 -4
  49. package/dist/core/engine/lifecycle/start-commit.d.ts +47 -0
  50. package/dist/core/engine/lifecycle/start-commit.js +27 -0
  51. package/dist/core/engine/lifecycle/start-exec.d.ts +30 -2
  52. package/dist/core/engine/lifecycle/start-exec.js +38 -0
  53. package/dist/core/engine/lifecycle/start-or-signal-resolution.d.ts +79 -0
  54. package/dist/core/engine/lifecycle/start-or-signal-resolution.js +60 -0
  55. package/dist/core/engine/lifecycle/start-or-signal.d.ts +45 -0
  56. package/dist/core/engine/lifecycle/start-or-signal.js +141 -0
  57. package/dist/core/engine/lifecycle/start.d.ts +3 -3
  58. package/dist/core/engine/lifecycle/start.js +31 -37
  59. package/dist/core/engine/lifecycle.d.ts +3 -2
  60. package/dist/core/engine/lifecycle.js +9 -2
  61. package/dist/core/engine/listing.js +1 -1
  62. package/dist/core/engine/persisted-data-version.d.ts +5 -9
  63. package/dist/core/engine/persisted-data-version.js +4 -5
  64. package/dist/core/engine/schedule-handle.d.ts +45 -0
  65. package/dist/core/engine/schedule-handle.js +26 -0
  66. package/dist/core/engine/schedules.d.ts +1 -1
  67. package/dist/core/engine/schedules.js +7 -3
  68. package/dist/core/engine/second-instance-detector.d.ts +96 -0
  69. package/dist/core/engine/second-instance-detector.js +108 -0
  70. package/dist/core/engine/signals.d.ts +22 -0
  71. package/dist/core/engine/signals.js +15 -0
  72. package/dist/core/engine/termination/cleanup.d.ts +25 -0
  73. package/dist/core/engine/termination/cleanup.js +19 -1
  74. package/dist/core/engine/termination/complete.js +4 -3
  75. package/dist/core/engine/termination/suspend.d.ts +68 -0
  76. package/dist/core/engine/termination/suspend.js +41 -0
  77. package/dist/core/engine/termination.d.ts +4 -2
  78. package/dist/core/engine/termination.js +2 -0
  79. package/dist/core/engine/validation.js +25 -1
  80. package/dist/core/engine/workflow-feed.d.ts +5 -3
  81. package/dist/core/events/event-map.d.ts +2 -1
  82. package/dist/core/events/workflow-events.d.ts +23 -0
  83. package/dist/core/events/workflow-events.js +9 -0
  84. package/dist/core/list-filter-validation.js +2 -1
  85. package/dist/core/start-workflow-validation.d.ts +22 -0
  86. package/dist/core/start-workflow-validation.js +11 -1
  87. package/dist/core/step-context.d.ts +10 -6
  88. package/dist/core/step-context.js +7 -15
  89. package/dist/core/types/activity.d.ts +6 -3
  90. package/dist/core/types/identity.d.ts +8 -1
  91. package/dist/core/types/launch-metadata.d.ts +33 -0
  92. package/dist/core/types/launch-metadata.js +0 -0
  93. package/dist/core/types/message-handles.d.ts +25 -0
  94. package/dist/core/types/options.d.ts +48 -54
  95. package/dist/core/types/reviews.d.ts +2 -1
  96. package/dist/core/types/services-resolution.d.ts +47 -0
  97. package/dist/core/types/services-resolution.js +0 -0
  98. package/dist/core/types/state.d.ts +11 -11
  99. package/dist/core/types/workflow-builder.d.ts +5 -4
  100. package/dist/core/types/workflow-function.d.ts +17 -0
  101. package/dist/core/types/workflow-snapshot.d.ts +29 -0
  102. package/dist/core/types/workflow-snapshot.js +0 -0
  103. package/dist/core/types.d.ts +3 -0
  104. package/dist/core/types.js +3 -0
  105. package/dist/core/weft-error.d.ts +1 -1
  106. package/dist/core/weft-error.js +3 -1
  107. package/dist/diagnostics/doctor.js +6 -3
  108. package/dist/diagnostics/format.js +2 -2
  109. package/dist/diagnostics/types.d.ts +1 -0
  110. package/dist/diagnostics/version-check.js +6 -4
  111. package/dist/index.d.ts +4 -4
  112. package/dist/index.js +10 -1
  113. package/dist/json-schema.js +1 -1
  114. package/dist/mcp/cli.js +35 -35
  115. package/dist/mcp/list-filter.js +2 -1
  116. package/dist/mcp/session.js +1 -0
  117. package/dist/observability/index.js +2 -2
  118. package/dist/server/handler.js +30 -30
  119. package/dist/server/index.js +33 -33
  120. package/dist/server/interactive-operations.js +1 -0
  121. package/dist/server/operations/resume-workflow.js +2 -2
  122. package/dist/server/operations/start-or-signal-workflow.d.ts +39 -0
  123. package/dist/server/operations/start-or-signal-workflow.js +140 -0
  124. package/dist/server/operations/start-workflow-options.d.ts +32 -0
  125. package/dist/server/operations/start-workflow-options.js +63 -0
  126. package/dist/server/operations/start-workflow.js +7 -69
  127. package/dist/server/operations/suspend-workflow.d.ts +13 -0
  128. package/dist/server/operations/suspend-workflow.js +36 -0
  129. package/dist/server/rest-binding.d.ts +18 -7
  130. package/dist/server/rest-bindings.js +12 -0
  131. package/dist/server/runtime/task-dispatch.js +5 -3
  132. package/dist/server/runtime/task-polling.d.ts +16 -2
  133. package/dist/server/runtime/task-polling.js +20 -5
  134. package/dist/server/runtime/websocket-worker.js +8 -0
  135. package/dist/server/serve-internals.d.ts +8 -0
  136. package/dist/server/serve-internals.js +4 -2
  137. package/dist/server/task-state.d.ts +8 -0
  138. package/dist/service-worker/index.js +28 -28
  139. package/dist/storage/capabilities.d.ts +10 -2
  140. package/dist/storage/capabilities.js +2 -2
  141. package/dist/storage/http.js +2 -2
  142. package/dist/storage/index.d.ts +6 -1
  143. package/dist/storage/indexeddb.js +1 -1
  144. package/dist/storage/interface.d.ts +26 -0
  145. package/dist/storage/interface.js +1 -1
  146. package/dist/storage/key-prefixes.d.ts +1 -1
  147. package/dist/storage/key-prefixes.js +2 -0
  148. package/dist/storage/lmdb.js +1 -1
  149. package/dist/storage/memory.js +1 -1
  150. package/dist/storage/neon-value-mapping.d.ts +47 -0
  151. package/dist/storage/neon-value-mapping.js +11 -0
  152. package/dist/storage/neon.d.ts +108 -0
  153. package/dist/storage/neon.js +10 -0
  154. package/dist/storage/node-sqlite-loader.d.ts +71 -0
  155. package/dist/storage/node-sqlite-loader.js +41 -0
  156. package/dist/storage/node-sqlite.d.ts +1 -19
  157. package/dist/storage/node-sqlite.js +38 -32
  158. package/dist/storage/postgres-key-value-queries.d.ts +79 -0
  159. package/dist/storage/postgres-key-value-queries.js +63 -0
  160. package/dist/storage/resolve.d.ts +2 -165
  161. package/dist/storage/resolve.js +1 -1
  162. package/dist/storage/scoped-storage.js +1 -1
  163. package/dist/storage/storage-configuration.d.ts +209 -0
  164. package/dist/storage/storage-configuration.js +0 -0
  165. package/dist/storage/text-value-store.d.ts +9 -9
  166. package/dist/storage/turso.js +2 -2
  167. package/dist/storage/typed-storage.js +1 -1
  168. package/dist/storage/web-extension.js +1 -1
  169. package/dist/testing/index.js +33 -33
  170. package/dist/version.d.ts +1 -1
  171. package/dist/version.js +1 -1
  172. package/dist/worker/index.js +9 -5
  173. package/dist/worker/long-poll.js +4 -0
  174. package/dist/worker/protocol-messages.d.ts +20 -0
  175. package/dist/worker/protocol-schemas.d.ts +32 -0
  176. package/dist/worker/protocol-schemas.js +8 -4
  177. package/dist/worker/protocol-task-result.d.ts +28 -0
  178. package/dist/worker/protocol-task-result.js +76 -0
  179. package/dist/worker/protocol.d.ts +4 -15
  180. package/dist/worker/protocol.js +1 -1
  181. package/dist/worker/registry/fair-share.d.ts +29 -0
  182. package/dist/worker/registry/fair-share.js +30 -0
  183. package/dist/worker/registry/routing.d.ts +18 -0
  184. package/dist/worker/registry/routing.js +14 -0
  185. package/dist/worker/registry/types.d.ts +7 -0
  186. package/dist/worker/registry.d.ts +16 -1
  187. package/dist/worker/registry.js +24 -36
  188. package/package.json +17 -4
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Weft
2
2
 
3
- A Bun-native durable execution engine. Current launch version: `0.2.0`.
3
+ A Bun-native durable execution engine. Current release: `0.3.0`.
4
4
 
5
5
  Install the library from npm as `@lostgradient/weft`:
6
6
 
@@ -43,12 +43,12 @@ Weft is a ground-up rethink: what would durable execution look like if you desig
43
43
 
44
44
  ## Stability Tiers
45
45
 
46
- Weft is launching as `0.2.0`, not `1.0`. The table below is the current adoption guidance, not a permanent compatibility guarantee. Surfaces marked **candidate-stable** are expected to carry the 1.0 support promise if the [Tier-0 Behavioral Contract](documentation/architecture/tier-0-behavioral-contract.md) does not force a public-shape change. Tier-0 work may still add error codes, duplicate-response shapes, or storage-capability failures before those surfaces graduate.
46
+ Weft is still pre-1.0. The table below is the current adoption guidance, not a permanent compatibility guarantee. Surfaces marked **candidate-stable** are expected to carry the 1.0 support promise if the [Tier-0 Behavioral Contract](documentation/architecture/tier-0-behavioral-contract.md) does not force a public-shape change. Tier-0 work may still add error codes, duplicate-response shapes, or storage-capability failures before those surfaces graduate.
47
47
 
48
- | Tier | Surfaces | What to expect |
49
- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
50
- | Candidate-stable, provisional | Engine core, [`TestEngine`](documentation/guides/testing.md), Bun SQLite, Node SQLite, LMDB, [`RemoteWorker`](documentation/guides/remote-workers.md), [`serve()`](documentation/guides/server.md) and `/v1` REST, exported public error codes | Suitable for serious trials. Pin the package version and read release notes before upgrading until the 1.0 contract lands. |
51
- | Experimental | [Browser runtime](documentation/guides/service-worker.md), [MCP](documentation/reference/api-server.md#mcp-server), IndexedDB, WebExtension, HTTP and compressed storage, Turso pending conformance proof, CLI commands beyond `serve` and `doctor` when running Weft from source or a standalone binary, [OpenTelemetry](documentation/guides/observability.md) metric names, externally supplied dashboard mounting, [`ctx.step()`](documentation/guides/workflows.md#getting-started-without-generators) sugar | API shape, storage guarantees, diagnostics, or compatibility behavior may change without a deprecation window before 1.0. |
48
+ | Tier | Surfaces | What to expect |
49
+ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
50
+ | Candidate-stable, provisional | Engine core, [`TestEngine`](documentation/guides/testing.md), Bun SQLite, Node SQLite, LMDB, [`RemoteWorker`](documentation/guides/remote-workers.md), [`serve()`](documentation/guides/server.md) and `/v1` REST, source/binary CLI commands `serve`, `doctor`, `version`, `--version`, and `-v`, exported public error codes | Suitable for serious trials. Pin the package version and read release notes before upgrading until the 1.0 contract lands. |
51
+ | Experimental | [Browser runtime](documentation/guides/service-worker.md), [MCP](documentation/reference/api-server.md#mcp-server), IndexedDB, WebExtension, HTTP and compressed storage, Turso pending conformance proof, CLI commands beyond `serve`, `doctor`, `version`, `--version`, and `-v` when running Weft from source or a standalone binary, [OpenTelemetry](documentation/guides/observability.md) metric names, externally supplied dashboard mounting, [`ctx.step()`](documentation/guides/workflows.md#getting-started-without-generators) sugar | API shape, storage guarantees, diagnostics, or compatibility behavior may change without a deprecation window before 1.0. |
52
52
 
53
53
  If a surface is not named here, treat it as experimental. Stability is about compatibility and operational guarantees; it is not a statement that every candidate-stable surface is appropriate for every deployment.
54
54
 
@@ -94,6 +94,14 @@ That's the core loop: `workflow({ name })` is a **chained builder** that co-loca
94
94
 
95
95
  If you'd rather wire things up by hand — useful for tests, isolating engines onto separate storage scopes via `ScopedStorage`, or adding new workflows after the engine starts up — `new Engine({ storage })`, `engine.register(workflow)` or `engine.registerWorkflows({ ... })`, and `await engine.recoverAll()` are the underlying primitives. Each `engine.register(workflow)` call returns the engine with that workflow's name and types baked in, so `engine.start('welcome', ...)` autocompletes immediately.
96
96
 
97
+ When a workflow needs a live host capability that cannot be checkpointed, pass it as per-run `services`:
98
+
99
+ ```typescript
100
+ const handle = await engine.start('welcome', { name: 'Steve' }, { services: { crmClient } });
101
+ ```
102
+
103
+ 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.
104
+
97
105
  > [!NOTE]
98
106
  > 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.
99
107
 
@@ -120,6 +128,7 @@ Because recovery never re-executes the workflow from the beginning, your workflo
120
128
  | **Worker** | A process or thread that executes activities. Inline by default; can run remote over WebSocket. |
121
129
  | **Interceptor** | A composable hook that wraps context operations for tracing, validation, encryption, or any cross-cutting concern. |
122
130
  | **Shared state** | A compare-and-swap (CAS) durable mutable primitive for safe concurrent reads and writes across workflows. |
131
+ | **Idempotent start** | A stable `idempotencyKey` that makes retried starts return the existing run instead of creating duplicates. |
123
132
 
124
133
  ## Features
125
134
 
@@ -188,6 +197,21 @@ for await (const event of tail) {
188
197
 
189
198
  The tail is single-consumer and stops on terminal workflow events or `tail.close()`. In runtimes without a built-in WebSocket, or where authenticated WebSockets need headers the platform constructor cannot send, provide `HttpClientOptions.webSocketFactory`.
190
199
 
200
+ ### Idempotent Starts and Signal-With-Start
201
+
202
+ Retried webhooks and queue deliveries should not double-start workflows. Pass a stable `idempotencyKey` to `engine.start()` to make every retry return a handle for the same run. Use `engine.startOrSignal()` when the first event should create the workflow and later events should signal the existing non-terminal run.
203
+
204
+ ```typescript
205
+ const handle = await engine.startOrSignal(
206
+ 'approval',
207
+ { orderId: 'order-123' },
208
+ { name: 'payment', payload: { status: 'succeeded' } },
209
+ { idempotencyKey: 'payment-webhook-order-123' },
210
+ );
211
+ ```
212
+
213
+ The idempotency mapping intentionally outlives terminal cleanup. If retention removes the workflow record, the key is spent and future calls return a conflict instead of starting a replacement.
214
+
191
215
  ### Search Attributes
192
216
 
193
217
  Attach indexed metadata to a workflow at runtime, then list and filter on it.
@@ -268,6 +292,7 @@ A small `Storage` interface over string keys and `Uint8Array` values: five requi
268
292
  - **`NodeSQLiteStorage`** (subpath `@lostgradient/weft/storage/sqlite/node`) for an explicit Node.js SQLite override via `better-sqlite3`
269
293
  - **`LMDBStorage`** (subpath `@lostgradient/weft/storage/lmdb`) for embedded high-throughput workloads
270
294
  - **`TursoStorage`** (subpath `@lostgradient/weft/storage/turso`) for distributed libSQL deployments
295
+ - **`NeonStorage`** (subpath `@lostgradient/weft/storage/neon`) for durable remote Neon/Postgres deployments
271
296
  - **`IndexedDBStorage`** (subpath `@lostgradient/weft/storage/indexeddb`) for browser environments
272
297
  - **`WebExtensionStorage`** (subpath `@lostgradient/weft/storage/web-extension`) for extension contexts using `browser.storage` or `chrome.storage`
273
298
  - **`HTTPStorage`** (subpath `@lostgradient/weft/storage/http`) for remote storage over Weft's HTTP storage routes
@@ -275,6 +300,8 @@ A small `Storage` interface over string keys and `Uint8Array` values: five requi
275
300
 
276
301
  Bring your own backend by implementing the interface—five methods is enough.
277
302
 
303
+ 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.
304
+
278
305
  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.
279
306
 
280
307
  ### Server Mode
@@ -372,39 +399,36 @@ For chaos testing, `withChaos()` wraps activities with configurable transient fa
372
399
  Every error Weft throws extends `WeftError`, so a single `instanceof` check catches them all, and each carries a stable string `code` equal to its class name:
373
400
 
374
401
  ```typescript
375
- import { isWeftError, isWeftErrorCode } from '@lostgradient/weft';
402
+ import { isWeftError } from '@lostgradient/weft';
376
403
 
377
404
  try {
378
405
  await engine.start('checkout', { orderId: 'order-1' }, { id: 'order-1' });
379
406
  } catch (error) {
380
407
  if (!isWeftError(error)) throw error; // not ours — rethrow
381
408
 
382
- if (isWeftErrorCode(error.code)) {
383
- switch (error.code) {
384
- case 'WorkflowAlreadyExistsError':
385
- // idempotent retry — already running
386
- break;
387
- case 'WorkflowNotRegisteredError':
388
- throw error; // a programming error, not a runtime condition
389
- default:
390
- console.error(`[${error.code}] ${error.message}`);
391
- }
409
+ switch (error.code) {
410
+ case 'WorkflowAlreadyExistsError':
411
+ // idempotent retry — already running
412
+ break;
413
+ case 'WorkflowNotRegisteredError':
414
+ throw error; // a programming error, not a runtime condition
415
+ default:
416
+ console.error(`[${error.code}] ${error.message}`);
392
417
  }
393
418
  }
394
419
  ```
395
420
 
396
- `isWeftError` is an `instanceof` check — the right tool in the common case where the error came from the same module instance. If an error can reach you across a realm or a duplicate module load (multiple copies of `@lostgradient/weft` in one process), `instanceof` is unreliable; skip `isWeftError` and branch on `error.code` directly, since the string `code` survives those boundaries:
421
+ `isWeftError` is an `instanceof` check — the right tool in the common case where the error came from the same module instance. If an error can reach you across a realm or a duplicate module load (multiple copies of `@lostgradient/weft` in one process), `instanceof` is unreliable; use `isWeftErrorLike` to narrow the caught value structurally:
397
422
 
398
423
  ```typescript
399
- import { isWeftErrorCode } from '@lostgradient/weft';
424
+ import { isWeftErrorLike } from '@lostgradient/weft';
400
425
 
401
426
  function isAlreadyRunning(error: unknown): boolean {
402
- const code = (error as { code?: unknown }).code;
403
- return isWeftErrorCode(code) && code === 'WorkflowAlreadyExistsError';
427
+ return isWeftErrorLike(error) && error.code === 'WorkflowAlreadyExistsError';
404
428
  }
405
429
  ```
406
430
 
407
- The exported `WeftErrorCode` union lists every code that belongs to a public, exported error class; those codes are stable contract and safe to `switch` on exhaustively. Errors that are internal to Weft also extend `WeftError` but carry codes intentionally left out of `WeftErrorCode` — `isWeftErrorCode` returns `false` for them — so internal codes may change between releases without breaking your types.
431
+ The exported `WeftErrorCode` union lists every code that belongs to a public, exported error class; those codes are stable contract and safe to `switch` on exhaustively. Errors that are internal to Weft also extend `WeftError` but carry codes intentionally left out of `WeftErrorCode` — `isWeftErrorCode` and `isWeftErrorLike` return `false` for them — so internal codes may change between releases without breaking your types.
408
432
 
409
433
  ## Installation
410
434
 
@@ -418,6 +442,7 @@ Storage backends and adapters are exported under subpaths so they only load when
418
442
  import { SQLiteStorage } from '@lostgradient/weft/storage/sqlite';
419
443
  import { LMDBStorage } from '@lostgradient/weft/storage/lmdb';
420
444
  import { TursoStorage } from '@lostgradient/weft/storage/turso';
445
+ import { NeonStorage } from '@lostgradient/weft/storage/neon';
421
446
  import { IndexedDBStorage } from '@lostgradient/weft/storage/indexeddb';
422
447
  import { WebExtensionStorage } from '@lostgradient/weft/storage/web-extension';
423
448
  import { HTTPStorage } from '@lostgradient/weft/storage/http';
@@ -1,5 +1,5 @@
1
1
  import { type CatalogWeftClient, type WeftClientConnection } from '../operation-client-runtime.ts';
2
- export declare const CATALOG_OPERATION_NAMES: readonly ["weft.activities.complete", "weft.activities.fail", "weft.recover.all", "weft.retention.get", "weft.reviews.decision.submit", "weft.reviews.get", "weft.reviews.list", "weft.schedules.cancel", "weft.schedules.create", "weft.schedules.get", "weft.schedules.list", "weft.schedules.pause", "weft.schedules.resume", "weft.schedules.update", "weft.system.metrics", "weft.system.registry", "weft.task.queues.list", "weft.tasks.diagnostics", "weft.updates.result.get", "weft.worker.deployments.drain", "weft.worker.deployments.resume", "weft.workers.drain", "weft.workers.list", "weft.workers.resume", "weft.workflows.aggregate", "weft.workflows.attributes.get", "weft.workflows.attributes.set", "weft.workflows.bulk.cancel", "weft.workflows.bulk.delete", "weft.workflows.bulk.signal", "weft.workflows.bulk.tags", "weft.workflows.cancel", "weft.workflows.checkpoints.get", "weft.workflows.checkpoints.list", "weft.workflows.events.list", "weft.workflows.fork", "weft.workflows.get", "weft.workflows.list", "weft.workflows.purge", "weft.workflows.query", "weft.workflows.replay", "weft.workflows.result.get", "weft.workflows.resume", "weft.workflows.signal", "weft.workflows.start", "weft.workflows.streams.chunks", "weft.workflows.tags.add", "weft.workflows.tags.remove", "weft.workflows.timeline.get", "weft.workflows.timeout", "weft.workflows.update"];
2
+ export declare const CATALOG_OPERATION_NAMES: readonly ["weft.activities.complete", "weft.activities.fail", "weft.recover.all", "weft.retention.get", "weft.reviews.decision.submit", "weft.reviews.get", "weft.reviews.list", "weft.schedules.cancel", "weft.schedules.create", "weft.schedules.get", "weft.schedules.list", "weft.schedules.pause", "weft.schedules.resume", "weft.schedules.update", "weft.system.metrics", "weft.system.registry", "weft.task.queues.list", "weft.tasks.diagnostics", "weft.updates.result.get", "weft.worker.deployments.drain", "weft.worker.deployments.resume", "weft.workers.drain", "weft.workers.list", "weft.workers.resume", "weft.workflows.aggregate", "weft.workflows.attributes.get", "weft.workflows.attributes.set", "weft.workflows.bulk.cancel", "weft.workflows.bulk.delete", "weft.workflows.bulk.signal", "weft.workflows.bulk.tags", "weft.workflows.cancel", "weft.workflows.checkpoints.get", "weft.workflows.checkpoints.list", "weft.workflows.events.list", "weft.workflows.fork", "weft.workflows.get", "weft.workflows.list", "weft.workflows.purge", "weft.workflows.query", "weft.workflows.replay", "weft.workflows.result.get", "weft.workflows.resume", "weft.workflows.signal", "weft.workflows.start", "weft.workflows.startorsignal", "weft.workflows.streams.chunks", "weft.workflows.suspend", "weft.workflows.tags.add", "weft.workflows.tags.remove", "weft.workflows.timeline.get", "weft.workflows.timeout", "weft.workflows.update"];
3
3
  export type CatalogOperationName = (typeof CATALOG_OPERATION_NAMES)[number];
4
4
  type SharedAttributesConfirmationTo_f933f774 = {
5
5
  readonly attributes?: ReadonlyArray<SharedGtGteKey_896a0c41>;
@@ -540,6 +540,26 @@ export type CatalogOperationTypes = {
540
540
  };
541
541
  readonly faults: 'Conflict';
542
542
  };
543
+ 'weft.workflows.startorsignal': {
544
+ readonly input: {
545
+ readonly executionTimeout?: unknown;
546
+ readonly id?: unknown;
547
+ readonly idempotencyKey?: unknown;
548
+ readonly input?: unknown;
549
+ readonly searchAttributes?: unknown;
550
+ readonly signalId?: string;
551
+ readonly signalName: string;
552
+ readonly signalPayload?: unknown;
553
+ readonly startAfter?: unknown;
554
+ readonly startAt?: unknown;
555
+ readonly tags?: unknown;
556
+ readonly type: unknown;
557
+ };
558
+ readonly output: {
559
+ readonly id: string;
560
+ };
561
+ readonly faults: 'Conflict';
562
+ };
543
563
  'weft.workflows.streams.chunks': {
544
564
  readonly input: {
545
565
  readonly after?: unknown;
@@ -551,6 +571,13 @@ export type CatalogOperationTypes = {
551
571
  };
552
572
  readonly faults: never;
553
573
  };
574
+ 'weft.workflows.suspend': {
575
+ readonly input: {
576
+ readonly workflowId: string;
577
+ };
578
+ readonly output: unknown;
579
+ readonly faults: 'Unprocessable';
580
+ };
554
581
  'weft.workflows.tags.add': {
555
582
  readonly input: {
556
583
  readonly tags?: unknown;
@@ -48,7 +48,9 @@ export const CATALOG_OPERATION_NAMES = [
48
48
  "weft.workflows.resume",
49
49
  "weft.workflows.signal",
50
50
  "weft.workflows.start",
51
+ "weft.workflows.startorsignal",
51
52
  "weft.workflows.streams.chunks",
53
+ "weft.workflows.suspend",
52
54
  "weft.workflows.tags.add",
53
55
  "weft.workflows.tags.remove",
54
56
  "weft.workflows.timeline.get",