@lostgradient/weft 0.11.0 → 0.13.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 +1 -1
- package/dist/cli/api.d.ts +2 -0
- package/dist/cli/api.js +3 -4
- package/dist/cli/generated/operation-catalog.snapshot.json +5167 -0
- package/dist/cli/generated/operation-client.generated.d.ts +119 -10
- package/dist/cli/generated/operation-client.generated.js +74 -1
- package/dist/cli/index.js +1 -0
- package/dist/cli/operation-catalog-snapshot.d.ts +11 -2
- package/dist/cli/operation-catalog-snapshot.js +14 -5
- package/dist/cli/operation-client-runtime.d.ts +29 -0
- package/dist/cli-main.js +227 -401
- package/dist/client/client-storage.d.ts +24 -0
- package/dist/client/client-storage.js +14 -0
- package/dist/client/handle-delegation.d.ts +3 -3
- package/dist/client/handle-delegation.js +2 -2
- package/dist/client/http-client-requests.d.ts +5 -3
- package/dist/client/http-client-requests.js +20 -2
- package/dist/client/http-client-storage.d.ts +3 -0
- package/dist/client/http-client-storage.js +110 -0
- package/dist/client/http-client.d.ts +9 -6
- package/dist/client/http-client.js +13 -18
- package/dist/client/http-operations.d.ts +3 -1
- package/dist/client/http-operations.js +84 -2
- package/dist/client/http-request.d.ts +35 -6
- package/dist/client/http-request.js +31 -10
- package/dist/client/in-process-operations.d.ts +2 -2
- package/dist/client/in-process-operations.js +2 -2
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +18 -0
- package/dist/client/interface.d.ts +26 -26
- package/dist/client/local.d.ts +9 -6
- package/dist/client/local.js +9 -4
- package/dist/client/search-params.js +10 -6
- package/dist/client/start-body.d.ts +3 -1
- package/dist/client/start-body.js +9 -0
- package/dist/connection.d.ts +8 -0
- package/dist/connection.js +41 -17
- package/dist/core/bulk-workflow-filter.d.ts +2 -1
- package/dist/core/bulk-workflow-filter.js +5 -1
- package/dist/core/engine/async-activity-records.d.ts +12 -1
- package/dist/core/engine/async-activity-records.js +81 -2
- package/dist/core/engine/bulk-operations-purge.js +16 -1
- package/dist/core/engine/bulk-operations-shared.js +2 -0
- package/dist/core/engine/callback-creators-core.js +2 -1
- package/dist/core/engine/callback-creators-schedule.d.ts +2 -1
- package/dist/core/engine/callback-creators-schedule.js +3 -3
- package/dist/core/engine/checkpoint-reads.js +11 -1
- package/dist/core/engine/child-workflow.js +15 -6
- package/dist/core/engine/construction.js +3 -0
- package/dist/core/engine/disposal.js +2 -0
- package/dist/core/engine/engine-internal-types.d.ts +4 -1
- package/dist/core/engine/fenced-write.d.ts +5 -3
- package/dist/core/engine/finalizer-status.d.ts +10 -0
- package/dist/core/engine/finalizer-status.js +82 -0
- package/dist/core/engine/index.d.ts +69 -2
- package/dist/core/engine/index.js +71 -8
- package/dist/core/engine/internals.d.ts +3 -0
- package/dist/core/engine/lease-health.d.ts +64 -0
- package/dist/core/engine/lease-health.js +0 -0
- package/dist/core/engine/lease-manager.d.ts +4 -2
- package/dist/core/engine/lease-manager.js +32 -4
- package/dist/core/engine/lifecycle/recovered-services.js +0 -2
- package/dist/core/engine/lifecycle/shared.d.ts +28 -0
- package/dist/core/engine/lifecycle/start-batch.js +12 -0
- package/dist/core/engine/lifecycle/start.d.ts +1 -1
- package/dist/core/engine/lifecycle/start.js +34 -5
- package/dist/core/engine/lifecycle/transition.js +19 -9
- package/dist/core/engine/operations-coordination.d.ts +1 -12
- package/dist/core/engine/operations-coordination.js +57 -10
- package/dist/core/engine/operations-speculate.d.ts +1 -1
- package/dist/core/engine/operations-speculate.js +19 -5
- package/dist/core/engine/registration.js +14 -0
- package/dist/core/engine/schedule-handle.d.ts +4 -4
- package/dist/core/engine/schedule-handle.js +2 -2
- package/dist/core/engine/schedule-overlap.d.ts +11 -0
- package/dist/core/engine/schedule-overlap.js +50 -0
- package/dist/core/engine/schedule-run.d.ts +11 -3
- package/dist/core/engine/schedule-run.js +27 -4
- package/dist/core/engine/schedule-timer.js +10 -1
- package/dist/core/engine/schedules.d.ts +5 -4
- package/dist/core/engine/schedules.js +62 -56
- package/dist/core/engine/state-utilities.js +1 -1
- package/dist/core/engine/storage-io.d.ts +12 -0
- package/dist/core/engine/storage-io.js +49 -10
- package/dist/core/engine/termination/finalizer-claim.d.ts +8 -6
- package/dist/core/engine/termination/finalizer-claim.js +2 -1
- package/dist/core/engine/termination/finalizer.js +10 -14
- package/dist/core/engine/timeline-coordinator-constants.d.ts +3 -0
- package/dist/core/engine/timeline-coordinator-constants.js +1 -0
- package/dist/core/engine/timeline-coordinator-detail.d.ts +13 -0
- package/dist/core/engine/timeline-coordinator-detail.js +76 -0
- package/dist/core/engine/validation/schedule-options.d.ts +8 -1
- package/dist/core/engine/validation/schedule-options.js +18 -0
- package/dist/core/engine/validation/schedule.d.ts +1 -1
- package/dist/core/engine/validation/schedule.js +27 -3
- package/dist/core/engine/validation.js +66 -2
- package/dist/core/engine/workflow-state-stream.d.ts +5 -1
- package/dist/core/engine/workflow-state-stream.js +37 -14
- package/dist/core/events/schedule-events.d.ts +3 -4
- package/dist/core/events/workflow-events.d.ts +2 -1
- package/dist/core/list-filter-validation.d.ts +3 -0
- package/dist/core/list-filter-validation.js +11 -0
- package/dist/core/registry-snapshot.d.ts +32 -0
- package/dist/core/registry-snapshot.js +28 -0
- package/dist/core/review/index.d.ts +4 -4
- package/dist/core/types/activity.d.ts +52 -5
- package/dist/core/types/bulk.d.ts +1 -0
- package/dist/core/types/definition-schema-to-json.d.ts +11 -0
- package/dist/core/types/definition-schema-to-json.js +11 -2
- package/dist/core/types/list-options.d.ts +6 -0
- package/dist/core/types/options.d.ts +6 -5
- package/dist/core/types/reviews.d.ts +2 -2
- package/dist/core/types/schedules.d.ts +45 -2
- package/dist/core/types/services-resolution.d.ts +5 -5
- package/dist/core/types/state.d.ts +64 -0
- package/dist/core/types/workflow-log.d.ts +3 -2
- package/dist/core/types/workflow-observability.d.ts +50 -0
- package/dist/core/types/workflow-observability.js +0 -0
- package/dist/core/types/workflow-registry.d.ts +7 -0
- package/dist/core/types.d.ts +1 -0
- package/dist/core/types.js +1 -0
- package/dist/http.js +2 -0
- package/dist/index.d.ts +4 -3
- package/dist/indexeddb.js +1 -0
- package/dist/json-schema.js +3 -3
- package/dist/mcp/cli.js +63 -61
- package/dist/mcp/http.d.ts +7 -2
- package/dist/mcp/session.d.ts +3 -3
- package/dist/mcp/session.js +3 -2
- package/dist/mcp/stdio.d.ts +7 -2
- package/dist/observability/index.js +2 -2
- package/dist/runtime/portable.d.ts +33 -0
- package/dist/runtime/portable.js +17 -6
- package/dist/server/access-policy-metadata.d.ts +92 -0
- package/dist/server/access-policy-metadata.js +78 -0
- package/dist/server/engine-event-feed-backend.d.ts +22 -3
- package/dist/server/fault-to-http.d.ts +3 -7
- package/dist/server/fault-to-http.js +2 -34
- package/dist/server/fleet-event-feed.d.ts +65 -0
- package/dist/server/handler/index.d.ts +11 -2
- package/dist/server/handler/index.js +8 -1
- package/dist/server/handler/route-dispatch.d.ts +10 -3
- package/dist/server/handler/route-dispatch.js +19 -4
- package/dist/server/handler.js +1 -56
- package/dist/server/index.d.ts +13 -2
- package/dist/server/index.js +88 -64
- package/dist/server/interactive-operations.js +2 -0
- package/dist/server/openapi-error-responses.js +55 -4
- package/dist/server/openapi.d.ts +3 -1
- package/dist/server/openapi.js +4 -0
- package/dist/server/openrpc-document-schema.d.ts +64 -0
- package/dist/server/openrpc-document-schema.js +6 -26
- package/dist/server/openrpc.d.ts +4 -0
- package/dist/server/openrpc.js +9 -33
- package/dist/server/operation-fault.d.ts +24 -7
- package/dist/server/operation-fault.js +65 -13
- package/dist/server/operations/aggregate-workflows.d.ts +6 -0
- package/dist/server/operations/aggregate-workflows.js +3 -2
- package/dist/server/operations/async-activity.d.ts +14 -0
- package/dist/server/operations/async-activity.js +88 -4
- package/dist/server/operations/bulk-filter-helpers.d.ts +3 -0
- package/dist/server/operations/bulk-filter-helpers.js +27 -3
- package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +6 -0
- package/dist/server/operations/bulk-signal-workflows.d.ts +6 -0
- package/dist/server/operations/get-stream-chunks.js +2 -7
- package/dist/server/operations/get-system-lease.d.ts +19 -0
- package/dist/server/operations/get-system-lease.js +48 -0
- package/dist/server/operations/get-workflow-observability.d.ts +24 -0
- package/dist/server/operations/get-workflow-observability.js +80 -0
- package/dist/server/operations/get-workflow-result.js +2 -2
- package/dist/server/operations/get-workflow.d.ts +2 -2
- package/dist/server/operations/list-filter-query-extractor.js +15 -0
- package/dist/server/operations/list-workflows.d.ts +6 -0
- package/dist/server/operations/list-workflows.js +12 -3
- package/dist/server/operations/operation-helpers.d.ts +9 -18
- package/dist/server/operations/operation-helpers.js +5 -23
- package/dist/server/operations/purge-workflows.d.ts +3 -0
- package/dist/server/operations/recover-all.js +2 -1
- package/dist/server/operations/single-workflow-tag-mutation.js +2 -2
- package/dist/server/operations/sse-stream.js +2 -7
- package/dist/server/operations/storage-capabilities.d.ts +34 -0
- package/dist/server/operations/storage-capabilities.js +38 -0
- package/dist/server/operations/storage.js +8 -17
- package/dist/server/operations/stream-workflow-sse.js +3 -9
- package/dist/server/operations/submit-review-decision.d.ts +2 -0
- package/dist/server/operations/submit-review-decision.js +19 -2
- package/dist/server/operations/update-schedule.d.ts +8 -0
- package/dist/server/operations/update-schedule.js +70 -7
- package/dist/server/operations/workflow-events-sse.js +2 -2
- package/dist/server/replay-live-feed-internals.d.ts +19 -0
- package/dist/server/replay-live-feed-internals.js +76 -0
- package/dist/server/rest-binding.d.ts +7 -6
- package/dist/server/rest-bindings.d.ts +2 -13
- package/dist/server/rest-bindings.js +19 -10
- package/dist/server/runtime/authentication-bridge.d.ts +2 -2
- package/dist/server/serve-internals.js +3 -3
- package/dist/server/task-queue.d.ts +7 -5
- package/dist/server/workflow-event-feed.d.ts +100 -11
- package/dist/server/workflow-event-feed.js +1 -140
- package/dist/service-worker/index.d.ts +8 -2
- package/dist/service-worker/index.js +37 -56
- package/dist/service-worker/setup.d.ts +6 -2
- package/dist/storage/auto.js +1 -1
- package/dist/storage/bun-sql.js +3 -3
- package/dist/storage/capabilities.d.ts +1 -1
- package/dist/storage/cloudflare-durable-object-sql.d.ts +75 -0
- package/dist/storage/cloudflare-durable-object-sql.js +0 -0
- package/dist/storage/cloudflare-value-codec.d.ts +67 -0
- package/dist/storage/cloudflare-value-codec.js +46 -0
- package/dist/storage/cloudflare.d.ts +140 -0
- package/dist/storage/cloudflare.js +127 -0
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/http.js +200 -2
- package/dist/storage/index.d.ts +8 -1
- package/dist/storage/indexeddb.js +311 -1
- package/dist/storage/interface.d.ts +16 -4
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +4 -0
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.js +4 -4
- package/dist/storage/node-sqlite.js +3 -3
- package/dist/storage/postgres-key-value-queries.d.ts +6 -0
- package/dist/storage/postgres-key-value-queries.js +2 -3
- package/dist/storage/postgres.js +4 -4
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/sql-identifier.d.ts +35 -0
- package/dist/storage/sql-identifier.js +5 -0
- package/dist/storage/sqlite-key-value-queries.d.ts +11 -6
- package/dist/storage/sqlite-key-value-queries.js +3 -3
- package/dist/storage/testing.js +1 -1
- package/dist/storage/turso.js +2 -2
- package/dist/storage/typed-storage.js +138 -2
- package/dist/storage/web-extension.js +298 -1
- package/dist/testing/index.js +21 -60
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/web-extension.js +1 -0
- package/dist/worker/protocol.js +1 -1
- package/package.json +8 -3
|
@@ -29,9 +29,8 @@ import type { TaskQueue } from './task-queue.ts';
|
|
|
29
29
|
export type UnknownRestBinding = RestBinding<any, any>;
|
|
30
30
|
/**
|
|
31
31
|
* Static REST bindings for all operations that do not need per-server
|
|
32
|
-
* configuration. The `weft.system.metrics` binding is excluded
|
|
33
|
-
*
|
|
34
|
-
* (to receive the metrics collector without module-level singletons).
|
|
32
|
+
* configuration. The `weft.system.metrics` binding is excluded because its
|
|
33
|
+
* factory receives the per-server metrics collector.
|
|
35
34
|
* Use `createLiveRestBindings()` to get the full set for a given server.
|
|
36
35
|
*/
|
|
37
36
|
export declare const REST_BINDINGS: ReadonlyArray<UnknownRestBinding>;
|
|
@@ -43,16 +42,6 @@ export declare const REST_BINDINGS: ReadonlyArray<UnknownRestBinding>;
|
|
|
43
42
|
* are wired into the operations through {@link createLiveOperationRegistry}.
|
|
44
43
|
*/
|
|
45
44
|
export declare function createLiveRestBindings(): ReadonlyArray<UnknownRestBinding>;
|
|
46
|
-
/**
|
|
47
|
-
* Live operation registry — populated with every operation that has a
|
|
48
|
-
* `RestBinding`, a JSON-RPC mount, or an stdio mount. Exposed via a
|
|
49
|
-
* factory so tests can spin up a fresh registry without inheriting
|
|
50
|
-
* the live one's state.
|
|
51
|
-
*
|
|
52
|
-
* Concrete `OperationDefinition<Input, Output>` values are directly
|
|
53
|
-
* assignable to `RegistrableOperation` by the variance design in
|
|
54
|
-
* `operation-catalog.ts` — no `as ErasedOperation` cast is needed.
|
|
55
|
-
*/
|
|
56
45
|
/**
|
|
57
46
|
* Create the live operation registry for a server instance.
|
|
58
47
|
*
|
|
@@ -7,12 +7,7 @@ import {
|
|
|
7
7
|
aggregateWorkflowsOperation,
|
|
8
8
|
aggregateWorkflowsRestBinding
|
|
9
9
|
} from "./operations/aggregate-workflows.js";
|
|
10
|
-
import
|
|
11
|
-
completeAsyncActivityOperation,
|
|
12
|
-
completeAsyncActivityRestBinding,
|
|
13
|
-
failAsyncActivityOperation,
|
|
14
|
-
failAsyncActivityRestBinding
|
|
15
|
-
} from "./operations/async-activity.js";
|
|
10
|
+
import * as asyncActivity from "./operations/async-activity.js";
|
|
16
11
|
import {
|
|
17
12
|
bulkCancelWorkflowsOperation,
|
|
18
13
|
bulkCancelWorkflowsRestBinding
|
|
@@ -66,6 +61,10 @@ import {
|
|
|
66
61
|
getStreamChunksOperation,
|
|
67
62
|
getStreamChunksRestBinding
|
|
68
63
|
} from "./operations/get-stream-chunks.js";
|
|
64
|
+
import {
|
|
65
|
+
getSystemLeaseOperation,
|
|
66
|
+
getSystemLeaseRestBinding
|
|
67
|
+
} from "./operations/get-system-lease.js";
|
|
69
68
|
import {
|
|
70
69
|
createGetSystemMetricsOperation,
|
|
71
70
|
createGetSystemMetricsRestBinding
|
|
@@ -89,6 +88,7 @@ import {
|
|
|
89
88
|
getWorkflowEventsOperation,
|
|
90
89
|
getWorkflowEventsRestBinding
|
|
91
90
|
} from "./operations/get-workflow-events.js";
|
|
91
|
+
import * as workflowObservability from "./operations/get-workflow-observability.js";
|
|
92
92
|
import {
|
|
93
93
|
getWorkflowResultOperation,
|
|
94
94
|
getWorkflowResultRestBinding
|
|
@@ -155,6 +155,7 @@ import {
|
|
|
155
155
|
startOrSignalWorkflowRestBinding
|
|
156
156
|
} from "./operations/start-or-signal-workflow.js";
|
|
157
157
|
import { startWorkflowOperation, startWorkflowRestBinding } from "./operations/start-workflow.js";
|
|
158
|
+
import * as storageCapabilities from "./operations/storage-capabilities.js";
|
|
158
159
|
import {
|
|
159
160
|
storageBatchOperation,
|
|
160
161
|
storageBatchRestBinding,
|
|
@@ -228,11 +229,13 @@ export const REST_BINDINGS = [
|
|
|
228
229
|
cancelWorkflowRestBinding,
|
|
229
230
|
getWorkflowResultRestBinding,
|
|
230
231
|
getWorkflowAttributesRestBinding,
|
|
232
|
+
...workflowObservability.workflowObservabilityRestBindings,
|
|
231
233
|
getWorkflowEventsRestBinding,
|
|
232
234
|
setWorkflowAttributesRestBinding,
|
|
233
235
|
signalWorkflowRestBinding,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
+
asyncActivity.listPendingAsyncActivitiesRestBinding,
|
|
237
|
+
asyncActivity.completeAsyncActivityRestBinding,
|
|
238
|
+
asyncActivity.failAsyncActivityRestBinding,
|
|
236
239
|
queryWorkflowRestBinding,
|
|
237
240
|
queryWorkflowWithInputRestBinding,
|
|
238
241
|
resumeWorkflowRestBinding,
|
|
@@ -243,6 +246,7 @@ export const REST_BINDINGS = [
|
|
|
243
246
|
createScheduleRestBinding,
|
|
244
247
|
updateScheduleRestBinding,
|
|
245
248
|
getRegistryRestBinding,
|
|
249
|
+
getSystemLeaseRestBinding,
|
|
246
250
|
getRetentionOverviewRestBinding,
|
|
247
251
|
getUpdateResultRestBinding,
|
|
248
252
|
listReviewsRestBinding,
|
|
@@ -265,6 +269,7 @@ export const REST_BINDINGS = [
|
|
|
265
269
|
listSchedulesRestBinding,
|
|
266
270
|
getScheduleRestBinding,
|
|
267
271
|
replayWorkflowRestBinding,
|
|
272
|
+
storageCapabilities.storageCapabilitiesRestBinding,
|
|
268
273
|
storageGetRestBinding,
|
|
269
274
|
storagePutRestBinding,
|
|
270
275
|
storageDeleteRestBinding,
|
|
@@ -357,11 +362,13 @@ export function createLiveOperationRegistry(options) {
|
|
|
357
362
|
cancelWorkflowOperation,
|
|
358
363
|
getWorkflowResultOperation,
|
|
359
364
|
getWorkflowAttributesOperation,
|
|
365
|
+
...workflowObservability.workflowObservabilityOperations,
|
|
360
366
|
getWorkflowEventsOperation,
|
|
361
367
|
setWorkflowAttributesOperation,
|
|
362
368
|
signalWorkflowOperation,
|
|
363
|
-
|
|
364
|
-
|
|
369
|
+
asyncActivity.listPendingAsyncActivitiesOperation,
|
|
370
|
+
asyncActivity.completeAsyncActivityOperation,
|
|
371
|
+
asyncActivity.failAsyncActivityOperation,
|
|
365
372
|
queryWorkflowOperation,
|
|
366
373
|
resumeWorkflowOperation,
|
|
367
374
|
suspendWorkflowOperation,
|
|
@@ -371,6 +378,7 @@ export function createLiveOperationRegistry(options) {
|
|
|
371
378
|
createScheduleOperation,
|
|
372
379
|
updateScheduleOperation,
|
|
373
380
|
getRegistryOperation,
|
|
381
|
+
getSystemLeaseOperation,
|
|
374
382
|
getRetentionOverviewOperation,
|
|
375
383
|
getUpdateResultOperation,
|
|
376
384
|
listReviewsOperation,
|
|
@@ -395,6 +403,7 @@ export function createLiveOperationRegistry(options) {
|
|
|
395
403
|
listSchedulesOperation,
|
|
396
404
|
getScheduleOperation,
|
|
397
405
|
replayWorkflowOperation,
|
|
406
|
+
storageCapabilities.storageCapabilitiesOperation,
|
|
398
407
|
storageGetOperation,
|
|
399
408
|
storagePutOperation,
|
|
400
409
|
storageDeleteOperation,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ServerWebSocket } from 'bun';
|
|
2
|
-
import type {
|
|
2
|
+
import type { RegistryAgnosticEngine } from '../../core/engine.ts';
|
|
3
3
|
import type { PrometheusExporter } from '../../observability/metrics.ts';
|
|
4
4
|
import type { AuthConfig } from '../authentication.ts';
|
|
5
5
|
import { type WebSocketData } from '../json-rpc-websocket-runtime.ts';
|
|
6
6
|
import type { OpenApiSecuritySchemeName } from '../openapi.ts';
|
|
7
7
|
import type { ServerContext } from './context.ts';
|
|
8
8
|
type ServerFetchOptions = {
|
|
9
|
-
engine:
|
|
9
|
+
engine: RegistryAgnosticEngine;
|
|
10
10
|
prometheusExporter?: PrometheusExporter;
|
|
11
11
|
discoveryInfo?: import('../discovery-info.ts').DiscoveryInfo;
|
|
12
12
|
publicOrigin?: string;
|
|
@@ -85,7 +85,7 @@ export function resolveNetworkConfig(options) {
|
|
|
85
85
|
return { port, hostname, development, tlsOptions, serverOptions, serverMetricsCollector };
|
|
86
86
|
}
|
|
87
87
|
export function buildServerContext(options, serverMetricsCollector) {
|
|
88
|
-
const workerRegistry = new WorkerRegistry(options.routingPolicy !== void 0 ? { policy: options.routingPolicy } : void 0), taskQueue = new TaskQueue(options.schedulingPolicy !== void 0 ? { schedulingPolicy: options.schedulingPolicy } : void 0), eventFeedBackend = createEngineEventFeedBackend(
|
|
88
|
+
const workerRegistry = new WorkerRegistry(options.routingPolicy !== void 0 ? { policy: options.routingPolicy } : void 0), taskQueue = new TaskQueue(options.schedulingPolicy !== void 0 ? { schedulingPolicy: options.schedulingPolicy } : void 0), engine = options.engine, eventFeedBackend = createEngineEventFeedBackend(engine);
|
|
89
89
|
return {
|
|
90
90
|
registry: workerRegistry,
|
|
91
91
|
taskQueue,
|
|
@@ -112,12 +112,12 @@ export function buildServerContext(options, serverMetricsCollector) {
|
|
|
112
112
|
workflowEventFeed: createWorkflowEventFeed(eventFeedBackend),
|
|
113
113
|
fleetEventFeed: createFleetEventFeed(options.engine.storage),
|
|
114
114
|
activeJsonRpcSessions: new Set,
|
|
115
|
-
mcpSessionManager: createMcpSessionManager(
|
|
115
|
+
mcpSessionManager: createMcpSessionManager(engine),
|
|
116
116
|
authenticatorPromise: options.auth ? createAuthenticator(options.auth) : null,
|
|
117
117
|
rateLimiter: options.rateLimit ? createRateLimiter(options.rateLimit) : null,
|
|
118
118
|
visibilityPollMs: options.visibilityPollIntervalMs ?? 5000,
|
|
119
119
|
workerReconnectGracePeriodMs: clampWorkerReconnectGracePeriod(options.workerReconnectGracePeriodMs),
|
|
120
|
-
payloadSizeMaxBytes: getEnginePayloadSizeMaxBytes(
|
|
120
|
+
payloadSizeMaxBytes: getEnginePayloadSizeMaxBytes(engine),
|
|
121
121
|
pendingWorkerRequeues: new Map,
|
|
122
122
|
scanRunning: !1,
|
|
123
123
|
processingOperations: new Set,
|
|
@@ -14,21 +14,23 @@ export declare function resetLifoStarvationWarningForTesting(): void;
|
|
|
14
14
|
* until a task arrives or the timeout expires.
|
|
15
15
|
*
|
|
16
16
|
* `serve()` owns the live instance and exposes it as
|
|
17
|
-
* {@link WeftServer.taskQueue} for inspection.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* {@link WeftServer.taskQueue} for inspection. Direct `handleRequest()` hosts
|
|
18
|
+
* can construct an instance alongside a `WorkerRegistry` and inject both via
|
|
19
|
+
* `HandlerOptions`. Prefer the `WeftServer` methods (`dispatchTask`,
|
|
20
|
+
* `shutdownWorker`, etc.) over mutating a server-owned queue directly.
|
|
21
21
|
*
|
|
22
22
|
* @example
|
|
23
23
|
* ```ts
|
|
24
|
-
* import { serve,
|
|
24
|
+
* import { serve, TaskQueue } from '@lostgradient/weft/server';
|
|
25
25
|
* import { Engine, MemoryStorage } from '@lostgradient/weft';
|
|
26
26
|
*
|
|
27
27
|
* await using engine = new Engine({ storage: new MemoryStorage() });
|
|
28
28
|
* await using server = serve({ engine });
|
|
29
29
|
*
|
|
30
30
|
* const taskQueue: TaskQueue = server.taskQueue;
|
|
31
|
+
* const standaloneTaskQueue = new TaskQueue();
|
|
31
32
|
* void taskQueue;
|
|
33
|
+
* standaloneTaskQueue[Symbol.dispose]();
|
|
32
34
|
* ```
|
|
33
35
|
*/
|
|
34
36
|
export declare class TaskQueue implements Disposable {
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import type { WeftEventMap } from '../core/events.ts';
|
|
2
2
|
/** Discriminator string carried on every feed envelope. */
|
|
3
3
|
export type FeedEventKind = keyof WeftEventMap | 'workflow:checkpoint' | 'stream:chunk' | (string & {});
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Opaque cursor into a workflow or fleet event feed. Only `encodeCursor` /
|
|
6
|
+
* `decodeCursor` know the format — treat it as an opaque string, pass it back
|
|
7
|
+
* as `fromCursor` to resume a feed, and never parse it.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import type { Cursor, EventEnvelope } from '@lostgradient/weft/server/handler';
|
|
12
|
+
*
|
|
13
|
+
* declare const envelope: EventEnvelope;
|
|
14
|
+
* const lastCursor: Cursor = envelope.cursor;
|
|
15
|
+
* void lastCursor;
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
5
18
|
export type Cursor = string;
|
|
6
19
|
/** Encode a non-negative integer sequence as an opaque cursor. */
|
|
7
20
|
export declare function encodeCursor(sequence: number): Cursor;
|
|
@@ -11,6 +24,22 @@ export declare function encodeCursor(sequence: number): Cursor;
|
|
|
11
24
|
*/
|
|
12
25
|
export declare function decodeCursor(cursor: Cursor): number | null;
|
|
13
26
|
export type EventSelector = 'events' | 'tokens';
|
|
27
|
+
/**
|
|
28
|
+
* A single committed record from a workflow's event feed — the `events`
|
|
29
|
+
* (durable log entries, e.g. `workflow:checkpoint`) or `tokens` (streamed
|
|
30
|
+
* output chunks) selector, distinguished by `selector`. Returned by
|
|
31
|
+
* `WorkflowEventFeed.replay()` / `WorkflowEventFeed.subscribe()`, and
|
|
32
|
+
* consumed directly by the `/v1/workflows/:id/events/sse` REST route.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import type { EventEnvelope } from '@lostgradient/weft/server/handler';
|
|
37
|
+
*
|
|
38
|
+
* declare const envelope: EventEnvelope;
|
|
39
|
+
* console.log(envelope.selector); // 'events' | 'tokens'
|
|
40
|
+
* console.log(envelope.kind); // e.g. 'workflow:checkpoint'
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
14
43
|
export type EventEnvelope = {
|
|
15
44
|
readonly kind: FeedEventKind;
|
|
16
45
|
readonly workflowId: string;
|
|
@@ -20,6 +49,26 @@ export type EventEnvelope = {
|
|
|
20
49
|
readonly emittedAtMs: number;
|
|
21
50
|
readonly payload: unknown;
|
|
22
51
|
};
|
|
52
|
+
/**
|
|
53
|
+
* The durable source a `WorkflowEventFeed` replays and subscribes against.
|
|
54
|
+
* Most callers never implement this directly — `createEngineEventFeedBackend()`
|
|
55
|
+
* builds the production, `Engine`-backed implementation. Implement it
|
|
56
|
+
* yourself only to back a feed with a non-`Engine` source (e.g. a test
|
|
57
|
+
* double).
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { Engine, MemoryStorage } from '@lostgradient/weft';
|
|
62
|
+
* import {
|
|
63
|
+
* createEngineEventFeedBackend,
|
|
64
|
+
* type WorkflowEventFeedBackend,
|
|
65
|
+
* } from '@lostgradient/weft/server/handler';
|
|
66
|
+
*
|
|
67
|
+
* const engine = new Engine({ storage: new MemoryStorage() });
|
|
68
|
+
* const backend: WorkflowEventFeedBackend = createEngineEventFeedBackend(engine);
|
|
69
|
+
* void backend;
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
23
72
|
export type WorkflowEventFeedBackend = {
|
|
24
73
|
replay(options: {
|
|
25
74
|
workflowId: string;
|
|
@@ -29,6 +78,29 @@ export type WorkflowEventFeedBackend = {
|
|
|
29
78
|
snapshotTailSequence(workflowId: string, selector: EventSelector): Promise<number>;
|
|
30
79
|
subscribeLive(workflowId: string, selector: EventSelector, listener: (envelope: EventEnvelope) => void): () => void;
|
|
31
80
|
};
|
|
81
|
+
/**
|
|
82
|
+
* A per-workflow event feed: replay committed history from a cursor, then
|
|
83
|
+
* subscribe for live delivery. This is the shape of
|
|
84
|
+
* `HandlerOptions.workflowEventFeed` — build a real one with
|
|
85
|
+
* `createWorkflowEventFeed()` to drive `/v1/workflows/:id/events/sse`
|
|
86
|
+
* through `handleRequest()` without `serve()`.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* import { Engine, MemoryStorage } from '@lostgradient/weft';
|
|
91
|
+
* import {
|
|
92
|
+
* createEngineEventFeedBackend,
|
|
93
|
+
* createWorkflowEventFeed,
|
|
94
|
+
* type WorkflowEventFeed,
|
|
95
|
+
* } from '@lostgradient/weft/server/handler';
|
|
96
|
+
*
|
|
97
|
+
* const engine = new Engine({ storage: new MemoryStorage() });
|
|
98
|
+
* const workflowEventFeed: WorkflowEventFeed = createWorkflowEventFeed(
|
|
99
|
+
* createEngineEventFeedBackend(engine),
|
|
100
|
+
* );
|
|
101
|
+
* void workflowEventFeed;
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
32
104
|
export type WorkflowEventFeed = {
|
|
33
105
|
replay(options: {
|
|
34
106
|
workflowId: string;
|
|
@@ -74,15 +146,32 @@ export type ReplayLiveSubscribeOptions<TEnvelope extends SequencedEventEnvelope>
|
|
|
74
146
|
createReplayLimitError?: (count: number, limit: number) => unknown;
|
|
75
147
|
onReplayComplete?: () => void;
|
|
76
148
|
};
|
|
77
|
-
export declare class ReplayWindowExceededError extends Error {
|
|
78
|
-
readonly count: number;
|
|
79
|
-
readonly limit: number;
|
|
80
|
-
constructor(count: number, limit: number);
|
|
81
|
-
}
|
|
82
149
|
export declare function createReplayLiveFeed<TEnvelope extends SequencedEventEnvelope>(backend: ReplayLiveFeedBackend<TEnvelope>, options?: WorkflowEventFeedOptions): ReplayLiveFeed<TEnvelope>;
|
|
150
|
+
/**
|
|
151
|
+
* Build a `WorkflowEventFeed` over the given backend. Pass the result as
|
|
152
|
+
* `HandlerOptions.workflowEventFeed` to drive `/v1/workflows/:id/events/sse`
|
|
153
|
+
* through `handleRequest()` directly, without `serve()`. Call once and share
|
|
154
|
+
* the returned feed across every workflow and transport that needs it —
|
|
155
|
+
* `createWorkflowEventFeed()` itself holds no per-workflow state.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* import { Engine, MemoryStorage } from '@lostgradient/weft';
|
|
160
|
+
* import {
|
|
161
|
+
* createEngineEventFeedBackend,
|
|
162
|
+
* createWorkflowEventFeed,
|
|
163
|
+
* handleRequest,
|
|
164
|
+
* type HandlerOptions,
|
|
165
|
+
* } from '@lostgradient/weft/server/handler';
|
|
166
|
+
*
|
|
167
|
+
* const engine = new Engine({ storage: new MemoryStorage() });
|
|
168
|
+
* const workflowEventFeed = createWorkflowEventFeed(createEngineEventFeedBackend(engine));
|
|
169
|
+
* const options: HandlerOptions = { workflowEventFeed };
|
|
170
|
+
*
|
|
171
|
+
* async function handleWorkflowEventsSse(request: Request): Promise<Response> {
|
|
172
|
+
* return handleRequest(request, engine, options);
|
|
173
|
+
* }
|
|
174
|
+
* void handleWorkflowEventsSse;
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
83
177
|
export declare function createWorkflowEventFeed(backend: WorkflowEventFeedBackend, options?: WorkflowEventFeedOptions): WorkflowEventFeed;
|
|
84
|
-
export type InMemoryEventBackend = WorkflowEventFeedBackend & {
|
|
85
|
-
append(envelope: EventEnvelope): Promise<void>;
|
|
86
|
-
emitLive(envelope: EventEnvelope): Promise<void>;
|
|
87
|
-
};
|
|
88
|
-
export declare function createInMemoryEventBackend(): InMemoryEventBackend;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { drainLive, replayUpTo, shouldDeliverEnvelope } from "./replay-live-feed-internals.js";
|
|
1
2
|
const CURSOR_PATTERN = /^(?:-1|\d+)$/;
|
|
2
3
|
export function encodeCursor(sequence) {
|
|
3
4
|
if (!Number.isInteger(sequence) || sequence < 0)
|
|
@@ -18,17 +19,6 @@ function decodeCursorOrThrow(cursor) {
|
|
|
18
19
|
throw Error("Invalid cursor");
|
|
19
20
|
return sequence;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
-
export class ReplayWindowExceededError extends Error {
|
|
23
|
-
count;
|
|
24
|
-
limit;
|
|
25
|
-
constructor(count, limit) {
|
|
26
|
-
super(`Replay window is ${count} events; maximum is ${limit}.`);
|
|
27
|
-
this.count = count;
|
|
28
|
-
this.limit = limit;
|
|
29
|
-
this.name = "ReplayWindowExceededError";
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
22
|
const DEFAULT_LIVE_BUFFER_SIZE = 1000;
|
|
33
23
|
export function createReplayLiveFeed(backend, options) {
|
|
34
24
|
const bufferSize = options?.liveBufferSize ?? DEFAULT_LIVE_BUFFER_SIZE;
|
|
@@ -138,132 +128,3 @@ export function createWorkflowEventFeed(backend, options) {
|
|
|
138
128
|
dispose() {}
|
|
139
129
|
};
|
|
140
130
|
}
|
|
141
|
-
async function* replayUpTo(backend, afterSequence, snapshot, signal, replayOptions) {
|
|
142
|
-
let replayCount = 0;
|
|
143
|
-
for await (const envelope of backend.replay({ afterSequence })) {
|
|
144
|
-
if (envelope.sequence > snapshot)
|
|
145
|
-
break;
|
|
146
|
-
if (signal?.aborted)
|
|
147
|
-
return;
|
|
148
|
-
if (!shouldDeliverEnvelope(envelope, replayOptions))
|
|
149
|
-
continue;
|
|
150
|
-
if (shouldCountReplayEnvelope(envelope, replayOptions)) {
|
|
151
|
-
replayCount += 1;
|
|
152
|
-
const replayLimit = replayOptions?.replayLimit;
|
|
153
|
-
if (replayLimit !== void 0 && replayCount > replayLimit)
|
|
154
|
-
throw createReplayLimitError(replayOptions, replayCount, replayLimit);
|
|
155
|
-
}
|
|
156
|
-
yield envelope;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
function shouldDeliverEnvelope(envelope, replayOptions) {
|
|
160
|
-
return replayOptions?.filterEnvelope?.(envelope) ?? !0;
|
|
161
|
-
}
|
|
162
|
-
function shouldCountReplayEnvelope(envelope, replayOptions) {
|
|
163
|
-
return replayOptions?.countReplayEnvelope?.(envelope) ?? !0;
|
|
164
|
-
}
|
|
165
|
-
function createReplayLimitError(replayOptions, count, limit) {
|
|
166
|
-
return replayOptions?.createReplayLimitError?.(count, limit) ?? new ReplayWindowExceededError(count, limit);
|
|
167
|
-
}
|
|
168
|
-
function flushPendingBuffer(buffer, watermark) {
|
|
169
|
-
const batch = [];
|
|
170
|
-
let newWatermark = watermark, head = buffer.shift();
|
|
171
|
-
while (head !== void 0) {
|
|
172
|
-
if (head.sequence > newWatermark) {
|
|
173
|
-
batch.push(head);
|
|
174
|
-
newWatermark = head.sequence;
|
|
175
|
-
}
|
|
176
|
-
head = buffer.shift();
|
|
177
|
-
}
|
|
178
|
-
return { batch, newWatermark };
|
|
179
|
-
}
|
|
180
|
-
async function armAndWait(buffer, overflowed, signal, installWaker) {
|
|
181
|
-
const armed = new Promise((resolve) => {
|
|
182
|
-
installWaker(resolve);
|
|
183
|
-
});
|
|
184
|
-
if (buffer.length > 0 || overflowed() || signal?.aborted) {
|
|
185
|
-
installWaker(null);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
await armed;
|
|
189
|
-
}
|
|
190
|
-
async function* drainLive(buffer, snapshot, signal, overflowed, installWaker) {
|
|
191
|
-
let watermark = snapshot;
|
|
192
|
-
while (!0) {
|
|
193
|
-
if (signal?.aborted || overflowed())
|
|
194
|
-
break;
|
|
195
|
-
const { batch, newWatermark } = flushPendingBuffer(buffer, watermark);
|
|
196
|
-
watermark = newWatermark;
|
|
197
|
-
for (const envelope of batch) {
|
|
198
|
-
if (signal?.aborted || overflowed())
|
|
199
|
-
return;
|
|
200
|
-
yield envelope;
|
|
201
|
-
}
|
|
202
|
-
if (batch.length > 0)
|
|
203
|
-
continue;
|
|
204
|
-
await armAndWait(buffer, overflowed, signal, installWaker);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
function bucketKey(workflowId, selector) {
|
|
208
|
-
return `${workflowId}:${selector}`;
|
|
209
|
-
}
|
|
210
|
-
export function createInMemoryEventBackend() {
|
|
211
|
-
const storage = new Map, listeners = new Map;
|
|
212
|
-
function fireLive(envelope) {
|
|
213
|
-
const set = listeners.get(bucketKey(envelope.workflowId, envelope.selector));
|
|
214
|
-
if (!set)
|
|
215
|
-
return;
|
|
216
|
-
for (const listener of set)
|
|
217
|
-
try {
|
|
218
|
-
listener(envelope);
|
|
219
|
-
} catch {}
|
|
220
|
-
}
|
|
221
|
-
return {
|
|
222
|
-
async* replay(options) {
|
|
223
|
-
const bucket = storage.get(bucketKey(options.workflowId, options.selector));
|
|
224
|
-
if (!bucket)
|
|
225
|
-
return;
|
|
226
|
-
const sorted = [...bucket].toSorted((a, b) => a.sequence - b.sequence);
|
|
227
|
-
for (const envelope of sorted)
|
|
228
|
-
if (envelope.sequence > options.afterSequence)
|
|
229
|
-
yield envelope;
|
|
230
|
-
},
|
|
231
|
-
async snapshotTailSequence(workflowId, selector) {
|
|
232
|
-
const bucket = storage.get(bucketKey(workflowId, selector));
|
|
233
|
-
if (!bucket || bucket.length === 0)
|
|
234
|
-
return -1;
|
|
235
|
-
let max = -1;
|
|
236
|
-
for (const envelope of bucket)
|
|
237
|
-
if (envelope.sequence > max)
|
|
238
|
-
max = envelope.sequence;
|
|
239
|
-
return max;
|
|
240
|
-
},
|
|
241
|
-
subscribeLive(workflowId, selector, listener) {
|
|
242
|
-
const k = bucketKey(workflowId, selector);
|
|
243
|
-
let set = listeners.get(k);
|
|
244
|
-
if (!set) {
|
|
245
|
-
set = new Set;
|
|
246
|
-
listeners.set(k, set);
|
|
247
|
-
}
|
|
248
|
-
set.add(listener);
|
|
249
|
-
return () => {
|
|
250
|
-
set?.delete(listener);
|
|
251
|
-
if (set && set.size === 0)
|
|
252
|
-
listeners.delete(k);
|
|
253
|
-
};
|
|
254
|
-
},
|
|
255
|
-
async append(envelope) {
|
|
256
|
-
const k = bucketKey(envelope.workflowId, envelope.selector);
|
|
257
|
-
let bucket = storage.get(k);
|
|
258
|
-
if (!bucket) {
|
|
259
|
-
bucket = [];
|
|
260
|
-
storage.set(k, bucket);
|
|
261
|
-
}
|
|
262
|
-
bucket.push(envelope);
|
|
263
|
-
fireLive(envelope);
|
|
264
|
-
},
|
|
265
|
-
async emitLive(envelope) {
|
|
266
|
-
fireLive(envelope);
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module service-worker
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
9
|
+
import type { RegistryAgnosticEngine } from '../core/engine';
|
|
10
10
|
import type { ServiceWorkerScheduler } from './scheduler.ts';
|
|
11
11
|
import type { MinimalExtendableEvent, MinimalFetchEvent, MinimalPeriodicSyncEvent } from './shared.ts';
|
|
12
12
|
export { ServiceWorkerScheduler } from './scheduler.ts';
|
|
@@ -36,7 +36,13 @@ export type { MinimalExtendableEvent, MinimalFetchEvent, MinimalPeriodicSyncEven
|
|
|
36
36
|
* ```
|
|
37
37
|
*/
|
|
38
38
|
export interface ServiceWorkerOptions {
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* The engine this handler delegates workflow requests to. Typed as
|
|
41
|
+
* {@link RegistryAgnosticEngine} (see its JSDoc) rather than the plain
|
|
42
|
+
* default `Engine`, so both `new Engine({ storage })` and
|
|
43
|
+
* `Engine.create({ workflows })` type-check here directly.
|
|
44
|
+
*/
|
|
45
|
+
engine: RegistryAgnosticEngine;
|
|
40
46
|
pathPrefix?: string;
|
|
41
47
|
}
|
|
42
48
|
/**
|