@astrosheep/keiyaku 4.6.8 → 4.6.9

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 (253) hide show
  1. package/README.md +40 -14
  2. package/build/plugins/claude/.claude-plugin/plugin.json +1 -1
  3. package/build/plugins/claude/skills/keiyaku/SKILL.md +5 -6
  4. package/build/plugins/claude/skills/keiyaku-akuma/SKILL.md +1 -1
  5. package/build/plugins/claude/skills/keiyaku-akuma/references/automation.md +8 -8
  6. package/build/plugins/claude/skills/keiyaku-babysit/SKILL.md +1 -1
  7. package/build/plugins/claude/skills/keiyaku-bind/SKILL.md +9 -9
  8. package/build/plugins/claude/skills/keiyaku-debt/SKILL.md +91 -0
  9. package/build/plugins/claude/skills/keiyaku-workflow/SKILL.md +2 -2
  10. package/build/plugins/codex/.codex-plugin/plugin.json +1 -1
  11. package/build/plugins/codex/skills/keiyaku/SKILL.md +5 -6
  12. package/build/plugins/codex/skills/keiyaku-akuma/SKILL.md +1 -1
  13. package/build/plugins/codex/skills/keiyaku-akuma/references/automation.md +8 -8
  14. package/build/plugins/codex/skills/keiyaku-babysit/SKILL.md +1 -1
  15. package/build/plugins/codex/skills/keiyaku-bind/SKILL.md +9 -9
  16. package/build/plugins/codex/skills/keiyaku-debt/SKILL.md +91 -0
  17. package/build/plugins/codex/skills/keiyaku-workflow/SKILL.md +2 -2
  18. package/build/plugins/opencode/index.js +1 -1
  19. package/build/plugins/opencode/skills/keiyaku/SKILL.md +5 -6
  20. package/build/plugins/opencode/skills/keiyaku-akuma/SKILL.md +1 -1
  21. package/build/plugins/opencode/skills/keiyaku-akuma/references/automation.md +8 -8
  22. package/build/plugins/opencode/skills/keiyaku-babysit/SKILL.md +1 -1
  23. package/build/plugins/opencode/skills/keiyaku-bind/SKILL.md +9 -9
  24. package/build/plugins/opencode/skills/keiyaku-debt/SKILL.md +91 -0
  25. package/build/plugins/opencode/skills/keiyaku-workflow/SKILL.md +2 -2
  26. package/build/skills/keiyaku/SKILL.md +5 -6
  27. package/build/skills/keiyaku-akuma/SKILL.md +1 -1
  28. package/build/skills/keiyaku-akuma/references/automation.md +8 -8
  29. package/build/skills/keiyaku-babysit/SKILL.md +1 -1
  30. package/build/skills/keiyaku-bind/SKILL.md +9 -9
  31. package/build/skills/keiyaku-debt/SKILL.md +91 -0
  32. package/build/skills/keiyaku-workflow/SKILL.md +2 -2
  33. package/build/src/akuma/akuma-instance.d.ts +2 -0
  34. package/build/src/akuma/akuma-instance.js +10 -0
  35. package/build/src/akuma/akuma-observe.d.ts +33 -8
  36. package/build/src/akuma/akuma-observe.js +88 -64
  37. package/build/src/akuma/akuma-owner.d.ts +11 -2
  38. package/build/src/akuma/akuma-owner.js +45 -35
  39. package/build/src/akuma/akuma-selection-execution.js +9 -1
  40. package/build/src/akuma/akuma-stream.d.ts +22 -0
  41. package/build/src/akuma/akuma-stream.js +116 -0
  42. package/build/src/akuma/akuma-wait.d.ts +1 -40
  43. package/build/src/akuma/akuma-wait.js +23 -84
  44. package/build/src/akuma/akuma.d.ts +17 -11
  45. package/build/src/akuma/akuma.js +2 -0
  46. package/build/src/akuma/allowed.d.ts +7 -12
  47. package/build/src/akuma/allowed.js +13 -4
  48. package/build/src/akuma/body-supervisor.d.ts +5 -5
  49. package/build/src/akuma/body-supervisor.js +22 -20
  50. package/build/src/akuma/body.js +28 -1
  51. package/build/src/akuma/call-request.d.ts +12 -22
  52. package/build/src/akuma/heart/activity-schema.d.ts +12 -0
  53. package/build/src/akuma/heart/activity-schema.js +6 -0
  54. package/build/src/akuma/heart/index.d.ts +59 -2
  55. package/build/src/akuma/heart/index.js +87 -8
  56. package/build/src/akuma/heart/rows.js +5 -3
  57. package/build/src/akuma/heart/soul.d.ts +9 -0
  58. package/build/src/akuma/heart/soul.js +29 -0
  59. package/build/src/akuma/heart/storage.d.ts +15 -0
  60. package/build/src/akuma/heart/storage.js +55 -0
  61. package/build/src/akuma/heart/timeline.d.ts +7 -0
  62. package/build/src/akuma/heart/timeline.js +10 -0
  63. package/build/src/akuma/index.d.ts +1 -0
  64. package/build/src/akuma/projection.d.ts +25 -0
  65. package/build/src/akuma/projection.js +24 -7
  66. package/build/src/akuma/provider-recipe.d.ts +11 -0
  67. package/build/src/akuma/provider-recipe.js +23 -0
  68. package/build/src/akuma/provider.d.ts +25 -0
  69. package/build/src/akuma/provider.js +99 -7
  70. package/build/src/akuma/providers/acp/events.js +25 -2
  71. package/build/src/akuma/providers/claude/events.js +76 -10
  72. package/build/src/akuma/providers/claude/index.js +2 -5
  73. package/build/src/akuma/providers/codex-app-server/events.js +17 -2
  74. package/build/src/akuma/providers/codex-app-server/index.js +15 -9
  75. package/build/src/akuma/providers/decode.d.ts +8 -0
  76. package/build/src/akuma/providers/decode.js +21 -0
  77. package/build/src/akuma/providers/grok-build/index.js +10 -26
  78. package/build/src/akuma/providers/opencode-sdk/event-stream.d.ts +3 -3
  79. package/build/src/akuma/providers/opencode-sdk/event-stream.js +2 -25
  80. package/build/src/akuma/providers/opencode-sdk/events.d.ts +7 -43
  81. package/build/src/akuma/providers/opencode-sdk/events.js +147 -284
  82. package/build/src/akuma/providers/opencode-sdk/index.js +267 -421
  83. package/build/src/akuma/providers/opencode-sdk/native-http.d.ts +9 -0
  84. package/build/src/akuma/providers/opencode-sdk/native-http.js +69 -0
  85. package/build/src/akuma/providers/opencode-sdk/session.d.ts +42 -36
  86. package/build/src/akuma/providers/opencode-sdk/session.js +75 -82
  87. package/build/src/akuma/providers/paseo/events.d.ts +8 -0
  88. package/build/src/akuma/providers/paseo/events.js +58 -11
  89. package/build/src/akuma/providers/paseo/index.js +11 -7
  90. package/build/src/akuma/providers/pi/events.d.ts +2 -0
  91. package/build/src/akuma/providers/pi/events.js +32 -24
  92. package/build/src/akuma/providers/pi/index.js +21 -35
  93. package/build/src/akuma/request-lifecycle.d.ts +1 -2
  94. package/build/src/akuma/request-lifecycle.js +2 -8
  95. package/build/src/akuma/request-rendezvous.js +38 -55
  96. package/build/src/akuma/request-serve.d.ts +1 -1
  97. package/build/src/akuma/request-serve.js +77 -113
  98. package/build/src/akuma/selection-observation.d.ts +57 -51
  99. package/build/src/akuma/selection-observation.js +3 -3
  100. package/build/src/akuma/turn-drive.d.ts +3 -0
  101. package/build/src/akuma/turn-drive.js +26 -5
  102. package/build/src/akuma-body.js +12 -22
  103. package/build/src/cli/akuma-caller.js +10 -0
  104. package/build/src/cli/commands/akuma-grammar.js +3 -4
  105. package/build/src/cli/commands/akuma.js +13 -51
  106. package/build/src/cli/commands/contract-grammar.d.ts +7 -6
  107. package/build/src/cli/commands/contract-grammar.js +27 -32
  108. package/build/src/cli/commands/contract-help.d.ts +16 -7
  109. package/build/src/cli/commands/contract-help.js +20 -11
  110. package/build/src/cli/commands/contract.js +11 -11
  111. package/build/src/cli/commands/debt-grammar.d.ts +19 -0
  112. package/build/src/cli/commands/debt-grammar.js +323 -0
  113. package/build/src/cli/commands/debt-query.d.ts +5 -0
  114. package/build/src/cli/commands/{task-query.js → debt-query.js} +9 -9
  115. package/build/src/cli/commands/{task.d.ts → debt.d.ts} +2 -2
  116. package/build/src/cli/commands/{task.js → debt.js} +83 -143
  117. package/build/src/cli/coordinates.d.ts +1 -1
  118. package/build/src/cli/coordinates.js +1 -1
  119. package/build/src/cli/parse.d.ts +4 -4
  120. package/build/src/cli/parse.js +17 -16
  121. package/build/src/cli/render/akuma-activity.d.ts +11 -83
  122. package/build/src/cli/render/akuma-activity.js +20 -382
  123. package/build/src/cli/render/catalog.d.ts +2 -2
  124. package/build/src/cli/render/catalog.js +5 -5
  125. package/build/src/cli/render/contract.js +2 -2
  126. package/build/src/cli/render/debt.d.ts +28 -0
  127. package/build/src/cli/render/{task.js → debt.js} +51 -112
  128. package/build/src/cli/render/kanshi.js +28 -28
  129. package/build/src/cli/render/marks.d.ts +5 -5
  130. package/build/src/cli/render/marks.js +4 -10
  131. package/build/src/cli/render/nuke.js +1 -1
  132. package/build/src/cli/runtime.js +3 -3
  133. package/build/src/cli/scan.d.ts +1 -1
  134. package/build/src/cli/usage.d.ts +1 -1
  135. package/build/src/cli/usage.js +4 -4
  136. package/build/src/contract-worktree.js +3 -3
  137. package/build/src/debt/board.d.ts +160 -0
  138. package/build/src/{task → debt}/board.js +89 -89
  139. package/build/src/debt/catalog.d.ts +11 -0
  140. package/build/src/debt/catalog.js +59 -0
  141. package/build/src/{task → debt}/context.d.ts +1 -1
  142. package/build/src/{task → debt}/context.js +1 -1
  143. package/build/src/{task → debt}/created-observation.d.ts +6 -10
  144. package/build/src/{task → debt}/created-observation.js +7 -7
  145. package/build/src/debt/document.d.ts +37 -0
  146. package/build/src/{task → debt}/document.js +37 -37
  147. package/build/src/debt/identity.d.ts +21 -0
  148. package/build/src/{task → debt}/identity.js +35 -35
  149. package/build/src/debt/index.d.ts +111 -0
  150. package/build/src/debt/index.js +203 -0
  151. package/build/src/{task → debt}/input.d.ts +8 -8
  152. package/build/src/{task → debt}/input.js +21 -21
  153. package/build/src/debt/lifecycle-operations.d.ts +6 -0
  154. package/build/src/{task → debt}/lifecycle-operations.js +27 -31
  155. package/build/src/debt/mutation-result.d.ts +981 -0
  156. package/build/src/debt/mutation-result.js +109 -0
  157. package/build/src/debt/mutation.d.ts +424 -0
  158. package/build/src/debt/mutation.js +223 -0
  159. package/build/src/debt/operation-types.d.ts +71 -0
  160. package/build/src/debt/operations.d.ts +28 -0
  161. package/build/src/{task → debt}/operations.js +59 -60
  162. package/build/src/debt/query.d.ts +76 -0
  163. package/build/src/{task → debt}/query.js +55 -55
  164. package/build/src/{task → debt}/store.d.ts +13 -13
  165. package/build/src/{task → debt}/store.js +58 -49
  166. package/build/src/debt/view.d.ts +4 -0
  167. package/build/src/debt/view.js +7 -0
  168. package/build/src/identity/coordinates.d.ts +1 -1
  169. package/build/src/index.d.ts +13 -13
  170. package/build/src/index.js +9 -9
  171. package/build/src/kanshi/index.d.ts +1 -1
  172. package/build/src/kanshi/read.js +33 -33
  173. package/build/src/kanshi/report.d.ts +7 -7
  174. package/build/src/kanshi/select.js +4 -4
  175. package/build/src/library/akumas.d.ts +2 -3
  176. package/build/src/library/bind.d.ts +3 -3
  177. package/build/src/library/bind.js +5 -5
  178. package/build/src/library/contract-creation.js +5 -5
  179. package/build/src/library/contract-execution.js +4 -4
  180. package/build/src/library/contract-types.d.ts +2 -2
  181. package/build/src/library/input.d.ts +2 -2
  182. package/build/src/library/input.js +5 -5
  183. package/build/src/library/invocation.js +2 -2
  184. package/build/src/library/nuke.js +3 -3
  185. package/build/src/library/outcome.d.ts +126 -126
  186. package/build/src/library/outcome.js +3 -3
  187. package/build/src/library/selection.d.ts +1 -4
  188. package/build/src/library/selection.js +11 -62
  189. package/build/src/plugin/public.d.ts +5 -0
  190. package/build/src/plugin/runtime.js +3 -1
  191. package/build/src/runtime/proc/windows-launch.exe +0 -0
  192. package/build/src/settlement/fence.d.ts +3 -3
  193. package/build/src/settlement/fence.js +4 -4
  194. package/build/src/settlement/holder.d.ts +16 -16
  195. package/build/src/settlement/holder.js +69 -63
  196. package/build/src/settlement/settle.d.ts +5 -5
  197. package/build/src/settlement/settle.js +53 -53
  198. package/package.json +12 -6
  199. package/plugins/paseo/plugin/index.server.ts +17 -0
  200. package/plugins/paseo/plugin/paseo-plugin.json +4 -0
  201. package/plugins/paseo/plugin/server/attach.ts +52 -0
  202. package/plugins/paseo/plugin/server/keiyaku.ts +44 -0
  203. package/plugins/paseo/plugin/server/message.ts +60 -0
  204. package/plugins/paseo/plugin/server/mirror.ts +193 -0
  205. package/plugins/paseo/plugin/server/model.ts +14 -0
  206. package/plugins/paseo/plugin/server/provider.ts +276 -0
  207. package/plugins/paseo/plugin/server/sdk-worker.ts +237 -0
  208. package/plugins/paseo/plugin/server/sdk.ts +289 -0
  209. package/plugins/paseo/plugin/server/stop.ts +26 -0
  210. package/plugins/paseo/plugin/server/transport.ts +35 -0
  211. package/plugins/paseo/plugin/shared/attach-rpc.ts +10 -0
  212. package/plugins/paseo/plugin/shared/refresh-rpc.ts +6 -0
  213. package/plugins/paseo/plugin/tsconfig.json +6 -0
  214. package/skills/keiyaku/SKILL.md +5 -6
  215. package/skills/keiyaku-akuma/SKILL.md +1 -1
  216. package/skills/keiyaku-akuma/references/automation.md +8 -8
  217. package/skills/keiyaku-babysit/SKILL.md +1 -1
  218. package/skills/keiyaku-bind/SKILL.md +9 -9
  219. package/skills/keiyaku-debt/SKILL.md +91 -0
  220. package/skills/keiyaku-workflow/SKILL.md +2 -2
  221. package/build/plugins/claude/skills/keiyaku-task/SKILL.md +0 -104
  222. package/build/plugins/codex/skills/keiyaku-task/SKILL.md +0 -104
  223. package/build/plugins/opencode/skills/keiyaku-task/SKILL.md +0 -104
  224. package/build/skills/keiyaku-task/SKILL.md +0 -104
  225. package/build/src/cli/commands/task-grammar.d.ts +0 -19
  226. package/build/src/cli/commands/task-grammar.js +0 -384
  227. package/build/src/cli/commands/task-query.d.ts +0 -5
  228. package/build/src/cli/render/task.d.ts +0 -39
  229. package/build/src/task/board.d.ts +0 -168
  230. package/build/src/task/catalog.d.ts +0 -11
  231. package/build/src/task/catalog.js +0 -59
  232. package/build/src/task/compose-language.d.ts +0 -57
  233. package/build/src/task/compose-language.js +0 -364
  234. package/build/src/task/compose-parser.d.ts +0 -32
  235. package/build/src/task/compose-parser.js +0 -180
  236. package/build/src/task/compose.d.ts +0 -16
  237. package/build/src/task/compose.js +0 -189
  238. package/build/src/task/document.d.ts +0 -39
  239. package/build/src/task/identity.d.ts +0 -21
  240. package/build/src/task/index.d.ts +0 -138
  241. package/build/src/task/index.js +0 -269
  242. package/build/src/task/lifecycle-operations.d.ts +0 -6
  243. package/build/src/task/mutation-result.d.ts +0 -1726
  244. package/build/src/task/mutation-result.js +0 -198
  245. package/build/src/task/mutation.d.ts +0 -590
  246. package/build/src/task/mutation.js +0 -262
  247. package/build/src/task/operation-types.d.ts +0 -71
  248. package/build/src/task/operations.d.ts +0 -28
  249. package/build/src/task/query.d.ts +0 -76
  250. package/build/src/task/view.d.ts +0 -4
  251. package/build/src/task/view.js +0 -7
  252. package/skills/keiyaku-task/SKILL.md +0 -104
  253. /package/build/src/{task → debt}/operation-types.js +0 -0
@@ -1,7 +1,7 @@
1
1
  import { abortable } from "../../abort.js";
2
2
  import { akumaExecutionEnvironment } from "../execution-environment.js";
3
- import { AgentEventChannel, createProviderAttempt, } from "../../provider.js";
4
- import { piTerminalFailure, translatePiEvent } from "./events.js";
3
+ import { AgentEventChannel, createProviderAttempt, launchPrompt, modelEvent, tellRegistry, } from "../../provider.js";
4
+ import { piSessionModel, piTerminalFailure, translatePiEvent } from "./events.js";
5
5
  const PI_THINKING_LEVELS = new Set(["minimal", "low", "medium", "high", "xhigh", "max"]);
6
6
  const MODEL_PATTERN = /^[^/\s]+\/[^\s]+$/u;
7
7
  function diagnostic(error) {
@@ -83,15 +83,7 @@ async function createPiSession(sdk, execution, input) {
83
83
  }
84
84
  async function runPiPrompt(native, input, events, state, settle) {
85
85
  try {
86
- const prompt = [input.body, ...input.launchTells.map((tell) => tell.text)]
87
- .filter((part) => part.length > 0)
88
- .join("\n\n");
89
- const schemaPrompt = input.schemaJson === undefined
90
- ? prompt
91
- : [prompt, "Respond with JSON matching this JSON Schema and no other text:", input.schemaJson]
92
- .filter((part) => part.length > 0)
93
- .join("\n\n");
94
- await native.prompt(schemaPrompt);
86
+ await native.prompt(launchPrompt(input.body, input.launchTells, input.schemaJson));
95
87
  let result;
96
88
  if (state.aborting)
97
89
  result = { kind: "failed", diagnostic: "Pi session aborted" };
@@ -162,17 +154,15 @@ async function drivePi(sdk, execution, input, signal, custody) {
162
154
  aborting: false,
163
155
  settled: false,
164
156
  };
165
- const pendingTells = new Map();
166
- const endPendingTells = () => {
167
- for (const waiter of pendingTells.values())
168
- waiter.resolve({ kind: "turn-ended" });
169
- pendingTells.clear();
170
- };
157
+ const tells = tellRegistry((id) => `${native.sessionId}:${id}`);
171
158
  let settleCompletion;
172
159
  const completion = new Promise((resolve) => {
173
160
  settleCompletion = resolve;
174
161
  });
175
162
  const agent = native.agent;
163
+ // Tells are harness input, not interactive typing: deliver every queued one at
164
+ // the next boundary regardless of the user's interactive Pi setting.
165
+ agent.steeringMode = "all";
176
166
  let unsubscribeAgent;
177
167
  let unsubscribe;
178
168
  let binding;
@@ -180,7 +170,7 @@ async function drivePi(sdk, execution, input, signal, custody) {
180
170
  if (state.settled)
181
171
  return closed;
182
172
  state.settled = true;
183
- endPendingTells();
173
+ tells.end();
184
174
  let failure;
185
175
  try {
186
176
  unsubscribe?.();
@@ -219,13 +209,8 @@ async function drivePi(sdk, execution, input, signal, custody) {
219
209
  custody?.own({ closed, abort: forceDispose, forceDispose });
220
210
  try {
221
211
  unsubscribeAgent = agent.subscribe((event) => {
222
- if (event.type === "message_end") {
223
- const waiter = pendingTells.get(event.message);
224
- if (waiter !== undefined) {
225
- pendingTells.delete(event.message);
226
- waiter.resolve({ kind: "accepted", fence: `${native.sessionId}:${waiter.id}` });
227
- }
228
- }
212
+ if (event.type === "message_end")
213
+ tells.accept(event.message);
229
214
  });
230
215
  unsubscribe = native.subscribe((event) => {
231
216
  if (event.type === "agent_end" && !event.willRetry) {
@@ -251,6 +236,9 @@ async function drivePi(sdk, execution, input, signal, custody) {
251
236
  await abortable(binding, signal);
252
237
  signal.throwIfAborted();
253
238
  events.emit({ type: "session", coordinate: { sessionFile: native.sessionFile, sessionId: native.sessionId } });
239
+ const sessionModel = piSessionModel(native.model);
240
+ if (sessionModel !== undefined)
241
+ events.emit(modelEvent(sessionModel));
254
242
  void runPiPrompt(native, input, eventState, state, (result) => {
255
243
  void settle(result).catch(() => undefined);
256
244
  });
@@ -266,16 +254,14 @@ async function drivePi(sdk, execution, input, signal, custody) {
266
254
  content: [{ type: "text", text: tell.text }],
267
255
  timestamp: new Date().getTime(),
268
256
  };
269
- return new Promise((resolve, reject) => {
270
- pendingTells.set(message, { id: tell.id, resolve });
271
- try {
272
- agent.steer(message);
273
- }
274
- catch (error) {
275
- pendingTells.delete(message);
276
- reject(error);
277
- }
278
- });
257
+ const submission = tells.register(message, tell.id);
258
+ try {
259
+ agent.steer(message);
260
+ }
261
+ catch (error) {
262
+ tells.fail(message, error);
263
+ }
264
+ return submission;
279
265
  },
280
266
  abort: () => {
281
267
  state.abortRequest ??= (async () => {
@@ -14,7 +14,7 @@ type ServeClaim = (input: PumpInput & Readonly<{
14
14
  claim: RequestEnvelope;
15
15
  signal: AbortSignal;
16
16
  admissionOpen(): boolean;
17
- }>) => Promise<boolean>;
17
+ }>) => Promise<void>;
18
18
  export declare class BodyRequestPump {
19
19
  private readonly input;
20
20
  private readonly serveClaim;
@@ -23,7 +23,6 @@ export declare class BodyRequestPump {
23
23
  readonly failure: Promise<never>;
24
24
  private readonly closeSignal;
25
25
  private readonly executionSignal;
26
- private readonly handled;
27
26
  private readonly running;
28
27
  private readonly cancelBody;
29
28
  private admissionClosed;
@@ -14,7 +14,6 @@ export class BodyRequestPump {
14
14
  failure;
15
15
  closeSignal = new AbortController();
16
16
  executionSignal = new AbortController();
17
- handled = new Set();
18
17
  running;
19
18
  cancelBody;
20
19
  admissionClosed = false;
@@ -54,8 +53,6 @@ export class BodyRequestPump {
54
53
  if (this.closeSignal.signal.aborted)
55
54
  return;
56
55
  const transportId = name.slice(0, -".request.json".length);
57
- if (this.handled.has(transportId))
58
- continue;
59
56
  const path = join(this.directory, name);
60
57
  let serialized;
61
58
  try {
@@ -69,11 +66,10 @@ export class BodyRequestPump {
69
66
  const claim = decodeEnvelope(serialized, transportId);
70
67
  if (claim === null) {
71
68
  await rm(path, { force: true });
72
- this.handled.add(transportId);
73
69
  continue;
74
70
  }
75
71
  if (!this.admissionClosed) {
76
- const served = await this.serveClaim({
72
+ await this.serveClaim({
77
73
  directory: this.directory,
78
74
  transportId,
79
75
  claim,
@@ -81,10 +77,8 @@ export class BodyRequestPump {
81
77
  signal: this.executionSignal.signal,
82
78
  admissionOpen: () => !this.admissionClosed,
83
79
  });
84
- if (!served)
85
- await rm(path, { force: true });
86
80
  }
87
- this.handled.add(transportId);
81
+ await rm(path, { force: true });
88
82
  }
89
83
  try {
90
84
  await abortableDelay(POLL_MS, this.closeSignal.signal);
@@ -19,15 +19,6 @@ export class AkumaBodyRequestError extends Error {
19
19
  this.name = "AkumaBodyRequestError";
20
20
  }
21
21
  }
22
- function throwVoidedRequestFailure(action, evidence, failure, decodeFailure, requestId) {
23
- const ownerFailure = decodeOwnerFailure(failure, decodeFailure);
24
- if (ownerFailure !== null)
25
- throw withRequestMetadata(ownerFailure, requestId, action);
26
- throw new AkumaBodyRequestError(action, "voided", evidence, requestId);
27
- }
28
- function throwUnprovenRequestFailure(action, evidence, requestId, ownerFailure) {
29
- throw new AkumaBodyRequestError(action, "unproven", evidence, requestId, ownerFailure === null ? undefined : { cause: ownerFailure });
30
- }
31
22
  function decodeOwnerFailure(failure, decodeFailure) {
32
23
  if (failure === undefined || decodeFailure === undefined)
33
24
  return null;
@@ -46,59 +37,49 @@ function withRequestMetadata(response, id, action) {
46
37
  return response;
47
38
  }
48
39
  async function readRequestReceipt(input, path, id) {
40
+ let bytes;
49
41
  try {
50
- const receipt = decodeReceiptEnvelope(await readFile(path, "utf8"), id, input.command.action);
51
- if (receipt === null)
52
- throw new Error(`Akuma body request ${id} has an invalid receipt`);
53
- if (receipt.state === "refused") {
54
- throw new AkumaBodyRequestError(receipt.action, "refused", receipt.diagnostic, receipt.id);
55
- }
56
- if (receipt.state === "voided" && receipt.outcome !== undefined) {
57
- let result;
58
- try {
59
- result = input.command.decodeResult(receipt.outcome);
60
- }
61
- catch (error) {
62
- throw new Error(`transport integrity: invalid voided live result: ${error instanceof Error ? error.message : String(error)}`);
63
- }
64
- return withRequestMetadata({ kind: "returned", result }, id, input.command.action);
65
- }
66
- if (receipt.state === "voided") {
67
- throwVoidedRequestFailure(receipt.action, receipt.evidence, receipt.failure, input.command.decodeFailure, receipt.id);
68
- }
69
- if (receipt.state === "unproven") {
70
- throwUnprovenRequestFailure(receipt.action, receipt.evidence, receipt.id, decodeOwnerFailure(receipt.failure, input.command.decodeFailure));
71
- }
72
- if ("reference" in receipt) {
73
- let reference;
74
- try {
75
- reference = input.command.decodeReference(receipt.reference);
76
- }
77
- catch (error) {
78
- const diagnostic = error instanceof Error ? error.message : String(error);
79
- throw new Error(`transport integrity: request ${id} action ${input.command.action} returned an invalid durable reference: ${diagnostic}`);
80
- }
81
- return withRequestMetadata({ kind: "reference", reference }, id, input.command.action);
82
- }
83
- if (receipt.outcome.kind === "failed") {
84
- const failure = receipt.outcome.failure;
85
- throw new Error(failure.kind === "failed" ? failure.diagnostic : `Akuma ${failure.id} was not born`);
86
- }
87
- let result;
88
- try {
89
- result = input.command.decodeResult(receipt.outcome.result);
90
- }
91
- catch (error) {
92
- const diagnostic = error instanceof Error ? error.message : String(error);
93
- throw new Error(`transport integrity: request ${id} action ${input.command.action} returned an invalid live result: ${diagnostic}`);
94
- }
95
- return withRequestMetadata({ kind: "returned", result }, id, input.command.action);
42
+ bytes = await readFile(path, "utf8");
96
43
  }
97
44
  catch (error) {
98
45
  if (error.code === "ENOENT")
99
46
  return undefined;
100
47
  throw error;
101
48
  }
49
+ return decodeRequestReceipt(input.command, bytes, id);
50
+ }
51
+ function decodeRequestReceipt(command, bytes, id) {
52
+ const receipt = decodeReceiptEnvelope(bytes, id, command.action);
53
+ if (receipt === null)
54
+ throw new Error(`Akuma body request ${id} has an invalid receipt`);
55
+ if (receipt.state === "refused") {
56
+ throw new AkumaBodyRequestError(receipt.action, "refused", receipt.diagnostic, receipt.id);
57
+ }
58
+ if (receipt.state === "unproven" || (receipt.state === "voided" && receipt.outcome === undefined)) {
59
+ const failure = decodeOwnerFailure(receipt.failure, command.decodeFailure);
60
+ if (receipt.state === "voided" && failure !== null)
61
+ throw withRequestMetadata(failure, id, command.action);
62
+ throw new AkumaBodyRequestError(command.action, receipt.state, receipt.evidence, id, failure === null ? undefined : { cause: failure });
63
+ }
64
+ if (receipt.state === "served" && "outcome" in receipt && receipt.outcome.kind === "failed") {
65
+ const failure = receipt.outcome.failure;
66
+ throw new Error(failure.kind === "failed" ? failure.diagnostic : `Akuma ${failure.id} was not born`);
67
+ }
68
+ const label = "reference" in receipt ? "durable reference" : receipt.state === "voided" ? "voided live result" : "live result";
69
+ try {
70
+ if ("reference" in receipt) {
71
+ return withRequestMetadata({ kind: "reference", reference: command.decodeReference(receipt.reference) }, id, command.action);
72
+ }
73
+ const value = receipt.state === "voided"
74
+ ? receipt.outcome
75
+ : receipt.outcome.kind === "returned"
76
+ ? receipt.outcome.result
77
+ : undefined;
78
+ return withRequestMetadata({ kind: "returned", result: command.decodeResult(value) }, id, command.action);
79
+ }
80
+ catch (error) {
81
+ throw new Error(`transport integrity: request ${id} action ${command.action} returned an invalid ${label}: ${error instanceof Error ? error.message : String(error)}`);
82
+ }
102
83
  }
103
84
  /** Generic rendezvous only: operation owners supply their own request and result codecs. */
104
85
  export async function requestBodyCommand(input) {
@@ -126,6 +107,8 @@ export async function requestBodyCommand(input) {
126
107
  async function observePublishedRequest(input, id, transportId, path) {
127
108
  let observedSequence = 0;
128
109
  const consumeProgress = async () => {
110
+ if (input.onProgress === undefined && input.onProgressGap === undefined)
111
+ return;
129
112
  const snapshot = await readRequestProgress({
130
113
  directory: input.directory,
131
114
  transportId,
@@ -10,7 +10,7 @@ export type ServeInput = Omit<PumpInput, "bodySequence"> & Readonly<{
10
10
  claim: RequestEnvelope;
11
11
  admissionOpen(): boolean;
12
12
  }>;
13
- export declare function serveRequest(input: ServeInput): Promise<boolean>;
13
+ export declare function serveRequest(input: ServeInput): Promise<void>;
14
14
  export declare class BodyRequestPump extends LifecycleBodyRequestPump {
15
15
  static open(input: PumpInput): Promise<BodyRequestPump>;
16
16
  }
@@ -21,33 +21,22 @@ function replayReference(fact, command) {
21
21
  }
22
22
  }
23
23
  async function projectCommandReceipt(input, fact, command, outcome, failure) {
24
+ const identity = { id: fact.id, action: fact.action };
24
25
  const receipt = fact.state === "refused"
25
- ? { id: fact.id, action: fact.action, state: "refused", diagnostic: fact.diagnostic }
26
- : fact.state === "voided"
26
+ ? { ...identity, state: fact.state, diagnostic: fact.diagnostic }
27
+ : fact.state === "voided" || fact.state === "unproven"
27
28
  ? {
28
- id: fact.id,
29
- action: fact.action,
30
- state: "voided",
29
+ ...identity,
30
+ state: fact.state,
31
31
  evidence: fact.evidence,
32
32
  ...(failure === undefined ? {} : { failure }),
33
- ...(outcome === undefined ? {} : { outcome: outcome.result }),
33
+ ...(fact.state === "voided" && outcome !== undefined ? { outcome: outcome.result } : {}),
34
34
  }
35
- : fact.state === "unproven"
36
- ? {
37
- id: fact.id,
38
- action: fact.action,
39
- state: "unproven",
40
- evidence: fact.evidence,
41
- ...(failure === undefined ? {} : { failure }),
42
- }
43
- : outcome === undefined
44
- ? {
45
- id: fact.id,
46
- action: fact.action,
47
- state: "served",
48
- reference: replayReference(fact, command),
49
- }
50
- : { id: fact.id, action: fact.action, state: "served", outcome };
35
+ : {
36
+ ...identity,
37
+ state: "served",
38
+ ...(outcome === undefined ? { reference: replayReference(fact, command) } : { outcome }),
39
+ };
51
40
  try {
52
41
  await atomicJson(receiptPath(input.directory, input.transportId), receipt);
53
42
  }
@@ -64,51 +53,39 @@ async function serveResolvedCommand(input, command, request, execute) {
64
53
  admittedAt: input.now(),
65
54
  permitted: request.isPermitted(input.allowed),
66
55
  });
67
- if (fact.state !== "admitted") {
68
- await projectCommandReceipt(input, fact, command);
69
- return true;
70
- }
71
- if (!input.admissionOpen()) {
56
+ if (fact.state === "admitted" && !input.admissionOpen()) {
72
57
  fact = await voidRequest(input.paths, fact.id, "body closed request admission");
58
+ }
59
+ if (fact.state !== "admitted") {
73
60
  await projectCommandReceipt(input, fact, command);
74
- return true;
61
+ return;
75
62
  }
63
+ const observation = {
64
+ directory: input.directory,
65
+ transportId: input.transportId,
66
+ id: fact.id,
67
+ action: fact.action,
68
+ };
69
+ const progress = publishRequestProgress(observation);
70
+ const cancellation = command.completion === "service" && request.supportsCancellation
71
+ ? observeRequestCancellation(observation)
72
+ : undefined;
73
+ let outcome;
74
+ let failure;
76
75
  try {
77
- const progress = publishRequestProgress({
78
- directory: input.directory,
79
- transportId: input.transportId,
80
- id: fact.id,
81
- action: fact.action,
82
- });
83
- const cancellation = command.completion === "service" && request.supportsCancellation
84
- ? observeRequestCancellation({
85
- directory: input.directory,
86
- transportId: input.transportId,
87
- id: fact.id,
88
- action: fact.action,
89
- })
90
- : undefined;
91
- const facts = {
76
+ const served = await execute(fact, {
92
77
  id: fact.id,
93
78
  admittedAt: fact.admittedAt,
94
79
  requester: fact.requester,
95
80
  signal: cancellation === undefined ? input.signal : AbortSignal.any([input.signal, cancellation.signal]),
96
81
  admissionOpen: input.admissionOpen,
97
82
  progress: progress.progress,
98
- };
99
- try {
100
- const served = await execute(fact, facts);
101
- fact = served.fact;
102
- await progress.flush();
103
- await projectCommandReceipt(input, fact, command, served.outcome);
104
- }
105
- finally {
106
- await progress.close();
107
- await cancellation?.close();
108
- }
83
+ });
84
+ fact = served.fact;
85
+ outcome = served.outcome;
109
86
  }
110
87
  catch (error) {
111
- const failure = encodedFailure(request, error);
88
+ failure = encodedFailure(request, error);
112
89
  const current = await readRequest(input.paths, fact.id);
113
90
  if (current === null)
114
91
  throw error;
@@ -117,7 +94,7 @@ async function serveResolvedCommand(input, command, request, execute) {
117
94
  if (parent === null)
118
95
  throw new Error("reserved request settlement requires a born parent Soul");
119
96
  if (!(await settleReserved(input.paths, parent, current, input.now, input.signal)))
120
- return true;
97
+ return;
121
98
  fact = (await readRequest(input.paths, fact.id)) ?? current;
122
99
  }
123
100
  else {
@@ -130,49 +107,45 @@ async function serveResolvedCommand(input, command, request, execute) {
130
107
  : await unproveRequest(input.paths, fact.id, diagnostic(error))
131
108
  : current;
132
109
  }
133
- await projectCommandReceipt(input, fact, command, undefined, failure);
134
110
  }
135
- return true;
136
- }
137
- async function serveChildCommand(input, command) {
138
- const request = command.resolve(input.claim.payload);
139
- if (request === null)
140
- throw new Error(`registered request action ${input.claim.action} rejected its payload`);
141
- return await serveResolvedCommand(input, command, request, async (fact, facts) => {
142
- const served = await request.execute(facts);
143
- return {
144
- fact: await serveChildRequest(input.paths, fact.id, served.child),
145
- outcome: { kind: "returned", result: served.result },
146
- };
147
- });
111
+ finally {
112
+ try {
113
+ await progress.close();
114
+ }
115
+ finally {
116
+ await cancellation?.close();
117
+ }
118
+ }
119
+ // Transport failure cannot re-enter execution settlement.
120
+ await projectCommandReceipt(input, fact, command, outcome, failure);
148
121
  }
149
- async function serveServiceCommand(input, command) {
150
- const request = command.resolve(input.claim.payload);
122
+ async function serveCommand(input, command) {
123
+ const { completion, request } = command.completion === "child"
124
+ ? { completion: "child", request: command.resolve(input.claim.payload) }
125
+ : { completion: "service", request: command.resolve(input.claim.payload) };
151
126
  if (request === null)
152
127
  throw new Error(`registered request action ${input.claim.action} rejected its payload`);
153
128
  return await serveResolvedCommand(input, command, request, async (fact, facts) => {
129
+ if (completion === "child") {
130
+ const served = await request.execute(facts);
131
+ return {
132
+ fact: await serveChildRequest(input.paths, fact.id, served.child),
133
+ outcome: { kind: "returned", result: served.result },
134
+ };
135
+ }
154
136
  await beginRequest(input.paths, fact.id);
155
137
  const served = await request.execute(facts);
156
- if (served.kind === "voided") {
157
- return {
138
+ return served.kind === "voided"
139
+ ? {
158
140
  fact: await voidRequest(input.paths, fact.id, "returned owner outcome was voided"),
159
141
  outcome: { kind: "returned", result: served.outcome },
142
+ }
143
+ : {
144
+ fact: await serveUpstreamRequest(input.paths, fact.id, served.serviceJson),
145
+ outcome: { kind: "returned", result: served.result },
160
146
  };
161
- }
162
- return {
163
- fact: await serveUpstreamRequest(input.paths, fact.id, served.serviceJson),
164
- outcome: { kind: "returned", result: served.result },
165
- };
166
147
  });
167
148
  }
168
- async function serveCommand(input, command) {
169
- switch (command.completion) {
170
- case "child":
171
- return await serveChildCommand(input, command);
172
- case "service":
173
- return await serveServiceCommand(input, command);
174
- }
175
- }
176
149
  function diagnostic(error) {
177
150
  return error instanceof Error ? error.message : String(error);
178
151
  }
@@ -190,35 +163,26 @@ function provesNoProductEffect(failure) {
190
163
  }
191
164
  export async function serveRequest(input) {
192
165
  const command = input.commands[input.claim.action];
193
- if (command === undefined) {
194
- await atomicJson(receiptPath(input.directory, input.transportId), {
195
- id: input.claim.id,
196
- action: input.claim.action,
197
- state: "refused",
198
- diagnostic: `request action ${input.claim.action} is not registered`,
199
- });
200
- return true;
201
- }
202
- return await serveCommand(input, command);
203
- }
204
- async function serveTransportClaim(input) {
205
- try {
206
- return await serveRequest(input);
207
- }
208
- catch (error) {
209
- if (!isRequestInputConflict(error))
210
- throw error;
211
- await atomicJson(receiptPath(input.directory, input.transportId), {
212
- id: input.claim.id,
213
- action: input.claim.action,
214
- state: "refused",
215
- diagnostic: error.message,
216
- });
217
- return true;
166
+ let diagnostic = `request action ${input.claim.action} is not registered`;
167
+ if (command !== undefined) {
168
+ try {
169
+ return await serveCommand(input, command);
170
+ }
171
+ catch (error) {
172
+ if (!isRequestInputConflict(error))
173
+ throw error;
174
+ diagnostic = error.message;
175
+ }
218
176
  }
177
+ await atomicJson(receiptPath(input.directory, input.transportId), {
178
+ id: input.claim.id,
179
+ action: input.claim.action,
180
+ state: "refused",
181
+ diagnostic,
182
+ });
219
183
  }
220
184
  export class BodyRequestPump extends LifecycleBodyRequestPump {
221
185
  static async open(input) {
222
- return (await LifecycleBodyRequestPump.openWithService(input, async (claim) => await serveTransportClaim({ ...claim, commands: input.commands })));
186
+ return (await LifecycleBodyRequestPump.openWithService(input, async (claim) => await serveRequest({ ...claim, commands: input.commands })));
223
187
  }
224
188
  }