@astrosheep/keiyaku 2.9.3 → 2.9.5

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 (282) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/agents/call-terms.js +14 -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 +26 -222
  6. package/build/agents/harness/index.js +3 -1
  7. package/build/agents/harness/outcome.js +68 -5
  8. package/build/agents/harness/projection.js +179 -124
  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 +82 -53
  21. package/build/agents/providers/codex-app-server/events.js +90 -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/events.js +4 -3
  36. package/build/agents/providers/pi/registration.js +145 -0
  37. package/build/agents/providers/pi/session-schema.js +6 -0
  38. package/build/agents/providers/pi/terms.js +1 -0
  39. package/build/agents/providers/registration.js +7 -0
  40. package/build/agents/providers/registry.js +76 -0
  41. package/build/agents/selector.js +2 -29
  42. package/build/agents/types.js +10 -0
  43. package/build/artifact-directories.js +22 -0
  44. package/build/cli/commands/akuma/akuma/handler.js +1 -1
  45. package/build/cli/commands/akuma/akuma/meta.js +1 -1
  46. package/build/cli/commands/akuma/list/meta-ls.js +1 -1
  47. package/build/cli/commands/akuma/view/handler.js +5 -4
  48. package/build/cli/commands/akuma/view/meta.js +1 -1
  49. package/build/cli/commands/akuma.js +6 -0
  50. package/build/cli/commands/contract/amend/handler.js +8 -2
  51. package/build/cli/commands/contract/amend/meta.js +4 -4
  52. package/build/cli/commands/contract/arc/handler.js +8 -2
  53. package/build/cli/commands/contract/arc/meta.js +4 -4
  54. package/build/cli/commands/contract/audit/handler.js +16 -0
  55. package/build/cli/commands/contract/audit/meta.js +16 -0
  56. package/build/cli/commands/contract/bind/handler.js +4 -3
  57. package/build/cli/commands/contract/bind/meta.js +44 -8
  58. package/build/cli/commands/contract/catalog.js +2 -0
  59. package/build/cli/commands/contract/forfeit/handler.js +4 -4
  60. package/build/cli/commands/contract/forfeit/meta.js +1 -1
  61. package/build/cli/commands/contract/log/handler.js +3 -3
  62. package/build/cli/commands/contract/log/meta.js +1 -1
  63. package/build/cli/commands/contract/petition/handler.js +5 -8
  64. package/build/cli/commands/contract/petition/meta.js +6 -6
  65. package/build/cli/commands/contract/renew/handler.js +20 -6
  66. package/build/cli/commands/contract/renew/meta.js +6 -5
  67. package/build/cli/commands/metadata.js +59 -0
  68. package/build/cli/commands/projection/call/handler.js +6 -5
  69. package/build/cli/commands/projection/call/meta.js +4 -1
  70. package/build/cli/commands/projection/kill/handler.js +16 -32
  71. package/build/cli/commands/projection/kill/meta.js +1 -1
  72. package/build/cli/commands/projection/revive/meta.js +4 -1
  73. package/build/cli/commands/projection/shared.js +28 -0
  74. package/build/cli/commands/projection/status/handler.js +1 -1
  75. package/build/cli/commands/projection/status/meta.js +1 -1
  76. package/build/cli/commands/projection/tell/handler.js +14 -30
  77. package/build/cli/commands/projection/tell/meta.js +4 -1
  78. package/build/cli/commands/projection/wait/handler.js +45 -22
  79. package/build/cli/commands/projection/wait/meta.js +8 -3
  80. package/build/cli/commands/registry.js +2 -54
  81. package/build/cli/commands/shared.js +10 -7
  82. package/build/cli/commands/skills/install/handler.js +2 -5
  83. package/build/cli/commands/skills/install/meta.js +1 -1
  84. package/build/cli/commands/skills/skills/handler.js +1 -1
  85. package/build/cli/commands/skills/skills/meta.js +1 -1
  86. package/build/cli/commands/system/completion/meta.js +1 -1
  87. package/build/cli/commands/system/dump-env/meta.js +1 -1
  88. package/build/cli/commands/system/guide/meta.js +1 -1
  89. package/build/cli/commands/task/add/handler.js +7 -15
  90. package/build/cli/commands/task/add/meta.js +4 -1
  91. package/build/cli/commands/task/catalog.js +2 -2
  92. package/build/cli/commands/task/doctor/meta.js +1 -1
  93. package/build/cli/commands/task/done/handler.js +4 -8
  94. package/build/cli/commands/task/done/meta.js +1 -1
  95. package/build/cli/commands/task/drop/handler.js +3 -6
  96. package/build/cli/commands/task/drop/meta.js +1 -1
  97. package/build/cli/commands/task/ls/handler.js +12 -8
  98. package/build/cli/commands/task/ls/meta.js +3 -3
  99. package/build/cli/commands/task/shared.js +14 -4
  100. package/build/cli/commands/task/{view → show}/handler.js +7 -8
  101. package/build/cli/commands/task/show/meta.js +8 -0
  102. package/build/cli/commands/task/start/handler.js +3 -6
  103. package/build/cli/commands/task/start/meta.js +1 -1
  104. package/build/cli/commands/task/stop/handler.js +4 -8
  105. package/build/cli/commands/task/stop/meta.js +1 -1
  106. package/build/cli/commands/task/task/handler.js +1 -1
  107. package/build/cli/commands/task/task/meta.js +1 -1
  108. package/build/cli/commands/task/update/handler.js +6 -11
  109. package/build/cli/commands/task/update/meta.js +4 -1
  110. package/build/cli/completion.js +1 -1
  111. package/build/cli/flags.js +37 -6
  112. package/build/cli/help.js +7 -14
  113. package/build/cli/index.js +112 -154
  114. package/build/cli/missing-subcommand.js +7 -0
  115. package/build/cli/output-stream-error-policy.js +19 -5
  116. package/build/cli/parse-flags.js +33 -7
  117. package/build/cli/parse-metadata.js +3 -9
  118. package/build/cli/parse-selectors.js +2 -1
  119. package/build/cli/parse.js +35 -5
  120. package/build/cli/projection-address.js +12 -12
  121. package/build/cli/render/address.js +41 -37
  122. package/build/cli/render/arc.js +24 -12
  123. package/build/cli/render/audit.js +121 -0
  124. package/build/cli/render/call.js +11 -5
  125. package/build/cli/render/errors.js +36 -1
  126. package/build/cli/render/format.js +4 -0
  127. package/build/cli/render/kanshi.js +6 -12
  128. package/build/cli/render/kill.js +9 -0
  129. package/build/cli/render/misc.js +58 -13
  130. package/build/cli/render/petition.js +20 -15
  131. package/build/cli/render/projection-activity.js +15 -6
  132. package/build/cli/render/shared.js +60 -21
  133. package/build/cli/render/skills.js +10 -0
  134. package/build/cli/render/status.js +56 -23
  135. package/build/cli/render/success-response.js +78 -0
  136. package/build/cli/render/task.js +66 -57
  137. package/build/cli/render/tell.js +5 -0
  138. package/build/cli/render/terminal-failure.js +63 -0
  139. package/build/cli/render/types.js +1 -0
  140. package/build/cli/render/wait.js +68 -38
  141. package/build/cli/types.js +1 -1
  142. package/build/config/akuma-loader.js +0 -5
  143. package/build/config/env-keys.js +3 -1
  144. package/build/config/env.js +3 -0
  145. package/build/config/provider-policy-ownership.js +3 -32
  146. package/build/config/settings/disease.js +8 -1
  147. package/build/config/settings/loader.js +11 -3
  148. package/build/config/settings/provider-instance-fields.js +51 -0
  149. package/build/config/settings/schema.js +6 -176
  150. package/build/core/addressing.js +66 -16
  151. package/build/core/amend.js +61 -18
  152. package/build/core/arc.js +33 -73
  153. package/build/core/audit.js +650 -0
  154. package/build/core/bind.js +82 -35
  155. package/build/core/call/call.js +15 -9
  156. package/build/core/call/context.js +6 -51
  157. package/build/core/call/execution.js +22 -22
  158. package/build/core/call/prompt.js +14 -1
  159. package/build/core/command-markdown.js +45 -0
  160. package/build/core/context.js +13 -7
  161. package/build/core/contract-view.js +22 -6
  162. package/build/core/draft.js +139 -19
  163. package/build/core/entry.js +3 -4
  164. package/build/core/forfeit.js +5 -2
  165. package/build/core/hints.js +1 -75
  166. package/build/core/identifier-slug.js +66 -0
  167. package/build/core/ids.js +25 -11
  168. package/build/core/ledger.js +20 -68
  169. package/build/core/markdown/lex.js +2 -1
  170. package/build/core/markdown/parser.js +0 -68
  171. package/build/core/markdown/render.js +68 -0
  172. package/build/core/markdown/sections.js +2 -1
  173. package/build/core/outcome-base.js +4 -0
  174. package/build/core/projection/generation/database.js +41 -52
  175. package/build/core/projection/generation/model.js +63 -2
  176. package/build/core/{projection-generation-continuation.js → projection/generation/projection-generation-continuation.js} +3 -3
  177. package/build/core/{projection-generation-execution.js → projection/generation/projection-generation-execution.js} +36 -53
  178. package/build/core/{projection-generation-identity.js → projection/generation/projection-generation-identity.js} +2 -2
  179. package/build/core/{projection-generation-launcher.js → projection/generation/projection-generation-launcher.js} +9 -7
  180. package/build/core/{projection-generation-process.js → projection/generation/projection-generation-process.js} +2 -1
  181. package/build/core/{projection-generation-runner.js → projection/generation/projection-generation-runner.js} +19 -3
  182. package/build/core/projection/generation/store.js +3 -3
  183. package/build/core/projection/generation/transitions.js +19 -3
  184. package/build/core/projection/index.js +27 -0
  185. package/build/core/{projection-activity.js → projection/projection-activity.js} +12 -0
  186. package/build/core/{projection-alias.js → projection/projection-alias.js} +13 -13
  187. package/build/core/projection/projection-coordinate.js +61 -0
  188. package/build/core/{projection-core.js → projection/projection-core.js} +9 -9
  189. package/build/core/{projection-execution-observer.js → projection/projection-execution-observer.js} +37 -78
  190. package/build/core/{projection-identity.js → projection/projection-identity.js} +1 -1
  191. package/build/core/{projection-kill.js → projection/projection-kill.js} +1 -1
  192. package/build/core/{projection-life-observer.js → projection/projection-life-observer.js} +16 -2
  193. package/build/core/{projection-mint.js → projection/projection-mint.js} +10 -10
  194. package/build/core/{projection-status.js → projection/projection-status.js} +163 -45
  195. package/build/core/projection/projection-terminal-failure.js +106 -0
  196. package/build/core/projection/projection-wait.js +275 -0
  197. package/build/core/projection/projection-wake.js +227 -0
  198. package/build/core/provider-loader-ports.js +4 -0
  199. package/build/core/ref-log.js +65 -40
  200. package/build/core/registry.js +63 -10
  201. package/build/core/renew-session.js +128 -0
  202. package/build/core/renew.js +448 -102
  203. package/build/core/scope.js +272 -68
  204. package/build/core/seal.js +165 -40
  205. package/build/core/{claim-delivery.js → settlement/claim-delivery.js} +8 -8
  206. package/build/core/{claim.js → settlement/claim.js} +32 -8
  207. package/build/core/settlement/index.js +19 -0
  208. package/build/core/{petition-claim-gates.js → settlement/petition-claim-gates.js} +24 -49
  209. package/build/core/{petition-forfeit.js → settlement/petition-forfeit.js} +2 -2
  210. package/build/core/{petition-head-guard.js → settlement/petition-head-guard.js} +2 -2
  211. package/build/core/settlement/petition-io.js +1 -0
  212. package/build/core/{petition-preview.js → settlement/petition-preview.js} +2 -2
  213. package/build/core/{petition.js → settlement/petition.js} +21 -12
  214. package/build/core/settlement/queue-read-model.js +143 -0
  215. package/build/core/settlement/queue-seat-allocation.js +156 -0
  216. package/build/core/settlement/queue.js +6 -0
  217. package/build/core/settlement/settlement.js +288 -0
  218. package/build/core/{verdict.js → settlement/verdict.js} +9 -37
  219. package/build/core/settlement/verification.js +59 -0
  220. package/build/core/status/board.js +62 -41
  221. package/build/core/status/ledger-batch.js +158 -0
  222. package/build/core/status/reconciliation.js +10 -4
  223. package/build/core/stored-agent-event.js +6 -2
  224. package/build/core/task/board.js +41 -4
  225. package/build/core/task/commands.js +45 -28
  226. package/build/core/task/document.js +5 -0
  227. package/build/core/task/index.js +12 -0
  228. package/build/core/task/model.js +8 -1
  229. package/build/core/task/query.js +172 -0
  230. package/build/core/task/settlement-git.js +265 -74
  231. package/build/core/task/settlement-policy.js +67 -29
  232. package/build/core/task/source-board.js +1 -0
  233. package/build/core/task/task-contract.js +444 -0
  234. package/build/core/{task-doctor.js → task/task-doctor.js} +1 -1
  235. package/build/core/{task-git-actor.js → task/task-git-actor.js} +5 -10
  236. package/build/core/{task-git-runtime.js → task/task-git-runtime.js} +3 -3
  237. package/build/core/{task-git-store.js → task/task-git-store.js} +90 -19
  238. package/build/core/task/task-repository.js +1 -0
  239. package/build/core/{task-store-repository.js → task/task-store-repository.js} +6 -4
  240. package/build/core/task/task-store.js +1 -0
  241. package/build/core/{task-worktree.js → task/task-worktree.js} +2 -1
  242. package/build/core/task/task.js +7 -0
  243. package/build/core/task/tree.js +37 -0
  244. package/build/core/task/validation.js +5 -2
  245. package/build/core/transcripts.js +15 -3
  246. package/build/core/worktree-path.js +43 -28
  247. package/build/flow-error.js +83 -39
  248. package/build/fs/path-coordinate.js +16 -0
  249. package/build/generated/version.js +3 -2
  250. package/build/git/branches.js +2 -1
  251. package/build/git/core.js +106 -2
  252. package/build/git/diff/parsers.js +23 -13
  253. package/build/git/diff/structured.js +127 -0
  254. package/build/git/path-coordinate.js +17 -0
  255. package/build/git/refs.js +57 -0
  256. package/build/git/streaming-batch.js +301 -0
  257. package/build/git/worktree.js +65 -0
  258. package/build/index.js +9 -9
  259. package/build/keiyaku.js +2 -36
  260. package/build/telemetry/logger.js +4 -2
  261. package/package.json +4 -10
  262. package/skills/keiyaku/SKILL.md +5 -4
  263. package/skills/keiyaku-akuma/SKILL.md +25 -11
  264. package/skills/keiyaku-task/SKILL.md +17 -8
  265. package/skills/keiyaku-workflow/SKILL.md +58 -9
  266. package/build/agents/providers/codex-sdk.js +0 -329
  267. package/build/cli/commands/task/view/meta.js +0 -8
  268. package/build/core/command-io.js +0 -174
  269. package/build/core/path-coordinate.js +0 -27
  270. package/build/core/petition-claim.js +0 -117
  271. package/build/core/petition-run.js +0 -83
  272. package/build/core/projection-coordinate.js +0 -63
  273. package/build/core/projection-wait.js +0 -165
  274. package/build/core/projection-wake.js +0 -136
  275. package/build/core/queue.js +0 -343
  276. package/build/core/task-contract.js +0 -237
  277. package/build/core/task.js +0 -4
  278. /package/build/{core/task-repository.js → agents/launch-snapshot/types.js} +0 -0
  279. /package/build/{core/task-store.js → agents/providers/claude-agent-sdk/terms.js} +0 -0
  280. /package/build/core/{projection-generation-runtime.js → projection/generation/projection-generation-runtime.js} +0 -0
  281. /package/build/core/{projection-life-protocol.js → projection/projection-life-protocol.js} +0 -0
  282. /package/build/core/{projection-runner-lock.js → projection/projection-runner-lock.js} +0 -0
@@ -1,52 +1,23 @@
1
- import { z } from "zod";
2
1
  import { appendDebugLog } from "../../../telemetry/debug-log.js";
3
2
  import { SUBAGENT_SESSION_VERSION } from "../../session.js";
4
3
  import { createProjectionDriver } from "../../harness/execution-handle.js";
5
- import { buildSubagentEnv, createAbortError, emitProviderEvidence, coerceString } from "../../harness/runtime.js";
4
+ import { createProviderFailure } from "../../harness/provider-adapter.js";
5
+ import { awaitProviderAbortSettlement, buildSubagentEnv, createAbortError, emitProviderEvidence, coerceString, } from "../../harness/runtime.js";
6
+ import { CODEX_APP_SERVER_PROVIDER } from "./identity.js";
6
7
  import { CodexAppServerProcess } from "./session.js";
7
8
  import { createCodexAppServerTurnMonitor, createCodexAppServerTurnState, recordTurnStartResponse, } from "./events.js";
9
+ export { CODEX_APP_SERVER_PROVIDER } from "./identity.js";
8
10
  /** Identity-only opacity boundary for codex-app-server turn/start effort. */
9
11
  function toCodexAppServerEffort(effort) {
10
12
  return effort;
11
13
  }
12
- /** Session handle for codex-app-server: thread id plus optional CODEX_HOME for cross-process resume. */
13
- export const codexAppServerSessionSchema = z.object({
14
- threadId: z.string().trim().min(1),
15
- codexHome: z.string().trim().min(1).optional(),
16
- });
17
- const CODEX_APP_SERVER_PROVIDER = "codex-app-server";
14
+ export { codexAppServerSessionSchema } from "./session-schema.js";
18
15
  const MINIMUM_CODEX_APP_SERVER_VERSION = { major: 0, minor: 143, patch: 0 };
16
+ const CODEX_APP_SERVER_PROBE_TIMEOUT_MS = 1_000;
19
17
  /** Non-interactive defaults for turn/start (faye #316 policy A). */
20
18
  export const CODEX_APP_SERVER_TURN_APPROVAL_POLICY = "never";
21
- export function buildCodexAppServerWorkspaceWriteSandboxPolicy(input) {
22
- return {
23
- type: "workspaceWrite",
24
- writableRoots: [...input.writableRoots],
25
- networkAccess: input.networkAccess,
26
- excludeTmpdirEnvVar: false,
27
- excludeSlashTmp: false,
28
- };
29
- }
30
- /** True when config.* already owns approval policy — omit turn-level approvalPolicy default. */
31
- export function configOwnsApprovalPolicy(config) {
32
- if (!config)
33
- return false;
34
- return Object.prototype.hasOwnProperty.call(config, "approval_policy");
35
- }
36
- /**
37
- * True when config.* already owns sandbox settings — omit turn-level sandboxPolicy default.
38
- * Matches `sandbox_mode` or any `sandbox_workspace_write` / `sandbox_workspace_write.*` key.
39
- */
40
- export function configOwnsSandboxPolicy(config) {
41
- if (!config)
42
- return false;
43
- for (const key of Object.keys(config)) {
44
- if (key === "sandbox_mode" || key === "sandbox_workspace_write" || key.startsWith("sandbox_workspace_write.")) {
45
- return true;
46
- }
47
- }
48
- return false;
49
- }
19
+ export { buildCodexAppServerWorkspaceWriteSandboxPolicy, configOwnsApprovalPolicy, configOwnsSandboxPolicy, } from "./policy.js";
20
+ import { buildCodexAppServerWorkspaceWriteSandboxPolicy, configOwnsApprovalPolicy, configOwnsSandboxPolicy, } from "./policy.js";
50
21
  function parseSemver(version) {
51
22
  const match = version.trim().match(/(\d+)\.(\d+)\.(\d+)/);
52
23
  if (!match)
@@ -83,6 +54,14 @@ function extractVersionFromInitialize(result) {
83
54
  }
84
55
  return coerceString(record.version) ?? coerceString(record.cliVersion);
85
56
  }
57
+ export async function settleCodexGracefulInterrupt(input) {
58
+ await input.requestInterrupt();
59
+ const terminal = await input.completion;
60
+ const terminalTurnId = coerceString(terminal.turn.id);
61
+ if (terminalTurnId !== input.turnId || terminal.status !== "interrupted") {
62
+ throw new Error(`${CODEX_APP_SERVER_PROVIDER} graceful abort expected interrupted turn '${input.turnId}', got '${terminalTurnId ?? "unknown"}' status '${terminal.status}'`);
63
+ }
64
+ }
86
65
  /** Gate-facing production entry: the harness owns clocks, capture, classification, and outcome construction. */
87
66
  export async function startCodexAppServer(prompt, cwd, options = {}) {
88
67
  const executable = options.executable?.trim() || "codex";
@@ -91,6 +70,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
91
70
  const turnState = createCodexAppServerTurnState();
92
71
  let activeThreadId;
93
72
  let interruptRequested = false;
73
+ let activeTurnCompletion;
94
74
  let builderDiagnostic;
95
75
  let emitTurnStarted;
96
76
  const pendingTells = [];
@@ -193,10 +173,41 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
193
173
  void drainPendingTells();
194
174
  });
195
175
  };
176
+ const probe = async () => {
177
+ if (!server || !activeThreadId) {
178
+ throw createProviderFailure(`${CODEX_APP_SERVER_PROVIDER} session probe has no active thread`, {
179
+ code: "SUBAGENT_TRANSPORT_ERROR",
180
+ timeoutMs: CODEX_APP_SERVER_PROBE_TIMEOUT_MS,
181
+ });
182
+ }
183
+ let timer;
184
+ const deadline = new Promise((_, reject) => {
185
+ timer = setTimeout(() => reject(new Error("session probe timed out")), CODEX_APP_SERVER_PROBE_TIMEOUT_MS);
186
+ timer.unref?.();
187
+ });
188
+ try {
189
+ await Promise.race([
190
+ server.request("thread/read", { threadId: activeThreadId }),
191
+ deadline,
192
+ ]);
193
+ }
194
+ catch (error) {
195
+ throw createProviderFailure(`${CODEX_APP_SERVER_PROVIDER} session transport probe failed`, {
196
+ code: "SUBAGENT_TRANSPORT_ERROR",
197
+ timeoutMs: CODEX_APP_SERVER_PROBE_TIMEOUT_MS,
198
+ cause: error,
199
+ });
200
+ }
201
+ finally {
202
+ if (timer)
203
+ clearTimeout(timer);
204
+ }
205
+ };
196
206
  return createProjectionDriver({
197
207
  steerMode: "mid-execution",
198
208
  initialTurn: options.initialTurn,
199
209
  enqueue,
210
+ probe,
200
211
  onIngress: options.onIngress,
201
212
  async abort(mode) {
202
213
  interruptRequested = true;
@@ -204,19 +215,29 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
204
215
  await server?.close("force");
205
216
  return;
206
217
  }
207
- if (server && activeThreadId && turnState.activeTurnId) {
208
- try {
209
- // RPC acknowledgement is NOT terminal proof; wait for turn/completed interrupted.
210
- await server.request("turn/interrupt", {
211
- threadId: activeThreadId,
212
- turnId: turnState.activeTurnId,
213
- });
214
- }
215
- catch {
216
- // idle interrupt may error; still rely on process teardown
218
+ if (!server)
219
+ return;
220
+ if (activeThreadId && turnState.activeTurnId) {
221
+ const turnId = turnState.activeTurnId;
222
+ const completion = activeTurnCompletion;
223
+ if (!completion) {
224
+ throw new Error(`${CODEX_APP_SERVER_PROVIDER} graceful abort lacked an active turn monitor`);
217
225
  }
226
+ await awaitProviderAbortSettlement(CODEX_APP_SERVER_PROVIDER, (async () => {
227
+ // RPC acknowledgement is submission evidence only. Keep the monitor
228
+ // and server alive until the matching terminal notification arrives.
229
+ await settleCodexGracefulInterrupt({
230
+ turnId,
231
+ requestInterrupt: () => server.request("turn/interrupt", {
232
+ threadId: activeThreadId,
233
+ turnId,
234
+ }),
235
+ completion,
236
+ });
237
+ })());
238
+ return;
218
239
  }
219
- await server?.close("graceful");
240
+ await awaitProviderAbortSettlement(CODEX_APP_SERVER_PROVIDER, server.close("force"), "startup abort could not force-close owned server");
220
241
  },
221
242
  async run(builder) {
222
243
  builderDiagnostic = (text) => builder.emit({ type: "diagnostic", text });
@@ -239,6 +260,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
239
260
  isDrainingTells: () => drainingTells,
240
261
  setFinishAfterTellDrain: (finish) => { finishAfterTellDrain = finish; },
241
262
  });
263
+ activeTurnCompletion = turnCompleted;
242
264
  try {
243
265
  const initResult = await server.request("initialize", {
244
266
  clientInfo: {
@@ -255,7 +277,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
255
277
  if (isCodexAppServerVersionBelowMinimum(version)) {
256
278
  const message = `${CODEX_APP_SERVER_PROVIDER} refused: initialize version '${version}' is below minimum supported version 0.143.0`;
257
279
  builder.emit({ type: "fail", message });
258
- throw new Error(message);
280
+ throw createProviderFailure(message);
259
281
  }
260
282
  const initRecord = (initResult && typeof initResult === "object" ? initResult : {});
261
283
  const serverCodexHome = coerceString(initRecord.codexHome) ?? options.codexHome;
@@ -280,7 +302,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
280
302
  if (!activeThreadId) {
281
303
  const message = `${CODEX_APP_SERVER_PROVIDER} exec could not determine thread id`;
282
304
  builder.emit({ type: "fail", message });
283
- throw new Error(message);
305
+ throw createProviderFailure(message);
284
306
  }
285
307
  if (options.onEvidence)
286
308
  emitProviderEvidence(options.onEvidence, { type: "session", provider: CODEX_APP_SERVER_PROVIDER, threadId: activeThreadId }, builderDiagnostic);
@@ -303,6 +325,8 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
303
325
  turnState.activeTurnId = undefined;
304
326
  turnState.activeTurnSource = undefined;
305
327
  turnState.activeTurnAcceptingSteer = false;
328
+ turnState.failureCause = undefined;
329
+ turnState.turnInFlight = true;
306
330
  const turnStart = await server.request("turn/start", turnStartParams);
307
331
  const turn = turnStart && typeof turnStart === "object"
308
332
  ? (turnStart.turn ?? undefined)
@@ -311,18 +335,20 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
311
335
  if (options.onEvidence)
312
336
  emitProviderEvidence(options.onEvidence, { type: "checkpoint", provider: CODEX_APP_SERVER_PROVIDER, fence: { kind: "turn", turnId }, source: "response" }, builderDiagnostic);
313
337
  const completed = await turnCompleted;
338
+ turnState.turnInFlight = false;
314
339
  if (completed.status === "interrupted" || interruptRequested) {
315
340
  throw createAbortError(`${CODEX_APP_SERVER_PROVIDER} turn interrupted`);
316
341
  }
317
342
  if (completed.status === "failed") {
318
343
  const message = `${CODEX_APP_SERVER_PROVIDER} turn failed`;
319
- builder.emit({ type: "fail", message });
320
- throw new Error(message);
344
+ throw createProviderFailure(message, {
345
+ ...(turnState.failureCause ? { publicCause: turnState.failureCause } : {}),
346
+ });
321
347
  }
322
348
  if (completed.status !== "completed") {
323
349
  const message = `${CODEX_APP_SERVER_PROVIDER} turn ended with status '${completed.status}'`;
324
350
  builder.emit({ type: "fail", message });
325
- throw new Error(message);
351
+ throw createProviderFailure(message);
326
352
  }
327
353
  // Successful turn/completed is consumption evidence; interrupt ack alone is not terminal proof.
328
354
  const session = {
@@ -338,6 +364,7 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
338
364
  return { finalMessage, session };
339
365
  }
340
366
  finally {
367
+ activeTurnCompletion = undefined;
341
368
  rejectPendingTells(new Error(`${CODEX_APP_SERVER_PROVIDER} execution ended before queued tell acceptance`));
342
369
  await server?.close();
343
370
  server = undefined;
@@ -345,3 +372,5 @@ export async function startCodexAppServer(prompt, cwd, options = {}) {
345
372
  },
346
373
  });
347
374
  }
375
+ // Compiler-level binding to the named ProviderAdapter function contract.
376
+ startCodexAppServer;
@@ -1,7 +1,8 @@
1
1
  import { boundActivityExcerpt, diffstatFromUnifiedPatch } from "../../harness/activity-values.js";
2
2
  import { AGENT_PLAN_ITEM_TEXT_MAX_CHARS, AGENT_PLAN_MAX_ITEMS, AGENT_THOUGHT_TEXT_MAX_CHARS, } from "../../harness/events.js";
3
+ import { createProviderFailure } from "../../harness/provider-adapter.js";
3
4
  import { createAbortError, emitProviderEvidence, coerceString } from "../../harness/runtime.js";
4
- const CODEX_APP_SERVER_PROVIDER = "codex-app-server";
5
+ import { CODEX_APP_SERVER_PROVIDER } from "./identity.js";
5
6
  const CODEX_APP_SERVER_NOTIFICATION_ACKNOWLEDGED = new Set([
6
7
  "item/agentMessage/delta",
7
8
  "item/commandExecution/outputDelta",
@@ -16,11 +17,18 @@ const CODEX_APP_SERVER_NOTIFICATION_MAPPED = new Set([
16
17
  "turn/completed",
17
18
  "error",
18
19
  ]);
19
- export function codexAppServerNotificationDisposition(method) {
20
+ export function codexAppServerNotificationDisposition(method, params) {
20
21
  if (CODEX_APP_SERVER_NOTIFICATION_ACKNOWLEDGED.has(method))
21
22
  return "acknowledged-unpersisted";
22
23
  if (CODEX_APP_SERVER_NOTIFICATION_MAPPED.has(method))
23
24
  return "mapped";
25
+ if (method === "item/started") {
26
+ const item = appServerRecord(appServerRecord(params)?.item);
27
+ if (item && typeof item.type === "string" && isCodexAppServerActivityItemType(item.type))
28
+ return "mapped";
29
+ }
30
+ if (method === "account/rateLimits/updated" && codexAppServerRateLimitCause(params))
31
+ return "mapped";
24
32
  return "unknown";
25
33
  }
26
34
  export function appServerRecord(value) {
@@ -37,6 +45,41 @@ const CODEX_APP_SERVER_ACTIVITY_ITEM_TYPES = [
37
45
  function isCodexAppServerActivityItemType(value) {
38
46
  return CODEX_APP_SERVER_ACTIVITY_ITEM_TYPES.includes(value);
39
47
  }
48
+ /** Map a native or legacy fileChange kind fact into the public op. */
49
+ function appServerFileChangeOp(kind) {
50
+ if (kind === "add" || kind === "update" || kind === "delete")
51
+ return kind;
52
+ const record = appServerRecord(kind);
53
+ if (!record)
54
+ return undefined;
55
+ if (record.type === "add" || record.type === "update" || record.type === "delete")
56
+ return record.type;
57
+ return undefined;
58
+ }
59
+ /** Trustworthy provider patch text only: per-change native `diff`, else legacy `details.patch`. */
60
+ function appServerFileChangeDiffstat(item) {
61
+ let additions = 0;
62
+ let deletions = 0;
63
+ let saw = false;
64
+ if (Array.isArray(item.changes)) {
65
+ for (const entry of item.changes) {
66
+ const change = appServerRecord(entry);
67
+ if (!change || typeof change.diff !== "string" || !change.diff)
68
+ continue;
69
+ const partial = diffstatFromUnifiedPatch(change.diff);
70
+ if (!partial)
71
+ continue;
72
+ saw = true;
73
+ additions += partial.additions;
74
+ deletions += partial.deletions;
75
+ }
76
+ }
77
+ if (saw)
78
+ return additions || deletions ? { additions, deletions } : undefined;
79
+ const details = appServerRecord(item.details);
80
+ const patch = typeof details?.patch === "string" ? details.patch : undefined;
81
+ return patch ? diffstatFromUnifiedPatch(patch) : undefined;
82
+ }
40
83
  export function appServerActivityCall(itemType, item) {
41
84
  switch (itemType) {
42
85
  case "commandExecution":
@@ -53,9 +96,9 @@ export function appServerActivityCall(itemType, item) {
53
96
  const change = appServerRecord(entry);
54
97
  if (!change || typeof change.path !== "string")
55
98
  return [];
56
- if (change.kind !== "add" && change.kind !== "update" && change.kind !== "delete")
99
+ const op = appServerFileChangeOp(change.kind);
100
+ if (!op)
57
101
  return [];
58
- const op = change.kind;
59
102
  return [{ op, path: change.path }];
60
103
  })
61
104
  : [];
@@ -80,11 +123,7 @@ export function appServerActivityResult(item) {
80
123
  : typeof item.error === "string" && item.error
81
124
  ? boundActivityExcerpt(item.error)
82
125
  : undefined;
83
- const details = item.details !== null && typeof item.details === "object" && !Array.isArray(item.details)
84
- ? item.details
85
- : undefined;
86
- const patch = typeof details?.patch === "string" ? details.patch : undefined;
87
- const diffstat = patch ? diffstatFromUnifiedPatch(patch) : undefined;
126
+ const diffstat = appServerFileChangeDiffstat(item);
88
127
  return {
89
128
  status: item.status === "failed" || (exitCode !== undefined && exitCode !== 0) ? "error" : "ok",
90
129
  ...(message ? { message } : {}),
@@ -131,9 +170,23 @@ export function createCodexAppServerTurnState() {
131
170
  responseSeenTurnIds: new Set(),
132
171
  completedBeforeResponseTurnIds: new Set(),
133
172
  activeTurnAcceptingSteer: false,
173
+ turnInFlight: false,
134
174
  lastAgentMessage: "",
135
175
  };
136
176
  }
177
+ /** Admit only positive native exhaustion evidence; no provider strings survive. */
178
+ export function codexAppServerRateLimitCause(params) {
179
+ const rateLimits = appServerRecord(appServerRecord(params)?.rateLimits);
180
+ if (!rateLimits)
181
+ return undefined;
182
+ for (const value of Object.values(rateLimits)) {
183
+ const window = appServerRecord(value);
184
+ if (typeof window?.usedPercent === "number" && window.usedPercent >= 100) {
185
+ return { kind: "rate_limit_exhausted" };
186
+ }
187
+ }
188
+ return undefined;
189
+ }
137
190
  export function recordActiveTurnId(state, candidate, source) {
138
191
  const turnId = coerceString(candidate);
139
192
  if (!turnId)
@@ -178,7 +231,7 @@ export function createCodexAppServerTurnMonitor(options) {
178
231
  const failServerRequest = (request) => {
179
232
  // Policy A forbids interactive server→client requests. Fail immediately with named diagnostic.
180
233
  const message = `${CODEX_APP_SERVER_PROVIDER} unexpected server request '${request.method}' (id=${String(request.id)}); non-interactive policy forbids server→client requests`;
181
- failTurn(new Error(message));
234
+ failTurn(createProviderFailure(message));
182
235
  };
183
236
  const requestDeliveryOpportunity = () => {
184
237
  try {
@@ -200,7 +253,7 @@ export function createCodexAppServerTurnMonitor(options) {
200
253
  });
201
254
  unsubNotifications = server.onNotification((notification) => {
202
255
  try {
203
- builder.ingress(CODEX_APP_SERVER_PROVIDER, notification.method, notification, codexAppServerNotificationDisposition(notification.method), () => {
256
+ builder.ingress(CODEX_APP_SERVER_PROVIDER, notification.method, notification, codexAppServerNotificationDisposition(notification.method, notification.params), () => {
204
257
  if (notification.method === "item/agentMessage/delta") {
205
258
  const delta = coerceString(notification.params?.delta);
206
259
  if (delta) {
@@ -255,6 +308,24 @@ export function createCodexAppServerTurnMonitor(options) {
255
308
  });
256
309
  }
257
310
  }
311
+ if (notification.method === "item/started") {
312
+ const item = notification.params?.item;
313
+ if (!item)
314
+ throw new Error(`${CODEX_APP_SERVER_PROVIDER} item/started lacked required item`);
315
+ const id = coerceString(item.id);
316
+ const itemType = coerceString(item.type);
317
+ if (!id || !itemType)
318
+ throw new Error(`${CODEX_APP_SERVER_PROVIDER} item/started lacked required item id or type`);
319
+ if (isCodexAppServerActivityItemType(itemType)) {
320
+ builder.emit({
321
+ type: "activity",
322
+ phase: "started",
323
+ id,
324
+ tool: itemType,
325
+ call: appServerActivityCall(itemType, item),
326
+ });
327
+ }
328
+ }
258
329
  if (notification.method === "turn/started") {
259
330
  const turn = notification.params?.turn;
260
331
  const turnId = recordActiveTurnId(state, turn?.id, "notification");
@@ -274,6 +345,14 @@ export function createCodexAppServerTurnMonitor(options) {
274
345
  onSyncCheckpoint?.({ enqueue }, checkpoint);
275
346
  void drainPendingTells();
276
347
  }
348
+ if (notification.method === "account/rateLimits/updated") {
349
+ const cause = codexAppServerRateLimitCause(notification.params);
350
+ if (cause) {
351
+ builder.emit({ type: "warning", warning: { reason: "rate-limit", state: "exhausted" } });
352
+ if (state.turnInFlight)
353
+ state.failureCause ??= cause;
354
+ }
355
+ }
277
356
  if (notification.method === "turn/completed") {
278
357
  const turn = notification.params?.turn ?? {};
279
358
  const status = coerceString(turn.status) ?? "unknown";
@@ -0,0 +1 @@
1
+ export const CODEX_APP_SERVER_PROVIDER = "codex-app-server";
@@ -0,0 +1,29 @@
1
+ export function buildCodexAppServerWorkspaceWriteSandboxPolicy(input) {
2
+ return {
3
+ type: "workspaceWrite",
4
+ writableRoots: [...input.writableRoots],
5
+ networkAccess: input.networkAccess,
6
+ excludeTmpdirEnvVar: false,
7
+ excludeSlashTmp: false,
8
+ };
9
+ }
10
+ /** True when config.* already owns approval policy — omit turn-level approvalPolicy default. */
11
+ export function configOwnsApprovalPolicy(config) {
12
+ if (!config)
13
+ return false;
14
+ return Object.prototype.hasOwnProperty.call(config, "approval_policy");
15
+ }
16
+ /**
17
+ * True when config.* already owns sandbox settings — omit turn-level sandboxPolicy default.
18
+ * Matches `sandbox_mode` or any `sandbox_workspace_write` / `sandbox_workspace_write.*` key.
19
+ */
20
+ export function configOwnsSandboxPolicy(config) {
21
+ if (!config)
22
+ return false;
23
+ for (const key of Object.keys(config)) {
24
+ if (key === "sandbox_mode" || key === "sandbox_workspace_write" || key.startsWith("sandbox_workspace_write.")) {
25
+ return true;
26
+ }
27
+ }
28
+ return false;
29
+ }