@yolk-sdk/harness 0.1.0-canary.77 → 0.1.0-canary.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -2
- package/dist/coordinator.d.mts +12 -2
- package/dist/coordinator.d.mts.map +1 -1
- package/dist/coordinator.mjs +31 -6
- package/dist/coordinator.mjs.map +1 -1
- package/dist/driver/durable-object.d.mts +1 -1
- package/dist/driver/durable-object.d.mts.map +1 -1
- package/dist/driver/durable-object.mjs +4 -4
- package/dist/driver/durable-object.mjs.map +1 -1
- package/dist/driver/memory.d.mts +1 -1
- package/dist/driver/memory.d.mts.map +1 -1
- package/dist/driver/memory.mjs +5 -5
- package/dist/driver/memory.mjs.map +1 -1
- package/dist/driver.d.mts +68 -9
- package/dist/driver.d.mts.map +1 -1
- package/dist/driver.mjs +84 -83
- package/dist/driver.mjs.map +1 -1
- package/dist/inbox.d.mts +274 -5
- package/dist/inbox.d.mts.map +1 -1
- package/dist/inbox.mjs +201 -196
- package/dist/inbox.mjs.map +1 -1
- package/dist/outcome-constructors-internal.d.mts +403 -0
- package/dist/outcome-constructors-internal.d.mts.map +1 -0
- package/dist/outcome-constructors-internal.mjs +11 -0
- package/dist/outcome-constructors-internal.mjs.map +1 -0
- package/dist/outcome.d.mts +325 -25
- package/dist/outcome.d.mts.map +1 -1
- package/dist/outcome.mjs +47 -70
- package/dist/outcome.mjs.map +1 -1
- package/dist/store.d.mts +22 -8
- package/dist/store.d.mts.map +1 -1
- package/dist/store.mjs +80 -68
- package/dist/store.mjs.map +1 -1
- package/package.json +3 -3
- package/src/coordinator.ts +108 -7
- package/src/driver/durable-object.ts +6 -12
- package/src/driver/memory.ts +9 -8
- package/src/driver.ts +179 -160
- package/src/inbox.ts +330 -268
- package/src/outcome-constructors-internal.ts +18 -0
- package/src/outcome.ts +165 -118
- package/src/store.ts +123 -99
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Canary APIs are unstable. Keep all `@yolk-sdk/*` packages on the same version.
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
pnpm add @yolk-sdk/harness@canary effect@4.0.0-
|
|
11
|
+
pnpm add @yolk-sdk/harness@canary effect@4.0.0-rc.115
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
## Subpaths
|
|
@@ -24,6 +24,34 @@ pnpm add @yolk-sdk/harness@canary effect@4.0.0-beta.80
|
|
|
24
24
|
| `@yolk-sdk/harness/driver/durable-object` | Durable Object storage-backed claims + driver |
|
|
25
25
|
| `@yolk-sdk/harness/outcome` | Classify one model/tool attempt: Completed / Retry / Continue / RecoverFull / Compacted / AwaitingInput |
|
|
26
26
|
|
|
27
|
+
## Tagged constructors
|
|
28
|
+
|
|
29
|
+
Inbox, driver, and outcome ADTs are `Data.taggedEnum` **values** on the existing subpaths. They are
|
|
30
|
+
plain objects with `_tag` last, not `Equal`/`Hash` Data classes.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import {
|
|
34
|
+
DrainBegin,
|
|
35
|
+
HitlDecision,
|
|
36
|
+
PauseDecision,
|
|
37
|
+
RecoveryAdmission,
|
|
38
|
+
RecoveryAttempt
|
|
39
|
+
} from '@yolk-sdk/harness/inbox'
|
|
40
|
+
import { StopDecision } from '@yolk-sdk/harness/driver'
|
|
41
|
+
import { HitlMatch, OverflowCompactionResult, StepOutcome } from '@yolk-sdk/harness/outcome'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
| Subpath | Value constructors |
|
|
45
|
+
| --------- | ------------------------------------------------------------------------------------- |
|
|
46
|
+
| `inbox` | `HitlDecision`, `PauseDecision`, `RecoveryAttempt`, `RecoveryAdmission`, `DrainBegin` |
|
|
47
|
+
| `driver` | `StopDecision` (`Idle` / `Interrupted` / `ParkCleared`) |
|
|
48
|
+
| `outcome` | `OverflowCompactionResult`, `StepOutcome`, `HitlMatch` |
|
|
49
|
+
|
|
50
|
+
`StopDecision` is the same internal tagged enum, re-exported as `export type` + `export const` from
|
|
51
|
+
`./driver`. Driver recovery uses Inbox `RecoveryAttempt` (`Skip` / `Exhausted` / `Resume`). Prefer
|
|
52
|
+
`Match.tag` / `Predicate.isTagged` over `_tag ===`. `HitlMatch.Match({ requestId })` /
|
|
53
|
+
`HitlMatch.Mismatch()` replace handwritten `{ _tag: 'Match' | 'Mismatch' }` objects.
|
|
54
|
+
|
|
27
55
|
## Example
|
|
28
56
|
|
|
29
57
|
Omitting `drain` uses a no-op (`Effect.void`): `driver.run` only claims and releases ownership. Attach host work with a custom drain. `Inbox.takePromotable` requires that drain's live `drainToken`.
|
|
@@ -33,7 +61,7 @@ Omitting `drain` uses a no-op (`Effect.void`): `driver.run` only claims and rele
|
|
|
33
61
|
Setup:
|
|
34
62
|
|
|
35
63
|
```bash
|
|
36
|
-
pnpm add @yolk-sdk/harness@canary effect@4.0.0-
|
|
64
|
+
pnpm add @yolk-sdk/harness@canary effect@4.0.0-rc.115
|
|
37
65
|
pnpm add -D tsx
|
|
38
66
|
```
|
|
39
67
|
|
|
@@ -115,6 +143,40 @@ Startup is explicit: build the shared Driver/Inbox/Store, restore host-owned wai
|
|
|
115
143
|
- Human pause releases the busy claim. User `stop` is terminal at the captured owner's settlement (including shutdown then user-stop). Shutdown interrupt keeps the claim. The Durable Object snapshot claim store does not make Inbox durable.
|
|
116
144
|
- After process restart, hosts enumerate their own persisted waiting checkpoints and rebuild a fresh park with the current drain token. Do not import old Inbox parks, drain tokens, or generation strings. Correlate later responses to the new park and host identity policy. Persisted partial responses may be re-admitted only after protocol/host validation against that fresh park.
|
|
117
145
|
|
|
146
|
+
## Type imports (breaking)
|
|
147
|
+
|
|
148
|
+
Runtime/wire is unchanged. These public type exports were renamed; there are no `Shape` aliases.
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
import type { RunStoreApi } from '@yolk-sdk/harness/store'
|
|
152
|
+
import type { InboxApi } from '@yolk-sdk/harness/inbox'
|
|
153
|
+
import type { DriverApi } from '@yolk-sdk/harness/driver'
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
| Old type import | New type import |
|
|
157
|
+
| ---------------------------------------------- | --------------- |
|
|
158
|
+
| `RunStoreShape` from `@yolk-sdk/harness/store` | `RunStoreApi` |
|
|
159
|
+
| `InboxShape` from `@yolk-sdk/harness/inbox` | `InboxApi` |
|
|
160
|
+
| `DriverShape` from `@yolk-sdk/harness/driver` | `DriverApi` |
|
|
161
|
+
|
|
162
|
+
## Owner layers
|
|
163
|
+
|
|
164
|
+
Each service is acquired through its owning static layer factory, which holds the real
|
|
165
|
+
construction logic. The historical `make*` factories keep their signatures and behavior
|
|
166
|
+
and delegate to these canonical owners:
|
|
167
|
+
|
|
168
|
+
| Canonical owner layer | Backward-compatible factory |
|
|
169
|
+
| ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
170
|
+
| `RunStore.inMemoryLayer()` / `snapshotLayer()` | `makeInMemoryRunStoreLayer` / `makeSnapshotRunStoreLayer` |
|
|
171
|
+
| `Inbox.layer()` | `makeInMemoryInboxLayer` |
|
|
172
|
+
| `RunCoordinator.layer()` (claims via `RunStore`) | `makeCoordinator` stays as the scoped doorbell factory |
|
|
173
|
+
| `Driver.layer()` (requires `RunStore` + `Inbox` + `RunCoordinator`) + `Driver.coordinatedLayer()` (default coordinator, lazy options) | `makeDriverLayer` delegates to `coordinatedLayer`, keeping the `RunStore` + `Inbox` requirement |
|
|
174
|
+
|
|
175
|
+
Every factory call builds fresh layers, so composed harnesses never share `Ref` state.
|
|
176
|
+
Within one composed harness, the driver and the merged output share a single store
|
|
177
|
+
instance. `InterruptReason` is owned by `@yolk-sdk/harness/coordinator` and re-exported
|
|
178
|
+
from `@yolk-sdk/harness/driver`.
|
|
179
|
+
|
|
118
180
|
## Step outcomes
|
|
119
181
|
|
|
120
182
|
`attemptModelTurn` classifies **one `runModelTurn` invocation** after that stream's configured loop/provider retries. It does not add another retry loop or persist. Hosts that schedule physical attempts themselves should pass `LoopConfig.maxRetries: 0` and skip retry decorators.
|
package/dist/coordinator.d.mts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RunStore } from "./store.mjs";
|
|
2
|
+
import { Context, Effect, Exit, Layer, Scope } from "effect";
|
|
2
3
|
|
|
3
4
|
//#region src/coordinator.d.ts
|
|
4
5
|
/** `"input"` subsumes `"steer"` when coalescing wakes. */
|
|
5
6
|
type Promotable = 'input' | 'steer';
|
|
7
|
+
/** Shutdown retains the claim; explicit user stop releases it after settlement. */
|
|
8
|
+
type InterruptReason = 'user' | 'shutdown';
|
|
6
9
|
type CapturedRun<E> = {
|
|
7
10
|
readonly _tag: 'Started';
|
|
8
11
|
readonly join: Effect.Effect<void, E>;
|
|
@@ -57,6 +60,13 @@ declare const makeCoordinator: <Key, E, Reason = never>(options: {
|
|
|
57
60
|
readonly started?: (key: Key) => Effect.Effect<void>;
|
|
58
61
|
readonly settled?: (key: Key, exit: Exit.Exit<void, E>, reason?: Reason) => Effect.Effect<void>;
|
|
59
62
|
}) => Effect.Effect<Coordinator<Key, E, Reason>, never, Scope.Scope>;
|
|
63
|
+
declare const RunCoordinator_base: Context.ServiceClass<RunCoordinator, "@yolk-sdk/harness/RunCoordinator", Coordinator<string, never, InterruptReason>>;
|
|
64
|
+
/** Owning coordinator layer, with per-acquisition claim receipts and settlement policy. */
|
|
65
|
+
declare class RunCoordinator extends RunCoordinator_base {
|
|
66
|
+
static layer: (options?: {
|
|
67
|
+
readonly drain?: (runId: string, force: boolean, scope: Promotable) => Effect.Effect<void>;
|
|
68
|
+
}) => Layer.Layer<RunCoordinator, never, RunStore>;
|
|
69
|
+
}
|
|
60
70
|
//#endregion
|
|
61
|
-
export { CapturedRun, Coordinator, Promotable, StopReceipt, makeCoordinator };
|
|
71
|
+
export { CapturedRun, Coordinator, InterruptReason, Promotable, RunCoordinator, StopReceipt, makeCoordinator };
|
|
62
72
|
//# sourceMappingURL=coordinator.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinator.d.mts","names":[],"sources":["../src/coordinator.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"coordinator.d.mts","names":[],"sources":["../src/coordinator.ts"],"mappings":";;;;;KAqBY,UAAA;AAKZ;AAAA,KAFY,eAAA;AAAA,KAEA,WAAA;EAAA,SACG,IAAA;EAAA,SAA0B,IAAA,EAAM,MAAA,CAAO,MAAA,OAAa,CAAA;AAAA;EAAA,SACpD,IAAA;EAAA,SAAyB,IAAA,EAAM,MAAA,CAAO,MAAA,OAAa,CAAA;AAAA;EAAA,SACnD,IAAA;EAAA,SAA2B,eAAA,EAAiB,MAAA,CAAO,MAAA;AAAA;AAAA,KAEtD,WAAA;EAAA,SACG,IAAA;AAAA;EAAA,SACA,IAAA;AAAA;EAAA,SACA,IAAA;AAAA;EAAA,SACA,IAAA;AAAA;AAAA,KAEH,WAAA;EAAA,SACD,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAO,WAAA,CAAY,GAAA;EAAA,SAClC,QAAA,GAAW,GAAA,EAAK,GAAA,KAAQ,MAAA,CAAO,MAAA,WAVwB;EAAA,SAYvD,GAAA,GAAM,GAAA,EAAK,GAAA,KAAQ,MAAA,CAAO,MAAA,OAAa,CAAA;EAZsB;AAExE;;;;;EAFwE,SAmB7D,UAAA,GAAa,GAAA,EAAK,GAAA,KAAQ,MAAA,CAAO,MAAA,CAAO,WAAA,CAAY,CAAA,IAdhD;EAAA,SAgBJ,IAAA,GAAO,GAAA,EAAK,GAAA,EAAK,KAAA,GAAQ,UAAA,KAAe,MAAA,CAAO,MAAA;EAfvC;AAAA;AAEnB;;;EAFmB,SAqBR,SAAA,GACP,GAAA,EAAK,GAAA,EACL,MAAA,GAAS,MAAA,EACT,OAAA;IAAA,SAAqB,eAAA;EAAA,MAClB,MAAA,CAAO,MAAA;EArBa;;;;;;;EAAA,SA6BhB,YAAA,GAAe,GAAA,EAAK,GAAA,EAAK,MAAA,EAAQ,MAAA,KAAW,MAAA,CAAO,MAAA,CAAO,WAAA,GApBhC;EAAA,SAsB1B,SAAA,GAAY,GAAA,EAAK,GAAA,KAAQ,MAAA,CAAO,MAAA;AAAA;AAAA,cAgB9B,eAAA,2BAA2C,OAAA;EAAA,SAC7C,KAAA,GAAQ,GAAA,EAAK,GAAA,EAAK,KAAA,WAAgB,KAAA,EAAO,UAAA,KAAe,MAAA,CAAO,MAAA,OAAa,CAAA;EAAA,SAC5E,OAAA,IAAW,GAAA,EAAK,GAAA,KAAQ,MAAA,CAAO,MAAA;EAAA,SAC/B,OAAA,IAAW,GAAA,EAAK,GAAA,EAAK,IAAA,EAAM,IAAA,CAAK,IAAA,OAAW,CAAA,GAAI,MAAA,GAAS,MAAA,KAAW,MAAA,CAAO,MAAA;AAAA,MACjF,MAAA,CAAO,MAAA,CAAO,WAAA,CAAY,GAAA,EAAK,CAAA,EAAG,MAAA,UAAgB,KAAA,CAAM,KAAA;AAAA,cAyMxD,mBAAA;;cAGS,cAAA,SAAuB,mBAAA;EAAA,OAI3B,KAAA,GAAS,OAAA;IAAA,SACL,KAAA,IAAS,KAAA,UAAe,KAAA,WAAgB,KAAA,EAAO,UAAA,KAAe,MAAA,CAAO,MAAA;EAAA,MAC5E,KAAA,CAAM,KAAA,CAAM,cAAA,SAAuB,QAAA;AAAA"}
|
package/dist/coordinator.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StopReceipt } from "./outcome-constructors-internal.mjs";
|
|
2
|
+
import { RunStore } from "./store.mjs";
|
|
3
|
+
import { Cause, Context, Deferred, Effect, Exit, Fiber, FiberSet, Layer } from "effect";
|
|
2
4
|
//#region src/coordinator.ts
|
|
3
5
|
/**
|
|
4
6
|
* Process-local run coordinator.
|
|
@@ -103,27 +105,50 @@ const makeCoordinator = (options) => Effect.gen(function* () {
|
|
|
103
105
|
}),
|
|
104
106
|
terminalStop: (key, reason) => Effect.suspend(() => {
|
|
105
107
|
const execution = executions.get(key);
|
|
106
|
-
if (execution === void 0) return Effect.succeed(
|
|
108
|
+
if (execution === void 0) return Effect.succeed(StopReceipt.Idle());
|
|
107
109
|
execution.pendingWake = void 0;
|
|
108
110
|
if (execution.owner === void 0) {
|
|
109
111
|
execution.stopping = true;
|
|
110
|
-
return Effect.succeed(
|
|
112
|
+
return Effect.succeed(StopReceipt.Settling());
|
|
111
113
|
}
|
|
112
114
|
execution.interruptionReason = reason;
|
|
113
115
|
if (execution.stopping) {
|
|
114
116
|
const request = execution.request;
|
|
115
|
-
return request === void 0 ? Effect.succeed(
|
|
117
|
+
return request === void 0 ? Effect.succeed(StopReceipt.LiveStopping()) : Fiber.join(request).pipe(Effect.as(StopReceipt.LiveStopping()));
|
|
116
118
|
}
|
|
117
119
|
const owner = execution.owner;
|
|
118
120
|
execution.stopping = true;
|
|
119
121
|
const request = forkInterruptionRequest(owner);
|
|
120
122
|
execution.request = request;
|
|
121
|
-
return Fiber.join(request).pipe(Effect.as(
|
|
123
|
+
return Fiber.join(request).pipe(Effect.as(StopReceipt.Interrupted()));
|
|
122
124
|
}),
|
|
123
125
|
awaitIdle
|
|
124
126
|
};
|
|
125
127
|
});
|
|
128
|
+
/** Owning coordinator layer, with per-acquisition claim receipts and settlement policy. */
|
|
129
|
+
var RunCoordinator = class extends Context.Service()("@yolk-sdk/harness/RunCoordinator") {
|
|
130
|
+
static layer = (options) => Layer.effect(this, Effect.gen(function* () {
|
|
131
|
+
const store = yield* RunStore;
|
|
132
|
+
const drain = options?.drain ?? ((_runId, _force, _scope) => Effect.void);
|
|
133
|
+
const acquired = /* @__PURE__ */ new Set();
|
|
134
|
+
return yield* makeCoordinator({
|
|
135
|
+
drain,
|
|
136
|
+
started: (runId) => store.claim(runId).pipe(Effect.tap(() => Effect.sync(() => {
|
|
137
|
+
acquired.add(runId);
|
|
138
|
+
}))),
|
|
139
|
+
settled: (runId, exit, reason) => Effect.suspend(() => {
|
|
140
|
+
const owned = acquired.delete(runId);
|
|
141
|
+
if (owned && (reason === "user" || reason === void 0 && !Exit.hasInterrupts(exit))) return store.release(runId);
|
|
142
|
+
if (reason === "user" && !owned) return store.isClaimed(runId).pipe(Effect.flatMap((claimed) => claimed ? store.release(runId) : Effect.void));
|
|
143
|
+
return Effect.void;
|
|
144
|
+
}).pipe(Effect.exit, Effect.flatMap((settledExit) => {
|
|
145
|
+
if (Exit.isSuccess(settledExit)) return Effect.void;
|
|
146
|
+
return Effect.failCause(Exit.isFailure(exit) ? Cause.combine(exit.cause, settledExit.cause) : settledExit.cause);
|
|
147
|
+
}))
|
|
148
|
+
});
|
|
149
|
+
}));
|
|
150
|
+
};
|
|
126
151
|
//#endregion
|
|
127
|
-
export { makeCoordinator };
|
|
152
|
+
export { RunCoordinator, makeCoordinator };
|
|
128
153
|
|
|
129
154
|
//# sourceMappingURL=coordinator.mjs.map
|
package/dist/coordinator.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordinator.mjs","names":[],"sources":["../src/coordinator.ts"],"sourcesContent":["/**\n * Process-local run coordinator.\n *\n * Port of OpenCode v2 `SessionRunCoordinator` (MIT): one busy period per key,\n * a doorbell that coalesces wakes, and interrupt that claims pending wakes so a\n * dead intent cannot restart. Steering lands at the next drain boundary.\n *\n * @see https://github.com/sst/opencode (packages/core/src/session/run-coordinator.ts)\n */\nimport { Deferred, Effect, Fiber, FiberSet } from 'effect'\nimport type { Exit, Scope } from 'effect'\n\n// Private settlement receipt: succeed the Deferred with Exit as a value so\n// interrupt fan-out does not skip Effect 4.0.0-beta.80 Deferred listeners.\n// Public waiters flatten that Exit; this is not a global Deferred fix.\nconst awaitDone = <E>(done: Deferred.Deferred<Exit.Exit<void, E>>): Effect.Effect<void, E> =>\n Deferred.await(done).pipe(Effect.flatMap(exit => exit))\n\n/** `\"input\"` subsumes `\"steer\"` when coalescing wakes. */\nexport type Promotable = 'input' | 'steer'\n\nexport type CapturedRun<E> =\n | { readonly _tag: 'Started'; readonly join: Effect.Effect<void, E> }\n | { readonly _tag: 'Joined'; readonly join: Effect.Effect<void, E> }\n | { readonly _tag: 'Stopping'; readonly awaitSettlement: Effect.Effect<void> }\n\nexport type StopReceipt =\n | { readonly _tag: 'Idle' }\n | { readonly _tag: 'Interrupted' }\n | { readonly _tag: 'LiveStopping' }\n | { readonly _tag: 'Settling' }\n\nexport type Coordinator<Key, E, Reason = never> = {\n readonly active: Effect.Effect<ReadonlySet<Key>>\n readonly isActive: (key: Key) => Effect.Effect<boolean>\n /** Starts an execution while idle, or joins the active execution. */\n readonly run: (key: Key) => Effect.Effect<void, E>\n /**\n * Captures a run waiter without awaiting settlement.\n * Idle starts force=true (`Started`); an active owner is joined (`Joined`),\n * including during natural settlement. A stopping owner yields `Stopping` with a\n * settlement waiter and no start.\n */\n readonly captureRun: (key: Key) => Effect.Effect<CapturedRun<E>>\n /** Rings the doorbell: idle starts; active drains again before settling. */\n readonly wake: (key: Key, scope?: Promotable) => Effect.Effect<void>\n /**\n * Stops the active execution and clears its doorbell. No-op when idle.\n * Resolves once the interruption request is delivered, not when cleanup settles.\n * First accepted `reason` is kept; use `terminalStop` to escalate.\n */\n readonly interrupt: (\n key: Key,\n reason?: Reason,\n options?: { readonly awaitSettlement?: boolean }\n ) => Effect.Effect<boolean>\n /**\n * Terminal stop receipt. Always clears pendingWake. Settling means the owner\n * is already gone and the settled callback is chosen; Driver may release the\n * claim under the Inbox gate. LiveStopping/Interrupted leave release to that\n * owner's future settled callback. LiveStopping joins the same outstanding\n * interruption request rather than forking a second one.\n */\n readonly terminalStop: (key: Key, reason: Reason) => Effect.Effect<StopReceipt>\n /** Resolves once no execution is active. Never starts work. */\n readonly awaitIdle: (key: Key) => Effect.Effect<void>\n}\n\ntype Execution<E, Reason> = {\n readonly done: Deferred.Deferred<Exit.Exit<void, E>>\n owner?: Fiber.Fiber<void>\n request?: Fiber.Fiber<void>\n scope: Promotable\n pendingWake?: Promotable\n stopping: boolean\n interruptionReason?: Reason\n}\n\nconst widerScope = (current: Promotable | undefined, next: Promotable): Promotable =>\n current === 'input' || next === 'input' ? 'input' : 'steer'\n\nexport const makeCoordinator = <Key, E, Reason = never>(options: {\n readonly drain: (key: Key, force: boolean, scope: Promotable) => Effect.Effect<void, E>\n readonly started?: (key: Key) => Effect.Effect<void>\n readonly settled?: (key: Key, exit: Exit.Exit<void, E>, reason?: Reason) => Effect.Effect<void>\n}): Effect.Effect<Coordinator<Key, E, Reason>, never, Scope.Scope> =>\n Effect.gen(function* () {\n const executions = new Map<Key, Execution<E, Reason>>()\n const fork = yield* FiberSet.makeRuntime<never, void, never>()\n\n const loop = (\n key: Key,\n execution: Execution<E, Reason>,\n force: boolean\n ): Effect.Effect<void, E> =>\n Effect.suspend(() => {\n if (execution.stopping) return Effect.void\n return options.drain(key, force, execution.scope)\n }).pipe(\n Effect.andThen(\n Effect.suspend(() => {\n if (execution.stopping || execution.pendingWake === undefined) return Effect.void\n execution.scope = execution.pendingWake\n execution.pendingWake = undefined\n return Effect.yieldNow.pipe(Effect.andThen(loop(key, execution, false)))\n })\n )\n )\n\n const settle = (key: Key, execution: Execution<E, Reason>, exit: Exit.Exit<void, E>) => {\n if (execution.pendingWake !== undefined) start(key, false, execution.pendingWake)\n else executions.delete(key)\n return Deferred.succeed(execution.done, exit).pipe(Effect.asVoid)\n }\n\n const start = (key: Key, force: boolean, scope: Promotable) => {\n const execution: Execution<E, Reason> = {\n done: Deferred.makeUnsafe<Exit.Exit<void, E>>(),\n scope,\n stopping: false\n }\n executions.set(key, execution)\n execution.owner = fork(\n Effect.yieldNow.pipe(\n Effect.andThen(\n Effect.uninterruptible(Effect.suspend(() => options.started?.(key) ?? Effect.void))\n ),\n Effect.andThen(loop(key, execution, force)),\n Effect.onExit(exit =>\n Effect.suspend(() => {\n execution.owner = undefined\n return options.settled?.(key, exit, execution.interruptionReason) ?? Effect.void\n })\n ),\n Effect.onExit(exit => settle(key, execution, exit)),\n Effect.exit,\n Effect.asVoid\n )\n )\n return execution\n }\n\n const forkInterruptionRequest = (owner: Fiber.Fiber<void>): Fiber.Fiber<void> =>\n fork(Effect.yieldNow.pipe(Effect.andThen(Effect.sync(() => owner.interruptUnsafe()))))\n\n const interruptNow = (key: Key, reason?: Reason): Effect.Effect<boolean> =>\n Effect.suspend(() => {\n const execution = executions.get(key)\n if (execution === undefined || execution.stopping) return Effect.succeed(false)\n if (execution.owner === undefined) {\n execution.pendingWake = undefined\n return Effect.succeed(false)\n }\n const owner = execution.owner\n execution.stopping = true\n execution.pendingWake = undefined\n execution.interruptionReason = reason\n // Capture the exact old owner and fork the request in this same lazy\n // transition so cancellation cannot leave stopping=true with no request.\n // Initial yield breaks owner -> resumed caller -> owner reentrancy.\n // Join the request fiber only; interruptUnsafe may run interruptible\n // finalizers inline until they suspend. Do not await owner settlement.\n const request = forkInterruptionRequest(owner)\n execution.request = request\n return Fiber.join(request).pipe(Effect.as(true))\n })\n\n const awaitIdle = (key: Key): Effect.Effect<void> =>\n Effect.suspend(() => {\n const execution = executions.get(key)\n if (execution === undefined) return Effect.void\n return awaitDone(execution.done).pipe(Effect.ignoreCause, Effect.andThen(awaitIdle(key)))\n })\n\n return {\n active: Effect.sync(() => new Set(executions.keys())),\n isActive: key => Effect.sync(() => executions.has(key)),\n run: key =>\n Effect.suspend(() => {\n const execution = executions.get(key)\n if (execution === undefined) return awaitDone(start(key, true, 'input').done)\n if (!execution.stopping) return awaitDone(execution.done)\n return awaitDone(execution.done).pipe(\n Effect.ignoreCause,\n Effect.andThen(\n Effect.suspend(() => {\n const next = executions.get(key)\n return next === undefined\n ? awaitDone(start(key, true, 'input').done)\n : awaitDone(next.done)\n })\n )\n )\n }),\n captureRun: key =>\n Effect.sync(() => {\n const execution = executions.get(key)\n if (execution === undefined) {\n const started = start(key, true, 'input')\n return { _tag: 'Started' as const, join: awaitDone(started.done) }\n }\n if (!execution.stopping) {\n return { _tag: 'Joined' as const, join: awaitDone(execution.done) }\n }\n return {\n _tag: 'Stopping' as const,\n awaitSettlement: awaitDone(execution.done).pipe(Effect.ignoreCause)\n }\n }),\n wake: (key, scope = 'input') =>\n Effect.sync(() => {\n const execution = executions.get(key)\n if (execution !== undefined) {\n execution.pendingWake = widerScope(execution.pendingWake, scope)\n return\n }\n start(key, false, scope)\n }),\n interrupt: (key, reason, options) =>\n Effect.suspend(() => {\n const execution = executions.get(key)\n return interruptNow(key, reason).pipe(\n Effect.tap(() =>\n options?.awaitSettlement === true && execution !== undefined\n ? awaitDone(execution.done).pipe(Effect.ignoreCause)\n : Effect.void\n )\n )\n }),\n terminalStop: (key, reason) =>\n Effect.suspend((): Effect.Effect<StopReceipt> => {\n const execution = executions.get(key)\n if (execution === undefined) return Effect.succeed({ _tag: 'Idle' } as const)\n execution.pendingWake = undefined\n if (execution.owner === undefined) {\n execution.stopping = true\n return Effect.succeed({ _tag: 'Settling' } as const)\n }\n execution.interruptionReason = reason\n if (execution.stopping) {\n const request = execution.request\n return request === undefined\n ? Effect.succeed({ _tag: 'LiveStopping' } as const)\n : Fiber.join(request).pipe(Effect.as({ _tag: 'LiveStopping' } as const))\n }\n const owner = execution.owner\n execution.stopping = true\n const request = forkInterruptionRequest(owner)\n execution.request = request\n return Fiber.join(request).pipe(Effect.as({ _tag: 'Interrupted' } as const))\n }),\n awaitIdle\n }\n })\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"coordinator.mjs","names":["stopReceipt"],"sources":["../src/coordinator.ts"],"sourcesContent":["/**\n * Process-local run coordinator.\n *\n * Port of OpenCode v2 `SessionRunCoordinator` (MIT): one busy period per key,\n * a doorbell that coalesces wakes, and interrupt that claims pending wakes so a\n * dead intent cannot restart. Steering lands at the next drain boundary.\n *\n * @see https://github.com/sst/opencode (packages/core/src/session/run-coordinator.ts)\n */\nimport { Cause, Context, Deferred, Effect, Exit, Fiber, FiberSet, Layer } from 'effect'\nimport type { Scope } from 'effect'\nimport { StopReceipt as stopReceipt } from './outcome-constructors-internal.ts'\nimport { RunStore } from './store.ts'\n\n// Private settlement receipt: succeed the Deferred with Exit as a value so\n// interrupt fan-out does not skip Effect 4.0.0-beta.80 Deferred listeners.\n// Public waiters flatten that Exit; this is not a global Deferred fix.\nconst awaitDone = <E>(done: Deferred.Deferred<Exit.Exit<void, E>>): Effect.Effect<void, E> =>\n Deferred.await(done).pipe(Effect.flatMap(exit => exit))\n\n/** `\"input\"` subsumes `\"steer\"` when coalescing wakes. */\nexport type Promotable = 'input' | 'steer'\n\n/** Shutdown retains the claim; explicit user stop releases it after settlement. */\nexport type InterruptReason = 'user' | 'shutdown'\n\nexport type CapturedRun<E> =\n | { readonly _tag: 'Started'; readonly join: Effect.Effect<void, E> }\n | { readonly _tag: 'Joined'; readonly join: Effect.Effect<void, E> }\n | { readonly _tag: 'Stopping'; readonly awaitSettlement: Effect.Effect<void> }\n\nexport type StopReceipt =\n | { readonly _tag: 'Idle' }\n | { readonly _tag: 'Interrupted' }\n | { readonly _tag: 'LiveStopping' }\n | { readonly _tag: 'Settling' }\n\nexport type Coordinator<Key, E, Reason = never> = {\n readonly active: Effect.Effect<ReadonlySet<Key>>\n readonly isActive: (key: Key) => Effect.Effect<boolean>\n /** Starts an execution while idle, or joins the active execution. */\n readonly run: (key: Key) => Effect.Effect<void, E>\n /**\n * Captures a run waiter without awaiting settlement.\n * Idle starts force=true (`Started`); an active owner is joined (`Joined`),\n * including during natural settlement. A stopping owner yields `Stopping` with a\n * settlement waiter and no start.\n */\n readonly captureRun: (key: Key) => Effect.Effect<CapturedRun<E>>\n /** Rings the doorbell: idle starts; active drains again before settling. */\n readonly wake: (key: Key, scope?: Promotable) => Effect.Effect<void>\n /**\n * Stops the active execution and clears its doorbell. No-op when idle.\n * Resolves once the interruption request is delivered, not when cleanup settles.\n * First accepted `reason` is kept; use `terminalStop` to escalate.\n */\n readonly interrupt: (\n key: Key,\n reason?: Reason,\n options?: { readonly awaitSettlement?: boolean }\n ) => Effect.Effect<boolean>\n /**\n * Terminal stop receipt. Always clears pendingWake. Settling means the owner\n * is already gone and the settled callback is chosen; Driver may release the\n * claim under the Inbox gate. LiveStopping/Interrupted leave release to that\n * owner's future settled callback. LiveStopping joins the same outstanding\n * interruption request rather than forking a second one.\n */\n readonly terminalStop: (key: Key, reason: Reason) => Effect.Effect<StopReceipt>\n /** Resolves once no execution is active. Never starts work. */\n readonly awaitIdle: (key: Key) => Effect.Effect<void>\n}\n\ntype Execution<E, Reason> = {\n readonly done: Deferred.Deferred<Exit.Exit<void, E>>\n owner?: Fiber.Fiber<void>\n request?: Fiber.Fiber<void>\n scope: Promotable\n pendingWake?: Promotable\n stopping: boolean\n interruptionReason?: Reason\n}\n\nconst widerScope = (current: Promotable | undefined, next: Promotable): Promotable =>\n current === 'input' || next === 'input' ? 'input' : 'steer'\n\nexport const makeCoordinator = <Key, E, Reason = never>(options: {\n readonly drain: (key: Key, force: boolean, scope: Promotable) => Effect.Effect<void, E>\n readonly started?: (key: Key) => Effect.Effect<void>\n readonly settled?: (key: Key, exit: Exit.Exit<void, E>, reason?: Reason) => Effect.Effect<void>\n}): Effect.Effect<Coordinator<Key, E, Reason>, never, Scope.Scope> =>\n Effect.gen(function* () {\n const executions = new Map<Key, Execution<E, Reason>>()\n const fork = yield* FiberSet.makeRuntime<never, void, never>()\n\n const loop = (\n key: Key,\n execution: Execution<E, Reason>,\n force: boolean\n ): Effect.Effect<void, E> =>\n Effect.suspend(() => {\n if (execution.stopping) return Effect.void\n\n return options.drain(key, force, execution.scope)\n }).pipe(\n Effect.andThen(\n Effect.suspend(() => {\n if (execution.stopping || execution.pendingWake === undefined) return Effect.void\n execution.scope = execution.pendingWake\n execution.pendingWake = undefined\n\n return Effect.yieldNow.pipe(Effect.andThen(loop(key, execution, false)))\n })\n )\n )\n\n const settle = (key: Key, execution: Execution<E, Reason>, exit: Exit.Exit<void, E>) => {\n if (execution.pendingWake !== undefined) start(key, false, execution.pendingWake)\n else executions.delete(key)\n\n return Deferred.succeed(execution.done, exit).pipe(Effect.asVoid)\n }\n\n const start = (key: Key, force: boolean, scope: Promotable) => {\n const execution: Execution<E, Reason> = {\n done: Deferred.makeUnsafe<Exit.Exit<void, E>>(),\n scope,\n stopping: false\n }\n\n executions.set(key, execution)\n execution.owner = fork(\n Effect.yieldNow.pipe(\n Effect.andThen(\n Effect.uninterruptible(Effect.suspend(() => options.started?.(key) ?? Effect.void))\n ),\n Effect.andThen(loop(key, execution, force)),\n Effect.onExit(exit =>\n Effect.suspend(() => {\n execution.owner = undefined\n\n return options.settled?.(key, exit, execution.interruptionReason) ?? Effect.void\n })\n ),\n Effect.onExit(exit => settle(key, execution, exit)),\n Effect.exit,\n Effect.asVoid\n )\n )\n\n return execution\n }\n\n const forkInterruptionRequest = (owner: Fiber.Fiber<void>): Fiber.Fiber<void> =>\n fork(Effect.yieldNow.pipe(Effect.andThen(Effect.sync(() => owner.interruptUnsafe()))))\n\n const interruptNow = (key: Key, reason?: Reason): Effect.Effect<boolean> =>\n Effect.suspend(() => {\n const execution = executions.get(key)\n\n if (execution === undefined || execution.stopping) return Effect.succeed(false)\n\n if (execution.owner === undefined) {\n execution.pendingWake = undefined\n\n return Effect.succeed(false)\n }\n\n const owner = execution.owner\n execution.stopping = true\n execution.pendingWake = undefined\n execution.interruptionReason = reason\n // Capture the exact old owner and fork the request in this same lazy\n // transition so cancellation cannot leave stopping=true with no request.\n // Initial yield breaks owner -> resumed caller -> owner reentrancy.\n // Join the request fiber only; interruptUnsafe may run interruptible\n // finalizers inline until they suspend. Do not await owner settlement.\n const request = forkInterruptionRequest(owner)\n execution.request = request\n\n return Fiber.join(request).pipe(Effect.as(true))\n })\n\n const awaitIdle = (key: Key): Effect.Effect<void> =>\n Effect.suspend(() => {\n const execution = executions.get(key)\n\n if (execution === undefined) return Effect.void\n\n return awaitDone(execution.done).pipe(Effect.ignoreCause, Effect.andThen(awaitIdle(key)))\n })\n\n return {\n active: Effect.sync(() => new Set(executions.keys())),\n isActive: key => Effect.sync(() => executions.has(key)),\n run: key =>\n Effect.suspend(() => {\n const execution = executions.get(key)\n\n if (execution === undefined) return awaitDone(start(key, true, 'input').done)\n\n if (!execution.stopping) return awaitDone(execution.done)\n\n return awaitDone(execution.done).pipe(\n Effect.ignoreCause,\n Effect.andThen(\n Effect.suspend(() => {\n const next = executions.get(key)\n\n return next === undefined\n ? awaitDone(start(key, true, 'input').done)\n : awaitDone(next.done)\n })\n )\n )\n }),\n captureRun: key =>\n Effect.sync(() => {\n const execution = executions.get(key)\n\n if (execution === undefined) {\n const started = start(key, true, 'input')\n\n return { _tag: 'Started' as const, join: awaitDone(started.done) }\n }\n\n if (!execution.stopping) {\n return { _tag: 'Joined' as const, join: awaitDone(execution.done) }\n }\n\n return {\n _tag: 'Stopping' as const,\n awaitSettlement: awaitDone(execution.done).pipe(Effect.ignoreCause)\n }\n }),\n wake: (key, scope = 'input') =>\n Effect.sync(() => {\n const execution = executions.get(key)\n\n if (execution !== undefined) {\n execution.pendingWake = widerScope(execution.pendingWake, scope)\n\n return\n }\n\n start(key, false, scope)\n }),\n interrupt: (key, reason, options) =>\n Effect.suspend(() => {\n const execution = executions.get(key)\n\n return interruptNow(key, reason).pipe(\n Effect.tap(() =>\n options?.awaitSettlement === true && execution !== undefined\n ? awaitDone(execution.done).pipe(Effect.ignoreCause)\n : Effect.void\n )\n )\n }),\n terminalStop: (key, reason) =>\n Effect.suspend((): Effect.Effect<StopReceipt> => {\n const execution = executions.get(key)\n\n if (execution === undefined) return Effect.succeed(stopReceipt.Idle())\n execution.pendingWake = undefined\n\n if (execution.owner === undefined) {\n execution.stopping = true\n\n return Effect.succeed(stopReceipt.Settling())\n }\n\n execution.interruptionReason = reason\n\n if (execution.stopping) {\n const request = execution.request\n\n return request === undefined\n ? Effect.succeed(stopReceipt.LiveStopping())\n : Fiber.join(request).pipe(Effect.as(stopReceipt.LiveStopping()))\n }\n\n const owner = execution.owner\n execution.stopping = true\n const request = forkInterruptionRequest(owner)\n execution.request = request\n\n return Fiber.join(request).pipe(Effect.as(stopReceipt.Interrupted()))\n }),\n awaitIdle\n }\n })\n\n/** Owning coordinator layer, with per-acquisition claim receipts and settlement policy. */\nexport class RunCoordinator extends Context.Service<\n RunCoordinator,\n Coordinator<string, never, InterruptReason>\n>()('@yolk-sdk/harness/RunCoordinator') {\n static layer = (options?: {\n readonly drain?: (runId: string, force: boolean, scope: Promotable) => Effect.Effect<void>\n }): Layer.Layer<RunCoordinator, never, RunStore> =>\n Layer.effect(\n this,\n Effect.gen(function* () {\n const store = yield* RunStore\n const drain = options?.drain ?? ((_runId, _force, _scope) => Effect.void)\n const acquired = new Set<string>()\n\n return yield* makeCoordinator<string, never, InterruptReason>({\n drain,\n started: runId =>\n store.claim(runId).pipe(\n Effect.tap(() =>\n Effect.sync(() => {\n acquired.add(runId)\n })\n )\n ),\n settled: (runId, exit, reason) =>\n Effect.suspend(() => {\n const owned = acquired.delete(runId)\n\n if (\n owned &&\n (reason === 'user' || (reason === undefined && !Exit.hasInterrupts(exit)))\n ) {\n return store.release(runId)\n }\n\n // Acquisition receipt guards automatic failed-start settlement only.\n // Explicit user-terminal authority still releases a leftover claim\n // after this owner has actually settled, matching Idle/Settling stop.\n if (reason === 'user' && !owned) {\n return store\n .isClaimed(runId)\n .pipe(Effect.flatMap(claimed => (claimed ? store.release(runId) : Effect.void)))\n }\n\n return Effect.void\n }).pipe(\n Effect.exit,\n Effect.flatMap(settledExit => {\n if (Exit.isSuccess(settledExit)) return Effect.void\n\n return Effect.failCause(\n Exit.isFailure(exit)\n ? Cause.combine(exit.cause, settledExit.cause)\n : settledExit.cause\n )\n })\n )\n })\n })\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,MAAM,aAAgB,SACpB,SAAS,MAAM,IAAI,EAAE,KAAK,OAAO,SAAQ,SAAQ,IAAI,CAAC;AAiExD,MAAM,cAAc,SAAiC,SACnD,YAAY,WAAW,SAAS,UAAU,UAAU;AAEtD,MAAa,mBAA2C,YAKtD,OAAO,IAAI,aAAa;CACtB,MAAM,6BAAa,IAAI,IAA+B;CACtD,MAAM,OAAO,OAAO,SAAS,YAAgC;CAE7D,MAAM,QACJ,KACA,WACA,UAEA,OAAO,cAAc;EACnB,IAAI,UAAU,UAAU,OAAO,OAAO;EAEtC,OAAO,QAAQ,MAAM,KAAK,OAAO,UAAU,KAAK;CAClD,CAAC,EAAE,KACD,OAAO,QACL,OAAO,cAAc;EACnB,IAAI,UAAU,YAAY,UAAU,gBAAgB,KAAA,GAAW,OAAO,OAAO;EAC7E,UAAU,QAAQ,UAAU;EAC5B,UAAU,cAAc,KAAA;EAExB,OAAO,OAAO,SAAS,KAAK,OAAO,QAAQ,KAAK,KAAK,WAAW,KAAK,CAAC,CAAC;CACzE,CAAC,CACH,CACF;CAEF,MAAM,UAAU,KAAU,WAAiC,SAA6B;EACtF,IAAI,UAAU,gBAAgB,KAAA,GAAW,MAAM,KAAK,OAAO,UAAU,WAAW;OAC3E,WAAW,OAAO,GAAG;EAE1B,OAAO,SAAS,QAAQ,UAAU,MAAM,IAAI,EAAE,KAAK,OAAO,MAAM;CAClE;CAEA,MAAM,SAAS,KAAU,OAAgB,UAAsB;EAC7D,MAAM,YAAkC;GACtC,MAAM,SAAS,WAA+B;GAC9C;GACA,UAAU;EACZ;EAEA,WAAW,IAAI,KAAK,SAAS;EAC7B,UAAU,QAAQ,KAChB,OAAO,SAAS,KACd,OAAO,QACL,OAAO,gBAAgB,OAAO,cAAc,QAAQ,UAAU,GAAG,KAAK,OAAO,IAAI,CAAC,CACpF,GACA,OAAO,QAAQ,KAAK,KAAK,WAAW,KAAK,CAAC,GAC1C,OAAO,QAAO,SACZ,OAAO,cAAc;GACnB,UAAU,QAAQ,KAAA;GAElB,OAAO,QAAQ,UAAU,KAAK,MAAM,UAAU,kBAAkB,KAAK,OAAO;EAC9E,CAAC,CACH,GACA,OAAO,QAAO,SAAQ,OAAO,KAAK,WAAW,IAAI,CAAC,GAClD,OAAO,MACP,OAAO,MACT,CACF;EAEA,OAAO;CACT;CAEA,MAAM,2BAA2B,UAC/B,KAAK,OAAO,SAAS,KAAK,OAAO,QAAQ,OAAO,WAAW,MAAM,gBAAgB,CAAC,CAAC,CAAC,CAAC;CAEvF,MAAM,gBAAgB,KAAU,WAC9B,OAAO,cAAc;EACnB,MAAM,YAAY,WAAW,IAAI,GAAG;EAEpC,IAAI,cAAc,KAAA,KAAa,UAAU,UAAU,OAAO,OAAO,QAAQ,KAAK;EAE9E,IAAI,UAAU,UAAU,KAAA,GAAW;GACjC,UAAU,cAAc,KAAA;GAExB,OAAO,OAAO,QAAQ,KAAK;EAC7B;EAEA,MAAM,QAAQ,UAAU;EACxB,UAAU,WAAW;EACrB,UAAU,cAAc,KAAA;EACxB,UAAU,qBAAqB;EAM/B,MAAM,UAAU,wBAAwB,KAAK;EAC7C,UAAU,UAAU;EAEpB,OAAO,MAAM,KAAK,OAAO,EAAE,KAAK,OAAO,GAAG,IAAI,CAAC;CACjD,CAAC;CAEH,MAAM,aAAa,QACjB,OAAO,cAAc;EACnB,MAAM,YAAY,WAAW,IAAI,GAAG;EAEpC,IAAI,cAAc,KAAA,GAAW,OAAO,OAAO;EAE3C,OAAO,UAAU,UAAU,IAAI,EAAE,KAAK,OAAO,aAAa,OAAO,QAAQ,UAAU,GAAG,CAAC,CAAC;CAC1F,CAAC;CAEH,OAAO;EACL,QAAQ,OAAO,WAAW,IAAI,IAAI,WAAW,KAAK,CAAC,CAAC;EACpD,WAAU,QAAO,OAAO,WAAW,WAAW,IAAI,GAAG,CAAC;EACtD,MAAK,QACH,OAAO,cAAc;GACnB,MAAM,YAAY,WAAW,IAAI,GAAG;GAEpC,IAAI,cAAc,KAAA,GAAW,OAAO,UAAU,MAAM,KAAK,MAAM,OAAO,EAAE,IAAI;GAE5E,IAAI,CAAC,UAAU,UAAU,OAAO,UAAU,UAAU,IAAI;GAExD,OAAO,UAAU,UAAU,IAAI,EAAE,KAC/B,OAAO,aACP,OAAO,QACL,OAAO,cAAc;IACnB,MAAM,OAAO,WAAW,IAAI,GAAG;IAE/B,OAAO,SAAS,KAAA,IACZ,UAAU,MAAM,KAAK,MAAM,OAAO,EAAE,IAAI,IACxC,UAAU,KAAK,IAAI;GACzB,CAAC,CACH,CACF;EACF,CAAC;EACH,aAAY,QACV,OAAO,WAAW;GAChB,MAAM,YAAY,WAAW,IAAI,GAAG;GAEpC,IAAI,cAAc,KAAA,GAGhB,OAAO;IAAE,MAAM;IAAoB,MAAM,UAFzB,MAAM,KAAK,MAAM,OAEwB,EAAE,IAAI;GAAE;GAGnE,IAAI,CAAC,UAAU,UACb,OAAO;IAAE,MAAM;IAAmB,MAAM,UAAU,UAAU,IAAI;GAAE;GAGpE,OAAO;IACL,MAAM;IACN,iBAAiB,UAAU,UAAU,IAAI,EAAE,KAAK,OAAO,WAAW;GACpE;EACF,CAAC;EACH,OAAO,KAAK,QAAQ,YAClB,OAAO,WAAW;GAChB,MAAM,YAAY,WAAW,IAAI,GAAG;GAEpC,IAAI,cAAc,KAAA,GAAW;IAC3B,UAAU,cAAc,WAAW,UAAU,aAAa,KAAK;IAE/D;GACF;GAEA,MAAM,KAAK,OAAO,KAAK;EACzB,CAAC;EACH,YAAY,KAAK,QAAQ,YACvB,OAAO,cAAc;GACnB,MAAM,YAAY,WAAW,IAAI,GAAG;GAEpC,OAAO,aAAa,KAAK,MAAM,EAAE,KAC/B,OAAO,UACL,SAAS,oBAAoB,QAAQ,cAAc,KAAA,IAC/C,UAAU,UAAU,IAAI,EAAE,KAAK,OAAO,WAAW,IACjD,OAAO,IACb,CACF;EACF,CAAC;EACH,eAAe,KAAK,WAClB,OAAO,cAA0C;GAC/C,MAAM,YAAY,WAAW,IAAI,GAAG;GAEpC,IAAI,cAAc,KAAA,GAAW,OAAO,OAAO,QAAQA,YAAY,KAAK,CAAC;GACrE,UAAU,cAAc,KAAA;GAExB,IAAI,UAAU,UAAU,KAAA,GAAW;IACjC,UAAU,WAAW;IAErB,OAAO,OAAO,QAAQA,YAAY,SAAS,CAAC;GAC9C;GAEA,UAAU,qBAAqB;GAE/B,IAAI,UAAU,UAAU;IACtB,MAAM,UAAU,UAAU;IAE1B,OAAO,YAAY,KAAA,IACf,OAAO,QAAQA,YAAY,aAAa,CAAC,IACzC,MAAM,KAAK,OAAO,EAAE,KAAK,OAAO,GAAGA,YAAY,aAAa,CAAC,CAAC;GACpE;GAEA,MAAM,QAAQ,UAAU;GACxB,UAAU,WAAW;GACrB,MAAM,UAAU,wBAAwB,KAAK;GAC7C,UAAU,UAAU;GAEpB,OAAO,MAAM,KAAK,OAAO,EAAE,KAAK,OAAO,GAAGA,YAAY,YAAY,CAAC,CAAC;EACtE,CAAC;EACH;CACF;AACF,CAAC;;AAGH,IAAa,iBAAb,cAAoC,QAAQ,QAG1C,EAAE,kCAAkC,EAAE;CACtC,OAAO,SAAS,YAGd,MAAM,OACJ,MACA,OAAO,IAAI,aAAa;EACtB,MAAM,QAAQ,OAAO;EACrB,MAAM,QAAQ,SAAS,WAAW,QAAQ,QAAQ,WAAW,OAAO;EACpE,MAAM,2BAAW,IAAI,IAAY;EAEjC,OAAO,OAAO,gBAAgD;GAC5D;GACA,UAAS,UACP,MAAM,MAAM,KAAK,EAAE,KACjB,OAAO,UACL,OAAO,WAAW;IAChB,SAAS,IAAI,KAAK;GACpB,CAAC,CACH,CACF;GACF,UAAU,OAAO,MAAM,WACrB,OAAO,cAAc;IACnB,MAAM,QAAQ,SAAS,OAAO,KAAK;IAEnC,IACE,UACC,WAAW,UAAW,WAAW,KAAA,KAAa,CAAC,KAAK,cAAc,IAAI,IAEvE,OAAO,MAAM,QAAQ,KAAK;IAM5B,IAAI,WAAW,UAAU,CAAC,OACxB,OAAO,MACJ,UAAU,KAAK,EACf,KAAK,OAAO,SAAQ,YAAY,UAAU,MAAM,QAAQ,KAAK,IAAI,OAAO,IAAK,CAAC;IAGnF,OAAO,OAAO;GAChB,CAAC,EAAE,KACD,OAAO,MACP,OAAO,SAAQ,gBAAe;IAC5B,IAAI,KAAK,UAAU,WAAW,GAAG,OAAO,OAAO;IAE/C,OAAO,OAAO,UACZ,KAAK,UAAU,IAAI,IACf,MAAM,QAAQ,KAAK,OAAO,YAAY,KAAK,IAC3C,YAAY,KAClB;GACF,CAAC,CACH;EACJ,CAAC;CACH,CAAC,CACH;AACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-object.d.mts","names":[],"sources":["../../src/driver/durable-object.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"durable-object.d.mts","names":[],"sources":["../../src/driver/durable-object.ts"],"mappings":";;;;;;KAQK,uBAAA;EAAA,SACM,IAAA,EAAM,MAAA,CAAO,MAAA,CAAO,uBAAA;EAAA,SACpB,IAAA,GAAO,QAAA,EAAU,uBAAA,KAA4B,MAAA,CAAO,MAAA;EAAA,SACpD,KAAA,GAAQ,KAAA;AAAA;AAAA,iBAGH,4BAAA,CACd,OAAA,EAAS,uBAAA;EAAA,SAAqC,iBAAA;AAAA,IAC7C,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,QAAA,GAAW,KAAA;AAAA,iBACnB,4BAAA,CACd,OAAA,EAAS,uBAAA;EAAA,SAAqC,iBAAA;AAAA,IAC7C,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,QAAA,GAAW,KAAA,EAAO,wBAAA"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { RunStore } from "../store.mjs";
|
|
2
|
+
import { Inbox } from "../inbox.mjs";
|
|
3
|
+
import { Driver } from "../driver.mjs";
|
|
4
4
|
import { Layer } from "effect";
|
|
5
5
|
//#region src/driver/durable-object.ts
|
|
6
6
|
function makeDurableObjectDriverLayer(options) {
|
|
7
|
-
return
|
|
7
|
+
return Driver.coordinatedLayer(options).pipe(Layer.provideMerge(RunStore.snapshotLayer(options)), Layer.provideMerge(Inbox.layer()));
|
|
8
8
|
}
|
|
9
9
|
//#endregion
|
|
10
10
|
export { makeDurableObjectDriverLayer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-object.mjs","names":[],"sources":["../../src/driver/durable-object.ts"],"sourcesContent":["import { Layer } from 'effect'\nimport type { Effect } from 'effect'\nimport {
|
|
1
|
+
{"version":3,"file":"durable-object.mjs","names":[],"sources":["../../src/driver/durable-object.ts"],"sourcesContent":["import { Layer } from 'effect'\nimport type { Effect } from 'effect'\nimport { Driver, type Drain, type InvalidMaxResumeAttempts } from '../driver.ts'\nimport { Inbox } from '../inbox.ts'\nimport { RunStore, type DurableRunStoreSnapshot } from '../store.ts'\n\nexport type { DurableRunStoreSnapshot }\n\ntype DurableObjectDriverBase = {\n readonly load: Effect.Effect<DurableRunStoreSnapshot | undefined>\n readonly save: (snapshot: DurableRunStoreSnapshot) => Effect.Effect<void>\n readonly drain?: Drain\n}\n\nexport function makeDurableObjectDriverLayer(\n options: DurableObjectDriverBase & { readonly maxResumeAttempts?: undefined }\n): Layer.Layer<Driver | RunStore | Inbox>\nexport function makeDurableObjectDriverLayer(\n options: DurableObjectDriverBase & { readonly maxResumeAttempts?: number }\n): Layer.Layer<Driver | RunStore | Inbox, InvalidMaxResumeAttempts>\nexport function makeDurableObjectDriverLayer(\n options: DurableObjectDriverBase & { readonly maxResumeAttempts?: number }\n) {\n return Driver.coordinatedLayer(options).pipe(\n Layer.provideMerge(RunStore.snapshotLayer(options)),\n Layer.provideMerge(Inbox.layer())\n )\n}\n"],"mappings":";;;;;AAoBA,SAAgB,6BACd,SACA;CACA,OAAO,OAAO,iBAAiB,OAAO,EAAE,KACtC,MAAM,aAAa,SAAS,cAAc,OAAO,CAAC,GAClD,MAAM,aAAa,MAAM,MAAM,CAAC,CAClC;AACF"}
|
package/dist/driver/memory.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.mts","names":[],"sources":["../../src/driver/memory.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"memory.d.mts","names":[],"sources":["../../src/driver/memory.ts"],"mappings":";;;;;;iBAUgB,uBAAA,CAAA,GAA2B,KAAA,CAAM,KAAA,CAAM,MAAA,SAAe,QAAA,GAAW,KAAA;AAAA,iBACjE,uBAAA,CAAwB,OAAA;EAAA,SAC7B,KAAA,GAAQ,KAAA;EAAA,SACR,iBAAA;AAAA,IACP,KAAA,CAAM,KAAA,CAAM,MAAA,SAAe,QAAA,GAAW,KAAA;AAAA,iBAC1B,uBAAA,CACd,OAAA,GAAU,kBAAA,GACT,KAAA,CAAM,KAAA,CAAM,MAAA,EAAQ,wBAAA,EAA0B,QAAA,GAAW,KAAA;AAAA,iBAK5C,wBAAA,CAAA,GAA4B,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,QAAA,GAAW,KAAA;AAAA,iBAC5D,wBAAA,CAAyB,OAAA;EAAA,SAC9B,KAAA,GAAQ,KAAA;EAAA,SACR,iBAAA;AAAA,IACP,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,QAAA,GAAW,KAAA;AAAA,iBACpB,wBAAA,CACd,OAAA,GAAU,kBAAA,GACT,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,QAAA,GAAW,KAAA,EAAO,wBAAA"}
|
package/dist/driver/memory.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { RunStore } from "../store.mjs";
|
|
2
|
+
import { Inbox } from "../inbox.mjs";
|
|
3
|
+
import { Driver } from "../driver.mjs";
|
|
4
4
|
import { Layer } from "effect";
|
|
5
5
|
//#region src/driver/memory.ts
|
|
6
6
|
function makeInMemoryDriverLayer(options) {
|
|
7
|
-
return options === void 0 ?
|
|
7
|
+
return options === void 0 ? Driver.coordinatedLayer() : Driver.coordinatedLayer(options);
|
|
8
8
|
}
|
|
9
9
|
function makeInMemoryHarnessLayer(options) {
|
|
10
|
-
return (options === void 0 ?
|
|
10
|
+
return (options === void 0 ? Driver.coordinatedLayer() : Driver.coordinatedLayer(options)).pipe(Layer.provideMerge(RunStore.inMemoryLayer()), Layer.provideMerge(Inbox.layer()));
|
|
11
11
|
}
|
|
12
12
|
//#endregion
|
|
13
13
|
export { makeInMemoryDriverLayer, makeInMemoryHarnessLayer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.mjs","names":[],"sources":["../../src/driver/memory.ts"],"sourcesContent":["import { Layer } from 'effect'\nimport {\n
|
|
1
|
+
{"version":3,"file":"memory.mjs","names":[],"sources":["../../src/driver/memory.ts"],"sourcesContent":["import { Layer } from 'effect'\nimport {\n Driver,\n type Drain,\n type DriverLayerOptions,\n type InvalidMaxResumeAttempts\n} from '../driver.ts'\nimport { Inbox } from '../inbox.ts'\nimport { RunStore } from '../store.ts'\n\nexport function makeInMemoryDriverLayer(): Layer.Layer<Driver, never, RunStore | Inbox>\nexport function makeInMemoryDriverLayer(options?: {\n readonly drain?: Drain\n readonly maxResumeAttempts?: undefined\n}): Layer.Layer<Driver, never, RunStore | Inbox>\nexport function makeInMemoryDriverLayer(\n options?: DriverLayerOptions\n): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox>\nexport function makeInMemoryDriverLayer(options?: DriverLayerOptions) {\n return options === undefined ? Driver.coordinatedLayer() : Driver.coordinatedLayer(options)\n}\n\nexport function makeInMemoryHarnessLayer(): Layer.Layer<Driver | RunStore | Inbox>\nexport function makeInMemoryHarnessLayer(options?: {\n readonly drain?: Drain\n readonly maxResumeAttempts?: undefined\n}): Layer.Layer<Driver | RunStore | Inbox>\nexport function makeInMemoryHarnessLayer(\n options?: DriverLayerOptions\n): Layer.Layer<Driver | RunStore | Inbox, InvalidMaxResumeAttempts>\nexport function makeInMemoryHarnessLayer(options?: DriverLayerOptions) {\n const driver =\n options === undefined ? Driver.coordinatedLayer() : Driver.coordinatedLayer(options)\n\n return driver.pipe(\n Layer.provideMerge(RunStore.inMemoryLayer()),\n Layer.provideMerge(Inbox.layer())\n )\n}\n"],"mappings":";;;;;AAkBA,SAAgB,wBAAwB,SAA8B;CACpE,OAAO,YAAY,KAAA,IAAY,OAAO,iBAAiB,IAAI,OAAO,iBAAiB,OAAO;AAC5F;AAUA,SAAgB,yBAAyB,SAA8B;CAIrE,QAFE,YAAY,KAAA,IAAY,OAAO,iBAAiB,IAAI,OAAO,iBAAiB,OAAO,GAEvE,KACZ,MAAM,aAAa,SAAS,cAAc,CAAC,GAC3C,MAAM,aAAa,MAAM,MAAM,CAAC,CAClC;AACF"}
|
package/dist/driver.d.mts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { Promotable } from "./coordinator.mjs";
|
|
2
|
-
import { HitlAdmission, HitlDecision, Inbox, InboxItem, ParkedResponse, PauseDecision } from "./inbox.mjs";
|
|
3
1
|
import { RunStore } from "./store.mjs";
|
|
4
|
-
import {
|
|
2
|
+
import { InterruptReason, Promotable, RunCoordinator } from "./coordinator.mjs";
|
|
3
|
+
import { HitlAdmission, HitlDecision, Inbox, InboxItem, ParkedResponse, PauseDecision } from "./inbox.mjs";
|
|
4
|
+
import { Context, Data, Effect, Layer } from "effect";
|
|
5
5
|
|
|
6
6
|
//#region src/driver.d.ts
|
|
7
|
-
type InterruptReason = 'user' | 'shutdown';
|
|
8
7
|
declare const defaultMaxResumeAttempts = 10;
|
|
9
|
-
declare const InvalidMaxResumeAttempts_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] }>) => Cause.YieldableError & {
|
|
8
|
+
declare const InvalidMaxResumeAttempts_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 & {
|
|
10
9
|
readonly _tag: "InvalidMaxResumeAttempts";
|
|
11
10
|
} & Readonly<A>;
|
|
12
11
|
declare class InvalidMaxResumeAttempts extends InvalidMaxResumeAttempts_base<{
|
|
@@ -32,7 +31,55 @@ type StopDecision = {
|
|
|
32
31
|
} | {
|
|
33
32
|
readonly _tag: 'Idle';
|
|
34
33
|
};
|
|
35
|
-
|
|
34
|
+
declare const StopDecision: {
|
|
35
|
+
readonly Interrupted: Data.TaggedEnum.ConstructorFrom<{
|
|
36
|
+
readonly _tag: "Interrupted";
|
|
37
|
+
}, "_tag">;
|
|
38
|
+
readonly ParkCleared: Data.TaggedEnum.ConstructorFrom<{
|
|
39
|
+
readonly _tag: "ParkCleared";
|
|
40
|
+
}, "_tag">;
|
|
41
|
+
readonly Idle: Data.TaggedEnum.ConstructorFrom<{
|
|
42
|
+
readonly _tag: "Idle";
|
|
43
|
+
}, "_tag">;
|
|
44
|
+
readonly $is: <Tag extends "Interrupted" | "ParkCleared" | "Idle">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
45
|
+
readonly _tag: "Interrupted";
|
|
46
|
+
}, {
|
|
47
|
+
readonly _tag: Tag;
|
|
48
|
+
}> | Extract<{
|
|
49
|
+
readonly _tag: "ParkCleared";
|
|
50
|
+
}, {
|
|
51
|
+
readonly _tag: Tag;
|
|
52
|
+
}> | Extract<{
|
|
53
|
+
readonly _tag: "Idle";
|
|
54
|
+
}, {
|
|
55
|
+
readonly _tag: Tag;
|
|
56
|
+
}>;
|
|
57
|
+
readonly $match: {
|
|
58
|
+
<Cases extends {
|
|
59
|
+
readonly Interrupted: (args: {
|
|
60
|
+
readonly _tag: "Interrupted";
|
|
61
|
+
}) => any;
|
|
62
|
+
readonly ParkCleared: (args: {
|
|
63
|
+
readonly _tag: "ParkCleared";
|
|
64
|
+
}) => any;
|
|
65
|
+
readonly Idle: (args: {
|
|
66
|
+
readonly _tag: "Idle";
|
|
67
|
+
}) => any;
|
|
68
|
+
}>(cases: Cases): (value: StopDecision) => import("effect/Unify").Unify<ReturnType<Cases["Interrupted" | "ParkCleared" | "Idle"]>>;
|
|
69
|
+
<Cases extends {
|
|
70
|
+
readonly Interrupted: (args: {
|
|
71
|
+
readonly _tag: "Interrupted";
|
|
72
|
+
}) => any;
|
|
73
|
+
readonly ParkCleared: (args: {
|
|
74
|
+
readonly _tag: "ParkCleared";
|
|
75
|
+
}) => any;
|
|
76
|
+
readonly Idle: (args: {
|
|
77
|
+
readonly _tag: "Idle";
|
|
78
|
+
}) => any;
|
|
79
|
+
}>(value: StopDecision, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Interrupted" | "ParkCleared" | "Idle"]>>;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
type DriverApi = {
|
|
36
83
|
readonly active: Effect.Effect<ReadonlySet<string>>;
|
|
37
84
|
readonly isActive: (runId: string) => Effect.Effect<boolean>;
|
|
38
85
|
readonly run: (runId: string) => Effect.Effect<void>;
|
|
@@ -48,8 +95,20 @@ type DriverShape = {
|
|
|
48
95
|
readonly resumeHitl: (runId: string, admission: HitlAdmission) => Effect.Effect<HitlDecision>;
|
|
49
96
|
readonly stop: (runId: string) => Effect.Effect<StopDecision>;
|
|
50
97
|
};
|
|
51
|
-
declare const Driver_base: Context.ServiceClass<Driver, "@yolk-sdk/harness/Driver",
|
|
52
|
-
declare class Driver extends Driver_base {
|
|
98
|
+
declare const Driver_base: Context.ServiceClass<Driver, "@yolk-sdk/harness/Driver", DriverApi>;
|
|
99
|
+
declare class Driver extends Driver_base {
|
|
100
|
+
static layer(): Layer.Layer<Driver, never, RunStore | Inbox | RunCoordinator>;
|
|
101
|
+
static layer(options?: {
|
|
102
|
+
readonly maxResumeAttempts?: undefined;
|
|
103
|
+
}): Layer.Layer<Driver, never, RunStore | Inbox | RunCoordinator>;
|
|
104
|
+
static layer(options?: Pick<DriverLayerOptions, 'maxResumeAttempts'>): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox | RunCoordinator>;
|
|
105
|
+
static coordinatedLayer(): Layer.Layer<Driver, never, RunStore | Inbox>;
|
|
106
|
+
static coordinatedLayer(options?: {
|
|
107
|
+
readonly drain?: Drain;
|
|
108
|
+
readonly maxResumeAttempts?: undefined;
|
|
109
|
+
}): Layer.Layer<Driver, never, RunStore | Inbox>;
|
|
110
|
+
static coordinatedLayer(options?: DriverLayerOptions): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox>;
|
|
111
|
+
}
|
|
53
112
|
declare const makeHarness: <DE, DR, SE, SR, IE, IR>(input: {
|
|
54
113
|
readonly driver: Layer.Layer<Driver, DE, DR>;
|
|
55
114
|
readonly store: Layer.Layer<RunStore, SE, SR>;
|
|
@@ -63,5 +122,5 @@ declare function makeDriverLayer(options?: {
|
|
|
63
122
|
}): Layer.Layer<Driver, never, RunStore | Inbox>;
|
|
64
123
|
declare function makeDriverLayer(options?: DriverLayerOptions): Layer.Layer<Driver, InvalidMaxResumeAttempts, RunStore | Inbox>;
|
|
65
124
|
//#endregion
|
|
66
|
-
export { Drain, DrainContext, Driver,
|
|
125
|
+
export { Drain, DrainContext, Driver, DriverApi, DriverLayerOptions, type InterruptReason, InvalidMaxResumeAttempts, ResumeSuspendedResult, StopDecision, admit, defaultMaxResumeAttempts, makeDriverLayer, makeHarness };
|
|
67
126
|
//# sourceMappingURL=driver.d.mts.map
|
package/dist/driver.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.d.mts","names":[],"sources":["../src/driver.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"driver.d.mts","names":[],"sources":["../src/driver.ts"],"mappings":"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"}
|