@astrosheep/keiyaku 2.9.2 → 2.9.4

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 (238) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/agents/call-terms.js +13 -94
  3. package/build/agents/harness/activity-values.js +16 -0
  4. package/build/agents/harness/event-persistence.js +218 -0
  5. package/build/agents/harness/execution-handle.js +25 -222
  6. package/build/agents/harness/index.js +3 -1
  7. package/build/agents/harness/outcome.js +47 -4
  8. package/build/agents/harness/projection.js +42 -59
  9. package/build/agents/harness/provider-adapter.js +58 -0
  10. package/build/agents/harness/router.js +11 -187
  11. package/build/agents/harness/runtime.js +17 -4
  12. package/build/agents/harness/session.js +15 -0
  13. package/build/agents/launch-snapshot/model.js +15 -236
  14. package/build/agents/launch-snapshot/parse-helpers.js +114 -0
  15. package/build/agents/launch-snapshot/resolve.js +17 -43
  16. package/build/agents/opencode-sdk.js +45 -12
  17. package/build/agents/providers/claude-agent-sdk/adapter.js +6 -17
  18. package/build/agents/providers/claude-agent-sdk/registration.js +214 -0
  19. package/build/agents/providers/claude-agent-sdk/session-schema.js +2 -0
  20. package/build/agents/providers/codex-app-server/adapter.js +50 -53
  21. package/build/agents/providers/codex-app-server/events.js +67 -11
  22. package/build/agents/providers/codex-app-server/identity.js +1 -0
  23. package/build/agents/providers/codex-app-server/policy.js +29 -0
  24. package/build/agents/providers/codex-app-server/registration.js +248 -0
  25. package/build/agents/providers/codex-app-server/session-schema.js +6 -0
  26. package/build/agents/providers/codex-app-server/session.js +23 -17
  27. package/build/agents/providers/codex-app-server/terms.js +1 -0
  28. package/build/agents/providers/opencode-sdk/adapter.js +94 -50
  29. package/build/agents/providers/opencode-sdk/events.js +8 -4
  30. package/build/agents/providers/opencode-sdk/registration.js +135 -0
  31. package/build/agents/providers/opencode-sdk/session-schema.js +2 -0
  32. package/build/agents/providers/opencode-sdk/session.js +21 -14
  33. package/build/agents/providers/opencode-sdk/terms.js +1 -0
  34. package/build/agents/providers/pi/adapter.js +36 -30
  35. package/build/agents/providers/pi/registration.js +145 -0
  36. package/build/agents/providers/pi/session-schema.js +6 -0
  37. package/build/agents/providers/pi/terms.js +1 -0
  38. package/build/agents/providers/registration.js +7 -0
  39. package/build/agents/providers/registry.js +76 -0
  40. package/build/agents/selector.js +2 -29
  41. package/build/agents/types.js +8 -0
  42. package/build/artifact-directories.js +22 -0
  43. package/build/cli/commands/akuma/akuma/handler.js +1 -1
  44. package/build/cli/commands/akuma/view/handler.js +5 -4
  45. package/build/cli/commands/akuma.js +6 -0
  46. package/build/cli/commands/contract/amend/handler.js +8 -2
  47. package/build/cli/commands/contract/arc/handler.js +7 -1
  48. package/build/cli/commands/contract/bind/handler.js +4 -3
  49. package/build/cli/commands/contract/bind/meta.js +34 -7
  50. package/build/cli/commands/contract/forfeit/handler.js +4 -4
  51. package/build/cli/commands/contract/log/handler.js +3 -3
  52. package/build/cli/commands/contract/petition/handler.js +4 -6
  53. package/build/cli/commands/contract/renew/handler.js +20 -6
  54. package/build/cli/commands/contract/renew/meta.js +5 -4
  55. package/build/cli/commands/metadata.js +58 -0
  56. package/build/cli/commands/projection/call/handler.js +6 -5
  57. package/build/cli/commands/projection/kill/handler.js +16 -32
  58. package/build/cli/commands/projection/shared.js +28 -0
  59. package/build/cli/commands/projection/status/handler.js +1 -1
  60. package/build/cli/commands/projection/tell/handler.js +14 -30
  61. package/build/cli/commands/projection/wait/handler.js +45 -22
  62. package/build/cli/commands/projection/wait/meta.js +7 -2
  63. package/build/cli/commands/registry.js +2 -54
  64. package/build/cli/commands/shared.js +10 -7
  65. package/build/cli/commands/skills/install/handler.js +2 -5
  66. package/build/cli/commands/skills/skills/handler.js +1 -1
  67. package/build/cli/commands/task/add/handler.js +5 -13
  68. package/build/cli/commands/task/catalog.js +2 -2
  69. package/build/cli/commands/task/done/handler.js +4 -8
  70. package/build/cli/commands/task/drop/handler.js +3 -6
  71. package/build/cli/commands/task/ls/handler.js +3 -5
  72. package/build/cli/commands/task/shared.js +14 -4
  73. package/build/cli/commands/task/{view → show}/handler.js +7 -8
  74. package/build/cli/commands/task/show/meta.js +8 -0
  75. package/build/cli/commands/task/start/handler.js +3 -6
  76. package/build/cli/commands/task/stop/handler.js +4 -8
  77. package/build/cli/commands/task/task/handler.js +1 -1
  78. package/build/cli/commands/task/update/handler.js +4 -8
  79. package/build/cli/completion.js +1 -1
  80. package/build/cli/flags.js +19 -3
  81. package/build/cli/help.js +4 -11
  82. package/build/cli/index.js +57 -83
  83. package/build/cli/missing-subcommand.js +7 -0
  84. package/build/cli/parse-flags.js +14 -5
  85. package/build/cli/parse-metadata.js +3 -3
  86. package/build/cli/parse-selectors.js +1 -1
  87. package/build/cli/parse.js +21 -0
  88. package/build/cli/projection-address.js +7 -12
  89. package/build/cli/render/address.js +41 -37
  90. package/build/cli/render/arc.js +24 -12
  91. package/build/cli/render/call.js +11 -5
  92. package/build/cli/render/errors.js +36 -1
  93. package/build/cli/render/format.js +4 -0
  94. package/build/cli/render/kanshi.js +6 -12
  95. package/build/cli/render/kill.js +9 -0
  96. package/build/cli/render/misc.js +55 -12
  97. package/build/cli/render/petition.js +20 -15
  98. package/build/cli/render/projection-activity.js +3 -0
  99. package/build/cli/render/shared.js +60 -21
  100. package/build/cli/render/skills.js +10 -0
  101. package/build/cli/render/status.js +37 -14
  102. package/build/cli/render/success-response.js +77 -0
  103. package/build/cli/render/task.js +54 -14
  104. package/build/cli/render/tell.js +5 -0
  105. package/build/cli/render/terminal-failure.js +58 -0
  106. package/build/cli/render/types.js +1 -0
  107. package/build/cli/render/wait.js +38 -36
  108. package/build/cli/types.js +1 -1
  109. package/build/config/akuma-loader.js +0 -5
  110. package/build/config/env-keys.js +1 -1
  111. package/build/config/provider-policy-ownership.js +3 -32
  112. package/build/config/settings/disease.js +8 -1
  113. package/build/config/settings/loader.js +11 -3
  114. package/build/config/settings/provider-instance-fields.js +51 -0
  115. package/build/config/settings/schema.js +6 -176
  116. package/build/core/addressing.js +66 -16
  117. package/build/core/amend.js +135 -18
  118. package/build/core/arc.js +19 -67
  119. package/build/core/bind.js +82 -35
  120. package/build/core/call/call.js +15 -9
  121. package/build/core/call/context.js +6 -51
  122. package/build/core/call/execution.js +21 -22
  123. package/build/core/call/prompt.js +14 -1
  124. package/build/core/command-markdown.js +45 -0
  125. package/build/core/context.js +13 -7
  126. package/build/core/contract-view.js +20 -3
  127. package/build/core/draft.js +123 -16
  128. package/build/core/forfeit.js +5 -2
  129. package/build/core/hints.js +1 -75
  130. package/build/core/identifier-slug.js +66 -0
  131. package/build/core/ids.js +25 -11
  132. package/build/core/ledger.js +20 -68
  133. package/build/core/markdown/parser.js +0 -68
  134. package/build/core/markdown/render.js +68 -0
  135. package/build/core/markdown/sections.js +2 -1
  136. package/build/core/outcome-base.js +4 -0
  137. package/build/core/projection/generation/database.js +2 -38
  138. package/build/core/projection/generation/model.js +42 -1
  139. package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
  140. package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +19 -49
  141. package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
  142. package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +5 -3
  143. package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
  144. package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +18 -3
  145. package/build/core/projection/generation/store.js +2 -2
  146. package/build/core/projection/generation/transitions.js +1 -1
  147. package/build/core/projection/index.js +27 -0
  148. package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
  149. package/build/core/{projection-alias.js → projection/projection-alias.js} +14 -19
  150. package/build/core/projection/projection-coordinate.js +61 -0
  151. package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
  152. package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +2 -57
  153. package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
  154. package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
  155. package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +1 -1
  156. package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
  157. package/build/core/{projection-status.js → projection/projection-status.js} +98 -25
  158. package/build/core/projection/projection-terminal-failure.js +104 -0
  159. package/build/core/projection/projection-wait.js +278 -0
  160. package/build/core/projection/projection-wake.js +203 -0
  161. package/build/core/provider-loader-ports.js +4 -0
  162. package/build/core/ref-log.js +65 -40
  163. package/build/core/registry.js +63 -10
  164. package/build/core/renew-session.js +128 -0
  165. package/build/core/renew.js +426 -99
  166. package/build/core/scope.js +143 -66
  167. package/build/core/seal.js +139 -35
  168. package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +9 -14
  169. package/build/core/{claim.js → settlement/claim.js} +32 -8
  170. package/build/core/settlement/index.js +19 -0
  171. package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +22 -18
  172. package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
  173. package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
  174. package/build/core/settlement/petition-io.js +1 -0
  175. package/build/core/{petition-preview.js → settlement/petition-preview.js} +1 -1
  176. package/build/core/{petition.js → settlement/petition.js} +12 -10
  177. package/build/core/settlement/queue-read-model.js +143 -0
  178. package/build/core/settlement/queue-seat-allocation.js +156 -0
  179. package/build/core/settlement/queue.js +6 -0
  180. package/build/core/settlement/settlement.js +295 -0
  181. package/build/core/{verdict.js → settlement/verdict.js} +9 -37
  182. package/build/core/status/board.js +24 -23
  183. package/build/core/status/ledger-batch.js +158 -0
  184. package/build/core/status/reconciliation.js +10 -4
  185. package/build/core/stored-agent-event.js +3 -0
  186. package/build/core/task/board.js +40 -4
  187. package/build/core/task/commands.js +30 -21
  188. package/build/core/task/index.js +12 -0
  189. package/build/core/task/settlement-git.js +157 -65
  190. package/build/core/task/settlement-policy.js +54 -24
  191. package/build/core/task/task-contract.js +370 -0
  192. package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
  193. package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
  194. package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
  195. package/build/core/{task-git-store.js → task/task-git-store.js} +92 -29
  196. package/build/core/task/task-repository.js +1 -0
  197. package/build/core/{task-store-repository.js → task/task-store-repository.js} +5 -4
  198. package/build/core/task/task-store.js +1 -0
  199. package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
  200. package/build/core/task/task.js +5 -0
  201. package/build/core/task/tree.js +37 -0
  202. package/build/core/task/validation.js +5 -2
  203. package/build/core/transcripts.js +15 -3
  204. package/build/core/worktree-path.js +43 -28
  205. package/build/flow-error.js +85 -39
  206. package/build/fs/durability.js +27 -0
  207. package/build/fs/path-coordinate.js +16 -0
  208. package/build/generated/version.js +3 -2
  209. package/build/git/branches.js +2 -1
  210. package/build/git/core.js +106 -2
  211. package/build/git/path-coordinate.js +17 -0
  212. package/build/git/refs.js +57 -0
  213. package/build/git/streaming-batch.js +301 -0
  214. package/build/git/worktree.js +65 -0
  215. package/build/index.js +3 -3
  216. package/build/keiyaku.js +2 -36
  217. package/package.json +4 -10
  218. package/skills/keiyaku/SKILL.md +3 -2
  219. package/skills/keiyaku-akuma/SKILL.md +10 -6
  220. package/skills/keiyaku-task/SKILL.md +1 -1
  221. package/skills/keiyaku-workflow/SKILL.md +25 -4
  222. package/build/agents/providers/codex-sdk.js +0 -329
  223. package/build/cli/commands/task/view/meta.js +0 -8
  224. package/build/core/command-io.js +0 -174
  225. package/build/core/path-coordinate.js +0 -27
  226. package/build/core/petition-claim.js +0 -117
  227. package/build/core/petition-run.js +0 -83
  228. package/build/core/projection-coordinate.js +0 -63
  229. package/build/core/projection-wait.js +0 -165
  230. package/build/core/projection-wake.js +0 -136
  231. package/build/core/queue.js +0 -343
  232. package/build/core/task-contract.js +0 -237
  233. package/build/core/task.js +0 -4
  234. /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
  235. /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
  236. /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
  237. /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
  238. /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
@@ -1,22 +1,11 @@
1
1
  import { getConfig } from "../config/env.js";
2
- function maxCaptureCharsForProvider(provider) {
3
- const config = getConfig();
4
- switch (provider) {
5
- case "codex-sdk":
6
- case "codex-app-server":
7
- case "pi":
8
- return config.codex.execMaxCaptureChars;
9
- case "claude-agent-sdk":
10
- return config.claude.execMaxCaptureChars;
11
- case "opencode-sdk":
12
- return config.opencode.execMaxCaptureChars;
13
- }
14
- }
2
+ import { getProviderRegistration } from "./providers/registry.js";
15
3
  export function buildCallTerms(snapshot, prompt, cwd, options) {
16
4
  const runtimeConfig = getConfig();
17
5
  const body = snapshot.akuma.body;
18
- const sessionContinuationPromptPrefix = body && (snapshot.provider.kind === "codex-sdk" || snapshot.provider.kind === "opencode-sdk")
19
- ? `[Akuma system prompt]\n${body}\n\n[Operator prompt]\n`
6
+ const registration = getProviderRegistration(snapshot.provider.kind);
7
+ const sessionContinuationPromptPrefix = body && registration.sessionContinuationPromptPrefix
8
+ ? registration.sessionContinuationPromptPrefix(body)
20
9
  : "";
21
10
  const replayPrompt = sessionContinuationPromptPrefix
22
11
  ? `${sessionContinuationPromptPrefix}${prompt}`
@@ -26,86 +15,16 @@ export function buildCallTerms(snapshot, prompt, cwd, options) {
26
15
  prompt,
27
16
  sessionContinuationPromptPrefix,
28
17
  idleTimeoutMs: options.idleTimeoutMs ?? runtimeConfig.subagent.execIdleTimeoutMs,
29
- maxCaptureChars: maxCaptureCharsForProvider(snapshot.provider.kind),
18
+ maxCaptureChars: registration.maxCaptureChars(runtimeConfig),
30
19
  signal: options.signal,
31
20
  ...(options.initialTurn !== undefined ? { initialTurn: options.initialTurn } : {}),
32
21
  };
33
- switch (snapshot.provider.kind) {
34
- case "codex-sdk":
35
- return {
36
- ...baseTerms,
37
- prompt: replayPrompt,
38
- provider: "codex-sdk",
39
- ...(snapshot.akuma.model !== undefined ? { model: snapshot.akuma.model } : {}),
40
- ...(snapshot.provider.profile !== undefined ? { profile: snapshot.provider.profile } : {}),
41
- ...(snapshot.provider.config !== undefined
42
- ? { config: snapshot.provider.config }
43
- : {}),
44
- threadOptions: snapshot.provider.threadOptions,
45
- ...(snapshot.provider.executable !== undefined ? { executable: snapshot.provider.executable } : {}),
46
- };
47
- case "codex-app-server":
48
- return {
49
- ...baseTerms,
50
- provider: "codex-app-server",
51
- ...(snapshot.provider.model !== undefined ? { model: snapshot.provider.model } : {}),
52
- ...(snapshot.provider.effort !== undefined ? { effort: snapshot.provider.effort } : {}),
53
- ...(snapshot.provider.profile !== undefined ? { profile: snapshot.provider.profile } : {}),
54
- ...(snapshot.provider.config !== undefined
55
- ? { config: snapshot.provider.config }
56
- : {}),
57
- ...(snapshot.provider.executable !== undefined ? { executable: snapshot.provider.executable } : {}),
58
- ...(snapshot.provider.sandboxPolicy !== undefined
59
- ? { sandboxPolicy: snapshot.provider.sandboxPolicy }
60
- : {}),
61
- ...(snapshot.provider.approvalPolicy !== undefined
62
- ? { approvalPolicy: snapshot.provider.approvalPolicy }
63
- : {}),
64
- ...(snapshot.provider.env !== undefined ? { env: snapshot.provider.env } : {}),
65
- developerInstructions: body || undefined,
66
- onCheckpoint() { },
67
- };
68
- case "claude-agent-sdk":
69
- return {
70
- ...baseTerms,
71
- provider: "claude-agent-sdk",
72
- ...(snapshot.provider.model !== undefined ? { model: snapshot.provider.model } : {}),
73
- ...(snapshot.provider.effort !== undefined ? { effort: snapshot.provider.effort } : {}),
74
- ...(snapshot.provider.executable !== undefined ? { executable: snapshot.provider.executable } : {}),
75
- ...(snapshot.provider.settingSources !== undefined ? { settingSources: snapshot.provider.settingSources } : {}),
76
- permissionMode: snapshot.provider.permissionMode,
77
- ...(snapshot.provider.allowDangerouslySkipPermissions !== undefined
78
- ? { allowDangerouslySkipPermissions: snapshot.provider.allowDangerouslySkipPermissions }
79
- : {}),
80
- ...(snapshot.provider.disallowedTools !== undefined
81
- ? { disallowedTools: snapshot.provider.disallowedTools }
82
- : {}),
83
- ...(snapshot.provider.env !== undefined ? { env: snapshot.provider.env } : {}),
84
- systemPrompt: body
85
- ? { type: "preset", preset: "claude_code", append: body }
86
- : undefined,
87
- onCheckpoint() { },
88
- };
89
- case "opencode-sdk":
90
- return {
91
- ...baseTerms,
92
- prompt: replayPrompt,
93
- provider: "opencode-sdk",
94
- ...(snapshot.provider.model !== undefined ? { model: snapshot.provider.model } : {}),
95
- ...(snapshot.provider.effort !== undefined ? { effort: snapshot.provider.effort } : {}),
96
- ...(snapshot.provider.executable !== undefined ? { executable: snapshot.provider.executable } : {}),
97
- ...(snapshot.provider.env !== undefined ? { env: snapshot.provider.env } : {}),
98
- };
99
- case "pi":
100
- return {
101
- ...baseTerms,
102
- provider: "pi",
103
- ...(snapshot.provider.model !== undefined ? { model: snapshot.provider.model } : {}),
104
- ...(snapshot.provider.thinkingLevel !== undefined
105
- ? { thinkingLevel: snapshot.provider.thinkingLevel }
106
- : {}),
107
- appendSystemPromptOverride: body ? () => [body] : undefined,
108
- onCheckpoint() { },
109
- };
110
- }
22
+ // Live registry only admits CallTerms-producing contributions; the open
23
+ // registration surface returns structural RegistrationCallTerms.
24
+ return registration.buildCallTerms({
25
+ snapshot,
26
+ baseTerms,
27
+ body,
28
+ replayPrompt,
29
+ });
111
30
  }
@@ -41,7 +41,23 @@ export function activityCallFromNamedTool(tool, facts) {
41
41
  export function boundActivityExcerpt(value) {
42
42
  return value.slice(-AGENT_EVENT_TEXT_MAX_CHARS);
43
43
  }
44
+ /** True only for text that carries at least one unified-diff hunk header. */
45
+ function hasUnifiedDiffHunk(patch) {
46
+ for (const line of patch.split("\n")) {
47
+ // Native app-server updates and ordinary unified patches use: @@ -a[,b] +c[,d] @@
48
+ if (/^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/.test(line))
49
+ return true;
50
+ }
51
+ return false;
52
+ }
53
+ /**
54
+ * Count additions/deletions from provider-supplied unified patch text only.
55
+ * Raw file contents (native add/delete `diff`) are rejected even when individual
56
+ * lines happen to begin with `+` or `-`.
57
+ */
44
58
  export function diffstatFromUnifiedPatch(patch) {
59
+ if (!hasUnifiedDiffHunk(patch))
60
+ return undefined;
45
61
  let additions = 0;
46
62
  let deletions = 0;
47
63
  for (const line of patch.split("\n")) {
@@ -0,0 +1,218 @@
1
+ import { AGENT_ACTIVITY_MAX_CHANGES, AGENT_EVENT_TEXT_MAX_CHARS, AGENT_UNKNOWN_PAYLOAD_MAX_CHARS, } from "./events.js";
2
+ import { EXEC_EVENT_BUFFER_HARD_CAP } from "./event-channel.js";
3
+ export function createTruncationMarker(envelope = {
4
+ seq: EXEC_EVENT_BUFFER_HARD_CAP,
5
+ at: new Date().toISOString(),
6
+ turn: 0,
7
+ }) {
8
+ return {
9
+ type: "truncation",
10
+ limit: EXEC_EVENT_BUFFER_HARD_CAP,
11
+ admitted: EXEC_EVENT_BUFFER_HARD_CAP,
12
+ seq: envelope.seq,
13
+ at: envelope.at,
14
+ turn: envelope.turn,
15
+ };
16
+ }
17
+ export function overflowMarkerFromDropped(dropped) {
18
+ if (dropped.type === "truncation")
19
+ return dropped;
20
+ return createTruncationMarker({
21
+ seq: dropped.seq,
22
+ at: dropped.at,
23
+ turn: dropped.turn,
24
+ });
25
+ }
26
+ function truncateText(value) {
27
+ return {
28
+ value: value.slice(0, AGENT_EVENT_TEXT_MAX_CHARS),
29
+ truncated: value.length > AGENT_EVENT_TEXT_MAX_CHARS,
30
+ };
31
+ }
32
+ /** Bound unknown native payloads before they enter the projection event stream. */
33
+ export function serializeUnknownPayload(value) {
34
+ let serialized;
35
+ try {
36
+ const encoded = JSON.stringify(value);
37
+ if (encoded === undefined) {
38
+ return {
39
+ payload: "null",
40
+ elided: { reason: "unserializable", retainedChars: 4 },
41
+ };
42
+ }
43
+ serialized = encoded;
44
+ }
45
+ catch {
46
+ serialized = "null";
47
+ return {
48
+ payload: serialized,
49
+ elided: { reason: "unserializable", retainedChars: serialized.length },
50
+ };
51
+ }
52
+ if (serialized.length <= AGENT_UNKNOWN_PAYLOAD_MAX_CHARS)
53
+ return { payload: serialized };
54
+ return {
55
+ payload: serialized.slice(0, AGENT_UNKNOWN_PAYLOAD_MAX_CHARS),
56
+ elided: {
57
+ reason: "truncated",
58
+ originalChars: serialized.length,
59
+ retainedChars: AGENT_UNKNOWN_PAYLOAD_MAX_CHARS,
60
+ },
61
+ };
62
+ }
63
+ function normalizeBodyForPersistence(body) {
64
+ switch (body.type) {
65
+ case "message": {
66
+ const id = truncateText(body.id);
67
+ const text = truncateText(body.text);
68
+ return {
69
+ body: { ...body, id: id.value, text: text.value },
70
+ truncated: id.truncated || text.truncated,
71
+ };
72
+ }
73
+ case "unknown": {
74
+ const provider = truncateText(body.provider);
75
+ const nativeType = truncateText(body.nativeType);
76
+ const payload = truncateText(body.payload);
77
+ return {
78
+ body: {
79
+ ...body,
80
+ provider: provider.value,
81
+ nativeType: nativeType.value,
82
+ payload: payload.value,
83
+ ...(payload.truncated && body.elided === undefined
84
+ ? { elided: { reason: "truncated", originalChars: body.payload.length, retainedChars: payload.value.length } }
85
+ : {}),
86
+ },
87
+ truncated: provider.truncated || nativeType.truncated || payload.truncated,
88
+ };
89
+ }
90
+ case "activity": {
91
+ const id = truncateText(body.id);
92
+ const tool = truncateText(body.tool);
93
+ let truncated = id.truncated || tool.truncated;
94
+ const text = (value) => {
95
+ const bounded = truncateText(value);
96
+ truncated ||= bounded.truncated;
97
+ return bounded.value;
98
+ };
99
+ const call = (() => {
100
+ switch (body.call.kind) {
101
+ case "run":
102
+ return {
103
+ ...body.call,
104
+ command: text(body.call.command),
105
+ ...(body.call.description === undefined ? {} : { description: text(body.call.description) }),
106
+ };
107
+ case "read":
108
+ return { ...body.call, path: text(body.call.path) };
109
+ case "search":
110
+ return { ...body.call, query: text(body.call.query) };
111
+ case "fileChange": {
112
+ const kept = body.call.changes.slice(0, AGENT_ACTIVITY_MAX_CHANGES);
113
+ const dropped = body.call.changes.length - kept.length;
114
+ truncated ||= dropped > 0;
115
+ return {
116
+ ...body.call,
117
+ changes: kept.map((change) => ({ ...change, path: text(change.path) })),
118
+ ...((body.call.omittedChanges ?? 0) + dropped > 0
119
+ ? { omittedChanges: (body.call.omittedChanges ?? 0) + dropped }
120
+ : {}),
121
+ };
122
+ }
123
+ case "other":
124
+ return { ...body.call, display: text(body.call.display) };
125
+ }
126
+ })();
127
+ const result = body.result === undefined
128
+ ? undefined
129
+ : {
130
+ ...body.result,
131
+ ...(body.result.message === undefined ? {} : { message: text(body.result.message) }),
132
+ };
133
+ return {
134
+ body: {
135
+ ...body,
136
+ id: id.value,
137
+ tool: tool.value,
138
+ call,
139
+ ...(result === undefined ? {} : { result }),
140
+ ...(truncated ? { truncated: true } : {}),
141
+ },
142
+ truncated,
143
+ };
144
+ }
145
+ case "thought":
146
+ case "plan":
147
+ case "truncation":
148
+ case "turn":
149
+ return { body, truncated: false };
150
+ case "usage": {
151
+ const model = body.model === undefined ? undefined : truncateText(body.model);
152
+ return {
153
+ body: { ...body, ...(model ? { model: model.value } : {}) },
154
+ truncated: model?.truncated ?? false,
155
+ };
156
+ }
157
+ case "warning": {
158
+ if (body.warning.reason === "retry" || body.warning.reason === "rate-limit") {
159
+ return { body, truncated: false };
160
+ }
161
+ const originalModel = body.warning.originalModel === undefined ? undefined : truncateText(body.warning.originalModel);
162
+ const fallbackModel = body.warning.fallbackModel === undefined ? undefined : truncateText(body.warning.fallbackModel);
163
+ const direction = body.warning.direction === undefined ? undefined : truncateText(body.warning.direction);
164
+ const requestId = body.warning.requestId === undefined || body.warning.requestId === null
165
+ ? undefined
166
+ : truncateText(body.warning.requestId);
167
+ const signerModel = body.warning.signerModel === undefined ? undefined : truncateText(body.warning.signerModel);
168
+ return {
169
+ body: {
170
+ ...body,
171
+ warning: {
172
+ ...body.warning,
173
+ ...(originalModel ? { originalModel: originalModel.value } : {}),
174
+ ...(fallbackModel ? { fallbackModel: fallbackModel.value } : {}),
175
+ ...(direction ? { direction: direction.value } : {}),
176
+ ...(requestId ? { requestId: requestId.value } : {}),
177
+ ...(signerModel ? { signerModel: signerModel.value } : {}),
178
+ },
179
+ },
180
+ truncated: [originalModel, fallbackModel, direction, requestId, signerModel]
181
+ .some((entry) => entry?.truncated === true),
182
+ };
183
+ }
184
+ case "diagnostic": {
185
+ const text = truncateText(body.text);
186
+ return { body: { ...body, text: text.value }, truncated: text.truncated };
187
+ }
188
+ case "done": {
189
+ const finalMessage = body.finalMessage === undefined ? undefined : truncateText(body.finalMessage);
190
+ return {
191
+ body: { ...body, ...(finalMessage ? { finalMessage: finalMessage.value } : {}) },
192
+ truncated: finalMessage?.truncated ?? false,
193
+ };
194
+ }
195
+ case "fail": {
196
+ const message = truncateText(body.message);
197
+ const diagnostics = body.diagnostics === undefined ? undefined : truncateText(body.diagnostics);
198
+ return {
199
+ body: {
200
+ ...body,
201
+ message: message.value,
202
+ ...(diagnostics ? { diagnostics: diagnostics.value } : {}),
203
+ },
204
+ truncated: message.truncated || (diagnostics?.truncated ?? false),
205
+ };
206
+ }
207
+ }
208
+ }
209
+ export function prepareAgentEventForPersistence(event) {
210
+ const normalized = normalizeBodyForPersistence(event);
211
+ return {
212
+ ...normalized.body,
213
+ seq: event.seq,
214
+ at: event.at,
215
+ turn: event.turn,
216
+ ...(normalized.truncated ? { truncated: true } : {}),
217
+ };
218
+ }
@@ -1,221 +1,8 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { AGENT_ACTIVITY_MAX_CHANGES, AGENT_EVENT_TEXT_MAX_CHARS, AGENT_UNKNOWN_PAYLOAD_MAX_CHARS, } from "./events.js";
3
2
  import { createEventChannel, EXEC_EVENT_BUFFER_HARD_CAP, } from "./event-channel.js";
4
- export function createTruncationMarker(envelope = {
5
- seq: EXEC_EVENT_BUFFER_HARD_CAP,
6
- at: new Date().toISOString(),
7
- turn: 0,
8
- }) {
9
- return {
10
- type: "truncation",
11
- limit: EXEC_EVENT_BUFFER_HARD_CAP,
12
- admitted: EXEC_EVENT_BUFFER_HARD_CAP,
13
- seq: envelope.seq,
14
- at: envelope.at,
15
- turn: envelope.turn,
16
- };
17
- }
18
- export function overflowMarkerFromDropped(dropped) {
19
- if (dropped.type === "truncation")
20
- return dropped;
21
- return createTruncationMarker({
22
- seq: dropped.seq,
23
- at: dropped.at,
24
- turn: dropped.turn,
25
- });
26
- }
27
- function truncateText(value) {
28
- return {
29
- value: value.slice(0, AGENT_EVENT_TEXT_MAX_CHARS),
30
- truncated: value.length > AGENT_EVENT_TEXT_MAX_CHARS,
31
- };
32
- }
33
- function serializeUnknownPayload(value) {
34
- let serialized;
35
- try {
36
- const encoded = JSON.stringify(value);
37
- if (encoded === undefined) {
38
- return {
39
- payload: "null",
40
- elided: { reason: "unserializable", retainedChars: 4 },
41
- };
42
- }
43
- serialized = encoded;
44
- }
45
- catch {
46
- serialized = "null";
47
- return {
48
- payload: serialized,
49
- elided: { reason: "unserializable", retainedChars: serialized.length },
50
- };
51
- }
52
- if (serialized.length <= AGENT_UNKNOWN_PAYLOAD_MAX_CHARS)
53
- return { payload: serialized };
54
- return {
55
- payload: serialized.slice(0, AGENT_UNKNOWN_PAYLOAD_MAX_CHARS),
56
- elided: {
57
- reason: "truncated",
58
- originalChars: serialized.length,
59
- retainedChars: AGENT_UNKNOWN_PAYLOAD_MAX_CHARS,
60
- },
61
- };
62
- }
63
- function normalizeBodyForPersistence(body) {
64
- switch (body.type) {
65
- case "message": {
66
- const id = truncateText(body.id);
67
- const text = truncateText(body.text);
68
- return {
69
- body: { ...body, id: id.value, text: text.value },
70
- truncated: id.truncated || text.truncated,
71
- };
72
- }
73
- case "unknown": {
74
- const provider = truncateText(body.provider);
75
- const nativeType = truncateText(body.nativeType);
76
- const payload = truncateText(body.payload);
77
- return {
78
- body: {
79
- ...body,
80
- provider: provider.value,
81
- nativeType: nativeType.value,
82
- payload: payload.value,
83
- ...(payload.truncated && body.elided === undefined
84
- ? { elided: { reason: "truncated", originalChars: body.payload.length, retainedChars: payload.value.length } }
85
- : {}),
86
- },
87
- truncated: provider.truncated || nativeType.truncated || payload.truncated,
88
- };
89
- }
90
- case "activity": {
91
- const id = truncateText(body.id);
92
- const tool = truncateText(body.tool);
93
- let truncated = id.truncated || tool.truncated;
94
- const text = (value) => {
95
- const bounded = truncateText(value);
96
- truncated ||= bounded.truncated;
97
- return bounded.value;
98
- };
99
- const call = (() => {
100
- switch (body.call.kind) {
101
- case "run":
102
- return {
103
- ...body.call,
104
- command: text(body.call.command),
105
- ...(body.call.description === undefined ? {} : { description: text(body.call.description) }),
106
- };
107
- case "read":
108
- return { ...body.call, path: text(body.call.path) };
109
- case "search":
110
- return { ...body.call, query: text(body.call.query) };
111
- case "fileChange": {
112
- const kept = body.call.changes.slice(0, AGENT_ACTIVITY_MAX_CHANGES);
113
- const dropped = body.call.changes.length - kept.length;
114
- truncated ||= dropped > 0;
115
- return {
116
- ...body.call,
117
- changes: kept.map((change) => ({ ...change, path: text(change.path) })),
118
- ...((body.call.omittedChanges ?? 0) + dropped > 0
119
- ? { omittedChanges: (body.call.omittedChanges ?? 0) + dropped }
120
- : {}),
121
- };
122
- }
123
- case "other":
124
- return { ...body.call, display: text(body.call.display) };
125
- }
126
- })();
127
- const result = body.result === undefined
128
- ? undefined
129
- : {
130
- ...body.result,
131
- ...(body.result.message === undefined ? {} : { message: text(body.result.message) }),
132
- };
133
- return {
134
- body: {
135
- ...body,
136
- id: id.value,
137
- tool: tool.value,
138
- call,
139
- ...(result === undefined ? {} : { result }),
140
- ...(truncated ? { truncated: true } : {}),
141
- },
142
- truncated,
143
- };
144
- }
145
- case "thought":
146
- case "plan":
147
- case "truncation":
148
- case "turn":
149
- return { body, truncated: false };
150
- case "usage": {
151
- const model = body.model === undefined ? undefined : truncateText(body.model);
152
- return {
153
- body: { ...body, ...(model ? { model: model.value } : {}) },
154
- truncated: model?.truncated ?? false,
155
- };
156
- }
157
- case "warning": {
158
- if (body.warning.reason === "retry") {
159
- return { body, truncated: false };
160
- }
161
- const originalModel = body.warning.originalModel === undefined ? undefined : truncateText(body.warning.originalModel);
162
- const fallbackModel = body.warning.fallbackModel === undefined ? undefined : truncateText(body.warning.fallbackModel);
163
- const direction = body.warning.direction === undefined ? undefined : truncateText(body.warning.direction);
164
- const requestId = body.warning.requestId === undefined || body.warning.requestId === null
165
- ? undefined
166
- : truncateText(body.warning.requestId);
167
- const signerModel = body.warning.signerModel === undefined ? undefined : truncateText(body.warning.signerModel);
168
- return {
169
- body: {
170
- ...body,
171
- warning: {
172
- ...body.warning,
173
- ...(originalModel ? { originalModel: originalModel.value } : {}),
174
- ...(fallbackModel ? { fallbackModel: fallbackModel.value } : {}),
175
- ...(direction ? { direction: direction.value } : {}),
176
- ...(requestId ? { requestId: requestId.value } : {}),
177
- ...(signerModel ? { signerModel: signerModel.value } : {}),
178
- },
179
- },
180
- truncated: [originalModel, fallbackModel, direction, requestId, signerModel]
181
- .some((entry) => entry?.truncated === true),
182
- };
183
- }
184
- case "diagnostic": {
185
- const text = truncateText(body.text);
186
- return { body: { ...body, text: text.value }, truncated: text.truncated };
187
- }
188
- case "done": {
189
- const finalMessage = body.finalMessage === undefined ? undefined : truncateText(body.finalMessage);
190
- return {
191
- body: { ...body, ...(finalMessage ? { finalMessage: finalMessage.value } : {}) },
192
- truncated: finalMessage?.truncated ?? false,
193
- };
194
- }
195
- case "fail": {
196
- const message = truncateText(body.message);
197
- const diagnostics = body.diagnostics === undefined ? undefined : truncateText(body.diagnostics);
198
- return {
199
- body: {
200
- ...body,
201
- message: message.value,
202
- ...(diagnostics ? { diagnostics: diagnostics.value } : {}),
203
- },
204
- truncated: message.truncated || (diagnostics?.truncated ?? false),
205
- };
206
- }
207
- }
208
- }
209
- export function prepareAgentEventForPersistence(event) {
210
- const normalized = normalizeBodyForPersistence(event);
211
- return {
212
- ...normalized.body,
213
- seq: event.seq,
214
- at: event.at,
215
- turn: event.turn,
216
- ...(normalized.truncated ? { truncated: true } : {}),
217
- };
218
- }
3
+ import { toProviderTerminalError } from "./provider-adapter.js";
4
+ import { createTruncationMarker, overflowMarkerFromDropped, serializeUnknownPayload, } from "./event-persistence.js";
5
+ export { createTruncationMarker, overflowMarkerFromDropped, prepareAgentEventForPersistence, } from "./event-persistence.js";
219
6
  export function createProjectionDriver(input) {
220
7
  if (input.initialTurn !== undefined
221
8
  && (!Number.isSafeInteger(input.initialTurn) || input.initialTurn < 0)) {
@@ -326,10 +113,19 @@ export function createProjectionDriver(input) {
326
113
  },
327
114
  signal: abortController.signal,
328
115
  });
329
- finish(() => resolveCompletion(outcome));
116
+ const completed = {
117
+ kind: "completed",
118
+ finalMessage: outcome.finalMessage,
119
+ session: outcome.session,
120
+ };
121
+ finish(() => resolveCompletion({
122
+ finalMessage: completed.finalMessage,
123
+ session: completed.session,
124
+ }));
330
125
  }
331
126
  catch (error) {
332
- finish(() => rejectCompletion(error));
127
+ // Boundary gate: adapter run throws become typed failed/aborted facts only.
128
+ finish(() => rejectCompletion(toProviderTerminalError(error)));
333
129
  }
334
130
  })();
335
131
  void runPromise;
@@ -348,11 +144,11 @@ export function createProjectionDriver(input) {
348
144
  ...(enqueue ? { enqueue } : {}),
349
145
  ...(input.clearQueue ? { clearQueue: input.clearQueue } : {}),
350
146
  async abort(mode = "graceful") {
351
- if (!abortController.signal.aborted) {
352
- abortController.abort();
353
- }
354
147
  if (mode === "force") {
355
148
  forceAbort ??= (async () => {
149
+ if (!abortController.signal.aborted) {
150
+ abortController.abort();
151
+ }
356
152
  await input.abort?.("force");
357
153
  await runPromise;
358
154
  })();
@@ -360,7 +156,14 @@ export function createProjectionDriver(input) {
360
156
  return;
361
157
  }
362
158
  gracefulAbort ??= (async () => {
363
- await input.abort?.("graceful");
159
+ try {
160
+ await input.abort?.("graceful");
161
+ }
162
+ finally {
163
+ if (!abortController.signal.aborted) {
164
+ abortController.abort();
165
+ }
166
+ }
364
167
  })();
365
168
  await gracefulAbort;
366
169
  },
@@ -1,7 +1,9 @@
1
1
  export { activityEventBodySchema, AGENT_EVENT_TEXT_MAX_CHARS, AGENT_UNKNOWN_PAYLOAD_MAX_CHARS, } from "./events.js";
2
2
  export { EXEC_EVENT_BUFFER_HARD_CAP } from "./event-channel.js";
3
3
  export { createAbortError } from "./runtime.js";
4
+ export { createProviderFailure, isProviderTerminalError, ProviderTerminalError, toProviderTerminalError, } from "./provider-adapter.js";
4
5
  export { restoreOutcome } from "./outcome.js";
5
6
  export { call, revive } from "./projection.js";
6
- export { SubagentFailure } from "../types.js";
7
+ export { isRecoverableSessionEnvelope } from "./session.js";
8
+ export { OUTCOME_ERROR_VERSION, SubagentFailure } from "../types.js";
7
9
  export { SUBAGENT_SESSION_VERSION, subagentSessionEnvelopeSchema, } from "../session.js";