@swirls/looms 0.0.2 → 0.2.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/CHANGELOG.md +24 -2
- package/dist/actor/cell.d.ts +9 -4
- package/dist/actor/cell.js +7 -11
- package/dist/actor/host.d.ts +7 -3
- package/dist/actor/host.js +57 -33
- package/dist/actor/index.d.ts +1 -1
- package/dist/actor/index.js +1 -1
- package/dist/actor/routing.d.ts +12 -1
- package/dist/actor/routing.js +57 -51
- package/dist/agent/agent-session.d.ts +5 -0
- package/dist/agent/agent-session.js +270 -0
- package/dist/agent/debugger/agent-chat.d.ts +2 -0
- package/dist/agent/debugger/agent-chat.js +176 -0
- package/dist/agent/debugger/index.d.ts +5 -0
- package/dist/agent/debugger/index.js +19 -0
- package/dist/agent/debugger/summarize.d.ts +2 -0
- package/dist/agent/debugger/summarize.js +51 -0
- package/dist/agent/debugger/token-usage.d.ts +3 -0
- package/dist/agent/debugger/token-usage.js +11 -0
- package/dist/agent/definitions-store.d.ts +2 -3
- package/dist/agent/definitions-store.js +2 -4
- package/dist/agent/definitions.d.ts +47 -29
- package/dist/agent/definitions.js +39 -12
- package/dist/agent/effects.d.ts +359 -2
- package/dist/agent/effects.js +60 -34
- package/dist/agent/events.d.ts +175 -19
- package/dist/agent/events.js +45 -10
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.js +1 -0
- package/dist/agent/llm.d.ts +11 -2
- package/dist/agent/llm.js +13 -3
- package/dist/agent/module.d.ts +812 -78
- package/dist/agent/module.js +16 -4
- package/dist/agent/scope.d.ts +174 -18
- package/dist/agent/signals.d.ts +26 -1
- package/dist/agent/signals.js +79 -0
- package/dist/agent/threads.d.ts +3 -33
- package/dist/agent/threads.js +20 -25
- package/dist/agent/tool-schema.d.ts +1 -17
- package/dist/agent/tool-schema.js +3 -43
- package/dist/agent/types.d.ts +49 -4
- package/dist/agent/types.js +5 -5
- package/dist/ai-vercel/index.d.ts +1 -0
- package/dist/ai-vercel/index.js +1 -0
- package/dist/ai-vercel/messages.js +22 -7
- package/dist/ai-vercel/vercel-evaluator.d.ts +36 -0
- package/dist/ai-vercel/vercel-evaluator.js +73 -0
- package/dist/ai-vercel/vercel-llm.js +64 -44
- package/dist/approval/debugger/approvals-view.d.ts +3 -0
- package/dist/approval/debugger/approvals-view.js +16 -0
- package/dist/approval/debugger/index.d.ts +4 -0
- package/dist/approval/debugger/index.js +11 -0
- package/dist/approval/debugger/summarize.d.ts +2 -0
- package/dist/approval/debugger/summarize.js +17 -0
- package/dist/approval/effects.d.ts +89 -0
- package/dist/approval/module.d.ts +179 -29
- package/dist/approval/projections.d.ts +0 -14
- package/dist/approval/projections.js +20 -3
- package/dist/approval/signals.d.ts +2 -0
- package/dist/approval/signals.js +18 -2
- package/dist/cli/cli.js +2 -0
- package/dist/cli/commands.js +12 -16
- package/dist/client/client.d.ts +1213 -18
- package/dist/client/client.js +120 -120
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/sse.d.ts +13 -0
- package/dist/client/sse.js +38 -44
- package/dist/cloudflare/alarm-scheduler.d.ts +12 -2
- package/dist/cloudflare/alarm-scheduler.js +34 -7
- package/dist/cloudflare/durable-object.d.ts +10 -2
- package/dist/cloudflare/durable-object.js +59 -28
- package/dist/cloudflare/event-store.d.ts +7 -2
- package/dist/cloudflare/event-store.js +8 -7
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.js +2 -2
- package/dist/cloudflare/router.d.ts +1 -1
- package/dist/cloudflare/router.js +15 -16
- package/dist/core/catalog.d.ts +3 -3
- package/dist/core/catalog.js +2 -5
- package/dist/core/coalesce.js +5 -3
- package/dist/core/compose.d.ts +2 -1
- package/dist/core/compose.js +19 -2
- package/dist/core/debugger-host.d.ts +16 -0
- package/dist/core/debugger-host.js +1 -0
- package/dist/core/definition-store.d.ts +11 -0
- package/dist/core/definition-store.js +6 -0
- package/dist/core/effects.d.ts +127 -15
- package/dist/core/effects.js +89 -17
- package/dist/core/envelope.d.ts +27 -7
- package/dist/core/envelope.js +20 -6
- package/dist/core/event-codec.d.ts +4 -2
- package/dist/core/event-codec.js +10 -5
- package/dist/core/event-index.js +1 -3
- package/dist/core/fold.d.ts +3 -0
- package/dist/core/fold.js +171 -24
- package/dist/core/ids.d.ts +5 -0
- package/dist/core/ids.js +35 -2
- package/dist/core/index.d.ts +7 -1
- package/dist/core/index.js +6 -1
- package/dist/core/kind.d.ts +22 -0
- package/dist/core/kind.js +17 -0
- package/dist/core/limits.d.ts +34 -0
- package/dist/core/limits.js +46 -0
- package/dist/core/match.d.ts +1 -0
- package/dist/core/match.js +10 -1
- package/dist/core/module-scope.d.ts +22 -20
- package/dist/core/module-scope.js +38 -28
- package/dist/core/module.d.ts +18 -5
- package/dist/core/module.js +4 -0
- package/dist/core/projection.d.ts +13 -13
- package/dist/core/projection.js +9 -5
- package/dist/core/protocol.d.ts +68 -11
- package/dist/core/protocol.js +82 -11
- package/dist/core/published.d.ts +43 -0
- package/dist/core/published.js +44 -0
- package/dist/core/replay.d.ts +312 -3
- package/dist/core/replay.js +11 -1
- package/dist/core/schema.d.ts +11 -20
- package/dist/core/schema.js +63 -80
- package/dist/core/serialize.js +2 -4
- package/dist/core/snapshot-store.d.ts +6 -1
- package/dist/core/snapshot-store.js +15 -2
- package/dist/core/snapshots.d.ts +5 -1
- package/dist/core/snapshots.js +10 -15
- package/dist/core/sqlite-store.js +95 -11
- package/dist/core/state.d.ts +142 -4
- package/dist/core/state.js +78 -0
- package/dist/core/store.d.ts +38 -3
- package/dist/core/store.js +77 -22
- package/dist/core/thread.d.ts +10 -9
- package/dist/core/types.d.ts +5 -8
- package/dist/core/types.js +28 -24
- package/dist/core/validate-event.js +14 -4
- package/dist/core/worker-callback.d.ts +17 -0
- package/dist/core/worker-callback.js +1 -0
- package/dist/debugger/app/assets/index-B3Ah8WAE.css +2 -0
- package/dist/debugger/app/assets/index-Qb371t_O.js +22 -0
- package/dist/debugger/app/assets/rolldown-runtime-CbXtAM7H.js +1 -0
- package/dist/debugger/app/assets/routes-CjtEHgPQ.js +47 -0
- package/dist/debugger/app/index.html +14 -0
- package/dist/debugger/components/composer.d.ts +17 -0
- package/dist/debugger/components/composer.js +25 -0
- package/dist/debugger/components/debugger-split.d.ts +2 -1
- package/dist/debugger/components/debugger-split.js +2 -2
- package/dist/debugger/components/event-inspector.d.ts +2 -1
- package/dist/debugger/components/event-inspector.js +25 -16
- package/dist/debugger/components/event-stream.d.ts +2 -1
- package/dist/debugger/components/event-stream.js +14 -74
- package/dist/debugger/components/follow-list.d.ts +19 -0
- package/dist/debugger/components/follow-list.js +96 -0
- package/dist/debugger/components/json-tree.d.ts +11 -0
- package/dist/debugger/components/json-tree.js +120 -0
- package/dist/debugger/components/json-view.js +2 -2
- package/dist/debugger/components/run-tree.js +53 -20
- package/dist/debugger/components/status-dot.d.ts +4 -0
- package/dist/debugger/components/status-dot.js +6 -2
- package/dist/debugger/context.d.ts +14 -0
- package/dist/debugger/context.js +17 -0
- package/dist/debugger/contracts.d.ts +7 -4
- package/dist/debugger/events/builtin-families.d.ts +3 -0
- package/dist/debugger/events/builtin-families.js +9 -0
- package/dist/debugger/events/catalog.d.ts +3 -4
- package/dist/debugger/events/catalog.js +27 -17
- package/dist/debugger/events/protocol-summarize.d.ts +1 -2
- package/dist/debugger/events/protocol-summarize.js +42 -24
- package/dist/debugger/index.d.ts +20 -6
- package/dist/debugger/index.js +19 -5
- package/dist/debugger/lib/cn.d.ts +1 -0
- package/dist/debugger/lib/cn.js +3 -0
- package/dist/debugger/lib/event-meta.d.ts +2 -3
- package/dist/debugger/lib/event-meta.js +6 -12
- package/dist/debugger/lib/json.d.ts +25 -0
- package/dist/debugger/lib/json.js +87 -0
- package/dist/debugger/lib/payload.d.ts +7 -0
- package/dist/debugger/lib/payload.js +11 -0
- package/dist/debugger/lib/time.d.ts +3 -0
- package/dist/debugger/lib/time.js +24 -0
- package/dist/debugger/plugin.d.ts +36 -0
- package/dist/debugger/plugin.js +14 -0
- package/dist/debugger/server/index.d.ts +14 -0
- package/dist/debugger/server/index.js +114 -0
- package/dist/debugger/shell/debugger-shell.d.ts +15 -0
- package/dist/debugger/shell/debugger-shell.js +43 -0
- package/dist/debugger/shell/definition-key.d.ts +3 -0
- package/dist/debugger/shell/definition-key.js +4 -0
- package/dist/debugger/shell/events-pane.d.ts +12 -0
- package/dist/debugger/shell/events-pane.js +25 -0
- package/dist/debugger/shell/projections-panel.d.ts +4 -0
- package/dist/debugger/shell/projections-panel.js +59 -0
- package/dist/debugger/shell/run-controls.d.ts +4 -0
- package/dist/debugger/shell/run-controls.js +72 -0
- package/dist/debugger/shell/run-search.d.ts +6 -0
- package/dist/debugger/shell/run-search.js +102 -0
- package/dist/debugger/shell/run-type-menu.d.ts +6 -0
- package/dist/debugger/shell/run-type-menu.js +11 -0
- package/dist/debugger/shell/schema-form.d.ts +31 -0
- package/dist/debugger/shell/schema-form.js +117 -0
- package/dist/debugger/shell/start-form.d.ts +3 -0
- package/dist/debugger/shell/start-form.js +75 -0
- package/dist/debugger/shell/use-start-run.d.ts +14 -0
- package/dist/debugger/shell/use-start-run.js +32 -0
- package/dist/debugger/shell/workspace.d.ts +6 -0
- package/dist/debugger/shell/workspace.js +15 -0
- package/dist/debugger/styles.css +111 -27
- package/dist/debugger/ui/button.d.ts +24 -0
- package/dist/debugger/ui/button.js +24 -0
- package/dist/debugger/ui/command.d.ts +9 -0
- package/dist/debugger/ui/command.js +24 -0
- package/dist/debugger/ui/dropdown-menu.d.ts +13 -0
- package/dist/debugger/ui/dropdown-menu.js +37 -0
- package/dist/debugger/ui/panel.d.ts +14 -0
- package/dist/debugger/ui/panel.js +16 -0
- package/dist/debugger/ui/popover.d.ts +7 -0
- package/dist/debugger/ui/popover.js +17 -0
- package/dist/debugger/ui/resizable.d.ts +7 -0
- package/dist/debugger/ui/resizable.js +14 -0
- package/dist/debugger/ui/scroll-area.d.ts +2 -1
- package/dist/debugger/ui/scroll-area.js +5 -3
- package/dist/debugger/ui/select.d.ts +10 -0
- package/dist/debugger/ui/select.js +21 -0
- package/dist/debugger/ui/tabs.js +2 -2
- package/dist/debugger/ui/textarea.d.ts +3 -0
- package/dist/debugger/ui/textarea.js +7 -0
- package/dist/evaluator/definitions-store.d.ts +11 -0
- package/dist/evaluator/definitions-store.js +8 -0
- package/dist/evaluator/definitions.d.ts +18 -0
- package/dist/evaluator/definitions.js +4 -0
- package/dist/evaluator/effects.d.ts +226 -0
- package/dist/evaluator/effects.js +132 -0
- package/dist/evaluator/evaluator.d.ts +24 -0
- package/dist/evaluator/evaluator.js +67 -0
- package/dist/evaluator/events.d.ts +59 -0
- package/dist/evaluator/events.js +21 -0
- package/dist/evaluator/index.d.ts +11 -0
- package/dist/evaluator/index.js +11 -0
- package/dist/evaluator/module.d.ts +606 -0
- package/dist/evaluator/module.js +25 -0
- package/dist/evaluator/projections.d.ts +50 -0
- package/dist/evaluator/projections.js +20 -0
- package/dist/evaluator/scope.d.ts +59 -0
- package/dist/evaluator/scope.js +7 -0
- package/dist/evaluator/signals.d.ts +3 -0
- package/dist/evaluator/signals.js +17 -0
- package/dist/evaluator/threads.d.ts +62 -0
- package/dist/evaluator/threads.js +117 -0
- package/dist/evaluator/types.d.ts +125 -0
- package/dist/evaluator/types.js +51 -0
- package/dist/projectors/delivery.d.ts +83 -0
- package/dist/projectors/delivery.js +182 -0
- package/dist/projectors/index-model.d.ts +1 -1
- package/dist/projectors/index-model.js +4 -6
- package/dist/projectors/index.d.ts +2 -0
- package/dist/projectors/index.js +2 -0
- package/dist/projectors/memory.d.ts +1 -1
- package/dist/projectors/memory.js +10 -8
- package/dist/projectors/postgres.js +44 -58
- package/dist/projectors/projector.d.ts +17 -0
- package/dist/projectors/projector.js +26 -1
- package/dist/projectors/sqlite-delivery.d.ts +4 -0
- package/dist/projectors/sqlite-delivery.js +147 -0
- package/dist/projectors/sqlite.js +23 -23
- package/dist/projectors/with-projectors.d.ts +7 -2
- package/dist/projectors/with-projectors.js +27 -28
- package/dist/react/notify.js +11 -8
- package/dist/react/react.d.ts +2 -3
- package/dist/react/react.js +14 -30
- package/dist/react/sse.d.ts +1 -1
- package/dist/react/sse.js +1 -1
- package/dist/react/store.d.ts +3 -3
- package/dist/react/store.js +109 -119
- package/dist/runtime/cancellation.d.ts +16 -0
- package/dist/runtime/cancellation.js +129 -0
- package/dist/runtime/deadline-transition-planner.d.ts +31 -0
- package/dist/runtime/deadline-transition-planner.js +139 -0
- package/dist/runtime/dispatch-effect.d.ts +3 -2
- package/dist/runtime/dispatch-effect.js +7 -13
- package/dist/runtime/errors.d.ts +51 -0
- package/dist/runtime/errors.js +39 -0
- package/dist/runtime/{runtime-helpers.d.ts → helpers.d.ts} +24 -4
- package/dist/runtime/{runtime-helpers.js → helpers.js} +56 -19
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/index.js +3 -3
- package/dist/runtime/ingress.d.ts +15 -0
- package/dist/runtime/ingress.js +42 -0
- package/dist/runtime/local-effect-executor.d.ts +21 -0
- package/dist/runtime/local-effect-executor.js +137 -0
- package/dist/runtime/looms.d.ts +30 -4
- package/dist/runtime/looms.js +57 -37
- package/dist/runtime/observer.d.ts +45 -0
- package/dist/runtime/observer.js +11 -0
- package/dist/runtime/repository.d.ts +55 -0
- package/dist/runtime/repository.js +293 -0
- package/dist/runtime/retry-policy.d.ts +16 -0
- package/dist/runtime/retry-policy.js +29 -0
- package/dist/runtime/run-execution-context.d.ts +30 -0
- package/dist/runtime/run-execution-context.js +56 -0
- package/dist/runtime/run-start.d.ts +4 -0
- package/dist/runtime/run-start.js +44 -0
- package/dist/runtime/runtime.d.ts +6 -87
- package/dist/runtime/runtime.js +248 -470
- package/dist/runtime/server/auth.d.ts +41 -0
- package/dist/runtime/server/auth.js +45 -0
- package/dist/runtime/server/debugger-host.d.ts +11 -0
- package/dist/runtime/server/debugger-host.js +32 -0
- package/dist/runtime/server/fetch-handler.d.ts +18 -0
- package/dist/runtime/server/fetch-handler.js +62 -0
- package/dist/runtime/server/http.d.ts +38 -0
- package/dist/runtime/server/http.js +66 -0
- package/dist/runtime/server/route-table.d.ts +55 -0
- package/dist/runtime/server/route-table.js +74 -0
- package/dist/runtime/server/routes/definitions.d.ts +3 -0
- package/dist/runtime/server/routes/definitions.js +20 -0
- package/dist/runtime/server/routes/effects.d.ts +3 -0
- package/dist/runtime/server/routes/effects.js +59 -0
- package/dist/runtime/server/routes/operations.d.ts +3 -0
- package/dist/runtime/server/routes/operations.js +14 -0
- package/dist/runtime/server/routes/runs.d.ts +3 -0
- package/dist/runtime/server/routes/runs.js +199 -0
- package/dist/runtime/server.d.ts +4 -8
- package/dist/runtime/server.js +6 -211
- package/dist/runtime/sse.d.ts +2 -1
- package/dist/runtime/sse.js +24 -17
- package/dist/runtime/types.d.ts +117 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/wake-engine.d.ts +20 -0
- package/dist/runtime/wake-engine.js +311 -0
- package/dist/runtime/wake-scheduler.d.ts +3 -4
- package/dist/runtime/wake-scheduler.js +25 -31
- package/dist/runtime/worker-callbacks.d.ts +16 -0
- package/dist/runtime/worker-callbacks.js +167 -0
- package/dist/runtime/worker-effect-dispatch.d.ts +36 -0
- package/dist/runtime/worker-effect-dispatch.js +126 -0
- package/dist/s2/config.d.ts +1 -1
- package/dist/s2/config.js +1 -1
- package/dist/s2/lite.js +70 -82
- package/dist/s2/pagination.d.ts +15 -0
- package/dist/s2/pagination.js +36 -0
- package/dist/s2/projector.js +6 -5
- package/dist/s2/snapshot-store.js +188 -161
- package/dist/s2/store.d.ts +3 -21
- package/dist/s2/store.js +71 -165
- package/dist/testing/index.d.ts +15 -0
- package/dist/testing/index.js +53 -16
- package/dist/workflow/debugger/index.d.ts +4 -0
- package/dist/workflow/debugger/index.js +11 -0
- package/dist/workflow/debugger/nodes-view.d.ts +3 -0
- package/dist/workflow/debugger/nodes-view.js +13 -0
- package/dist/workflow/debugger/summarize.d.ts +2 -0
- package/dist/workflow/debugger/summarize.js +30 -0
- package/dist/workflow/definitions-store.d.ts +2 -3
- package/dist/workflow/definitions-store.js +2 -2
- package/dist/workflow/definitions.d.ts +78 -22
- package/dist/workflow/definitions.js +80 -14
- package/dist/workflow/effects.d.ts +453 -107
- package/dist/workflow/effects.js +214 -115
- package/dist/workflow/events.d.ts +149 -5
- package/dist/workflow/events.js +27 -5
- package/dist/workflow/graph.d.ts +56 -0
- package/dist/workflow/graph.js +207 -0
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.js +1 -0
- package/dist/workflow/module.d.ts +1047 -266
- package/dist/workflow/projections.d.ts +14 -12
- package/dist/workflow/projections.js +30 -8
- package/dist/workflow/scope.d.ts +146 -4
- package/dist/workflow/threads.d.ts +383 -155
- package/dist/workflow/threads.js +308 -110
- package/package.json +26 -2
- package/dist/debugger/events/domain-summarize.d.ts +0 -3
- package/dist/debugger/events/domain-summarize.js +0 -107
- package/dist/debugger/events/family.d.ts +0 -8
- package/dist/debugger/events/family.js +0 -44
- package/dist/runtime/events-api.d.ts +0 -4
- package/dist/runtime/events-api.js +0 -84
package/dist/core/effects.js
CHANGED
|
@@ -1,6 +1,54 @@
|
|
|
1
|
-
import { Effect, Predicate } from 'effect';
|
|
2
|
-
import {
|
|
1
|
+
import { Data, Effect, Predicate, Schema } from 'effect';
|
|
2
|
+
import { EventInputSchema } from './envelope.js';
|
|
3
|
+
import { DEFAULT_DEFINITION_VERSION } from './module.js';
|
|
4
|
+
import { validateInputEffect, } from './schema.js';
|
|
3
5
|
import { asJson } from './types.js';
|
|
6
|
+
export const WaitConditionSchema = Schema.Union([
|
|
7
|
+
Schema.Struct({
|
|
8
|
+
type: Schema.Union([Schema.String, Schema.Array(Schema.String)]),
|
|
9
|
+
match: Schema.optional(Schema.Json),
|
|
10
|
+
}),
|
|
11
|
+
Schema.Struct({ timerAt: Schema.Finite }),
|
|
12
|
+
]);
|
|
13
|
+
export const RuntimeEffectSchema = Schema.Union([
|
|
14
|
+
Schema.Struct({
|
|
15
|
+
type: Schema.Literal('runtime.spawn'),
|
|
16
|
+
childThreadId: Schema.String,
|
|
17
|
+
kind: Schema.String,
|
|
18
|
+
definitionName: Schema.String,
|
|
19
|
+
definitionVersion: Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed(DEFAULT_DEFINITION_VERSION))),
|
|
20
|
+
input: Schema.Json,
|
|
21
|
+
}),
|
|
22
|
+
Schema.Struct({
|
|
23
|
+
type: Schema.Literal('runtime.wait'),
|
|
24
|
+
waitId: Schema.String,
|
|
25
|
+
on: WaitConditionSchema,
|
|
26
|
+
tag: Schema.optional(Schema.Json),
|
|
27
|
+
}),
|
|
28
|
+
Schema.Struct({
|
|
29
|
+
type: Schema.Literal('runtime.emit'),
|
|
30
|
+
event: EventInputSchema,
|
|
31
|
+
tag: Schema.optional(Schema.String),
|
|
32
|
+
}),
|
|
33
|
+
Schema.Struct({
|
|
34
|
+
type: Schema.Literal('runtime.complete'),
|
|
35
|
+
output: Schema.Json,
|
|
36
|
+
}),
|
|
37
|
+
Schema.Struct({
|
|
38
|
+
type: Schema.Literal('runtime.fail'),
|
|
39
|
+
error: Schema.String,
|
|
40
|
+
}),
|
|
41
|
+
Schema.Struct({
|
|
42
|
+
type: Schema.Literal('runtime.cancel'),
|
|
43
|
+
threadId: Schema.String,
|
|
44
|
+
tag: Schema.optional(Schema.String),
|
|
45
|
+
}),
|
|
46
|
+
Schema.Struct({
|
|
47
|
+
type: Schema.String,
|
|
48
|
+
input: Schema.Json,
|
|
49
|
+
tag: Schema.optional(Schema.String),
|
|
50
|
+
}),
|
|
51
|
+
]);
|
|
4
52
|
export function isPrimitiveEffect(effect) {
|
|
5
53
|
switch (effect.type) {
|
|
6
54
|
case 'runtime.spawn':
|
|
@@ -27,35 +75,40 @@ export function withdrawnError(siblingEffectId) {
|
|
|
27
75
|
export function isWithdrawnError(error) {
|
|
28
76
|
return error.startsWith(WITHDRAWN_ERROR_PREFIX);
|
|
29
77
|
}
|
|
78
|
+
export class EffectHandlerError extends Data.TaggedError('EffectHandlerError') {
|
|
79
|
+
constructor(cause) {
|
|
80
|
+
super({
|
|
81
|
+
cause,
|
|
82
|
+
message: cause instanceof Error ? cause.message : String(cause),
|
|
83
|
+
});
|
|
84
|
+
this.name = 'EffectHandlerError';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
30
87
|
function liftHandlerResult(result) {
|
|
31
88
|
if (Effect.isEffect(result)) {
|
|
32
|
-
return result;
|
|
89
|
+
return result.pipe(Effect.mapError((cause) => new EffectHandlerError(cause)));
|
|
33
90
|
}
|
|
34
91
|
if (result instanceof Promise) {
|
|
35
92
|
return Effect.tryPromise({
|
|
36
93
|
try: () => result,
|
|
37
|
-
catch: (cause) =>
|
|
94
|
+
catch: (cause) => new EffectHandlerError(cause),
|
|
38
95
|
});
|
|
39
96
|
}
|
|
40
97
|
return Effect.succeed(result);
|
|
41
98
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Define an effect handler. A run's actor cell executes each effect at most
|
|
44
|
-
* once while it is alive. If the cell dies mid-execution, the replacement
|
|
45
|
-
* actor may re-run the handler (at-least-once across failover). Keep handlers
|
|
46
|
-
* idempotent when they have external side effects.
|
|
47
|
-
*/
|
|
48
99
|
export function defineEffect(def) {
|
|
49
100
|
const schema = def.input;
|
|
50
|
-
|
|
101
|
+
const handler = def.execute;
|
|
102
|
+
const noOutput = [];
|
|
51
103
|
return {
|
|
52
104
|
type: def.type,
|
|
53
105
|
input: schema,
|
|
54
106
|
retry: def.retry,
|
|
107
|
+
execution: def.execution,
|
|
108
|
+
hasHandler: handler !== undefined,
|
|
55
109
|
execute: (raw, ctx) => Effect.gen(function* () {
|
|
56
110
|
const input = schema ? yield* validateInputEffect(schema, raw) : raw;
|
|
57
|
-
|
|
58
|
-
return yield* liftHandlerResult(def.execute(input, ctx));
|
|
111
|
+
return handler ? yield* liftHandlerResult(handler(input, ctx)) : noOutput;
|
|
59
112
|
}),
|
|
60
113
|
};
|
|
61
114
|
}
|
|
@@ -66,6 +119,7 @@ export function spawn(args) {
|
|
|
66
119
|
childThreadId,
|
|
67
120
|
kind: args.kind,
|
|
68
121
|
definitionName: args.definitionName,
|
|
122
|
+
definitionVersion: args.definitionVersion ?? DEFAULT_DEFINITION_VERSION,
|
|
69
123
|
input: args.input,
|
|
70
124
|
};
|
|
71
125
|
}
|
|
@@ -80,8 +134,24 @@ export function wait(args) {
|
|
|
80
134
|
}
|
|
81
135
|
return effect;
|
|
82
136
|
}
|
|
83
|
-
|
|
84
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Reads the outcome of a satisfied wait. The wait fails when the satisfying event's payload has an
|
|
139
|
+
* `error`, or when the waiter put an `error` on the wait's tag (such as a timeout that loses a
|
|
140
|
+
* race). Otherwise the result is the payload's `output`, else the whole payload.
|
|
141
|
+
*/
|
|
142
|
+
export function waitOutcome(satisfied, tag, fallback = null) {
|
|
143
|
+
const payload = Predicate.isObject(satisfied) && Predicate.isObject(satisfied.payload) ? satisfied.payload : {};
|
|
144
|
+
const tagError = Predicate.isObject(tag) && Predicate.isString(tag.error) ? tag.error : null;
|
|
145
|
+
const error = Predicate.isString(payload.error) ? payload.error : tagError;
|
|
146
|
+
if (error !== null) {
|
|
147
|
+
return { result: null, error };
|
|
148
|
+
}
|
|
149
|
+
const result = payload.output ?? (Predicate.isObject(satisfied) ? satisfied.payload : fallback);
|
|
150
|
+
// SAFETY: wait results are persisted JSON event payloads.
|
|
151
|
+
return { result: asJson(result) ?? null, error: null };
|
|
152
|
+
}
|
|
153
|
+
export function emit(event, tag) {
|
|
154
|
+
return tag === undefined ? { type: 'runtime.emit', event } : { type: 'runtime.emit', event, tag };
|
|
85
155
|
}
|
|
86
156
|
export function complete(output) {
|
|
87
157
|
return { type: 'runtime.complete', output };
|
|
@@ -89,8 +159,10 @@ export function complete(output) {
|
|
|
89
159
|
export function fail(error) {
|
|
90
160
|
return { type: 'runtime.fail', error };
|
|
91
161
|
}
|
|
92
|
-
export function cancel(threadId) {
|
|
93
|
-
return
|
|
162
|
+
export function cancel(threadId, tag) {
|
|
163
|
+
return tag === undefined
|
|
164
|
+
? { type: 'runtime.cancel', threadId }
|
|
165
|
+
: { type: 'runtime.cancel', threadId, tag };
|
|
94
166
|
}
|
|
95
167
|
export function invoke(typeOrDef, input, tag) {
|
|
96
168
|
const type = Predicate.isString(typeOrDef) ? typeOrDef : typeOrDef.type;
|
package/dist/core/envelope.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema } from 'effect';
|
|
2
|
-
import type
|
|
2
|
+
import { type JsonValue } from './types';
|
|
3
3
|
export declare const JsonValueSchema: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
4
4
|
export declare const EventOriginSchema: Schema.Union<readonly [Schema.Struct<{
|
|
5
5
|
readonly type: Schema.Literal<"thread">;
|
|
@@ -14,8 +14,8 @@ export type EventOrigin = Schema.Schema.Type<typeof EventOriginSchema>;
|
|
|
14
14
|
export declare const EventEnvelopeSchema: Schema.Struct<{
|
|
15
15
|
readonly id: Schema.String;
|
|
16
16
|
readonly runId: Schema.String;
|
|
17
|
-
readonly seq: Schema.
|
|
18
|
-
readonly ts: Schema.
|
|
17
|
+
readonly seq: Schema.Finite;
|
|
18
|
+
readonly ts: Schema.Finite;
|
|
19
19
|
readonly type: Schema.String;
|
|
20
20
|
readonly payload: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
21
21
|
readonly threadId: Schema.NullOr<Schema.String>;
|
|
@@ -35,6 +35,28 @@ export declare const EventEnvelopeSchema: Schema.Struct<{
|
|
|
35
35
|
readonly ephemeral: Schema.optional<Schema.Boolean>;
|
|
36
36
|
readonly idempotencyKey: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
37
37
|
}>;
|
|
38
|
+
export declare const EventInputSchema: Schema.Struct<{
|
|
39
|
+
readonly type: Schema.String;
|
|
40
|
+
readonly payload: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
41
|
+
readonly threadId: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
42
|
+
readonly parentThreadId: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
43
|
+
readonly causationId: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
44
|
+
readonly correlationId: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
45
|
+
readonly effectId: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
46
|
+
readonly origin: Schema.optional<Schema.Union<readonly [Schema.Struct<{
|
|
47
|
+
readonly type: Schema.Literal<"thread">;
|
|
48
|
+
readonly threadId: Schema.String;
|
|
49
|
+
}>, Schema.Struct<{
|
|
50
|
+
readonly type: Schema.Literal<"external">;
|
|
51
|
+
readonly actorId: Schema.optional<Schema.String>;
|
|
52
|
+
}>, Schema.Struct<{
|
|
53
|
+
readonly type: Schema.Literal<"system">;
|
|
54
|
+
}>]>>;
|
|
55
|
+
readonly ephemeral: Schema.optional<Schema.Boolean>;
|
|
56
|
+
readonly id: Schema.optional<Schema.String>;
|
|
57
|
+
readonly ts: Schema.optional<Schema.Finite>;
|
|
58
|
+
readonly idempotencyKey: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
59
|
+
}>;
|
|
38
60
|
export type EventEnvelope<TType extends string = string, TPayload = JsonValue> = {
|
|
39
61
|
id: string;
|
|
40
62
|
runId: string;
|
|
@@ -71,9 +93,7 @@ export type AppendableEvent = Omit<EventEnvelope, 'seq'> & {
|
|
|
71
93
|
};
|
|
72
94
|
export declare function payloadAsJson(payload: JsonValue): JsonValue;
|
|
73
95
|
export declare function withAssignedSeq(partial: AppendableEvent, runId: string, seq: number): EventEnvelope;
|
|
74
|
-
export declare function createEvent<TType extends string>(runId: string, input:
|
|
75
|
-
type: TType;
|
|
76
|
-
}, options?: {
|
|
96
|
+
export declare function createEvent<TType extends string, TPayload = JsonValue>(runId: string, input: EventInput<TType, TPayload>, options?: {
|
|
77
97
|
seq?: number;
|
|
78
|
-
}): EventEnvelope<TType>;
|
|
98
|
+
}): EventEnvelope<TType, TPayload>;
|
|
79
99
|
export declare function fromWireEvent(wire: Schema.Schema.Type<typeof EventEnvelopeSchema>): EventEnvelope;
|
package/dist/core/envelope.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Schema } from 'effect';
|
|
1
|
+
import { DateTime, Schema } from 'effect';
|
|
2
2
|
import { createEventId } from './ids.js';
|
|
3
|
+
import { cleanUndefined } from './types.js';
|
|
3
4
|
export const JsonValueSchema = Schema.Json;
|
|
4
5
|
export const EventOriginSchema = Schema.Union([
|
|
5
6
|
Schema.Struct({
|
|
@@ -17,8 +18,8 @@ export const EventOriginSchema = Schema.Union([
|
|
|
17
18
|
export const EventEnvelopeSchema = Schema.Struct({
|
|
18
19
|
id: Schema.String,
|
|
19
20
|
runId: Schema.String,
|
|
20
|
-
seq: Schema.
|
|
21
|
-
ts: Schema.
|
|
21
|
+
seq: Schema.Finite,
|
|
22
|
+
ts: Schema.Finite,
|
|
22
23
|
type: Schema.String,
|
|
23
24
|
payload: JsonValueSchema,
|
|
24
25
|
threadId: Schema.NullOr(Schema.String),
|
|
@@ -30,9 +31,22 @@ export const EventEnvelopeSchema = Schema.Struct({
|
|
|
30
31
|
ephemeral: Schema.optional(Schema.Boolean),
|
|
31
32
|
idempotencyKey: Schema.optional(Schema.NullOr(Schema.String)),
|
|
32
33
|
});
|
|
34
|
+
export const EventInputSchema = Schema.Struct({
|
|
35
|
+
type: Schema.String,
|
|
36
|
+
payload: JsonValueSchema,
|
|
37
|
+
threadId: Schema.optional(Schema.NullOr(Schema.String)),
|
|
38
|
+
parentThreadId: Schema.optional(Schema.NullOr(Schema.String)),
|
|
39
|
+
causationId: Schema.optional(Schema.NullOr(Schema.String)),
|
|
40
|
+
correlationId: Schema.optional(Schema.NullOr(Schema.String)),
|
|
41
|
+
effectId: Schema.optional(Schema.NullOr(Schema.String)),
|
|
42
|
+
origin: Schema.optional(EventOriginSchema),
|
|
43
|
+
ephemeral: Schema.optional(Schema.Boolean),
|
|
44
|
+
id: Schema.optional(Schema.String),
|
|
45
|
+
ts: Schema.optional(Schema.Finite),
|
|
46
|
+
idempotencyKey: Schema.optional(Schema.NullOr(Schema.String)),
|
|
47
|
+
});
|
|
33
48
|
export function payloadAsJson(payload) {
|
|
34
|
-
|
|
35
|
-
return JSON.parse(JSON.stringify(payload));
|
|
49
|
+
return cleanUndefined(payload);
|
|
36
50
|
}
|
|
37
51
|
export function withAssignedSeq(partial, runId, seq) {
|
|
38
52
|
return { ...partial, runId, seq };
|
|
@@ -44,7 +58,7 @@ export function createEvent(runId, input, options) {
|
|
|
44
58
|
id: input.id ?? createEventId(),
|
|
45
59
|
runId,
|
|
46
60
|
seq: options?.seq ?? 0,
|
|
47
|
-
ts: input.ts ??
|
|
61
|
+
ts: input.ts ?? DateTime.toEpochMillis(DateTime.nowUnsafe()),
|
|
48
62
|
type: input.type,
|
|
49
63
|
payload: input.payload,
|
|
50
64
|
threadId,
|
|
@@ -2,7 +2,9 @@ import type { AppendableEvent, EventEnvelope } from './envelope';
|
|
|
2
2
|
import type { JsonValue } from './types';
|
|
3
3
|
/** JSON-safe event envelope for SSE and pull responses. */
|
|
4
4
|
export type EncodedLoomsEvent = EventEnvelope;
|
|
5
|
+
type EventWireInput = JsonValue | Partial<EncodedLoomsEvent>;
|
|
5
6
|
export declare function encodeLoomsEvent(event: EventEnvelope): EncodedLoomsEvent;
|
|
6
7
|
export declare function encodeAppendableEvent(event: AppendableEvent): EncodedLoomsEvent;
|
|
7
|
-
export declare function decodeLoomsEvent(raw:
|
|
8
|
-
export declare function decodeAppendableEvent(raw:
|
|
8
|
+
export declare function decodeLoomsEvent(raw: EventWireInput, runId: string): EventEnvelope;
|
|
9
|
+
export declare function decodeAppendableEvent(raw: EventWireInput, runId: string): AppendableEvent | undefined;
|
|
10
|
+
export {};
|
package/dist/core/event-codec.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Predicate } from 'effect';
|
|
1
|
+
import { DateTime, Predicate, Schema } from 'effect';
|
|
2
2
|
import { createEvent, payloadAsJson } from './envelope.js';
|
|
3
3
|
import { createEventId } from './ids.js';
|
|
4
|
+
const decodeJsonValue = Schema.decodeUnknownSync(Schema.Json);
|
|
4
5
|
export function encodeLoomsEvent(event) {
|
|
5
6
|
return {
|
|
6
7
|
...event,
|
|
@@ -12,7 +13,7 @@ export function encodeAppendableEvent(event) {
|
|
|
12
13
|
id: event.id ?? createEventId(),
|
|
13
14
|
runId: event.runId,
|
|
14
15
|
seq: event.seq ?? 0,
|
|
15
|
-
ts: event.ts ??
|
|
16
|
+
ts: event.ts ?? DateTime.toEpochMillis(DateTime.nowUnsafe()),
|
|
16
17
|
type: event.type,
|
|
17
18
|
payload: payloadAsJson(event.payload),
|
|
18
19
|
threadId: event.threadId ?? null,
|
|
@@ -25,6 +26,9 @@ export function encodeAppendableEvent(event) {
|
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
function readOrigin(raw) {
|
|
29
|
+
if (!Predicate.isReadonlyObject(raw)) {
|
|
30
|
+
return { type: 'system' };
|
|
31
|
+
}
|
|
28
32
|
if ('type' in raw && raw.type === 'thread') {
|
|
29
33
|
const threadId = 'threadId' in raw && Predicate.isString(raw.threadId) ? raw.threadId : '';
|
|
30
34
|
return { type: 'thread', threadId };
|
|
@@ -41,10 +45,11 @@ export function decodeLoomsEvent(raw, runId) {
|
|
|
41
45
|
}
|
|
42
46
|
if ('type' in raw && Predicate.isString(raw.type)) {
|
|
43
47
|
const rawPayload = 'payload' in raw ? raw.payload : {};
|
|
44
|
-
|
|
45
|
-
const payload = rawPayload;
|
|
48
|
+
const payload = decodeJsonValue(rawPayload);
|
|
46
49
|
const id = 'id' in raw && Predicate.isString(raw.id) ? raw.id : createEventId();
|
|
47
|
-
const ts = 'ts' in raw && Predicate.isNumber(raw.ts)
|
|
50
|
+
const ts = 'ts' in raw && Predicate.isNumber(raw.ts)
|
|
51
|
+
? raw.ts
|
|
52
|
+
: DateTime.toEpochMillis(DateTime.nowUnsafe());
|
|
48
53
|
const seq = 'seq' in raw && Predicate.isNumber(raw.seq) ? raw.seq : 0;
|
|
49
54
|
const ephemeral = 'ephemeral' in raw && Predicate.isBoolean(raw.ephemeral) ? raw.ephemeral : false;
|
|
50
55
|
const itemRunId = 'runId' in raw && Predicate.isString(raw.runId) ? raw.runId : runId;
|
package/dist/core/event-index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const EMPTY_EVENTS = Object.freeze([]);
|
|
2
1
|
/** Thread bucket key used by run-tree counts (`threadId` or `'run'` for run-scoped). */
|
|
3
2
|
export function eventThreadKey(event) {
|
|
4
3
|
return event.threadId ?? 'run';
|
|
@@ -60,8 +59,7 @@ export class EventIndex {
|
|
|
60
59
|
}
|
|
61
60
|
getByThread(threadId) {
|
|
62
61
|
this.publish();
|
|
63
|
-
|
|
64
|
-
return this.byThreadSnapshots.get(threadId) ?? EMPTY_EVENTS;
|
|
62
|
+
return this.byThreadSnapshots.get(threadId) ?? [];
|
|
65
63
|
}
|
|
66
64
|
getBySeq(seq) {
|
|
67
65
|
return this.bySeqMap.get(seq);
|
package/dist/core/fold.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { Stream, type Effect } from 'effect';
|
|
2
|
+
import { type RuntimeEffect } from './effects';
|
|
2
3
|
import type { EventEnvelope } from './envelope';
|
|
3
4
|
import type { RunState } from './state';
|
|
4
5
|
import { type ThreadDefinition } from './thread';
|
|
5
6
|
export interface FoldRegistry {
|
|
6
7
|
readonly threads: ReadonlyMap<string, ThreadDefinition>;
|
|
7
8
|
}
|
|
9
|
+
/** The id an effect keeps across folds when it names itself by tag, wait id, or child thread. */
|
|
10
|
+
export declare function stableEffectId(threadId: string, effect: RuntimeEffect): string | undefined;
|
|
8
11
|
export declare function foldEvent(state: RunState, event: EventEnvelope, registry: FoldRegistry): RunState;
|
|
9
12
|
export declare function foldRun(events: readonly EventEnvelope[], registry: FoldRegistry, options?: {
|
|
10
13
|
runId?: string;
|
package/dist/core/fold.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { Predicate, Stream } from 'effect';
|
|
2
|
-
import { isWithdrawnError } from './effects.js';
|
|
1
|
+
import { Option, Predicate, Schema, Stream } from 'effect';
|
|
2
|
+
import { isWithdrawnError, WaitConditionSchema } from './effects.js';
|
|
3
3
|
import { createEffectId } from './ids.js';
|
|
4
|
+
import { DEFAULT_DEFINITION_VERSION } from './module.js';
|
|
4
5
|
import { emptyRunState } from './state.js';
|
|
5
6
|
import { isTerminalStatus } from './thread.js';
|
|
7
|
+
const decodeWaitCondition = Schema.decodeUnknownOption(WaitConditionSchema);
|
|
6
8
|
function payloadObject(event) {
|
|
7
9
|
const payload = event.payload;
|
|
8
10
|
if (payload === null || Array.isArray(payload)) {
|
|
@@ -22,9 +24,11 @@ function cloneState(state) {
|
|
|
22
24
|
runId: state.runId,
|
|
23
25
|
status: state.status,
|
|
24
26
|
rootThreadId: state.rootThreadId,
|
|
27
|
+
startIdentity: state.startIdentity,
|
|
25
28
|
threads: { ...state.threads },
|
|
26
29
|
waits: { ...state.waits },
|
|
27
30
|
outstandingEffects: [...state.outstandingEffects],
|
|
31
|
+
effectExecutions: { ...state.effectExecutions },
|
|
28
32
|
completedEffectIds: state.completedEffectIds ? [...state.completedEffectIds] : [],
|
|
29
33
|
processedIdempotencyKeys: state.processedIdempotencyKeys
|
|
30
34
|
? [...state.processedIdempotencyKeys]
|
|
@@ -33,9 +37,11 @@ function cloneState(state) {
|
|
|
33
37
|
}
|
|
34
38
|
function completeEffect(state, effectId) {
|
|
35
39
|
const completed = state.completedEffectIds ?? [];
|
|
40
|
+
const { [effectId]: _completedExecution, ...effectExecutions } = state.effectExecutions ?? {};
|
|
36
41
|
return {
|
|
37
42
|
...state,
|
|
38
43
|
outstandingEffects: state.outstandingEffects.filter((item) => item.effectId !== effectId),
|
|
44
|
+
effectExecutions,
|
|
39
45
|
completedEffectIds: completed.includes(effectId) ? completed : [...completed, effectId],
|
|
40
46
|
};
|
|
41
47
|
}
|
|
@@ -75,18 +81,41 @@ function applyProtocol(state, event, registry) {
|
|
|
75
81
|
const payload = payloadObject(event);
|
|
76
82
|
switch (event.type) {
|
|
77
83
|
case 'runtime.run.started': {
|
|
78
|
-
const rootThreadId = readString(payload, 'rootThreadId')
|
|
79
|
-
|
|
84
|
+
const rootThreadId = readString(payload, 'rootThreadId');
|
|
85
|
+
const kind = readString(payload, 'kind');
|
|
86
|
+
const definitionName = readString(payload, 'definitionName');
|
|
87
|
+
const definitionVersion = readString(payload, 'definitionVersion') ?? DEFAULT_DEFINITION_VERSION;
|
|
88
|
+
const startIdentity = rootThreadId && kind && definitionName && definitionVersion
|
|
89
|
+
? {
|
|
90
|
+
kind,
|
|
91
|
+
definitionName,
|
|
92
|
+
definitionVersion,
|
|
93
|
+
input: payload.input ?? null,
|
|
94
|
+
requestedThreadId: readString(payload, 'requestedThreadId') ?? null,
|
|
95
|
+
idempotencyKey: event.idempotencyKey ?? null,
|
|
96
|
+
rootThreadId,
|
|
97
|
+
}
|
|
98
|
+
: null;
|
|
99
|
+
return {
|
|
100
|
+
...state,
|
|
101
|
+
runId: event.runId,
|
|
102
|
+
rootThreadId: rootThreadId ?? null,
|
|
103
|
+
startIdentity,
|
|
104
|
+
status: 'running',
|
|
105
|
+
};
|
|
80
106
|
}
|
|
81
107
|
case 'runtime.run.completed': {
|
|
82
108
|
const error = payload.error;
|
|
83
109
|
const status = Predicate.isString(error) && error.length > 0 ? 'failed' : 'completed';
|
|
84
110
|
return { ...state, status };
|
|
85
111
|
}
|
|
112
|
+
case 'runtime.run.cancelled':
|
|
113
|
+
return { ...state, status: 'cancelled' };
|
|
86
114
|
case 'runtime.thread.started': {
|
|
87
115
|
const threadId = readString(payload, 'threadId') ?? event.threadId;
|
|
88
116
|
const kind = readString(payload, 'kind');
|
|
89
117
|
const definitionName = readString(payload, 'definitionName');
|
|
118
|
+
const definitionVersion = readString(payload, 'definitionVersion') ?? DEFAULT_DEFINITION_VERSION;
|
|
90
119
|
if (!threadId || !kind || !definitionName) {
|
|
91
120
|
return state;
|
|
92
121
|
}
|
|
@@ -98,6 +127,7 @@ function applyProtocol(state, event, registry) {
|
|
|
98
127
|
threadId,
|
|
99
128
|
kind,
|
|
100
129
|
definitionName,
|
|
130
|
+
definitionVersion,
|
|
101
131
|
parentThreadId,
|
|
102
132
|
status: definition ? 'running' : 'failed',
|
|
103
133
|
input,
|
|
@@ -109,6 +139,7 @@ function applyProtocol(state, event, registry) {
|
|
|
109
139
|
threadId,
|
|
110
140
|
parentThreadId,
|
|
111
141
|
definitionName,
|
|
142
|
+
definitionVersion,
|
|
112
143
|
input,
|
|
113
144
|
})
|
|
114
145
|
: {},
|
|
@@ -156,7 +187,7 @@ function applyProtocol(state, event, registry) {
|
|
|
156
187
|
return state;
|
|
157
188
|
}
|
|
158
189
|
const existing = state.threads[threadId];
|
|
159
|
-
if (!existing) {
|
|
190
|
+
if (!existing || isTerminalStatus(existing.status)) {
|
|
160
191
|
return state;
|
|
161
192
|
}
|
|
162
193
|
return dropThreadWork(putThread(state, {
|
|
@@ -165,6 +196,111 @@ function applyProtocol(state, event, registry) {
|
|
|
165
196
|
error: readString(payload, 'reason') ?? existing.error,
|
|
166
197
|
}), threadId);
|
|
167
198
|
}
|
|
199
|
+
case 'runtime.effect.attempt.started': {
|
|
200
|
+
const effectId = readString(payload, 'effectId');
|
|
201
|
+
const attempt = payload.attempt;
|
|
202
|
+
if (!effectId || !Predicate.isNumber(attempt)) {
|
|
203
|
+
return state;
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
...state,
|
|
207
|
+
effectExecutions: {
|
|
208
|
+
...state.effectExecutions,
|
|
209
|
+
[effectId]: {
|
|
210
|
+
effectId,
|
|
211
|
+
attempt,
|
|
212
|
+
status: 'running',
|
|
213
|
+
nextAttemptAt: null,
|
|
214
|
+
deadlineAt: null,
|
|
215
|
+
startedAt: event.ts,
|
|
216
|
+
lastHeartbeatAt: null,
|
|
217
|
+
lastError: null,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
case 'runtime.effect.queued':
|
|
223
|
+
case 'runtime.effect.dispatched':
|
|
224
|
+
case 'runtime.effect.worker.started':
|
|
225
|
+
case 'runtime.effect.heartbeat':
|
|
226
|
+
case 'runtime.effect.cancel.requested':
|
|
227
|
+
case 'runtime.effect.timed_out':
|
|
228
|
+
case 'runtime.effect.ambiguous': {
|
|
229
|
+
const effectId = readString(payload, 'effectId');
|
|
230
|
+
const attempt = payload.attempt;
|
|
231
|
+
if (!effectId || !Predicate.isNumber(attempt)) {
|
|
232
|
+
return state;
|
|
233
|
+
}
|
|
234
|
+
const status = event.type === 'runtime.effect.queued'
|
|
235
|
+
? 'queued'
|
|
236
|
+
: event.type === 'runtime.effect.dispatched'
|
|
237
|
+
? 'dispatched'
|
|
238
|
+
: event.type === 'runtime.effect.worker.started'
|
|
239
|
+
? 'started'
|
|
240
|
+
: event.type === 'runtime.effect.heartbeat'
|
|
241
|
+
? 'heartbeat'
|
|
242
|
+
: event.type === 'runtime.effect.cancel.requested'
|
|
243
|
+
? 'cancel_requested'
|
|
244
|
+
: event.type === 'runtime.effect.timed_out'
|
|
245
|
+
? 'timed_out'
|
|
246
|
+
: 'ambiguous';
|
|
247
|
+
const deadlineAt = payload.deadlineAt;
|
|
248
|
+
const heartbeatAt = payload.heartbeatAt;
|
|
249
|
+
const previous = state.effectExecutions[effectId];
|
|
250
|
+
const sameAttempt = previous?.attempt === attempt;
|
|
251
|
+
return {
|
|
252
|
+
...state,
|
|
253
|
+
effectExecutions: {
|
|
254
|
+
...state.effectExecutions,
|
|
255
|
+
[effectId]: {
|
|
256
|
+
effectId,
|
|
257
|
+
attempt,
|
|
258
|
+
status,
|
|
259
|
+
nextAttemptAt: null,
|
|
260
|
+
deadlineAt: Predicate.isNumber(deadlineAt) ? deadlineAt : null,
|
|
261
|
+
startedAt: event.type === 'runtime.effect.worker.started'
|
|
262
|
+
? event.ts
|
|
263
|
+
: sameAttempt
|
|
264
|
+
? previous.startedAt
|
|
265
|
+
: null,
|
|
266
|
+
lastHeartbeatAt: Predicate.isNumber(heartbeatAt)
|
|
267
|
+
? heartbeatAt
|
|
268
|
+
: sameAttempt
|
|
269
|
+
? previous.lastHeartbeatAt
|
|
270
|
+
: null,
|
|
271
|
+
lastError: readString(payload, 'error') ?? null,
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
case 'runtime.effect.cancelled': {
|
|
277
|
+
const effectId = readString(payload, 'effectId');
|
|
278
|
+
return effectId ? completeEffect(state, effectId) : state;
|
|
279
|
+
}
|
|
280
|
+
case 'runtime.effect.retry.scheduled': {
|
|
281
|
+
const effectId = readString(payload, 'effectId');
|
|
282
|
+
const attempt = payload.attempt;
|
|
283
|
+
const nextAttemptAt = payload.nextAttemptAt;
|
|
284
|
+
if (!effectId || !Predicate.isNumber(attempt) || !Predicate.isNumber(nextAttemptAt)) {
|
|
285
|
+
return state;
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
...state,
|
|
289
|
+
effectExecutions: {
|
|
290
|
+
...state.effectExecutions,
|
|
291
|
+
[effectId]: {
|
|
292
|
+
effectId,
|
|
293
|
+
attempt,
|
|
294
|
+
status: 'retry_wait',
|
|
295
|
+
nextAttemptAt,
|
|
296
|
+
deadlineAt: nextAttemptAt,
|
|
297
|
+
startedAt: null,
|
|
298
|
+
lastHeartbeatAt: null,
|
|
299
|
+
lastError: readString(payload, 'error') ?? 'effect failed',
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
}
|
|
168
304
|
case 'runtime.wait.registered': {
|
|
169
305
|
const waitId = readString(payload, 'waitId');
|
|
170
306
|
const threadId = readString(payload, 'threadId') ?? event.threadId;
|
|
@@ -172,11 +308,14 @@ function applyProtocol(state, event, registry) {
|
|
|
172
308
|
if (!waitId || !threadId || !on || !Predicate.isObject(on)) {
|
|
173
309
|
return state;
|
|
174
310
|
}
|
|
175
|
-
|
|
311
|
+
const waitCondition = decodeWaitCondition(on);
|
|
312
|
+
if (Option.isNone(waitCondition)) {
|
|
313
|
+
return state;
|
|
314
|
+
}
|
|
176
315
|
const record = {
|
|
177
316
|
waitId,
|
|
178
317
|
threadId,
|
|
179
|
-
on:
|
|
318
|
+
on: waitCondition.value,
|
|
180
319
|
};
|
|
181
320
|
if (payload.tag !== undefined) {
|
|
182
321
|
record.tag = payload.tag;
|
|
@@ -195,6 +334,16 @@ function applyProtocol(state, event, registry) {
|
|
|
195
334
|
}
|
|
196
335
|
const existingWait = state.waits[waitId];
|
|
197
336
|
let next = removeWait(state, waitId);
|
|
337
|
+
const existingTag = Predicate.isObject(existingWait?.tag) ? existingWait.tag : undefined;
|
|
338
|
+
const raceId = existingTag && Predicate.isString(existingTag.raceId) ? existingTag.raceId : undefined;
|
|
339
|
+
if (raceId) {
|
|
340
|
+
for (const sibling of Object.values(next.waits)) {
|
|
341
|
+
const siblingTag = Predicate.isObject(sibling.tag) ? sibling.tag : undefined;
|
|
342
|
+
if (siblingTag?.raceId === raceId) {
|
|
343
|
+
next = removeWait(next, sibling.waitId);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
198
347
|
const threadId = existingWait?.threadId ?? event.threadId;
|
|
199
348
|
if (!threadId) {
|
|
200
349
|
return next;
|
|
@@ -206,16 +355,19 @@ function applyProtocol(state, event, registry) {
|
|
|
206
355
|
return next;
|
|
207
356
|
}
|
|
208
357
|
case 'runtime.snapshot.taken':
|
|
358
|
+
case 'runtime.thread.cancel.requested':
|
|
209
359
|
case 'runtime.timer.set':
|
|
210
360
|
case 'runtime.timer.fired':
|
|
211
361
|
case 'runtime.effect.failed':
|
|
362
|
+
case 'runtime.effect.completed':
|
|
212
363
|
case 'runtime.signal.received':
|
|
213
364
|
return state;
|
|
214
365
|
default:
|
|
215
366
|
return state;
|
|
216
367
|
}
|
|
217
368
|
}
|
|
218
|
-
|
|
369
|
+
/** The id an effect keeps across folds when it names itself by tag, wait id, or child thread. */
|
|
370
|
+
export function stableEffectId(threadId, effect) {
|
|
219
371
|
if ('tag' in effect && Predicate.isString(effect.tag)) {
|
|
220
372
|
return createEffectId(threadId, effect.tag);
|
|
221
373
|
}
|
|
@@ -225,29 +377,21 @@ function deriveEffectId(threadId, causingSeq, index, effect, existingId) {
|
|
|
225
377
|
if ('childThreadId' in effect && Predicate.isString(effect.childThreadId)) {
|
|
226
378
|
return createEffectId(threadId, `spawn_${effect.childThreadId}`);
|
|
227
379
|
}
|
|
228
|
-
if (
|
|
229
|
-
|
|
380
|
+
if (effect.type === 'runtime.cancel' &&
|
|
381
|
+
'threadId' in effect &&
|
|
382
|
+
Predicate.isString(effect.threadId)) {
|
|
383
|
+
return createEffectId(threadId, `cancel_${effect.threadId}`);
|
|
230
384
|
}
|
|
231
|
-
return
|
|
385
|
+
return undefined;
|
|
232
386
|
}
|
|
233
387
|
function mapEffects(threadId, event, effects, completed, existingForThread) {
|
|
234
388
|
const remainingExisting = [...existingForThread];
|
|
235
389
|
return effects
|
|
236
390
|
.map((effect, index) => {
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
return item.effectId === createEffectId(threadId, effect.tag);
|
|
240
|
-
}
|
|
241
|
-
if ('waitId' in effect && Predicate.isString(effect.waitId)) {
|
|
242
|
-
return item.effectId === createEffectId(threadId, effect.waitId);
|
|
243
|
-
}
|
|
244
|
-
if ('childThreadId' in effect && Predicate.isString(effect.childThreadId)) {
|
|
245
|
-
return item.effectId === createEffectId(threadId, `spawn_${effect.childThreadId}`);
|
|
246
|
-
}
|
|
247
|
-
return item.effect.type === effect.type;
|
|
248
|
-
});
|
|
391
|
+
const stableId = stableEffectId(threadId, effect);
|
|
392
|
+
const matchIndex = remainingExisting.findIndex((item) => stableId === undefined ? item.effect.type === effect.type : item.effectId === stableId);
|
|
249
393
|
const existing = matchIndex >= 0 ? remainingExisting.splice(matchIndex, 1)[0] : undefined;
|
|
250
|
-
const effectId =
|
|
394
|
+
const effectId = stableId ?? existing?.effectId ?? createEffectId(threadId, event.seq, index);
|
|
251
395
|
return (existing ?? {
|
|
252
396
|
effectId,
|
|
253
397
|
threadId,
|
|
@@ -285,6 +429,9 @@ function deliver(state, event, registry) {
|
|
|
285
429
|
if (!record) {
|
|
286
430
|
return state;
|
|
287
431
|
}
|
|
432
|
+
if (isTerminalStatus(record.status)) {
|
|
433
|
+
return state;
|
|
434
|
+
}
|
|
288
435
|
const definition = registry.threads.get(record.kind);
|
|
289
436
|
if (!definition) {
|
|
290
437
|
return state;
|