@astrosheep/keiyaku 4.6.19 → 4.6.21

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 +3 -3
  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
@@ -42,7 +42,7 @@ function piCreateOptions(sdk, input, services) {
42
42
  sdk.createBashToolDefinition(input.cwd, {
43
43
  spawnHook: (context) => ({
44
44
  ...context,
45
- env: akumaExecutionEnvironment(context.env, {}, input.requests.dir, ["PI_SESSION_ID", "PI_SESSION_FILE"]),
45
+ env: akumaExecutionEnvironment(context.env, {}, input.requests.dir, ["PI_SESSION_ID", "PI_SESSION_FILE"], input.execution),
46
46
  }),
47
47
  }),
48
48
  ];
@@ -58,17 +58,25 @@ async function createPiSession(sdk, execution, input) {
58
58
  if (execution.config !== undefined) {
59
59
  throw new TypeError("Pi provider config cannot be consumed by native CreateAgentSessionOptions");
60
60
  }
61
+ const personality = input.options.systemPrompt;
62
+ const append = [
63
+ ...(input.options.systemPromptMode === "append" && personality !== undefined ? [personality] : []),
64
+ ...(input.runtimeInstructions === undefined ? [] : [input.runtimeInstructions]),
65
+ ];
61
66
  const services = await sdk.createAgentSessionServices({
62
67
  cwd: input.cwd,
63
68
  agentDir: sdk.getAgentDir(),
64
69
  modelRuntimeSignal: input.signal,
65
- ...(input.options.systemPrompt === undefined
66
- ? {}
67
- : {
68
- resourceLoaderOptions: input.options.systemPromptMode === "append"
69
- ? { appendSystemPromptOverride: (base) => [...base, input.options.systemPrompt] }
70
- : { systemPromptOverride: () => input.options.systemPrompt },
71
- }),
70
+ // A positive restriction is applied after resource loading, before startup.
71
+ // If the optional shipped extension is absent Pi collects an unknown-option
72
+ // diagnostic; it is not a setup failure and must not disable other resources.
73
+ extensionFlagValues: new Map([["keiyaku-request-only", true]]),
74
+ resourceLoaderOptions: {
75
+ ...(personality === undefined || input.options.systemPromptMode === "append"
76
+ ? {}
77
+ : { systemPromptOverride: () => personality }),
78
+ appendSystemPromptOverride: (base) => [...base, ...append],
79
+ },
72
80
  });
73
81
  const extensionErrors = services.resourceLoader.getExtensions().errors ?? [];
74
82
  for (const failure of extensionErrors)
@@ -170,6 +178,7 @@ async function drivePi(sdk, execution, input, signal, custody) {
170
178
  let unsubscribeAgent;
171
179
  let unsubscribe;
172
180
  let binding;
181
+ let prompting;
173
182
  const settle = (result) => {
174
183
  if (state.settled)
175
184
  return closed;
@@ -200,6 +209,10 @@ async function drivePi(sdk, execution, input, signal, custody) {
200
209
  catch (error) {
201
210
  failure ??= error;
202
211
  }
212
+ // dispose() only requests abort. Owned tool/prompt work must actually
213
+ // finish before this attempt can certify retirement. The prompt callback
214
+ // initiates settlement without awaiting closed, so this cannot await itself.
215
+ await prompting;
203
216
  if (failure !== undefined)
204
217
  throw failure;
205
218
  })().then(settleRetired, failRetired);
@@ -258,8 +271,12 @@ async function drivePi(sdk, execution, input, signal, custody) {
258
271
  const sessionModel = piSessionModel(native.model);
259
272
  if (sessionModel !== undefined)
260
273
  events.emit(modelEvent(sessionModel));
261
- void runPiPrompt(native, input, eventState, state, (result) => {
262
- void settle(result).catch(() => undefined);
274
+ prompting = Promise.resolve().then(async () => {
275
+ if (signal.aborted || state.settled)
276
+ return;
277
+ await runPiPrompt(native, input, eventState, state, (result) => {
278
+ void settle(result).catch(() => undefined);
279
+ });
263
280
  });
264
281
  return {
265
282
  admission: { fence: native.sessionId },
@@ -1,7 +1,7 @@
1
1
  import { type AkumaCaller } from "./caller.js";
2
2
  import { type Soul } from "./heart/index.js";
3
3
  import { type AllocatedAkuma, type AkumaPaths, type AkuId } from "./identity.js";
4
- import type { OwnedProcess } from "../runtime/proc/run.js";
4
+ import type { LiveBodyLaunch } from "./body-launch.js";
5
5
  import type { RequestRecipe } from "./heart/facts.js";
6
6
  import type { CallInitialTell, CallInitialTellAdmission, TellResult } from "./call-initial-tell.js";
7
7
  import { type WorldRoot } from "../world.js";
@@ -14,7 +14,7 @@ export type BirthInput = Readonly<{
14
14
  export type LaunchInput = Readonly<{
15
15
  allocated: AllocatedAkuma;
16
16
  awaitAsleep?: boolean;
17
- launch(allocated: AllocatedAkuma): Promise<OwnedProcess | void>;
17
+ launch(allocated: AllocatedAkuma): Promise<LiveBodyLaunch | void>;
18
18
  signal?: AbortSignal;
19
19
  }>;
20
20
  export declare function publishAkuma(input: BirthInput & Omit<LaunchInput, "allocated">): Promise<AllocatedAkuma>;
@@ -46,7 +46,7 @@ export type PreparedCallInitialTellAdmission = Readonly<{
46
46
  }>;
47
47
  type PreparedCallPorts = Readonly<{
48
48
  /** Spawn one already-allocated child; publication already owns the allocated directory. */
49
- spawn(launch: PreparedCallSpawn): Promise<OwnedProcess | void>;
49
+ spawn(launch: PreparedCallSpawn): Promise<LiveBodyLaunch | void>;
50
50
  /** Admit the optional initial Tell against the just-confirmed child. */
51
51
  admitInitialTell(input: PreparedCallInitialTellAdmission): Promise<CallInitialTellAdmission>;
52
52
  }>;
@@ -82,6 +82,7 @@ type PreparedCallResult = Readonly<{
82
82
  type PreparedCallInput = Readonly<{
83
83
  archetype: string;
84
84
  cwd: string;
85
+ writableDirectories?: readonly string[];
85
86
  caller?: AkumaCaller;
86
87
  initialTell?: CallInitialTell;
87
88
  signal?: AbortSignal;
@@ -4,11 +4,14 @@ import { acquireLeash } from "./control.js";
4
4
  import { allocateAkumaDirectory } from "./identity.js";
5
5
  import { abortableDelay } from "./abort.js";
6
6
  import { clipAllowedActions } from "./allowed.js";
7
- import { resolveProviderExecution } from "./providers/index.js";
7
+ import { resolveProviderExecution, withWritableDirectories } from "./providers/index.js";
8
+ import { writableDirectoriesOption } from "./call-input.js";
8
9
  import { World } from "../world.js";
9
10
  const POLL_MS = 100;
10
11
  const CUSTODY_HANDOFF_MS = 1_000;
11
12
  export const BIRTH_TIMEOUT_MS = 30_000;
13
+ class LaunchCompletedError extends Error {
14
+ }
12
15
  function diagnostic(error) {
13
16
  return error instanceof Error ? error.message : String(error);
14
17
  }
@@ -46,15 +49,12 @@ async function observedBirthFailure(paths) {
46
49
  leash.release();
47
50
  }
48
51
  }
49
- function preAdmissionDiagnostic(exit) {
50
- return exit.code === null ? `pre-admission signal ${exit.signal ?? "unknown"}` : `pre-admission exit ${exit.code}`;
51
- }
52
52
  async function observeSettledExit(owned) {
53
53
  if (owned === undefined)
54
54
  return { kind: "pending" };
55
55
  const pending = Symbol("pending");
56
56
  try {
57
- const exit = await Promise.race([owned.exited, Promise.resolve(pending)]);
57
+ const exit = await Promise.race([owned.completed, Promise.resolve(pending)]);
58
58
  return exit === pending ? { kind: "pending" } : { kind: "exited", exit };
59
59
  }
60
60
  catch (error) {
@@ -63,14 +63,14 @@ async function observeSettledExit(owned) {
63
63
  }
64
64
  async function observeExitWithin(owned, milliseconds) {
65
65
  return await Promise.race([
66
- owned.exited.then((exit) => ({ kind: "exited", exit }), (error) => ({ kind: "exit-error", error })),
66
+ owned.completed.then((exit) => ({ kind: "exited", exit }), (error) => ({ kind: "exit-error", error })),
67
67
  abortableDelay(milliseconds).then(() => ({ kind: "timeout" })),
68
68
  ]);
69
69
  }
70
70
  async function attemptTermination(owned, force = false) {
71
71
  const outcome = await Promise.race([
72
72
  Promise.resolve()
73
- .then(() => owned.terminate(force))
73
+ .then(() => owned.cancel(force))
74
74
  .then(() => ({ kind: "terminated" }), (error) => ({ kind: "error", error })),
75
75
  abortableDelay(CUSTODY_HANDOFF_MS).then(() => ({ kind: "timeout" })),
76
76
  ]);
@@ -87,7 +87,7 @@ async function awaitBirth(paths, owned, signal) {
87
87
  if (failure !== null) {
88
88
  const settled = await observeSettledExit(owned);
89
89
  if (settled.kind === "exited")
90
- throw new Error(preAdmissionDiagnostic(settled.exit));
90
+ throw new LaunchCompletedError(settled.exit.diagnostic);
91
91
  if (settled.kind === "exit-error")
92
92
  throw new Error(diagnostic(settled.error));
93
93
  throw new Error(failure);
@@ -106,7 +106,7 @@ async function awaitBirth(paths, owned, signal) {
106
106
  }
107
107
  const outcome = await Promise.race([
108
108
  abortableDelay(Math.min(POLL_MS, Math.max(0, deadline - performance.now())), signal).then(() => "poll"),
109
- owned.exited.then((exit) => ({ kind: "exited", exit }), (error) => ({ kind: "exit-error", error })),
109
+ owned.completed.then((exit) => ({ kind: "exited", exit }), (error) => ({ kind: "exit-error", error })),
110
110
  ]);
111
111
  if (outcome === "poll")
112
112
  continue;
@@ -114,7 +114,7 @@ async function awaitBirth(paths, owned, signal) {
114
114
  const settledSoul = await readSoul(paths);
115
115
  if (settledSoul !== null)
116
116
  return settledSoul;
117
- throw new Error(preAdmissionDiagnostic(outcome.exit));
117
+ throw new LaunchCompletedError(outcome.exit.diagnostic);
118
118
  }
119
119
  throw new Error(diagnostic(outcome.error));
120
120
  }
@@ -154,8 +154,7 @@ async function settleLaunch(allocated, owned, failure) {
154
154
  let terminationError;
155
155
  let exitError;
156
156
  let outcome;
157
- const preAdmissionExit = diagnostic(failure).startsWith("pre-admission ");
158
- const settled = preAdmissionExit ? await observeSettledExit(owned) : { kind: "pending" };
157
+ const settled = failure instanceof LaunchCompletedError ? await observeSettledExit(owned) : { kind: "pending" };
159
158
  if (settled.kind !== "exited") {
160
159
  terminationError = await attemptTermination(owned);
161
160
  const exit = await observeSettledExit(owned);
@@ -163,7 +162,7 @@ async function settleLaunch(allocated, owned, failure) {
163
162
  exitError = exit.error;
164
163
  }
165
164
  else {
166
- /* An already-settled pre-admission exit needs no second termination request. */
165
+ /* An already-observed launch completion needs no second cancellation request. */
167
166
  }
168
167
  if ((await readSoul(allocated.paths)) !== null) {
169
168
  await allocatedSoul(allocated);
@@ -300,10 +299,12 @@ export function callDiagnostic(error) {
300
299
  * decoded execution to its adapter, admit the raw options once, and clip the
301
300
  * requested actions only when a parent ceiling applies.
302
301
  */
303
- async function admittedRecipe(recipe, bounds = {}) {
302
+ async function admittedRecipe(recipe, input, bounds = {}) {
304
303
  let selected;
305
304
  try {
306
- selected = await resolveProviderExecution(recipe.provider);
305
+ const directories = await writableDirectoriesOption(input.writableDirectories);
306
+ const provider = await withWritableDirectories(recipe.provider, input.cwd, directories, input.signal);
307
+ selected = await resolveProviderExecution(provider);
307
308
  }
308
309
  catch (error) {
309
310
  if (error instanceof TypeError)
@@ -317,10 +318,11 @@ async function admittedRecipe(recipe, bounds = {}) {
317
318
  throw new PreparedCallAdmissionError("options", admission.diagnostic);
318
319
  }
319
320
  return Object.freeze({
320
- ...(recipe.description === undefined ? {} : { description: recipe.description }),
321
+ ...recipe,
321
322
  provider: selected.execution,
322
323
  options: admission.options,
323
324
  allowed: bounds.ceiling === undefined ? recipe.allowed : clipAllowedActions(recipe.allowed, bounds.ceiling),
325
+ ...(recipe.bare === undefined ? {} : { bare: recipe.bare }),
324
326
  });
325
327
  }
326
328
  /** Judge durable birth from the allocated child's own evidence, never from the caught error. */
@@ -355,8 +357,8 @@ export async function executePreparedCall(input) {
355
357
  world = custody.world;
356
358
  }
357
359
  const recipe = custody.kind === "request"
358
- ? await admittedRecipe(custody.recipe, { ceiling: custody.parent.allowed, refuse: custody.refuse })
359
- : await admittedRecipe(custody.recipe);
360
+ ? await admittedRecipe(custody.recipe, input, { ceiling: custody.parent.allowed, refuse: custody.refuse })
361
+ : await admittedRecipe(custody.recipe, input);
360
362
  const origin = custody.kind === "request"
361
363
  ? { kind: "request", parent: custody.parent.id, requestId: custody.requestId }
362
364
  : { kind: "direct" };
@@ -385,6 +387,7 @@ export async function executePreparedCall(input) {
385
387
  provider: recipe.provider,
386
388
  options: recipe.options,
387
389
  allowed: recipe.allowed,
390
+ ...(recipe.bare === undefined ? {} : { bare: recipe.bare }),
388
391
  cwd: input.cwd,
389
392
  origin,
390
393
  ...(caller === undefined ? {} : { caller }),
@@ -101,6 +101,13 @@ declare const akumaObservationSchema: z.ZodObject<{
101
101
  }, z.core.$strict>, z.ZodObject<{
102
102
  kind: z.ZodLiteral<"row">;
103
103
  row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
104
+ kind: z.ZodLiteral<"report">;
105
+ sequence: z.ZodNumber;
106
+ bodySequence: z.ZodNumber;
107
+ turnSequence: z.ZodNumber;
108
+ text: z.ZodString;
109
+ at: z.ZodString;
110
+ }, z.core.$strict>, z.ZodObject<{
104
111
  kind: z.ZodLiteral<"call">;
105
112
  sequence: z.ZodNumber;
106
113
  turnSequence: z.ZodNumber;
@@ -306,6 +313,9 @@ declare const akumaObservationSchema: z.ZodObject<{
306
313
  kind: z.ZodLiteral<"failed">;
307
314
  historyId: z.ZodString;
308
315
  diagnostic: z.ZodString;
316
+ }, z.core.$strict>, z.ZodObject<{
317
+ kind: z.ZodLiteral<"canceled">;
318
+ historyId: z.ZodString;
309
319
  }, z.core.$strict>]>;
310
320
  }, z.core.$strict>>;
311
321
  entries: z.ZodReadonly<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
@@ -314,6 +324,13 @@ declare const akumaObservationSchema: z.ZodObject<{
314
324
  }, z.core.$strict>, z.ZodObject<{
315
325
  kind: z.ZodLiteral<"row">;
316
326
  row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
327
+ kind: z.ZodLiteral<"report">;
328
+ sequence: z.ZodNumber;
329
+ bodySequence: z.ZodNumber;
330
+ turnSequence: z.ZodNumber;
331
+ text: z.ZodString;
332
+ at: z.ZodString;
333
+ }, z.core.$strict>, z.ZodObject<{
317
334
  kind: z.ZodLiteral<"call">;
318
335
  sequence: z.ZodNumber;
319
336
  turnSequence: z.ZodNumber;
@@ -590,6 +607,13 @@ declare const akumaWaitResultSchema: z.ZodObject<{
590
607
  }, z.core.$strict>, z.ZodObject<{
591
608
  kind: z.ZodLiteral<"row">;
592
609
  row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
610
+ kind: z.ZodLiteral<"report">;
611
+ sequence: z.ZodNumber;
612
+ bodySequence: z.ZodNumber;
613
+ turnSequence: z.ZodNumber;
614
+ text: z.ZodString;
615
+ at: z.ZodString;
616
+ }, z.core.$strict>, z.ZodObject<{
593
617
  kind: z.ZodLiteral<"call">;
594
618
  sequence: z.ZodNumber;
595
619
  turnSequence: z.ZodNumber;
@@ -795,6 +819,9 @@ declare const akumaWaitResultSchema: z.ZodObject<{
795
819
  kind: z.ZodLiteral<"failed">;
796
820
  historyId: z.ZodString;
797
821
  diagnostic: z.ZodString;
822
+ }, z.core.$strict>, z.ZodObject<{
823
+ kind: z.ZodLiteral<"canceled">;
824
+ historyId: z.ZodString;
798
825
  }, z.core.$strict>]>;
799
826
  }, z.core.$strict>>;
800
827
  entries: z.ZodReadonly<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
@@ -803,6 +830,13 @@ declare const akumaWaitResultSchema: z.ZodObject<{
803
830
  }, z.core.$strict>, z.ZodObject<{
804
831
  kind: z.ZodLiteral<"row">;
805
832
  row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
833
+ kind: z.ZodLiteral<"report">;
834
+ sequence: z.ZodNumber;
835
+ bodySequence: z.ZodNumber;
836
+ turnSequence: z.ZodNumber;
837
+ text: z.ZodString;
838
+ at: z.ZodString;
839
+ }, z.core.$strict>, z.ZodObject<{
806
840
  kind: z.ZodLiteral<"call">;
807
841
  sequence: z.ZodNumber;
808
842
  turnSequence: z.ZodNumber;
@@ -1361,6 +1395,13 @@ export declare const selectionResultSchemas: {
1361
1395
  }, z.core.$strict>, z.ZodObject<{
1362
1396
  kind: z.ZodLiteral<"row">;
1363
1397
  row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
1398
+ kind: z.ZodLiteral<"report">;
1399
+ sequence: z.ZodNumber;
1400
+ bodySequence: z.ZodNumber;
1401
+ turnSequence: z.ZodNumber;
1402
+ text: z.ZodString;
1403
+ at: z.ZodString;
1404
+ }, z.core.$strict>, z.ZodObject<{
1364
1405
  kind: z.ZodLiteral<"call">;
1365
1406
  sequence: z.ZodNumber;
1366
1407
  turnSequence: z.ZodNumber;
@@ -1566,6 +1607,9 @@ export declare const selectionResultSchemas: {
1566
1607
  kind: z.ZodLiteral<"failed">;
1567
1608
  historyId: z.ZodString;
1568
1609
  diagnostic: z.ZodString;
1610
+ }, z.core.$strict>, z.ZodObject<{
1611
+ kind: z.ZodLiteral<"canceled">;
1612
+ historyId: z.ZodString;
1569
1613
  }, z.core.$strict>]>;
1570
1614
  }, z.core.$strict>>;
1571
1615
  entries: z.ZodReadonly<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
@@ -1574,6 +1618,13 @@ export declare const selectionResultSchemas: {
1574
1618
  }, z.core.$strict>, z.ZodObject<{
1575
1619
  kind: z.ZodLiteral<"row">;
1576
1620
  row: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodObject<{
1621
+ kind: z.ZodLiteral<"report">;
1622
+ sequence: z.ZodNumber;
1623
+ bodySequence: z.ZodNumber;
1624
+ turnSequence: z.ZodNumber;
1625
+ text: z.ZodString;
1626
+ at: z.ZodString;
1627
+ }, z.core.$strict>, z.ZodObject<{
1577
1628
  kind: z.ZodLiteral<"call">;
1578
1629
  sequence: z.ZodNumber;
1579
1630
  turnSequence: z.ZodNumber;
@@ -1,4 +1,5 @@
1
1
  import type { WorldRoot } from "../world.js";
2
+ import type { BodyLauncher } from "./body-launch.js";
2
3
  import type { AkumaStatus } from "./akuma.js";
3
4
  import type { SelectionRequestPort } from "./selection-request.js";
4
5
  /**
@@ -10,4 +11,4 @@ import type { SelectionRequestPort } from "./selection-request.js";
10
11
  * unaddressable member never starts; the executor's own access to the target is
11
12
  * then the product act, never a second addressing probe.
12
13
  */
13
- export declare function selectionRequestPort(world: WorldRoot, _reportDiagnostic: (message: string) => void, servingBodyId?: AkumaStatus["id"]): SelectionRequestPort;
14
+ export declare function selectionRequestPort(world: WorldRoot, spawn: BodyLauncher, servingBodyId?: AkumaStatus["id"]): SelectionRequestPort;
@@ -12,7 +12,7 @@ import { akumaObservationOf } from "./selection-observation.js";
12
12
  * unaddressable member never starts; the executor's own access to the target is
13
13
  * then the product act, never a second addressing probe.
14
14
  */
15
- export function selectionRequestPort(world, _reportDiagnostic, servingBodyId) {
15
+ export function selectionRequestPort(world, spawn, servingBodyId) {
16
16
  const prove = async (targets) => {
17
17
  for (const id of targets)
18
18
  await requireBornAkuma(world, id);
@@ -33,13 +33,14 @@ export function selectionRequestPort(world, _reportDiagnostic, servingBodyId) {
33
33
  if (request.interrupt === true && servingBodyId === target)
34
34
  throw new AkumaSelfInterruptError(target);
35
35
  await prove([target]);
36
- return await executeTellAkuma({ path: world, id: target, ...request });
36
+ return await executeTellAkuma({ path: world, id: target, spawn, ...request });
37
37
  },
38
38
  ask: async ({ target, ...request }) => {
39
39
  if (request.interrupt === true && servingBodyId === target)
40
40
  throw new AkumaSelfInterruptError(target);
41
41
  await prove([target]);
42
42
  return await executeAskAkuma({
43
+ spawn,
43
44
  path: world,
44
45
  id: target,
45
46
  ...request,
@@ -47,7 +48,7 @@ export function selectionRequestPort(world, _reportDiagnostic, servingBodyId) {
47
48
  },
48
49
  kill: async ({ targets, ...request }) => {
49
50
  await prove(targets);
50
- return await executeKillAkuma({ path: world, ids: targets, ...request });
51
+ return await executeKillAkuma({ path: world, ids: targets, spawn, ...request });
51
52
  },
52
53
  };
53
54
  }
@@ -1,12 +1,13 @@
1
1
  import { type ResumeCoordinate, type Soul, type TellFact } from "./heart/index.js";
2
2
  import type { AkumaPaths } from "./identity.js";
3
+ import { type ExecutionAssociationReader } from "./execution-instructions.js";
3
4
  import type { CallInitialTellAdmission } from "./call-initial-tell.js";
4
5
  import type { InitialTellAdmissionRequest } from "./call-request.js";
5
6
  import { type ProviderAdapter, type TurnResult } from "./provider.js";
6
7
  import { type AkumaCallRequestChildLaunch } from "./call-request.js";
7
8
  import { type ErasedRequestCommand } from "./request-wire.js";
8
9
  import { BodySupervisor } from "./body-supervisor.js";
9
- import type { OwnedProcess } from "../runtime/proc/run.js";
10
+ import type { LiveBodyLaunch } from "./body-launch.js";
10
11
  export declare function turnRecipe(paths: AkumaPaths, soul: Soul): Promise<Readonly<{
11
12
  cwd: string;
12
13
  options: Soul["options"];
@@ -30,10 +31,11 @@ export type DriveTurnInput = Readonly<{
30
31
  initiator?: string;
31
32
  schemaJson?: string;
32
33
  supervisor: BodySupervisor;
33
- runtimeSpawn(launch: AkumaCallRequestChildLaunch): Promise<OwnedProcess | void>;
34
+ runtimeSpawn(launch: AkumaCallRequestChildLaunch): Promise<LiveBodyLaunch | void>;
34
35
  admitInitialTell(input: InitialTellAdmissionRequest): Promise<CallInitialTellAdmission>;
35
36
  world: import("../world.js").WorldRoot;
36
37
  externalCommands: Readonly<Record<string, ErasedRequestCommand>>;
38
+ executionAssociation?: ExecutionAssociationReader;
37
39
  turnStarted: Readonly<{
38
40
  emit(turnSequence: number): Promise<void>;
39
41
  }>;
@@ -1,6 +1,7 @@
1
- import { abortableDelay } from "./abort.js";
1
+ import { abortable, abortableDelay } from "./abort.js";
2
2
  /* eslint-disable max-lines-per-function -- Turn setup and consumption each preserve one ordered lifecycle transaction. */
3
3
  import { appendActivity, beginTurn, bindTellsToTurn, BodyControlledError, breakBody, drainPendingTells, heartExists, readHeart, recordCurrentModel, recordSession, recordTellDeliveries, recordTellReceipt, } from "./heart/index.js";
4
+ import { keiyakuExecutionInstructions } from "./execution-instructions.js";
4
5
  import { withoutModel } from "./provider-recipe.js";
5
6
  import { encodeAgentEvent, } from "./provider.js";
6
7
  import { akumaCallRequestCommands } from "./call-request.js";
@@ -85,10 +86,36 @@ async function writeProviderEvent(input, active, event, witness) {
85
86
  }
86
87
  await appendActivity(input.paths, { turnSequence: active.turnSequence, event: encodeAgentEvent(event), at });
87
88
  }
89
+ function startProviderAttempt(input, setup) {
90
+ const { cwd, options, session } = setup.recipe;
91
+ const driveInput = {
92
+ body: input.body,
93
+ launchTells: setup.tells.map((tell) => ({ id: tell.id, text: tell.body })),
94
+ cwd,
95
+ options,
96
+ signal: setup.signal,
97
+ execution: {
98
+ akumaId: input.soul.id,
99
+ world: input.world,
100
+ bodySequence: input.bodySequence,
101
+ turnSequence: setup.turnSequence,
102
+ },
103
+ requests: { dir: setup.requests.directory, entry: setup.requests.entry },
104
+ ...(setup.runtimeInstructions === undefined ? {} : { runtimeInstructions: setup.runtimeInstructions }),
105
+ ...(setup.schemaJson === undefined ? {} : { schemaJson: setup.schemaJson }),
106
+ };
107
+ return session === undefined
108
+ ? input.adapter.start({ ...driveInput, session: { kind: "fresh" } })
109
+ : input.adapter.resume({ ...driveInput, session: { kind: "resume", coordinate: session } });
110
+ }
88
111
  async function startTurnDrive(input) {
89
- const { cwd, options, session } = await turnRecipe(input.paths, input.soul);
112
+ if (input.supervisor.signal.aborted)
113
+ return { kind: "stopped" };
114
+ const recipe = await turnRecipe(input.paths, input.soul);
115
+ const { session } = recipe;
90
116
  if (session !== undefined && input.adapter.resume === undefined)
91
117
  return { kind: "resume-unsupported" };
118
+ const runtimeInstructions = keiyakuExecutionInstructions(input.soul, input.soul.bare !== false ? undefined : await input.executionAssociation?.());
92
119
  const boundTells = drainPendingTells(input.launchTells);
93
120
  const schemaJson = input.schemaJson ?? boundTells.find((tell) => tell.schemaJson !== undefined)?.schemaJson;
94
121
  const initiator = input.call === undefined ? boundTells[0]?.initiator : input.initiator;
@@ -107,6 +134,8 @@ async function startTurnDrive(input) {
107
134
  });
108
135
  }
109
136
  await input.turnStarted.emit(turn.sequence);
137
+ if (input.supervisor.signal.aborted)
138
+ return { kind: "stopped" };
110
139
  const { world, paths, soul: parent, runtimeSpawn: spawn, externalCommands, admitInitialTell } = input;
111
140
  const commands = composeRequestCommands(akumaCallRequestCommands({ world, paths, parent, spawn, admitInitialTell }), externalCommands);
112
141
  const requests = await BodyRequestPump.open({
@@ -117,6 +146,15 @@ async function startTurnDrive(input) {
117
146
  commands,
118
147
  signal: input.supervisor.signal,
119
148
  });
149
+ return await establishTurnDrive(input, turn.sequence, requests, {
150
+ ...recipe,
151
+ boundTells,
152
+ ...(schemaJson === undefined ? {} : { schemaJson }),
153
+ ...(runtimeInstructions === undefined ? {} : { runtimeInstructions }),
154
+ });
155
+ }
156
+ async function establishTurnDrive(input, turnSequence, requests, recipe) {
157
+ const { cwd, options, session, boundTells, schemaJson, runtimeInstructions } = recipe;
120
158
  const driveController = new AbortController();
121
159
  const cancelDrive = () => {
122
160
  if (!driveController.signal.aborted)
@@ -129,24 +167,21 @@ async function startTurnDrive(input) {
129
167
  if (!driveController.signal.aborted)
130
168
  driveController.abort(error);
131
169
  });
132
- const driveInput = {
133
- body: input.body,
134
- launchTells: boundTells.map((tell) => ({ id: tell.id, text: tell.body })),
135
- cwd,
136
- options,
170
+ const attempt = startProviderAttempt(input, {
171
+ recipe,
172
+ tells: boundTells,
173
+ requests,
137
174
  signal: driveController.signal,
138
- requests: { dir: requests.directory, entry: requests.entry },
139
- ...(schemaJson === undefined ? {} : { schemaJson }),
140
- };
141
- const attempt = session === undefined
142
- ? input.adapter.start({ ...driveInput, session: { kind: "fresh" } })
143
- : input.adapter.resume({ ...driveInput, session: { kind: "resume", coordinate: session } });
175
+ turnSequence,
176
+ schemaJson,
177
+ runtimeInstructions,
178
+ });
144
179
  const custodyFailure = observeFailure(attempt.closed);
145
180
  try {
146
- const selected = await Promise.race([attempt.result, requests.failure, custodyFailure]);
181
+ const selected = await abortable(Promise.race([attempt.result, requests.failure, custodyFailure]), input.supervisor.signal);
147
182
  if (input.supervisor.signal.aborted) {
148
183
  try {
149
- const retirement = await retireProviderCustody(input, turn.sequence, attempt);
184
+ const retirement = await retireProviderCustody(input, turnSequence, attempt);
150
185
  await requests.close();
151
186
  if (retirement.kind === "hung")
152
187
  return retirement;
@@ -160,13 +195,13 @@ async function startTurnDrive(input) {
160
195
  await recordTellDeliveries(input.paths, boundTells.map((tell) => ({
161
196
  tellId: tell.id,
162
197
  route: "launch",
163
- turnSequence: turn.sequence,
198
+ turnSequence,
164
199
  fence: selected.admission.fence,
165
200
  deliveredAt: input.now(),
166
201
  })));
167
202
  void selected.completion.then(() => requests.stopAdmission(), () => undefined);
168
203
  return {
169
- turnSequence: turn.sequence,
204
+ turnSequence,
170
205
  attempt,
171
206
  drive: selected,
172
207
  requests,
@@ -177,7 +212,7 @@ async function startTurnDrive(input) {
177
212
  };
178
213
  }
179
214
  catch (error) {
180
- const retirement = await retireProviderCustody(input, turn.sequence, attempt);
215
+ const retirement = await retireProviderCustody(input, turnSequence, attempt);
181
216
  if (retirement.kind === "hung") {
182
217
  try {
183
218
  await requests.close();
@@ -187,7 +222,7 @@ async function startTurnDrive(input) {
187
222
  }
188
223
  return retirement;
189
224
  }
190
- return await failedTurnSetup(input, turn.sequence, requests, cancelDrive, error);
225
+ return await failedTurnSetup(input, turnSequence, requests, cancelDrive, error);
191
226
  }
192
227
  }
193
228
  async function retireProviderCustody(input, turnSequence, attempt) {
@@ -206,7 +241,7 @@ async function retireProviderCustody(input, turnSequence, attempt) {
206
241
  error: new Error(`provider custody remained live after ${CONTROL_RESPONSE_MS}ms`),
207
242
  })),
208
243
  ]);
209
- let outcome = await dispose(attempt.abort);
244
+ let outcome = await dispose(input.supervisor.forceSignal?.aborted ? attempt.forceDispose : attempt.abort);
210
245
  if (outcome.kind === "retired")
211
246
  return outcome;
212
247
  outcome = await dispose(attempt.forceDispose);
@@ -429,7 +464,9 @@ async function consumeTurnDrive(input, active) {
429
464
  /** Retirement decides the ending: only a provider that could not retire replaces the requested one. */
430
465
  const stopAndReturn = async (outcome) => {
431
466
  const retirement = await stopActiveDrive(input, active);
432
- return retirement.kind === "hung" ? retirement : outcome;
467
+ if (retirement.kind === "hung")
468
+ return retirement;
469
+ return input.supervisor.signal.aborted ? { kind: "stopped" } : outcome;
433
470
  };
434
471
  wakeups.event(iterator.next());
435
472
  wakeups.heart(heart);
@@ -1,11 +1 @@
1
- import { type BodyLaunch } from "./akuma/body.js";
2
- import { World } from "./world.js";
3
- type BodyProcessConfiguration = Readonly<{
4
- home?: string;
5
- gitPath?: string;
6
- }>;
7
- export declare function externalRequestCommandsFor(launch: BodyLaunch, processConfiguration: BodyProcessConfiguration): Promise<Readonly<{
8
- world: Awaited<ReturnType<typeof World.prove>>;
9
- commands: Readonly<Record<string, import("./akuma/request-wire.js").ErasedRequestCommand>>;
10
- }>>;
11
1
  export {};