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.
- package/ARCHITECTURE.md +22 -17
- package/CHANGELOG.md +14 -0
- package/CONTEXT.md +51 -44
- package/README.md +145 -172
- package/SECURITY.md +16 -26
- package/TELEMETRY.md +8 -6
- package/dist/actors/affordance.d.ts +4 -4
- package/dist/actors/affordance.js +12 -12
- package/dist/actors/agent-session.d.ts +2 -2
- package/dist/actors/agent-session.js +7 -7
- package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
- package/dist/actors/codex/app-server-actor-trace.js +1 -1
- package/dist/actors/codex/app-server-ui.js +1 -1
- package/dist/actors/codex/codex-admission.d.ts +91 -0
- package/dist/actors/codex/codex-admission.js +150 -0
- package/dist/actors/codex/restricted-executable.d.ts +4 -4
- package/dist/actors/codex/restricted-executable.js +8 -8
- package/dist/actors/codex/restricted-launch.d.ts +2 -1
- package/dist/actors/codex/restricted-launch.js +1 -1
- package/dist/actors/codex/restricted-participant.js +8 -6
- package/dist/actors/codex/restricted-policy.d.ts +2 -2
- package/dist/actors/codex/restricted-policy.js +2 -2
- package/dist/actors/codex/restricted-session.d.ts +2 -2
- package/dist/actors/codex/restricted-session.js +10 -5
- package/dist/actors/computer-use/actor.d.ts +16 -16
- package/dist/actors/computer-use/actor.js +2 -2
- package/dist/actors/computer-use/admission-limit.d.ts +1 -1
- package/dist/actors/computer-use/admission-limit.js +1 -1
- package/dist/actors/computer-use/loop/actions.d.ts +3 -3
- package/dist/actors/computer-use/loop/actions.js +10 -10
- package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
- package/dist/actors/computer-use/loop/backstop.js +14 -12
- package/dist/actors/computer-use/loop/ending.d.ts +5 -5
- package/dist/actors/computer-use/loop/ending.js +7 -7
- package/dist/actors/computer-use/loop/observation.d.ts +2 -2
- package/dist/actors/computer-use/loop/observation.js +9 -9
- package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
- package/dist/actors/computer-use/loop/provider-call.js +1 -1
- package/dist/actors/computer-use/loop/session.js +3 -3
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +1 -1
- package/dist/actors/computer-use/loop/trace.js +9 -8
- package/dist/actors/computer-use/loop/types.d.ts +25 -23
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/openai-context.d.ts +37 -0
- package/dist/actors/computer-use/openai-context.js +214 -0
- package/dist/actors/computer-use/openai-provider.d.ts +11 -8
- package/dist/actors/computer-use/openai-provider.js +45 -34
- package/dist/actors/computer-use/openai-requests.d.ts +36 -10
- package/dist/actors/computer-use/openai-requests.js +82 -15
- package/dist/actors/computer-use/openai-wire.d.ts +19 -7
- package/dist/actors/computer-use/openai-wire.js +36 -34
- package/dist/actors/contract.d.ts +78 -43
- package/dist/actors/contract.js +29 -23
- package/dist/actors/local-agent/claude-session.d.ts +1 -1
- package/dist/actors/local-agent/claude-session.js +10 -9
- package/dist/actors/local-agent/cli.d.ts +8 -6
- package/dist/actors/local-agent/cli.js +24 -28
- package/dist/actors/local-agent/readiness.d.ts +2 -2
- package/dist/actors/local-agent/readiness.js +4 -4
- package/dist/actors/reasoning-effort.js +6 -6
- package/dist/actors/registry.d.ts +10 -10
- package/dist/actors/registry.js +18 -17
- package/dist/actors/scripted-browser/actor.d.ts +8 -8
- package/dist/actors/scripted-browser/actor.js +16 -16
- package/dist/actors/scripted-browser/browser-command.js +1 -1
- package/dist/actors/scripted-browser/steps.js +1 -1
- package/dist/actors/scripted-browser/types.d.ts +1 -1
- package/dist/actors/stop-conditions.d.ts +1 -1
- package/dist/analysis/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- package/dist/analysis/service.js +5 -5
- package/dist/cli/commands/analyze.js +19 -16
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +54 -33
- package/dist/cli/commands/feedback.js +20 -21
- package/dist/cli/commands/lab-format.d.ts +5 -4
- package/dist/cli/commands/lab-format.js +35 -23
- package/dist/cli/commands/lab-route-computer-use.js +6 -7
- package/dist/cli/commands/lab-route-preview.js +4 -3
- package/dist/cli/commands/lab-route-shared-world.js +3 -3
- package/dist/cli/commands/lab-run.js +10 -11
- package/dist/cli/commands/lab-scorer.d.ts +2 -2
- package/dist/cli/commands/lab-scorer.js +1 -1
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.js +65 -0
- package/dist/cli/commands/observe.js +147 -108
- package/dist/cli/commands/run-command.d.ts +10 -0
- package/dist/cli/commands/run-command.js +85 -0
- package/dist/cli/commands/runs.js +137 -138
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.js +26 -21
- package/dist/cli/commands/study.d.ts +3 -0
- package/dist/cli/commands/study.js +182 -0
- package/dist/cli/commands/tui.d.ts +4 -4
- package/dist/cli/commands/tui.js +21 -21
- package/dist/cli/commands/watch.js +60 -75
- package/dist/cli/deprecations.d.ts +18 -0
- package/dist/cli/deprecations.js +48 -0
- package/dist/cli/doctor.d.ts +15 -5
- package/dist/cli/doctor.js +103 -48
- package/dist/cli/first-run-path.d.ts +12 -10
- package/dist/cli/first-run-path.js +30 -28
- package/dist/cli/io.d.ts +41 -6
- package/dist/cli/io.js +97 -22
- package/dist/cli/observer-follow.d.ts +2 -2
- package/dist/cli/observer-follow.js +5 -6
- package/dist/cli/orientation.d.ts +6 -3
- package/dist/cli/orientation.js +43 -39
- package/dist/cli/product-sentence.d.ts +6 -0
- package/dist/cli/product-sentence.js +6 -0
- package/dist/cli/program.d.ts +6 -1
- package/dist/cli/program.js +109 -40
- package/dist/cli/telemetry.d.ts +15 -15
- package/dist/cli/telemetry.js +48 -40
- package/dist/cli.js +1 -1
- package/dist/comms/capture-surface.d.ts +13 -12
- package/dist/comms/capture-surface.js +23 -22
- package/dist/comms/catch-host.d.ts +7 -7
- package/dist/comms/catch-host.js +14 -14
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.js +2 -2
- package/dist/comms/extract.js +2 -2
- package/dist/comms/fake-inbox.d.ts +2 -2
- package/dist/comms/fake-inbox.js +2 -2
- package/dist/comms/receiving-render.d.ts +1 -1
- package/dist/comms/receiving-render.js +2 -2
- package/dist/comms/sandbox-catch-script.d.ts +6 -6
- package/dist/comms/sandbox-catch-script.js +6 -6
- package/dist/comms/sandbox-catch.d.ts +36 -37
- package/dist/comms/sandbox-catch.js +34 -35
- package/dist/comms/setup.js +42 -8
- package/dist/comms/thread-evidence.d.ts +1 -1
- package/dist/comms/thread-evidence.js +6 -6
- package/dist/comms/types.d.ts +6 -6
- package/dist/comms/types.js +3 -3
- package/dist/evidence/frame-signature.d.ts +1 -1
- package/dist/evidence/frame-signature.js +4 -4
- package/dist/evidence/redaction.d.ts +3 -3
- package/dist/evidence/redaction.js +4 -4
- package/dist/feedback/draft.js +36 -78
- package/dist/feedback/export-bundle.js +1 -1
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +7 -8
- package/dist/feedback/feedback.d.ts +2 -2
- package/dist/feedback/feedback.js +21 -3
- package/dist/guest/chromium-text.js +2 -2
- package/dist/guest/desktop-native.d.ts +1 -1
- package/dist/guest/runtime.js +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +8 -6
- package/dist/keys/key-resolution.d.ts +5 -5
- package/dist/keys/key-resolution.js +23 -23
- package/dist/lab/adapter-extension.d.ts +7 -7
- package/dist/lab/adapter-extension.js +13 -36
- package/dist/lab/adapter-scorer-loader.d.ts +7 -7
- package/dist/lab/adapter-scorer-loader.js +32 -32
- package/dist/lab/composition-rules.js +42 -42
- package/dist/lab/config.js +65 -25
- package/dist/lab/deprecated-fields.d.ts +10 -0
- package/dist/lab/deprecated-fields.js +24 -0
- package/dist/lab/device-presets.d.ts +8 -8
- package/dist/lab/device-presets.js +11 -11
- package/dist/lab/discover.d.ts +13 -9
- package/dist/lab/discover.js +117 -57
- package/dist/lab/doctor.d.ts +10 -3
- package/dist/lab/doctor.js +47 -9
- package/dist/lab/init-templates.js +147 -147
- package/dist/lab/init.d.ts +1 -1
- package/dist/lab/init.js +41 -9
- package/dist/lab/keys.d.ts +2 -0
- package/dist/lab/keys.js +42 -8
- package/dist/lab/lab-deps.d.ts +7 -12
- package/dist/lab/parse/actors.js +9 -9
- package/dist/lab/parse/comms.js +5 -5
- package/dist/lab/parse/execution.js +13 -13
- package/dist/lab/parse/study-v3.d.ts +23 -0
- package/dist/lab/parse/study-v3.js +259 -0
- package/dist/lab/parse/subject-state.d.ts +7 -7
- package/dist/lab/parse/subject-state.js +16 -16
- package/dist/lab/parse/subject.js +28 -28
- package/dist/lab/parse/values.d.ts +1 -1
- package/dist/lab/parse/values.js +3 -3
- package/dist/lab/persona-resolve.d.ts +4 -4
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/plan-participants.d.ts +2 -2
- package/dist/lab/plan-types.d.ts +4 -4
- package/dist/lab/plan.d.ts +1 -7
- package/dist/lab/plan.js +10 -41
- package/dist/lab/preflight-probes.js +11 -11
- package/dist/lab/preflight-result.d.ts +2 -1
- package/dist/lab/preflight-result.js +5 -4
- package/dist/lab/preflight.d.ts +7 -5
- package/dist/lab/preflight.js +5 -5
- package/dist/lab/routing.d.ts +31 -25
- package/dist/lab/routing.js +60 -29
- package/dist/lab/run-lab-events.d.ts +0 -3
- package/dist/lab/run-lab-events.js +0 -6
- package/dist/lab/run-lab-homes.d.ts +22 -10
- package/dist/lab/run-lab-homes.js +5 -1
- package/dist/lab/run-lab-options.d.ts +1 -1
- package/dist/lab/run-lab-options.js +16 -13
- package/dist/lab/summary.d.ts +7 -6
- package/dist/lab/summary.js +10 -10
- package/dist/lab/tasks.d.ts +15 -15
- package/dist/lab/tasks.js +14 -14
- package/dist/lab/types.d.ts +101 -95
- package/dist/lab/types.js +2 -0
- package/dist/lab/validation.d.ts +13 -13
- package/dist/lab/validation.js +44 -42
- package/dist/lab/warnings.d.ts +10 -0
- package/dist/lab/warnings.js +61 -33
- package/dist/library-aliases.d.ts +56 -0
- package/dist/library-aliases.js +22 -0
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +6 -6
- package/dist/observer/data.d.ts +6 -6
- package/dist/observer/data.js +5 -4
- package/dist/observer/exposure.d.ts +1 -1
- package/dist/observer/exposure.js +11 -11
- package/dist/observer/http.js +1 -1
- package/dist/observer/library.d.ts +1 -1
- package/dist/observer/library.js +4 -2
- package/dist/observer/listen.js +5 -4
- package/dist/observer/render.d.ts +1 -1
- package/dist/observer/render.js +10 -5
- package/dist/observer/run-routes.d.ts +3 -3
- package/dist/observer/run-routes.js +1 -1
- package/dist/observer/serve.js +7 -3
- package/dist/observer/tunnel.js +1 -1
- package/dist/observer-app.html +4 -4
- package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
- package/dist/routes/computer-use/bundle-parts.js +15 -15
- package/dist/routes/computer-use/bundle.js +3 -3
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.js +14 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +4 -3
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
- package/dist/routes/computer-use/e2b-desktop/prepare.js +7 -7
- package/dist/routes/computer-use/e2b-desktop/start.js +9 -8
- package/dist/routes/computer-use/e2b-desktop/teardown.js +5 -4
- package/dist/routes/computer-use/external-comms.d.ts +1 -1
- package/dist/routes/computer-use/external-comms.js +1 -1
- package/dist/routes/computer-use/fanout-bundle.js +18 -18
- package/dist/routes/computer-use/fanout-records.js +10 -11
- package/dist/routes/computer-use/live-flush.d.ts +1 -1
- package/dist/routes/computer-use/live-flush.js +6 -6
- package/dist/routes/computer-use/live-phase.d.ts +4 -2
- package/dist/routes/computer-use/live-phase.js +6 -6
- package/dist/routes/computer-use/local-vm.js +1 -1
- package/dist/routes/computer-use/participant-desktop.d.ts +4 -4
- package/dist/routes/computer-use/participant-desktop.js +4 -4
- package/dist/routes/computer-use/participant-execution.d.ts +4 -4
- package/dist/routes/computer-use/participant-execution.js +9 -9
- package/dist/routes/computer-use/participant-model.d.ts +6 -0
- package/dist/routes/computer-use/participant-model.js +31 -13
- package/dist/routes/computer-use/participant-prompt.d.ts +11 -11
- package/dist/routes/computer-use/participant-prompt.js +6 -6
- package/dist/routes/computer-use/participant-runs.d.ts +7 -7
- package/dist/routes/computer-use/participant-runs.js +13 -13
- package/dist/routes/computer-use/plan.js +22 -22
- package/dist/routes/computer-use/preflight.js +21 -21
- package/dist/routes/computer-use/rerun-selection.js +1 -1
- package/dist/routes/computer-use/result.js +11 -11
- package/dist/routes/computer-use/route.d.ts +2 -1
- package/dist/routes/computer-use/route.js +15 -14
- package/dist/routes/computer-use/self-report.d.ts +7 -7
- package/dist/routes/computer-use/self-report.js +31 -31
- package/dist/routes/computer-use/setup.d.ts +1 -1
- package/dist/routes/computer-use/setup.js +17 -18
- package/dist/routes/computer-use/single-bundle.d.ts +7 -7
- package/dist/routes/computer-use/single-bundle.js +28 -30
- package/dist/routes/computer-use/subject-projection.d.ts +1 -1
- package/dist/routes/computer-use/subject-projection.js +6 -6
- package/dist/routes/computer-use/types.d.ts +40 -42
- package/dist/routes/computer-use/types.js +10 -10
- package/dist/routes/preview.d.ts +8 -2
- package/dist/routes/preview.js +8 -4
- package/dist/routes/scripted/bundle.d.ts +2 -2
- package/dist/routes/scripted/bundle.js +13 -12
- package/dist/routes/scripted/plan.d.ts +1 -1
- package/dist/routes/scripted/plan.js +9 -9
- package/dist/routes/scripted/result.js +5 -5
- package/dist/routes/scripted/route.js +5 -6
- package/dist/routes/scripted/scenario.js +2 -2
- package/dist/routes/scripted/setup.js +7 -7
- package/dist/routes/scripted/subject.js +1 -1
- package/dist/routes/scripted/surface-records.js +3 -3
- package/dist/routes/scripted/types.d.ts +3 -5
- package/dist/routes/scripted/types.js +1 -1
- package/dist/routes/shared-world/bundle-records.js +9 -8
- package/dist/routes/shared-world/bundle.d.ts +5 -5
- package/dist/routes/shared-world/bundle.js +40 -38
- package/dist/routes/shared-world/checkpoints.d.ts +1 -1
- package/dist/routes/shared-world/checkpoints.js +1 -1
- package/dist/routes/shared-world/comms.d.ts +5 -5
- package/dist/routes/shared-world/comms.js +14 -14
- package/dist/routes/shared-world/external-public.d.ts +4 -3
- package/dist/routes/shared-world/external-public.js +16 -12
- package/dist/routes/shared-world/handoff.d.ts +7 -6
- package/dist/routes/shared-world/handoff.js +65 -57
- package/dist/routes/shared-world/lobby-code.d.ts +2 -2
- package/dist/routes/shared-world/lobby-code.js +9 -9
- package/dist/routes/shared-world/participant-specs.d.ts +7 -6
- package/dist/routes/shared-world/participant-specs.js +31 -24
- package/dist/routes/shared-world/plan.js +7 -7
- package/dist/routes/shared-world/provenance.d.ts +2 -2
- package/dist/routes/shared-world/provenance.js +2 -2
- package/dist/routes/shared-world/provisioned.js +14 -13
- package/dist/routes/shared-world/result.js +20 -21
- package/dist/routes/shared-world/route.js +23 -22
- package/dist/routes/shared-world/setup.d.ts +3 -3
- package/dist/routes/shared-world/setup.js +4 -4
- package/dist/routes/shared-world/types.d.ts +30 -28
- package/dist/routes/shared-world/types.js +4 -4
- package/dist/routes/terminal/adapter.d.ts +3 -3
- package/dist/routes/terminal/adapter.js +5 -5
- package/dist/routes/terminal/bundle.d.ts +3 -3
- package/dist/routes/terminal/bundle.js +22 -21
- package/dist/routes/terminal/credentials.d.ts +4 -4
- package/dist/routes/terminal/credentials.js +7 -7
- package/dist/routes/terminal/dry-run.js +4 -4
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +3 -3
- package/dist/routes/terminal/ledger.js +14 -14
- package/dist/routes/terminal/live-finish.js +3 -3
- package/dist/routes/terminal/live-sandbox.js +12 -13
- package/dist/routes/terminal/persona.js +1 -1
- package/dist/routes/terminal/plan.js +11 -11
- package/dist/routes/terminal/recorder.js +2 -2
- package/dist/routes/terminal/result.js +8 -8
- package/dist/routes/terminal/route.js +6 -7
- package/dist/routes/terminal/sandbox.d.ts +1 -1
- package/dist/routes/terminal/sandbox.js +1 -1
- package/dist/routes/terminal/session.js +8 -7
- package/dist/routes/terminal/token-usage.d.ts +1 -1
- package/dist/routes/terminal/token-usage.js +7 -8
- package/dist/routes/terminal/trace.d.ts +2 -2
- package/dist/routes/terminal/trace.js +2 -2
- package/dist/routes/terminal/types.d.ts +26 -28
- package/dist/routes/terminal/types.js +3 -3
- package/dist/run/bundle-shape.js +3 -3
- package/dist/run/bundle.d.ts +46 -46
- package/dist/run/bundle.js +2 -1
- package/dist/run/cost-summary.js +3 -3
- package/dist/run/costs.js +7 -1
- package/dist/run/detail.d.ts +6 -6
- package/dist/run/detail.js +4 -4
- package/dist/run/dry-run-inputs.js +1 -1
- package/dist/run/dry-run.js +18 -18
- package/dist/run/judge.d.ts +19 -13
- package/dist/run/judge.js +18 -8
- package/dist/run/paths.d.ts +1 -1
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +11 -6
- package/dist/run/pricing.js +20 -13
- package/dist/run/projection.d.ts +14 -14
- package/dist/run/projection.js +15 -15
- package/dist/run/reclaim.js +2 -2
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-index.d.ts +8 -6
- package/dist/run/run-index.js +15 -16
- package/dist/run/run-not-found.d.ts +5 -0
- package/dist/run/run-not-found.js +15 -0
- package/dist/run/run.d.ts +5 -4
- package/dist/run/run.js +1 -1
- package/dist/run/sandbox-receipts.d.ts +2 -2
- package/dist/run/sandbox-receipts.js +3 -3
- package/dist/run/shared-world-evidence.d.ts +36 -35
- package/dist/run/shared-world-evidence.js +4 -4
- package/dist/run/shared-world-shape.d.ts +1 -1
- package/dist/run/shared-world-shape.js +6 -6
- package/dist/run/stats.d.ts +12 -6
- package/dist/run/stats.js +116 -58
- package/dist/run/status.d.ts +8 -29
- package/dist/run/status.js +5 -27
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +6 -6
- package/dist/run/study-provenance.d.ts +47 -0
- package/dist/run/study-provenance.js +63 -0
- package/dist/run/study-result.d.ts +16 -0
- package/dist/run/study-result.js +9 -0
- package/dist/run/text.d.ts +2 -0
- package/dist/run/text.js +4 -0
- package/dist/run-lab.d.ts +7 -7
- package/dist/run-lab.js +1 -3
- package/dist/study/convert.d.ts +33 -0
- package/dist/study/convert.js +432 -0
- package/dist/study/field-paths.d.ts +12 -0
- package/dist/study/field-paths.js +126 -0
- package/dist/study/files.d.ts +26 -0
- package/dist/study/files.js +43 -0
- package/dist/study/migrate.d.ts +48 -0
- package/dist/study/migrate.js +408 -0
- package/dist/study/owned-files.d.ts +38 -0
- package/dist/study/owned-files.js +182 -0
- package/dist/subject/clone.d.ts +1 -1
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +2 -2
- package/dist/subject/local-tree-archive.js +1 -1
- package/dist/subject/local-tree.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +1 -1
- package/dist/subject/runtime.js +8 -9
- package/dist/subject/serve.d.ts +1 -1
- package/dist/subject/serve.js +3 -3
- package/dist/subject/state.d.ts +1 -1
- package/dist/subject/steps.d.ts +5 -5
- package/dist/subject/steps.js +4 -4
- package/dist/substrates/command-failure.d.ts +3 -3
- package/dist/substrates/command-failure.js +3 -3
- package/dist/substrates/detached.d.ts +6 -6
- package/dist/substrates/detached.js +7 -7
- package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
- package/dist/substrates/e2b/cdp-probe.js +14 -17
- package/dist/substrates/e2b/desktop-browser.d.ts +2 -2
- package/dist/substrates/e2b/desktop-browser.js +8 -8
- package/dist/substrates/e2b/desktop-cdp.d.ts +9 -9
- package/dist/substrates/e2b/desktop-cdp.js +8 -8
- package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
- package/dist/substrates/e2b/desktop-executor.js +1 -1
- package/dist/substrates/e2b/desktop-geometry.d.ts +3 -3
- package/dist/substrates/e2b/desktop-geometry.js +7 -7
- package/dist/substrates/e2b/desktop-media.d.ts +1 -1
- package/dist/substrates/e2b/desktop-media.js +1 -1
- package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
- package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
- package/dist/substrates/e2b/sandbox.d.ts +1 -1
- package/dist/substrates/e2b/sandbox.js +1 -1
- package/dist/substrates/e2b/sdk.d.ts +11 -11
- package/dist/substrates/e2b/sdk.js +6 -6
- package/dist/tui/actions.d.ts +1 -1
- package/dist/tui/actions.js +13 -13
- package/dist/tui/contract.d.ts +16 -16
- package/dist/tui/contract.js +10 -10
- package/dist/tui/launch.d.ts +4 -4
- package/dist/tui/launch.js +18 -19
- package/dist/tui/project.js +5 -5
- package/dist/tui-app.js +82 -82
- package/dist/verify/actor.d.ts +8 -8
- package/dist/verify/actor.js +36 -36
- package/dist/verify/artifacts.d.ts +2 -2
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/context-growth.d.ts +9 -0
- package/dist/verify/context-growth.js +62 -0
- package/dist/verify/costs.d.ts +6 -6
- package/dist/verify/costs.js +8 -8
- package/dist/verify/shared-world-concurrent.d.ts +2 -2
- package/dist/verify/shared-world-concurrent.js +79 -76
- package/dist/verify/shared-world.d.ts +2 -2
- package/dist/verify/shared-world.js +16 -16
- package/dist/verify/subject.d.ts +4 -4
- package/dist/verify/subject.js +18 -18
- package/dist/verify/verify.js +92 -43
- package/docs/README.md +25 -32
- package/docs/architecture/actor-contract.md +56 -87
- package/docs/architecture/desktop-sessions.md +7 -7
- package/docs/architecture/external-public-shared-world.md +61 -59
- package/docs/architecture/github-feedback-loop.md +1 -4
- package/docs/architecture/guest-desktop.md +2 -2
- package/docs/architecture/observer.md +34 -34
- package/docs/architecture/restricted-codex-analysis.md +34 -28
- package/docs/architecture/serve.md +34 -37
- package/docs/architecture/state-driven-executor.md +55 -58
- package/docs/architecture/task-protocol-support.md +5 -5
- package/docs/architecture/terminal-product-route.md +67 -107
- package/docs/contracts/README.md +24 -0
- package/docs/contracts/adapter-admission.md +3 -3
- package/docs/contracts/adapter-fixtures.md +2 -5
- package/docs/contracts/core.md +1 -3
- package/docs/contracts/errors.md +62 -0
- package/docs/contracts/feedback.md +8 -9
- package/docs/contracts/policy.md +7 -12
- package/docs/contracts/run-bundle.md +45 -44
- package/docs/contracts/schemas.md +421 -362
- package/docs/contracts/study-analysis.md +3 -3
- package/docs/contracts/study-costs.md +11 -7
- package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
- package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
- package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
- package/docs/principles/actor-fidelity.md +4 -4
- package/docs/principles/engineering.md +3 -3
- package/docs/principles/invariants-and-defaults.md +38 -38
- package/docs/principles/self-driving-harness.md +1 -5
- package/docs/principles/three-roles.md +1 -1
- package/docs/product/automatic-analysis.md +7 -7
- package/examples/participant/README.md +5 -5
- package/examples/participant/run.mjs +11 -10
- package/examples/scorer/README.md +3 -3
- package/examples/scorer/run.mjs +11 -12
- package/package.json +16 -17
- package/skills/humanish/SKILL.md +60 -58
- package/skills/humanish/agents/openai.yaml +1 -1
- package/AGENTS.md +0 -99
- package/CONTRIBUTING.md +0 -148
- package/dist/actors/codex/qualified-versions.d.ts +0 -72
- package/dist/actors/codex/qualified-versions.js +0 -132
- package/dist/cli/commands/lab.d.ts +0 -3
- package/dist/cli/commands/lab.js +0 -199
- package/dist/cli/renamed-options.d.ts +0 -11
- package/dist/cli/renamed-options.js +0 -18
- package/dist/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/docs/architecture/comms-inbox.md +0 -122
- package/docs/architecture/desktop-recording.md +0 -80
- package/docs/architecture/local-browser-runtime.md +0 -178
- package/docs/architecture/observer-review.md +0 -144
- package/docs/architecture/participant-media.md +0 -90
- package/docs/architecture/project-layout.md +0 -62
- package/docs/architecture/real-email-receiving.md +0 -136
- package/docs/assets/humanish-drawdb-hero.png +0 -0
- package/docs/assets/humanish-observer-hero.png +0 -0
- package/docs/goals/current.md +0 -207
- package/docs/product/lobby-trivia-3player-external-public.md +0 -77
- package/docs/product/open-source-install-experience.md +0 -240
- package/docs/ramp/README.md +0 -295
- package/docs/release/open-source-readiness.md +0 -222
- package/docs/release/public-readiness-standard.md +0 -210
- 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 {
|
|
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
|
|
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
|
|
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).
|
|
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
|
|
27
|
-
// lockstep with the bug while every live action was silently dropped
|
|
28
|
-
// that deterministic fixtures must derive from
|
|
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
|
|
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
|
-
// -
|
|
34
|
-
// -
|
|
35
|
-
// instructions and are
|
|
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
|
-
// -
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
449
|
-
// an absent request to "medium", and the trace has to say what produced it
|
|
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
|
|
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
|
-
|
|
465
|
-
|
|
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
|
-
/**
|
|
17
|
-
|
|
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
|
|
25
|
-
*
|
|
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
|
|
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
|
|
32
|
-
* is set aside, so the next request is the same one again
|
|
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 {
|
|
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.
|
|
22
|
+
return state.replies === 0;
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
|
-
* The
|
|
24
|
-
*
|
|
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
|
|
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:
|
|
34
|
-
...(
|
|
35
|
-
|
|
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
|
|
64
|
-
* is set aside, so the next request is the same one again
|
|
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.
|
|
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
|
|
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
|
|
47
|
-
* requiresFrame), so a missing frame is a hard error here
|
|
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:
|
|
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
|
|
64
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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
|
|
312
|
-
* requiresFrame), so a missing frame is a hard error here
|
|
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
|
-
|
|
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
|
|
349
|
-
*
|
|
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;
|