@swirls/looms 0.3.0 → 0.5.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 +64 -0
- package/dist/actor/cell.d.ts +21 -2
- package/dist/actor/cell.js +15 -3
- package/dist/actor/host.d.ts +10 -2
- package/dist/actor/host.js +27 -4
- package/dist/actor/index.d.ts +2 -1
- package/dist/actor/index.js +1 -1
- package/dist/actor/routing.d.ts +3 -0
- package/dist/actor/routing.js +13 -2
- package/dist/agent/debugger/agent-chat.js +3 -30
- package/dist/agent/debugger/streaming-text.d.ts +6 -0
- package/dist/agent/debugger/streaming-text.js +33 -0
- package/dist/agent/definitions-store.d.ts +1 -1
- package/dist/agent/definitions-store.js +1 -1
- package/dist/agent/definitions.d.ts +48 -0
- package/dist/agent/definitions.js +44 -0
- package/dist/agent/effects.d.ts +184 -0
- package/dist/agent/effects.js +172 -40
- package/dist/agent/events.d.ts +89 -0
- package/dist/agent/events.js +25 -0
- package/dist/agent/module.d.ts +819 -407
- package/dist/agent/module.js +5 -1
- package/dist/agent/scope.d.ts +88 -0
- package/dist/agent/threads.js +39 -3
- package/dist/agent/types.d.ts +4 -0
- package/dist/approval/effects.d.ts +40 -0
- package/dist/approval/module.d.ts +80 -0
- package/dist/client/client.d.ts +468 -119
- package/dist/client/client.js +214 -21
- package/dist/client/index.d.ts +1 -1
- package/dist/client/sse.d.ts +1 -1
- package/dist/client/sse.js +2 -2
- package/dist/cloudflare/durable-object.d.ts +66 -2
- package/dist/cloudflare/durable-object.js +96 -1
- package/dist/cloudflare/event-store.d.ts +7 -3
- package/dist/cloudflare/event-store.js +16 -3
- package/dist/cloudflare/index.d.ts +7 -1
- package/dist/cloudflare/index.js +7 -1
- package/dist/cloudflare/memory-queue.d.ts +18 -0
- package/dist/cloudflare/memory-queue.js +53 -0
- package/dist/cloudflare/queue-consumer.d.ts +52 -0
- package/dist/cloudflare/queue-consumer.js +102 -0
- package/dist/cloudflare/queue-message.d.ts +31 -0
- package/dist/cloudflare/queue-message.js +33 -0
- package/dist/cloudflare/queue-pull.d.ts +62 -0
- package/dist/cloudflare/queue-pull.js +130 -0
- package/dist/cloudflare/queue-worker.d.ts +39 -0
- package/dist/cloudflare/queue-worker.js +62 -0
- package/dist/cloudflare/r2-blob-store.d.ts +33 -0
- package/dist/cloudflare/r2-blob-store.js +60 -0
- package/dist/cloudflare/router.d.ts +4 -1
- package/dist/cloudflare/router.js +8 -3
- package/dist/cloudflare/websocket.d.ts +27 -0
- package/dist/cloudflare/websocket.js +215 -0
- package/dist/core/attempts.d.ts +8 -0
- package/dist/core/attempts.js +27 -0
- package/dist/core/blob-offload.d.ts +21 -0
- package/dist/core/blob-offload.js +143 -0
- package/dist/core/blob-store.d.ts +45 -0
- package/dist/core/blob-store.js +164 -0
- package/dist/core/blobs.d.ts +37 -0
- package/dist/core/blobs.js +160 -0
- package/dist/core/definition-resolver.d.ts +40 -0
- package/dist/core/definition-resolver.js +129 -0
- package/dist/core/definition-store.d.ts +6 -0
- package/dist/core/definition-store.js +37 -1
- package/dist/core/effects.d.ts +86 -3
- package/dist/core/effects.js +99 -3
- package/dist/core/envelope.d.ts +9 -0
- package/dist/core/envelope.js +4 -0
- package/dist/core/event-codec.js +3 -0
- package/dist/core/fold.js +83 -1
- package/dist/core/ids.d.ts +2 -0
- package/dist/core/ids.js +4 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.js +9 -0
- package/dist/core/launcher.d.ts +97 -0
- package/dist/core/launcher.js +67 -0
- package/dist/core/module-scope.d.ts +7 -3
- package/dist/core/module-scope.js +3 -0
- package/dist/core/module.d.ts +10 -0
- package/dist/core/projection.d.ts +5 -4
- package/dist/core/projection.js +4 -0
- package/dist/core/protocol.d.ts +36 -1
- package/dist/core/protocol.js +35 -0
- package/dist/core/published.d.ts +2 -0
- package/dist/core/published.js +4 -1
- package/dist/{react → core}/register.d.ts +9 -8
- package/dist/core/replay.d.ts +96 -0
- package/dist/core/run-context.d.ts +33 -0
- package/dist/core/run-context.js +23 -0
- package/dist/core/sqlite-store.js +57 -5
- package/dist/core/state.d.ts +60 -0
- package/dist/core/state.js +19 -0
- package/dist/core/store.d.ts +6 -0
- package/dist/core/store.js +7 -0
- package/dist/core/subscription.d.ts +97 -0
- package/dist/core/subscription.js +224 -0
- package/dist/core/thread.d.ts +7 -0
- package/dist/core/thread.js +1 -0
- package/dist/core/trace.d.ts +21 -0
- package/dist/core/trace.js +45 -0
- package/dist/core/worker-callback.d.ts +25 -1
- package/dist/debugger/app/assets/{index-CgDzWJg7.css → index-B7GdT1UA.css} +1 -1
- package/dist/debugger/app/assets/index-C31SnCuN.js +22 -0
- package/dist/debugger/app/assets/routes-DPA3O5AF.js +47 -0
- package/dist/debugger/app/index.html +2 -2
- package/dist/debugger/components/event-inspector.d.ts +3 -1
- package/dist/debugger/components/event-inspector.js +25 -4
- package/dist/debugger/components/event-stream.d.ts +4 -1
- package/dist/debugger/components/event-stream.js +2 -2
- package/dist/debugger/components/run-tree.d.ts +5 -2
- package/dist/debugger/components/run-tree.js +10 -4
- package/dist/debugger/context.d.ts +8 -1
- package/dist/debugger/context.js +15 -3
- package/dist/debugger/events/protocol-summarize.js +18 -3
- package/dist/debugger/index.d.ts +1 -1
- package/dist/debugger/index.js +1 -1
- package/dist/debugger/shell/debugger-shell.js +1 -1
- package/dist/debugger/shell/events-pane.js +4 -3
- package/dist/debugger/styles.css +1 -0
- package/dist/evaluator/definitions-store.d.ts +3 -4
- package/dist/evaluator/definitions-store.js +3 -3
- package/dist/evaluator/definitions.d.ts +4 -1
- package/dist/evaluator/definitions.js +5 -2
- package/dist/evaluator/effects.d.ts +41 -0
- package/dist/evaluator/effects.js +6 -2
- package/dist/evaluator/module.d.ts +84 -0
- package/dist/evaluator/module.js +7 -3
- package/dist/evaluator/threads.d.ts +2 -0
- package/dist/evaluator/threads.js +4 -0
- package/dist/projectors/event-log.d.ts +87 -0
- package/dist/projectors/event-log.js +396 -0
- package/dist/projectors/index-model.d.ts +12 -0
- package/dist/projectors/index-model.js +12 -3
- package/dist/projectors/memory.js +7 -0
- package/dist/projectors/postgres.d.ts +1 -0
- package/dist/projectors/postgres.js +32 -15
- package/dist/projectors/schema.d.ts +5 -0
- package/dist/projectors/schema.js +26 -1
- package/dist/projectors/sqlite.js +47 -19
- package/dist/projectors/with-projectors.d.ts +7 -1
- package/dist/projectors/with-projectors.js +13 -3
- package/dist/react/derived.d.ts +26 -8
- package/dist/react/derived.js +23 -26
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +2 -2
- package/dist/react/materialize.js +5 -1
- package/dist/react/react.d.ts +16 -9
- package/dist/react/react.js +47 -23
- package/dist/react/store.d.ts +14 -6
- package/dist/react/store.js +104 -12
- package/dist/react/tables.d.ts +4 -1
- package/dist/runtime/cancellation.d.ts +2 -1
- package/dist/runtime/cancellation.js +35 -2
- package/dist/runtime/child-run.d.ts +10 -0
- package/dist/runtime/child-run.js +58 -0
- package/dist/runtime/deadline-transition-planner.js +11 -2
- package/dist/runtime/dispatch-effect.d.ts +2 -2
- package/dist/runtime/dispatch-effect.js +43 -19
- package/dist/runtime/errors.d.ts +14 -1
- package/dist/runtime/errors.js +10 -0
- package/dist/runtime/filesystem-blob-store.d.ts +6 -0
- package/dist/runtime/filesystem-blob-store.js +59 -0
- package/dist/runtime/helpers.d.ts +15 -6
- package/dist/runtime/helpers.js +46 -6
- package/dist/runtime/index.d.ts +4 -2
- package/dist/runtime/index.js +3 -1
- package/dist/runtime/local-effect-executor.d.ts +11 -2
- package/dist/runtime/local-effect-executor.js +80 -4
- package/dist/runtime/looms.d.ts +38 -4
- package/dist/runtime/looms.js +17 -3
- package/dist/runtime/repository.d.ts +5 -4
- package/dist/runtime/repository.js +5 -2
- package/dist/runtime/retry-policy.d.ts +5 -0
- package/dist/runtime/retry-policy.js +10 -2
- package/dist/runtime/run-start.d.ts +1 -1
- package/dist/runtime/run-start.js +10 -0
- package/dist/runtime/runtime.d.ts +2 -2
- package/dist/runtime/runtime.js +191 -68
- package/dist/runtime/server/auth.d.ts +3 -0
- package/dist/runtime/server/fetch-handler.d.ts +2 -2
- package/dist/runtime/server/fetch-handler.js +35 -4
- package/dist/runtime/server/grant.d.ts +49 -0
- package/dist/runtime/server/grant.js +177 -0
- package/dist/runtime/server/routes/effects.js +47 -5
- package/dist/runtime/server/routes/runs.js +6 -1
- package/dist/runtime/server/run-route.d.ts +18 -0
- package/dist/runtime/server/run-route.js +26 -0
- package/dist/runtime/server.d.ts +3 -1
- package/dist/runtime/server.js +3 -1
- package/dist/runtime/sse.js +26 -4
- package/dist/runtime/subscription.d.ts +8 -0
- package/dist/runtime/subscription.js +23 -0
- package/dist/runtime/types.d.ts +87 -8
- package/dist/runtime/wake-engine.d.ts +4 -2
- package/dist/runtime/wake-engine.js +57 -6
- package/dist/runtime/worker-callbacks.d.ts +12 -2
- package/dist/runtime/worker-callbacks.js +102 -72
- package/dist/runtime/worker-effect-dispatch.d.ts +14 -5
- package/dist/runtime/worker-effect-dispatch.js +84 -18
- package/dist/schedule/debugger/index.d.ts +4 -0
- package/dist/schedule/debugger/index.js +11 -0
- package/dist/schedule/debugger/schedule-view.d.ts +3 -0
- package/dist/schedule/debugger/schedule-view.js +68 -0
- package/dist/schedule/debugger/summarize.d.ts +2 -0
- package/dist/schedule/debugger/summarize.js +43 -0
- package/dist/schedule/definitions-store.d.ts +10 -0
- package/dist/schedule/definitions-store.js +8 -0
- package/dist/schedule/definitions.d.ts +57 -0
- package/dist/schedule/definitions.js +30 -0
- package/dist/schedule/effects.d.ts +756 -0
- package/dist/schedule/effects.js +244 -0
- package/dist/schedule/ensure.d.ts +55 -0
- package/dist/schedule/ensure.js +109 -0
- package/dist/schedule/events.d.ts +116 -0
- package/dist/schedule/events.js +49 -0
- package/dist/schedule/index.d.ts +11 -0
- package/dist/schedule/index.js +11 -0
- package/dist/schedule/module.d.ts +1474 -0
- package/dist/schedule/module.js +22 -0
- package/dist/schedule/projections.d.ts +55 -0
- package/dist/schedule/projections.js +88 -0
- package/dist/schedule/scope.d.ts +121 -0
- package/dist/schedule/scope.js +7 -0
- package/dist/schedule/signals.d.ts +25 -0
- package/dist/schedule/signals.js +33 -0
- package/dist/schedule/specs.d.ts +59 -0
- package/dist/schedule/specs.js +231 -0
- package/dist/schedule/threads.d.ts +25 -0
- package/dist/schedule/threads.js +259 -0
- package/dist/testing/corpus-module.d.ts +34 -0
- package/dist/testing/corpus-module.js +87 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +5 -6
- package/dist/testing/replay-corpus.d.ts +22 -0
- package/dist/testing/replay-corpus.js +50 -0
- package/dist/workflow/definitions-store.d.ts +1 -1
- package/dist/workflow/definitions-store.js +1 -1
- package/dist/workflow/definitions.d.ts +14 -0
- package/dist/workflow/effects.d.ts +122 -0
- package/dist/workflow/effects.js +16 -6
- package/dist/workflow/events.d.ts +42 -0
- package/dist/workflow/events.js +4 -0
- package/dist/workflow/module.d.ts +345 -32
- package/dist/workflow/module.js +7 -3
- package/dist/workflow/scope.d.ts +42 -0
- package/dist/workflow/threads.d.ts +72 -0
- package/dist/workflow/threads.js +106 -38
- package/package.json +11 -2
- package/dist/debugger/app/assets/index-BevQYa-U.js +0 -22
- package/dist/debugger/app/assets/routes-B17Om93i.js +0 -47
- /package/dist/{react → core}/register.js +0 -0
package/dist/react/store.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Data, Effect, Fiber, Option, Predicate, Schema } from 'effect';
|
|
2
|
-
import { decodeLoomsEvent, stringifyJson, } from '@swirls/looms/core';
|
|
2
|
+
import { decodeLoomsEvent, readSubscriptionData, stringifyJson, } from '@swirls/looms/core';
|
|
3
3
|
import { EventIndex, ProjectionCache } from './derived.js';
|
|
4
4
|
import { materializeEvents } from './materialize.js';
|
|
5
5
|
import { createNotifyScheduler } from './notify.js';
|
|
6
|
-
import { consumeSseStreamEffect
|
|
6
|
+
import { consumeSseStreamEffect } from './sse.js';
|
|
7
7
|
import { emptyTables } from './tables.js';
|
|
8
8
|
class LoomsStoreError extends Data.TaggedError('LoomsStoreError') {
|
|
9
9
|
constructor(message, cause) {
|
|
@@ -11,6 +11,18 @@ class LoomsStoreError extends Data.TaggedError('LoomsStoreError') {
|
|
|
11
11
|
this.name = 'LoomsStoreError';
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
+
function socketConstructor(options) {
|
|
15
|
+
if (options.transport !== 'websocket' && options.transport !== 'auto') {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
if (options.webSocket) {
|
|
19
|
+
return options.webSocket;
|
|
20
|
+
}
|
|
21
|
+
if (!('WebSocket' in globalThis) || !Predicate.isFunction(globalThis.WebSocket)) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
return globalThis.WebSocket;
|
|
25
|
+
}
|
|
14
26
|
function eventSourceCtor() {
|
|
15
27
|
if (typeof EventSource === 'undefined') {
|
|
16
28
|
return undefined;
|
|
@@ -42,6 +54,7 @@ export function createLoomsStore(options) {
|
|
|
42
54
|
let liveStarted = false;
|
|
43
55
|
let liveAbort;
|
|
44
56
|
let eventSource;
|
|
57
|
+
let socket;
|
|
45
58
|
let reconnectFiber;
|
|
46
59
|
let syncing = null;
|
|
47
60
|
const publishedEvents = () => {
|
|
@@ -88,11 +101,33 @@ export function createLoomsStore(options) {
|
|
|
88
101
|
version += 1;
|
|
89
102
|
notify.schedule();
|
|
90
103
|
};
|
|
91
|
-
const
|
|
92
|
-
|
|
104
|
+
const applyLiveData = (data) => {
|
|
105
|
+
const read = readSubscriptionData(data, options.storeId);
|
|
106
|
+
switch (read.kind) {
|
|
107
|
+
case 'events':
|
|
108
|
+
applyBatch(read.events.slice());
|
|
109
|
+
return 'continue';
|
|
110
|
+
case 'resync':
|
|
111
|
+
fromSeq = read.head;
|
|
112
|
+
return 'resync';
|
|
113
|
+
case 'hello':
|
|
114
|
+
case 'ignore':
|
|
115
|
+
return 'continue';
|
|
116
|
+
default: {
|
|
117
|
+
const unexpected = read;
|
|
118
|
+
return unexpected;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
93
121
|
};
|
|
94
122
|
const liveUrl = () => {
|
|
95
|
-
|
|
123
|
+
const params = new URLSearchParams({ live: 'true', fromSeq: String(fromSeq) });
|
|
124
|
+
if (options.threadId) {
|
|
125
|
+
params.set('threadId', options.threadId);
|
|
126
|
+
}
|
|
127
|
+
if (options.includeEphemeral === false) {
|
|
128
|
+
params.set('includeEphemeral', 'false');
|
|
129
|
+
}
|
|
130
|
+
return `${endpoint}/runs/${encodeURIComponent(options.storeId)}/events?${params.toString()}`;
|
|
96
131
|
};
|
|
97
132
|
const pull = Effect.gen(function* () {
|
|
98
133
|
const url = `${endpoint}/runs/${encodeURIComponent(options.storeId)}/events?fromSeq=${fromSeq}`;
|
|
@@ -135,7 +170,7 @@ export function createLoomsStore(options) {
|
|
|
135
170
|
});
|
|
136
171
|
return syncing;
|
|
137
172
|
};
|
|
138
|
-
const scheduleReconnect = (
|
|
173
|
+
const scheduleReconnect = (start) => {
|
|
139
174
|
if (disposed || !liveStarted || reconnectFiber !== undefined) {
|
|
140
175
|
return;
|
|
141
176
|
}
|
|
@@ -150,7 +185,7 @@ export function createLoomsStore(options) {
|
|
|
150
185
|
catch: (cause) => new LoomsStoreError('Event resync failed', cause),
|
|
151
186
|
}).pipe(Effect.ignore);
|
|
152
187
|
if (!disposed && liveStarted) {
|
|
153
|
-
|
|
188
|
+
start();
|
|
154
189
|
}
|
|
155
190
|
}));
|
|
156
191
|
};
|
|
@@ -165,7 +200,16 @@ export function createLoomsStore(options) {
|
|
|
165
200
|
setStatus('live');
|
|
166
201
|
});
|
|
167
202
|
es.addEventListener('message', (msg) => {
|
|
168
|
-
|
|
203
|
+
if (applyLiveData(msg.data) === 'resync') {
|
|
204
|
+
es.close();
|
|
205
|
+
if (eventSource === es) {
|
|
206
|
+
eventSource = undefined;
|
|
207
|
+
}
|
|
208
|
+
setStatus('reconnecting');
|
|
209
|
+
scheduleReconnect(() => {
|
|
210
|
+
startEventSource(Ctor);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
169
213
|
});
|
|
170
214
|
es.addEventListener('error', () => {
|
|
171
215
|
live = es.readyState === Ctor.OPEN;
|
|
@@ -178,7 +222,9 @@ export function createLoomsStore(options) {
|
|
|
178
222
|
if (eventSource === es) {
|
|
179
223
|
eventSource = undefined;
|
|
180
224
|
}
|
|
181
|
-
scheduleReconnect(
|
|
225
|
+
scheduleReconnect(() => {
|
|
226
|
+
startEventSource(Ctor);
|
|
227
|
+
});
|
|
182
228
|
}
|
|
183
229
|
else if (!live) {
|
|
184
230
|
setStatus('reconnecting');
|
|
@@ -209,9 +255,7 @@ export function createLoomsStore(options) {
|
|
|
209
255
|
}
|
|
210
256
|
live = true;
|
|
211
257
|
setStatus('live');
|
|
212
|
-
return yield* consumeSseStreamEffect(body, (frame) =>
|
|
213
|
-
applyEncoded(frame.data);
|
|
214
|
-
});
|
|
258
|
+
return yield* consumeSseStreamEffect(body, (frame) => applyLiveData(frame.data) === 'resync' ? false : undefined);
|
|
215
259
|
}).pipe(Effect.catch(() => Effect.sync(() => {
|
|
216
260
|
live = false;
|
|
217
261
|
if (!disposed) {
|
|
@@ -226,12 +270,58 @@ export function createLoomsStore(options) {
|
|
|
226
270
|
});
|
|
227
271
|
void Effect.runPromise(run, { signal: controller.signal }).catch(() => undefined);
|
|
228
272
|
};
|
|
273
|
+
const startWebSocket = (Ctor) => {
|
|
274
|
+
if (disposed || !liveStarted) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
let url;
|
|
278
|
+
try {
|
|
279
|
+
const http = new URL(liveUrl());
|
|
280
|
+
http.protocol = http.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
281
|
+
url = http.toString();
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
startFetchStream();
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const ws = new Ctor(url);
|
|
288
|
+
socket = ws;
|
|
289
|
+
ws.addEventListener('open', () => {
|
|
290
|
+
live = true;
|
|
291
|
+
setStatus('live');
|
|
292
|
+
});
|
|
293
|
+
ws.addEventListener('message', (event) => {
|
|
294
|
+
if (!Predicate.isString(event.data)) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (applyLiveData(event.data) === 'resync') {
|
|
298
|
+
ws.close();
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
ws.addEventListener('close', () => {
|
|
302
|
+
live = false;
|
|
303
|
+
if (socket === ws) {
|
|
304
|
+
socket = undefined;
|
|
305
|
+
}
|
|
306
|
+
if (!disposed && liveStarted) {
|
|
307
|
+
setStatus('reconnecting');
|
|
308
|
+
scheduleReconnect(() => {
|
|
309
|
+
startWebSocket(Ctor);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
};
|
|
229
314
|
const startLive = () => {
|
|
230
315
|
if (!options.storeId || (liveStarted && !disposed)) {
|
|
231
316
|
return;
|
|
232
317
|
}
|
|
233
318
|
liveStarted = true;
|
|
234
319
|
disposed = false;
|
|
320
|
+
const socketCtor = socketConstructor(options);
|
|
321
|
+
if (socketCtor) {
|
|
322
|
+
startWebSocket(socketCtor);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
235
325
|
const ctor = options.fetch === undefined ? eventSourceCtor() : undefined;
|
|
236
326
|
if (ctor) {
|
|
237
327
|
startEventSource(ctor);
|
|
@@ -249,6 +339,8 @@ export function createLoomsStore(options) {
|
|
|
249
339
|
}
|
|
250
340
|
eventSource?.close();
|
|
251
341
|
eventSource = undefined;
|
|
342
|
+
socket?.close();
|
|
343
|
+
socket = undefined;
|
|
252
344
|
liveAbort?.abort();
|
|
253
345
|
liveAbort = undefined;
|
|
254
346
|
};
|
package/dist/react/tables.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { RunStatus, ThreadStatus } from '@swirls/looms/core';
|
|
1
|
+
import type { RunAttributes, RunLaunchSource, RunStatus, ThreadStatus } from '@swirls/looms/core';
|
|
2
2
|
export interface RunRow {
|
|
3
3
|
runId: string;
|
|
4
4
|
status: RunStatus;
|
|
5
5
|
rootThreadId: string | null;
|
|
6
6
|
kind: string | null;
|
|
7
7
|
definitionName: string | null;
|
|
8
|
+
/** The effect in another run that launched this one. */
|
|
9
|
+
launchedBy: RunLaunchSource | null;
|
|
10
|
+
attributes: RunAttributes;
|
|
8
11
|
}
|
|
9
12
|
export interface ThreadRow {
|
|
10
13
|
threadId: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComposedRegistry } from '@swirls/looms/core';
|
|
1
|
+
import { type ComposedRegistry, type RunLauncher } from '@swirls/looms/core';
|
|
2
2
|
import type { RunIngress } from './ingress';
|
|
3
3
|
import { type RuntimeObserver } from './observer';
|
|
4
4
|
import type { RuntimeRepository } from './repository';
|
|
@@ -12,5 +12,6 @@ export interface CancellationOptions {
|
|
|
12
12
|
readonly observer?: RuntimeObserver;
|
|
13
13
|
readonly wake: LoomsRuntime['wake'];
|
|
14
14
|
readonly withRunIngress: RunIngress;
|
|
15
|
+
readonly launcher: () => RunLauncher;
|
|
15
16
|
}
|
|
16
17
|
export declare function createCancellation(options: CancellationOptions): LoomsRuntime['cancel'];
|
|
@@ -75,6 +75,32 @@ export function createCancellation(options) {
|
|
|
75
75
|
const store = yield* EventStoreTag;
|
|
76
76
|
const now = yield* Clock.currentTimeMillis;
|
|
77
77
|
return yield* repository.commit(store, runId, (current) => {
|
|
78
|
+
const rootCancel = threadId === undefined || threadId === current.state.rootThreadId;
|
|
79
|
+
const deferClose = rootCancel &&
|
|
80
|
+
!current.state.childCloseSent &&
|
|
81
|
+
current.state.launchedRuns.some((child) => child.close === 'wait');
|
|
82
|
+
if (deferClose) {
|
|
83
|
+
const requested = createEvent(runId, {
|
|
84
|
+
type: 'runtime.child.close.requested',
|
|
85
|
+
payload: { policy: 'wait' },
|
|
86
|
+
threadId: current.state.rootThreadId,
|
|
87
|
+
origin: { type: 'system' },
|
|
88
|
+
idempotencyKey: `child-close:${current.state.rootThreadId ?? runId}`,
|
|
89
|
+
});
|
|
90
|
+
return Effect.succeed({
|
|
91
|
+
events: [requested],
|
|
92
|
+
value: {
|
|
93
|
+
plan: {
|
|
94
|
+
events: [],
|
|
95
|
+
threadIds: new Set(),
|
|
96
|
+
workerCancellations: [],
|
|
97
|
+
},
|
|
98
|
+
now,
|
|
99
|
+
childRunIds: current.state.launchedRuns.map((child) => child.runId),
|
|
100
|
+
},
|
|
101
|
+
idempotencyKey: `signal:child-close:${current.state.rootThreadId ?? runId}`,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
78
104
|
const plan = planCancellation({
|
|
79
105
|
runId,
|
|
80
106
|
seq: current.seq,
|
|
@@ -84,14 +110,21 @@ export function createCancellation(options) {
|
|
|
84
110
|
worker,
|
|
85
111
|
now,
|
|
86
112
|
});
|
|
113
|
+
const childRunIds = [];
|
|
87
114
|
return Effect.succeed({
|
|
88
115
|
events: plan.events,
|
|
89
|
-
value: { plan, now },
|
|
116
|
+
value: { plan, now, childRunIds },
|
|
90
117
|
idempotencyKey: `signal:cancel:${threadId ?? current.state.rootThreadId ?? ''}`,
|
|
91
118
|
});
|
|
92
119
|
});
|
|
93
120
|
}));
|
|
94
|
-
const { plan, now } = committed.value;
|
|
121
|
+
const { plan, now, childRunIds } = committed.value;
|
|
122
|
+
if (childRunIds.length > 0) {
|
|
123
|
+
yield* Effect.forEach(childRunIds, (childRunId) => options.launcher().cancel(childRunId), {
|
|
124
|
+
concurrency: 1,
|
|
125
|
+
discard: true,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
95
128
|
if (committed.append) {
|
|
96
129
|
executionContexts.abort(runId, plan.threadIds, 'Effect cancelled');
|
|
97
130
|
for (const { item, execution } of plan.workerCancellations) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
import { type EventInput, type RunLauncher, type RunState } from '@swirls/looms/core';
|
|
3
|
+
/** Tell the launching run that this child has reached a terminal status. */
|
|
4
|
+
export declare function notifyLaunchingParent(launcher: RunLauncher, runId: string, state: RunState): Effect.Effect<void, Error>;
|
|
5
|
+
/**
|
|
6
|
+
* When a run asked to wait for child cancellation and those children are gone, cancel the
|
|
7
|
+
* run's own threads. The caller appends these events from the parent wake, which must not
|
|
8
|
+
* call `runtime.cancel` on itself.
|
|
9
|
+
*/
|
|
10
|
+
export declare function childCloseCancellations(state: RunState): EventInput[];
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
import { descendantThreadIds, isTerminalStatus, } from '@swirls/looms/core';
|
|
3
|
+
/** Tell the launching run that this child has reached a terminal status. */
|
|
4
|
+
export function notifyLaunchingParent(launcher, runId, state) {
|
|
5
|
+
const launchedBy = state.startIdentity?.launchedBy;
|
|
6
|
+
const status = state.status;
|
|
7
|
+
if (!launchedBy || status === 'running') {
|
|
8
|
+
return Effect.void;
|
|
9
|
+
}
|
|
10
|
+
const root = state.rootThreadId ? state.threads[state.rootThreadId] : undefined;
|
|
11
|
+
const error = status === 'completed' ? null : (root?.error ?? status);
|
|
12
|
+
return launcher.signal(launchedBy.runId, [
|
|
13
|
+
{
|
|
14
|
+
type: 'runtime.child.settled',
|
|
15
|
+
payload: {
|
|
16
|
+
runId,
|
|
17
|
+
status,
|
|
18
|
+
output: root?.output ?? null,
|
|
19
|
+
error,
|
|
20
|
+
},
|
|
21
|
+
threadId: launchedBy.threadId,
|
|
22
|
+
idempotencyKey: `child-settled:${runId}`,
|
|
23
|
+
origin: { type: 'run', runId },
|
|
24
|
+
},
|
|
25
|
+
], { idempotencyKey: `child-settled:${runId}` });
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* When a run asked to wait for child cancellation and those children are gone, cancel the
|
|
29
|
+
* run's own threads. The caller appends these events from the parent wake, which must not
|
|
30
|
+
* call `runtime.cancel` on itself.
|
|
31
|
+
*/
|
|
32
|
+
export function childCloseCancellations(state) {
|
|
33
|
+
if (!state.closeWaiting || state.launchedRuns.some((run) => run.close === 'wait')) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
const rootId = state.rootThreadId;
|
|
37
|
+
if (!rootId) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const root = state.threads[rootId];
|
|
41
|
+
if (!root || isTerminalStatus(root.status)) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
const ids = [...descendantThreadIds(state, rootId).toReversed(), rootId];
|
|
45
|
+
return ids.flatMap((threadId) => {
|
|
46
|
+
const record = state.threads[threadId];
|
|
47
|
+
if (!record || isTerminalStatus(record.status)) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
return [
|
|
51
|
+
{
|
|
52
|
+
type: 'runtime.thread.cancelled',
|
|
53
|
+
payload: { threadId, reason: 'cancelled' },
|
|
54
|
+
threadId,
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createEvent, foldRun, isRunTerminal, isWaitOnTimer, } from '@swirls/looms/core';
|
|
1
|
+
import { createEvent, deferredUntil, foldRun, isRunTerminal, isWaitOnTimer, } from '@swirls/looms/core';
|
|
2
2
|
import { waitSatisfiedEvents } from './helpers.js';
|
|
3
3
|
import { planAttemptFailure } from './retry-policy.js';
|
|
4
4
|
const EMPTY_PLAN = {
|
|
@@ -122,7 +122,16 @@ export function nextRuntimeDeadline(state, after = Number.NEGATIVE_INFINITY) {
|
|
|
122
122
|
execution.deadlineAt > after
|
|
123
123
|
? [execution.deadlineAt]
|
|
124
124
|
: []);
|
|
125
|
-
const
|
|
125
|
+
const deferred = terminal
|
|
126
|
+
? []
|
|
127
|
+
: state.outstandingEffects.flatMap((item) => {
|
|
128
|
+
if (state.effectExecutions[item.effectId]) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
const at = deferredUntil(item.effect);
|
|
132
|
+
return at !== undefined && at > after ? [at] : [];
|
|
133
|
+
});
|
|
134
|
+
const deadlines = [...timers, ...executions, ...deferred];
|
|
126
135
|
return deadlines.length > 0 ? Math.min(...deadlines) : undefined;
|
|
127
136
|
}
|
|
128
137
|
function cancellationAmbiguous(runId, effectId, attempt) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Context, ManagedRuntime } from 'effect';
|
|
2
2
|
import { Effect } from 'effect';
|
|
3
|
-
import { type ComposedRegistry, type EffectContext, type EventInput, type
|
|
4
|
-
export declare function dispatchEffect(registry: ComposedRegistry, services: ManagedRuntime.ManagedRuntime<Context.Service.Any, never>, definitions:
|
|
3
|
+
import { type ComposedRegistry, type EffectContext, type EventInput, type DefinitionResolver, type RunLauncher, type RuntimeEffect } from '@swirls/looms/core';
|
|
4
|
+
export declare function dispatchEffect(registry: ComposedRegistry, services: ManagedRuntime.ManagedRuntime<Context.Service.Any, never>, definitions: DefinitionResolver, launcher: RunLauncher, effect: RuntimeEffect, ctx: EffectContext): Effect.Effect<ReadonlyArray<EventInput>, Error>;
|
|
@@ -1,7 +1,28 @@
|
|
|
1
|
-
import { Effect } from 'effect';
|
|
2
|
-
import { asJson, isPrimitiveEffect, isWaitOnTimer, } from '@swirls/looms/core';
|
|
1
|
+
import { Effect, Predicate } from 'effect';
|
|
2
|
+
import { asJson, isPrimitiveEffect, isWaitOnTimer, readEffectFailure, RunLauncherTag, } from '@swirls/looms/core';
|
|
3
3
|
import { threadStartedEvents } from './helpers.js';
|
|
4
|
-
|
|
4
|
+
function causeMessage(cause) {
|
|
5
|
+
if (Predicate.isString(cause)) {
|
|
6
|
+
return cause;
|
|
7
|
+
}
|
|
8
|
+
if (cause instanceof Error) {
|
|
9
|
+
return cause.message;
|
|
10
|
+
}
|
|
11
|
+
return String(cause);
|
|
12
|
+
}
|
|
13
|
+
function failedAttempt(effectId, threadId, cause) {
|
|
14
|
+
const failure = readEffectFailure(cause);
|
|
15
|
+
const error = failure?.error ?? causeMessage(cause);
|
|
16
|
+
const payload = { effectId, error };
|
|
17
|
+
if (failure?.nonRetryable) {
|
|
18
|
+
payload.nonRetryable = true;
|
|
19
|
+
}
|
|
20
|
+
if (failure?.retryAfterMs !== undefined) {
|
|
21
|
+
payload.retryAfterMs = failure.retryAfterMs;
|
|
22
|
+
}
|
|
23
|
+
return { type: 'runtime.effect.failed', payload, threadId };
|
|
24
|
+
}
|
|
25
|
+
export function dispatchEffect(registry, services, definitions, launcher, effect, ctx) {
|
|
5
26
|
const currentThreadId = ctx.threadId;
|
|
6
27
|
const baseDispatch = (eff, effCtx) => {
|
|
7
28
|
if (isPrimitiveEffect(eff)) {
|
|
@@ -67,6 +88,20 @@ export function dispatchEffect(registry, services, definitions, effect, ctx) {
|
|
|
67
88
|
},
|
|
68
89
|
]);
|
|
69
90
|
}
|
|
91
|
+
case 'runtime.launch':
|
|
92
|
+
return launcher
|
|
93
|
+
.launch({
|
|
94
|
+
runId: eff.runId,
|
|
95
|
+
kind: eff.kind,
|
|
96
|
+
definitionName: eff.definitionName,
|
|
97
|
+
definitionVersion: eff.definitionVersion,
|
|
98
|
+
input: eff.input,
|
|
99
|
+
idempotencyKey: eff.runId,
|
|
100
|
+
close: eff.close,
|
|
101
|
+
})
|
|
102
|
+
.pipe(Effect.map(() => []));
|
|
103
|
+
case 'runtime.cancelRun':
|
|
104
|
+
return launcher.cancel(eff.runId).pipe(Effect.map(() => []));
|
|
70
105
|
default: {
|
|
71
106
|
const exhaustiveCheck = eff;
|
|
72
107
|
return exhaustiveCheck;
|
|
@@ -76,28 +111,17 @@ export function dispatchEffect(registry, services, definitions, effect, ctx) {
|
|
|
76
111
|
const handler = registry.effects.get(eff.type);
|
|
77
112
|
if (!handler) {
|
|
78
113
|
return Effect.succeed([
|
|
79
|
-
{
|
|
80
|
-
type: 'runtime.effect.failed',
|
|
81
|
-
payload: { effectId: effCtx.effectId, error: `No handler for ${eff.type}` },
|
|
82
|
-
threadId: currentThreadId,
|
|
83
|
-
},
|
|
114
|
+
failedAttempt(effCtx.effectId, currentThreadId, `No handler for ${eff.type}`),
|
|
84
115
|
]);
|
|
85
116
|
}
|
|
86
117
|
const input = 'input' in eff ? eff.input : {};
|
|
87
118
|
const execution = Effect.gen(function* () {
|
|
88
119
|
const serviceContext = yield* services.contextEffect;
|
|
89
|
-
return yield* handler
|
|
120
|
+
return yield* handler
|
|
121
|
+
.execute(input, effCtx)
|
|
122
|
+
.pipe(Effect.provideService(RunLauncherTag, launcher), Effect.provide(serviceContext));
|
|
90
123
|
});
|
|
91
|
-
return execution.pipe(Effect.catch((err) => Effect.succeed([
|
|
92
|
-
{
|
|
93
|
-
type: 'runtime.effect.failed',
|
|
94
|
-
payload: {
|
|
95
|
-
effectId: effCtx.effectId,
|
|
96
|
-
error: err instanceof Error ? err.message : String(err),
|
|
97
|
-
},
|
|
98
|
-
threadId: currentThreadId,
|
|
99
|
-
},
|
|
100
|
-
])));
|
|
124
|
+
return execution.pipe(Effect.catch((err) => Effect.succeed([failedAttempt(effCtx.effectId, currentThreadId, err)])));
|
|
101
125
|
};
|
|
102
126
|
if (registry.middleware && registry.middleware.length > 0) {
|
|
103
127
|
const pipeline = registry.middleware.reduceRight((next, mw) => (e, c) => mw(e, c, next), baseDispatch);
|
package/dist/runtime/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { JsonValue, RunStartIdentity as DurableRunStartIdentity } from '@swirls/looms/core';
|
|
1
|
+
import type { JsonValue, RunAttributes, RunLaunchSource, RunStartIdentity as DurableRunStartIdentity } from '@swirls/looms/core';
|
|
2
2
|
export interface RunStartIdentity {
|
|
3
3
|
readonly kind: string;
|
|
4
4
|
readonly definitionName: string;
|
|
@@ -6,6 +6,19 @@ export interface RunStartIdentity {
|
|
|
6
6
|
readonly input: JsonValue;
|
|
7
7
|
readonly requestedThreadId: string | null;
|
|
8
8
|
readonly idempotencyKey: string | null;
|
|
9
|
+
readonly launchedBy: RunLaunchSource | null;
|
|
10
|
+
readonly correlationId: string | null;
|
|
11
|
+
readonly attributes: RunAttributes;
|
|
12
|
+
}
|
|
13
|
+
declare const SecretContextConflictError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
14
|
+
readonly _tag: "SecretContextConflictError";
|
|
15
|
+
} & Readonly<A>;
|
|
16
|
+
/** The stored secret context differs. The message never includes the secret values. */
|
|
17
|
+
export declare class SecretContextConflictError extends SecretContextConflictError_base<{
|
|
18
|
+
readonly runId: string;
|
|
19
|
+
readonly message: string;
|
|
20
|
+
}> {
|
|
21
|
+
constructor(runId: string);
|
|
9
22
|
}
|
|
10
23
|
declare const StartRunConflictError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
11
24
|
readonly _tag: "StartRunConflictError";
|
package/dist/runtime/errors.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { Data } from 'effect';
|
|
2
|
+
/** The stored secret context differs. The message never includes the secret values. */
|
|
3
|
+
export class SecretContextConflictError extends Data.TaggedError('SecretContextConflictError') {
|
|
4
|
+
constructor(runId) {
|
|
5
|
+
super({
|
|
6
|
+
runId,
|
|
7
|
+
message: `Run "${runId}" already has a different secret context`,
|
|
8
|
+
});
|
|
9
|
+
this.name = 'SecretContextConflictError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
2
12
|
export class StartRunConflictError extends Data.TaggedError('StartRunConflictError') {
|
|
3
13
|
constructor(runId, requested, existing, mismatches) {
|
|
4
14
|
super({
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type BlobStore } from '@swirls/looms/core';
|
|
2
|
+
/**
|
|
3
|
+
* Content-addressed blob store rooted at `directory`. For Bun and Node hosts.
|
|
4
|
+
* A Durable Object should use `r2BlobStore` instead.
|
|
5
|
+
*/
|
|
6
|
+
export declare function filesystemBlobStore(directory: string): BlobStore;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { Data, Effect, Predicate } from 'effect';
|
|
3
|
+
import { blobStoreFromBytes, BlobStoreError } from '@swirls/looms/core';
|
|
4
|
+
class MissingBlobFile extends Data.TaggedError('MissingBlobFile') {
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Content-addressed blob store rooted at `directory`. For Bun and Node hosts.
|
|
8
|
+
* A Durable Object should use `r2BlobStore` instead.
|
|
9
|
+
*/
|
|
10
|
+
export function filesystemBlobStore(directory) {
|
|
11
|
+
return blobStoreFromBytes(filesystemBlobBytes(directory));
|
|
12
|
+
}
|
|
13
|
+
function filesystemBlobBytes(directory) {
|
|
14
|
+
return {
|
|
15
|
+
read: (key) => readOptional(`${directory}/${key}`, key),
|
|
16
|
+
write: (key, body) => Effect.tryPromise({
|
|
17
|
+
try: () => mkdir(`${directory}/${folderOf(key)}`, { recursive: true }),
|
|
18
|
+
catch: (cause) => new BlobStoreError(`Unable to create a directory for blob key ${key}`, cause),
|
|
19
|
+
}).pipe(Effect.andThen(Effect.tryPromise({
|
|
20
|
+
try: () => writeFile(`${directory}/${key}`, body),
|
|
21
|
+
catch: (cause) => new BlobStoreError(`Unable to write blob key ${key}`, cause),
|
|
22
|
+
}))),
|
|
23
|
+
remove: (key) => Effect.tryPromise({
|
|
24
|
+
try: () => rm(`${directory}/${key}`, { force: true }),
|
|
25
|
+
catch: (cause) => new BlobStoreError(`Unable to delete blob key ${key}`, cause),
|
|
26
|
+
}),
|
|
27
|
+
exists: (key) => Effect.tryPromise({
|
|
28
|
+
try: () => stat(`${directory}/${key}`),
|
|
29
|
+
catch: (cause) => isMissingFile(cause)
|
|
30
|
+
? new MissingBlobFile()
|
|
31
|
+
: new BlobStoreError(`Unable to check blob key ${key}`, cause),
|
|
32
|
+
}).pipe(Effect.as(true), Effect.catchTag('MissingBlobFile', () => Effect.succeed(false))),
|
|
33
|
+
list: (prefix) => listFolder(directory, prefix),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function readOptional(path, key) {
|
|
37
|
+
return Effect.tryPromise({
|
|
38
|
+
try: () => readFile(path),
|
|
39
|
+
catch: (cause) => isMissingFile(cause)
|
|
40
|
+
? new MissingBlobFile()
|
|
41
|
+
: new BlobStoreError(`Unable to read blob key ${key}`, cause),
|
|
42
|
+
}).pipe(Effect.catchTag('MissingBlobFile', () => Effect.succeed(null)), Effect.map((body) => (body === null ? null : new Uint8Array(body))));
|
|
43
|
+
}
|
|
44
|
+
function listFolder(directory, prefix) {
|
|
45
|
+
const folder = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
|
|
46
|
+
return Effect.tryPromise({
|
|
47
|
+
try: () => readdir(`${directory}/${folder}`),
|
|
48
|
+
catch: (cause) => isMissingFile(cause)
|
|
49
|
+
? new MissingBlobFile()
|
|
50
|
+
: new BlobStoreError(`Unable to list blob keys ${prefix}`, cause),
|
|
51
|
+
}).pipe(Effect.catchTag('MissingBlobFile', () => Effect.succeed([])), Effect.map((names) => names.map((name) => `${folder}/${name}`)));
|
|
52
|
+
}
|
|
53
|
+
function folderOf(key) {
|
|
54
|
+
const slash = key.lastIndexOf('/');
|
|
55
|
+
return slash < 0 ? '' : key.slice(0, slash);
|
|
56
|
+
}
|
|
57
|
+
function isMissingFile(cause) {
|
|
58
|
+
return Predicate.isObject(cause) && 'code' in cause && cause.code === 'ENOENT';
|
|
59
|
+
}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import { Effect, Layer, type Context } from 'effect';
|
|
2
|
-
import { type AnyRuntimeModule, type AppendableEvent, type EventCatalog, type EventEnvelope, type EventInput, type EventOrigin, type EventStore, InvalidEventError, type JsonValue, type OutstandingEffect, type
|
|
1
|
+
import { Effect, Layer, type Context, type Types } from 'effect';
|
|
2
|
+
import { type AnyRuntimeModule, type AppendableEvent, type EventCatalog, type EventEnvelope, type EventInput, type EventOrigin, type EventStore, InvalidEventError, type DefinitionResolveError, type DefinitionResolver, type JsonValue, type OutstandingEffect, type RetryPolicy, type SecretContext, type TraceContext, type RunCursor, type RunState, type SnapshotStore } from '@swirls/looms/core';
|
|
3
3
|
import type { EffectWorkerTask } from './types';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/** What a dispatch carries beyond the effect itself. */
|
|
5
|
+
export interface WorkerTaskExtras {
|
|
6
|
+
/** Progress from the previous attempt's last heartbeat. */
|
|
7
|
+
readonly details?: JsonValue | null;
|
|
8
|
+
readonly secrets?: SecretContext;
|
|
9
|
+
readonly trace?: TraceContext | null;
|
|
10
|
+
readonly retry?: RetryPolicy;
|
|
11
|
+
readonly scheduleToStartAt?: number | null;
|
|
12
|
+
}
|
|
13
|
+
export declare function workerTask(runId: string, item: OutstandingEffect, attempt: number, extras?: WorkerTaskExtras): EffectWorkerTask;
|
|
14
|
+
declare const UnknownDefinitionError_base: new <A extends Record<string, any> = {}>(args: Types.VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
6
15
|
readonly _tag: "UnknownDefinitionError";
|
|
7
16
|
} & Readonly<A>;
|
|
8
17
|
export declare class UnknownDefinitionError extends UnknownDefinitionError_base<{
|
|
@@ -34,14 +43,14 @@ export declare function groupOutstanding(items: readonly {
|
|
|
34
43
|
* A future third producer of thread.started must call this; do not emit the
|
|
35
44
|
* event with raw input.
|
|
36
45
|
*/
|
|
37
|
-
export declare function threadStartedEvents(definitions:
|
|
46
|
+
export declare function threadStartedEvents(definitions: DefinitionResolver, args: {
|
|
38
47
|
kind: string;
|
|
39
48
|
definitionName: string;
|
|
40
49
|
definitionVersion: string;
|
|
41
50
|
input: JsonValue;
|
|
42
51
|
threadId: string;
|
|
43
52
|
parentThreadId: string | null;
|
|
44
|
-
}): Effect.Effect<ReadonlyArray<EventInput>, UnknownDefinitionError>;
|
|
53
|
+
}): Effect.Effect<ReadonlyArray<EventInput>, UnknownDefinitionError | DefinitionResolveError>;
|
|
45
54
|
export declare function synthesizedThreadFailed(before: RunState, after: RunState, written: readonly EventEnvelope[]): EventInput[];
|
|
46
55
|
/** Cancel whatever is still live below each thread `written` cancels, deepest first. */
|
|
47
56
|
export declare function cascadedCancellations(state: RunState, written: readonly EventEnvelope[]): EventInput[];
|