@cotal-ai/runtime 0.47.1 → 0.48.1

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 (45) hide show
  1. package/dist/fork.d.ts.map +1 -1
  2. package/dist/fork.js +26 -12
  3. package/dist/fork.js.map +1 -1
  4. package/dist/inspect-compiled.d.ts +16 -0
  5. package/dist/inspect-compiled.d.ts.map +1 -0
  6. package/dist/inspect-compiled.js +39 -0
  7. package/dist/inspect-compiled.js.map +1 -0
  8. package/dist/mesh-handler.d.ts +12 -15
  9. package/dist/mesh-handler.d.ts.map +1 -1
  10. package/dist/mesh-handler.js +108 -39
  11. package/dist/mesh-handler.js.map +1 -1
  12. package/dist/migrate.d.ts.map +1 -1
  13. package/dist/migrate.js +23 -10
  14. package/dist/migrate.js.map +1 -1
  15. package/dist/run-command.d.ts.map +1 -1
  16. package/dist/run-command.js +47 -27
  17. package/dist/run-command.js.map +1 -1
  18. package/dist/run-driver.d.ts +1 -1
  19. package/dist/run-driver.d.ts.map +1 -1
  20. package/dist/run-driver.js +16 -40
  21. package/dist/run-driver.js.map +1 -1
  22. package/dist/run-effect-host.d.ts +13 -0
  23. package/dist/run-effect-host.d.ts.map +1 -0
  24. package/dist/run-effect-host.js +57 -0
  25. package/dist/run-effect-host.js.map +1 -0
  26. package/dist/run-host.d.ts.map +1 -1
  27. package/dist/run-host.js +14 -13
  28. package/dist/run-host.js.map +1 -1
  29. package/dist/run-pause-host.d.ts +23 -0
  30. package/dist/run-pause-host.d.ts.map +1 -0
  31. package/dist/run-pause-host.js +99 -0
  32. package/dist/run-pause-host.js.map +1 -0
  33. package/dist/run-record-host.d.ts +20 -0
  34. package/dist/run-record-host.d.ts.map +1 -0
  35. package/dist/run-record-host.js +76 -0
  36. package/dist/run-record-host.js.map +1 -0
  37. package/dist/run-scope-authority.d.ts +51 -0
  38. package/dist/run-scope-authority.d.ts.map +1 -0
  39. package/dist/run-scope-authority.js +193 -0
  40. package/dist/run-scope-authority.js.map +1 -0
  41. package/dist/run-wait-host.d.ts +22 -0
  42. package/dist/run-wait-host.d.ts.map +1 -0
  43. package/dist/run-wait-host.js +70 -0
  44. package/dist/run-wait-host.js.map +1 -0
  45. package/package.json +4 -4
@@ -0,0 +1,23 @@
1
+ import { type CheckpointAnswerValue, type CheckpointSettleFact, type RunHostPlanes } from "@cotal-ai/core";
2
+ import { RunScopeAuthority } from "./run-scope-authority.js";
3
+ export interface RunPauseHost {
4
+ arm(token: string, deadline: number): Promise<void>;
5
+ heartbeat(token: string, deadline: number): Promise<void>;
6
+ readSettle(token: string): Promise<CheckpointSettleFact | undefined>;
7
+ readAnswer(token: string): Promise<CheckpointAnswerValue | undefined>;
8
+ takeFire(token: string): Promise<boolean>;
9
+ claim(token: string): Promise<void>;
10
+ rearm(): Promise<readonly string[]>;
11
+ }
12
+ /** The trusted host owns these planes. Its returned methods derive every subject from the
13
+ * bound endpoint and attempt, and authorize tokens against its own broker journal. */
14
+ export declare function createRunPauseHost(broker: RunHostPlanes, binding: {
15
+ endpoint: string;
16
+ instanceId: string;
17
+ epoch: number;
18
+ holder: {
19
+ id: string;
20
+ lifecycleUid: string;
21
+ };
22
+ }, authority: RunScopeAuthority, clock?: () => number): RunPauseHost;
23
+ //# sourceMappingURL=run-pause-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-pause-host.d.ts","sourceRoot":"","sources":["../src/run-pause-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAaL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAC;IACrE,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CAAC;IACtE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,KAAK,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;CACrC;AAED;uFACuF;AACvF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C,EACD,SAAS,EAAE,iBAAiB,EAC5B,KAAK,GAAE,MAAM,MAAiB,GAC7B,YAAY,CAmFd"}
@@ -0,0 +1,99 @@
1
+ import { EpEnvelopeError, eptStreamName, eptSubject, handleCheckpointFire, heartbeatCheckpoint, mintCheckpoint, readCheckpointAnswer, readCheckpointSettle, readCheckpointSpec, readCheckpointStatus, reconcileCheckpointSchedule, resumeCheckpoint, } from "@cotal-ai/core";
2
+ import { RunScopeAuthority } from "./run-scope-authority.js";
3
+ /** The trusted host owns these planes. Its returned methods derive every subject from the
4
+ * bound endpoint and attempt, and authorize tokens against its own broker journal. */
5
+ export function createRunPauseHost(broker, binding, authority, clock = Date.now) {
6
+ const { kv, js, jsm, space } = broker;
7
+ const pinned = structuredClone(binding);
8
+ const ref = (token) => ({ endpoint: pinned.endpoint, token });
9
+ return Object.freeze({
10
+ async arm(token, deadline) {
11
+ await authority.pause(token, "mint");
12
+ const pause = ref(token);
13
+ if (await readCheckpointSettle(jsm, space, pause))
14
+ return;
15
+ const prior = await readCheckpointSpec(kv, pause);
16
+ const now = clock();
17
+ if (prior === undefined) {
18
+ await mintCheckpoint(kv, js, space, { ref: pause, ...pinned, deadline, now });
19
+ return;
20
+ }
21
+ const mine = prior.holder.id === pinned.holder.id && prior.holder.lifecycleUid === pinned.holder.lifecycleUid;
22
+ if (mine && prior.initialDeadline > now) {
23
+ await mintCheckpoint(kv, js, space, { ref: pause, ...pinned, deadline: prior.initialDeadline, now });
24
+ return;
25
+ }
26
+ const status = await readCheckpointStatus(kv, pause);
27
+ if (status === undefined)
28
+ throw new Error(`checkpoint ${token} has a spec without status; only its recorded holder can complete the identical mint`);
29
+ if (status.value.state !== "waiting")
30
+ return;
31
+ await authority.pause(token, "attach");
32
+ await reconcileCheckpointSchedule(kv, js, jsm, space, { ref: pause, instanceId: pinned.instanceId, epoch: pinned.epoch });
33
+ },
34
+ async heartbeat(token, deadline) {
35
+ await authority.pause(token, "heartbeat");
36
+ await heartbeatCheckpoint(kv, js, jsm, space, {
37
+ ref: ref(token), instanceId: pinned.instanceId, epoch: pinned.epoch, deadline, now: clock(),
38
+ });
39
+ },
40
+ async readSettle(token) {
41
+ await authority.pause(token, "read");
42
+ return readCheckpointSettle(jsm, space, ref(token));
43
+ },
44
+ async readAnswer(token) {
45
+ await authority.pause(token, "read");
46
+ const settled = await readCheckpointSettle(jsm, space, ref(token));
47
+ if (settled?.answerId === undefined)
48
+ return undefined;
49
+ return readCheckpointAnswer(kv, pinned.endpoint, token, settled.answerId);
50
+ },
51
+ async takeFire(token) {
52
+ await authority.pause(token, "fire");
53
+ const subject = eptSubject(space, pinned.endpoint, pinned.instanceId, pinned.epoch, token, "fire");
54
+ const fired = await jsm.streams.getMessage(eptStreamName(space), { last_by_subj: subject }).catch((error) => {
55
+ if (error?.code === 10037)
56
+ return null;
57
+ throw error;
58
+ });
59
+ if (fired === null || fired === undefined)
60
+ return false;
61
+ const result = await handleCheckpointFire(kv, js, jsm, space, {
62
+ ref: ref(token), instanceId: pinned.instanceId, epoch: pinned.epoch,
63
+ msg: { subject, ...(fired.header === undefined ? {} : { headers: fired.header }), data: fired.data },
64
+ now: clock(),
65
+ });
66
+ return result.acted;
67
+ },
68
+ async claim(token) {
69
+ await authority.pause(token, "claim");
70
+ const pause = ref(token);
71
+ const status = await readCheckpointStatus(kv, pause);
72
+ if (status?.value.state !== "waiting")
73
+ return;
74
+ const spec = await readCheckpointSpec(kv, pause);
75
+ if (spec === undefined)
76
+ throw new Error(`checkpoint ${token} is waiting without its spec`);
77
+ try {
78
+ await resumeCheckpoint(kv, js, jsm, space, { ref: pause, presenter: spec.holder, now: clock() });
79
+ }
80
+ catch (error) {
81
+ if (!(error instanceof EpEnvelopeError && (error.code === "conflict" || error.code === "failed-precondition")))
82
+ throw error;
83
+ }
84
+ },
85
+ async rearm() {
86
+ const rearmed = [];
87
+ for (const token of await authority.rearmTokens()) {
88
+ await authority.pause(token, "rearm");
89
+ const result = await reconcileCheckpointSchedule(kv, js, jsm, space, {
90
+ ref: ref(token), instanceId: pinned.instanceId, epoch: pinned.epoch,
91
+ });
92
+ if (result.reEmitted)
93
+ rearmed.push(token);
94
+ }
95
+ return rearmed;
96
+ },
97
+ });
98
+ }
99
+ //# sourceMappingURL=run-pause-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-pause-host.js","sourceRoot":"","sources":["../src/run-pause-host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { KV, KvEntry } from "@nats-io/kv";
2
+ import { type RunHostPlanes } from "@cotal-ai/core";
3
+ export interface RunRecordValue {
4
+ readonly key: string;
5
+ readonly value: Uint8Array;
6
+ readonly revision: number;
7
+ readonly createdAt: number;
8
+ readonly operation: KvEntry["operation"];
9
+ }
10
+ /** A run-bound leader reader. Neither the backing bucket nor its stream API is exposed. */
11
+ export interface RunRecordHost {
12
+ read(key: string): Promise<RunRecordValue | undefined>;
13
+ list(filter: string): Promise<readonly RunRecordValue[]>;
14
+ }
15
+ export declare function createRunRecordHost(broker: Pick<RunHostPlanes, "kv" | "jsm" | "space">, endpoint: string, runId: string): RunRecordHost;
16
+ /** Adapt the driver's own write-capable bucket for core's record helpers. Only get crosses
17
+ * the host boundary. Every other method and internal client still belongs to the driver,
18
+ * so reaching through this view cannot recover the host's broker connection. */
19
+ export declare function runRecordView(driver: KV, host: RunRecordHost, space: string): KV;
20
+ //# sourceMappingURL=run-record-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-record-host.d.ts","sourceRoot":"","sources":["../src/run-record-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAmF,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGrI,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1C;AAED,2FAA2F;AAC3F,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;CAC1D;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,KAAK,GAAG,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAiCvI;AAED;;iFAEiF;AACjF,wBAAgB,aAAa,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE,CA4BhF"}
@@ -0,0 +1,76 @@
1
+ import { assertIdToken, endpointToken, recordsBucket, recordsKvStreamName, walkKvEntries } from "@cotal-ai/core";
2
+ import { RunScopeDenied } from "./run-scope-authority.js";
3
+ export function createRunRecordHost(broker, endpoint, runId) {
4
+ const { kv, jsm, space } = broker;
5
+ const e = endpointToken(endpoint);
6
+ const run = assertIdToken(runId, "runId");
7
+ const exact = new Set([`run.${e}.${run}.spec`, `run.${e}.${run}.status`, `program.${e}.${run}`]);
8
+ const families = [`notice.${e}.${run}.`, `migration.${e}.${run}.`];
9
+ const own = (key) => typeof key === "string"
10
+ && (exact.has(key) || families.some((prefix) => key.startsWith(prefix) && key.length > prefix.length));
11
+ const copy = (entry) => Object.freeze({
12
+ key: entry.key, value: entry.value.slice(), revision: entry.revision, createdAt: entry.created.getTime(), operation: entry.operation,
13
+ });
14
+ return Object.freeze({
15
+ async read(key) {
16
+ if (!own(key) || /[*>]/.test(key))
17
+ throw new RunScopeDenied(run, key, "read record");
18
+ const message = await jsm.streams.getMessage(recordsKvStreamName(space), {
19
+ last_by_subj: `$KV.${recordsBucket(space)}.${key}`,
20
+ }).catch((error) => {
21
+ if (error?.code === 10037)
22
+ return null;
23
+ throw error;
24
+ });
25
+ if (message === null || message === undefined)
26
+ return undefined;
27
+ const operation = message.header?.get("KV-Operation") || "PUT";
28
+ if (operation !== "PUT" && operation !== "DEL" && operation !== "PURGE")
29
+ throw new Error(`record ${key} carries an unknown operation ${operation}`);
30
+ return Object.freeze({ key, value: message.data.slice(), revision: message.seq, createdAt: message.time.getTime(), operation });
31
+ },
32
+ async list(filter) {
33
+ if (!own(filter))
34
+ throw new RunScopeDenied(run, filter, "list records");
35
+ const entries = await walkKvEntries(kv, filter);
36
+ if (entries.some((entry) => !own(entry.key)))
37
+ throw new RunScopeDenied(run, filter, "read outside record filter");
38
+ return entries.map(copy);
39
+ },
40
+ });
41
+ }
42
+ /** Adapt the driver's own write-capable bucket for core's record helpers. Only get crosses
43
+ * the host boundary. Every other method and internal client still belongs to the driver,
44
+ * so reaching through this view cannot recover the host's broker connection. */
45
+ export function runRecordView(driver, host, space) {
46
+ const get = async (key, options) => {
47
+ if (options?.revision !== undefined)
48
+ throw new Error("a run record view does not support revision-addressed reads");
49
+ const value = await host.read(key);
50
+ if (value === undefined)
51
+ return null;
52
+ const entry = {
53
+ bucket: recordsBucket(space),
54
+ key: value.key,
55
+ rawKey: value.key,
56
+ value: value.value,
57
+ created: new Date(value.createdAt),
58
+ revision: value.revision,
59
+ operation: value.operation,
60
+ delta: 0,
61
+ length: value.value.length,
62
+ string: () => new TextDecoder().decode(value.value),
63
+ json: () => JSON.parse(new TextDecoder().decode(value.value)),
64
+ };
65
+ return entry;
66
+ };
67
+ return new Proxy(driver, {
68
+ get(target, property) {
69
+ if (property === "get")
70
+ return get;
71
+ const value = Reflect.get(target, property, target);
72
+ return typeof value === "function" ? value.bind(target) : value;
73
+ },
74
+ });
75
+ }
76
+ //# sourceMappingURL=run-record-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-record-host.js","sourceRoot":"","sources":["../src/run-record-host.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,aAAa,EAAsB,MAAM,gBAAgB,CAAC;AACrI,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAgB1D,MAAM,UAAU,mBAAmB,CAAC,MAAmD,EAAE,QAAgB,EAAE,KAAa;IACtH,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IAClC,MAAM,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,OAAO,EAAE,OAAO,CAAC,IAAI,GAAG,SAAS,EAAE,WAAW,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;IACjG,MAAM,QAAQ,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,EAAE,aAAa,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ;WAC/C,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACzG,MAAM,IAAI,GAAG,CAAC,KAAc,EAAkB,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;QAC7D,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS;KACrI,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,GAAW;YACpB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;YACrF,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE;gBACvE,YAAY,EAAE,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE;aACnD,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBAC1B,IAAK,KAA4B,EAAE,IAAI,KAAK,KAAK;oBAAE,OAAO,IAAI,CAAC;gBAC/D,MAAM,KAAK,CAAC;YACd,CAAC,CAAC,CAAC;YACH,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAChE,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC;YAC/D,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,OAAO;gBACrE,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,iCAAiC,SAAS,EAAE,CAAC,CAAC;YAC7E,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAClI,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAc;YACvB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,MAAM,IAAI,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;YACxE,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAChD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAAE,MAAM,IAAI,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,4BAA4B,CAAC,CAAC;YAClH,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;iFAEiF;AACjF,MAAM,UAAU,aAAa,CAAC,MAAU,EAAE,IAAmB,EAAE,KAAa;IAC1E,MAAM,GAAG,GAAc,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QAC5C,IAAI,OAAO,EAAE,QAAQ,KAAK,SAAS;YACjC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACrC,MAAM,KAAK,GAAY;YACrB,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC;YAC5B,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,MAAM,EAAE,KAAK,CAAC,GAAG;YACjB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YAClC,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,KAAK,EAAE,CAAC;YACR,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;YAC1B,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YACnD,IAAI,EAAE,GAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAM;SACtE,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE;QACvB,GAAG,CAAC,MAAM,EAAE,QAAQ;YAClB,IAAI,QAAQ,KAAK,KAAK;gBAAE,OAAO,GAAG,CAAC;YACnC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YACpD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAClE,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { type EffectContext, type JournalEntry } from "@cotal-ai/lang";
2
+ import { type RunHostPlanes, type RunHostLease, type RunJournalActivation } from "@cotal-ai/core";
3
+ interface RunScopeSnapshot {
4
+ readonly entries: readonly JournalEntry[];
5
+ readonly activation: RunJournalActivation | undefined;
6
+ }
7
+ /** The reader and its replay durable are host-bound. No request selects another run. */
8
+ export declare function createRunScopeAuthority(broker: RunHostPlanes, runId: string, lease: RunHostLease): RunScopeAuthority;
9
+ export type PauseOperation = "read" | "mint" | "attach" | "rearm" | "heartbeat" | "claim" | "fire";
10
+ export type WaitOperation = "open" | "fetch" | "ack" | "close";
11
+ export declare class RunScopeDenied extends Error {
12
+ constructor(runId: string, resource: string, operation: string);
13
+ }
14
+ /** The caller supplies a reader already bound to one run's broker journal. Requests cannot
15
+ * replace that reader or provide their own entries. Each decision uses a fresh folded snapshot. */
16
+ export declare class RunScopeAuthority {
17
+ private readonly runId;
18
+ private readonly readJournal;
19
+ private readonly attempt;
20
+ private reading;
21
+ constructor(runId: string, readJournal: () => Promise<RunScopeSnapshot>, attempt: Pick<RunHostLease, "holder" | "epoch" | "fencingToken">);
22
+ private entries;
23
+ /** Fork prefixes keep settled parent ids as history. Such an entry can be replayed but
24
+ * cannot authorize this child to operate on a parent's checkpoint or wait consumer. */
25
+ private owns;
26
+ journal(): Promise<readonly JournalEntry[]>;
27
+ effect(kind: string, ctx: Pick<EffectContext, "key" | "requestId" | "attempt">): Promise<JournalEntry>;
28
+ private cleanup;
29
+ /** Cleanup authority comes from the settled parent scope. A settled child alone carries none. */
30
+ cleanupEntries(): Promise<readonly JournalEntry[]>;
31
+ pause(token: string, operation: PauseOperation): Promise<JournalEntry>;
32
+ wait(requestId: string, operation: WaitOperation): Promise<JournalEntry>;
33
+ matchedMessage(requestId: string, sequence: number): Promise<JournalEntry>;
34
+ /** The driver cannot add tokens to the adoption sweep. Plane status still decides whether
35
+ * a derived wait timer exists and needs rearming. This list never authorizes its first mint. */
36
+ rearmTokens(): Promise<readonly string[]>;
37
+ }
38
+ /** A receipt's identity is held in a WeakMap. Serializing, copying or inventing a receipt
39
+ * does not copy the delivery it authorizes. The host never exposes its ACK subject. */
40
+ export interface WaitReceipt {
41
+ readonly _brand: "WaitReceipt";
42
+ }
43
+ export declare class WaitReceipts {
44
+ private readonly deliveries;
45
+ private readonly byWait;
46
+ issue(requestId: string, ack: () => void | Promise<void>): WaitReceipt;
47
+ ack(requestId: string, receipt: WaitReceipt): Promise<void>;
48
+ close(requestId: string): void;
49
+ }
50
+ export {};
51
+ //# sourceMappingURL=run-scope-authority.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-scope-authority.d.ts","sourceRoot":"","sources":["../src/run-scope-authority.ts"],"names":[],"mappings":"AACA,OAAO,EAAyD,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9H,OAAO,EAAoB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEpH,UAAU,gBAAgB;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,oBAAoB,GAAG,SAAS,CAAC;CACvD;AAED,wFAAwF;AACxF,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,GAClB,iBAAiB,CAUnB;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;AACnG,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAE/D,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAI/D;AAED;oGACoG;AACpG,qBAAa,iBAAiB;IAI1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,OAAO,CAAoC;gBAGhC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,EAC5C,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,OAAO,GAAG,cAAc,CAAC;YAGrE,OAAO;IAgBrB;4FACwF;IACxF,OAAO,CAAC,IAAI;IASN,OAAO,IAAI,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;IAI3C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,WAAW,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IAU5G,OAAO,CAAC,OAAO;IAaf,iGAAiG;IAC3F,cAAc,IAAI,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;IAMlD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAiBtE,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAWxE,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAOhF;qGACiG;IAC3F,WAAW,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC;CAKhD;AAoBD;wFACwF;AACxF,MAAM,WAAW,WAAW;IAAG,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE;AAE/D,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsF;IACjH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAE9D,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW;IAShE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAM/B"}
@@ -0,0 +1,193 @@
1
+ import { createHash } from "node:crypto";
2
+ import { Journal, digest, journalEntryKeyString, stepKeyString } from "@cotal-ai/lang";
3
+ import { replayRunJournal } from "@cotal-ai/core";
4
+ /** The reader and its replay durable are host-bound. No request selects another run. */
5
+ export function createRunScopeAuthority(broker, runId, lease) {
6
+ const pinned = structuredClone(lease);
7
+ return new RunScopeAuthority(runId, async () => {
8
+ const replay = await replayRunJournal(broker.js, broker.jsm, broker.space, runId, pinned.takeoverId);
9
+ const last = replay.records.findLast(({ record }) => record.kind === "activation")?.record;
10
+ return {
11
+ entries: replay.records.flatMap(({ record }) => record.kind === "step" ? [record.entry] : []),
12
+ activation: last?.kind === "activation" ? last : undefined,
13
+ };
14
+ }, pinned);
15
+ }
16
+ export class RunScopeDenied extends Error {
17
+ constructor(runId, resource, operation) {
18
+ super(`run ${runId} has no current journal authority to ${operation} ${resource}`);
19
+ this.name = "RunScopeDenied";
20
+ }
21
+ }
22
+ /** The caller supplies a reader already bound to one run's broker journal. Requests cannot
23
+ * replace that reader or provide their own entries. Each decision uses a fresh folded snapshot. */
24
+ export class RunScopeAuthority {
25
+ runId;
26
+ readJournal;
27
+ attempt;
28
+ reading = Promise.resolve();
29
+ constructor(runId, readJournal, attempt) {
30
+ this.runId = runId;
31
+ this.readJournal = readJournal;
32
+ this.attempt = attempt;
33
+ }
34
+ async entries() {
35
+ const reading = this.reading.then(() => this.readJournal());
36
+ this.reading = reading.then(() => undefined, () => undefined);
37
+ const snapshot = await reading;
38
+ const active = snapshot.activation;
39
+ if (active === undefined || active.run !== this.runId || active.holder !== this.attempt.holder
40
+ || active.epoch !== this.attempt.epoch || active.fencingToken !== this.attempt.fencingToken)
41
+ throw new RunScopeDenied(this.runId, "drive attempt", "use superseded host");
42
+ const entries = new Journal({ run: this.runId, entries: snapshot.entries }).entries();
43
+ for (const entry of entries) {
44
+ if (entry.requestId === undefined || entry.state === "settled")
45
+ continue;
46
+ if (!this.owns(entry))
47
+ throw new RunScopeDenied(this.runId, entry.requestId, "load");
48
+ }
49
+ return entries;
50
+ }
51
+ /** Fork prefixes keep settled parent ids as history. Such an entry can be replayed but
52
+ * cannot authorize this child to operate on a parent's checkpoint or wait consumer. */
53
+ owns(entry) {
54
+ if (entry.requestId === undefined)
55
+ return false;
56
+ const attempt = entry.attempt ?? 0;
57
+ if (!Number.isSafeInteger(attempt) || attempt < 0)
58
+ return false;
59
+ const hash = digest([this.runId, journalEntryKeyString(entry), entry.inputHash, attempt]);
60
+ const expected = Buffer.from(hash.slice("sha256:".length), "hex").toString("base64url");
61
+ return entry.requestId === expected;
62
+ }
63
+ async journal() {
64
+ return this.entries();
65
+ }
66
+ async effect(kind, ctx) {
67
+ const entries = await this.entries();
68
+ const entry = entries.find((candidate) => journalEntryKeyString(candidate) === stepKeyString(ctx.key));
69
+ if (entry === undefined || entry.kind !== kind || entry.requestId !== ctx.requestId
70
+ || (entry.attempt ?? 0) !== ctx.attempt || entry.state !== "pending"
71
+ || this.cleanup(entries).has(journalEntryKeyString(entry)))
72
+ throw new RunScopeDenied(this.runId, ctx.requestId, `perform ${kind}`);
73
+ return entry;
74
+ }
75
+ cleanup(entries) {
76
+ const owed = new Set();
77
+ for (const parent of entries) {
78
+ if (parent.state !== "settled" || parent.cancel === undefined || parent.cancel.issued)
79
+ continue;
80
+ const prefixes = parent.cancel.losers.map((branch) => `${journalEntryKeyString(parent)}/b:${branch}/`);
81
+ for (const entry of entries) {
82
+ const key = journalEntryKeyString(entry);
83
+ if (prefixes.some((prefix) => key.startsWith(prefix)))
84
+ owed.add(key);
85
+ }
86
+ }
87
+ return owed;
88
+ }
89
+ /** Cleanup authority comes from the settled parent scope. A settled child alone carries none. */
90
+ async cleanupEntries() {
91
+ const entries = await this.entries();
92
+ const owed = this.cleanup(entries);
93
+ return entries.filter((entry) => this.owns(entry) && owed.has(journalEntryKeyString(entry)));
94
+ }
95
+ async pause(token, operation) {
96
+ const entries = await this.entries();
97
+ const entry = entries.find((candidate) => this.owns(candidate) && pauseTokens(candidate).includes(token));
98
+ if (entry !== undefined) {
99
+ if (entry.kind === "wait" && (operation === "mint" || operation === "heartbeat")) {
100
+ const timers = entry.external?.waitTimers;
101
+ if (!Array.isArray(timers) || !timers.includes(token))
102
+ throw new RunScopeDenied(this.runId, token, `${operation} unrecorded wait timer`);
103
+ }
104
+ if (operation === "read")
105
+ return entry;
106
+ const cleaning = this.cleanup(entries).has(journalEntryKeyString(entry));
107
+ if (operation === "claim" && cleaning)
108
+ return entry;
109
+ if (entry.state === "pending" && !cleaning)
110
+ return entry;
111
+ }
112
+ throw new RunScopeDenied(this.runId, token, operation);
113
+ }
114
+ async wait(requestId, operation) {
115
+ const entries = await this.entries();
116
+ const entry = entries.find((candidate) => this.owns(candidate) && candidate.kind === "wait" && candidate.requestId === requestId);
117
+ if (entry !== undefined) {
118
+ const cleaning = this.cleanup(entries).has(journalEntryKeyString(entry));
119
+ if (operation === "close" && cleaning)
120
+ return entry;
121
+ if (entry.state === "pending" && !cleaning)
122
+ return entry;
123
+ }
124
+ throw new RunScopeDenied(this.runId, requestId, operation);
125
+ }
126
+ async matchedMessage(requestId, sequence) {
127
+ const entry = (await this.entries()).find((candidate) => this.owns(candidate) && candidate.kind === "wait" && candidate.requestId === requestId);
128
+ if (!Number.isSafeInteger(sequence) || sequence <= 0 || entry?.external?.chatSeq !== sequence)
129
+ throw new RunScopeDenied(this.runId, `${requestId}/${sequence}`, "read message");
130
+ return entry;
131
+ }
132
+ /** The driver cannot add tokens to the adoption sweep. Plane status still decides whether
133
+ * a derived wait timer exists and needs rearming. This list never authorizes its first mint. */
134
+ async rearmTokens() {
135
+ const entries = await this.entries();
136
+ const owed = this.cleanup(entries);
137
+ return entries.filter((entry) => this.owns(entry) && entry.state === "pending" && !owed.has(journalEntryKeyString(entry))).flatMap(pauseTokens);
138
+ }
139
+ }
140
+ /** Identities a step can own. An ask's old attempt drops out as soon as the next bind lands. */
141
+ function pauseTokens(entry) {
142
+ const id = entry.requestId;
143
+ if (id === undefined)
144
+ return [];
145
+ if (entry.kind === "sleep" || entry.kind === "checkpoint" || entry.kind === "turn")
146
+ return [id];
147
+ if (entry.kind === "wait")
148
+ return [id, derive(id, "wait-timeout")];
149
+ if (entry.kind !== "ask")
150
+ return [];
151
+ const attempt = entry.external?.attempt ?? 1;
152
+ if (typeof attempt !== "number" || !Number.isSafeInteger(attempt) || attempt < 1)
153
+ return [];
154
+ const expected = attempt === 1 ? id : derive(id, `ask-attempt-${attempt}`);
155
+ if (entry.external?.askToken !== undefined && entry.external.askToken !== expected)
156
+ return [];
157
+ return [expected];
158
+ }
159
+ function derive(requestId, purpose) {
160
+ return createHash("sha256").update(`${requestId}:${purpose}`, "utf8").digest("base64url");
161
+ }
162
+ export class WaitReceipts {
163
+ deliveries = new WeakMap();
164
+ byWait = new Map();
165
+ issue(requestId, ack) {
166
+ const receipt = Object.freeze({ _brand: "WaitReceipt" });
167
+ this.deliveries.set(receipt, { requestId, ack });
168
+ const held = this.byWait.get(requestId) ?? new Set();
169
+ held.add(receipt);
170
+ this.byWait.set(requestId, held);
171
+ return receipt;
172
+ }
173
+ async ack(requestId, receipt) {
174
+ const delivery = this.deliveries.get(receipt);
175
+ if (delivery === undefined || delivery.requestId !== requestId)
176
+ throw new Error(`wait ${requestId} has no live delivery for this receipt`);
177
+ this.deliveries.delete(receipt);
178
+ const held = this.byWait.get(requestId);
179
+ held.delete(receipt);
180
+ if (held.size === 0)
181
+ this.byWait.delete(requestId);
182
+ await delivery.ack();
183
+ }
184
+ close(requestId) {
185
+ const held = this.byWait.get(requestId);
186
+ if (held === undefined)
187
+ return;
188
+ for (const receipt of held)
189
+ this.deliveries.delete(receipt);
190
+ this.byWait.delete(requestId);
191
+ }
192
+ }
193
+ //# sourceMappingURL=run-scope-authority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-scope-authority.js","sourceRoot":"","sources":["../src/run-scope-authority.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { JetStreamClient, JetStreamManager } from "@nats-io/jetstream";
2
+ import { RunScopeAuthority, type WaitReceipt } from "./run-scope-authority.js";
3
+ export interface RunWaitMessage {
4
+ readonly sequence: number;
5
+ readonly data: Uint8Array;
6
+ readonly receipt: WaitReceipt;
7
+ }
8
+ /** Only these operations cross from a driver into the trusted wait host. Broker objects,
9
+ * consumer names and ACK subjects remain inside the closure. */
10
+ export interface RunWaitHost {
11
+ open(requestId: string, channel: string): Promise<void>;
12
+ fetch(requestId: string): Promise<readonly RunWaitMessage[]>;
13
+ ack(requestId: string, receipt: WaitReceipt): Promise<void>;
14
+ close(requestId: string): Promise<void>;
15
+ messageAt(requestId: string, sequence: number): Promise<Uint8Array>;
16
+ }
17
+ export declare function createRunWaitHost(broker: {
18
+ js: JetStreamClient;
19
+ jsm: JetStreamManager;
20
+ space: string;
21
+ }, authority: RunScopeAuthority): RunWaitHost;
22
+ //# sourceMappingURL=run-wait-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-wait-host.d.ts","sourceRoot":"","sources":["../src/run-wait-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,OAAO,EAAE,iBAAiB,EAAgC,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE7G,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B;AAED;iEACiE;AACjE,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;IAC7D,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACrE;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE;IAAE,EAAE,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EACrE,SAAS,EAAE,iBAAiB,GAC3B,WAAW,CA6Db"}
@@ -0,0 +1,70 @@
1
+ import { chatStream, chatSubject, subjectMatches, waitConsumerConfig, waitConsumerName } from "@cotal-ai/core";
2
+ import { RunScopeAuthority, RunScopeDenied, WaitReceipts } from "./run-scope-authority.js";
3
+ export function createRunWaitHost(broker, authority) {
4
+ const stream = chatStream(broker.space);
5
+ const receipts = new WaitReceipts();
6
+ return Object.freeze({
7
+ async open(requestId, channel) {
8
+ const entry = await authority.wait(requestId, "open");
9
+ if (entry.external?.waitChannel !== channel)
10
+ throw new RunScopeDenied(entry.run, channel, "open unrecorded wait channel");
11
+ await broker.jsm.consumers.add(stream, waitConsumerConfig(broker.space, requestId, channel));
12
+ },
13
+ async fetch(requestId) {
14
+ const entry = await authority.wait(requestId, "fetch");
15
+ const channel = entry.external?.waitChannel;
16
+ if (typeof channel !== "string")
17
+ throw new RunScopeDenied(entry.run, requestId, "fetch unrecorded wait channel");
18
+ const consumer = await broker.js.consumers.get(stream, waitConsumerName(requestId));
19
+ const info = await consumer.info();
20
+ const expected = chatSubject(broker.space, "*", "*", channel);
21
+ if (info.config.filter_subject !== expected || (info.config.filter_subjects?.length ?? 0) !== 0)
22
+ throw new RunScopeDenied(entry.run, requestId, "fetch changed wait filter");
23
+ const messages = [];
24
+ const batch = await consumer.fetch({ max_messages: 16, expires: 2_000 });
25
+ try {
26
+ for await (const message of batch) {
27
+ if (!subjectMatches(expected, message.subject))
28
+ throw new RunScopeDenied(entry.run, message.subject, "receive outside wait channel");
29
+ messages.push(Object.freeze({
30
+ sequence: message.seq,
31
+ data: message.data.slice(),
32
+ receipt: receipts.issue(requestId, () => message.ack()),
33
+ }));
34
+ }
35
+ }
36
+ finally {
37
+ batch.stop();
38
+ }
39
+ return messages;
40
+ },
41
+ async ack(requestId, receipt) {
42
+ await authority.wait(requestId, "ack");
43
+ await receipts.ack(requestId, receipt);
44
+ },
45
+ async close(requestId) {
46
+ await authority.wait(requestId, "close");
47
+ try {
48
+ await broker.jsm.consumers.delete(stream, waitConsumerName(requestId));
49
+ }
50
+ catch (error) {
51
+ if (error?.code !== 10014)
52
+ throw error;
53
+ }
54
+ receipts.close(requestId);
55
+ },
56
+ async messageAt(requestId, sequence) {
57
+ const entry = await authority.matchedMessage(requestId, sequence);
58
+ const channel = entry.external?.waitChannel;
59
+ if (typeof channel !== "string")
60
+ throw new RunScopeDenied(entry.run, requestId, "read unrecorded wait channel");
61
+ const message = await broker.jsm.streams.getMessage(stream, { seq: sequence });
62
+ if (message === null || message === undefined)
63
+ throw new Error(`wait ${requestId}'s recorded message ${sequence} no longer exists`);
64
+ if (!subjectMatches(chatSubject(broker.space, "*", "*", channel), message.subject))
65
+ throw new RunScopeDenied(entry.run, requestId, "read outside wait channel");
66
+ return message.data.slice();
67
+ },
68
+ });
69
+ }
70
+ //# sourceMappingURL=run-wait-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-wait-host.js","sourceRoot":"","sources":["../src/run-wait-host.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC/G,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,YAAY,EAAoB,MAAM,0BAA0B,CAAC;AAkB7G,MAAM,UAAU,iBAAiB,CAC/B,MAAqE,EACrE,SAA4B;IAE5B,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;IACpC,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,SAAiB,EAAE,OAAe;YAC3C,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACtD,IAAI,KAAK,CAAC,QAAQ,EAAE,WAAW,KAAK,OAAO;gBACzC,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,8BAA8B,CAAC,CAAC;YAC/E,MAAM,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAC/F,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,SAAiB;YAC3B,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACvD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,EAAE,WAAW,CAAC;YAC5C,IAAI,OAAO,OAAO,KAAK,QAAQ;gBAAE,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,+BAA+B,CAAC,CAAC;YACjH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;YACpF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YAC9D,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC;gBAC7F,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,2BAA2B,CAAC,CAAC;YAC9E,MAAM,QAAQ,GAAqB,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACzE,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;oBAClC,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC;wBAC5C,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,8BAA8B,CAAC,CAAC;oBACvF,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;wBAC1B,QAAQ,EAAE,OAAO,CAAC,GAAG;wBACrB,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE;wBAC1B,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;qBACxD,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,KAAK,CAAC,IAAI,EAAE,CAAC;YACf,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,SAAiB,EAAE,OAAoB;YAC/C,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,SAAiB;YAC3B,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACzC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;YACzE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAK,KAA4B,EAAE,IAAI,KAAK,KAAK;oBAAE,MAAM,KAAK,CAAC;YACjE,CAAC;YACD,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,SAAiB,EAAE,QAAgB;YACjD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAClE,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,EAAE,WAAW,CAAC;YAC5C,IAAI,OAAO,OAAO,KAAK,QAAQ;gBAAE,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,8BAA8B,CAAC,CAAC;YAChH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC/E,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS;gBAC3C,MAAM,IAAI,KAAK,CAAC,QAAQ,SAAS,uBAAuB,QAAQ,mBAAmB,CAAC,CAAC;YACvF,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;gBAChF,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,2BAA2B,CAAC,CAAC;YAC9E,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}