@astrosheep/keiyaku 4.6.19 → 4.6.20

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 (102) hide show
  1. package/README.md +7 -3
  2. package/build/plugins/pi/README.md +111 -0
  3. package/build/plugins/pi/akuma-tools.ts +310 -0
  4. package/build/plugins/pi/keiyaku.ts +2 -0
  5. package/build/src/akuma/akuma-call.d.ts +4 -1
  6. package/build/src/akuma/akuma-call.js +24 -7
  7. package/build/src/akuma/akuma-instance.d.ts +28 -8
  8. package/build/src/akuma/akuma-instance.js +85 -42
  9. package/build/src/akuma/akuma-owner.d.ts +18 -9
  10. package/build/src/akuma/akuma-owner.js +31 -25
  11. package/build/src/akuma/akuma-selection-execution.d.ts +4 -1
  12. package/build/src/akuma/akuma-selection-execution.js +8 -4
  13. package/build/src/akuma/akuma.d.ts +17 -0
  14. package/build/src/akuma/body-launch.d.ts +107 -0
  15. package/build/src/akuma/body-launch.js +57 -0
  16. package/build/src/akuma/body-supervisor.d.ts +7 -6
  17. package/build/src/akuma/body-supervisor.js +17 -12
  18. package/build/src/akuma/body.d.ts +13 -94
  19. package/build/src/akuma/body.js +124 -296
  20. package/build/src/akuma/call-input.d.ts +2 -0
  21. package/build/src/akuma/call-input.js +21 -1
  22. package/build/src/akuma/call-request.d.ts +6 -2
  23. package/build/src/akuma/call-request.js +9 -1
  24. package/build/src/akuma/detached-body.d.ts +9 -0
  25. package/build/src/akuma/detached-body.js +94 -0
  26. package/build/src/akuma/execution-instructions.d.ts +8 -0
  27. package/build/src/akuma/execution-instructions.js +17 -0
  28. package/build/src/akuma/heart/facts.d.ts +21 -1
  29. package/build/src/akuma/heart/facts.js +10 -0
  30. package/build/src/akuma/heart/index.d.ts +16 -1
  31. package/build/src/akuma/heart/index.js +95 -30
  32. package/build/src/akuma/heart/rows.d.ts +14 -2
  33. package/build/src/akuma/heart/rows.js +48 -4
  34. package/build/src/akuma/heart/schema.d.ts +4 -1
  35. package/build/src/akuma/heart/schema.js +87 -30
  36. package/build/src/akuma/heart/soul.js +4 -0
  37. package/build/src/akuma/heart/storage.d.ts +1 -0
  38. package/build/src/akuma/heart/storage.js +59 -15
  39. package/build/src/akuma/heart/timeline.d.ts +6 -4
  40. package/build/src/akuma/heart/timeline.js +14 -4
  41. package/build/src/akuma/in-process-body.d.ts +5 -0
  42. package/build/src/akuma/in-process-body.js +57 -0
  43. package/build/src/akuma/index.d.ts +1 -1
  44. package/build/src/akuma/projection.d.ts +44 -1
  45. package/build/src/akuma/projection.js +13 -1
  46. package/build/src/akuma/provider.d.ts +4 -0
  47. package/build/src/akuma/providers/acp/core.js +1 -1
  48. package/build/src/akuma/providers/acp/index.js +3 -0
  49. package/build/src/akuma/providers/claude/index.js +8 -5
  50. package/build/src/akuma/providers/codex-app-server/configuration.d.ts +5 -0
  51. package/build/src/akuma/providers/codex-app-server/configuration.js +72 -0
  52. package/build/src/akuma/providers/codex-app-server/index.js +7 -10
  53. package/build/src/akuma/providers/execution-environment.d.ts +8 -2
  54. package/build/src/akuma/providers/execution-environment.js +10 -1
  55. package/build/src/akuma/providers/grok-build/index.js +23 -16
  56. package/build/src/akuma/providers/index.d.ts +1 -0
  57. package/build/src/akuma/providers/index.js +8 -0
  58. package/build/src/akuma/providers/opencode-sdk/index.js +9 -0
  59. package/build/src/akuma/providers/opencode-sdk/session.d.ts +6 -0
  60. package/build/src/akuma/providers/opencode-sdk/session.js +4 -3
  61. package/build/src/akuma/providers/paseo/index.js +8 -2
  62. package/build/src/akuma/providers/pi/index.js +27 -10
  63. package/build/src/akuma/publication.d.ts +4 -3
  64. package/build/src/akuma/publication.js +21 -18
  65. package/build/src/akuma/selection-observation.d.ts +51 -0
  66. package/build/src/akuma/selection-owner-port.d.ts +2 -1
  67. package/build/src/akuma/selection-owner-port.js +4 -3
  68. package/build/src/akuma/turn-drive.d.ts +4 -2
  69. package/build/src/akuma/turn-drive.js +58 -21
  70. package/build/src/akuma-body.d.ts +0 -10
  71. package/build/src/akuma-body.js +13 -118
  72. package/build/src/body-host.d.ts +28 -0
  73. package/build/src/body-host.js +86 -0
  74. package/build/src/body-requests.d.ts +13 -0
  75. package/build/src/body-requests.js +131 -0
  76. package/build/src/cli/commands/akuma-grammar.d.ts +8 -1
  77. package/build/src/cli/commands/akuma-grammar.js +36 -6
  78. package/build/src/cli/commands/akuma.js +11 -0
  79. package/build/src/cli/commands/report.d.ts +6 -0
  80. package/build/src/cli/commands/report.js +31 -0
  81. package/build/src/cli/parse.js +1 -0
  82. package/build/src/cli/render/akuma-activity.js +27 -17
  83. package/build/src/cli/render/terminal.d.ts +5 -0
  84. package/build/src/cli/render/terminal.js +7 -0
  85. package/build/src/cli/runtime.js +4 -1
  86. package/build/src/index.d.ts +3 -1
  87. package/build/src/index.js +1 -0
  88. package/build/src/library/akuma-creation.d.ts +7 -3
  89. package/build/src/library/akuma-creation.js +23 -11
  90. package/build/src/library/akumas.d.ts +4 -1
  91. package/build/src/library/akumas.js +13 -5
  92. package/build/src/library/selection.d.ts +2 -1
  93. package/build/src/library/selection.js +6 -3
  94. package/build/src/plugin/public.d.ts +11 -0
  95. package/build/src/plugin/runtime.js +1 -0
  96. package/build/src/runtime/proc/windows-launch.exe +0 -0
  97. package/package.json +2 -2
  98. package/plugins/paseo/plugin/server/keiyaku.ts +1 -0
  99. package/plugins/paseo/plugin/server/mirror.ts +2 -2
  100. package/plugins/pi/README.md +111 -0
  101. package/plugins/pi/akuma-tools.ts +310 -0
  102. package/plugins/pi/keiyaku.ts +2 -0
@@ -1,24 +1,15 @@
1
- import { outcomePluginObserver, stderrPluginDiagnostic, withAkumaWaitDeferrals } from "../plugin/akuma-signals.js";
1
+ import { emitPluginSignal, outcomePluginObserver, stderrPluginDiagnostic, withAkumaWaitDeferrals, } from "../plugin/akuma-signals.js";
2
2
  import { abortable } from "./abort.js";
3
3
  import { admitAkumaCall } from "./akuma-call.js";
4
4
  import { defaultWaitComplete } from "./akuma-observe.js";
5
5
  import { AkumaOwner } from "./akuma-owner.js";
6
6
  import { decodeAskObservation, executeAskAkuma, executeTellAkuma } from "./akuma-selection-execution.js";
7
+ import { captureAkumaHost } from "../body-host.js";
7
8
  import { parseAkuId } from "./identity.js";
8
9
  import { schemaFromStandard, schemaJsonText } from "./schema.js";
9
10
  /** Capture the observer capability, not the caller's mutable options object. */
10
11
  export function captureAkumaHostDiagnostic(host) {
11
- if (host === undefined)
12
- return undefined;
13
- if (typeof host !== "object" || host === null || Array.isArray(host))
14
- throw new TypeError("Akuma host options must be an object");
15
- const unknown = Object.keys(host).find((key) => key !== "reportDiagnostic");
16
- if (unknown !== undefined)
17
- throw new TypeError(`Akuma host options has unknown field: ${unknown}`);
18
- const reportDiagnostic = host.reportDiagnostic;
19
- if (reportDiagnostic !== undefined && typeof reportDiagnostic !== "function")
20
- throw new TypeError("Akuma host reportDiagnostic must be a function");
21
- return reportDiagnostic;
12
+ return captureAkumaHost(host).reportDiagnostic;
22
13
  }
23
14
  function signalOption(value) {
24
15
  if (value === undefined)
@@ -27,46 +18,21 @@ function signalOption(value) {
27
18
  throw new TypeError("signal must be an AbortSignal");
28
19
  return value;
29
20
  }
30
- export class Akuma {
21
+ class AkumaHandle {
31
22
  id;
32
23
  root;
33
24
  reportDiagnostic;
34
- constructor(id, root, reportDiagnostic) {
25
+ spawn;
26
+ constructor(id, root, reportDiagnostic, spawn) {
35
27
  this.id = id;
36
28
  this.root = root;
37
29
  this.reportDiagnostic = reportDiagnostic;
30
+ this.spawn = spawn;
38
31
  Object.freeze(this);
39
32
  }
40
33
  owner(observing = false) {
41
34
  return new AkumaOwner(this.id, this.root, observing ? outcomePluginObserver({ world: this.root, reportDiagnostic: this.reportDiagnostic }) : undefined);
42
35
  }
43
- static async birth(archetype, input) {
44
- if (typeof input !== "object" || input === null || Array.isArray(input)) {
45
- throw new TypeError("Akuma birth input must be an object");
46
- }
47
- if (typeof input.root !== "string")
48
- throw new TypeError("Akuma birth root must be a WorldRoot");
49
- const reportDiagnostic = captureAkumaHostDiagnostic(input.host) ?? stderrPluginDiagnostic;
50
- const admitted = await admitAkumaCall(input.root, {
51
- ...(input.home === undefined ? {} : { home: input.home }),
52
- ...(input.settings === undefined ? {} : { settings: input.settings }),
53
- }, {
54
- archetype,
55
- ...(input.cwd === undefined ? {} : { cwd: input.cwd }),
56
- ...(input.allowed === undefined ? {} : { allowed: input.allowed }),
57
- ...(input.caller === undefined ? {} : { caller: input.caller }),
58
- ...(input.initiator === undefined ? {} : { initiator: input.initiator }),
59
- }, {});
60
- if (admitted.failure !== undefined)
61
- throw admitted.failure;
62
- return new Akuma(admitted.id, input.root, reportDiagnostic);
63
- }
64
- static select(root, selector, host) {
65
- if (typeof root !== "string")
66
- throw new TypeError("Akuma.select root must be a WorldRoot");
67
- const reportDiagnostic = captureAkumaHostDiagnostic(host) ?? stderrPluginDiagnostic;
68
- return new Akuma(parseAkuId(selector).id, root, reportDiagnostic);
69
- }
70
36
  async tell(text, options = {}) {
71
37
  if (typeof text !== "string")
72
38
  throw new TypeError("Akuma tell text must be a string");
@@ -80,6 +46,7 @@ export class Akuma {
80
46
  const signal = signalOption(options.signal);
81
47
  signal?.throwIfAborted();
82
48
  return await executeTellAkuma({
49
+ spawn: this.spawn,
83
50
  path: this.root,
84
51
  id: this.id,
85
52
  body: text,
@@ -103,6 +70,7 @@ export class Akuma {
103
70
  signal?.throwIfAborted();
104
71
  const schema = options.schema === undefined ? undefined : schemaFromStandard(options.schema);
105
72
  const result = await executeAskAkuma({
73
+ spawn: this.spawn,
106
74
  path: this.root,
107
75
  id: this.id,
108
76
  outcomeObserved: outcomePluginObserver({ world: this.root, reportDiagnostic: this.reportDiagnostic }),
@@ -115,6 +83,40 @@ export class Akuma {
115
83
  });
116
84
  return (schema === undefined ? result : { ...result, observation: decodeAskObservation(result.observation, schema) });
117
85
  }
86
+ async report(text, options) {
87
+ if (typeof text !== "string" || text.trim() === "")
88
+ throw new TypeError("Akuma report text must be nonblank");
89
+ if (typeof options !== "object" || options === null || Array.isArray(options))
90
+ throw new TypeError("Akuma report requires exact execution options");
91
+ const unknown = Object.keys(options).find((key) => !["bodySequence", "turnSequence", "signal"].includes(key));
92
+ if (unknown !== undefined)
93
+ throw new TypeError(`Akuma report options has unknown field: ${unknown}`);
94
+ for (const key of ["bodySequence", "turnSequence"]) {
95
+ if (!Number.isSafeInteger(options[key]) || options[key] <= 0)
96
+ throw new TypeError(`Akuma report ${key} must be a positive safe integer`);
97
+ }
98
+ const signal = signalOption(options.signal);
99
+ const result = await this.owner().report({
100
+ bodySequence: options.bodySequence,
101
+ turnSequence: options.turnSequence,
102
+ text,
103
+ at: new Date().toISOString(),
104
+ }, signal);
105
+ if (result.kind !== "recorded")
106
+ return result;
107
+ const { report, initiator } = result;
108
+ await emitPluginSignal({ world: this.root, reportDiagnostic: this.reportDiagnostic }, {
109
+ kind: "akuma.reported",
110
+ akumaId: this.id,
111
+ bodySequence: report.bodySequence,
112
+ turnSequence: report.turnSequence,
113
+ reportSequence: report.sequence,
114
+ text: report.text,
115
+ at: report.at,
116
+ ...(initiator === undefined ? {} : { initiator }),
117
+ });
118
+ return { kind: "recorded", report };
119
+ }
118
120
  async status() {
119
121
  return await this.owner(true).status();
120
122
  }
@@ -169,6 +171,47 @@ export class Akuma {
169
171
  }
170
172
  const signal = signalOption(options.signal);
171
173
  signal?.throwIfAborted();
172
- return await abortable(this.owner().kill(signal === undefined ? {} : { signal }), signal ?? new AbortController().signal);
174
+ return await abortable(this.owner().kill(this.spawn, signal === undefined ? {} : { signal }), signal ?? new AbortController().signal);
175
+ }
176
+ }
177
+ export class Akuma extends AkumaHandle {
178
+ constructor(id, root, reportDiagnostic, spawn) {
179
+ super(id, root, reportDiagnostic, spawn);
173
180
  }
181
+ static async birth(archetype, input) {
182
+ if (typeof input !== "object" || input === null || Array.isArray(input)) {
183
+ throw new TypeError("Akuma birth input must be an object");
184
+ }
185
+ if (typeof input.root !== "string")
186
+ throw new TypeError("Akuma birth root must be a WorldRoot");
187
+ const { spawn, reportDiagnostic = stderrPluginDiagnostic } = captureAkumaHost(input.host);
188
+ const admitted = await admitAkumaCall(input.root, {
189
+ ...(input.home === undefined ? {} : { home: input.home }),
190
+ ...(input.settings === undefined ? {} : { settings: input.settings }),
191
+ }, {
192
+ archetype,
193
+ ...(input.cwd === undefined ? {} : { cwd: input.cwd }),
194
+ ...(input.allowed === undefined ? {} : { allowed: input.allowed }),
195
+ ...(input.writableDirectories === undefined ? {} : { writableDirectories: input.writableDirectories }),
196
+ ...(input.bare === undefined ? {} : { bare: input.bare }),
197
+ ...(input.caller === undefined ? {} : { caller: input.caller }),
198
+ ...(input.initiator === undefined ? {} : { initiator: input.initiator }),
199
+ }, {}, spawn);
200
+ if (admitted.failure !== undefined)
201
+ throw admitted.failure;
202
+ return new Akuma(admitted.id, input.root, reportDiagnostic, spawn);
203
+ }
204
+ static select(root, selector, host) {
205
+ if (typeof root !== "string")
206
+ throw new TypeError("Akuma.select root must be a WorldRoot");
207
+ const { spawn, reportDiagnostic = stderrPluginDiagnostic } = captureAkumaHost(host);
208
+ return new Akuma(parseAkuId(selector).id, root, reportDiagnostic, spawn);
209
+ }
210
+ }
211
+ /** Internal product composition; hosting is captured independently of public operation inputs. */
212
+ export function akumaWithLauncher(root, selector, spawn, host) {
213
+ if (typeof root !== "string")
214
+ throw new TypeError("Akuma.select root must be a WorldRoot");
215
+ const reportDiagnostic = captureAkumaHostDiagnostic(host) ?? stderrPluginDiagnostic;
216
+ return new AkumaHandle(parseAkuId(selector).id, root, reportDiagnostic, spawn);
174
217
  }
@@ -3,10 +3,12 @@ import type { WorldRoot } from "../world.js";
3
3
  import { type OutcomeObserver, type LiveStatusObservation, type WaitReason } from "./akuma-observe.js";
4
4
  import { type AkumaStreamSnapshot } from "./akuma-stream.js";
5
5
  import type { AkumaStatus } from "./akuma.js";
6
+ import type { BodyLauncher } from "./body-launch.js";
6
7
  import { type TellResult, type TellWakeRuntime } from "./body.js";
7
8
  import { type CallInitialTell, type CallInitialTellAdmission } from "./call-initial-tell.js";
8
9
  import { HeldAkumaLeash, type InterruptTellAdmission, type KillEvidence, type ResumeCoordinate, type TellFact, type TurnOutcome } from "./heart/index.js";
9
10
  import { type AkuId, type AkumaPaths } from "./identity.js";
11
+ import type { ReportAdmission } from "./heart/facts.js";
10
12
  import type { ActivityHistory, ExactHistory } from "./projection.js";
11
13
  export type InterruptReceipt = TellResult | Extract<InterruptTellAdmission, {
12
14
  kind: "unavailable";
@@ -68,6 +70,12 @@ export declare class AkumaOwner {
68
70
  private get paths();
69
71
  private projectHistoryTurns;
70
72
  private exactHistory;
73
+ report(input: Readonly<{
74
+ bodySequence: number;
75
+ turnSequence: number;
76
+ text: string;
77
+ at: string;
78
+ }>, signal?: AbortSignal): Promise<ReportAdmission>;
71
79
  status(): Promise<AkumaStatus>;
72
80
  history(input?: Readonly<{
73
81
  id?: string;
@@ -94,11 +102,11 @@ export declare class AkumaOwner {
94
102
  timeoutMs?: number;
95
103
  signal?: AbortSignal;
96
104
  }>): Promise<AkumaStatus>;
97
- admitInitialTell(initialTell: CallInitialTell, options?: Readonly<{
105
+ admitInitialTell(initialTell: CallInitialTell, options: Readonly<{
98
106
  signal?: AbortSignal;
99
- runtime?: TellWakeRuntime;
107
+ runtime: TellWakeRuntime;
100
108
  }>): Promise<InitialTellAdmission>;
101
- tell(body: string, tellId?: string, recordedAt?: string, runtime?: TellWakeRuntime, options?: Readonly<{
109
+ tell(body: string, tellId: string | undefined, recordedAt: string | undefined, runtime: TellWakeRuntime, options?: Readonly<{
102
110
  schemaJson?: string;
103
111
  initiator?: string;
104
112
  signal?: AbortSignal;
@@ -108,7 +116,7 @@ export declare class AkumaOwner {
108
116
  * caller starts its own deadline at this admission boundary while the wake
109
117
  * continues in the background; the unbounded public Tell awaits `wake`.
110
118
  */
111
- admitTell(body: string, tellId?: string, recordedAt?: string, runtime?: TellWakeRuntime, options?: Readonly<{
119
+ admitTell(body: string, tellId: string | undefined, recordedAt: string | undefined, runtime: TellWakeRuntime, options?: Readonly<{
112
120
  schemaJson?: string;
113
121
  initiator?: string;
114
122
  signal?: AbortSignal;
@@ -130,13 +138,13 @@ export declare class AkumaOwner {
130
138
  outcome: TurnOutcome | null;
131
139
  completedAt: string | null;
132
140
  }>>;
133
- interrupt(body: string, options?: Readonly<{
141
+ interrupt(body: string, options: Readonly<{
134
142
  tellId?: string;
135
143
  recordedAt?: string;
136
144
  schemaJson?: string;
137
145
  initiator?: string;
138
146
  signal?: AbortSignal;
139
- runtime?: TellWakeRuntime;
147
+ runtime: TellWakeRuntime;
140
148
  }>): Promise<InterruptReceipt>;
141
149
  /** Atomic Tell-plus-barrier admission; no leash wait or completion observation occurs here. */
142
150
  admitInterrupt(body: string, options?: Readonly<{
@@ -149,13 +157,14 @@ export declare class AkumaOwner {
149
157
  /** Complete only the exact admitted predecessor barrier, then wake the stable Tell. */
150
158
  completeInterruptAdmission(admission: Extract<InterruptAdmission, {
151
159
  kind: "admitted";
152
- }>, runtime?: TellWakeRuntime, signal?: AbortSignal): Promise<TellResult>;
160
+ }>, runtime: TellWakeRuntime, signal?: AbortSignal): Promise<TellResult>;
153
161
  fork(input: Readonly<{
154
162
  at: string;
163
+ bare?: boolean;
155
164
  caller?: AkumaCaller;
156
165
  initiator?: string;
157
- }>): Promise<ForkReceipt>;
158
- kill(options?: Readonly<{
166
+ }>, spawn: BodyLauncher): Promise<ForkReceipt>;
167
+ kill(spawn: BodyLauncher, options?: Readonly<{
159
168
  signal?: AbortSignal;
160
169
  }>): Promise<KillEvidence>;
161
170
  lastAnswer(): Promise<LastAnswer>;
@@ -1,13 +1,14 @@
1
+ import { bareOption } from "./call-input.js";
1
2
  import { decodeAkumaCaller } from "./caller.js";
2
3
  import { randomUUID } from "node:crypto";
3
4
  import { AkumaNotBornError, AkumaProviderError } from "./akuma-errors.js";
4
5
  import { createLiveStatusReader, bornStatus, defaultWaitComplete, executionProgress, observeOutcomeRows, observeStatusOutcome, waitForObservation, } from "./akuma-observe.js";
5
6
  import { executeWaitAkuma } from "./akuma-wait.js";
6
7
  import { createAkumaStream } from "./akuma-stream.js";
7
- import { handoffPendingTells, spawnAkumaBody, wakeRecordedTell, } from "./body.js";
8
+ import { handoffPendingTells, wakeRecordedTell } from "./body.js";
8
9
  import { admitCallInitialTell } from "./call-initial-tell.js";
9
10
  import { acquireLeash } from "./control.js";
10
- import { activitySlice, projectTell, readForkPoint, readHeart, readInterruptCompletion, readKill, readLastAnsweredTurn, readSoul, readTell, recordTell, requestStop, } from "./heart/index.js";
11
+ import { activitySlice, projectTell, readForkPoint, readHeart, readInterruptCompletion, readKill, readLastAnsweredTurn, readSoul, readTell, recordReport, recordTell, requestStop, } from "./heart/index.js";
11
12
  import { parsePublicHistoryId, pathsForAkuId } from "./identity.js";
12
13
  import { projectTurns, selectExactHistory, selectHistory } from "./projection.js";
13
14
  import { resolveProviderExecution } from "./providers/index.js";
@@ -73,6 +74,8 @@ export async function settleAkumaKill(paths, signal, retainLeash = false) {
73
74
  if (settledBody?.sequence !== target.sequence) {
74
75
  return { evidence: (await readKill(paths, target.sequence)) === null ? "unavailable" : "killed" };
75
76
  }
77
+ if (settledBody.hung !== undefined)
78
+ return { evidence: "hung" };
76
79
  if (settledBody.end !== "put-down") {
77
80
  await leash.clearStop(paths);
78
81
  return { evidence: "untidy" };
@@ -128,6 +131,9 @@ export class AkumaOwner {
128
131
  throw new TypeError("Akuma history id must match turn/<positive safe integer>");
129
132
  return selectExactHistory((await this.projectHistoryTurns()).rows, input.id);
130
133
  }
134
+ async report(input, signal) {
135
+ return await recordReport(this.paths, input, signal);
136
+ }
131
137
  async status() {
132
138
  const { status } = await bornStatus(this.paths, this.id, { aperture: "monitoring" });
133
139
  await observeStatusOutcome(status, this.outcomeObserved);
@@ -190,7 +196,7 @@ export class AkumaOwner {
190
196
  async wait(predicate = defaultWaitComplete, options = {}) {
191
197
  return (await this.waitReceipt(predicate, options)).status;
192
198
  }
193
- async admitInitialTell(initialTell, options = {}) {
199
+ async admitInitialTell(initialTell, options) {
194
200
  return await admitCallInitialTell({
195
201
  world: this.worldPath,
196
202
  id: this.id,
@@ -284,7 +290,7 @@ export class AkumaOwner {
284
290
  reader.clear();
285
291
  }
286
292
  }
287
- async interrupt(body, options = {}) {
293
+ async interrupt(body, options) {
288
294
  const admitted = await this.admitInterrupt(body, options);
289
295
  if (admitted.kind === "unavailable")
290
296
  return admitted;
@@ -332,7 +338,8 @@ export class AkumaOwner {
332
338
  },
333
339
  };
334
340
  }
335
- async fork(input) {
341
+ async fork(input, spawn) {
342
+ const bare = bareOption(input.bare);
336
343
  const caller = decodeAkumaCaller(input.caller);
337
344
  const source = await readSoul(this.paths);
338
345
  if (source === null)
@@ -369,24 +376,23 @@ export class AkumaOwner {
369
376
  worldPath: this.worldPath,
370
377
  archetype: source.archetype,
371
378
  awaitAsleep: true,
372
- launch: async (allocated) => {
373
- return await spawnAkumaBody({
374
- paths: allocated.paths,
375
- seed: {
376
- id: allocated.id,
377
- archetype: source.archetype,
378
- ...(source.description === undefined ? {} : { description: source.description }),
379
- provider: source.provider,
380
- options: source.options,
381
- allowed: source.allowed,
382
- cwd: source.cwd,
383
- origin: { kind: "fork", parent: this.id, at: input.at },
384
- ...(caller === undefined ? {} : { caller }),
385
- },
386
- birthSession,
387
- ...(input.initiator === undefined ? {} : { birthInitiator: input.initiator }),
388
- });
389
- },
379
+ launch: async (allocated) => await spawn({
380
+ paths: allocated.paths,
381
+ seed: {
382
+ id: allocated.id,
383
+ archetype: source.archetype,
384
+ ...(source.description === undefined ? {} : { description: source.description }),
385
+ provider: source.provider,
386
+ options: source.options,
387
+ allowed: source.allowed,
388
+ bare: source.bare === true || bare === true,
389
+ cwd: source.cwd,
390
+ origin: { kind: "fork", parent: this.id, at: input.at },
391
+ ...(caller === undefined ? {} : { caller }),
392
+ },
393
+ birthSession,
394
+ ...(input.initiator === undefined ? {} : { birthInitiator: input.initiator }),
395
+ }),
390
396
  });
391
397
  return { kind: "forked", child: child.id };
392
398
  }
@@ -398,8 +404,8 @@ export class AkumaOwner {
398
404
  };
399
405
  }
400
406
  }
401
- async kill(options = {}) {
402
- return await killAkumaWithRecovery(this.paths, handoffPendingTells, options.signal);
407
+ async kill(spawn, options = {}) {
408
+ return await killAkumaWithRecovery(this.paths, (paths) => handoffPendingTells(paths, spawn), options.signal);
403
409
  }
404
410
  async lastAnswer() {
405
411
  const turn = await readLastAnsweredTurn(this.paths);
@@ -1,7 +1,8 @@
1
1
  import type { WorldRoot } from "../world.js";
2
2
  import type { LiveStatusObservation, OutcomeObserver } from "./akuma-observe.js";
3
3
  import type { AkumaStatus } from "./akuma.js";
4
- import type { TellResult } from "./body.js";
4
+ import { type TellResult } from "./body.js";
5
+ import type { BodyLauncher } from "./body-launch.js";
5
6
  import type { Schema } from "./schema.js";
6
7
  import type { AkumaAskObservation, AkumaAskResult, AkumaKillResult, AkumaTellResult } from "./selection-observation.js";
7
8
  export type AskObserver = Readonly<{
@@ -9,6 +10,7 @@ export type AskObserver = Readonly<{
9
10
  observe?: (observation: LiveStatusObservation) => void | Promise<void>;
10
11
  }>;
11
12
  type TellExecutionInput = Readonly<{
13
+ spawn: BodyLauncher;
12
14
  path: WorldRoot;
13
15
  id: AkumaStatus["id"];
14
16
  body: string;
@@ -46,6 +48,7 @@ export declare function observeAdmittedAskAkuma(input: Readonly<{
46
48
  }>): Promise<AkumaAskResult>;
47
49
  export declare function executeAskAkuma(input: AskExecutionInput): Promise<AkumaAskResult>;
48
50
  type KillExecutionInput = Readonly<{
51
+ spawn: BodyLauncher;
49
52
  path: WorldRoot;
50
53
  ids: readonly AkumaStatus["id"][];
51
54
  signal?: AbortSignal;
@@ -1,11 +1,13 @@
1
1
  import { AkumaNotBornError, AkumaProviderError } from "./akuma-errors.js";
2
2
  import { AkumaOwner } from "./akuma-owner.js";
3
+ import { tellWakeRuntime } from "./body.js";
3
4
  export async function executeTellAkuma(input) {
4
5
  input.signal?.throwIfAborted();
5
6
  const owner = new AkumaOwner(input.id, input.path);
6
7
  let tell;
7
8
  if (input.interrupt === true) {
8
9
  const interrupted = await owner.interrupt(input.body, {
10
+ runtime: tellWakeRuntime(input.spawn),
9
11
  ...(input.tellId === undefined ? {} : { tellId: input.tellId }),
10
12
  ...(input.recordedAt === undefined ? {} : { recordedAt: input.recordedAt }),
11
13
  ...(input.initiator === undefined ? {} : { initiator: input.initiator }),
@@ -16,7 +18,7 @@ export async function executeTellAkuma(input) {
16
18
  tell = interrupted;
17
19
  }
18
20
  else {
19
- tell = await owner.tell(input.body, input.tellId, input.recordedAt, undefined, {
21
+ tell = await owner.tell(input.body, input.tellId, input.recordedAt, tellWakeRuntime(input.spawn), {
20
22
  ...(input.initiator === undefined ? {} : { initiator: input.initiator }),
21
23
  ...(input.signal === undefined ? {} : { signal: input.signal }),
22
24
  });
@@ -27,6 +29,8 @@ export async function executeTellAkuma(input) {
27
29
  function askObservation(observed) {
28
30
  if (observed.outcome === null)
29
31
  return observed.reason === "deadline" ? { reason: "deadline" } : { reason: "unanswered" };
32
+ if (observed.outcome.kind === "canceled")
33
+ return { reason: "unanswered" };
30
34
  if (observed.outcome.kind === "answered")
31
35
  return { reason: "answered", answer: observed.outcome.answerJson ?? observed.outcome.answer };
32
36
  if (observed.outcome.kind === "failed")
@@ -120,7 +124,7 @@ async function executeInterruptAskAkuma(input, owner) {
120
124
  throw new AkumaProviderError(`Tell interrupt unavailable: ${admission.evidence}`);
121
125
  const observing = new AbortController();
122
126
  const signal = input.signal === undefined ? observing.signal : AbortSignal.any([input.signal, observing.signal]);
123
- const wake = owner.completeInterruptAdmission(admission, undefined, signal);
127
+ const wake = owner.completeInterruptAdmission(admission, tellWakeRuntime(input.spawn), signal);
124
128
  try {
125
129
  const receipt = admission.barrier === undefined
126
130
  ? undefined
@@ -152,7 +156,7 @@ export async function executeAskAkuma(input) {
152
156
  const owner = new AkumaOwner(input.id, input.path);
153
157
  if (input.interrupt === true)
154
158
  return await executeInterruptAskAkuma(input, owner);
155
- const admission = await owner.admitTell(input.body, input.tellId, input.recordedAt, undefined, {
159
+ const admission = await owner.admitTell(input.body, input.tellId, input.recordedAt, tellWakeRuntime(input.spawn), {
156
160
  ...(input.schemaJson === undefined ? {} : { schemaJson: input.schemaJson }),
157
161
  ...(input.initiator === undefined ? {} : { initiator: input.initiator }),
158
162
  ...(input.signal === undefined ? {} : { signal: input.signal }),
@@ -174,7 +178,7 @@ export async function executeAskAkuma(input) {
174
178
  export async function executeKillAkuma(input) {
175
179
  input.signal?.throwIfAborted();
176
180
  const owners = input.ids.map((id) => new AkumaOwner(id, input.path));
177
- const evidence = await Promise.all(owners.map(async (owner) => await owner.kill(input.signal === undefined ? {} : { signal: input.signal })));
181
+ const evidence = await Promise.all(owners.map(async (owner) => await owner.kill(input.spawn, input.signal === undefined ? {} : { signal: input.signal })));
178
182
  input.signal?.throwIfAborted();
179
183
  return {
180
184
  results: input.ids.map((id, index) => ({ id, evidence: evidence[index] })),
@@ -135,6 +135,13 @@ export declare const akumaStatusSchema: z.ZodObject<{
135
135
  }, z.core.$strict>, z.ZodObject<{
136
136
  kind: z.ZodLiteral<"row">;
137
137
  row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
138
+ kind: z.ZodLiteral<"report">;
139
+ sequence: z.ZodNumber;
140
+ bodySequence: z.ZodNumber;
141
+ turnSequence: z.ZodNumber;
142
+ text: z.ZodString;
143
+ at: z.ZodString;
144
+ }, z.core.$strict>, z.ZodObject<{
138
145
  kind: z.ZodLiteral<"call">;
139
146
  sequence: z.ZodNumber;
140
147
  turnSequence: z.ZodNumber;
@@ -340,6 +347,9 @@ export declare const akumaStatusSchema: z.ZodObject<{
340
347
  kind: z.ZodLiteral<"failed">;
341
348
  historyId: z.ZodString;
342
349
  diagnostic: z.ZodString;
350
+ }, z.core.$strict>, z.ZodObject<{
351
+ kind: z.ZodLiteral<"canceled">;
352
+ historyId: z.ZodString;
343
353
  }, z.core.$strict>]>;
344
354
  }, z.core.$strict>>;
345
355
  entries: z.ZodReadonly<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
@@ -348,6 +358,13 @@ export declare const akumaStatusSchema: z.ZodObject<{
348
358
  }, z.core.$strict>, z.ZodObject<{
349
359
  kind: z.ZodLiteral<"row">;
350
360
  row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
361
+ kind: z.ZodLiteral<"report">;
362
+ sequence: z.ZodNumber;
363
+ bodySequence: z.ZodNumber;
364
+ turnSequence: z.ZodNumber;
365
+ text: z.ZodString;
366
+ at: z.ZodString;
367
+ }, z.core.$strict>, z.ZodObject<{
351
368
  kind: z.ZodLiteral<"call">;
352
369
  sequence: z.ZodNumber;
353
370
  turnSequence: z.ZodNumber;
@@ -0,0 +1,107 @@
1
+ import { z } from "zod";
2
+ import type { TellWake } from "./call-initial-tell.js";
3
+ export declare const bodyLaunchSchema: z.ZodObject<{
4
+ paths: z.ZodObject<{
5
+ directory: z.ZodString;
6
+ heart: z.ZodString;
7
+ leash: z.ZodString;
8
+ log: z.ZodString;
9
+ requests: z.ZodString;
10
+ }, z.core.$strict>;
11
+ seed: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodTransform<Omit<Readonly<{
12
+ id: import("./identity.js").AkuId;
13
+ archetype: string;
14
+ description?: string;
15
+ provider: import("./provider-recipe.js").ProviderExecution;
16
+ options: import("./provider-recipe.js").ProviderOptions;
17
+ cwd: string;
18
+ origin: import("./index.js").AkumaOrigin;
19
+ caller?: import("./caller.js").AkumaCaller;
20
+ allowed: import("./allowed.js").AllowedActions;
21
+ bare?: boolean;
22
+ createdAt: string;
23
+ }>, "createdAt">, unknown>>>;
24
+ birthSession: z.ZodOptional<z.ZodObject<{
25
+ provider: z.ZodString;
26
+ coordinate: z.ZodUnion<readonly [z.ZodPipe<z.ZodObject<{
27
+ sessionFile: z.ZodString;
28
+ sessionId: z.ZodOptional<z.ZodString>;
29
+ }, z.core.$strict>, z.ZodTransform<{
30
+ sessionFile: string;
31
+ sessionId?: never;
32
+ } | {
33
+ sessionFile: string;
34
+ sessionId: string;
35
+ }, {
36
+ sessionFile: string;
37
+ sessionId?: string | undefined;
38
+ }>>, z.ZodObject<{
39
+ sessionId: z.ZodString;
40
+ }, z.core.$strict>]>;
41
+ cwd: z.ZodString;
42
+ options: z.ZodPipe<z.ZodObject<{
43
+ model: z.ZodOptional<z.ZodString>;
44
+ effort: z.ZodOptional<z.ZodString>;
45
+ network: z.ZodOptional<z.ZodEnum<{
46
+ disabled: "disabled";
47
+ enabled: "enabled";
48
+ }>>;
49
+ systemPrompt: z.ZodOptional<z.ZodString>;
50
+ systemPromptMode: z.ZodOptional<z.ZodEnum<{
51
+ replace: "replace";
52
+ append: "append";
53
+ }>>;
54
+ }, z.core.$strip>, z.ZodTransform<Readonly<{
55
+ systemPromptMode?: "replace" | "append";
56
+ systemPrompt?: string;
57
+ network?: "disabled" | "enabled";
58
+ effort?: string;
59
+ model?: string;
60
+ }>, {
61
+ model?: string | undefined;
62
+ effort?: string | undefined;
63
+ network?: "disabled" | "enabled" | undefined;
64
+ systemPrompt?: string | undefined;
65
+ systemPromptMode?: "replace" | "append" | undefined;
66
+ }>>;
67
+ admittedAt: z.ZodString;
68
+ }, z.core.$strict>>;
69
+ initialBody: z.ZodOptional<z.ZodString>;
70
+ initiator: z.ZodOptional<z.ZodString>;
71
+ birthInitiator: z.ZodOptional<z.ZodString>;
72
+ initialSchemaJson: z.ZodOptional<z.ZodString>;
73
+ refuseIfHeld: z.ZodOptional<z.ZodBoolean>;
74
+ handoffFromBodySequence: z.ZodOptional<z.ZodNumber>;
75
+ completion: z.ZodOptional<z.ZodObject<{
76
+ contractId: z.ZodOptional<z.ZodString>;
77
+ }, z.core.$strict>>;
78
+ }, z.core.$strict>;
79
+ export type BodyLaunch = z.infer<typeof bodyLaunchSchema>;
80
+ /** Live launch evidence only; Heart and leash alone judge birth and settlement. */
81
+ export type BodyLaunchEnd = Readonly<{
82
+ diagnostic: string;
83
+ held?: boolean;
84
+ child?: Extract<TellWake, {
85
+ child: unknown;
86
+ }>["child"];
87
+ }>;
88
+ export type LiveBodyLaunch = Readonly<{
89
+ /** Launch completion evidence, never a product outcome or closure proof. */
90
+ completed: Promise<BodyLaunchEnd>;
91
+ /** Ask owned resources to retire; force requests supported disposal, not shared-host termination or rollback. */
92
+ cancel(force?: boolean): Promise<void>;
93
+ /** Relinquish this holder's custody, not kill or closure, with no guarantee of host survival. */
94
+ release(): void;
95
+ }>;
96
+ export type BodyLauncher = (launch: BodyLaunch) => Promise<LiveBodyLaunch>;
97
+ /** Observe durable custody first, including once more after live launch completion. */
98
+ export declare function observeBodyLaunch<T>(child: LiveBodyLaunch, observe: () => Promise<T | null>, schedule?: (milliseconds: number, signal: AbortSignal) => Promise<void>, signal?: AbortSignal): Promise<Readonly<{
99
+ kind: "observed";
100
+ value: T;
101
+ }> | Readonly<{
102
+ kind: "completed";
103
+ end: BodyLaunchEnd;
104
+ }>>;
105
+ export declare function launchEndWake(end: BodyLaunchEnd): Extract<TellWake, {
106
+ kind: "held" | "failed";
107
+ }>;