humanish 0.106.0 → 0.107.0

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 (459) hide show
  1. package/AGENTS.md +4 -2
  2. package/ARCHITECTURE.md +17 -16
  3. package/CHANGELOG.md +24 -0
  4. package/CONTEXT.md +42 -39
  5. package/CONTRIBUTING.md +8 -6
  6. package/README.md +8 -3
  7. package/dist/actors/codex/app-server-client.js +2 -1
  8. package/dist/actors/codex/app-server-trace.d.ts +0 -1
  9. package/dist/actors/codex/app-server-trace.js +1 -3
  10. package/dist/actors/codex/app-server.js +2 -1
  11. package/dist/actors/codex/protocol-compat.d.ts +27 -0
  12. package/dist/actors/codex/protocol-compat.js +357 -0
  13. package/dist/actors/codex/protocol-contract.d.ts +61 -0
  14. package/dist/actors/codex/protocol-contract.js +471 -0
  15. package/dist/actors/codex/qualified-versions.d.ts +31 -4
  16. package/dist/actors/codex/qualified-versions.js +51 -6
  17. package/dist/actors/codex/restricted-executable.d.ts +24 -0
  18. package/dist/actors/codex/restricted-executable.js +97 -22
  19. package/dist/actors/codex/restricted-launch.d.ts +7 -1
  20. package/dist/actors/codex/restricted-launch.js +42 -3
  21. package/dist/actors/codex/restricted-notifications.d.ts +101 -0
  22. package/dist/actors/codex/restricted-notifications.js +277 -0
  23. package/dist/actors/codex/restricted-participant.d.ts +30 -0
  24. package/dist/actors/codex/restricted-participant.js +60 -2
  25. package/dist/actors/codex/restricted-policy.d.ts +9 -1
  26. package/dist/actors/codex/restricted-session.d.ts +14 -1
  27. package/dist/actors/codex/restricted-session.js +50 -17
  28. package/dist/actors/codex/restricted-transport.d.ts +29 -0
  29. package/dist/actors/codex/restricted-transport.js +139 -27
  30. package/dist/actors/codex/restricted-turn.d.ts +19 -4
  31. package/dist/actors/codex/restricted-turn.js +43 -30
  32. package/dist/actors/computer-use/actor.d.ts +1 -1
  33. package/dist/actors/computer-use/actor.js +4 -4
  34. package/dist/actors/computer-use/loop/backstop.js +1 -1
  35. package/dist/actors/computer-use/loop/ending.d.ts +2 -2
  36. package/dist/actors/computer-use/loop/ending.js +2 -2
  37. package/dist/actors/computer-use/loop/spend.d.ts +1 -1
  38. package/dist/actors/computer-use/loop/spend.js +3 -3
  39. package/dist/actors/computer-use/loop/trace.js +2 -2
  40. package/dist/actors/computer-use/loop/types.d.ts +14 -5
  41. package/dist/actors/computer-use/loop.js +4 -4
  42. package/dist/actors/computer-use/openai-provider.d.ts +1 -1
  43. package/dist/actors/computer-use/openai-provider.js +2 -2
  44. package/dist/actors/contract.d.ts +10 -8
  45. package/dist/actors/contract.js +7 -1
  46. package/dist/actors/local-agent/cli.js +1 -1
  47. package/dist/actors/scripted-browser/actor.d.ts +2 -2
  48. package/dist/actors/scripted-browser/journey.js +15 -4
  49. package/dist/actors/scripted-browser/steps.js +18 -0
  50. package/dist/actors/scripted-browser/types.d.ts +11 -1
  51. package/dist/actors/stop-conditions.js +1 -3
  52. package/dist/analysis/automatic-completion.d.ts +13 -8
  53. package/dist/analysis/automatic-completion.js +14 -8
  54. package/dist/analysis/automatic-config.d.ts +1 -1
  55. package/dist/analysis/automatic-config.js +2 -2
  56. package/dist/analysis/automatic.d.ts +10 -4
  57. package/dist/analysis/automatic.js +17 -13
  58. package/dist/analysis/diagnostics.d.ts +23 -0
  59. package/dist/analysis/diagnostics.js +112 -0
  60. package/dist/analysis/evidence-sources.js +2 -2
  61. package/dist/analysis/evidence.js +6 -6
  62. package/dist/analysis/execute.d.ts +7 -1
  63. package/dist/analysis/execute.js +39 -12
  64. package/dist/analysis/job.d.ts +8 -5
  65. package/dist/analysis/job.js +15 -14
  66. package/dist/analysis/load.d.ts +1 -1
  67. package/dist/analysis/load.js +5 -5
  68. package/dist/analysis/provider.d.ts +9 -1
  69. package/dist/analysis/restricted-codex.d.ts +2 -0
  70. package/dist/analysis/restricted-codex.js +10 -1
  71. package/dist/analysis/service.d.ts +2 -0
  72. package/dist/analysis/service.js +31 -12
  73. package/dist/analysis/sharing.d.ts +2 -2
  74. package/dist/analysis/sharing.js +5 -5
  75. package/dist/analysis/store-executions.d.ts +5 -5
  76. package/dist/analysis/store-executions.js +12 -12
  77. package/dist/analysis/store.d.ts +4 -4
  78. package/dist/analysis/store.js +13 -13
  79. package/dist/cli/commands/analysis-signals.d.ts +2 -1
  80. package/dist/cli/commands/analysis-signals.js +4 -1
  81. package/dist/cli/commands/analyze.js +4 -2
  82. package/dist/cli/commands/comms.js +8 -1
  83. package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
  84. package/dist/cli/commands/lab-route-computer-use.js +26 -14
  85. package/dist/cli/commands/lab-route-preview.d.ts +1 -3
  86. package/dist/cli/commands/lab-route-preview.js +3 -4
  87. package/dist/cli/commands/lab-route-run.d.ts +6 -4
  88. package/dist/cli/commands/lab-route-run.js +6 -2
  89. package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
  90. package/dist/cli/commands/lab-route-scripted.js +0 -1
  91. package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
  92. package/dist/cli/commands/lab-route-shared-world.js +0 -1
  93. package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
  94. package/dist/cli/commands/lab-route-terminal.js +0 -1
  95. package/dist/cli/commands/lab-run.js +76 -45
  96. package/dist/cli/commands/lab-scorer.d.ts +0 -2
  97. package/dist/cli/commands/lab.js +12 -6
  98. package/dist/cli/commands/observe.js +22 -0
  99. package/dist/cli/commands/run-signals.d.ts +30 -0
  100. package/dist/cli/commands/run-signals.js +146 -0
  101. package/dist/cli/commands/runs.js +10 -8
  102. package/dist/cli/commands/watch.js +12 -10
  103. package/dist/cli/doctor.d.ts +3 -0
  104. package/dist/cli/doctor.js +10 -2
  105. package/dist/cli/io.d.ts +5 -4
  106. package/dist/cli/io.js +12 -8
  107. package/dist/cli/program.js +3 -3
  108. package/dist/cli/renamed-options.d.ts +11 -0
  109. package/dist/cli/renamed-options.js +18 -0
  110. package/dist/cli/telemetry.d.ts +2 -2
  111. package/dist/cli/telemetry.js +1 -1
  112. package/dist/comms/capture-surface.d.ts +1 -1
  113. package/dist/comms/catch-host.d.ts +1 -1
  114. package/dist/comms/connections.js +4 -4
  115. package/dist/comms/external-evidence.d.ts +27 -0
  116. package/dist/comms/external-evidence.js +93 -0
  117. package/dist/comms/lease-store.js +7 -7
  118. package/dist/comms/types.js +1 -1
  119. package/dist/evidence/browser-hygiene.d.ts +1 -1
  120. package/dist/evidence/browser-hygiene.js +1 -1
  121. package/dist/evidence/redaction.js +1 -1
  122. package/dist/evidence/secret-scrub.d.ts +9 -0
  123. package/dist/evidence/secret-scrub.js +96 -0
  124. package/dist/feedback/draft.js +7 -9
  125. package/dist/feedback/export-bundle.js +4 -4
  126. package/dist/feedback/export.js +9 -9
  127. package/dist/feedback/feedback.d.ts +1 -1
  128. package/dist/index.d.ts +3 -6
  129. package/dist/index.js +3 -6
  130. package/dist/keys/key-resolution.d.ts +3 -1
  131. package/dist/keys/key-resolution.js +18 -16
  132. package/dist/lab/adapter-extension.d.ts +28 -6
  133. package/dist/lab/adapter-extension.js +65 -126
  134. package/dist/lab/adapter-scorer-loader.d.ts +25 -5
  135. package/dist/lab/adapter-scorer-loader.js +24 -0
  136. package/dist/lab/composition-rules.d.ts +2 -0
  137. package/dist/lab/composition-rules.js +35 -26
  138. package/dist/lab/config.js +28 -26
  139. package/dist/lab/device-presets.d.ts +2 -2
  140. package/dist/lab/discover.js +1 -3
  141. package/dist/lab/doctor.d.ts +44 -9
  142. package/dist/lab/doctor.js +149 -41
  143. package/dist/lab/init-plan.js +1 -3
  144. package/dist/lab/keys.js +1 -1
  145. package/dist/lab/lab-deps.d.ts +85 -0
  146. package/dist/lab/lab-deps.js +4 -0
  147. package/dist/lab/parse/actors.js +8 -7
  148. package/dist/lab/parse/comms.js +3 -2
  149. package/dist/lab/parse/execution.js +3 -2
  150. package/dist/lab/parse/subject-state.js +2 -1
  151. package/dist/lab/parse/subject.js +2 -1
  152. package/dist/lab/parse/values.d.ts +0 -1
  153. package/dist/lab/parse/values.js +0 -3
  154. package/dist/lab/persona-resolve.d.ts +3 -3
  155. package/dist/lab/persona-resolve.js +4 -4
  156. package/dist/lab/persona.js +1 -3
  157. package/dist/lab/plan-base.d.ts +6 -2
  158. package/dist/lab/plan-base.js +22 -7
  159. package/dist/lab/plan-participants.d.ts +5 -5
  160. package/dist/lab/plan-participants.js +2 -2
  161. package/dist/lab/plan-types.d.ts +33 -7
  162. package/dist/lab/plan.d.ts +3 -11
  163. package/dist/lab/plan.js +18 -42
  164. package/dist/lab/preflight-result.js +0 -2
  165. package/dist/lab/preflight.d.ts +0 -3
  166. package/dist/lab/preflight.js +1 -1
  167. package/dist/lab/requirements.d.ts +20 -0
  168. package/dist/lab/requirements.js +54 -0
  169. package/dist/lab/route-inputs.d.ts +23 -12
  170. package/dist/lab/route-inputs.js +48 -51
  171. package/dist/lab/routing.d.ts +19 -24
  172. package/dist/lab/routing.js +14 -47
  173. package/dist/lab/run-lab-events.d.ts +6 -11
  174. package/dist/lab/run-lab-events.js +3 -11
  175. package/dist/lab/run-lab-homes.d.ts +64 -0
  176. package/dist/lab/run-lab-homes.js +3 -0
  177. package/dist/lab/run-lab-options.d.ts +12 -66
  178. package/dist/lab/run-lab-options.js +45 -275
  179. package/dist/lab/summary.d.ts +9 -4
  180. package/dist/lab/summary.js +15 -8
  181. package/dist/lab/types.d.ts +132 -132
  182. package/dist/lab/validation.d.ts +15 -15
  183. package/dist/lab/validation.js +28 -28
  184. package/dist/lab/warnings.js +20 -19
  185. package/dist/observer/artifact.d.ts +1 -1
  186. package/dist/observer/artifact.js +3 -3
  187. package/dist/observer/data.js +2 -2
  188. package/dist/observer/render.js +2 -2
  189. package/dist/observer/run-routes.d.ts +1 -1
  190. package/dist/observer/run-routes.js +5 -5
  191. package/dist/observer/serve.d.ts +17 -0
  192. package/dist/observer/serve.js +34 -3
  193. package/dist/observer-app.html +1 -1
  194. package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
  195. package/dist/routes/computer-use/bundle-parts.js +10 -3
  196. package/dist/routes/computer-use/bundle.d.ts +4 -11
  197. package/dist/routes/computer-use/bundle.js +9 -15
  198. package/dist/routes/computer-use/diagnostics.d.ts +1 -1
  199. package/dist/routes/computer-use/diagnostics.js +1 -1
  200. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
  201. package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
  202. package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
  203. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
  204. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
  205. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
  206. package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
  207. package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
  208. package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
  209. package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
  210. package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
  211. package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
  212. package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
  213. package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
  214. package/dist/routes/computer-use/external-comms.d.ts +4 -4
  215. package/dist/routes/computer-use/external-comms.js +19 -43
  216. package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
  217. package/dist/routes/computer-use/fanout-bundle.js +25 -29
  218. package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
  219. package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
  220. package/dist/routes/computer-use/in-process-desktop.js +3 -9
  221. package/dist/routes/computer-use/live-flush.d.ts +7 -5
  222. package/dist/routes/computer-use/live-flush.js +19 -27
  223. package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +14 -13
  224. package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
  225. package/dist/routes/computer-use/local-tree-pack.js +4 -5
  226. package/dist/routes/computer-use/local-vm.d.ts +11 -8
  227. package/dist/routes/computer-use/local-vm.js +39 -66
  228. package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
  229. package/dist/routes/computer-use/participant-desktop.js +5 -25
  230. package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
  231. package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
  232. package/dist/routes/computer-use/participant-facts.d.ts +7 -1
  233. package/dist/routes/computer-use/participant-facts.js +12 -1
  234. package/dist/routes/computer-use/participant-model.d.ts +19 -11
  235. package/dist/routes/computer-use/participant-model.js +58 -33
  236. package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
  237. package/dist/routes/computer-use/participant-prompt.js +4 -4
  238. package/dist/routes/computer-use/participant-runs.d.ts +6 -6
  239. package/dist/routes/computer-use/participant-runs.js +8 -8
  240. package/dist/routes/computer-use/plan.d.ts +21 -29
  241. package/dist/routes/computer-use/plan.js +59 -65
  242. package/dist/routes/computer-use/preflight.d.ts +6 -11
  243. package/dist/routes/computer-use/preflight.js +26 -18
  244. package/dist/routes/computer-use/rerun-selection.js +10 -6
  245. package/dist/routes/computer-use/result.d.ts +1 -1
  246. package/dist/routes/computer-use/result.js +40 -30
  247. package/dist/routes/computer-use/route.d.ts +3 -4
  248. package/dist/routes/computer-use/route.js +21 -19
  249. package/dist/routes/computer-use/self-report.d.ts +2 -2
  250. package/dist/routes/computer-use/self-report.js +4 -4
  251. package/dist/routes/computer-use/setup.d.ts +8 -17
  252. package/dist/routes/computer-use/setup.js +98 -86
  253. package/dist/routes/computer-use/single-bundle.d.ts +8 -11
  254. package/dist/routes/computer-use/single-bundle.js +20 -25
  255. package/dist/routes/computer-use/subject-projection.d.ts +5 -7
  256. package/dist/routes/computer-use/subject-projection.js +20 -19
  257. package/dist/routes/computer-use/types.d.ts +169 -211
  258. package/dist/routes/computer-use/types.js +13 -6
  259. package/dist/routes/preview.js +0 -1
  260. package/dist/routes/scripted/bundle.d.ts +3 -6
  261. package/dist/routes/scripted/bundle.js +11 -16
  262. package/dist/routes/scripted/plan.d.ts +5 -7
  263. package/dist/routes/scripted/plan.js +6 -4
  264. package/dist/routes/scripted/result.d.ts +4 -1
  265. package/dist/routes/scripted/result.js +10 -6
  266. package/dist/routes/scripted/route.js +10 -11
  267. package/dist/routes/scripted/scenario.d.ts +1 -1
  268. package/dist/routes/scripted/scenario.js +1 -1
  269. package/dist/routes/scripted/setup.d.ts +3 -2
  270. package/dist/routes/scripted/setup.js +22 -21
  271. package/dist/routes/scripted/subject.d.ts +8 -3
  272. package/dist/routes/scripted/subject.js +11 -6
  273. package/dist/routes/scripted/surface-records.js +1 -1
  274. package/dist/routes/scripted/surface-sessions.d.ts +2 -2
  275. package/dist/routes/scripted/surface-sessions.js +4 -4
  276. package/dist/routes/scripted/types.d.ts +19 -36
  277. package/dist/routes/scripted/types.js +1 -2
  278. package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
  279. package/dist/routes/shared-world/bundle.d.ts +2 -2
  280. package/dist/routes/shared-world/bundle.js +22 -26
  281. package/dist/routes/shared-world/checkpoints.d.ts +4 -4
  282. package/dist/routes/shared-world/checkpoints.js +4 -4
  283. package/dist/routes/shared-world/comms.d.ts +5 -4
  284. package/dist/routes/shared-world/comms.js +28 -41
  285. package/dist/routes/shared-world/external-public.d.ts +5 -5
  286. package/dist/routes/shared-world/external-public.js +19 -20
  287. package/dist/routes/shared-world/handoff.d.ts +4 -4
  288. package/dist/routes/shared-world/handoff.js +50 -50
  289. package/dist/routes/shared-world/lobby-code.d.ts +5 -5
  290. package/dist/routes/shared-world/lobby-code.js +13 -13
  291. package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
  292. package/dist/routes/shared-world/{seats.js → participant-specs.js} +46 -51
  293. package/dist/routes/shared-world/plan.d.ts +2 -6
  294. package/dist/routes/shared-world/plan.js +1 -2
  295. package/dist/routes/shared-world/provenance.d.ts +4 -4
  296. package/dist/routes/shared-world/provenance.js +4 -4
  297. package/dist/routes/shared-world/provisioned.d.ts +3 -2
  298. package/dist/routes/shared-world/provisioned.js +48 -41
  299. package/dist/routes/shared-world/result.js +31 -19
  300. package/dist/routes/shared-world/route.js +37 -41
  301. package/dist/routes/shared-world/setup.d.ts +5 -4
  302. package/dist/routes/shared-world/setup.js +12 -14
  303. package/dist/routes/shared-world/types.d.ts +53 -126
  304. package/dist/routes/shared-world/types.js +2 -2
  305. package/dist/routes/terminal/adapter.d.ts +8 -8
  306. package/dist/routes/terminal/adapter.js +28 -125
  307. package/dist/routes/terminal/bundle.d.ts +7 -12
  308. package/dist/routes/terminal/bundle.js +24 -34
  309. package/dist/routes/terminal/credentials.d.ts +2 -2
  310. package/dist/routes/terminal/credentials.js +16 -16
  311. package/dist/routes/terminal/dry-run.d.ts +1 -1
  312. package/dist/routes/terminal/dry-run.js +9 -11
  313. package/dist/routes/terminal/encoding.d.ts +1 -1
  314. package/dist/routes/terminal/encoding.js +2 -2
  315. package/dist/routes/terminal/ledger.d.ts +6 -6
  316. package/dist/routes/terminal/ledger.js +9 -9
  317. package/dist/routes/terminal/live-finish.d.ts +1 -2
  318. package/dist/routes/terminal/live-finish.js +21 -20
  319. package/dist/routes/terminal/live-sandbox.d.ts +4 -2
  320. package/dist/routes/terminal/live-sandbox.js +25 -21
  321. package/dist/routes/terminal/participant-text.d.ts +23 -0
  322. package/dist/routes/terminal/participant-text.js +165 -0
  323. package/dist/routes/terminal/plan.d.ts +2 -6
  324. package/dist/routes/terminal/plan.js +13 -9
  325. package/dist/routes/terminal/recorder.d.ts +6 -1
  326. package/dist/routes/terminal/recorder.js +12 -4
  327. package/dist/routes/terminal/result.js +4 -4
  328. package/dist/routes/terminal/route.js +26 -26
  329. package/dist/routes/terminal/runtime.d.ts +3 -2
  330. package/dist/routes/terminal/runtime.js +3 -3
  331. package/dist/routes/terminal/sandbox.d.ts +5 -3
  332. package/dist/routes/terminal/sandbox.js +13 -16
  333. package/dist/routes/terminal/session.js +16 -14
  334. package/dist/routes/terminal/token-usage.js +5 -5
  335. package/dist/routes/terminal/trace.d.ts +5 -8
  336. package/dist/routes/terminal/trace.js +9 -64
  337. package/dist/routes/terminal/types.d.ts +85 -93
  338. package/dist/routes/terminal/types.js +9 -4
  339. package/dist/run/active-runs.d.ts +13 -0
  340. package/dist/run/active-runs.js +12 -0
  341. package/dist/run/bundle-shape.d.ts +2 -1
  342. package/dist/run/bundle-shape.js +4 -4
  343. package/dist/run/bundle.d.ts +63 -56
  344. package/dist/run/bundle.js +9 -8
  345. package/dist/run/cost-summary.js +3 -2
  346. package/dist/run/costs.d.ts +6 -6
  347. package/dist/run/costs.js +10 -10
  348. package/dist/run/detail.d.ts +5 -5
  349. package/dist/run/detail.js +6 -6
  350. package/dist/run/dry-run.js +5 -12
  351. package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
  352. package/dist/run/{study-files.js → evidence-files.js} +5 -5
  353. package/dist/run/feedback-shape.js +1 -1
  354. package/dist/run/judge.d.ts +16 -4
  355. package/dist/run/judge.js +24 -7
  356. package/dist/run/locate.d.ts +2 -0
  357. package/dist/run/locate.js +3 -1
  358. package/dist/run/outcomes.d.ts +3 -3
  359. package/dist/run/outcomes.js +3 -3
  360. package/dist/run/participant-records.d.ts +2 -2
  361. package/dist/run/participant-records.js +2 -2
  362. package/dist/run/paths.js +1 -1
  363. package/dist/run/pricing.d.ts +19 -9
  364. package/dist/run/pricing.js +30 -18
  365. package/dist/run/projection.d.ts +13 -13
  366. package/dist/run/projection.js +8 -8
  367. package/dist/run/reclaim.d.ts +7 -1
  368. package/dist/run/reclaim.js +24 -4
  369. package/dist/run/results.d.ts +1 -1
  370. package/dist/run/run-index.d.ts +1 -1
  371. package/dist/run/run-index.js +11 -11
  372. package/dist/run/run.d.ts +4 -2
  373. package/dist/run/run.js +9 -5
  374. package/dist/run/sandbox-receipts.d.ts +4 -4
  375. package/dist/run/sandbox-receipts.js +4 -4
  376. package/dist/run/shared-world-evidence.d.ts +47 -47
  377. package/dist/run/shared-world-shape.d.ts +3 -3
  378. package/dist/run/shared-world-shape.js +11 -11
  379. package/dist/run/stats.d.ts +5 -5
  380. package/dist/run/stats.js +8 -8
  381. package/dist/run/status.d.ts +16 -6
  382. package/dist/run/status.js +31 -8
  383. package/dist/run/streams.d.ts +26 -19
  384. package/dist/run/terminal-contract.d.ts +5 -5
  385. package/dist/run/terminal-contract.js +4 -4
  386. package/dist/run/transient-comms-secrets.d.ts +5 -0
  387. package/dist/run/transient-comms-secrets.js +12 -0
  388. package/dist/run-lab.d.ts +36 -34
  389. package/dist/run-lab.js +41 -37
  390. package/dist/subject/desktop-cli.d.ts +1 -1
  391. package/dist/subject/desktop-cli.js +1 -1
  392. package/dist/subject/local-tree-archive.d.ts +1 -1
  393. package/dist/subject/local-tree-archive.js +4 -4
  394. package/dist/subject/local-tree.d.ts +2 -2
  395. package/dist/subject/local-tree.js +1 -1
  396. package/dist/subject/node-bootstrap.d.ts +1 -1
  397. package/dist/subject/node-bootstrap.js +4 -4
  398. package/dist/subject/runtime.js +5 -5
  399. package/dist/subject/serve.js +1 -1
  400. package/dist/subject/steps.d.ts +4 -4
  401. package/dist/subject/steps.js +5 -5
  402. package/dist/substrates/desktop-session.d.ts +2 -0
  403. package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
  404. package/dist/substrates/e2b/cdp-probe.js +1 -1
  405. package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
  406. package/dist/substrates/e2b/desktop-browser.js +4 -4
  407. package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
  408. package/dist/substrates/e2b/desktop-cdp.js +4 -4
  409. package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
  410. package/dist/substrates/e2b/desktop-geometry.js +3 -3
  411. package/dist/substrates/e2b/desktop-media.js +2 -2
  412. package/dist/substrates/e2b/sandbox.d.ts +2 -0
  413. package/dist/substrates/e2b/sandbox.js +22 -8
  414. package/dist/substrates/e2b/sdk.d.ts +12 -1
  415. package/dist/substrates/e2b/sdk.js +30 -9
  416. package/dist/substrates/local/runtime-host.d.ts +2 -0
  417. package/dist/substrates/local/runtime-host.js +6 -0
  418. package/dist/tui/actions.d.ts +7 -5
  419. package/dist/tui/actions.js +18 -9
  420. package/dist/tui-app.js +42 -42
  421. package/dist/verify/actor.d.ts +10 -10
  422. package/dist/verify/actor.js +15 -15
  423. package/dist/verify/artifacts.d.ts +1 -1
  424. package/dist/verify/artifacts.js +3 -3
  425. package/dist/verify/costs.d.ts +2 -2
  426. package/dist/verify/costs.js +2 -2
  427. package/dist/verify/liveness.d.ts +1 -1
  428. package/dist/verify/liveness.js +4 -1
  429. package/dist/verify/rerun.d.ts +1 -1
  430. package/dist/verify/rerun.js +1 -1
  431. package/dist/verify/shared-world.js +2 -2
  432. package/dist/verify/verify.js +6 -6
  433. package/docs/README.md +1 -1
  434. package/docs/architecture/actor-contract.md +60 -22
  435. package/docs/architecture/desktop-sessions.md +9 -9
  436. package/docs/architecture/external-public-shared-world.md +5 -0
  437. package/docs/architecture/observer.md +4 -4
  438. package/docs/architecture/restricted-codex-analysis.md +40 -4
  439. package/docs/architecture/state-driven-executor.md +4 -5
  440. package/docs/architecture/task-protocol-support.md +3 -5
  441. package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
  442. package/docs/contracts/run-bundle.md +10 -8
  443. package/docs/contracts/schemas.md +109 -53
  444. package/docs/contracts/study-analysis.md +24 -0
  445. package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
  446. package/docs/product/automatic-analysis.md +1 -0
  447. package/docs/ramp/README.md +2 -1
  448. package/package.json +4 -4
  449. package/skills/humanish/SKILL.md +3 -2
  450. package/skills/humanish/agents/openai.yaml +1 -1
  451. package/dist/deprecated.d.ts +0 -90
  452. package/dist/deprecated.js +0 -106
  453. package/dist/lab/bag-overrides.d.ts +0 -18
  454. package/dist/lab/bag-overrides.js +0 -121
  455. package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
  456. package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
  457. /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
  458. /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
  459. /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
@@ -50,39 +50,72 @@ export function restrictedCodexNpmTarget(platform, arch) {
50
50
  /** Resolve PATH without running a shell. The npm launcher is resolved to its
51
51
  * native optional package so cleanup owns the real app-server child. */
52
52
  export async function resolveExecutable(options, env) {
53
- const platform = options.platform ?? process.platform, arch = options.arch ?? process.arch;
54
- let selected = options.executable;
55
- if (selected === undefined) {
56
- for (const directory of (env.PATH ?? "")
57
- .split(path.delimiter)
58
- .filter((entry) => path.isAbsolute(entry))) {
59
- const candidate = path.join(directory, "codex");
60
- try {
61
- await access(candidate, constants.X_OK);
62
- selected = candidate;
63
- break;
64
- }
65
- catch {
66
- /* Continue PATH. */
67
- }
53
+ const located = await locateExecutable(options, env);
54
+ // The stop carries only its code; doctor asks refusedCodexExecutable for the file and reason.
55
+ if ("refused" in located)
56
+ throw new RestrictedCodexStop("codex_unavailable");
57
+ return located.file;
58
+ }
59
+ /** The `codex` resolveExecutable turns down and why, or undefined when it finds one to run. */
60
+ export async function refusedCodexExecutable(env, options = {}) {
61
+ const located = await locateExecutable(options, env);
62
+ return "refused" in located ? located.refused : undefined;
63
+ }
64
+ /** The first executable `codex` on `PATH`, as resolveExecutable picks it. */
65
+ async function firstCodexOnPath(env) {
66
+ for (const directory of (env.PATH ?? "")
67
+ .split(path.delimiter)
68
+ .filter((entry) => path.isAbsolute(entry))) {
69
+ const candidate = path.join(directory, "codex");
70
+ try {
71
+ await access(candidate, constants.X_OK);
72
+ return candidate;
73
+ }
74
+ catch {
75
+ /* Continue PATH. */
68
76
  }
69
77
  }
70
- if (selected === undefined || !path.isAbsolute(selected))
71
- throw new RestrictedCodexStop("codex_unavailable");
78
+ return undefined;
79
+ }
80
+ /**
81
+ * The `codex` resolveExecutable picks from `PATH`, runnable or not, and the file it resolves to:
82
+ * what decides the command that replaces it. Undefined when `PATH` has none that resolves.
83
+ */
84
+ export async function foundCodexExecutable(env) {
85
+ const selected = await firstCodexOnPath(env);
86
+ if (selected === undefined)
87
+ return undefined;
88
+ try {
89
+ return { path: selected, resolved: await realpath(selected) };
90
+ }
91
+ catch {
92
+ return undefined;
93
+ }
94
+ }
95
+ async function locateExecutable(options, env) {
96
+ const platform = options.platform ?? process.platform, arch = options.arch ?? process.arch;
97
+ const selected = options.executable ?? (await firstCodexOnPath(env));
98
+ const refused = (reason, file) => ({
99
+ refused: { ...(file === undefined ? {} : { path: file }), reason },
100
+ });
101
+ if (selected === undefined)
102
+ return refused("no executable `codex` is on PATH");
103
+ if (!path.isAbsolute(selected))
104
+ return refused("it is not an absolute path", selected);
72
105
  let resolved;
73
106
  try {
74
107
  resolved = await realpath(selected);
75
108
  }
76
109
  catch {
77
- throw new RestrictedCodexStop("codex_unavailable");
110
+ return refused("it does not resolve to a file", selected);
78
111
  }
79
112
  if (await isNativeExecutable(resolved, platform))
80
- return resolved;
113
+ return { file: resolved };
81
114
  if (path.basename(resolved) === "codex.js" && path.basename(path.dirname(resolved)) === "bin") {
82
115
  const packageRoot = path.dirname(path.dirname(resolved));
83
116
  const target = restrictedCodexNpmTarget(platform, arch);
84
117
  if (!target)
85
- throw new RestrictedCodexStop("codex_unavailable");
118
+ return refused(`the npm package has no native build for ${platform}-${arch}`, resolved);
86
119
  const { triple, packageName: nativePackage } = target;
87
120
  const candidates = [];
88
121
  try {
@@ -97,10 +130,52 @@ export async function resolveExecutable(options, env) {
97
130
  candidates.push(path.join(packageRoot, "vendor", triple, "bin", "codex"));
98
131
  for (const candidate of candidates) {
99
132
  if (await isNativeExecutable(candidate, platform))
100
- return realpath(candidate);
133
+ return { file: await realpath(candidate) };
134
+ }
135
+ return refused(`the npm package's native ${nativePackage} build is missing`, resolved);
136
+ }
137
+ return refused("it is neither a native Codex executable nor the @openai/codex npm launcher", resolved);
138
+ }
139
+ /**
140
+ * Writes this release's app-server schema (`app-server generate-json-schema --experimental`) into
141
+ * `out`, for the protocol check. False when the release exits without one. Bounded like the
142
+ * version check: 15 seconds, and a few kilobytes of output, which it does not otherwise read.
143
+ */
144
+ export async function generateProtocolSchema(file, env, cwd, out, spawnFn, deadline) {
145
+ deadline.check();
146
+ const owned = ownCodexProcess(spawnFn(file, ["app-server", "generate-json-schema", "--experimental", "--out", out], {
147
+ cwd,
148
+ env,
149
+ detached: false,
150
+ stdio: ["pipe", "pipe", "pipe"],
151
+ }));
152
+ let bytes = 0, exitCode = null;
153
+ const timer = setTimeout(() => deadline.stop("timeout"), 15_000);
154
+ const count = (chunk) => {
155
+ bytes += chunk.length;
156
+ if (bytes > 65_536)
157
+ deadline.stop("response_too_large");
158
+ };
159
+ owned.child.on("error", () => deadline.stop("codex_unavailable"));
160
+ owned.child.stdin.on("error", () => deadline.stop("codex_unavailable"));
161
+ owned.child.stdout.on("data", count);
162
+ owned.child.stderr.on("data", count);
163
+ owned.child.on("exit", (code) => {
164
+ exitCode = code;
165
+ });
166
+ try {
167
+ owned.child.stdin.end();
168
+ await deadline.wait(owned.closed);
169
+ return exitCode === 0;
170
+ }
171
+ finally {
172
+ clearTimeout(timer);
173
+ if (!(await closeOwnedCodexProcess(owned))) {
174
+ retainUnclosedChild(owned.closed);
175
+ // oxlint-disable-next-line no-unsafe-finally -- a Codex process that did not close invalidates the check
176
+ throw new RestrictedCodexStop("codex_cleanup_failed");
101
177
  }
102
178
  }
103
- throw new RestrictedCodexStop("codex_unavailable");
104
179
  }
105
180
  /** Returns the detected release after checking it against the admitted list. */
106
181
  export async function checkVersion(file, env, cwd, spawnFn, deadline, admitted, expected) {
@@ -46,6 +46,12 @@ export interface LaunchState {
46
46
  resolvedModel: string | undefined;
47
47
  authentication: "chatgpt-account" | "api-key" | undefined;
48
48
  cliVersion: string | undefined;
49
+ /** Notification methods this humanish does not know that carried no item, by count. */
50
+ unknownNotifications: Map<string, number>;
51
+ /** How the release's schema differs from the fields humanish reads; set when that refuses. */
52
+ protocolIncompatibilities: string[] | undefined;
53
+ /** Schema values beyond the baseline, recorded at launch. */
54
+ protocolAdditions: string[] | undefined;
49
55
  }
50
56
  /** An admitted value, or the refusal a launch stops with. */
51
57
  export type Admission<T> = {
@@ -112,5 +118,5 @@ export declare function admitMcpStatus(reply: Record<string, unknown>): Admissio
112
118
  * The session's one-time launch: a private home, the auth link, the version check and the spawn,
113
119
  * then initialize, config, account, thread and MCP admission.
114
120
  */
115
- export declare function launchAdmittedAppServer(settings: LaunchSettings, state: LaunchState, request: RestrictedCodexRequest, deadline: RestrictedCodexDeadline, frameLimit: number, enter: (phase: CuaProviderFailurePhase) => void): Promise<RestrictedCodexTransport>;
121
+ export declare function launchAdmittedAppServer(settings: LaunchSettings, state: LaunchState, request: RestrictedCodexRequest, deadline: RestrictedCodexDeadline, frameLimit: number, enter: (phase: CuaProviderFailurePhase) => void, install: (transport: RestrictedCodexTransport) => void): Promise<RestrictedCodexTransport>;
116
122
  export {};
@@ -4,10 +4,12 @@
4
4
  // none of them touches the session. launchAdmittedAppServer sends the requests in order, stops on
5
5
  // the first refusal, and records each piece of state as soon as it exists so the session's
6
6
  // teardown (restricted-session.ts) cleans up a launch that fails partway.
7
- import { chmod, mkdir, mkdtemp, realpath, stat, symlink, writeFile } from "node:fs/promises";
7
+ import { chmod, mkdir, mkdtemp, realpath, rm, stat, symlink, writeFile } from "node:fs/promises";
8
8
  import { homedir, tmpdir } from "node:os";
9
9
  import path from "node:path";
10
- import { checkVersion, childEnvironment, resolveExecutable } from "./restricted-executable.js";
10
+ import { checkVersion, childEnvironment, generateProtocolSchema, resolveExecutable, } from "./restricted-executable.js";
11
+ import { checkProtocol, loadProtocolSchema } from "./protocol-compat.js";
12
+ import { protocolContract } from "./protocol-contract.js";
11
13
  import { admitsRestrictedCodexConfig, admitsRestrictedCodexThread, codexRecord, restrictedCodexConfig, } from "./restricted-policy.js";
12
14
  import { RestrictedCodexDeadline, RestrictedCodexStop, RestrictedCodexTransport, ownCodexProcess, } from "./restricted-transport.js";
13
15
  /** The admitted value; a refusal stops the launch. */
@@ -114,6 +116,37 @@ export function admitMcpStatus(reply) {
114
116
  return { refusal: "codex_unsafe_configuration" };
115
117
  return { value: undefined };
116
118
  }
119
+ /**
120
+ * The release's own app-server schema against the fields humanish reads and sends
121
+ * (protocol-contract.ts), generated into the private work directory on every launch. A change
122
+ * there refuses as codex_incompatible_release; a value beyond the baseline is recorded when the
123
+ * launch is admitted. Reading the schema waits on the deadline; a stop leaves the directory to
124
+ * the session's teardown, which removes the whole work directory.
125
+ */
126
+ async function admitProtocol(file, env, state, spawnFn, deadline, host) {
127
+ const directory = path.join(state.work, "schema");
128
+ const generated = await generateProtocolSchema(file, env, state.cwd, directory, spawnFn, deadline);
129
+ const schema = generated
130
+ ? await deadline.wait(loadProtocolSchema(directory).catch(() => undefined))
131
+ : undefined;
132
+ const result = schema === undefined
133
+ ? {
134
+ incompatibilities: [
135
+ generated
136
+ ? "its generated app-server schema could not be read"
137
+ : "it did not generate an app-server schema",
138
+ ],
139
+ additions: [],
140
+ }
141
+ : checkProtocol(schema, protocolContract(host));
142
+ await rm(directory, { recursive: true, force: true });
143
+ deadline.check();
144
+ if (result.incompatibilities.length > 0) {
145
+ state.protocolIncompatibilities = result.incompatibilities;
146
+ throw new RestrictedCodexStop("codex_incompatible_release");
147
+ }
148
+ state.protocolAdditions = result.additions;
149
+ }
117
150
  /** The host's Codex auth.json, which a private home links to instead of copying. */
118
151
  async function hostAuthFile(options, sourceEnv) {
119
152
  const authHome = options.authHome ?? sourceEnv.CODEX_HOME ?? path.join(sourceEnv.HOME ?? homedir(), ".codex");
@@ -133,7 +166,7 @@ async function hostAuthFile(options, sourceEnv) {
133
166
  * The session's one-time launch: a private home, the auth link, the version check and the spawn,
134
167
  * then initialize, config, account, thread and MCP admission.
135
168
  */
136
- export async function launchAdmittedAppServer(settings, state, request, deadline, frameLimit, enter) {
169
+ export async function launchAdmittedAppServer(settings, state, request, deadline, frameLimit, enter, install) {
137
170
  const { options, sourceEnv, participant, operatorAuth, reasoningEffort, spawnFn } = settings;
138
171
  const file = await resolveExecutable(options, sourceEnv);
139
172
  deadline.check();
@@ -147,6 +180,10 @@ export async function launchAdmittedAppServer(settings, state, request, deadline
147
180
  await mkdir(directory, { mode: 0o700 });
148
181
  const env = childEnvironment(sourceEnv, home, state.scratch);
149
182
  state.cliVersion = await checkVersion(file, env, state.cwd, spawnFn, deadline, settings.admittedVersions, options.cliVersion);
183
+ await admitProtocol(file, env, state, spawnFn, deadline, {
184
+ reasoningEffort,
185
+ platform: settings.platform,
186
+ });
150
187
  const configMode = {
151
188
  participantCodeMode: participant !== undefined,
152
189
  reasoningEffort,
@@ -173,6 +210,8 @@ export async function launchAdmittedAppServer(settings, state, request, deadline
173
210
  stdio: ["pipe", "pipe", "pipe"],
174
211
  }));
175
212
  const launched = new RestrictedCodexTransport(owned, deadline, frameLimit);
213
+ // The session's handlers check output from the first byte, before initialize returns.
214
+ install(launched);
176
215
  state.transport = launched;
177
216
  enter("initialize");
178
217
  const initialize = await launched.rpc("initialize", {
@@ -0,0 +1,101 @@
1
+ import { type RestrictedCodexAnalysisErrorCode } from "./restricted-policy.js";
2
+ import { type RestrictedCodexDeadline, type RestrictedCodexTransport } from "./restricted-transport.js";
3
+ /** Raw response item types an analyst turn may produce. */
4
+ export declare const ANALYST_RAW_ITEM_TYPES: readonly string[];
5
+ /** A participant also runs Code Mode: `exec` custom tool calls and `wait` function calls. */
6
+ export declare const PARTICIPANT_RAW_ITEM_TYPES: readonly string[];
7
+ /** Thread item types an analyst turn may produce. */
8
+ export declare const ANALYST_ITEM_TYPES: readonly string[];
9
+ /** A participant also has its one dynamic tool. */
10
+ export declare const PARTICIPANT_ITEM_TYPES: readonly string[];
11
+ /**
12
+ * Server notification methods in Codex CLI 0.160.0's app-server schema
13
+ * (`codex app-server generate-json-schema --experimental`, ServerNotification), plus two it sends
14
+ * outside that union: rawResponseItem/completed, and rawResponse/completed, whose v2 definition
15
+ * (RawResponseCompletedNotification) carries only a response id and usage.
16
+ */
17
+ export declare const KNOWN_CODEX_NOTIFICATIONS: ReadonlySet<string>;
18
+ /** What the item policy depends on: the session's role and, for a participant, its tool. */
19
+ export interface NotificationPolicy {
20
+ readonly participant: boolean;
21
+ /** The participant's tool name, read at each use; undefined for an analyst. */
22
+ toolName(): string | undefined;
23
+ }
24
+ /** The item policy for a session: a participant's tool name is read at each use. */
25
+ export declare function notificationPolicyOf(participant: {
26
+ readonly tool: {
27
+ readonly name: string;
28
+ };
29
+ } | undefined): NotificationPolicy;
30
+ /** Adds one notification of `method` to a session's unknown-method counts. */
31
+ export declare function countUnknownNotification(counts: Map<string, number>, method: string): void;
32
+ /**
33
+ * The items a notification carries, each with the method whose policy it takes, or null when one
34
+ * is malformed. 0.160.0's schema puts a ThreadItem in `params.item` (item/started,
35
+ * item/completed), `params.turn.items` (turn/started, turn/completed) and
36
+ * `params.thread.turns[].items` (thread/started). An `item` array and an `items` array are read
37
+ * too, for a release that adds them. A nested ThreadItem takes the item/completed policy.
38
+ */
39
+ export declare function notificationItems(method: string, params: Record<string, unknown>): {
40
+ method: string;
41
+ item: Record<string, unknown>;
42
+ }[] | null;
43
+ /**
44
+ * How a notification fares under the item policy: it carries no item, only allowed items, or a
45
+ * disallowed or malformed one.
46
+ */
47
+ export declare function itemPolicyOf(method: string, params: Record<string, unknown>, policy: NotificationPolicy): "none" | "allowed" | "violation";
48
+ /**
49
+ * True when an item breaks the item policy. rawResponseItem/completed, and an item of a raw type
50
+ * under any method other than item/started or item/completed, use the raw-item policy. Every
51
+ * other item uses the thread-item policy: an allowed type, the participant's one dynamic tool, and
52
+ * no agent message that delivers asynchronously or asks a question.
53
+ */
54
+ export declare function itemPolicyViolation(method: string, item: Record<string, unknown>, policy: NotificationPolicy): boolean;
55
+ /**
56
+ * The handler for notifications outside a dispatched turn: during the handshake, before
57
+ * turn/start, between requests and while closing. A disallowed or malformed item refuses; an
58
+ * unknown method without an item is counted; anything else is ignored, as there is no turn to
59
+ * apply it to.
60
+ */
61
+ export declare function idleNotificationHandler(policy: NotificationPolicy, recordUnknown: (method: string) => void, refuse: (code: RestrictedCodexAnalysisErrorCode) => void): (method: string, params: Record<string, unknown>) => void;
62
+ /** The run warning for unknown notification methods, or undefined when there were none. */
63
+ export declare function unknownNotificationsWarning(counts: Readonly<Record<string, number>> | undefined, cliVersion: string | undefined): string | undefined;
64
+ /** The run warning for a last frame cut off by humanish's own stop, or undefined when none was. */
65
+ export declare function truncatedFrameWarning(bytes: number | undefined): string | undefined;
66
+ /** The session fields its handlers outside a turn read and write (restricted-session). */
67
+ export interface NotificationSessionState {
68
+ readonly unknownNotifications: Map<string, number>;
69
+ /** The request in flight's deadline, or undefined between requests. */
70
+ readonly activeDeadline: RestrictedCodexDeadline | undefined;
71
+ readonly transport: RestrictedCodexTransport | undefined;
72
+ /**
73
+ * The first policy refusal or unchecked output in the session, whenever it happened and whether
74
+ * or not a request reported it: a caller that tolerates a request's failure (the debrief) must
75
+ * not absorb it.
76
+ */
77
+ policyRefusal: RestrictedCodexAnalysisErrorCode | undefined;
78
+ /** Bytes of last frames cut off after humanish stopped the app-server: a warning only. */
79
+ truncatedFrameBytes: number | undefined;
80
+ }
81
+ type Participant = {
82
+ readonly tool: {
83
+ readonly name: string;
84
+ };
85
+ } | undefined;
86
+ /**
87
+ * A policy refusal: it is recorded, the active request stops with `code`, pending RPCs are
88
+ * rejected, and between requests the next request fails with it.
89
+ */
90
+ export declare function refuseSession(state: NotificationSessionState, code: RestrictedCodexAnalysisErrorCode): void;
91
+ /** The session's handler for notifications outside a dispatched turn, on its current transport. */
92
+ export declare function idleNotifications(participant: Participant, state: NotificationSessionState): (method: string, params: Record<string, unknown>) => void;
93
+ /**
94
+ * Installs the session's handlers on a new transport, before its first request: notifications
95
+ * outside a turn, notifications once the transport stopped or is closing, and policy failures
96
+ * the transport finds itself.
97
+ */
98
+ export declare function installSessionHandlers(participant: Participant, state: NotificationSessionState, transport: RestrictedCodexTransport): void;
99
+ /** After a request: the turn's handlers come off the transport, and the idle handlers go on. */
100
+ export declare function detachTurn(participant: Participant, state: NotificationSessionState): void;
101
+ export {};
@@ -0,0 +1,277 @@
1
+ // The policy every app-server notification passes, whenever it arrives: during the launch
2
+ // handshake, before a turn is dispatched, during a turn, or between requests. A notification that
3
+ // carries an item is checked against the item policy whatever its method, so a new method cannot
4
+ // carry a native operation past it. A method this humanish does not know that carries no item is
5
+ // counted and reported, not refused, so a release's new progress events do not break a run.
6
+ import { codexRecord, toolPolicyViolation, } from "./restricted-policy.js";
7
+ import { RestrictedCodexStop, } from "./restricted-transport.js";
8
+ const rawCompactionTypes = ["compaction", "compaction_summary", "context_compaction"];
9
+ /** Raw response item types an analyst turn may produce. */
10
+ export const ANALYST_RAW_ITEM_TYPES = [
11
+ "message",
12
+ "reasoning",
13
+ ...rawCompactionTypes,
14
+ ];
15
+ /** A participant also runs Code Mode: `exec` custom tool calls and `wait` function calls. */
16
+ export const PARTICIPANT_RAW_ITEM_TYPES = [
17
+ ...ANALYST_RAW_ITEM_TYPES,
18
+ "custom_tool_call",
19
+ "custom_tool_call_output",
20
+ "function_call",
21
+ "function_call_output",
22
+ ];
23
+ /** Thread item types an analyst turn may produce. */
24
+ export const ANALYST_ITEM_TYPES = [
25
+ "userMessage",
26
+ "agentMessage",
27
+ "reasoning",
28
+ "contextCompaction",
29
+ ];
30
+ /** A participant also has its one dynamic tool. */
31
+ export const PARTICIPANT_ITEM_TYPES = [...ANALYST_ITEM_TYPES, "dynamicToolCall"];
32
+ /**
33
+ * Server notification methods in Codex CLI 0.160.0's app-server schema
34
+ * (`codex app-server generate-json-schema --experimental`, ServerNotification), plus two it sends
35
+ * outside that union: rawResponseItem/completed, and rawResponse/completed, whose v2 definition
36
+ * (RawResponseCompletedNotification) carries only a response id and usage.
37
+ */
38
+ export const KNOWN_CODEX_NOTIFICATIONS = new Set([
39
+ "account/gatewayOAuth/changed",
40
+ "account/login/completed",
41
+ "account/rateLimits/updated",
42
+ "account/updated",
43
+ "app/list/updated",
44
+ "autoApprovalReview/strictReviewRequired",
45
+ "command/exec/outputDelta",
46
+ "configWarning",
47
+ "deprecationNotice",
48
+ "error",
49
+ "externalAgentConfig/import/completed",
50
+ "externalAgentConfig/import/progress",
51
+ "fs/changed",
52
+ "fuzzyFileSearch/sessionCompleted",
53
+ "fuzzyFileSearch/sessionUpdated",
54
+ "guardianWarning",
55
+ "hook/completed",
56
+ "hook/started",
57
+ "item/agentMessage/delta",
58
+ "item/autoApprovalReview/completed",
59
+ "item/autoApprovalReview/started",
60
+ "item/commandExecution/outputDelta",
61
+ "item/commandExecution/terminalInteraction",
62
+ "item/completed",
63
+ "item/fileChange/outputDelta",
64
+ "item/fileChange/patchUpdated",
65
+ "item/mcpToolCall/progress",
66
+ "item/plan/delta",
67
+ "item/reasoning/summaryPartAdded",
68
+ "item/reasoning/summaryTextDelta",
69
+ "item/reasoning/textDelta",
70
+ "item/started",
71
+ "mcpServer/event/stream/notification",
72
+ "mcpServer/oauthLogin/completed",
73
+ "mcpServer/startupStatus/updated",
74
+ "model/rerouted",
75
+ "model/safetyBuffering/updated",
76
+ "model/verification",
77
+ "modelProvider/authRecoveryCompleted",
78
+ "modelProvider/authRecoveryStarted",
79
+ "process/exited",
80
+ "process/outputDelta",
81
+ "project/changed",
82
+ "rawResponse/completed",
83
+ "rawResponseItem/completed",
84
+ "remoteControl/status/changed",
85
+ "serverRequest/resolved",
86
+ "skills/changed",
87
+ "thread/archived",
88
+ "thread/attachment/updated",
89
+ "thread/closed",
90
+ "thread/compacted",
91
+ "thread/deleted",
92
+ "thread/environment/connected",
93
+ "thread/environment/disconnected",
94
+ "thread/goal/cleared",
95
+ "thread/goal/updated",
96
+ "thread/name/updated",
97
+ "thread/project/updated",
98
+ "thread/queue/changed",
99
+ "thread/realtime/closed",
100
+ "thread/realtime/error",
101
+ "thread/realtime/item/completed",
102
+ "thread/realtime/item/started",
103
+ "thread/realtime/item/transcript/delta",
104
+ "thread/realtime/itemAdded",
105
+ "thread/realtime/outputAudio/delta",
106
+ "thread/realtime/sdp",
107
+ "thread/realtime/started",
108
+ "thread/realtime/transcript/delta",
109
+ "thread/realtime/transcript/done",
110
+ "thread/reverted",
111
+ "thread/settings/updated",
112
+ "thread/started",
113
+ "thread/status/changed",
114
+ "thread/tokenUsage/updated",
115
+ "thread/unarchived",
116
+ "turn/completed",
117
+ "turn/diff/updated",
118
+ "turn/moderationMetadata",
119
+ "turn/plan/updated",
120
+ "turn/started",
121
+ "warning",
122
+ "windows/worldWritableWarning",
123
+ "windowsSandbox/setupCompleted",
124
+ ]);
125
+ /** The item policy for a session: a participant's tool name is read at each use. */
126
+ export function notificationPolicyOf(participant) {
127
+ return { participant: participant !== undefined, toolName: () => participant?.tool.name };
128
+ }
129
+ /** Adds one notification of `method` to a session's unknown-method counts. */
130
+ export function countUnknownNotification(counts, method) {
131
+ counts.set(method, (counts.get(method) ?? 0) + 1);
132
+ }
133
+ const isItem = (value) => value !== null &&
134
+ typeof value === "object" &&
135
+ !Array.isArray(value) &&
136
+ typeof value.type === "string";
137
+ /**
138
+ * The items a notification carries, each with the method whose policy it takes, or null when one
139
+ * is malformed. 0.160.0's schema puts a ThreadItem in `params.item` (item/started,
140
+ * item/completed), `params.turn.items` (turn/started, turn/completed) and
141
+ * `params.thread.turns[].items` (thread/started). An `item` array and an `items` array are read
142
+ * too, for a release that adds them. A nested ThreadItem takes the item/completed policy.
143
+ */
144
+ export function notificationItems(method, params) {
145
+ const found = [];
146
+ let malformed = false;
147
+ const add = (value, itemMethod) => {
148
+ if (isItem(value))
149
+ found.push({ method: itemMethod, item: value });
150
+ else
151
+ malformed = true;
152
+ };
153
+ const addAll = (value, itemMethod) => {
154
+ if (Array.isArray(value))
155
+ for (const item of value)
156
+ add(item, itemMethod);
157
+ };
158
+ if (Array.isArray(params.item))
159
+ addAll(params.item, method);
160
+ else if (params.item !== undefined && params.item !== null)
161
+ add(params.item, method);
162
+ addAll(params.items, method);
163
+ addAll(codexRecord(params.turn).items, "item/completed");
164
+ const turns = codexRecord(params.thread).turns;
165
+ if (Array.isArray(turns))
166
+ for (const turn of turns)
167
+ addAll(codexRecord(turn).items, "item/completed");
168
+ return malformed ? null : found;
169
+ }
170
+ /**
171
+ * How a notification fares under the item policy: it carries no item, only allowed items, or a
172
+ * disallowed or malformed one.
173
+ */
174
+ export function itemPolicyOf(method, params, policy) {
175
+ const found = notificationItems(method, params);
176
+ if (found === null)
177
+ return "violation";
178
+ if (found.length === 0)
179
+ return "none";
180
+ return found.some((entry) => itemPolicyViolation(entry.method, entry.item, policy))
181
+ ? "violation"
182
+ : "allowed";
183
+ }
184
+ /**
185
+ * True when an item breaks the item policy. rawResponseItem/completed, and an item of a raw type
186
+ * under any method other than item/started or item/completed, use the raw-item policy. Every
187
+ * other item uses the thread-item policy: an allowed type, the participant's one dynamic tool, and
188
+ * no agent message that delivers asynchronously or asks a question.
189
+ */
190
+ export function itemPolicyViolation(method, item, policy) {
191
+ const rawTypes = policy.participant ? PARTICIPANT_RAW_ITEM_TYPES : ANALYST_RAW_ITEM_TYPES;
192
+ const threadItemMethod = method === "item/started" || method === "item/completed";
193
+ const type = String(item.type);
194
+ if (method === "rawResponseItem/completed" || (!threadItemMethod && rawTypes.includes(type)))
195
+ return toolPolicyViolation("rawResponseItem/completed", item, rawTypes);
196
+ const itemTypes = policy.participant ? PARTICIPANT_ITEM_TYPES : ANALYST_ITEM_TYPES;
197
+ if (!itemTypes.includes(type))
198
+ return true;
199
+ if (type === "dynamicToolCall" && (item.tool !== policy.toolName() || item.namespace !== null))
200
+ return true;
201
+ return toolPolicyViolation("item/completed", item, rawTypes);
202
+ }
203
+ /**
204
+ * The handler for notifications outside a dispatched turn: during the handshake, before
205
+ * turn/start, between requests and while closing. A disallowed or malformed item refuses; an
206
+ * unknown method without an item is counted; anything else is ignored, as there is no turn to
207
+ * apply it to.
208
+ */
209
+ export function idleNotificationHandler(policy, recordUnknown, refuse) {
210
+ return (method, params) => {
211
+ const items = itemPolicyOf(method, params, policy);
212
+ if (items === "violation")
213
+ refuse("codex_tool_call");
214
+ else if (items === "none" && !KNOWN_CODEX_NOTIFICATIONS.has(method))
215
+ recordUnknown(method);
216
+ };
217
+ }
218
+ /** The run warning for unknown notification methods, or undefined when there were none. */
219
+ export function unknownNotificationsWarning(counts, cliVersion) {
220
+ const entries = Object.entries(counts ?? {}).sort(([a], [b]) => a.localeCompare(b));
221
+ if (entries.length === 0)
222
+ return undefined;
223
+ const list = entries.map(([method, count]) => `${method} ×${count}`).join(", ");
224
+ return `Codex CLI${cliVersion === undefined ? "" : ` ${cliVersion}`} sent notification methods humanish does not know: ${list}. They carried no item and were ignored.`;
225
+ }
226
+ /** The run warning for a last frame cut off by humanish's own stop, or undefined when none was. */
227
+ export function truncatedFrameWarning(bytes) {
228
+ return bytes === undefined
229
+ ? undefined
230
+ : `Codex output was cut off when humanish stopped the app-server: ${bytes} bytes of an unfinished last frame were not checked.`;
231
+ }
232
+ /**
233
+ * A policy refusal: it is recorded, the active request stops with `code`, pending RPCs are
234
+ * rejected, and between requests the next request fails with it.
235
+ */
236
+ export function refuseSession(state, code) {
237
+ state.policyRefusal ??= code;
238
+ state.activeDeadline?.stop(code);
239
+ state.transport?.refuse(code);
240
+ }
241
+ /** The session's handler for notifications outside a dispatched turn, on its current transport. */
242
+ export function idleNotifications(participant, state) {
243
+ return idleNotificationHandler(notificationPolicyOf(participant), (method) => countUnknownNotification(state.unknownNotifications, method), (code) => refuseSession(state, code));
244
+ }
245
+ /**
246
+ * Installs the session's handlers on a new transport, before its first request: notifications
247
+ * outside a turn, notifications once the transport stopped or is closing, and policy failures
248
+ * the transport finds itself.
249
+ */
250
+ export function installSessionHandlers(participant, state, transport) {
251
+ transport.onNotification = idleNotifications(participant, state);
252
+ transport.onPolicyOnlyNotification = idleNotificationHandler(notificationPolicyOf(participant), (method) => countUnknownNotification(state.unknownNotifications, method), (code) => {
253
+ state.policyRefusal ??= code;
254
+ });
255
+ transport.onPolicyFailure = (code) => {
256
+ state.policyRefusal ??= code;
257
+ };
258
+ transport.onTruncatedFrame = (bytes) => {
259
+ state.truncatedFrameBytes = (state.truncatedFrameBytes ?? 0) + bytes;
260
+ };
261
+ }
262
+ /** A server request outside a turn is refused; the transport answers it and stops the request. */
263
+ function idleRequests(state) {
264
+ return async () => {
265
+ state.policyRefusal ??= "codex_tool_call";
266
+ throw new RestrictedCodexStop("codex_tool_call");
267
+ };
268
+ }
269
+ /** After a request: the turn's handlers come off the transport, and the idle handlers go on. */
270
+ export function detachTurn(participant, state) {
271
+ const transport = state.transport;
272
+ if (!transport)
273
+ return;
274
+ transport.onNotification = idleNotifications(participant, state);
275
+ transport.onRequest = idleRequests(state);
276
+ transport.onRequestComplete = undefined;
277
+ }