humanish 0.107.0 → 0.108.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 (521) hide show
  1. package/ARCHITECTURE.md +22 -17
  2. package/CHANGELOG.md +14 -0
  3. package/CONTEXT.md +51 -44
  4. package/README.md +145 -172
  5. package/SECURITY.md +16 -26
  6. package/TELEMETRY.md +8 -6
  7. package/dist/actors/affordance.d.ts +4 -4
  8. package/dist/actors/affordance.js +12 -12
  9. package/dist/actors/agent-session.d.ts +2 -2
  10. package/dist/actors/agent-session.js +7 -7
  11. package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
  12. package/dist/actors/codex/app-server-actor-trace.js +1 -1
  13. package/dist/actors/codex/app-server-ui.js +1 -1
  14. package/dist/actors/codex/codex-admission.d.ts +91 -0
  15. package/dist/actors/codex/codex-admission.js +150 -0
  16. package/dist/actors/codex/restricted-executable.d.ts +4 -4
  17. package/dist/actors/codex/restricted-executable.js +8 -8
  18. package/dist/actors/codex/restricted-launch.d.ts +2 -1
  19. package/dist/actors/codex/restricted-launch.js +1 -1
  20. package/dist/actors/codex/restricted-participant.js +8 -6
  21. package/dist/actors/codex/restricted-policy.d.ts +2 -2
  22. package/dist/actors/codex/restricted-policy.js +2 -2
  23. package/dist/actors/codex/restricted-session.d.ts +2 -2
  24. package/dist/actors/codex/restricted-session.js +10 -5
  25. package/dist/actors/computer-use/actor.d.ts +16 -16
  26. package/dist/actors/computer-use/actor.js +2 -2
  27. package/dist/actors/computer-use/admission-limit.d.ts +1 -1
  28. package/dist/actors/computer-use/admission-limit.js +1 -1
  29. package/dist/actors/computer-use/loop/actions.d.ts +3 -3
  30. package/dist/actors/computer-use/loop/actions.js +10 -10
  31. package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
  32. package/dist/actors/computer-use/loop/backstop.js +14 -12
  33. package/dist/actors/computer-use/loop/ending.d.ts +5 -5
  34. package/dist/actors/computer-use/loop/ending.js +7 -7
  35. package/dist/actors/computer-use/loop/observation.d.ts +2 -2
  36. package/dist/actors/computer-use/loop/observation.js +9 -9
  37. package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
  38. package/dist/actors/computer-use/loop/provider-call.js +1 -1
  39. package/dist/actors/computer-use/loop/session.js +3 -3
  40. package/dist/actors/computer-use/loop/spend.d.ts +1 -1
  41. package/dist/actors/computer-use/loop/spend.js +1 -1
  42. package/dist/actors/computer-use/loop/trace.js +9 -8
  43. package/dist/actors/computer-use/loop/types.d.ts +25 -23
  44. package/dist/actors/computer-use/loop/usage.js +2 -2
  45. package/dist/actors/computer-use/openai-context.d.ts +37 -0
  46. package/dist/actors/computer-use/openai-context.js +214 -0
  47. package/dist/actors/computer-use/openai-provider.d.ts +11 -8
  48. package/dist/actors/computer-use/openai-provider.js +45 -34
  49. package/dist/actors/computer-use/openai-requests.d.ts +36 -10
  50. package/dist/actors/computer-use/openai-requests.js +82 -15
  51. package/dist/actors/computer-use/openai-wire.d.ts +19 -7
  52. package/dist/actors/computer-use/openai-wire.js +36 -34
  53. package/dist/actors/contract.d.ts +78 -43
  54. package/dist/actors/contract.js +29 -23
  55. package/dist/actors/local-agent/claude-session.d.ts +1 -1
  56. package/dist/actors/local-agent/claude-session.js +10 -9
  57. package/dist/actors/local-agent/cli.d.ts +8 -6
  58. package/dist/actors/local-agent/cli.js +24 -28
  59. package/dist/actors/local-agent/readiness.d.ts +2 -2
  60. package/dist/actors/local-agent/readiness.js +4 -4
  61. package/dist/actors/reasoning-effort.js +6 -6
  62. package/dist/actors/registry.d.ts +10 -10
  63. package/dist/actors/registry.js +18 -17
  64. package/dist/actors/scripted-browser/actor.d.ts +8 -8
  65. package/dist/actors/scripted-browser/actor.js +16 -16
  66. package/dist/actors/scripted-browser/browser-command.js +1 -1
  67. package/dist/actors/scripted-browser/steps.js +1 -1
  68. package/dist/actors/scripted-browser/types.d.ts +1 -1
  69. package/dist/actors/stop-conditions.d.ts +1 -1
  70. package/dist/analysis/codex-config.d.ts +6 -2
  71. package/dist/analysis/codex-config.js +22 -14
  72. package/dist/analysis/service.js +5 -5
  73. package/dist/cli/commands/analyze.js +19 -16
  74. package/dist/cli/commands/codex.js +9 -9
  75. package/dist/cli/commands/comms.js +54 -33
  76. package/dist/cli/commands/feedback.js +20 -21
  77. package/dist/cli/commands/lab-format.d.ts +5 -4
  78. package/dist/cli/commands/lab-format.js +35 -23
  79. package/dist/cli/commands/lab-route-computer-use.js +6 -7
  80. package/dist/cli/commands/lab-route-preview.js +4 -3
  81. package/dist/cli/commands/lab-route-shared-world.js +3 -3
  82. package/dist/cli/commands/lab-run.js +10 -11
  83. package/dist/cli/commands/lab-scorer.d.ts +2 -2
  84. package/dist/cli/commands/lab-scorer.js +1 -1
  85. package/dist/cli/commands/migrate.d.ts +4 -0
  86. package/dist/cli/commands/migrate.js +65 -0
  87. package/dist/cli/commands/observe.js +147 -108
  88. package/dist/cli/commands/run-command.d.ts +10 -0
  89. package/dist/cli/commands/run-command.js +85 -0
  90. package/dist/cli/commands/runs.js +137 -138
  91. package/dist/cli/commands/setup.d.ts +2 -2
  92. package/dist/cli/commands/setup.js +26 -21
  93. package/dist/cli/commands/study.d.ts +3 -0
  94. package/dist/cli/commands/study.js +182 -0
  95. package/dist/cli/commands/tui.d.ts +4 -4
  96. package/dist/cli/commands/tui.js +21 -21
  97. package/dist/cli/commands/watch.js +60 -75
  98. package/dist/cli/deprecations.d.ts +18 -0
  99. package/dist/cli/deprecations.js +48 -0
  100. package/dist/cli/doctor.d.ts +15 -5
  101. package/dist/cli/doctor.js +103 -48
  102. package/dist/cli/first-run-path.d.ts +12 -10
  103. package/dist/cli/first-run-path.js +30 -28
  104. package/dist/cli/io.d.ts +41 -6
  105. package/dist/cli/io.js +97 -22
  106. package/dist/cli/observer-follow.d.ts +2 -2
  107. package/dist/cli/observer-follow.js +5 -6
  108. package/dist/cli/orientation.d.ts +6 -3
  109. package/dist/cli/orientation.js +43 -39
  110. package/dist/cli/product-sentence.d.ts +6 -0
  111. package/dist/cli/product-sentence.js +6 -0
  112. package/dist/cli/program.d.ts +6 -1
  113. package/dist/cli/program.js +109 -40
  114. package/dist/cli/telemetry.d.ts +15 -15
  115. package/dist/cli/telemetry.js +48 -40
  116. package/dist/cli.js +1 -1
  117. package/dist/comms/capture-surface.d.ts +13 -12
  118. package/dist/comms/capture-surface.js +23 -22
  119. package/dist/comms/catch-host.d.ts +7 -7
  120. package/dist/comms/catch-host.js +14 -14
  121. package/dist/comms/email-catch.d.ts +3 -3
  122. package/dist/comms/email-catch.js +8 -8
  123. package/dist/comms/external-evidence.js +2 -2
  124. package/dist/comms/extract.js +2 -2
  125. package/dist/comms/fake-inbox.d.ts +2 -2
  126. package/dist/comms/fake-inbox.js +2 -2
  127. package/dist/comms/receiving-render.d.ts +1 -1
  128. package/dist/comms/receiving-render.js +2 -2
  129. package/dist/comms/sandbox-catch-script.d.ts +6 -6
  130. package/dist/comms/sandbox-catch-script.js +6 -6
  131. package/dist/comms/sandbox-catch.d.ts +36 -37
  132. package/dist/comms/sandbox-catch.js +34 -35
  133. package/dist/comms/setup.js +42 -8
  134. package/dist/comms/thread-evidence.d.ts +1 -1
  135. package/dist/comms/thread-evidence.js +6 -6
  136. package/dist/comms/types.d.ts +6 -6
  137. package/dist/comms/types.js +3 -3
  138. package/dist/evidence/frame-signature.d.ts +1 -1
  139. package/dist/evidence/frame-signature.js +4 -4
  140. package/dist/evidence/redaction.d.ts +3 -3
  141. package/dist/evidence/redaction.js +4 -4
  142. package/dist/feedback/draft.js +36 -78
  143. package/dist/feedback/export-bundle.js +1 -1
  144. package/dist/feedback/export.d.ts +5 -1
  145. package/dist/feedback/export.js +7 -8
  146. package/dist/feedback/feedback.d.ts +2 -2
  147. package/dist/feedback/feedback.js +21 -3
  148. package/dist/guest/chromium-text.js +2 -2
  149. package/dist/guest/desktop-native.d.ts +1 -1
  150. package/dist/guest/runtime.js +1 -1
  151. package/dist/index.d.ts +12 -10
  152. package/dist/index.js +8 -6
  153. package/dist/keys/key-resolution.d.ts +5 -5
  154. package/dist/keys/key-resolution.js +23 -23
  155. package/dist/lab/adapter-extension.d.ts +7 -7
  156. package/dist/lab/adapter-extension.js +13 -36
  157. package/dist/lab/adapter-scorer-loader.d.ts +7 -7
  158. package/dist/lab/adapter-scorer-loader.js +32 -32
  159. package/dist/lab/composition-rules.js +42 -42
  160. package/dist/lab/config.js +65 -25
  161. package/dist/lab/deprecated-fields.d.ts +10 -0
  162. package/dist/lab/deprecated-fields.js +24 -0
  163. package/dist/lab/device-presets.d.ts +8 -8
  164. package/dist/lab/device-presets.js +11 -11
  165. package/dist/lab/discover.d.ts +13 -9
  166. package/dist/lab/discover.js +117 -57
  167. package/dist/lab/doctor.d.ts +10 -3
  168. package/dist/lab/doctor.js +47 -9
  169. package/dist/lab/init-templates.js +147 -147
  170. package/dist/lab/init.d.ts +1 -1
  171. package/dist/lab/init.js +41 -9
  172. package/dist/lab/keys.d.ts +2 -0
  173. package/dist/lab/keys.js +42 -8
  174. package/dist/lab/lab-deps.d.ts +7 -12
  175. package/dist/lab/parse/actors.js +9 -9
  176. package/dist/lab/parse/comms.js +5 -5
  177. package/dist/lab/parse/execution.js +13 -13
  178. package/dist/lab/parse/study-v3.d.ts +23 -0
  179. package/dist/lab/parse/study-v3.js +259 -0
  180. package/dist/lab/parse/subject-state.d.ts +7 -7
  181. package/dist/lab/parse/subject-state.js +16 -16
  182. package/dist/lab/parse/subject.js +28 -28
  183. package/dist/lab/parse/values.d.ts +1 -1
  184. package/dist/lab/parse/values.js +3 -3
  185. package/dist/lab/persona-resolve.d.ts +4 -4
  186. package/dist/lab/persona-resolve.js +4 -4
  187. package/dist/lab/plan-participants.d.ts +2 -2
  188. package/dist/lab/plan-types.d.ts +4 -4
  189. package/dist/lab/plan.d.ts +1 -7
  190. package/dist/lab/plan.js +10 -41
  191. package/dist/lab/preflight-probes.js +11 -11
  192. package/dist/lab/preflight-result.d.ts +2 -1
  193. package/dist/lab/preflight-result.js +5 -4
  194. package/dist/lab/preflight.d.ts +7 -5
  195. package/dist/lab/preflight.js +5 -5
  196. package/dist/lab/routing.d.ts +31 -25
  197. package/dist/lab/routing.js +60 -29
  198. package/dist/lab/run-lab-events.d.ts +0 -3
  199. package/dist/lab/run-lab-events.js +0 -6
  200. package/dist/lab/run-lab-homes.d.ts +22 -10
  201. package/dist/lab/run-lab-homes.js +5 -1
  202. package/dist/lab/run-lab-options.d.ts +1 -1
  203. package/dist/lab/run-lab-options.js +16 -13
  204. package/dist/lab/summary.d.ts +7 -6
  205. package/dist/lab/summary.js +10 -10
  206. package/dist/lab/tasks.d.ts +15 -15
  207. package/dist/lab/tasks.js +14 -14
  208. package/dist/lab/types.d.ts +101 -95
  209. package/dist/lab/types.js +2 -0
  210. package/dist/lab/validation.d.ts +13 -13
  211. package/dist/lab/validation.js +44 -42
  212. package/dist/lab/warnings.d.ts +10 -0
  213. package/dist/lab/warnings.js +61 -33
  214. package/dist/library-aliases.d.ts +56 -0
  215. package/dist/library-aliases.js +22 -0
  216. package/dist/observer/artifact.d.ts +1 -1
  217. package/dist/observer/artifact.js +6 -6
  218. package/dist/observer/data.d.ts +6 -6
  219. package/dist/observer/data.js +5 -4
  220. package/dist/observer/exposure.d.ts +1 -1
  221. package/dist/observer/exposure.js +11 -11
  222. package/dist/observer/http.js +1 -1
  223. package/dist/observer/library.d.ts +1 -1
  224. package/dist/observer/library.js +4 -2
  225. package/dist/observer/listen.js +5 -4
  226. package/dist/observer/render.d.ts +1 -1
  227. package/dist/observer/render.js +10 -5
  228. package/dist/observer/run-routes.d.ts +3 -3
  229. package/dist/observer/run-routes.js +1 -1
  230. package/dist/observer/serve.js +7 -3
  231. package/dist/observer/tunnel.js +1 -1
  232. package/dist/observer-app.html +4 -4
  233. package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
  234. package/dist/routes/computer-use/bundle-parts.js +15 -15
  235. package/dist/routes/computer-use/bundle.js +3 -3
  236. package/dist/routes/computer-use/e2b-desktop/comms.d.ts +1 -1
  237. package/dist/routes/computer-use/e2b-desktop/comms.js +14 -14
  238. package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
  239. package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +4 -3
  240. package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
  241. package/dist/routes/computer-use/e2b-desktop/prepare.js +7 -7
  242. package/dist/routes/computer-use/e2b-desktop/start.js +9 -8
  243. package/dist/routes/computer-use/e2b-desktop/teardown.js +5 -4
  244. package/dist/routes/computer-use/external-comms.d.ts +1 -1
  245. package/dist/routes/computer-use/external-comms.js +1 -1
  246. package/dist/routes/computer-use/fanout-bundle.js +18 -18
  247. package/dist/routes/computer-use/fanout-records.js +10 -11
  248. package/dist/routes/computer-use/live-flush.d.ts +1 -1
  249. package/dist/routes/computer-use/live-flush.js +6 -6
  250. package/dist/routes/computer-use/live-phase.d.ts +4 -2
  251. package/dist/routes/computer-use/live-phase.js +6 -6
  252. package/dist/routes/computer-use/local-vm.js +1 -1
  253. package/dist/routes/computer-use/participant-desktop.d.ts +4 -4
  254. package/dist/routes/computer-use/participant-desktop.js +4 -4
  255. package/dist/routes/computer-use/participant-execution.d.ts +4 -4
  256. package/dist/routes/computer-use/participant-execution.js +9 -9
  257. package/dist/routes/computer-use/participant-model.d.ts +6 -0
  258. package/dist/routes/computer-use/participant-model.js +31 -13
  259. package/dist/routes/computer-use/participant-prompt.d.ts +11 -11
  260. package/dist/routes/computer-use/participant-prompt.js +6 -6
  261. package/dist/routes/computer-use/participant-runs.d.ts +7 -7
  262. package/dist/routes/computer-use/participant-runs.js +13 -13
  263. package/dist/routes/computer-use/plan.js +22 -22
  264. package/dist/routes/computer-use/preflight.js +21 -21
  265. package/dist/routes/computer-use/rerun-selection.js +1 -1
  266. package/dist/routes/computer-use/result.js +11 -11
  267. package/dist/routes/computer-use/route.d.ts +2 -1
  268. package/dist/routes/computer-use/route.js +15 -14
  269. package/dist/routes/computer-use/self-report.d.ts +7 -7
  270. package/dist/routes/computer-use/self-report.js +31 -31
  271. package/dist/routes/computer-use/setup.d.ts +1 -1
  272. package/dist/routes/computer-use/setup.js +17 -18
  273. package/dist/routes/computer-use/single-bundle.d.ts +7 -7
  274. package/dist/routes/computer-use/single-bundle.js +28 -30
  275. package/dist/routes/computer-use/subject-projection.d.ts +1 -1
  276. package/dist/routes/computer-use/subject-projection.js +6 -6
  277. package/dist/routes/computer-use/types.d.ts +40 -42
  278. package/dist/routes/computer-use/types.js +10 -10
  279. package/dist/routes/preview.d.ts +8 -2
  280. package/dist/routes/preview.js +8 -4
  281. package/dist/routes/scripted/bundle.d.ts +2 -2
  282. package/dist/routes/scripted/bundle.js +13 -12
  283. package/dist/routes/scripted/plan.d.ts +1 -1
  284. package/dist/routes/scripted/plan.js +9 -9
  285. package/dist/routes/scripted/result.js +5 -5
  286. package/dist/routes/scripted/route.js +5 -6
  287. package/dist/routes/scripted/scenario.js +2 -2
  288. package/dist/routes/scripted/setup.js +7 -7
  289. package/dist/routes/scripted/subject.js +1 -1
  290. package/dist/routes/scripted/surface-records.js +3 -3
  291. package/dist/routes/scripted/types.d.ts +3 -5
  292. package/dist/routes/scripted/types.js +1 -1
  293. package/dist/routes/shared-world/bundle-records.js +9 -8
  294. package/dist/routes/shared-world/bundle.d.ts +5 -5
  295. package/dist/routes/shared-world/bundle.js +40 -38
  296. package/dist/routes/shared-world/checkpoints.d.ts +1 -1
  297. package/dist/routes/shared-world/checkpoints.js +1 -1
  298. package/dist/routes/shared-world/comms.d.ts +5 -5
  299. package/dist/routes/shared-world/comms.js +14 -14
  300. package/dist/routes/shared-world/external-public.d.ts +4 -3
  301. package/dist/routes/shared-world/external-public.js +16 -12
  302. package/dist/routes/shared-world/handoff.d.ts +7 -6
  303. package/dist/routes/shared-world/handoff.js +65 -57
  304. package/dist/routes/shared-world/lobby-code.d.ts +2 -2
  305. package/dist/routes/shared-world/lobby-code.js +9 -9
  306. package/dist/routes/shared-world/participant-specs.d.ts +7 -6
  307. package/dist/routes/shared-world/participant-specs.js +31 -24
  308. package/dist/routes/shared-world/plan.js +7 -7
  309. package/dist/routes/shared-world/provenance.d.ts +2 -2
  310. package/dist/routes/shared-world/provenance.js +2 -2
  311. package/dist/routes/shared-world/provisioned.js +14 -13
  312. package/dist/routes/shared-world/result.js +20 -21
  313. package/dist/routes/shared-world/route.js +23 -22
  314. package/dist/routes/shared-world/setup.d.ts +3 -3
  315. package/dist/routes/shared-world/setup.js +4 -4
  316. package/dist/routes/shared-world/types.d.ts +30 -28
  317. package/dist/routes/shared-world/types.js +4 -4
  318. package/dist/routes/terminal/adapter.d.ts +3 -3
  319. package/dist/routes/terminal/adapter.js +5 -5
  320. package/dist/routes/terminal/bundle.d.ts +3 -3
  321. package/dist/routes/terminal/bundle.js +22 -21
  322. package/dist/routes/terminal/credentials.d.ts +4 -4
  323. package/dist/routes/terminal/credentials.js +7 -7
  324. package/dist/routes/terminal/dry-run.js +4 -4
  325. package/dist/routes/terminal/encoding.js +2 -2
  326. package/dist/routes/terminal/ledger.d.ts +3 -3
  327. package/dist/routes/terminal/ledger.js +14 -14
  328. package/dist/routes/terminal/live-finish.js +3 -3
  329. package/dist/routes/terminal/live-sandbox.js +12 -13
  330. package/dist/routes/terminal/persona.js +1 -1
  331. package/dist/routes/terminal/plan.js +11 -11
  332. package/dist/routes/terminal/recorder.js +2 -2
  333. package/dist/routes/terminal/result.js +8 -8
  334. package/dist/routes/terminal/route.js +6 -7
  335. package/dist/routes/terminal/sandbox.d.ts +1 -1
  336. package/dist/routes/terminal/sandbox.js +1 -1
  337. package/dist/routes/terminal/session.js +8 -7
  338. package/dist/routes/terminal/token-usage.d.ts +1 -1
  339. package/dist/routes/terminal/token-usage.js +7 -8
  340. package/dist/routes/terminal/trace.d.ts +2 -2
  341. package/dist/routes/terminal/trace.js +2 -2
  342. package/dist/routes/terminal/types.d.ts +26 -28
  343. package/dist/routes/terminal/types.js +3 -3
  344. package/dist/run/bundle-shape.js +3 -3
  345. package/dist/run/bundle.d.ts +46 -46
  346. package/dist/run/bundle.js +2 -1
  347. package/dist/run/cost-summary.js +3 -3
  348. package/dist/run/costs.js +7 -1
  349. package/dist/run/detail.d.ts +6 -6
  350. package/dist/run/detail.js +4 -4
  351. package/dist/run/dry-run-inputs.js +1 -1
  352. package/dist/run/dry-run.js +18 -18
  353. package/dist/run/judge.d.ts +19 -13
  354. package/dist/run/judge.js +18 -8
  355. package/dist/run/paths.d.ts +1 -1
  356. package/dist/run/paths.js +1 -1
  357. package/dist/run/pricing.d.ts +11 -6
  358. package/dist/run/pricing.js +20 -13
  359. package/dist/run/projection.d.ts +14 -14
  360. package/dist/run/projection.js +15 -15
  361. package/dist/run/reclaim.js +2 -2
  362. package/dist/run/results.d.ts +5 -5
  363. package/dist/run/run-index.d.ts +8 -6
  364. package/dist/run/run-index.js +15 -16
  365. package/dist/run/run-not-found.d.ts +5 -0
  366. package/dist/run/run-not-found.js +15 -0
  367. package/dist/run/run.d.ts +5 -4
  368. package/dist/run/run.js +1 -1
  369. package/dist/run/sandbox-receipts.d.ts +2 -2
  370. package/dist/run/sandbox-receipts.js +3 -3
  371. package/dist/run/shared-world-evidence.d.ts +36 -35
  372. package/dist/run/shared-world-evidence.js +4 -4
  373. package/dist/run/shared-world-shape.d.ts +1 -1
  374. package/dist/run/shared-world-shape.js +6 -6
  375. package/dist/run/stats.d.ts +12 -6
  376. package/dist/run/stats.js +116 -58
  377. package/dist/run/status.d.ts +8 -29
  378. package/dist/run/status.js +5 -27
  379. package/dist/run/stored-runs.js +2 -1
  380. package/dist/run/stream-shape.js +1 -1
  381. package/dist/run/streams.d.ts +6 -6
  382. package/dist/run/study-provenance.d.ts +47 -0
  383. package/dist/run/study-provenance.js +63 -0
  384. package/dist/run/study-result.d.ts +16 -0
  385. package/dist/run/study-result.js +9 -0
  386. package/dist/run/text.d.ts +2 -0
  387. package/dist/run/text.js +4 -0
  388. package/dist/run-lab.d.ts +7 -7
  389. package/dist/run-lab.js +1 -3
  390. package/dist/study/convert.d.ts +33 -0
  391. package/dist/study/convert.js +432 -0
  392. package/dist/study/field-paths.d.ts +12 -0
  393. package/dist/study/field-paths.js +126 -0
  394. package/dist/study/files.d.ts +26 -0
  395. package/dist/study/files.js +43 -0
  396. package/dist/study/migrate.d.ts +48 -0
  397. package/dist/study/migrate.js +408 -0
  398. package/dist/study/owned-files.d.ts +38 -0
  399. package/dist/study/owned-files.js +182 -0
  400. package/dist/subject/clone.d.ts +1 -1
  401. package/dist/subject/desktop-cli.d.ts +1 -1
  402. package/dist/subject/desktop-cli.js +2 -2
  403. package/dist/subject/local-tree-archive.js +1 -1
  404. package/dist/subject/local-tree.d.ts +1 -1
  405. package/dist/subject/node-bootstrap.js +1 -1
  406. package/dist/subject/runtime.js +8 -9
  407. package/dist/subject/serve.d.ts +1 -1
  408. package/dist/subject/serve.js +3 -3
  409. package/dist/subject/state.d.ts +1 -1
  410. package/dist/subject/steps.d.ts +5 -5
  411. package/dist/subject/steps.js +4 -4
  412. package/dist/substrates/command-failure.d.ts +3 -3
  413. package/dist/substrates/command-failure.js +3 -3
  414. package/dist/substrates/detached.d.ts +6 -6
  415. package/dist/substrates/detached.js +7 -7
  416. package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
  417. package/dist/substrates/e2b/cdp-probe.js +14 -17
  418. package/dist/substrates/e2b/desktop-browser.d.ts +2 -2
  419. package/dist/substrates/e2b/desktop-browser.js +8 -8
  420. package/dist/substrates/e2b/desktop-cdp.d.ts +9 -9
  421. package/dist/substrates/e2b/desktop-cdp.js +8 -8
  422. package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
  423. package/dist/substrates/e2b/desktop-executor.js +1 -1
  424. package/dist/substrates/e2b/desktop-geometry.d.ts +3 -3
  425. package/dist/substrates/e2b/desktop-geometry.js +7 -7
  426. package/dist/substrates/e2b/desktop-media.d.ts +1 -1
  427. package/dist/substrates/e2b/desktop-media.js +1 -1
  428. package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
  429. package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
  430. package/dist/substrates/e2b/sandbox.d.ts +1 -1
  431. package/dist/substrates/e2b/sandbox.js +1 -1
  432. package/dist/substrates/e2b/sdk.d.ts +11 -11
  433. package/dist/substrates/e2b/sdk.js +6 -6
  434. package/dist/tui/actions.d.ts +1 -1
  435. package/dist/tui/actions.js +13 -13
  436. package/dist/tui/contract.d.ts +16 -16
  437. package/dist/tui/contract.js +10 -10
  438. package/dist/tui/launch.d.ts +4 -4
  439. package/dist/tui/launch.js +18 -19
  440. package/dist/tui/project.js +5 -5
  441. package/dist/tui-app.js +82 -82
  442. package/dist/verify/actor.d.ts +8 -8
  443. package/dist/verify/actor.js +36 -36
  444. package/dist/verify/artifacts.d.ts +2 -2
  445. package/dist/verify/artifacts.js +3 -3
  446. package/dist/verify/context-growth.d.ts +9 -0
  447. package/dist/verify/context-growth.js +62 -0
  448. package/dist/verify/costs.d.ts +6 -6
  449. package/dist/verify/costs.js +8 -8
  450. package/dist/verify/shared-world-concurrent.d.ts +2 -2
  451. package/dist/verify/shared-world-concurrent.js +79 -76
  452. package/dist/verify/shared-world.d.ts +2 -2
  453. package/dist/verify/shared-world.js +16 -16
  454. package/dist/verify/subject.d.ts +4 -4
  455. package/dist/verify/subject.js +18 -18
  456. package/dist/verify/verify.js +92 -43
  457. package/docs/README.md +25 -32
  458. package/docs/architecture/actor-contract.md +56 -87
  459. package/docs/architecture/desktop-sessions.md +7 -7
  460. package/docs/architecture/external-public-shared-world.md +61 -59
  461. package/docs/architecture/github-feedback-loop.md +1 -4
  462. package/docs/architecture/guest-desktop.md +2 -2
  463. package/docs/architecture/observer.md +34 -34
  464. package/docs/architecture/restricted-codex-analysis.md +34 -28
  465. package/docs/architecture/serve.md +34 -37
  466. package/docs/architecture/state-driven-executor.md +55 -58
  467. package/docs/architecture/task-protocol-support.md +5 -5
  468. package/docs/architecture/terminal-product-route.md +67 -107
  469. package/docs/contracts/README.md +24 -0
  470. package/docs/contracts/adapter-admission.md +3 -3
  471. package/docs/contracts/adapter-fixtures.md +2 -5
  472. package/docs/contracts/core.md +1 -3
  473. package/docs/contracts/errors.md +62 -0
  474. package/docs/contracts/feedback.md +8 -9
  475. package/docs/contracts/policy.md +7 -12
  476. package/docs/contracts/run-bundle.md +45 -44
  477. package/docs/contracts/schemas.md +421 -362
  478. package/docs/contracts/study-analysis.md +3 -3
  479. package/docs/contracts/study-costs.md +11 -7
  480. package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
  481. package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
  482. package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
  483. package/docs/principles/actor-fidelity.md +4 -4
  484. package/docs/principles/engineering.md +3 -3
  485. package/docs/principles/invariants-and-defaults.md +38 -38
  486. package/docs/principles/self-driving-harness.md +1 -5
  487. package/docs/principles/three-roles.md +1 -1
  488. package/docs/product/automatic-analysis.md +7 -7
  489. package/examples/participant/README.md +5 -5
  490. package/examples/participant/run.mjs +11 -10
  491. package/examples/scorer/README.md +3 -3
  492. package/examples/scorer/run.mjs +11 -12
  493. package/package.json +16 -17
  494. package/skills/humanish/SKILL.md +60 -58
  495. package/skills/humanish/agents/openai.yaml +1 -1
  496. package/AGENTS.md +0 -99
  497. package/CONTRIBUTING.md +0 -148
  498. package/dist/actors/codex/qualified-versions.d.ts +0 -72
  499. package/dist/actors/codex/qualified-versions.js +0 -132
  500. package/dist/cli/commands/lab.d.ts +0 -3
  501. package/dist/cli/commands/lab.js +0 -199
  502. package/dist/cli/renamed-options.d.ts +0 -11
  503. package/dist/cli/renamed-options.js +0 -18
  504. package/dist/observer/static.d.ts +0 -39
  505. package/dist/observer/static.js +0 -369
  506. package/docs/architecture/comms-inbox.md +0 -122
  507. package/docs/architecture/desktop-recording.md +0 -80
  508. package/docs/architecture/local-browser-runtime.md +0 -178
  509. package/docs/architecture/observer-review.md +0 -144
  510. package/docs/architecture/participant-media.md +0 -90
  511. package/docs/architecture/project-layout.md +0 -62
  512. package/docs/architecture/real-email-receiving.md +0 -136
  513. package/docs/assets/humanish-drawdb-hero.png +0 -0
  514. package/docs/assets/humanish-observer-hero.png +0 -0
  515. package/docs/goals/current.md +0 -207
  516. package/docs/product/lobby-trivia-3player-external-public.md +0 -77
  517. package/docs/product/open-source-install-experience.md +0 -240
  518. package/docs/ramp/README.md +0 -295
  519. package/docs/release/open-source-readiness.md +0 -222
  520. package/docs/release/public-readiness-standard.md +0 -210
  521. package/docs/roadmap/world-class-open-source-v0.md +0 -311
@@ -1,7 +1,8 @@
1
1
  import { validClosingReport } from "./loop.js";
2
2
  import { CuaAdmissionLimitError, isCuaAdmissionLimitError } from "./admission-limit.js";
3
3
  import { CuaPromptRefusedError } from "./provider-error.js";
4
- import { acceptReply, debriefRequestBody, turnRequestBody, } from "./openai-requests.js";
4
+ import { CarriedConversation } from "./openai-context.js";
5
+ import { acceptReply, ConversationRecord, debriefRequestBody, turnInputItems, turnRequestBody, } from "./openai-requests.js";
5
6
  import { asRecord, optionalString, parseOpenAiResponse, } from "./openai-wire.js";
6
7
  import { redactText } from "../../evidence/redaction.js";
7
8
  import { isMaxOutputTokens } from "../output-token-limit.js";
@@ -10,35 +11,35 @@ import { OPENAI_RESPONSES_URL } from "../openai-endpoint.js";
10
11
  // A public-safe re-derivation of the OpenAI Responses API computer-use provider,
11
12
  // behind the CuaProvider port from src/actors/computer-use/loop.ts. The pure wire mapping
12
13
  // (openAiActionToCua, parseOpenAiResponse and the request builders) is in openai-wire.ts.
13
- // This module is the live shim: createOpenAiResponsesProvider does a RAW POST to the
14
+ // This module is the live shim: createOpenAiResponsesProvider does a raw POST to the
14
15
  // Responses endpoint (no SDK dependency) through an injectable FetchLike seam, so the retry,
15
16
  // ZDR fallback, and state threading are testable with a fake.
16
17
  //
17
18
  // Public-safety invariants (this is an OSS repo): the apiKey only ever appears in
18
19
  // the Authorization header, never in a returned object, thrown error, or comment.
19
20
  // Request bodies (which carry base64 screenshots and the persona instructions)
20
- // and screenshots are never logged or returned; nextTurn returns ONLY a CuaTurn,
21
+ // and screenshots are never logged or returned; nextTurn returns only a CuaTurn,
21
22
  // and the engine handles redaction of CuaTurn fields downstream. Error messages
22
23
  // carry the HTTP status only, never the response body (it can echo the input).
23
24
  //
24
- // Wire capture (fixture provenance). The 0.6.1 parser incident — the parser read
25
+ // Wire capture (fixture provenance). In the 0.6.1 parser incident, the parser read
25
26
  // `computer_call.action` (singular) while the live API returns `actions` (array),
26
- // and the hand-written fixtures encoded the SAME wrong shape, so tests passed in
27
- // lockstep with the bug while every live action was silently dropped — taught us
28
- // that deterministic fixtures must derive from CAPTURED live wire shapes, never
27
+ // and the hand-written fixtures encoded the same wrong shape, so tests passed in
28
+ // lockstep with the bug while every live action was silently dropped. It taught us
29
+ // that deterministic fixtures must derive from captured live wire shapes, never
29
30
  // from memory. Setting HUMANISH_CUA_WIRE_CAPTURE_DIR makes the live shim persist
30
- // each successful Responses RESPONSE body into that directory as pretty-printed
31
+ // each successful Responses response body into that directory as pretty-printed
31
32
  // JSON, one file per provider call in call order (wire-001.json, wire-002.json,
32
33
  // ...), for refreshing fixtures. The capture seam is:
33
- // - OPT-IN: unset (or empty) env means zero behavior change — nothing is written;
34
- // - RESPONSE-side only: request bodies carry base64 screenshots and the persona
35
- // instructions and are NEVER captured; non-ok response bodies can echo the
34
+ // - Opt-in: unset (or empty) env means zero behavior change, and nothing is written;
35
+ // - Response-side only: request bodies carry base64 screenshots and the persona
36
+ // instructions and are never captured; non-ok response bodies can echo the
36
37
  // request and are never captured either;
37
- // - REDACTED: every string field (keys and values) passes through the shared
38
+ // - Redacted: every string field (keys and values) passes through the shared
38
39
  // redactText (src/evidence/redaction.ts) before writing, so a secret-shaped echo in a
39
40
  // response cannot persist to disk.
40
41
  // Point the env var at a gitignored path (e.g. under .humanish/): raw captures must
41
- // never be committed — fixtures derived from them must be minimal, hand-reviewed
42
+ // never be committed; fixtures derived from them must be minimal, hand-reviewed
42
43
  // excerpts checked into tests deliberately.
43
44
  export const OPENAI_RESPONSES_CU_CAPABILITIES = {
44
45
  headless: true,
@@ -52,12 +53,12 @@ export const OPENAI_RESPONSES_CU_CAPABILITIES = {
52
53
  };
53
54
  // The flagship 5.6-generation tier ("gpt-5.6" is OpenAI's alias for this exact id; the
54
55
  // computer-use guide's own examples run on it). Explicit tier id so trace provenance and the
55
- // rate-table key stay stable if OpenAI repoints the alias (#334).
56
+ // rate-table key stay stable if OpenAI repoints the alias.
56
57
  export const DEFAULT_OPENAI_CU_MODEL = "gpt-5.6-sol";
57
58
  /**
58
59
  * The effort a request carries when a lab declares none. Exported because a default that only
59
60
  * exists as a literal inside the provider is exactly how it stayed invisible: the lab surface has
60
- * to be able to say what will actually run (#497).
61
+ * to be able to say what will actually run.
61
62
  */
62
63
  export const DEFAULT_OPENAI_CU_REASONING_EFFORT = "medium";
63
64
  // ---------------------------------------------------------------------------
@@ -66,7 +67,7 @@ export const DEFAULT_OPENAI_CU_REASONING_EFFORT = "medium";
66
67
  /** The opt-in gate for response wire capture: a directory path, or unset for off. */
67
68
  export const WIRE_CAPTURE_ENV = "HUMANISH_CUA_WIRE_CAPTURE_DIR";
68
69
  /**
69
- * Deep-copy a captured wire value with every string — object keys included —
70
+ * Deep-copy a captured wire value with every string (object keys included)
70
71
  * passed through the shared redactText, so a secret-shaped echo in a response
71
72
  * can never persist to disk. Pure; non-string primitives pass through unchanged.
72
73
  */
@@ -222,7 +223,7 @@ function defaultDelay(ms) {
222
223
  function isAbortError(error) {
223
224
  return error instanceof Error && error.name === "AbortError";
224
225
  }
225
- // Opt-in response wire capture (see module header): an undefined directory means OFF and zero
226
+ // Opt-in response wire capture (see module header): an undefined directory means off and zero
226
227
  // behavior change. The counter is per-provider, so file order is call order.
227
228
  function createWireCapture(captureDir) {
228
229
  let captureCount = 0;
@@ -237,7 +238,7 @@ function createWireCapture(captureDir) {
237
238
  };
238
239
  return {
239
240
  prepareNext,
240
- // Fails loud: a silent capture failure would mean missing turns in a fixture refresh — the
241
+ // Fails loud: a silent capture failure would mean missing turns in a fixture refresh: the
241
242
  // exact "fixtures drift from the wire" pathology capture exists to prevent.
242
243
  record: async (raw) => {
243
244
  if (captureDir === undefined)
@@ -252,7 +253,7 @@ function createWireCapture(captureDir) {
252
253
  }
253
254
  // POST the JSON body and return the parsed JSON on success. Retries on
254
255
  // transient statuses (408/409/429/>=500). Maps a ZDR-policy 400 to a typed
255
- // ZdrError; any other non-ok status throws with the STATUS ONLY (never the
256
+ // ZdrError; any other non-ok status throws with the status only (never the
256
257
  // body, which can echo the input/screenshot).
257
258
  async function postResponse(transport, body, signal, retries, interaction, spend) {
258
259
  // Preflight the deterministic next capture leaf before any network side
@@ -300,7 +301,7 @@ async function postResponse(transport, body, signal, retries, interaction, spend
300
301
  }
301
302
  if (res.ok) {
302
303
  const parsed = await res.json();
303
- // Capture AFTER ok and BEFORE parse-to-CuaTurn: responses only, never the
304
+ // Capture after ok and before parse-to-CuaTurn: responses only, never the
304
305
  // request (screenshots/instructions) and never a non-ok body (input echo).
305
306
  await transport.capture.record(parsed);
306
307
  return parsed;
@@ -353,7 +354,7 @@ async function postResponse(transport, body, signal, retries, interaction, spend
353
354
  * call outputs (with the latest screenshot) and thread state via
354
355
  * previous_response_id, transparently falling back to explicit-context mode if
355
356
  * the account rejects server-side retention. Transient HTTP failures are retried
356
- * with exponential backoff. Returns ONLY a CuaTurn from nextTurn; nothing
357
+ * with exponential backoff. Returns only a CuaTurn from nextTurn; nothing
357
358
  * sensitive (the key, the request body, the screenshot, the raw response body)
358
359
  * is ever returned or logged.
359
360
  */
@@ -379,10 +380,11 @@ export function createOpenAiResponsesProvider(options) {
379
380
  const state = {
380
381
  lastResponseId: undefined,
381
382
  pendingCallIds: [],
382
- lastOutputItems: [],
383
+ replies: 0,
384
+ conversation: new CarriedConversation(),
383
385
  mode: options.zeroDataRetention ? "explicit_context" : "previous_response_id",
384
386
  // Latches to undefined (stop asking) for the rest of the session when the
385
- // account/model rejects the summary request — see OpenAiResponsesProviderOptions.
387
+ // account/model rejects the summary request; see OpenAiResponsesProviderOptions.
386
388
  reasoningSummary: options.reasoningSummary === "off" ? undefined : (options.reasoningSummary ?? "auto"),
387
389
  };
388
390
  const transport = {
@@ -396,15 +398,16 @@ export function createOpenAiResponsesProvider(options) {
396
398
  },
397
399
  };
398
400
  const post = (body, signal, retries = maxRetries, interaction = true, spend) => postResponse(transport, body, signal, retries, interaction, spend);
401
+ const record = new ConversationRecord(options.zeroDataRetention === true, options.now ?? Date.now);
399
402
  // POST with the recoverable-policy latches: a ZDR rejection switches to explicit-context mode; a
400
403
  // reasoning-summary rejection latches summaries off. Each latch can flip only once, so the loop
401
404
  // is bounded; anything else rethrows. The body is rebuilt per attempt so a flipped latch shows.
402
- const postTurn = async (req, signal, spend) => {
405
+ const postTurn = async (req, sent, signal, spend) => {
403
406
  if (options.singleDispatch === true)
404
- return post(turnRequestBody(settings, state, req), signal, 0);
407
+ return post(turnRequestBody(settings, state, req, sent), signal, 0);
405
408
  for (;;) {
406
409
  try {
407
- return await post(turnRequestBody(settings, state, req), signal, maxRetries, true, spend);
410
+ return await post(turnRequestBody(settings, state, req, sent), signal, maxRetries, true, spend);
408
411
  }
409
412
  catch (error) {
410
413
  if (error instanceof SummaryRejectionError && state.reasoningSummary !== undefined) {
@@ -412,6 +415,7 @@ export function createOpenAiResponsesProvider(options) {
412
415
  continue;
413
416
  }
414
417
  if (error instanceof ZdrError && state.mode !== "explicit_context") {
418
+ record.switched();
415
419
  state.mode = "explicit_context";
416
420
  continue;
417
421
  }
@@ -421,12 +425,15 @@ export function createOpenAiResponsesProvider(options) {
421
425
  };
422
426
  const requestTurn = async (req, signal, closing = false, spend) => {
423
427
  await capture.prepareNext();
428
+ const sent = turnInputItems(state, req);
424
429
  // A closing report makes exactly one request: no HTTP or policy-latch retries.
425
430
  const raw = closing
426
- ? await post(debriefRequestBody(settings, state, req), signal, 0, false)
427
- : await postTurn(req, signal, spend);
431
+ ? await post(debriefRequestBody(settings, state, req, sent), signal, 0, false)
432
+ : await postTurn(req, sent, signal, spend);
433
+ if (!closing)
434
+ record.requested(state, sent);
428
435
  const parsed = parseOpenAiResponse(raw);
429
- acceptReply(state, parsed, closing);
436
+ acceptReply(state, parsed, closing, sent);
430
437
  if (closing) {
431
438
  // Refusals, incomplete output, malformed JSON, and invalid shapes remain no-report results.
432
439
  // Never promote raw JSON or a fallback paragraph into a structured finding.
@@ -445,14 +452,14 @@ export function createOpenAiResponsesProvider(options) {
445
452
  return {
446
453
  id: "openai-responses-cu",
447
454
  version: model,
448
- // The effort the wire actually carries, not the one the lab asked for — the provider defaults
449
- // an absent request to "medium", and the trace has to say what produced it (#497).
455
+ // The effort the wire actually carries, not the one the lab asked for: the provider defaults
456
+ // an absent request to "medium", and the trace has to say what produced it.
450
457
  modelSettings: {
451
458
  reasoningEffort,
452
459
  ...(maxOutputTokens === undefined ? {} : { maxOutputTokens }),
453
460
  },
454
461
  capabilities: OPENAI_RESPONSES_CU_CAPABILITIES,
455
- // This is a VISION provider: nextTurn sends the screenshot as the computer_call_output, so
462
+ // This is a vision provider: nextTurn sends the screenshot as the computer_call_output, so
456
463
  // it cannot reason over a screenshot-less observation. The loop reads this to fail closed
457
464
  // (harness_error) when a state-only executor is paired with it (provider-authoring contract).
458
465
  requiresFrame: true,
@@ -461,8 +468,12 @@ export function createOpenAiResponsesProvider(options) {
461
468
  return interactionUsageIncomplete;
462
469
  },
463
470
  nextTurn: (req, signal, spend) => requestTurn(req, signal, false, spend),
464
- // Stateless mode retains only the latest output packet, not the whole session needed for
465
- // retrospective claims. This getter follows both configured ZDR and a runtime policy latch.
471
+ get conversation() {
472
+ return record.snapshot(state);
473
+ },
474
+ // An explicit-context conversation summarizes its oldest turns past its budget, so it may not
475
+ // hold the whole session a retrospective report needs. This getter follows both configured
476
+ // ZDR and a runtime policy latch.
466
477
  get debrief() {
467
478
  return state.mode === "explicit_context" || state.lastResponseId === undefined
468
479
  ? undefined
@@ -1,5 +1,7 @@
1
1
  import type { CuaTurnRequest } from "./loop.js";
2
2
  import type { ReasoningEffort } from "../reasoning-effort.js";
3
+ import type { ActorConversation } from "../contract.js";
4
+ import { CarriedConversation } from "./openai-context.js";
3
5
  import { type OpenAiReasoningSummary, type ParsedOpenAiResponse } from "./openai-wire.js";
4
6
  /** Request settings fixed for a provider's whole session. */
5
7
  export interface OpenAiRequestSettings {
@@ -13,23 +15,47 @@ export interface OpenAiConversationState {
13
15
  lastResponseId: string | undefined;
14
16
  /** computer_call ids the next request owes an output for. */
15
17
  pendingCallIds: string[];
16
- /** The last reply's output items, resent in explicit-context mode. */
17
- lastOutputItems: unknown[];
18
+ /** Accepted replies so far; the next request is number `replies + 1`. */
19
+ replies: number;
20
+ /** The whole conversation, which explicit-context requests carry within its token budget. */
21
+ conversation: CarriedConversation;
18
22
  /** explicit_context after a zero-data-retention rejection or when configured. */
19
23
  mode: "previous_response_id" | "explicit_context";
20
24
  /** Undefined once the account or model rejected reasoning summaries. */
21
25
  reasoningSummary: OpenAiReasoningSummary | undefined;
22
26
  }
23
27
  /**
24
- * The body of the next participant request: the opening request with the first screen, or a
25
- * continuation that answers each pending computer_call with the latest screenshot.
28
+ * The items the next request adds to the conversation: the opening message with the first
29
+ * screen, or an output for each pending computer_call with the latest screenshot and any hint.
30
+ * Built once per turn, so every attempt at the request and the accepted reply see the same items.
26
31
  */
27
- export declare function turnRequestBody(settings: OpenAiRequestSettings, state: OpenAiConversationState, req: CuaTurnRequest): Record<string, unknown>;
32
+ export declare function turnInputItems(state: OpenAiConversationState, req: CuaTurnRequest): readonly unknown[];
33
+ /**
34
+ * The body of the next participant request: the opening request, or a continuation carrying
35
+ * `sent` (turnInputItems). A threaded continuation names the previous response; an
36
+ * explicit-context one carries the conversation ahead of `sent`.
37
+ */
38
+ export declare function turnRequestBody(settings: OpenAiRequestSettings, state: OpenAiConversationState, req: CuaTurnRequest, sent: readonly unknown[]): Record<string, unknown>;
28
39
  /** The body of the read-only closing report: no tools, a small output limit, a strict schema. */
29
- export declare function debriefRequestBody(settings: OpenAiRequestSettings, state: OpenAiConversationState, req: CuaTurnRequest): Record<string, unknown>;
40
+ export declare function debriefRequestBody(settings: OpenAiRequestSettings, state: OpenAiConversationState, req: CuaTurnRequest, sent: readonly unknown[]): Record<string, unknown>;
30
41
  /**
31
- * Move the conversation on to an accepted reply. A participant reply cut off by the output limit
32
- * is set aside, so the next request is the same one again (outputLimitRetry); its actions never
33
- * run, so no call output is owed for them.
42
+ * Move the conversation on to an accepted reply to a request that added `sent`. A participant
43
+ * reply cut off by the output limit is set aside, so the next request is the same one again
44
+ * (outputLimitRetry); its actions never run, so no call output is owed for them.
34
45
  */
35
- export declare function acceptReply(state: OpenAiConversationState, parsed: ParsedOpenAiResponse, closing: boolean): void;
46
+ export declare function acceptReply(state: OpenAiConversationState, parsed: ParsedOpenAiResponse, closing: boolean, sent: readonly unknown[]): void;
47
+ /** The trace's account of how a session carried its conversation (ActorConversation). */
48
+ export declare class ConversationRecord {
49
+ private readonly now;
50
+ private explicitReason;
51
+ private switchedAt;
52
+ private switchedAtRequest;
53
+ private summarizedTurns;
54
+ private readonly requests;
55
+ constructor(configured: boolean, now: () => number);
56
+ /** The organization rejected server-side state, so the request being sent is explicit_context. */
57
+ switched(): void;
58
+ /** A participant request just went out with `sent` after the carried conversation. */
59
+ requested(state: OpenAiConversationState, sent: readonly unknown[]): void;
60
+ snapshot(state: OpenAiConversationState): ActorConversation;
61
+ }
@@ -1,8 +1,10 @@
1
- import { buildCallOutput, buildContinuationRequest, buildInitialRequest, } from "./openai-wire.js";
1
+ import { CarriedConversation, estimateTokens } from "./openai-context.js";
2
+ import { buildCallOutput, buildContinuationRequest, buildInitialRequest, hintItems, openingMessage, } from "./openai-wire.js";
2
3
  /** The closing report's output limit: its own cap, or the declared limit when that is lower. */
3
4
  const CLOSING_OUTPUT_LIMIT = 1024;
4
5
  function requestContext(settings, state, instructions) {
5
6
  return {
7
+ stateless: state.mode === "explicit_context",
6
8
  model: settings.model,
7
9
  instructions,
8
10
  reasoningEffort: settings.reasoningEffort,
@@ -17,28 +19,43 @@ function requestContext(settings, state, instructions) {
17
19
  }
18
20
  /** No reply has been accepted yet, so the next request opens the conversation. */
19
21
  function isFirstTurn(state) {
20
- return state.lastResponseId === undefined && state.pendingCallIds.length === 0;
22
+ return state.replies === 0;
21
23
  }
22
24
  /**
23
- * The body of the next participant request: the opening request with the first screen, or a
24
- * continuation that answers each pending computer_call with the latest screenshot.
25
+ * The items the next request adds to the conversation: the opening message with the first
26
+ * screen, or an output for each pending computer_call with the latest screenshot and any hint.
27
+ * Built once per turn, so every attempt at the request and the accepted reply see the same items.
25
28
  */
26
- export function turnRequestBody(settings, state, req) {
29
+ export function turnInputItems(state, req) {
30
+ if (isFirstTurn(state))
31
+ return [openingMessage(req.instructions, req.observation.screenshot)];
32
+ return [
33
+ ...state.pendingCallIds.map((id) => buildCallOutput(id, req.observation.screenshot, req.acknowledgedSafetyChecks)),
34
+ ...hintItems(req.contextHint),
35
+ ];
36
+ }
37
+ /**
38
+ * The body of the next participant request: the opening request, or a continuation carrying
39
+ * `sent` (turnInputItems). A threaded continuation names the previous response; an
40
+ * explicit-context one carries the conversation ahead of `sent`.
41
+ */
42
+ export function turnRequestBody(settings, state, req, sent) {
27
43
  const ctx = requestContext(settings, state, req.instructions);
28
44
  if (isFirstTurn(state))
29
45
  return buildInitialRequest(ctx, req.observation.screenshot);
30
46
  return buildContinuationRequest({
31
47
  ctx,
32
48
  previousResponseId: state.lastResponseId,
33
- callOutputs: state.pendingCallIds.map((id) => buildCallOutput(id, req.observation.screenshot, req.acknowledgedSafetyChecks)),
34
- ...(req.contextHint === undefined ? {} : { contextHint: req.contextHint }),
35
- ...(state.mode === "explicit_context" ? { explicitContextItems: state.lastOutputItems } : {}),
49
+ callOutputs: [...sent],
50
+ ...(state.mode === "explicit_context"
51
+ ? { explicitContextItems: state.conversation.carried() }
52
+ : {}),
36
53
  });
37
54
  }
38
55
  /** The body of the read-only closing report: no tools, a small output limit, a strict schema. */
39
- export function debriefRequestBody(settings, state, req) {
56
+ export function debriefRequestBody(settings, state, req, sent) {
40
57
  return {
41
- ...turnRequestBody(settings, state, req),
58
+ ...turnRequestBody(settings, state, req, sent),
42
59
  tool_choice: "none",
43
60
  max_output_tokens: Math.min(settings.maxOutputTokens ?? CLOSING_OUTPUT_LIMIT, CLOSING_OUTPUT_LIMIT),
44
61
  text: {
@@ -60,15 +77,65 @@ export function debriefRequestBody(settings, state, req) {
60
77
  };
61
78
  }
62
79
  /**
63
- * Move the conversation on to an accepted reply. A participant reply cut off by the output limit
64
- * is set aside, so the next request is the same one again (outputLimitRetry); its actions never
65
- * run, so no call output is owed for them.
80
+ * Move the conversation on to an accepted reply to a request that added `sent`. A participant
81
+ * reply cut off by the output limit is set aside, so the next request is the same one again
82
+ * (outputLimitRetry); its actions never run, so no call output is owed for them.
66
83
  */
67
- export function acceptReply(state, parsed, closing) {
84
+ export function acceptReply(state, parsed, closing, sent) {
68
85
  if (!closing && parsed.turn.interruption === "output_limit")
69
86
  return;
70
87
  if (parsed.turn.responseId !== undefined)
71
88
  state.lastResponseId = parsed.turn.responseId;
72
89
  state.pendingCallIds = parsed.callIds;
73
- state.lastOutputItems = parsed.outputItems;
90
+ state.replies += 1;
91
+ state.conversation.accept(state.replies, sent, parsed.outputItems);
92
+ }
93
+ /** The trace's account of how a session carried its conversation (ActorConversation). */
94
+ export class ConversationRecord {
95
+ now;
96
+ explicitReason;
97
+ switchedAt;
98
+ switchedAtRequest;
99
+ summarizedTurns = 0;
100
+ requests = [];
101
+ constructor(configured, now) {
102
+ this.now = now;
103
+ if (configured)
104
+ this.explicitReason = "configured";
105
+ }
106
+ /** The organization rejected server-side state, so the request being sent is explicit_context. */
107
+ switched() {
108
+ this.explicitReason = "zdr_rejection";
109
+ this.switchedAt = new Date(this.now()).toISOString();
110
+ // Counted like requests[], which includes replies set aside at their output limit.
111
+ this.switchedAtRequest = this.requests.length + 1;
112
+ }
113
+ /** A participant request just went out with `sent` after the carried conversation. */
114
+ requested(state, sent) {
115
+ if (state.mode !== "explicit_context") {
116
+ this.requests.push({ mode: "threaded" });
117
+ return;
118
+ }
119
+ const carried = state.conversation.size();
120
+ // Only summaries a request carried count; the conversation also trims after the last reply.
121
+ this.summarizedTurns = carried.notedTurns;
122
+ this.requests.push({
123
+ mode: "explicit_context",
124
+ carriedExchanges: carried.exchanges,
125
+ carriedScreenshots: carried.screenshots,
126
+ estimatedInputTokens: carried.estimatedTokens + estimateTokens(sent),
127
+ });
128
+ }
129
+ snapshot(state) {
130
+ return {
131
+ mode: state.mode === "explicit_context" ? "explicit_context" : "threaded",
132
+ ...(this.explicitReason === undefined ? {} : { explicitReason: this.explicitReason }),
133
+ ...(this.switchedAt === undefined ? {} : { switchedAt: this.switchedAt }),
134
+ ...(this.switchedAtRequest === undefined
135
+ ? {}
136
+ : { switchedAtRequest: this.switchedAtRequest }),
137
+ summarizedTurns: this.summarizedTurns,
138
+ requests: this.requests.map((request) => ({ ...request })),
139
+ };
140
+ }
74
141
  }
@@ -1,6 +1,7 @@
1
1
  import type { CuaAction, CuaSafetyCheck, CuaTurn } from "./loop.js";
2
2
  import type { ReasoningEffort } from "../reasoning-effort.js";
3
3
  export declare function asRecord(value: unknown): Record<string, unknown>;
4
+ export declare function asArray(value: unknown): unknown[];
4
5
  export declare function optionalString(value: unknown): string | undefined;
5
6
  /**
6
7
  * Map an OpenAI computer action object to a provider-neutral CuaAction, or null
@@ -23,11 +24,16 @@ export interface ParsedOpenAiResponse {
23
24
  export declare function parseOpenAiResponse(raw: unknown): ParsedOpenAiResponse;
24
25
  export type OpenAiReasoningSummary = "auto" | "concise" | "detailed";
25
26
  export interface OpenAiCuContext {
27
+ /**
28
+ * The server keeps no conversation (explicit_context): the request asks not to be stored and
29
+ * for its reasoning back in encrypted form, so the next request can carry it.
30
+ */
31
+ stateless?: boolean;
26
32
  model: string;
27
33
  instructions: string;
28
34
  reasoningEffort: ReasoningEffort;
29
35
  maxOutputTokens?: number;
30
- /** When set, request provider-sanctioned reasoning summaries (#427). Absent = do not ask. */
36
+ /** When set, request provider-sanctioned reasoning summaries. Absent = do not ask. */
31
37
  reasoningSummary?: OpenAiReasoningSummary;
32
38
  safetyIdentifier?: string;
33
39
  }
@@ -37,14 +43,18 @@ export interface OpenAiCuContext {
37
43
  * limit when that is lower.
38
44
  */
39
45
  export declare function buildInitialRequest(ctx: OpenAiCuContext, screenshot?: Buffer): Record<string, unknown>;
46
+ /** One input message, read as the words of `sender`: the user, the developer, or the model itself. */
47
+ export declare function inputMessage(sender: "user" | "developer" | "assistant", content: readonly unknown[]): Record<string, unknown>;
48
+ /** The first request's only input item: the instructions and, when there is one, the first screen. */
49
+ export declare function openingMessage(instructions: string, screenshot?: Buffer): Record<string, unknown>;
40
50
  /**
41
51
  * Build one computer_call_output for a pending call id, carrying the latest
42
52
  * screenshot as an inline data URL. Acknowledged safety checks (if any) are
43
53
  * echoed back so the model can proceed past a check the harness approved.
44
54
  *
45
55
  * The screenshot param is `Buffer | undefined` because CuaObservation.screenshot is now
46
- * optional (a non-vision executor omits it). This provider is a VISION model (it sets
47
- * requiresFrame), so a missing frame is a hard error here — defense-in-depth: the loop's
56
+ * optional (a non-vision executor omits it). This provider is a vision model (it sets
57
+ * requiresFrame), so a missing frame is a hard error here as defense-in-depth: the loop's
48
58
  * per-turn requiresFrame guard already fails closed before this is reached, but throwing keeps
49
59
  * the mapper self-validating and isolable.
50
60
  */
@@ -52,16 +62,18 @@ export declare function buildCallOutput(callId: string, screenshot: Buffer | und
52
62
  export interface ContinuationRequestArgs {
53
63
  ctx: OpenAiCuContext;
54
64
  previousResponseId: string | undefined;
55
- callOutputs: object[];
65
+ callOutputs: readonly unknown[];
56
66
  contextHint?: string;
57
67
  explicitContextItems?: unknown[];
58
68
  }
69
+ /** An optional context hint as input items (none when there is no hint). */
70
+ export declare function hintItems(contextHint: string | undefined): unknown[];
59
71
  /**
60
72
  * Build a continuation request body. Two modes:
61
73
  * - default: thread server-side state via previous_response_id and send only the
62
74
  * new call outputs (plus an optional hint).
63
- * - explicit-context (ZDR): no previous_response_id; the prior output items are
64
- * re-sent inline ahead of the new call outputs so the model has full context
65
- * without the server retaining any.
75
+ * - explicit-context (ZDR): no previous_response_id; the carried conversation
76
+ * (openai-context.ts) is sent inline ahead of the new call outputs, so the model
77
+ * has the session without the server retaining any.
66
78
  */
67
79
  export declare function buildContinuationRequest(args: ContinuationRequestArgs): Record<string, unknown>;
@@ -11,7 +11,7 @@
11
11
  export function asRecord(value) {
12
12
  return typeof value === "object" && value !== null ? value : {};
13
13
  }
14
- function asArray(value) {
14
+ export function asArray(value) {
15
15
  return Array.isArray(value) ? value : [];
16
16
  }
17
17
  function asNumber(value) {
@@ -165,9 +165,9 @@ export function parseOpenAiResponse(raw) {
165
165
  const callId = optionalString(item.call_id);
166
166
  if (callId !== undefined)
167
167
  callIds.push(callId);
168
- // The live Responses API returns the actions as an ARRAY (`item.actions`); a single
169
- // computer_call can carry several. (An older/alt shape used a singular `item.action` —
170
- // supported as a fallback.) Reading only `item.action` silently dropped EVERY action,
168
+ // The live Responses API returns the actions as an array (`item.actions`); a single
169
+ // computer_call can carry several. (An older/alt shape used a singular `item.action`,
170
+ // supported as a fallback.) Reading only `item.action` silently dropped every action,
171
171
  // which made the loop see zero actions and stop on a false `goal_satisfied`.
172
172
  const rawActions = Array.isArray(item.actions)
173
173
  ? item.actions
@@ -209,9 +209,9 @@ export function parseOpenAiResponse(raw) {
209
209
  // Of the input tokens, how many the provider served from its prompt cache. This loop threads
210
210
  // state with previous_response_id and re-sends a growing warm prefix every turn, so most input on
211
211
  // a long session is a cache hit billed at a fraction of the full rate. Not reading it made every
212
- // cost line materially overstate the bill (#391).
212
+ // cost line materially overstate the bill.
213
213
  const usageCachedInput = optionalNumber(asRecord(usageRecord.input_tokens_details).cached_tokens);
214
- // GPT-5.6+ bills cache WRITES (1.25x input) and reports them here; older models omit the field.
214
+ // GPT-5.6+ bills cache writes (1.25x input) and reports them here; older models omit the field.
215
215
  const usageCacheWriteInput = optionalNumber(asRecord(usageRecord.input_tokens_details).cache_write_tokens);
216
216
  const usage = usageInput === undefined && usageOutput === undefined
217
217
  ? undefined
@@ -253,12 +253,12 @@ function sharedRequestFields(ctx) {
253
253
  // instructions, a provider that does not fully retain prior state can drift
254
254
  // into asking the operator what to do.
255
255
  instructions: ctx.instructions,
256
- // The Responses API `computer` tool takes no display/environment fields — the model infers
256
+ // The Responses API `computer` tool takes no display/environment fields; the model infers
257
257
  // resolution from the screenshots it is sent. (Sending display_* returns a 400
258
258
  // "Unknown parameter tools[0].display_width", confirmed against the live API 2026-06.)
259
259
  tools: [{ type: "computer" }],
260
260
  truncation: "auto",
261
- // `summary` asks for the provider-SANCTIONED reasoning summary items (#427) — the
261
+ // `summary` asks for the provider-sanctioned reasoning summary items; the
262
262
  // capture side never scrapes or reconstructs raw chain-of-thought. Parsed by
263
263
  // parseOpenAiResponse into turn.reasoning; the loop records them as redacted
264
264
  // `kind: "reasoning"` trace items.
@@ -267,6 +267,7 @@ function sharedRequestFields(ctx) {
267
267
  ...(ctx.reasoningSummary === undefined ? {} : { summary: ctx.reasoningSummary }),
268
268
  },
269
269
  ...(ctx.safetyIdentifier === undefined ? {} : { safety_identifier: ctx.safetyIdentifier }),
270
+ ...(ctx.stateless === true ? { store: false, include: ["reasoning.encrypted_content"] } : {}),
270
271
  };
271
272
  }
272
273
  /**
@@ -284,32 +285,35 @@ export function buildInitialRequest(ctx, screenshot) {
284
285
  const maxOutputTokens = Math.min(ctx.maxOutputTokens ?? FIRST_TURN_OUTPUT_LIMIT, FIRST_TURN_OUTPUT_LIMIT);
285
286
  return {
286
287
  ...sharedRequestFields({ ...ctx, maxOutputTokens }),
287
- input: [
288
- {
289
- role: "user",
290
- content: [
291
- { type: "input_text", text: ctx.instructions },
292
- ...(screenshot === undefined
293
- ? []
294
- : [
295
- {
296
- type: "input_image",
297
- image_url: `data:image/png;base64,${screenshot.toString("base64")}`,
298
- },
299
- ]),
300
- ],
301
- },
302
- ],
288
+ input: [openingMessage(ctx.instructions, screenshot)],
303
289
  };
304
290
  }
291
+ /** One input message, read as the words of `sender`: the user, the developer, or the model itself. */
292
+ export function inputMessage(sender, content) {
293
+ return { role: sender, content: [...content] };
294
+ }
295
+ /** The first request's only input item: the instructions and, when there is one, the first screen. */
296
+ export function openingMessage(instructions, screenshot) {
297
+ return inputMessage("user", [
298
+ { type: "input_text", text: instructions },
299
+ ...(screenshot === undefined
300
+ ? []
301
+ : [
302
+ {
303
+ type: "input_image",
304
+ image_url: `data:image/png;base64,${screenshot.toString("base64")}`,
305
+ },
306
+ ]),
307
+ ]);
308
+ }
305
309
  /**
306
310
  * Build one computer_call_output for a pending call id, carrying the latest
307
311
  * screenshot as an inline data URL. Acknowledged safety checks (if any) are
308
312
  * echoed back so the model can proceed past a check the harness approved.
309
313
  *
310
314
  * The screenshot param is `Buffer | undefined` because CuaObservation.screenshot is now
311
- * optional (a non-vision executor omits it). This provider is a VISION model (it sets
312
- * requiresFrame), so a missing frame is a hard error here — defense-in-depth: the loop's
315
+ * optional (a non-vision executor omits it). This provider is a vision model (it sets
316
+ * requiresFrame), so a missing frame is a hard error here as defense-in-depth: the loop's
313
317
  * per-turn requiresFrame guard already fails closed before this is reached, but throwing keeps
314
318
  * the mapper self-validating and isolable.
315
319
  */
@@ -335,19 +339,17 @@ export function buildCallOutput(callId, screenshot, acknowledged) {
335
339
  : {}),
336
340
  };
337
341
  }
338
- // Turn an optional context-hint string into an input item array (or empty).
339
- function hintItems(contextHint) {
340
- return contextHint
341
- ? [{ role: "user", content: [{ type: "input_text", text: contextHint }] }]
342
- : [];
342
+ /** An optional context hint as input items (none when there is no hint). */
343
+ export function hintItems(contextHint) {
344
+ return contextHint ? [inputMessage("user", [{ type: "input_text", text: contextHint }])] : [];
343
345
  }
344
346
  /**
345
347
  * Build a continuation request body. Two modes:
346
348
  * - default: thread server-side state via previous_response_id and send only the
347
349
  * new call outputs (plus an optional hint).
348
- * - explicit-context (ZDR): no previous_response_id; the prior output items are
349
- * re-sent inline ahead of the new call outputs so the model has full context
350
- * without the server retaining any.
350
+ * - explicit-context (ZDR): no previous_response_id; the carried conversation
351
+ * (openai-context.ts) is sent inline ahead of the new call outputs, so the model
352
+ * has the session without the server retaining any.
351
353
  */
352
354
  export function buildContinuationRequest(args) {
353
355
  const { ctx, previousResponseId, callOutputs, contextHint, explicitContextItems } = args;