@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/s2/store.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { AppendInput, AppendRecord, S2, S2Endpoints, S2Error } from '@s2-dev/streamstore';
|
|
2
|
-
import { Effect, Layer,
|
|
3
|
-
import { createKeyedSerializer, EventStoreConflictError, EventStoreError, EventStoreFencedError, EventStoreTag, EventEnvelopeSchema, fromWireEvent, withSnapshotStore, } from '@swirls/looms/core';
|
|
2
|
+
import { DateTime, Effect, Layer, Predicate, Schema, Stream } from 'effect';
|
|
3
|
+
import { createKeyedSerializer, assertEventByteLimits, EventStoreConflictError, EventStoreError, EventStoreFencedError, EventPayloadTooLargeError, EventStoreTag, EventEnvelopeSchema, fromWireEvent, withSnapshotStore, } from '@swirls/looms/core';
|
|
4
4
|
import { S2ConfigSchema, streamNameForRun } from './config.js';
|
|
5
|
+
import { paginateS2Stream } from './pagination.js';
|
|
5
6
|
import { s2SnapshotStore } from './snapshot-store.js';
|
|
6
7
|
function toStoreError(cause, message) {
|
|
7
8
|
if (cause instanceof EventStoreError) {
|
|
@@ -20,50 +21,8 @@ function isUnsatisfiableCause(cause) {
|
|
|
20
21
|
const text = cause instanceof Error ? cause.message : String(cause);
|
|
21
22
|
return text.includes('out of range') || text.includes('Range not satisfiable');
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*
|
|
26
|
-
* Pulls pages on demand until the stream tail is reached, an empty page is returned,
|
|
27
|
-
* or the caller's optional limit is satisfied.
|
|
28
|
-
*/
|
|
29
|
-
export function paginateS2Stream(fetchPage, options) {
|
|
30
|
-
const fromSeq = options?.fromSeq ?? 0;
|
|
31
|
-
const userLimit = options?.limit;
|
|
32
|
-
const maxPageSize = options?.maxPageSize ?? 1000;
|
|
33
|
-
if (userLimit !== undefined && userLimit <= 0) {
|
|
34
|
-
return Stream.empty;
|
|
35
|
-
}
|
|
36
|
-
const baseStream = Stream.paginate({ cursor: fromSeq, remaining: userLimit }, (state) => Effect.gen(function* () {
|
|
37
|
-
if (state.remaining !== undefined && state.remaining <= 0) {
|
|
38
|
-
return [[], Option.none()];
|
|
39
|
-
}
|
|
40
|
-
const count = state.remaining !== undefined ? Math.min(maxPageSize, state.remaining) : maxPageSize;
|
|
41
|
-
const page = yield* fetchPage(state.cursor, count);
|
|
42
|
-
if (!page || page.records.length === 0) {
|
|
43
|
-
return [[], Option.none()];
|
|
44
|
-
}
|
|
45
|
-
const records = page.records.filter((r) => r.seqNum >= fromSeq);
|
|
46
|
-
const nextRemaining = state.remaining !== undefined ? state.remaining - records.length : undefined;
|
|
47
|
-
const lastRecord = page.records[page.records.length - 1];
|
|
48
|
-
if (!lastRecord || (nextRemaining !== undefined && nextRemaining <= 0)) {
|
|
49
|
-
return [records, Option.none()];
|
|
50
|
-
}
|
|
51
|
-
const nextCursor = Math.max(state.cursor + 1, lastRecord.seqNum + 1);
|
|
52
|
-
if (nextCursor <= state.cursor) {
|
|
53
|
-
return [records, Option.none()];
|
|
54
|
-
}
|
|
55
|
-
// A byte-capped page is shorter than `count`. Do not trust `page.tail`
|
|
56
|
-
// there — S2 may report the batch end, not the stream tail.
|
|
57
|
-
const shortPage = page.records.length < count;
|
|
58
|
-
const reachedTail = !shortPage && page.tail?.seqNum !== undefined && nextCursor >= page.tail.seqNum;
|
|
59
|
-
if (reachedTail) {
|
|
60
|
-
return [records, Option.none()];
|
|
61
|
-
}
|
|
62
|
-
return [records, Option.some({ cursor: nextCursor, remaining: nextRemaining })];
|
|
63
|
-
}));
|
|
64
|
-
return userLimit !== undefined ? baseStream.pipe(Stream.take(userLimit)) : baseStream;
|
|
65
|
-
}
|
|
66
|
-
export async function readAllPages(fetchPage, options) {
|
|
24
|
+
export { paginateS2Stream };
|
|
25
|
+
export function readAllPages(fetchPage, options) {
|
|
67
26
|
const fetchPageEffect = (cursor, count) => Effect.tryPromise({
|
|
68
27
|
try: () => fetchPage(cursor, count),
|
|
69
28
|
catch: (cause) => toStoreError(cause, 'S2 page fetch failed'),
|
|
@@ -101,61 +60,49 @@ function createClient(config) {
|
|
|
101
60
|
* Expected tail mismatches during `append` map to `EventStoreConflictError`.
|
|
102
61
|
*/
|
|
103
62
|
export function s2(config) {
|
|
104
|
-
const parsed = Schema.
|
|
63
|
+
const parsed = Schema.decodeSync(S2ConfigSchema)(config);
|
|
105
64
|
const client = createClient(parsed);
|
|
106
65
|
const basin = client.basin(parsed.basin);
|
|
107
66
|
const ensured = new Set();
|
|
108
67
|
const appends = createKeyedSerializer();
|
|
109
68
|
let basinEnsured = false;
|
|
110
|
-
const ensureBasin = Effect.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
catch (err) {
|
|
119
|
-
// 409 = already exists
|
|
120
|
-
if (!(err instanceof S2Error && err.status === 409)) {
|
|
121
|
-
throw err;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
69
|
+
const ensureBasin = Effect.suspend(() => {
|
|
70
|
+
if (basinEnsured) {
|
|
71
|
+
return Effect.void;
|
|
72
|
+
}
|
|
73
|
+
return Effect.tryPromise({
|
|
74
|
+
try: () => client.basins.create({ basin: parsed.basin }),
|
|
75
|
+
catch: (cause) => toStoreError(cause, `Failed to ensure basin ${parsed.basin}`),
|
|
76
|
+
}).pipe(Effect.catchIf((error) => error.cause instanceof S2Error && error.cause.status === 409, () => Effect.void), Effect.tap(() => Effect.sync(() => {
|
|
124
77
|
basinEnsured = true;
|
|
125
|
-
},
|
|
126
|
-
catch: (cause) => toStoreError(cause, `Failed to ensure basin ${parsed.basin}`),
|
|
78
|
+
})), Effect.asVoid);
|
|
127
79
|
});
|
|
128
80
|
const ensureStream = (runId) => Effect.gen(function* () {
|
|
129
81
|
yield* ensureBasin;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
// Some local servers may not support create; try using the stream anyway.
|
|
146
|
-
if (!(err instanceof S2Error && (err.status === 404 || err.status === 405))) {
|
|
147
|
-
throw err;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
ensured.add(name);
|
|
152
|
-
return basin.stream(name);
|
|
153
|
-
},
|
|
154
|
-
catch: (cause) => toStoreError(cause, `Failed to open stream for ${runId}`),
|
|
155
|
-
});
|
|
82
|
+
const name = streamNameForRun(runId);
|
|
83
|
+
if (!ensured.has(name)) {
|
|
84
|
+
yield* Effect.tryPromise({
|
|
85
|
+
try: () => basin.streams.create({
|
|
86
|
+
stream: name,
|
|
87
|
+
config: parsed.streamConfig,
|
|
88
|
+
}),
|
|
89
|
+
catch: (cause) => toStoreError(cause, `Failed to open stream for ${runId}`),
|
|
90
|
+
}).pipe(Effect.catchIf((error) => error.cause instanceof S2Error &&
|
|
91
|
+
(error.cause.status === 409 ||
|
|
92
|
+
error.cause.status === 404 ||
|
|
93
|
+
error.cause.status === 405), () => Effect.void));
|
|
94
|
+
ensured.add(name);
|
|
95
|
+
}
|
|
96
|
+
return basin.stream(name);
|
|
156
97
|
});
|
|
157
98
|
const service = {
|
|
158
99
|
append: (runId, events, options) => Effect.gen(function* () {
|
|
100
|
+
yield* Effect.try({
|
|
101
|
+
try: () => assertEventByteLimits(runId, events),
|
|
102
|
+
catch: (cause) => cause instanceof EventPayloadTooLargeError
|
|
103
|
+
? cause
|
|
104
|
+
: new EventStoreError('event size validation failed', cause),
|
|
105
|
+
});
|
|
159
106
|
if (events.length === 0 && options?.fence === undefined) {
|
|
160
107
|
const tail = yield* service.tail(runId);
|
|
161
108
|
return { sequences: [], tail };
|
|
@@ -186,7 +133,7 @@ export function s2(config) {
|
|
|
186
133
|
cause.status === 412 &&
|
|
187
134
|
(message.includes('fenc') || message.includes('token'));
|
|
188
135
|
if (isFence) {
|
|
189
|
-
return yield*
|
|
136
|
+
return yield* new EventStoreFencedError(runId, options?.fencingToken ?? options?.fence ?? '');
|
|
190
137
|
}
|
|
191
138
|
if (cause instanceof S2Error &&
|
|
192
139
|
(cause.status === 409 ||
|
|
@@ -195,9 +142,9 @@ export function s2(config) {
|
|
|
195
142
|
message.includes('match'))) {
|
|
196
143
|
const tailCheck = yield* Effect.promise(() => stream.checkTail().catch(() => null));
|
|
197
144
|
const actualTail = tailCheck?.tail?.seqNum ?? 0;
|
|
198
|
-
return yield*
|
|
145
|
+
return yield* new EventStoreConflictError(runId, options?.expectedTail ?? 0, actualTail);
|
|
199
146
|
}
|
|
200
|
-
return yield*
|
|
147
|
+
return yield* toStoreError(cause, `Append failed for ${runId}`);
|
|
201
148
|
}
|
|
202
149
|
const ack = appendResult.ack;
|
|
203
150
|
const sequences = [];
|
|
@@ -213,23 +160,13 @@ export function s2(config) {
|
|
|
213
160
|
return Stream.unwrap(Effect.gen(function* () {
|
|
214
161
|
const stream = yield* ensureStream(runId);
|
|
215
162
|
const fetchPage = (cursor, count) => Effect.tryPromise({
|
|
216
|
-
try:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
ignoreCommandRecords: true,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
catch (cause) {
|
|
225
|
-
if (isUnsatisfiableCause(cause)) {
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
throw cause;
|
|
229
|
-
}
|
|
230
|
-
},
|
|
163
|
+
try: () => stream.read({
|
|
164
|
+
start: { from: { seqNum: cursor }, clamp: true },
|
|
165
|
+
stop: { limits: { count } },
|
|
166
|
+
ignoreCommandRecords: true,
|
|
167
|
+
}),
|
|
231
168
|
catch: (cause) => toStoreError(cause, `Read failed for ${runId}`),
|
|
232
|
-
});
|
|
169
|
+
}).pipe(Effect.catchIf((error) => isUnsatisfiableCause(error.cause), () => Effect.succeed(null)));
|
|
233
170
|
const recordStream = paginateS2Stream(fetchPage, {
|
|
234
171
|
fromSeq: s2From,
|
|
235
172
|
limit: options?.limit,
|
|
@@ -246,31 +183,21 @@ export function s2(config) {
|
|
|
246
183
|
const res = yield* Effect.tryPromise({
|
|
247
184
|
try: () => stream.checkTail(),
|
|
248
185
|
catch: (cause) => toStoreError(cause, `Tail failed for ${runId}`),
|
|
249
|
-
}).pipe(Effect.
|
|
250
|
-
|
|
251
|
-
|
|
186
|
+
}).pipe(Effect.catchIf((err) => err.cause instanceof S2Error && err.cause.status === 404, () => Effect.succeed({
|
|
187
|
+
tail: { seqNum: 0, timestamp: DateTime.toDateUtc(DateTime.makeUnsafe(0)) },
|
|
188
|
+
})));
|
|
252
189
|
return res.tail.seqNum;
|
|
253
190
|
}),
|
|
254
191
|
bounds: (runId) => Effect.gen(function* () {
|
|
255
192
|
const stream = yield* ensureStream(runId);
|
|
256
193
|
const page = yield* Effect.tryPromise({
|
|
257
|
-
try:
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
ignoreCommandRecords: false,
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
catch (cause) {
|
|
266
|
-
if (isUnsatisfiableCause(cause)) {
|
|
267
|
-
return null;
|
|
268
|
-
}
|
|
269
|
-
throw cause;
|
|
270
|
-
}
|
|
271
|
-
},
|
|
194
|
+
try: () => stream.read({
|
|
195
|
+
start: { from: { seqNum: 0 }, clamp: true },
|
|
196
|
+
stop: { limits: { count: 1 } },
|
|
197
|
+
ignoreCommandRecords: false,
|
|
198
|
+
}),
|
|
272
199
|
catch: (cause) => toStoreError(cause, `Bounds failed for ${runId}`),
|
|
273
|
-
});
|
|
200
|
+
}).pipe(Effect.catchIf((error) => isUnsatisfiableCause(error.cause), () => Effect.succeed(null)));
|
|
274
201
|
const tail = page?.tail?.seqNum ?? 0;
|
|
275
202
|
const first = page?.records[0];
|
|
276
203
|
const head = first ? first.seqNum + 1 : tail + 1;
|
|
@@ -284,49 +211,28 @@ export function s2(config) {
|
|
|
284
211
|
catch: (cause) => toStoreError(cause, `Trim failed for ${runId}`),
|
|
285
212
|
});
|
|
286
213
|
}),
|
|
287
|
-
subscribe: (runId, options) =>
|
|
214
|
+
subscribe: (runId, options) => {
|
|
288
215
|
const fromSeq = options?.fromSeq ?? 1;
|
|
289
216
|
const s2From = Math.max(0, fromSeq - 1);
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
const session = await stream.readSession({
|
|
217
|
+
return Stream.unwrap(Effect.gen(function* () {
|
|
218
|
+
const stream = yield* ensureStream(runId);
|
|
219
|
+
const session = yield* Effect.tryPromise({
|
|
220
|
+
try: () => stream.readSession({
|
|
295
221
|
start: { from: { seqNum: s2From }, clamp: true },
|
|
296
222
|
ignoreCommandRecords: true,
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
Queue.offerUnsafe(queue, parseEvent(record.body, record.seqNum));
|
|
306
|
-
}
|
|
307
|
-
Queue.endUnsafe(queue);
|
|
308
|
-
resume(Effect.void);
|
|
309
|
-
}
|
|
310
|
-
catch (cause) {
|
|
311
|
-
await Effect.runPromise(Queue.fail(queue, toStoreError(cause, `Subscribe failed for ${runId}`)));
|
|
312
|
-
resume(Effect.void);
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
void run();
|
|
316
|
-
return Effect.sync(() => {
|
|
317
|
-
stopped = true;
|
|
318
|
-
});
|
|
319
|
-
})),
|
|
320
|
-
listRuns: () => Effect.tryPromise({
|
|
321
|
-
try: async () => {
|
|
322
|
-
const listed = await basin.streams.list({ prefix: 'runs/' });
|
|
323
|
-
return listed.streams
|
|
324
|
-
.map((s) => s.name)
|
|
325
|
-
.filter((name) => name.startsWith('runs/'))
|
|
326
|
-
.map((name) => name.slice('runs/'.length));
|
|
327
|
-
},
|
|
223
|
+
}),
|
|
224
|
+
catch: (cause) => toStoreError(cause, `Subscribe failed for ${runId}`),
|
|
225
|
+
});
|
|
226
|
+
return Stream.fromAsyncIterable(session, (cause) => toStoreError(cause, `Subscribe failed for ${runId}`)).pipe(Stream.filter((record) => record.seqNum >= s2From), Stream.map((record) => parseEvent(record.body, record.seqNum)));
|
|
227
|
+
}));
|
|
228
|
+
},
|
|
229
|
+
listRuns: Effect.tryPromise({
|
|
230
|
+
try: () => basin.streams.list({ prefix: 'runs/' }),
|
|
328
231
|
catch: (cause) => toStoreError(cause, 'listRuns failed'),
|
|
329
|
-
})
|
|
232
|
+
}).pipe(Effect.map((listed) => listed.streams
|
|
233
|
+
.map((stream) => stream.name)
|
|
234
|
+
.filter((name) => name.startsWith('runs/'))
|
|
235
|
+
.map((name) => name.slice('runs/'.length)))),
|
|
330
236
|
};
|
|
331
237
|
return withSnapshotStore(service, s2SnapshotStore(parsed));
|
|
332
238
|
}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -9,3 +9,18 @@ export interface TestRuntime {
|
|
|
9
9
|
export declare function createTestRuntime(modules: readonly AnyRuntimeModule[]): Promise<TestRuntime>;
|
|
10
10
|
export declare function assertReplayDeterministic(test: TestRuntime, runId: string): Promise<void>;
|
|
11
11
|
export declare function moduleConformance(module: AnyRuntimeModule): string[];
|
|
12
|
+
export type EventStoreFaultOperation = 'append' | 'read' | 'tail' | 'bounds' | 'trim' | 'listRuns';
|
|
13
|
+
export interface EventStoreFaultContext {
|
|
14
|
+
readonly operation: EventStoreFaultOperation;
|
|
15
|
+
readonly runId: string | null;
|
|
16
|
+
readonly call: number;
|
|
17
|
+
}
|
|
18
|
+
export interface FaultInjectingEventStore {
|
|
19
|
+
readonly store: EventStore;
|
|
20
|
+
readonly calls: ReadonlyMap<EventStoreFaultOperation, number>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Wraps an EventStore with deterministic delay/failure injection. Throw from
|
|
24
|
+
* `before` to fail a call, or await inside it to pause a race at an exact store boundary.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createFaultInjectingEventStore(source: EventStore, before: (context: EventStoreFaultContext) => void | Promise<void>): FaultInjectingEventStore;
|
package/dist/testing/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Predicate } from 'effect';
|
|
2
|
-
import { composeModules, EventStoreTag, foldRun, makeMemoryEventStore, ModuleCompositionError, } from '@swirls/looms/core';
|
|
2
|
+
import { composeModules, EventStoreTag, foldRun, makeMemoryEventStore, ModuleCompositionError, EventStoreError, snapshotStoreOf, stringifyJson, withSnapshotStore, } from '@swirls/looms/core';
|
|
3
3
|
import { createRuntime } from '@swirls/looms/runtime';
|
|
4
4
|
function namedEffects(effects) {
|
|
5
5
|
const listed = [];
|
|
@@ -15,22 +15,24 @@ function namedEffects(effects) {
|
|
|
15
15
|
}
|
|
16
16
|
return listed;
|
|
17
17
|
}
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
export function createTestRuntime(modules) {
|
|
19
|
+
return Effect.runPromise(makeMemoryEventStore.pipe(Effect.map((store) => {
|
|
20
|
+
const runtime = createRuntime({ modules, store });
|
|
21
|
+
return {
|
|
22
|
+
runtime,
|
|
23
|
+
store,
|
|
24
|
+
run: (effect) => Effect.runPromise(Effect.provideService(effect, EventStoreTag, store)),
|
|
25
|
+
};
|
|
26
|
+
})));
|
|
26
27
|
}
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
export function assertReplayDeterministic(test, runId) {
|
|
29
|
+
return test.run(test.runtime.getEvents(runId)).then((events) => {
|
|
30
|
+
const first = foldRun(events, test.runtime.registry, { runId });
|
|
31
|
+
const second = foldRun(events, test.runtime.registry, { runId });
|
|
32
|
+
if (stringifyJson(first) !== stringifyJson(second)) {
|
|
33
|
+
throw new Error(`Replay is not deterministic for run ${runId}`);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
34
36
|
}
|
|
35
37
|
export function moduleConformance(module) {
|
|
36
38
|
const errors = [];
|
|
@@ -61,3 +63,38 @@ export function moduleConformance(module) {
|
|
|
61
63
|
}
|
|
62
64
|
return errors;
|
|
63
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Wraps an EventStore with deterministic delay/failure injection. Throw from
|
|
68
|
+
* `before` to fail a call, or await inside it to pause a race at an exact store boundary.
|
|
69
|
+
*/
|
|
70
|
+
export function createFaultInjectingEventStore(source, before) {
|
|
71
|
+
const calls = new Map();
|
|
72
|
+
const inject = (operation, runId) => Effect.tryPromise({
|
|
73
|
+
try: () => {
|
|
74
|
+
const call = (calls.get(operation) ?? 0) + 1;
|
|
75
|
+
calls.set(operation, call);
|
|
76
|
+
return Promise.resolve(before({ operation, runId, call }));
|
|
77
|
+
},
|
|
78
|
+
catch: (cause) => cause instanceof EventStoreError
|
|
79
|
+
? cause
|
|
80
|
+
: new EventStoreError(`Injected ${operation} fault`, cause),
|
|
81
|
+
});
|
|
82
|
+
const store = {
|
|
83
|
+
append: (runId, events, options) => inject('append', runId).pipe(Effect.andThen(source.append(runId, events, options))),
|
|
84
|
+
read: (runId, options) => inject('read', runId).pipe(Effect.andThen(source.read(runId, options))),
|
|
85
|
+
tail: (runId) => inject('tail', runId).pipe(Effect.andThen(source.tail(runId))),
|
|
86
|
+
subscribe: source.subscribe,
|
|
87
|
+
listRuns: inject('listRuns', null).pipe(Effect.andThen(source.listRuns)),
|
|
88
|
+
};
|
|
89
|
+
if (source.bounds) {
|
|
90
|
+
store.bounds = (runId) => inject('bounds', runId).pipe(Effect.andThen(source.bounds(runId)));
|
|
91
|
+
}
|
|
92
|
+
if (source.trim) {
|
|
93
|
+
store.trim = (runId, beforeSeq) => inject('trim', runId).pipe(Effect.andThen(source.trim(runId, beforeSeq)));
|
|
94
|
+
}
|
|
95
|
+
const snapshots = snapshotStoreOf(source);
|
|
96
|
+
if (snapshots) {
|
|
97
|
+
withSnapshotStore(store, snapshots);
|
|
98
|
+
}
|
|
99
|
+
return { store, calls };
|
|
100
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { nodes } from '../projections.js';
|
|
2
|
+
import { WorkflowNodesView } from './nodes-view.js';
|
|
3
|
+
import { summarizeWorkflowEvent } from './summarize.js';
|
|
4
|
+
export const workflowDebugger = {
|
|
5
|
+
name: 'workflow',
|
|
6
|
+
families: [
|
|
7
|
+
{ family: 'workflow', color: 'oklch(0.76 0.12 300)', summarize: summarizeWorkflowEvent },
|
|
8
|
+
],
|
|
9
|
+
projections: [{ name: nodes.name, component: WorkflowNodesView }],
|
|
10
|
+
};
|
|
11
|
+
export { WorkflowNodesView };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { asJson } from '@swirls/looms/core';
|
|
3
|
+
import { JsonTree, StatusBadge } from '@swirls/looms/debugger';
|
|
4
|
+
import { useProjection, useRunStore } from '@swirls/looms/react';
|
|
5
|
+
import { nodes } from '../projections.js';
|
|
6
|
+
export function WorkflowNodesView({ runId }) {
|
|
7
|
+
const state = useProjection(useRunStore(runId), nodes);
|
|
8
|
+
const entries = Object.entries(state.nodes);
|
|
9
|
+
if (entries.length === 0) {
|
|
10
|
+
return _jsx("p", { className: "text-muted-foreground text-xs", children: "No nodes yet." });
|
|
11
|
+
}
|
|
12
|
+
return (_jsx("ul", { className: "grid gap-2", children: entries.map(([id, node]) => (_jsxs("li", { className: "border-border bg-card/60 rounded-lg border p-2.5 text-xs", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "min-w-0 flex-1 truncate font-mono font-medium", children: id }), _jsx(StatusBadge, { status: node.status })] }), node.result !== null ? (_jsx(JsonTree, { value: asJson(node.result), className: "mt-1.5" })) : null, node.error ? _jsx("p", { className: "text-status-failed mt-1.5", children: node.error }) : null] }, id))) }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { compactJson, jsonFields, jsonText, } from '@swirls/looms/debugger';
|
|
2
|
+
export function summarizeWorkflowEvent(event) {
|
|
3
|
+
const payload = jsonFields(event.payload);
|
|
4
|
+
switch (event.type) {
|
|
5
|
+
case 'workflow.node.started':
|
|
6
|
+
return { title: 'node started', detail: jsonText(payload.nodeId) };
|
|
7
|
+
case 'workflow.node.finished':
|
|
8
|
+
return {
|
|
9
|
+
title: jsonText(payload.error) ? 'node failed' : 'node finished',
|
|
10
|
+
detail: jsonText(payload.error) ??
|
|
11
|
+
`${jsonText(payload.nodeId) ?? ''} ${compactJson(payload.result ?? null)}`,
|
|
12
|
+
};
|
|
13
|
+
case 'workflow.node.skipped':
|
|
14
|
+
return {
|
|
15
|
+
title: 'node skipped',
|
|
16
|
+
detail: `${jsonText(payload.nodeId) ?? ''} · ${jsonText(payload.reason) ?? ''}`,
|
|
17
|
+
};
|
|
18
|
+
case 'workflow.spawn.requested':
|
|
19
|
+
return {
|
|
20
|
+
title: 'workflow spawn',
|
|
21
|
+
detail: `${jsonText(payload.definitionName) ?? 'unknown'} from ${jsonText(payload.nodeId) ?? ''}`,
|
|
22
|
+
};
|
|
23
|
+
case 'workflow.sleep.requested':
|
|
24
|
+
return { title: 'sleep', detail: jsonText(payload.nodeId) };
|
|
25
|
+
case 'workflow.effects.requested':
|
|
26
|
+
return { title: 'workflow effects', detail: jsonText(payload.nodeId) };
|
|
27
|
+
default:
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Context, Layer } from 'effect';
|
|
2
|
+
import { type DefinitionStore } from '@swirls/looms/core';
|
|
2
3
|
import type { WorkflowDefinition } from './definitions';
|
|
3
|
-
export
|
|
4
|
-
get(name: string): WorkflowDefinition | undefined;
|
|
5
|
-
}
|
|
4
|
+
export type WorkflowDefinitionStore = DefinitionStore<WorkflowDefinition>;
|
|
6
5
|
declare const WorkflowDefinitionsTag_base: Context.ServiceClass<WorkflowDefinitionsTag, "looms/WorkflowDefinitions", WorkflowDefinitionStore>;
|
|
7
6
|
export declare class WorkflowDefinitionsTag extends WorkflowDefinitionsTag_base {
|
|
8
7
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Context, Layer } from 'effect';
|
|
2
|
+
import { makeDefinitionStore } from '@swirls/looms/core';
|
|
2
3
|
export class WorkflowDefinitionsTag extends Context.Service()('looms/WorkflowDefinitions') {
|
|
3
4
|
}
|
|
4
5
|
export function makeWorkflowDefinitionStore(definitions) {
|
|
5
|
-
|
|
6
|
-
return { get: (name) => map.get(name) };
|
|
6
|
+
return makeDefinitionStore('workflow', definitions);
|
|
7
7
|
}
|
|
8
8
|
export const WorkflowDefinitionsLive = (definitions) => Layer.succeed(WorkflowDefinitionsTag, makeWorkflowDefinitionStore(definitions));
|