@yolk-sdk/harness 0.1.0-canary.100

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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +206 -0
  3. package/dist/coordinator.d.mts +72 -0
  4. package/dist/coordinator.d.mts.map +1 -0
  5. package/dist/coordinator.mjs +154 -0
  6. package/dist/coordinator.mjs.map +1 -0
  7. package/dist/driver/durable-object.d.mts +20 -0
  8. package/dist/driver/durable-object.d.mts.map +1 -0
  9. package/dist/driver/durable-object.mjs +12 -0
  10. package/dist/driver/durable-object.mjs.map +1 -0
  11. package/dist/driver/memory.d.mts +21 -0
  12. package/dist/driver/memory.d.mts.map +1 -0
  13. package/dist/driver/memory.mjs +15 -0
  14. package/dist/driver/memory.mjs.map +1 -0
  15. package/dist/driver.d.mts +126 -0
  16. package/dist/driver.d.mts.map +1 -0
  17. package/dist/driver.mjs +96 -0
  18. package/dist/driver.mjs.map +1 -0
  19. package/dist/inbox.d.mts +368 -0
  20. package/dist/inbox.d.mts.map +1 -0
  21. package/dist/inbox.mjs +235 -0
  22. package/dist/inbox.mjs.map +1 -0
  23. package/dist/index.d.mts +1 -0
  24. package/dist/index.mjs +1 -0
  25. package/dist/outcome-constructors-internal.d.mts +403 -0
  26. package/dist/outcome-constructors-internal.d.mts.map +1 -0
  27. package/dist/outcome-constructors-internal.mjs +11 -0
  28. package/dist/outcome-constructors-internal.mjs.map +1 -0
  29. package/dist/outcome.d.mts +361 -0
  30. package/dist/outcome.d.mts.map +1 -0
  31. package/dist/outcome.mjs +136 -0
  32. package/dist/outcome.mjs.map +1 -0
  33. package/dist/store.d.mts +39 -0
  34. package/dist/store.d.mts.map +1 -0
  35. package/dist/store.mjs +98 -0
  36. package/dist/store.mjs.map +1 -0
  37. package/package.json +90 -0
  38. package/src/coordinator.ts +355 -0
  39. package/src/driver/durable-object.ts +28 -0
  40. package/src/driver/memory.ts +39 -0
  41. package/src/driver.ts +270 -0
  42. package/src/inbox.ts +528 -0
  43. package/src/index.ts +2 -0
  44. package/src/outcome-constructors-internal.ts +18 -0
  45. package/src/outcome.ts +377 -0
  46. package/src/store.ts +161 -0
package/dist/inbox.mjs ADDED
@@ -0,0 +1,235 @@
1
+ import { Context, Data, Effect, Layer, Predicate, Ref, Semaphore } from "effect";
2
+ import * as Schema from "effect/Schema";
3
+ //#region src/inbox.ts
4
+ /** Nominal identity only. All strings stay admissible so stale/empty/foreign
5
+ * tokens retain the inbox's existing no-op decisions rather than parse failures. */
6
+ const DrainToken = Schema.String.pipe(Schema.brand("DrainToken"));
7
+ /** Nominal identity only; freshness and instance ownership are checked by Inbox. */
8
+ const ParkGeneration = Schema.String.pipe(Schema.brand("ParkGeneration"));
9
+ const HitlDecision = Data.taggedEnum();
10
+ const PauseDecision = Data.taggedEnum();
11
+ const RecoveryAttempt = Data.taggedEnum();
12
+ const RecoveryAdmission = Data.taggedEnum();
13
+ const DrainBegin = Data.taggedEnum();
14
+ const isPromotableAt = (item, scope) => {
15
+ if (scope === "steer") return item.delivery === "steer";
16
+ return item.delivery === "steer" || item.delivery === "input" || item.delivery === "queue";
17
+ };
18
+ const emptyControl = {
19
+ pending: void 0,
20
+ liveToken: void 0,
21
+ park: void 0,
22
+ leasedGeneration: void 0
23
+ };
24
+ const widerPending = (current, next) => current === "input" || next === "input" ? "input" : "steer";
25
+ const remainingPending = (pending, scope) => scope === "steer" && pending === "input" ? "input" : void 0;
26
+ const itemScope = (item) => item.delivery === "steer" ? "steer" : "input";
27
+ const parkComplete = (park) => park.requestIds.every((requestId) => park.responses.some((response) => response.requestId === requestId));
28
+ const parkBlocked = (park) => park !== void 0 && !parkComplete(park);
29
+ const parkedState = (park) => ({
30
+ generation: park.generation,
31
+ requestIds: park.requestIds,
32
+ responses: park.responses,
33
+ ready: parkComplete(park)
34
+ });
35
+ const isPrunable = (control) => control.pending === void 0 && control.liveToken === void 0 && control.park === void 0 && control.leasedGeneration === void 0;
36
+ var Inbox = class Inbox extends Context.Service()("@yolk-sdk/harness/Inbox") {
37
+ /** Fresh queue, admission gate and HITL generations per layer acquisition. */
38
+ static layer = () => Layer.effect(this, Effect.gen(function* () {
39
+ const items = yield* Ref.make([]);
40
+ const controls = yield* Ref.make(/* @__PURE__ */ new Map());
41
+ const gate = yield* Semaphore.make(1);
42
+ let generationSeq = 0;
43
+ let drainSeq = 0;
44
+ const withGate = (body) => gate.withPermits(1)(body);
45
+ const getControl = (runId) => Ref.get(controls).pipe(Effect.map((current) => current.get(runId) ?? emptyControl));
46
+ const writeControl = (runId, next) => Ref.update(controls, (current) => {
47
+ const copy = new Map(current);
48
+ if (isPrunable(next)) copy.delete(runId);
49
+ else copy.set(runId, next);
50
+ return copy;
51
+ });
52
+ const dropQueued = (runId) => Ref.update(items, (current) => current.filter((item) => item.runId !== runId));
53
+ const acceptHitlPure = (control, admission) => {
54
+ const park = control.park;
55
+ if (park === void 0) return HitlDecision.NotParked();
56
+ if (park.generation !== admission.generation) return HitlDecision.Stale();
57
+ if (!park.requestIds.includes(admission.requestId)) return HitlDecision.UnknownRequest();
58
+ if (park.responses.some((response) => response.itemId === admission.itemId || response.requestId === admission.requestId)) return HitlDecision.Duplicate();
59
+ if (park.readyWoken) return HitlDecision.Duplicate();
60
+ const responses = [...park.responses, {
61
+ itemId: admission.itemId,
62
+ requestId: admission.requestId
63
+ }];
64
+ return parkComplete({
65
+ ...park,
66
+ responses
67
+ }) ? HitlDecision.Ready() : HitlDecision.Accepted();
68
+ };
69
+ return Inbox.of({
70
+ enqueue: (item) => Ref.update(items, (current) => [...current, item]),
71
+ takePromotable: (runId, scope, drainToken) => withGate(Effect.uninterruptible(Effect.gen(function* () {
72
+ const control = yield* getControl(runId);
73
+ if (control.liveToken === void 0 || control.liveToken !== drainToken) return;
74
+ return yield* Ref.modify(items, (current) => {
75
+ const index = current.findIndex((item) => item.runId === runId && isPromotableAt(item, scope));
76
+ if (index < 0) return [void 0, current];
77
+ return [current[index], current.filter((_, itemIndex) => itemIndex !== index)];
78
+ });
79
+ }))),
80
+ pending: (runId) => Ref.get(items).pipe(Effect.map((current) => current.filter((item) => item.runId === runId))),
81
+ parked: (runId) => getControl(runId).pipe(Effect.map((control) => control.park === void 0 ? void 0 : parkedState(control.park))),
82
+ park: (runId, requestIds, drainToken) => withGate(Effect.uninterruptible(Effect.gen(function* () {
83
+ const control = yield* getControl(runId);
84
+ if (control.liveToken !== drainToken) return PauseDecision.Stale();
85
+ generationSeq += 1;
86
+ const generation = ParkGeneration.make(String(generationSeq));
87
+ yield* writeControl(runId, {
88
+ pending: control.pending,
89
+ liveToken: control.liveToken,
90
+ leasedGeneration: control.leasedGeneration,
91
+ park: {
92
+ generation,
93
+ requestIds: [...requestIds],
94
+ responses: [],
95
+ readyWoken: false
96
+ }
97
+ });
98
+ return PauseDecision.Parked({ generation });
99
+ }))),
100
+ acceptHitl: (runId, admission, onReady) => withGate(Effect.uninterruptible(Effect.gen(function* () {
101
+ const control = yield* getControl(runId);
102
+ const decision = acceptHitlPure(control, admission);
103
+ if (!Predicate.isTagged(decision, "Accepted") && !Predicate.isTagged(decision, "Ready")) return decision;
104
+ const park = control.park;
105
+ if (park === void 0) return HitlDecision.NotParked();
106
+ const nextPark = {
107
+ ...park,
108
+ responses: [...park.responses, {
109
+ itemId: admission.itemId,
110
+ requestId: admission.requestId
111
+ }],
112
+ readyWoken: Predicate.isTagged(decision, "Ready")
113
+ };
114
+ yield* writeControl(runId, {
115
+ pending: Predicate.isTagged(decision, "Ready") ? widerPending(control.pending, "input") : control.pending,
116
+ liveToken: control.liveToken,
117
+ leasedGeneration: control.leasedGeneration,
118
+ park: nextPark
119
+ });
120
+ if (Predicate.isTagged(decision, "Ready")) yield* onReady;
121
+ return decision;
122
+ }))),
123
+ clearPark: (runId, generation) => withGate(Effect.uninterruptible(Effect.gen(function* () {
124
+ const control = yield* getControl(runId);
125
+ if (control.park === void 0 || control.park.generation !== generation) return false;
126
+ yield* writeControl(runId, {
127
+ pending: control.pending,
128
+ liveToken: control.liveToken,
129
+ leasedGeneration: control.leasedGeneration,
130
+ park: void 0
131
+ });
132
+ return true;
133
+ }))),
134
+ beginDrain: (runId, scope) => withGate(Effect.uninterruptible(Effect.gen(function* () {
135
+ const control = yield* getControl(runId);
136
+ const pending = control.pending;
137
+ if (parkBlocked(control.park) || pending === void 0) return DrainBegin.Skip();
138
+ drainSeq += 1;
139
+ const drainToken = DrainToken.make(`d${drainSeq}`);
140
+ const park = control.park;
141
+ const ready = park !== void 0 && parkComplete(park) ? park : void 0;
142
+ yield* writeControl(runId, {
143
+ pending: remainingPending(pending, scope),
144
+ liveToken: drainToken,
145
+ park,
146
+ leasedGeneration: ready?.generation
147
+ });
148
+ return DrainBegin.Run({
149
+ drainToken,
150
+ readyResponses: ready === void 0 ? [] : ready.responses
151
+ });
152
+ }))),
153
+ endDrain: (runId, drainToken, acknowledged) => withGate(Effect.uninterruptible(Effect.gen(function* () {
154
+ const control = yield* getControl(runId);
155
+ if (control.liveToken !== drainToken) return;
156
+ const leased = control.leasedGeneration;
157
+ const park = control.park;
158
+ const clearPark = acknowledged && leased !== void 0 && park !== void 0 && park.generation === leased;
159
+ yield* writeControl(runId, {
160
+ pending: control.pending,
161
+ liveToken: void 0,
162
+ leasedGeneration: void 0,
163
+ park: clearPark ? void 0 : park
164
+ });
165
+ }))),
166
+ invalidate: (runId, interrupt, releaseIdleClaim) => withGate(Effect.uninterruptible(Effect.gen(function* () {
167
+ const hadPark = (yield* getControl(runId)).park !== void 0;
168
+ yield* dropQueued(runId);
169
+ yield* writeControl(runId, emptyControl);
170
+ const interrupted = yield* interrupt;
171
+ if (!interrupted) yield* releaseIdleClaim;
172
+ return {
173
+ hadPark,
174
+ interrupted
175
+ };
176
+ }))),
177
+ enqueueAndWake: (item, wake) => withGate(Effect.uninterruptible(Effect.gen(function* () {
178
+ yield* Ref.update(items, (current) => [...current, item]);
179
+ const control = yield* getControl(item.runId);
180
+ if (parkBlocked(control.park)) return;
181
+ yield* writeControl(item.runId, {
182
+ pending: widerPending(control.pending, itemScope(item)),
183
+ liveToken: control.liveToken,
184
+ leasedGeneration: control.leasedGeneration,
185
+ park: control.park
186
+ });
187
+ yield* wake;
188
+ }))),
189
+ wakeIfUnblocked: (runId, scope, wake) => withGate(Effect.uninterruptible(Effect.gen(function* () {
190
+ const control = yield* getControl(runId);
191
+ if (parkBlocked(control.park)) return false;
192
+ yield* writeControl(runId, {
193
+ pending: widerPending(control.pending, scope),
194
+ liveToken: control.liveToken,
195
+ leasedGeneration: control.leasedGeneration,
196
+ park: control.park
197
+ });
198
+ yield* wake;
199
+ return true;
200
+ }))),
201
+ startIfUnblocked: (runId, start) => withGate(Effect.uninterruptible(Effect.gen(function* () {
202
+ const control = yield* getControl(runId);
203
+ if (parkBlocked(control.park)) return void 0;
204
+ const ticket = yield* start;
205
+ if (Predicate.isTagged(ticket, "Started")) yield* writeControl(runId, {
206
+ pending: widerPending(control.pending, "input"),
207
+ liveToken: control.liveToken,
208
+ leasedGeneration: control.leasedGeneration,
209
+ park: control.park
210
+ });
211
+ return ticket;
212
+ }))),
213
+ admitRecovery: (runId, attempt, wake) => Effect.uninterruptibleMask((restore) => restore(gate.take(1)).pipe(Effect.flatMap(() => Effect.gen(function* () {
214
+ const control = yield* getControl(runId);
215
+ if (parkBlocked(control.park)) return RecoveryAdmission.Skip();
216
+ const decision = yield* attempt;
217
+ if (!RecoveryAttempt.$is("Resume")(decision)) return decision;
218
+ yield* writeControl(runId, {
219
+ pending: widerPending(control.pending, "input"),
220
+ liveToken: control.liveToken,
221
+ leasedGeneration: control.leasedGeneration,
222
+ park: control.park
223
+ });
224
+ yield* wake;
225
+ return RecoveryAdmission.Resumed();
226
+ }).pipe(Effect.ensuring(gate.release(1))))))
227
+ });
228
+ }));
229
+ };
230
+ /** Backward-compatible delegation to the owning inbox layer. */
231
+ const makeInMemoryInboxLayer = () => Inbox.layer();
232
+ //#endregion
233
+ export { DrainBegin, DrainToken, HitlDecision, Inbox, ParkGeneration, PauseDecision, RecoveryAdmission, RecoveryAttempt, makeInMemoryInboxLayer };
234
+
235
+ //# sourceMappingURL=inbox.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.mjs","names":[],"sources":["../src/inbox.ts"],"sourcesContent":["import { Context, Data, Effect, Layer, Predicate, Ref, Semaphore } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport type { CapturedRun, Promotable } from './coordinator.ts'\n\n/** Nominal identity only. All strings stay admissible so stale/empty/foreign\n * tokens retain the inbox's existing no-op decisions rather than parse failures. */\nexport const DrainToken = Schema.String.pipe(Schema.brand('DrainToken'))\n\nexport type DrainToken = typeof DrainToken.Type\n\n/** Nominal identity only; freshness and instance ownership are checked by Inbox. */\nexport const ParkGeneration = Schema.String.pipe(Schema.brand('ParkGeneration'))\n\nexport type ParkGeneration = typeof ParkGeneration.Type\n\nexport type InboxKind = 'input' | 'hitl'\n\nexport type InboxItem = {\n readonly id: string\n readonly runId: string\n readonly delivery: Promotable | 'queue'\n readonly kind: InboxKind\n}\n\nexport type ParkedResponse = {\n readonly itemId: string\n readonly requestId: string\n}\n\nexport type ParkedState = {\n readonly generation: ParkGeneration\n readonly requestIds: ReadonlyArray<string>\n readonly responses: ReadonlyArray<ParkedResponse>\n readonly ready: boolean\n}\n\nexport type HitlAdmission = {\n readonly itemId: string\n readonly requestId: string\n readonly generation: ParkGeneration\n}\n\nexport type HitlDecision =\n | { readonly _tag: 'Accepted' }\n | { readonly _tag: 'Ready' }\n | { readonly _tag: 'Duplicate' }\n | { readonly _tag: 'Stale' }\n | { readonly _tag: 'UnknownRequest' }\n | { readonly _tag: 'NotParked' }\n\nexport type PauseDecision =\n | { readonly _tag: 'Parked'; readonly generation: ParkGeneration }\n | { readonly _tag: 'Stale' }\n\nexport type RecoveryAttempt =\n | { readonly _tag: 'Skip' }\n | { readonly _tag: 'Exhausted' }\n | { readonly _tag: 'Resume' }\n\nexport type RecoveryAdmission =\n | { readonly _tag: 'Skip' }\n | { readonly _tag: 'Exhausted' }\n | { readonly _tag: 'Resumed' }\n\nexport type DrainBegin =\n | { readonly _tag: 'Skip' }\n | {\n readonly _tag: 'Run'\n readonly drainToken: DrainToken\n readonly readyResponses: ReadonlyArray<ParkedResponse>\n }\n\nexport const HitlDecision = Data.taggedEnum<HitlDecision>()\n\nexport const PauseDecision = Data.taggedEnum<PauseDecision>()\n\nexport const RecoveryAttempt = Data.taggedEnum<RecoveryAttempt>()\n\nexport const RecoveryAdmission = Data.taggedEnum<RecoveryAdmission>()\n\nexport const DrainBegin = Data.taggedEnum<DrainBegin>()\n\nexport type InboxApi = {\n readonly enqueue: (item: InboxItem) => Effect.Effect<void>\n readonly takePromotable: (\n runId: string,\n scope: Promotable,\n drainToken: DrainToken\n ) => Effect.Effect<InboxItem | undefined>\n readonly pending: (runId: string) => Effect.Effect<ReadonlyArray<InboxItem>>\n readonly parked: (runId: string) => Effect.Effect<ParkedState | undefined>\n readonly park: (\n runId: string,\n requestIds: ReadonlyArray<string>,\n drainToken: DrainToken\n ) => Effect.Effect<PauseDecision>\n readonly acceptHitl: (\n runId: string,\n admission: HitlAdmission,\n onReady: Effect.Effect<void>\n ) => Effect.Effect<HitlDecision>\n readonly clearPark: (runId: string, generation: ParkGeneration) => Effect.Effect<boolean>\n readonly beginDrain: (runId: string, scope: Promotable) => Effect.Effect<DrainBegin>\n readonly endDrain: (\n runId: string,\n drainToken: DrainToken,\n acknowledged: boolean\n ) => Effect.Effect<void>\n readonly invalidate: (\n runId: string,\n interrupt: Effect.Effect<boolean>,\n releaseIdleClaim: Effect.Effect<void>\n ) => Effect.Effect<{ readonly hadPark: boolean; readonly interrupted: boolean }>\n readonly enqueueAndWake: (item: InboxItem, wake: Effect.Effect<void>) => Effect.Effect<void>\n readonly wakeIfUnblocked: (\n runId: string,\n scope: Promotable,\n wake: Effect.Effect<void>\n ) => Effect.Effect<boolean>\n readonly startIfUnblocked: <E, R>(\n runId: string,\n start: Effect.Effect<CapturedRun<E>, E, R>\n ) => Effect.Effect<CapturedRun<E> | undefined, E, R>\n readonly admitRecovery: <E, R>(\n runId: string,\n attempt: Effect.Effect<RecoveryAttempt, E, R>,\n wake: Effect.Effect<void>\n ) => Effect.Effect<RecoveryAdmission, E, R>\n}\n\nconst isPromotableAt = (item: InboxItem, scope: Promotable) => {\n if (scope === 'steer') return item.delivery === 'steer'\n\n return item.delivery === 'steer' || item.delivery === 'input' || item.delivery === 'queue'\n}\n\ntype Park = {\n readonly generation: ParkGeneration\n readonly requestIds: ReadonlyArray<string>\n readonly responses: ReadonlyArray<ParkedResponse>\n readonly readyWoken: boolean\n}\n\ntype RunControl = {\n readonly pending: Promotable | undefined\n readonly liveToken: DrainToken | undefined\n readonly park: Park | undefined\n readonly leasedGeneration: ParkGeneration | undefined\n}\n\nconst emptyControl: RunControl = {\n pending: undefined,\n liveToken: undefined,\n park: undefined,\n leasedGeneration: undefined\n}\n\nconst widerPending = (current: Promotable | undefined, next: Promotable): Promotable =>\n current === 'input' || next === 'input' ? 'input' : 'steer'\n\nconst remainingPending = (pending: Promotable, scope: Promotable): Promotable | undefined =>\n scope === 'steer' && pending === 'input' ? 'input' : undefined\n\nconst itemScope = (item: InboxItem): Promotable => (item.delivery === 'steer' ? 'steer' : 'input')\n\nconst parkComplete = (park: Park) =>\n park.requestIds.every(requestId =>\n park.responses.some(response => response.requestId === requestId)\n )\n\nconst parkBlocked = (park: Park | undefined) => park !== undefined && !parkComplete(park)\n\nconst parkedState = (park: Park): ParkedState => ({\n generation: park.generation,\n requestIds: park.requestIds,\n responses: park.responses,\n ready: parkComplete(park)\n})\n\nconst isPrunable = (control: RunControl) =>\n control.pending === undefined &&\n control.liveToken === undefined &&\n control.park === undefined &&\n control.leasedGeneration === undefined\n\nexport class Inbox extends Context.Service<Inbox, InboxApi>()('@yolk-sdk/harness/Inbox') {\n /** Fresh queue, admission gate and HITL generations per layer acquisition. */\n static layer = (): Layer.Layer<Inbox> =>\n Layer.effect(\n this,\n Effect.gen(function* () {\n const items = yield* Ref.make<ReadonlyArray<InboxItem>>([])\n const controls = yield* Ref.make<ReadonlyMap<string, RunControl>>(new Map())\n const gate = yield* Semaphore.make(1)\n let generationSeq = 0\n let drainSeq = 0\n\n const withGate = <A, E, R>(body: Effect.Effect<A, E, R>) => gate.withPermits(1)(body)\n\n const getControl = (runId: string) =>\n Ref.get(controls).pipe(Effect.map(current => current.get(runId) ?? emptyControl))\n\n const writeControl = (runId: string, next: RunControl) =>\n Ref.update(controls, current => {\n const copy = new Map(current)\n\n if (isPrunable(next)) copy.delete(runId)\n else copy.set(runId, next)\n\n return copy\n })\n\n const dropQueued = (runId: string) =>\n Ref.update(items, current => current.filter(item => item.runId !== runId))\n\n const acceptHitlPure = (control: RunControl, admission: HitlAdmission): HitlDecision => {\n const park = control.park\n\n if (park === undefined) return HitlDecision.NotParked()\n\n if (park.generation !== admission.generation) return HitlDecision.Stale()\n\n if (!park.requestIds.includes(admission.requestId)) return HitlDecision.UnknownRequest()\n\n if (\n park.responses.some(\n response =>\n response.itemId === admission.itemId || response.requestId === admission.requestId\n )\n ) {\n return HitlDecision.Duplicate()\n }\n\n if (park.readyWoken) return HitlDecision.Duplicate()\n\n const responses = [\n ...park.responses,\n { itemId: admission.itemId, requestId: admission.requestId }\n ]\n\n return parkComplete({ ...park, responses })\n ? HitlDecision.Ready()\n : HitlDecision.Accepted()\n }\n\n return Inbox.of({\n enqueue: item => Ref.update(items, current => [...current, item]),\n takePromotable: (runId, scope, drainToken) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n\n if (control.liveToken === undefined || control.liveToken !== drainToken) {\n return undefined\n }\n\n return yield* Ref.modify(items, current => {\n const index = current.findIndex(\n item => item.runId === runId && isPromotableAt(item, scope)\n )\n\n if (index < 0) return [undefined, current] as const\n const taken = current[index]\n\n return [taken, current.filter((_, itemIndex) => itemIndex !== index)] as const\n })\n })\n )\n ),\n pending: runId =>\n Ref.get(items).pipe(\n Effect.map(current => current.filter(item => item.runId === runId))\n ),\n parked: runId =>\n getControl(runId).pipe(\n Effect.map(control =>\n control.park === undefined ? undefined : parkedState(control.park)\n )\n ),\n park: (runId, requestIds, drainToken) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n\n if (control.liveToken !== drainToken) return PauseDecision.Stale()\n generationSeq += 1\n const generation = ParkGeneration.make(String(generationSeq))\n yield* writeControl(runId, {\n pending: control.pending,\n liveToken: control.liveToken,\n leasedGeneration: control.leasedGeneration,\n park: {\n generation,\n requestIds: [...requestIds],\n responses: [],\n readyWoken: false\n }\n })\n\n return PauseDecision.Parked({ generation })\n })\n )\n ),\n acceptHitl: (runId, admission, onReady) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n const decision = acceptHitlPure(control, admission)\n\n if (\n !Predicate.isTagged(decision, 'Accepted') &&\n !Predicate.isTagged(decision, 'Ready')\n ) {\n return decision\n }\n\n const park = control.park\n\n if (park === undefined) return HitlDecision.NotParked()\n\n const nextPark: Park = {\n ...park,\n responses: [\n ...park.responses,\n { itemId: admission.itemId, requestId: admission.requestId }\n ],\n readyWoken: Predicate.isTagged(decision, 'Ready')\n }\n\n yield* writeControl(runId, {\n pending: Predicate.isTagged(decision, 'Ready')\n ? widerPending(control.pending, 'input')\n : control.pending,\n liveToken: control.liveToken,\n leasedGeneration: control.leasedGeneration,\n park: nextPark\n })\n\n if (Predicate.isTagged(decision, 'Ready')) yield* onReady\n\n return decision\n })\n )\n ),\n clearPark: (runId, generation) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n\n if (control.park === undefined || control.park.generation !== generation) {\n return false\n }\n\n yield* writeControl(runId, {\n pending: control.pending,\n liveToken: control.liveToken,\n leasedGeneration: control.leasedGeneration,\n park: undefined\n })\n\n return true\n })\n )\n ),\n beginDrain: (runId, scope) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n const pending = control.pending\n\n if (parkBlocked(control.park) || pending === undefined) {\n return DrainBegin.Skip()\n }\n\n drainSeq += 1\n const drainToken = DrainToken.make(`d${drainSeq}`)\n const park = control.park\n const ready = park !== undefined && parkComplete(park) ? park : undefined\n yield* writeControl(runId, {\n pending: remainingPending(pending, scope),\n liveToken: drainToken,\n park,\n leasedGeneration: ready?.generation\n })\n\n return DrainBegin.Run({\n drainToken,\n readyResponses: ready === undefined ? [] : ready.responses\n })\n })\n )\n ),\n endDrain: (runId, drainToken, acknowledged) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n\n if (control.liveToken !== drainToken) return\n const leased = control.leasedGeneration\n const park = control.park\n\n const clearPark =\n acknowledged &&\n leased !== undefined &&\n park !== undefined &&\n park.generation === leased\n\n yield* writeControl(runId, {\n pending: control.pending,\n liveToken: undefined,\n leasedGeneration: undefined,\n park: clearPark ? undefined : park\n })\n })\n )\n ),\n invalidate: (runId, interrupt, releaseIdleClaim) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n const hadPark = control.park !== undefined\n yield* dropQueued(runId)\n yield* writeControl(runId, emptyControl)\n const interrupted = yield* interrupt\n\n if (!interrupted) yield* releaseIdleClaim\n\n return { hadPark, interrupted }\n })\n )\n ),\n enqueueAndWake: (item, wake) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n yield* Ref.update(items, current => [...current, item])\n const control = yield* getControl(item.runId)\n\n if (parkBlocked(control.park)) return\n yield* writeControl(item.runId, {\n pending: widerPending(control.pending, itemScope(item)),\n liveToken: control.liveToken,\n leasedGeneration: control.leasedGeneration,\n park: control.park\n })\n yield* wake\n })\n )\n ),\n wakeIfUnblocked: (runId, scope, wake) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n\n if (parkBlocked(control.park)) return false\n yield* writeControl(runId, {\n pending: widerPending(control.pending, scope),\n liveToken: control.liveToken,\n leasedGeneration: control.leasedGeneration,\n park: control.park\n })\n yield* wake\n\n return true\n })\n )\n ),\n startIfUnblocked: (runId, start) =>\n withGate(\n Effect.uninterruptible(\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n\n if (parkBlocked(control.park)) return undefined\n const ticket = yield* start\n\n if (Predicate.isTagged(ticket, 'Started')) {\n yield* writeControl(runId, {\n pending: widerPending(control.pending, 'input'),\n liveToken: control.liveToken,\n leasedGeneration: control.leasedGeneration,\n park: control.park\n })\n }\n\n return ticket\n })\n )\n ),\n admitRecovery: (runId, attempt, wake) =>\n Effect.uninterruptibleMask(restore =>\n restore(gate.take(1)).pipe(\n Effect.flatMap(() =>\n Effect.gen(function* () {\n const control = yield* getControl(runId)\n\n if (parkBlocked(control.park)) return RecoveryAdmission.Skip()\n const decision = yield* attempt\n\n if (!RecoveryAttempt.$is('Resume')(decision)) return decision\n yield* writeControl(runId, {\n pending: widerPending(control.pending, 'input'),\n liveToken: control.liveToken,\n leasedGeneration: control.leasedGeneration,\n park: control.park\n })\n yield* wake\n\n return RecoveryAdmission.Resumed()\n }).pipe(Effect.ensuring(gate.release(1)))\n )\n )\n )\n })\n })\n )\n}\n\n/** Backward-compatible delegation to the owning inbox layer. */\nexport const makeInMemoryInboxLayer = (): Layer.Layer<Inbox> => Inbox.layer()\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ export {};