@astrosheep/keiyaku 4.1.0 → 4.1.2

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 (278) hide show
  1. package/README.md +1 -1
  2. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku/SKILL.md +3 -0
  3. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-akuma/SKILL.md +3 -0
  4. package/build/integrations/marketplace/plugins/keiyaku/skills/keiyaku-workflow/SKILL.md +3 -6
  5. package/build/src/akuma/akuma-errors.d.ts +6 -0
  6. package/build/src/akuma/akuma-errors.js +9 -0
  7. package/build/src/akuma/akuma-handle.d.ts +39 -0
  8. package/build/src/akuma/akuma-handle.js +263 -0
  9. package/build/src/akuma/akuma-observe.d.ts +19 -0
  10. package/build/src/akuma/akuma-observe.js +74 -0
  11. package/build/src/akuma/akuma-product-symbols.d.ts +1 -0
  12. package/build/src/akuma/akuma-product-symbols.js +1 -0
  13. package/build/src/akuma/akuma-product.d.ts +18 -0
  14. package/build/src/akuma/akuma-product.js +154 -0
  15. package/build/src/akuma/akuma.d.ts +37 -81
  16. package/build/src/akuma/akuma.js +39 -447
  17. package/build/src/akuma/allowed.d.ts +1 -0
  18. package/build/src/akuma/allowed.js +6 -0
  19. package/build/src/akuma/archetype.js +8 -5
  20. package/build/src/akuma/body-supervisor.d.ts +26 -0
  21. package/build/src/akuma/body-supervisor.js +89 -0
  22. package/build/src/akuma/body.d.ts +45 -4
  23. package/build/src/akuma/body.js +145 -35
  24. package/build/src/akuma/coordinate.js +17 -7
  25. package/build/src/akuma/heart/facts.js +1 -1
  26. package/build/src/akuma/heart/index.d.ts +1 -1
  27. package/build/src/akuma/heart/index.js +2 -4
  28. package/build/src/akuma/heart/request-authority.js +4 -4
  29. package/build/src/akuma/heart/request-rows.js +27 -16
  30. package/build/src/akuma/heart/rows.js +79 -41
  31. package/build/src/akuma/heart/soul.js +1 -1
  32. package/build/src/akuma/heart/storage.d.ts +1 -0
  33. package/build/src/akuma/heart/storage.js +76 -11
  34. package/build/src/akuma/heart/tells.js +35 -18
  35. package/build/src/akuma/heart/timeline.js +19 -11
  36. package/build/src/akuma/identity.d.ts +1 -0
  37. package/build/src/akuma/identity.js +1 -0
  38. package/build/src/akuma/index.d.ts +3 -3
  39. package/build/src/akuma/index.js +1 -1
  40. package/build/src/akuma/nuke.js +106 -14
  41. package/build/src/akuma/projection-read.d.ts +17 -0
  42. package/build/src/akuma/projection-read.js +135 -0
  43. package/build/src/akuma/projection.d.ts +1 -16
  44. package/build/src/akuma/projection.js +77 -154
  45. package/build/src/akuma/provider-recipe.js +11 -5
  46. package/build/src/akuma/provider.js +105 -62
  47. package/build/src/akuma/providers/acp/config.js +5 -6
  48. package/build/src/akuma/providers/acp/core.js +17 -10
  49. package/build/src/akuma/providers/acp/events.js +38 -29
  50. package/build/src/akuma/providers/acp/index.js +13 -9
  51. package/build/src/akuma/providers/claude/events.js +8 -12
  52. package/build/src/akuma/providers/claude/index.d.ts +1 -0
  53. package/build/src/akuma/providers/claude/index.js +55 -26
  54. package/build/src/akuma/providers/claude/input.js +6 -2
  55. package/build/src/akuma/providers/codex-app-server/events.js +61 -36
  56. package/build/src/akuma/providers/codex-app-server/index.js +25 -13
  57. package/build/src/akuma/providers/grok-build/index.js +22 -25
  58. package/build/src/akuma/providers/index.js +2 -18
  59. package/build/src/akuma/providers/opencode-sdk/events.js +32 -18
  60. package/build/src/akuma/providers/opencode-sdk/index.js +26 -17
  61. package/build/src/akuma/providers/opencode-sdk/session.js +21 -5
  62. package/build/src/akuma/providers/pi/events.js +26 -19
  63. package/build/src/akuma/providers/pi/index.js +58 -40
  64. package/build/src/akuma/publication.js +9 -9
  65. package/build/src/akuma/request-execution.d.ts +6 -0
  66. package/build/src/akuma/request-execution.js +86 -0
  67. package/build/src/akuma/request-serve.d.ts +12 -1
  68. package/build/src/akuma/request-serve.js +19 -122
  69. package/build/src/akuma/request-wire.d.ts +2 -2
  70. package/build/src/akuma/request-wire.js +75 -102
  71. package/build/src/akuma/requests.js +2 -2
  72. package/build/src/akuma/{body-turn.d.ts → turn-drive.d.ts} +2 -25
  73. package/build/src/akuma/{body-turn.js → turn-drive.js} +20 -103
  74. package/build/src/akuma-body.js +6 -5
  75. package/build/src/body/amend.d.ts +4 -1
  76. package/build/src/body/amend.js +14 -6
  77. package/build/src/body/decode.js +2 -4
  78. package/build/src/body/envelope.js +2 -4
  79. package/build/src/body/region.d.ts +1 -2
  80. package/build/src/body/region.js +2 -70
  81. package/build/src/body/render.js +17 -12
  82. package/build/src/body/shape.js +1 -7
  83. package/build/src/cli/accepted.d.ts +1 -1
  84. package/build/src/cli/accepted.js +8 -1
  85. package/build/src/cli/commands/akuma-invoke.js +18 -6
  86. package/build/src/cli/commands/akuma.d.ts +0 -6
  87. package/build/src/cli/commands/akuma.js +11 -24
  88. package/build/src/cli/commands/amend.d.ts +2 -2
  89. package/build/src/cli/commands/amend.js +2 -4
  90. package/build/src/cli/commands/bind.d.ts +4 -4
  91. package/build/src/cli/commands/bind.js +16 -6
  92. package/build/src/cli/commands/contract-invoke.d.ts +25 -0
  93. package/build/src/cli/commands/contract-invoke.js +193 -0
  94. package/build/src/cli/commands/contract.d.ts +109 -10
  95. package/build/src/cli/commands/contract.js +339 -16
  96. package/build/src/cli/commands/install.d.ts +1 -1
  97. package/build/src/cli/commands/install.js +23 -15
  98. package/build/src/cli/commands/task-invoke.js +187 -67
  99. package/build/src/cli/commands/task-query.js +48 -24
  100. package/build/src/cli/commands/task.js +150 -38
  101. package/build/src/cli/coordinates.js +2 -4
  102. package/build/src/cli/invoke.js +92 -208
  103. package/build/src/cli/main.js +4 -2
  104. package/build/src/cli/parse.d.ts +3 -90
  105. package/build/src/cli/parse.js +27 -233
  106. package/build/src/cli/render/akuma-activity.d.ts +38 -0
  107. package/build/src/cli/render/akuma-activity.js +362 -0
  108. package/build/src/cli/render/akuma-tool-command.js +6 -7
  109. package/build/src/cli/render/akuma-tool.js +10 -8
  110. package/build/src/cli/render/akuma.d.ts +1 -1
  111. package/build/src/cli/render/akuma.js +61 -353
  112. package/build/src/cli/render/audit.js +5 -15
  113. package/build/src/cli/render/board.d.ts +1 -0
  114. package/build/src/cli/render/board.js +17 -0
  115. package/build/src/cli/render/catalog.js +81 -8
  116. package/build/src/cli/render/contract-history.d.ts +2 -0
  117. package/build/src/cli/render/contract-history.js +83 -0
  118. package/build/src/cli/render/contract-observation.d.ts +10 -0
  119. package/build/src/cli/render/contract-observation.js +58 -0
  120. package/build/src/cli/render/contract.d.ts +1 -2
  121. package/build/src/cli/render/contract.js +41 -142
  122. package/build/src/cli/render/kanshi.js +239 -215
  123. package/build/src/cli/render/receipt.js +2 -9
  124. package/build/src/cli/render/refusal.js +10 -15
  125. package/build/src/cli/render/region.js +22 -6
  126. package/build/src/cli/render/settings.js +4 -4
  127. package/build/src/cli/render/task.js +34 -14
  128. package/build/src/cli/render/terminal.js +16 -5
  129. package/build/src/cli/result.d.ts +3 -3
  130. package/build/src/cli/runtime.d.ts +6 -1
  131. package/build/src/cli/runtime.js +84 -63
  132. package/build/src/cli/selectors.js +2 -4
  133. package/build/src/cli/usage.js +6 -5
  134. package/build/src/contract-worktree.d.ts +1 -23
  135. package/build/src/contract-worktree.js +79 -155
  136. package/build/src/coordination/durable-file.js +7 -3
  137. package/build/src/coordination/sqlite-transaction-lock.js +29 -12
  138. package/build/src/core/facts/codec.js +7 -3
  139. package/build/src/core/facts/types.d.ts +1 -1
  140. package/build/src/core/subject.js +16 -9
  141. package/build/src/core/verbs/abandon.d.ts +1 -1
  142. package/build/src/core/verbs/abandon.js +1 -1
  143. package/build/src/core/verbs/amend.d.ts +1 -1
  144. package/build/src/core/verbs/amend.js +7 -7
  145. package/build/src/core/verbs/attestation.js +4 -1
  146. package/build/src/core/verbs/bind.d.ts +1 -1
  147. package/build/src/core/verbs/bind.js +1 -1
  148. package/build/src/core/verbs/placement.d.ts +1 -1
  149. package/build/src/core/verbs/placement.js +10 -8
  150. package/build/src/dispatch/index.js +8 -6
  151. package/build/src/duration.js +5 -1
  152. package/build/src/git/admission.js +5 -3
  153. package/build/src/git/hooks.d.ts +8 -0
  154. package/build/src/git/hooks.js +63 -14
  155. package/build/src/git/identity.js +1 -4
  156. package/build/src/git/integration.d.ts +2 -3
  157. package/build/src/git/integration.js +32 -39
  158. package/build/src/git/nuke.d.ts +1 -1
  159. package/build/src/git/nuke.js +110 -57
  160. package/build/src/git/observe.d.ts +13 -1
  161. package/build/src/git/observe.js +51 -44
  162. package/build/src/git/process.js +4 -2
  163. package/build/src/git/read-observation.js +10 -8
  164. package/build/src/git/reconcile.d.ts +22 -2
  165. package/build/src/git/reconcile.js +38 -274
  166. package/build/src/git/repository.d.ts +2 -0
  167. package/build/src/git/repository.js +13 -22
  168. package/build/src/git/scratch.d.ts +8 -5
  169. package/build/src/git/scratch.js +29 -2
  170. package/build/src/git/target-placement.d.ts +9 -10
  171. package/build/src/git/target-placement.js +59 -62
  172. package/build/src/git/tender.js +13 -46
  173. package/build/src/git/terminal-reconcile.d.ts +21 -0
  174. package/build/src/git/terminal-reconcile.js +278 -0
  175. package/build/src/git/terminal-seal.js +15 -12
  176. package/build/src/git/tree.js +5 -2
  177. package/build/src/git/workspace.d.ts +24 -2
  178. package/build/src/git/workspace.js +120 -16
  179. package/build/src/identity/coordinates.js +3 -1
  180. package/build/src/identity/selector.js +6 -3
  181. package/build/src/kanshi/fleet.d.ts +6 -0
  182. package/build/src/kanshi/fleet.js +27 -0
  183. package/build/src/kanshi/index.d.ts +1 -1
  184. package/build/src/kanshi/read.js +60 -48
  185. package/build/src/kanshi/report.d.ts +11 -23
  186. package/build/src/kanshi/select.js +25 -24
  187. package/build/src/library/address.d.ts +2 -1
  188. package/build/src/library/address.js +7 -8
  189. package/build/src/library/akuma-creation.js +20 -12
  190. package/build/src/library/audit.d.ts +0 -1
  191. package/build/src/library/audit.js +1 -2
  192. package/build/src/library/bind.d.ts +53 -5
  193. package/build/src/library/bind.js +98 -22
  194. package/build/src/library/catalog.d.ts +1 -0
  195. package/build/src/library/catalog.js +6 -3
  196. package/build/src/library/configuration.js +3 -1
  197. package/build/src/library/continuation.d.ts +15 -4
  198. package/build/src/library/continuation.js +24 -16
  199. package/build/src/library/contract-bind.d.ts +26 -0
  200. package/build/src/library/contract-bind.js +106 -0
  201. package/build/src/library/contract-operations.d.ts +77 -0
  202. package/build/src/library/contract-operations.js +130 -0
  203. package/build/src/library/contract-types.d.ts +95 -0
  204. package/build/src/library/contract-types.js +1 -0
  205. package/build/src/library/contract.d.ts +19 -154
  206. package/build/src/library/contract.js +46 -261
  207. package/build/src/library/fleet.d.ts +1 -1
  208. package/build/src/library/fleet.js +19 -11
  209. package/build/src/library/input.d.ts +2 -0
  210. package/build/src/library/input.js +14 -0
  211. package/build/src/library/keiyaku.d.ts +8 -7
  212. package/build/src/library/keiyaku.js +3 -3
  213. package/build/src/library/nuke.js +14 -5
  214. package/build/src/library/reconcile.d.ts +9 -4
  215. package/build/src/library/reconcile.js +30 -24
  216. package/build/src/library/refusal.d.ts +13 -5
  217. package/build/src/library/refusal.js +7 -0
  218. package/build/src/library/region.d.ts +8 -7
  219. package/build/src/library/region.js +31 -11
  220. package/build/src/library/repo.js +2 -2
  221. package/build/src/markdown/lex.js +9 -2
  222. package/build/src/markdown/parse.js +11 -7
  223. package/build/src/markdown/query.js +4 -2
  224. package/build/src/protocol/amend.js +3 -1
  225. package/build/src/protocol/attempt.d.ts +7 -3
  226. package/build/src/protocol/attempt.js +9 -5
  227. package/build/src/protocol/audit.d.ts +1 -1
  228. package/build/src/protocol/audit.js +4 -14
  229. package/build/src/protocol/bind.d.ts +19 -6
  230. package/build/src/protocol/bind.js +28 -13
  231. package/build/src/protocol/completion.d.ts +0 -1
  232. package/build/src/protocol/completion.js +1 -3
  233. package/build/src/protocol/deliver.d.ts +1 -3
  234. package/build/src/protocol/deliver.js +15 -39
  235. package/build/src/protocol/intent.d.ts +1 -0
  236. package/build/src/protocol/intent.js +9 -7
  237. package/build/src/protocol/operations.d.ts +3 -7
  238. package/build/src/protocol/operations.js +5 -3
  239. package/build/src/protocol/placement.d.ts +0 -1
  240. package/build/src/protocol/placement.js +6 -6
  241. package/build/src/protocol/read/observation.d.ts +11 -0
  242. package/build/src/protocol/read/observation.js +37 -0
  243. package/build/src/protocol/read/status.d.ts +23 -12
  244. package/build/src/protocol/read/status.js +90 -72
  245. package/build/src/protocol/reconcile.d.ts +1 -0
  246. package/build/src/protocol/reconcile.js +2 -3
  247. package/build/src/protocol/reintegrate.js +1 -1
  248. package/build/src/protocol/review.d.ts +0 -1
  249. package/build/src/protocol/review.js +15 -22
  250. package/build/src/protocol/run.d.ts +1 -0
  251. package/build/src/protocol/run.js +4 -5
  252. package/build/src/runtime/proc/launch.d.ts +33 -0
  253. package/build/src/runtime/proc/launch.js +98 -0
  254. package/build/src/runtime/proc/line-rpc.js +9 -3
  255. package/build/src/runtime/proc/run.d.ts +12 -6
  256. package/build/src/runtime/proc/run.js +78 -21
  257. package/build/src/runtime/proc/stdio.js +7 -10
  258. package/build/src/settings.js +6 -2
  259. package/build/src/settlement/holder.js +13 -10
  260. package/build/src/settlement/settle.js +39 -6
  261. package/build/src/task/board.js +12 -6
  262. package/build/src/task/compose.js +85 -22
  263. package/build/src/task/context.js +21 -8
  264. package/build/src/task/document.js +46 -10
  265. package/build/src/task/identity.js +5 -2
  266. package/build/src/task/index.d.ts +0 -1
  267. package/build/src/task/index.js +119 -34
  268. package/build/src/task/input.js +29 -7
  269. package/build/src/task/mutation.js +61 -19
  270. package/build/src/task/operations.d.ts +6 -1
  271. package/build/src/task/operations.js +83 -29
  272. package/build/src/task/query.js +55 -26
  273. package/build/src/task/store.d.ts +3 -1
  274. package/build/src/task/store.js +81 -17
  275. package/build/src/verification/execution.js +14 -11
  276. package/build/src/workspace-place.js +19 -7
  277. package/build/src/world.js +16 -6
  278. package/package.json +8 -3
@@ -1,18 +1,11 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { readdir, realpath, stat } from "node:fs/promises";
2
+ import { realpath, stat } from "node:fs/promises";
3
3
  import { resolve } from "node:path";
4
- import { CONTROL_RESPONSE_MS, spawnAkumaBody } from "./body.js";
5
- import { HeldAkumaLeash, activitySlice, isHeartAbsent, life, lifeAt, probeLeash, readHeart, readLastAnsweredTurn, readForkPoint, readKill, readSeal, readSoul, recordTell, requestPause, requestStop, } from "./heart/index.js";
6
- import { akuIdFromDirectoryName, akumaPaths, akumaRunRoot, parseAkuId, pathsForAkuId, archetypeName, } from "./identity.js";
7
- import { ordinarySelectedCount, ordinarySnapshotBudget, projectTurns, selectActivitySnapshot, selectHistory, selectSnapshot, } from "./projection.js";
8
- import { listArchetypes as readArchetypes, loadArchetype } from "./archetype.js";
9
- import { publishAkuma } from "./publication.js";
10
- import { resolveProviderExecution } from "./providers/index.js";
11
- import { injectedBodyRequests, requestBodyCall } from "./requests.js";
12
- import { settings as readSettings } from "../settings.js";
13
- import { decodeAllowedActions, } from "./allowed.js";
14
- const POLL_MS = 25;
15
- async function canonicalBirthCwd(input) {
4
+ import { CONTROL_RESPONSE_MS, handoffPendingTells, wakeRecordedTell, } from "./body.js";
5
+ import { HeldAkumaLeash, readHeart, readKill, recordTell, requestStop, } from "./heart/index.js";
6
+ import { pathsForAkuId } from "./identity.js";
7
+ export const POLL_MS = 100;
8
+ export async function canonicalBirthCwd(input) {
16
9
  const selected = resolve(input);
17
10
  try {
18
11
  const canonical = await realpath(selected);
@@ -24,485 +17,84 @@ async function canonicalBirthCwd(input) {
24
17
  throw new Error(`cwd is not an existing directory: ${input}`);
25
18
  }
26
19
  }
27
- function callReadonly(value) {
20
+ export function callReadonly(value) {
28
21
  if (value === undefined)
29
22
  return {};
30
23
  if (value !== true)
31
24
  throw new TypeError("Akuma call readonly must be true");
32
25
  return { readonly: true };
33
26
  }
34
- const CALL_EXECUTION = Symbol("akuma-call-execution");
35
- const CALL_WITH_CONTEXT = Symbol("akuma-call-with-context");
36
- export class AkumaNotBornError extends Error {
37
- id;
38
- kind = "akuma-not-born";
39
- constructor(id) {
40
- super(`Akuma ${id} is not born`);
41
- this.id = id;
42
- this.name = "AkumaNotBornError";
43
- }
27
+ /** The default completion judgment over one complete status snapshot. */
28
+ export function defaultWaitComplete(status) {
29
+ return (status.life !== "running" &&
30
+ !status.timeline.entries.some((entry) => entry.kind === "row" && entry.row.kind === "tell" && entry.row.state === "pending"));
44
31
  }
45
- function wait(milliseconds) {
32
+ export { CALL_WITH_CONTEXT } from "./akuma-product-symbols.js";
33
+ export { AkumaNotBornError } from "./akuma-errors.js";
34
+ import { AkumaNotBornError } from "./akuma-errors.js";
35
+ export function wait(milliseconds) {
46
36
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
47
37
  }
48
- async function takeLeashUntil(paths, deadline) {
38
+ export async function takeLeashUntil(paths, deadline) {
49
39
  for (;;) {
50
40
  const leash = await HeldAkumaLeash.try(paths);
51
41
  if (leash !== null)
52
42
  return leash;
53
43
  if (performance.now() >= deadline)
54
44
  return null;
55
- await wait(POLL_MS);
45
+ await wait(Math.min(POLL_MS, Math.max(0, deadline - performance.now())));
56
46
  }
57
47
  }
58
- async function recordTellBody(paths, akuma, body, id = randomUUID(), recordedAt = new Date().toISOString()) {
48
+ export async function recordTellBody(paths, akuma, body, id = randomUUID(), recordedAt = new Date().toISOString()) {
59
49
  const admitted = await recordTell(paths, { kind: "tell", id, body, recordedAt });
60
50
  if (admitted.kind === "not-born")
61
51
  throw new AkumaNotBornError(akuma);
62
52
  return { kind: "recorded", tellId: admitted.tell.id };
63
53
  }
64
- async function wakeTell(paths, tellId) {
65
- try {
66
- await spawnAkumaBody({ paths });
67
- return { admission: { tellId, fact: "recorded" }, wake: "spawned" };
68
- }
69
- catch (error) {
70
- return {
71
- admission: { tellId, fact: "recorded" },
72
- wake: { kind: "failed", diagnostic: diagnostic(error) },
73
- };
74
- }
75
- }
76
- export async function tellAkumaWithId(worldPath, id, body, tellId, recordedAt = new Date().toISOString()) {
77
- const paths = pathsForAkuId(worldPath, id);
78
- const recorded = await recordTellBody(paths, id, body, tellId, recordedAt);
79
- return await wakeTell(paths, recorded.tellId);
54
+ export async function tellAkumaWithId(input) {
55
+ const paths = pathsForAkuId(input.worldPath, input.id);
56
+ const recorded = await recordTellBody(paths, input.id, input.body, input.tellId, input.recordedAt);
57
+ return await wakeRecordedTell(paths, recorded.tellId, input.runtime);
80
58
  }
81
- function diagnostic(error) {
59
+ export function diagnostic(error) {
82
60
  return error instanceof Error ? error.message : String(error);
83
61
  }
84
- async function fleetListRow(paths, expected) {
85
- const snapshot = await readHeart(paths);
86
- if (snapshot.soul !== null)
87
- return await bornListRow(paths, expected, snapshot);
62
+ export async function killAkumaWithRecovery(paths, recover = handoffPendingTells) {
88
63
  try {
89
- if (await probeLeash(paths) === "held")
90
- return { id: expected, life: "unborn" };
91
- const seal = await readSeal(paths);
92
- return seal === null ? { id: expected, life: "unborn" } : { id: expected, life: "stillborn", seal };
93
- }
94
- catch (error) {
95
- if (isHeartAbsent(error))
96
- return { id: expected, life: "unborn" };
97
- throw error;
98
- }
99
- }
100
- async function bornListRow(paths, expected, snapshot) {
101
- snapshot ??= await readHeart(paths);
102
- if (snapshot.soul === null)
103
- throw new AkumaNotBornError(expected);
104
- if (snapshot.soul.id !== expected)
105
- throw new Error("Akuma soul does not match its coordinate");
106
- const currentLife = life({
107
- leash: await probeLeash(paths),
108
- body: snapshot.latestBody,
109
- kill: snapshot.latestKill,
110
- });
111
- return {
112
- id: snapshot.soul.id,
113
- archetype: snapshot.soul.archetype,
114
- ...(snapshot.soul.description === undefined ? {} : { description: snapshot.soul.description }),
115
- life: currentLife,
116
- lifeAt: lifeAt(currentLife, snapshot.latestBody, snapshot.latestKill, snapshot.soul.createdAt),
117
- lastActivityAt: snapshot.lastActivityAt,
118
- pending: snapshot.pending.map((tell) => tell.id),
119
- };
120
- }
121
- async function bornStatus(paths, expected, budget) {
122
- const snapshot = await readHeart(paths);
123
- if (snapshot.soul === null)
124
- throw new AkumaNotBornError(expected);
125
- const current = await bornListRow(paths, expected, snapshot);
126
- const resumeUnsupported = current.life === "stranded"
127
- && snapshot.latestSession?.provider === snapshot.soul.provider.name
128
- && (await resolveProviderExecution(snapshot.soul.provider)).adapter.resume === undefined;
129
- const slice = await activitySlice(paths);
130
- return {
131
- id: current.id,
132
- life: current.life,
133
- ...(snapshot.soul.readonly === undefined ? {} : { readonly: snapshot.soul.readonly }),
134
- ...(resumeUnsupported ? { strandedReason: "resume-unsupported" } : {}),
135
- timeline: budget === undefined
136
- ? selectActivitySnapshot(slice.rows)
137
- : selectSnapshot(projectTurns(slice.rows), budget),
138
- };
139
- }
140
- /** Package-internal budgeted observation; Fleet allocates, Akuma still selects. */
141
- export async function readBudgetedStatus(worldPath, id, input) {
142
- if (!Number.isSafeInteger(input.ordinaryBudget) || input.ordinaryBudget < 0) {
143
- throw new TypeError("ordinary budget must be a nonnegative safe integer");
144
- }
145
- const status = await bornStatus(pathsForAkuId(worldPath, id), id, ordinarySnapshotBudget(input.ordinaryBudget));
146
- return { status, ordinarySelected: ordinarySelectedCount(status.timeline) };
147
- }
148
- /** Package-internal birth projection used by the composed Library call result. */
149
- export async function readAkumaBirthCwd(worldPath, id) {
150
- const soul = await readSoul(pathsForAkuId(worldPath, id));
151
- if (soul === null)
152
- throw new AkumaNotBornError(id);
153
- return soul.cwd;
154
- }
155
- export class AkumaHandle {
156
- id;
157
- worldPath;
158
- [CALL_EXECUTION];
159
- constructor(id, worldPath, execution) {
160
- this.id = id;
161
- this.worldPath = worldPath;
162
- if (execution !== undefined)
163
- this[CALL_EXECUTION] = execution;
164
- }
165
- get paths() {
166
- return pathsForAkuId(this.worldPath, this.id);
167
- }
168
- async status() {
169
- return await bornStatus(this.paths, this.id);
170
- }
171
- async history(input = {}) {
172
- if (input.before !== undefined && input.since !== undefined) {
173
- throw new TypeError("Akuma history before and since are mutually exclusive");
174
- }
175
- for (const [name, value] of [["before", input.before], ["since", input.since]]) {
176
- if (value !== undefined && (!Number.isSafeInteger(value) || value <= 0)) {
177
- throw new TypeError(`Akuma history ${name} must be a positive safe integer`);
178
- }
179
- }
180
- const limit = input.limit ?? 50;
181
- if (!Number.isSafeInteger(limit) || limit <= 0 || limit > 5_000) {
182
- throw new TypeError("Akuma history limit must be a positive safe integer no greater than 5000");
183
- }
184
- const slice = await activitySlice(this.paths);
185
- return selectHistory(projectTurns(slice.rows, {
186
- lowestRetained: slice.lowestRetained,
187
- highest: slice.highest,
188
- }), {
189
- ...(input.before === undefined ? {} : { before: input.before }),
190
- ...(input.since === undefined ? {} : { since: input.since }),
191
- limit,
192
- });
193
- }
194
- async wait(predicate = (status) => status.life !== "running", options = {}) {
195
- if (options.timeoutMs !== undefined
196
- && (!Number.isFinite(options.timeoutMs) || options.timeoutMs < 0)) {
197
- throw new TypeError("Akuma wait timeoutMs must be a nonnegative finite millisecond duration");
198
- }
199
- const deadline = options.timeoutMs === undefined ? undefined : performance.now() + options.timeoutMs;
200
- for (;;) {
201
- const status = await this.status();
202
- if (predicate(status) || (deadline !== undefined && performance.now() >= deadline))
203
- return status;
204
- await wait(deadline === undefined ? POLL_MS : Math.min(POLL_MS, Math.max(0, deadline - performance.now())));
205
- }
206
- }
207
- async tell(body) {
208
- const recorded = await recordTellBody(this.paths, this.id, body);
209
- return await wakeTell(this.paths, recorded.tellId);
210
- }
211
- async interrupt(body) {
212
- const request = await requestPause(this.paths, new Date().toISOString());
213
- if (request.kind === "not-born") {
214
- throw new AkumaNotBornError(this.id);
215
- }
216
- let putDown = "was-idle";
217
- let leash = await HeldAkumaLeash.try(this.paths);
218
- if (leash === null) {
219
- leash = await takeLeashUntil(this.paths, performance.now() + CONTROL_RESPONSE_MS);
220
- putDown = "self-aborted";
221
- }
222
- if (leash === null) {
223
- const body = (await readHeart(this.paths)).latestBody;
224
- return { kind: "unavailable", evidence: body?.sequence === request.body.sequence && body.hung !== undefined
225
- ? "hung"
226
- : "unavailable" };
227
- }
228
- const settledBody = (await readHeart(this.paths)).latestBody;
229
- if (settledBody?.sequence === request.body.sequence && settledBody.hung !== undefined) {
230
- try {
231
- await leash.clearPause(this.paths);
232
- }
233
- finally {
234
- leash.release();
235
- }
236
- return { kind: "unavailable", evidence: "hung" };
237
- }
238
- if (settledBody?.sequence !== request.body.sequence || settledBody.end === undefined) {
239
- try {
240
- await leash.clearPause(this.paths);
241
- }
242
- finally {
243
- leash.release();
244
- }
245
- return { kind: "unavailable", evidence: "untidy" };
246
- }
247
- if (request.body.end !== undefined || settledBody.end !== "put-down")
248
- putDown = "was-idle";
249
- let recorded;
250
- try {
251
- const id = randomUUID();
252
- const admitted = await leash.recordInterruptTell(this.paths, {
253
- kind: "tell",
254
- id,
255
- body,
256
- recordedAt: new Date().toISOString(),
257
- });
258
- if (admitted.kind === "not-born")
259
- throw new AkumaNotBornError(this.id);
260
- recorded = { kind: "recorded", tellId: admitted.tell.id };
261
- }
262
- finally {
263
- leash.release();
264
- }
265
- return { kind: "interrupted", putDown, tell: await wakeTell(this.paths, recorded.tellId) };
266
- }
267
- async fork(input) {
268
- const source = await readSoul(this.paths);
269
- if (source === null)
270
- throw new AkumaNotBornError(this.id);
271
- if (source.id !== this.id)
272
- throw new Error("Akuma soul does not match its coordinate");
273
- const adapter = (await resolveProviderExecution(source.provider)).adapter;
274
- if (adapter.fork === undefined)
275
- return { kind: "provider-cannot-fork", provider: source.provider.name };
276
- const point = await readForkPoint(this.paths, input.at);
277
- if (point === null)
278
- return { kind: "unknown-history", at: input.at };
279
- if (point.provider !== source.provider.name)
280
- throw new Error(`Akuma fork point ${input.at} has a mismatched provider`);
281
- let childSession;
282
- try {
283
- childSession = (await adapter.fork({ session: point.session, at: point.historyId, cwd: point.cwd })).session;
284
- }
285
- catch (error) {
286
- return { kind: "fork-failed", diagnostic: diagnostic(error) };
287
- }
288
- const admittedAt = new Date().toISOString();
289
- const birthSession = {
290
- provider: point.provider,
291
- coordinate: childSession,
292
- cwd: point.cwd,
293
- options: point.options,
294
- admittedAt,
295
- };
296
- try {
297
- const child = await publishAkuma({
298
- worldPath: this.worldPath,
299
- archetype: source.archetype,
300
- awaitAsleep: true,
301
- launch: async (allocated) => await spawnAkumaBody({
302
- paths: allocated.paths,
303
- seed: {
304
- id: allocated.id,
305
- archetype: source.archetype,
306
- ...(source.description === undefined ? {} : { description: source.description }),
307
- provider: source.provider,
308
- options: source.options,
309
- ...(source.readonly === undefined ? {} : { readonly: source.readonly }),
310
- allowed: source.allowed,
311
- cwd: source.cwd,
312
- origin: { kind: "fork", parent: this.id, at: input.at },
313
- },
314
- birthSession,
315
- }),
316
- });
317
- return { kind: "forked", child: child.id };
318
- }
319
- catch (error) {
320
- return {
321
- kind: "upstream-forked",
322
- childSession,
323
- diagnostic: diagnostic(error),
324
- };
325
- }
326
- }
327
- async kill() {
328
- const at = new Date().toISOString();
329
- const request = await requestStop(this.paths, at);
64
+ const request = await requestStop(paths, new Date().toISOString());
330
65
  if (request.kind !== "requested")
331
66
  return request.kind;
332
67
  const target = request.body;
333
- const graceDeadline = performance.now() + CONTROL_RESPONSE_MS;
334
- const leash = await takeLeashUntil(this.paths, graceDeadline);
335
- if (await readKill(this.paths, target.sequence) !== null) {
68
+ const leash = await takeLeashUntil(paths, performance.now() + CONTROL_RESPONSE_MS);
69
+ if ((await readKill(paths, target.sequence)) !== null) {
336
70
  leash?.release();
337
71
  return "killed";
338
72
  }
339
73
  if (leash === null) {
340
- if (await readKill(this.paths, target.sequence) !== null)
74
+ if ((await readKill(paths, target.sequence)) !== null)
341
75
  return "killed";
342
- const body = (await readHeart(this.paths)).latestBody;
76
+ const body = (await readHeart(paths)).latestBody;
343
77
  return body?.sequence === target.sequence && body.hung !== undefined ? "hung" : "unavailable";
344
78
  }
345
79
  try {
346
- const settledBody = (await readHeart(this.paths)).latestBody;
80
+ const settledBody = (await readHeart(paths)).latestBody;
347
81
  if (settledBody?.sequence !== target.sequence)
348
- return await readKill(this.paths, target.sequence) === null ? "unavailable" : "killed";
82
+ return (await readKill(paths, target.sequence)) === null ? "unavailable" : "killed";
349
83
  if (settledBody.end !== "put-down") {
350
- await leash.clearStop(this.paths);
84
+ await leash.clearStop(paths);
351
85
  return "untidy";
352
86
  }
353
- const settled = await leash.settleStop(this.paths, target.sequence);
354
- if (settled === null)
355
- return "unavailable";
356
- return "killed";
87
+ const settled = await leash.settleStop(paths, target.sequence);
88
+ return settled === null ? "unavailable" : "killed";
357
89
  }
358
90
  finally {
359
91
  leash.release();
360
92
  }
361
93
  }
362
- async lastAnswer() {
363
- const turn = await readLastAnsweredTurn(this.paths);
364
- return turn?.end?.outcome.kind === "answered"
365
- ? { kind: "answer", answer: turn.end.outcome.answer }
366
- : { kind: "no-answer" };
367
- }
368
- }
369
- /** Package-internal provenance retained only by the handle returned from call. */
370
- export function akumaCallExecution(handle) {
371
- return handle[CALL_EXECUTION];
372
- }
373
- export class Akuma {
374
- path;
375
- configuration;
376
- constructor(path, configuration) {
377
- this.path = path;
378
- this.configuration = configuration;
379
- }
380
- static of(root, input = {}) {
381
- if (typeof root !== "string")
382
- throw new TypeError("Akuma.of root must be a WorldRoot");
383
- return new Akuma(root, input);
384
- }
385
- of(input) {
386
- return new AkumaHandle(parseAkuId(input.id).id, this.path);
387
- }
388
- async listArchetypes() {
389
- return readArchetypes(this.configuration.home === undefined ? {} : { home: this.configuration.home });
390
- }
391
- async call(input) {
392
- return await this[CALL_WITH_CONTEXT](input, { initiatorCwd: process.cwd() });
393
- }
394
- async [CALL_WITH_CONTEXT](input, context) {
395
- const readonly = callReadonly(input.readonly);
396
- const name = archetypeName(input.archetype);
397
- const home = this.configuration.home === undefined ? {} : { home: this.configuration.home };
398
- const settings = this.configuration.settings ?? await readSettings({ root: this.path, ...home });
399
- const archetype = await loadArchetype({
400
- name,
401
- ...home,
402
- settings,
403
- ...readonly,
404
- });
405
- const allowed = input.allowed === undefined
406
- ? archetype.allowed
407
- : decodeAllowedActions(input.allowed, "Akuma call allowed");
408
- const requests = injectedBodyRequests();
409
- const requestRecipe = Object.freeze({
410
- ...(archetype.description === undefined ? {} : { description: archetype.description }),
411
- provider: archetype.provider,
412
- options: archetype.options,
413
- ...(archetype.readonly === undefined ? {} : { readonly: archetype.readonly }),
414
- allowed,
415
- });
416
- if (requests !== null) {
417
- const cwd = input.cwd === undefined
418
- ? undefined
419
- : context?.cwdCanonical === true ? input.cwd : await canonicalBirthCwd(input.cwd);
420
- const child = await requestBodyCall({
421
- directory: requests,
422
- id: randomUUID(),
423
- world: this.path,
424
- archetype: name,
425
- body: input.body,
426
- ...(cwd === undefined ? {} : { cwd }),
427
- recipe: requestRecipe,
428
- });
429
- const bornCwd = await readAkumaBirthCwd(this.path, child);
430
- return new AkumaHandle(child, this.path, {
431
- cwd: bornCwd,
432
- source: cwd === undefined ? "caller" : "input",
433
- });
434
- }
435
- const initiatorCwd = context.initiatorCwd;
436
- const selectedCwd = input.cwd ?? initiatorCwd ?? this.path;
437
- const cwd = input.cwd !== undefined && context?.cwdCanonical === true
438
- ? input.cwd
439
- : await canonicalBirthCwd(selectedCwd);
440
- const recipe = requestRecipe;
441
- const published = await publishAkuma({
442
- worldPath: this.path,
443
- archetype: archetype.name,
444
- launch: async (allocated) => await spawnAkumaBody({
445
- paths: allocated.paths,
446
- seed: {
447
- id: allocated.id,
448
- archetype: allocated.archetype,
449
- ...recipe,
450
- cwd,
451
- origin: { kind: "direct" },
452
- },
453
- initialBody: input.body,
454
- }),
455
- });
456
- return new AkumaHandle(published.id, this.path, {
457
- cwd,
458
- source: input.cwd !== undefined ? "input" : initiatorCwd === undefined ? "world" : "process",
459
- });
460
- }
461
- async list(input = {}) {
462
- if (typeof input !== "object" || input === null || Array.isArray(input)) {
463
- throw new TypeError("Akuma list input must be an object");
464
- }
465
- const unknown = Object.keys(input).find((key) => key !== "archetype");
466
- if (unknown !== undefined)
467
- throw new TypeError(`Akuma list input has unknown field: ${unknown}`);
468
- const selected = input.archetype === undefined ? undefined : archetypeName(input.archetype);
469
- const runRoot = akumaRunRoot(this.path);
470
- let names;
471
- try {
472
- names = (await readdir(runRoot, { withFileTypes: true }))
473
- .filter((entry) => entry.isDirectory())
474
- .map((entry) => entry.name)
475
- .sort();
476
- }
477
- catch (error) {
478
- if (error.code === "ENOENT")
479
- return { rows: [], searched: [runRoot] };
480
- throw error;
481
- }
482
- const rows = [];
483
- for (const name of names) {
484
- let physical;
485
- try {
486
- physical = akuIdFromDirectoryName(name);
487
- }
488
- catch {
489
- continue;
490
- }
491
- if (selected !== undefined && physical.archetype !== selected)
492
- continue;
493
- const paths = akumaPaths({ runRoot, archetype: physical.archetype, suffix: physical.suffix });
494
- try {
495
- rows.push(await fleetListRow(paths, physical.id));
496
- }
497
- catch { }
498
- }
499
- return {
500
- rows,
501
- searched: [runRoot],
502
- };
94
+ finally {
95
+ void recover(paths).catch(() => undefined);
503
96
  }
504
97
  }
505
- /** Package-internal call path for a composition owner that already canonicalized cwd. */
506
- export async function callAkumaWithContext(akuma, input, context) {
507
- return await akuma[CALL_WITH_CONTEXT](input, context);
508
- }
98
+ export { bornStatus, fleetListRow, readAkumaBirthCwd, readBudgetedStatus, } from "./akuma-observe.js";
99
+ export { AkumaHandle, akumaCallExecution } from "./akuma-handle.js";
100
+ export { Akuma, callAkumaWithContext } from "./akuma-product.js";
@@ -4,4 +4,5 @@ export type AllowedActions = readonly AllowedAction[];
4
4
  export declare function isAllowedAction(value: unknown): value is AllowedAction;
5
5
  export declare function decodeAllowedActions(value: unknown, label?: string): AllowedActions;
6
6
  export declare function effectiveAllowedActions(value: unknown): AllowedActions;
7
+ export declare function unionAllowedActions(base: AllowedActions, additions: AllowedActions): AllowedActions;
7
8
  export declare function clipAllowedActions(requested: AllowedActions, parent: AllowedActions): AllowedActions;
@@ -27,6 +27,12 @@ export function decodeAllowedActions(value, label = "allowed") {
27
27
  export function effectiveAllowedActions(value) {
28
28
  return value === undefined ? ALLOWED_ACTIONS : decodeAllowedActions(value);
29
29
  }
30
+ export function unionAllowedActions(base, additions) {
31
+ const merged = new Set(base);
32
+ for (const action of additions)
33
+ merged.add(action);
34
+ return Object.freeze([...merged].sort());
35
+ }
30
36
  export function clipAllowedActions(requested, parent) {
31
37
  const ceiling = new Set(parent);
32
38
  return Object.freeze(requested.filter((action) => ceiling.has(action)));
@@ -110,10 +110,12 @@ function decodeArchetype(name, path, markdown) {
110
110
  ...(model === undefined ? {} : { model }),
111
111
  ...(effort === undefined ? {} : { effort }),
112
112
  ...(network === undefined ? {} : { network }),
113
- ...(systemPrompt.length === 0 ? {} : {
114
- systemPrompt,
115
- systemPromptMode: systemPromptMode ?? "append",
116
- }),
113
+ ...(systemPrompt.length === 0
114
+ ? {}
115
+ : {
116
+ systemPrompt,
117
+ systemPromptMode: systemPromptMode ?? "append",
118
+ }),
117
119
  }),
118
120
  ...(readonly === undefined ? {} : { readonly }),
119
121
  allowed,
@@ -142,7 +144,8 @@ export async function listArchetypeDefinitions(input = {}) {
142
144
  }
143
145
  function record(value) {
144
146
  return value !== null && typeof value === "object" && !Array.isArray(value)
145
- ? value : null;
147
+ ? value
148
+ : null;
146
149
  }
147
150
  function optionalProviderText(value, name, field) {
148
151
  const selected = value[field];
@@ -0,0 +1,26 @@
1
+ import { type HeartSnapshot, type HeldAkumaLeash } from "./heart/index.js";
2
+ import type { AkumaPaths } from "./identity.js";
3
+ export declare const CONTROL_RESPONSE_MS = 1000;
4
+ export declare class BodySupervisor {
5
+ private readonly paths;
6
+ private readonly bodySequence;
7
+ private readonly leash;
8
+ readonly signal: AbortSignal;
9
+ private readonly controller;
10
+ private readonly finished;
11
+ private readonly observer;
12
+ private waiter;
13
+ private observation;
14
+ private stopping?;
15
+ private constructor();
16
+ static open(paths: AkumaPaths, bodySequence: number, leash: HeldAkumaLeash): Promise<BodySupervisor>;
17
+ get reason(): "control" | "heart-gone" | undefined;
18
+ current(): HeartSnapshot;
19
+ recordHung(diagnostic: string, at: string): Promise<void>;
20
+ refresh(): Promise<HeartSnapshot>;
21
+ next(after: HeartSnapshot): Promise<HeartSnapshot>;
22
+ cancel(reason: "control" | "heart-gone"): void;
23
+ close(): Promise<void>;
24
+ private publish;
25
+ private observe;
26
+ }