humanish 0.106.1 → 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 +38 -32
- package/CHANGELOG.md +28 -0
- package/CONTEXT.md +51 -41
- package/README.md +152 -174
- 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-client.js +2 -1
- package/dist/actors/codex/app-server-trace.d.ts +0 -1
- package/dist/actors/codex/app-server-trace.js +1 -3
- package/dist/actors/codex/app-server-ui.js +1 -1
- package/dist/actors/codex/app-server.js +2 -1
- package/dist/actors/codex/codex-admission.d.ts +91 -0
- package/dist/actors/codex/codex-admission.js +150 -0
- package/dist/actors/codex/protocol-compat.d.ts +27 -0
- package/dist/actors/codex/protocol-compat.js +357 -0
- package/dist/actors/codex/protocol-contract.d.ts +61 -0
- package/dist/actors/codex/protocol-contract.js +471 -0
- package/dist/actors/codex/restricted-executable.d.ts +28 -4
- package/dist/actors/codex/restricted-executable.js +104 -29
- package/dist/actors/codex/restricted-launch.d.ts +9 -2
- package/dist/actors/codex/restricted-launch.js +43 -4
- package/dist/actors/codex/restricted-notifications.d.ts +101 -0
- package/dist/actors/codex/restricted-notifications.js +277 -0
- package/dist/actors/codex/restricted-participant.d.ts +30 -0
- package/dist/actors/codex/restricted-participant.js +66 -6
- package/dist/actors/codex/restricted-policy.d.ts +11 -3
- package/dist/actors/codex/restricted-policy.js +2 -2
- package/dist/actors/codex/restricted-session.d.ts +16 -3
- package/dist/actors/codex/restricted-session.js +60 -22
- package/dist/actors/codex/restricted-transport.d.ts +29 -0
- package/dist/actors/codex/restricted-transport.js +139 -27
- package/dist/actors/codex/restricted-turn.d.ts +19 -4
- package/dist/actors/codex/restricted-turn.js +43 -30
- package/dist/actors/computer-use/actor.d.ts +17 -17
- package/dist/actors/computer-use/actor.js +6 -6
- 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 +15 -13
- package/dist/actors/computer-use/loop/ending.d.ts +7 -7
- package/dist/actors/computer-use/loop/ending.js +9 -9
- 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 +2 -2
- package/dist/actors/computer-use/loop/spend.js +4 -4
- package/dist/actors/computer-use/loop/trace.js +11 -10
- package/dist/actors/computer-use/loop/types.d.ts +37 -26
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/loop.js +4 -4
- 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 +12 -9
- package/dist/actors/computer-use/openai-provider.js +47 -36
- 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 +86 -49
- 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/journey.js +15 -4
- package/dist/actors/scripted-browser/steps.js +19 -1
- package/dist/actors/scripted-browser/types.d.ts +12 -2
- package/dist/actors/stop-conditions.d.ts +1 -1
- package/dist/actors/stop-conditions.js +1 -3
- package/dist/analysis/automatic-completion.d.ts +13 -8
- package/dist/analysis/automatic-completion.js +14 -8
- package/dist/analysis/automatic-config.d.ts +1 -1
- package/dist/analysis/automatic-config.js +2 -2
- package/dist/analysis/automatic.d.ts +10 -4
- package/dist/analysis/automatic.js +17 -13
- package/dist/analysis/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- package/dist/analysis/diagnostics.d.ts +23 -0
- package/dist/analysis/diagnostics.js +112 -0
- package/dist/analysis/evidence-sources.js +2 -2
- package/dist/analysis/evidence.js +6 -6
- package/dist/analysis/execute.d.ts +7 -1
- package/dist/analysis/execute.js +39 -12
- package/dist/analysis/job.d.ts +8 -5
- package/dist/analysis/job.js +15 -14
- package/dist/analysis/load.d.ts +1 -1
- package/dist/analysis/load.js +5 -5
- package/dist/analysis/provider.d.ts +9 -1
- package/dist/analysis/restricted-codex.d.ts +2 -0
- package/dist/analysis/restricted-codex.js +10 -1
- package/dist/analysis/service.d.ts +2 -0
- package/dist/analysis/service.js +35 -16
- package/dist/analysis/sharing.d.ts +2 -2
- package/dist/analysis/sharing.js +5 -5
- package/dist/analysis/store-executions.d.ts +5 -5
- package/dist/analysis/store-executions.js +12 -12
- package/dist/analysis/store.d.ts +4 -4
- package/dist/analysis/store.js +13 -13
- package/dist/cli/commands/analysis-signals.d.ts +2 -1
- package/dist/cli/commands/analysis-signals.js +4 -1
- package/dist/cli/commands/analyze.js +23 -18
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +62 -34
- 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.d.ts +0 -2
- package/dist/cli/commands/lab-route-computer-use.js +32 -21
- package/dist/cli/commands/lab-route-preview.d.ts +1 -3
- package/dist/cli/commands/lab-route-preview.js +7 -7
- package/dist/cli/commands/lab-route-run.d.ts +6 -4
- package/dist/cli/commands/lab-route-run.js +6 -2
- package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
- package/dist/cli/commands/lab-route-scripted.js +0 -1
- package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
- package/dist/cli/commands/lab-route-shared-world.js +3 -4
- package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
- package/dist/cli/commands/lab-route-terminal.js +0 -1
- package/dist/cli/commands/lab-run.js +84 -54
- package/dist/cli/commands/lab-scorer.d.ts +2 -4
- 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 +168 -107
- package/dist/cli/commands/run-command.d.ts +10 -0
- package/dist/cli/commands/run-command.js +85 -0
- package/dist/cli/commands/run-signals.d.ts +30 -0
- package/dist/cli/commands/run-signals.js +146 -0
- package/dist/cli/commands/runs.js +137 -136
- 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 +64 -77
- package/dist/cli/deprecations.d.ts +18 -0
- package/dist/cli/deprecations.js +48 -0
- package/dist/cli/doctor.d.ts +18 -5
- package/dist/cli/doctor.js +111 -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 +46 -10
- package/dist/cli/io.js +109 -30
- 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 +112 -43
- package/dist/cli/telemetry.d.ts +17 -17
- package/dist/cli/telemetry.js +49 -41
- package/dist/cli.js +1 -1
- package/dist/comms/capture-surface.d.ts +14 -13
- package/dist/comms/capture-surface.js +23 -22
- package/dist/comms/catch-host.d.ts +8 -8
- package/dist/comms/catch-host.js +14 -14
- package/dist/comms/connections.js +4 -4
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.d.ts +27 -0
- package/dist/comms/external-evidence.js +93 -0
- 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/lease-store.js +7 -7
- 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 +4 -4
- package/dist/evidence/browser-hygiene.d.ts +1 -1
- package/dist/evidence/browser-hygiene.js +1 -1
- 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 +5 -5
- package/dist/evidence/secret-scrub.d.ts +9 -0
- package/dist/evidence/secret-scrub.js +96 -0
- package/dist/feedback/draft.js +41 -85
- package/dist/feedback/export-bundle.js +5 -5
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +16 -17
- package/dist/feedback/feedback.d.ts +3 -3
- 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 +14 -15
- package/dist/index.js +10 -11
- package/dist/keys/key-resolution.d.ts +7 -5
- package/dist/keys/key-resolution.js +40 -38
- package/dist/lab/adapter-extension.d.ts +35 -13
- package/dist/lab/adapter-extension.js +50 -134
- package/dist/lab/adapter-scorer-loader.d.ts +32 -12
- package/dist/lab/adapter-scorer-loader.js +56 -32
- package/dist/lab/composition-rules.js +58 -58
- package/dist/lab/config.js +85 -43
- package/dist/lab/deprecated-fields.d.ts +10 -0
- package/dist/lab/deprecated-fields.js +24 -0
- package/dist/lab/device-presets.d.ts +10 -10
- package/dist/lab/device-presets.js +11 -11
- package/dist/lab/discover.d.ts +13 -9
- package/dist/lab/discover.js +118 -60
- package/dist/lab/doctor.d.ts +53 -11
- package/dist/lab/doctor.js +193 -47
- package/dist/lab/init-plan.js +1 -3
- 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 +43 -9
- package/dist/lab/lab-deps.d.ts +80 -0
- package/dist/lab/lab-deps.js +4 -0
- package/dist/lab/parse/actors.js +17 -16
- package/dist/lab/parse/comms.js +8 -7
- package/dist/lab/parse/execution.js +15 -14
- 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 +18 -17
- package/dist/lab/parse/subject.js +30 -29
- package/dist/lab/parse/values.d.ts +1 -2
- package/dist/lab/parse/values.js +3 -6
- package/dist/lab/persona-resolve.d.ts +7 -7
- package/dist/lab/persona-resolve.js +8 -8
- package/dist/lab/persona.js +1 -3
- package/dist/lab/plan-base.d.ts +0 -2
- package/dist/lab/plan-base.js +6 -4
- package/dist/lab/plan-participants.d.ts +7 -7
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +26 -8
- package/dist/lab/plan.d.ts +4 -18
- package/dist/lab/plan.js +24 -79
- package/dist/lab/preflight-probes.js +11 -11
- package/dist/lab/preflight-result.d.ts +2 -1
- package/dist/lab/preflight-result.js +5 -6
- package/dist/lab/preflight.d.ts +7 -8
- package/dist/lab/preflight.js +6 -6
- package/dist/lab/requirements.d.ts +20 -0
- package/dist/lab/requirements.js +54 -0
- package/dist/lab/route-inputs.d.ts +23 -12
- package/dist/lab/route-inputs.js +48 -51
- package/dist/lab/routing.d.ts +42 -41
- package/dist/lab/routing.js +66 -68
- package/dist/lab/run-lab-events.d.ts +3 -11
- package/dist/lab/run-lab-events.js +2 -16
- package/dist/lab/run-lab-homes.d.ts +76 -0
- package/dist/lab/run-lab-homes.js +7 -0
- package/dist/lab/run-lab-options.d.ts +12 -66
- package/dist/lab/run-lab-options.js +58 -285
- package/dist/lab/summary.d.ts +15 -9
- package/dist/lab/summary.js +24 -17
- package/dist/lab/tasks.d.ts +15 -15
- package/dist/lab/tasks.js +14 -14
- package/dist/lab/types.d.ts +201 -195
- package/dist/lab/types.js +2 -0
- package/dist/lab/validation.d.ts +21 -21
- package/dist/lab/validation.js +61 -59
- package/dist/lab/warnings.d.ts +10 -0
- package/dist/lab/warnings.js +70 -41
- package/dist/library-aliases.d.ts +56 -0
- package/dist/library-aliases.js +22 -0
- package/dist/observer/artifact.d.ts +2 -2
- package/dist/observer/artifact.js +9 -9
- package/dist/observer/data.d.ts +6 -6
- package/dist/observer/data.js +7 -6
- 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 +12 -7
- package/dist/observer/run-routes.d.ts +4 -4
- package/dist/observer/run-routes.js +6 -6
- package/dist/observer/serve.d.ts +17 -0
- package/dist/observer/serve.js +41 -6
- 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 +24 -17
- package/dist/routes/computer-use/bundle.d.ts +4 -11
- package/dist/routes/computer-use/bundle.js +12 -18
- package/dist/routes/computer-use/diagnostics.d.ts +1 -1
- package/dist/routes/computer-use/diagnostics.js +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +11 -11
- package/dist/routes/computer-use/e2b-desktop/comms.js +24 -27
- package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/desktop.js +8 -11
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +16 -15
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +20 -19
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
- package/dist/routes/computer-use/e2b-desktop/prepare.js +40 -43
- package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/start.js +32 -30
- package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
- package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
- package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/teardown.js +33 -20
- package/dist/routes/computer-use/external-comms.d.ts +4 -4
- package/dist/routes/computer-use/external-comms.js +19 -43
- package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
- package/dist/routes/computer-use/fanout-bundle.js +38 -42
- package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +33 -28
- package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
- package/dist/routes/computer-use/in-process-desktop.js +3 -9
- package/dist/routes/computer-use/live-flush.d.ts +7 -5
- package/dist/routes/computer-use/live-flush.js +20 -28
- package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +4 -2
- package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +17 -16
- package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
- package/dist/routes/computer-use/local-tree-pack.js +4 -5
- package/dist/routes/computer-use/local-vm.d.ts +11 -8
- package/dist/routes/computer-use/local-vm.js +40 -67
- package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
- package/dist/routes/computer-use/participant-desktop.js +5 -25
- package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +11 -11
- package/dist/routes/computer-use/{lanes.js → participant-execution.js} +39 -26
- package/dist/routes/computer-use/participant-facts.d.ts +7 -1
- package/dist/routes/computer-use/participant-facts.js +12 -1
- package/dist/routes/computer-use/participant-model.d.ts +25 -11
- package/dist/routes/computer-use/participant-model.js +76 -34
- package/dist/routes/computer-use/participant-prompt.d.ts +13 -13
- package/dist/routes/computer-use/participant-prompt.js +8 -8
- package/dist/routes/computer-use/participant-runs.d.ts +11 -11
- package/dist/routes/computer-use/participant-runs.js +18 -18
- package/dist/routes/computer-use/plan.d.ts +21 -29
- package/dist/routes/computer-use/plan.js +70 -78
- package/dist/routes/computer-use/preflight.d.ts +3 -5
- package/dist/routes/computer-use/preflight.js +40 -36
- package/dist/routes/computer-use/rerun-selection.js +11 -7
- package/dist/routes/computer-use/result.d.ts +1 -1
- package/dist/routes/computer-use/result.js +48 -38
- package/dist/routes/computer-use/route.d.ts +5 -5
- package/dist/routes/computer-use/route.js +36 -33
- package/dist/routes/computer-use/self-report.d.ts +8 -8
- package/dist/routes/computer-use/self-report.js +33 -33
- package/dist/routes/computer-use/setup.d.ts +9 -15
- package/dist/routes/computer-use/setup.js +106 -83
- package/dist/routes/computer-use/single-bundle.d.ts +13 -16
- package/dist/routes/computer-use/single-bundle.js +46 -53
- package/dist/routes/computer-use/subject-projection.d.ts +6 -8
- package/dist/routes/computer-use/subject-projection.js +24 -23
- package/dist/routes/computer-use/types.d.ts +195 -238
- package/dist/routes/computer-use/types.js +21 -13
- package/dist/routes/preview.d.ts +8 -2
- package/dist/routes/preview.js +8 -5
- package/dist/routes/scripted/bundle.d.ts +5 -8
- package/dist/routes/scripted/bundle.js +23 -27
- package/dist/routes/scripted/plan.d.ts +6 -8
- package/dist/routes/scripted/plan.js +15 -13
- package/dist/routes/scripted/result.d.ts +4 -1
- package/dist/routes/scripted/result.js +15 -11
- package/dist/routes/scripted/route.js +15 -17
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +3 -3
- package/dist/routes/scripted/setup.d.ts +3 -2
- package/dist/routes/scripted/setup.js +27 -26
- package/dist/routes/scripted/subject.d.ts +8 -3
- package/dist/routes/scripted/subject.js +10 -6
- package/dist/routes/scripted/surface-records.js +4 -4
- package/dist/routes/scripted/surface-sessions.d.ts +2 -2
- package/dist/routes/scripted/surface-sessions.js +4 -4
- package/dist/routes/scripted/types.d.ts +21 -40
- package/dist/routes/scripted/types.js +2 -3
- package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +17 -16
- package/dist/routes/shared-world/bundle.d.ts +7 -7
- package/dist/routes/shared-world/bundle.js +60 -62
- package/dist/routes/shared-world/checkpoints.d.ts +5 -5
- package/dist/routes/shared-world/checkpoints.js +5 -5
- package/dist/routes/shared-world/comms.d.ts +8 -7
- package/dist/routes/shared-world/comms.js +38 -51
- package/dist/routes/shared-world/external-public.d.ts +6 -5
- package/dist/routes/shared-world/external-public.js +28 -25
- package/dist/routes/shared-world/handoff.d.ts +10 -9
- package/dist/routes/shared-world/handoff.js +89 -81
- package/dist/routes/shared-world/lobby-code.d.ts +7 -7
- package/dist/routes/shared-world/lobby-code.js +22 -22
- package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +15 -12
- package/dist/routes/shared-world/{seats.js → participant-specs.js} +65 -63
- package/dist/routes/shared-world/plan.d.ts +2 -6
- package/dist/routes/shared-world/plan.js +8 -9
- package/dist/routes/shared-world/provenance.d.ts +4 -4
- package/dist/routes/shared-world/provenance.js +4 -4
- package/dist/routes/shared-world/provisioned.d.ts +3 -2
- package/dist/routes/shared-world/provisioned.js +55 -48
- package/dist/routes/shared-world/result.js +47 -36
- package/dist/routes/shared-world/route.js +54 -57
- package/dist/routes/shared-world/setup.d.ts +6 -5
- package/dist/routes/shared-world/setup.js +16 -18
- package/dist/routes/shared-world/types.d.ts +70 -141
- package/dist/routes/shared-world/types.js +5 -5
- package/dist/routes/terminal/adapter.d.ts +10 -10
- package/dist/routes/terminal/adapter.js +32 -129
- package/dist/routes/terminal/bundle.d.ts +10 -15
- package/dist/routes/terminal/bundle.js +43 -52
- package/dist/routes/terminal/credentials.d.ts +4 -4
- package/dist/routes/terminal/credentials.js +20 -20
- package/dist/routes/terminal/dry-run.d.ts +1 -1
- package/dist/routes/terminal/dry-run.js +13 -15
- package/dist/routes/terminal/encoding.d.ts +1 -1
- package/dist/routes/terminal/encoding.js +4 -4
- package/dist/routes/terminal/ledger.d.ts +8 -8
- package/dist/routes/terminal/ledger.js +22 -22
- package/dist/routes/terminal/live-finish.d.ts +1 -2
- package/dist/routes/terminal/live-finish.js +24 -23
- package/dist/routes/terminal/live-sandbox.d.ts +3 -2
- package/dist/routes/terminal/live-sandbox.js +31 -32
- package/dist/routes/terminal/participant-text.d.ts +23 -0
- package/dist/routes/terminal/participant-text.js +165 -0
- package/dist/routes/terminal/persona.js +1 -1
- package/dist/routes/terminal/plan.d.ts +2 -6
- package/dist/routes/terminal/plan.js +23 -19
- package/dist/routes/terminal/recorder.d.ts +6 -1
- package/dist/routes/terminal/recorder.js +12 -4
- package/dist/routes/terminal/result.js +12 -12
- package/dist/routes/terminal/route.js +30 -31
- package/dist/routes/terminal/runtime.d.ts +3 -2
- package/dist/routes/terminal/runtime.js +3 -3
- package/dist/routes/terminal/sandbox.d.ts +4 -4
- package/dist/routes/terminal/sandbox.js +10 -10
- package/dist/routes/terminal/session.js +22 -19
- package/dist/routes/terminal/token-usage.d.ts +1 -1
- package/dist/routes/terminal/token-usage.js +10 -11
- package/dist/routes/terminal/trace.d.ts +7 -10
- package/dist/routes/terminal/trace.js +11 -66
- package/dist/routes/terminal/types.d.ts +104 -114
- package/dist/routes/terminal/types.js +12 -7
- package/dist/run/active-runs.d.ts +13 -0
- package/dist/run/active-runs.js +12 -0
- package/dist/run/bundle-shape.d.ts +2 -1
- package/dist/run/bundle-shape.js +7 -7
- package/dist/run/bundle.d.ts +99 -92
- package/dist/run/bundle.js +10 -8
- package/dist/run/cost-summary.js +6 -5
- package/dist/run/costs.d.ts +6 -6
- package/dist/run/costs.js +17 -11
- package/dist/run/detail.d.ts +9 -9
- package/dist/run/detail.js +10 -10
- package/dist/run/dry-run-inputs.js +1 -1
- package/dist/run/dry-run.js +23 -30
- package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
- package/dist/run/{study-files.js → evidence-files.js} +5 -5
- package/dist/run/feedback-shape.js +1 -1
- package/dist/run/judge.d.ts +34 -16
- package/dist/run/judge.js +41 -14
- package/dist/run/locate.d.ts +2 -0
- package/dist/run/locate.js +3 -1
- package/dist/run/outcomes.d.ts +3 -3
- package/dist/run/outcomes.js +3 -3
- package/dist/run/participant-records.d.ts +2 -2
- package/dist/run/participant-records.js +2 -2
- package/dist/run/paths.d.ts +1 -1
- package/dist/run/paths.js +2 -2
- package/dist/run/pricing.d.ts +30 -15
- package/dist/run/pricing.js +49 -30
- package/dist/run/projection.d.ts +27 -27
- package/dist/run/projection.js +23 -23
- package/dist/run/reclaim.d.ts +6 -0
- package/dist/run/reclaim.js +15 -5
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-index.d.ts +9 -7
- package/dist/run/run-index.js +24 -25
- 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 +7 -4
- package/dist/run/run.js +10 -6
- package/dist/run/sandbox-receipts.d.ts +5 -5
- package/dist/run/sandbox-receipts.js +6 -6
- package/dist/run/shared-world-evidence.d.ts +67 -66
- package/dist/run/shared-world-evidence.js +4 -4
- package/dist/run/shared-world-shape.d.ts +3 -3
- package/dist/run/shared-world-shape.js +16 -16
- package/dist/run/stats.d.ts +17 -11
- package/dist/run/stats.js +124 -66
- package/dist/run/status.d.ts +21 -32
- package/dist/run/status.js +34 -33
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +29 -22
- 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/terminal-contract.d.ts +5 -5
- package/dist/run/terminal-contract.js +4 -4
- package/dist/run/text.d.ts +2 -0
- package/dist/run/text.js +4 -0
- package/dist/run/transient-comms-secrets.d.ts +5 -0
- package/dist/run/transient-comms-secrets.js +12 -0
- package/dist/run-lab.d.ts +40 -38
- package/dist/run-lab.js +42 -40
- 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 +2 -2
- package/dist/subject/desktop-cli.js +3 -3
- package/dist/subject/local-tree-archive.d.ts +1 -1
- package/dist/subject/local-tree-archive.js +5 -5
- package/dist/subject/local-tree.d.ts +3 -3
- package/dist/subject/local-tree.js +1 -1
- package/dist/subject/node-bootstrap.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +4 -4
- package/dist/subject/runtime.js +10 -11
- package/dist/subject/serve.d.ts +1 -1
- package/dist/subject/serve.js +4 -4
- package/dist/subject/state.d.ts +1 -1
- package/dist/subject/steps.d.ts +8 -8
- package/dist/subject/steps.js +7 -7
- 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 +11 -11
- package/dist/substrates/e2b/cdp-probe.js +15 -18
- package/dist/substrates/e2b/desktop-browser.d.ts +5 -5
- package/dist/substrates/e2b/desktop-browser.js +12 -12
- package/dist/substrates/e2b/desktop-cdp.d.ts +15 -15
- package/dist/substrates/e2b/desktop-cdp.js +11 -11
- 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 +6 -6
- package/dist/substrates/e2b/desktop-geometry.js +9 -9
- package/dist/substrates/e2b/desktop-media.d.ts +1 -1
- package/dist/substrates/e2b/desktop-media.js +3 -3
- 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 +2 -2
- package/dist/substrates/e2b/sdk.d.ts +11 -11
- package/dist/substrates/e2b/sdk.js +8 -8
- package/dist/substrates/local/runtime-host.d.ts +2 -0
- package/dist/substrates/local/runtime-host.js +6 -0
- package/dist/tui/actions.d.ts +8 -6
- package/dist/tui/actions.js +31 -22
- 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 +83 -83
- package/dist/verify/actor.d.ts +14 -14
- package/dist/verify/actor.js +45 -45
- package/dist/verify/artifacts.d.ts +3 -3
- package/dist/verify/artifacts.js +6 -6
- package/dist/verify/context-growth.d.ts +9 -0
- package/dist/verify/context-growth.js +62 -0
- package/dist/verify/costs.d.ts +7 -7
- package/dist/verify/costs.js +9 -9
- package/dist/verify/liveness.d.ts +1 -1
- package/dist/verify/liveness.js +4 -1
- package/dist/verify/rerun.d.ts +1 -1
- package/dist/verify/rerun.js +1 -1
- 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 +18 -18
- package/dist/verify/subject.d.ts +4 -4
- package/dist/verify/subject.js +18 -18
- package/dist/verify/verify.js +98 -49
- package/docs/README.md +26 -33
- package/docs/architecture/actor-contract.md +105 -98
- package/docs/architecture/desktop-sessions.md +14 -14
- package/docs/architecture/external-public-shared-world.md +66 -59
- package/docs/architecture/github-feedback-loop.md +1 -4
- package/docs/architecture/guest-desktop.md +2 -2
- package/docs/architecture/observer.md +37 -37
- package/docs/architecture/restricted-codex-analysis.md +70 -30
- package/docs/architecture/serve.md +34 -37
- package/docs/architecture/state-driven-executor.md +55 -59
- package/docs/architecture/task-protocol-support.md +7 -9
- package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +83 -115
- 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 +54 -51
- package/docs/contracts/schemas.md +505 -390
- package/docs/contracts/study-analysis.md +26 -2
- 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/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
- 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 +8 -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 +63 -60
- 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 -45
- package/dist/actors/codex/qualified-versions.js +0 -87
- package/dist/cli/commands/lab.d.ts +0 -3
- package/dist/cli/commands/lab.js +0 -193
- package/dist/deprecated.d.ts +0 -90
- package/dist/deprecated.js +0 -106
- package/dist/lab/bag-overrides.d.ts +0 -18
- package/dist/lab/bag-overrides.js +0 -121
- package/dist/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
- package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
- 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 -294
- 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
- /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
- /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
|
@@ -52,13 +52,13 @@ export class LiveTerminalSandbox {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
async acquire() {
|
|
55
|
-
const { plan,
|
|
55
|
+
const { plan, deps, now, sanitize, runtimeEnv, e2bApiKey, runPaths, metadata } = this.inputs;
|
|
56
56
|
const { warnings } = this.inputs;
|
|
57
57
|
const { recordLifecycle } = this.inputs.recorder;
|
|
58
58
|
const { requestTimeoutMs, sandboxTimeoutMs } = this;
|
|
59
|
-
// Declared egress allowlist, or undefined for the historical unrestricted default
|
|
59
|
+
// Declared egress allowlist, or undefined for the historical unrestricted default.
|
|
60
60
|
const egressAllow = plan.egressAllow;
|
|
61
|
-
const sandboxModule = await (
|
|
61
|
+
const sandboxModule = await (deps.desktopModule ?? loadE2BDesktopModule)();
|
|
62
62
|
this.module = sandboxModule;
|
|
63
63
|
await validatePreparedRunArtifactPaths(runPaths);
|
|
64
64
|
// No sandbox-global env in either mode. In openai-egress, only this host-side SDK request
|
|
@@ -99,7 +99,7 @@ export class LiveTerminalSandbox {
|
|
|
99
99
|
this.sandboxId = sandboxId;
|
|
100
100
|
this.createdAtMs = now();
|
|
101
101
|
await validatePreparedRunArtifactPaths(runPaths);
|
|
102
|
-
recordLifecycle("terminal-lab.sandbox.created", `E2B shell sandbox ${sandboxId} created with
|
|
102
|
+
recordLifecycle("terminal-lab.sandbox.created", `E2B shell sandbox ${sandboxId} created with allowlisted metadata and kill-on-timeout, and with no sandbox-wide environment variables.`);
|
|
103
103
|
const sandboxResources = await observeDesktopResources(sandbox);
|
|
104
104
|
this.resources = sandboxResources;
|
|
105
105
|
if ("reason" in sandboxResources) {
|
|
@@ -108,7 +108,7 @@ export class LiveTerminalSandbox {
|
|
|
108
108
|
// The allowlist is evidence: a reader of the ledger can see exactly what the participant was
|
|
109
109
|
// able to reach, without the ledger carrying any secret.
|
|
110
110
|
recordLifecycle("terminal-lab.egress.policy", egressAllow === undefined
|
|
111
|
-
? "Egress
|
|
111
|
+
? "Egress is unrestricted (no execution.egressAllow declared)."
|
|
112
112
|
: `Egress routing allowlist: ${egressAllow.length} declared host(s): ${egressAllow.join(", ")}; deny-all fallback. Domain routing is not strict destination isolation on shared infrastructure.`);
|
|
113
113
|
recordLifecycle("terminal-lab.runtime-auth", runtimeEnv.mode === "openai-egress"
|
|
114
114
|
? "Runtime auth openai-egress: raw key remains outside the sandbox in the api.openai.com HTTPS Authorization transform; Codex receives an inert CODEX_API_KEY placeholder and the default OpenAI endpoint. Every sandbox process, including bootstrap/setup, can spend via this proxy; no added routing restriction or provider spending limit."
|
|
@@ -130,8 +130,8 @@ export class LiveTerminalSandbox {
|
|
|
130
130
|
const { recordLifecycle } = this.inputs.recorder;
|
|
131
131
|
const { requestTimeoutMs } = this;
|
|
132
132
|
// --- Runtime bootstrap: no runtime env; openai-egress proxy capability is already available. ---
|
|
133
|
-
// The stock desktop needs Node/npm on PATH before npx can run Codex. Reuse a working
|
|
134
|
-
// installation or install the pinned official binary after checksum verification
|
|
133
|
+
// The stock desktop needs Node/npm on `PATH` before npx can run Codex. Reuse a working
|
|
134
|
+
// installation or install the pinned official binary after checksum verification.
|
|
135
135
|
// No raw runtime key touches this step; the egress proxy, when selected, is already available.
|
|
136
136
|
const bootstrapStartedAt = now();
|
|
137
137
|
let bootstrapError;
|
|
@@ -149,10 +149,10 @@ export class LiveTerminalSandbox {
|
|
|
149
149
|
}
|
|
150
150
|
const bootstrapDurationMs = Math.max(0, now() - bootstrapStartedAt);
|
|
151
151
|
recordLifecycle("terminal-lab.runtime.bootstrapped", bootstrapError
|
|
152
|
-
? `Runtime bootstrap
|
|
152
|
+
? `Runtime bootstrap failed after ${bootstrapDurationMs}ms: ${bootstrapError}. codex exec runs through npx and needs Node and npm, so the participant stops here instead of starting codex with no runtime.`
|
|
153
153
|
: `Runtime bootstrap ensured Node/npm present in ${bootstrapDurationMs}ms (codex exec runs via npx).`);
|
|
154
154
|
if (bootstrapError) {
|
|
155
|
-
// Fail closed as a structured
|
|
155
|
+
// Fail closed as a structured route status (never a raw throw): no codex exec is attempted
|
|
156
156
|
// without a proven runtime; this mirrors the exec-error status assignment below so the
|
|
157
157
|
// bundle and verify surface the failure the same way.
|
|
158
158
|
this.status = "failed";
|
|
@@ -185,7 +185,7 @@ export class LiveTerminalSandbox {
|
|
|
185
185
|
throw new Error(`Codex version mismatch: requested ${requested}, observed ${observed}.`);
|
|
186
186
|
}
|
|
187
187
|
runtime.versionStatus = "verified";
|
|
188
|
-
recordLifecycle("terminal-lab.runtime.version", `Codex requested ${runtime.requestedVersion}, observed ${observed}; exact version selected for execution. Model ${runtime.requestedModel ?? "
|
|
188
|
+
recordLifecycle("terminal-lab.runtime.version", `Codex requested ${runtime.requestedVersion}, observed ${observed}; exact version selected for execution. Model ${runtime.requestedModel ?? "unrecorded"} (${runtime.modelStatus}); reasoning effort ${runtime.requestedReasoningEffort ?? "runtime default (unobserved)"}.`);
|
|
189
189
|
}
|
|
190
190
|
catch (error) {
|
|
191
191
|
runtime.versionStatus = "failed";
|
|
@@ -205,15 +205,15 @@ export class LiveTerminalSandbox {
|
|
|
205
205
|
const { requestTimeoutMs } = this;
|
|
206
206
|
// --- Optional product setup (no runtime env), before the Codex exec. ---
|
|
207
207
|
// Same channel and same guarantees as the runtime bootstrap above: no runtime key touches it,
|
|
208
|
-
// and a failure fails the
|
|
209
|
-
// exists so a study can put the participant
|
|
208
|
+
// and a failure fails the run closed rather than handing the agent a half-built world. It
|
|
209
|
+
// exists so a study can put the participant in a prepared project: asking an agent what
|
|
210
210
|
// studies a project contains, in an empty directory, measures the lab and not the product
|
|
211
|
-
// (learned the hard way on the desktop
|
|
211
|
+
// (learned the hard way on the desktop route, labs/tui-self-study.yaml).
|
|
212
212
|
const install = plan.product.install;
|
|
213
213
|
if (install === undefined)
|
|
214
214
|
return true;
|
|
215
215
|
// An optional local file, put on the machine before the install runs, so a study can meet a
|
|
216
|
-
// build that is not published yet.
|
|
216
|
+
// build that is not published yet. It is read and checked here, so nothing is trusted from the
|
|
217
217
|
// manifest: this puts a file from the operator's disk onto a machine an autonomous agent is
|
|
218
218
|
// about to drive, so it stays inside the project, must be a regular file, and is size-capped.
|
|
219
219
|
let uploadAssignment = "";
|
|
@@ -239,8 +239,8 @@ export class LiveTerminalSandbox {
|
|
|
239
239
|
});
|
|
240
240
|
const bytes = await readFile(real);
|
|
241
241
|
await this.sandbox.files.write(destination, bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
|
|
242
|
-
// Inlined into the command string rather than passed as `envs`: the
|
|
243
|
-
//
|
|
242
|
+
// Inlined into the command string rather than passed as `envs`: the only call on this
|
|
243
|
+
// route that carries envs is the keyed codex exec, and that invariant is worth more than
|
|
244
244
|
// the convenience of a second envs channel.
|
|
245
245
|
uploadAssignment = `export HUMANISH_PRODUCT_UPLOAD=${shellQuote(destination)}; `;
|
|
246
246
|
recordLifecycle("terminal-lab.product.uploaded", `Uploaded ${info.size} bytes to the sandbox in ${Math.max(0, now() - uploadStartedAt)}ms (no runtime env; declared egress auth may already be available).`);
|
|
@@ -259,7 +259,7 @@ export class LiveTerminalSandbox {
|
|
|
259
259
|
const setup = await this.sandbox.commands.run(`${uploadAssignment}cd ${SANDBOX_WORKDIR} && ${install}`, {
|
|
260
260
|
// The install step may run the product itself (release:dogfood's does: `humanish init
|
|
261
261
|
// --yes`); on the 0.67.0 dogfood that one command arrived unmarked while the participant's
|
|
262
|
-
// nine others carried the marker
|
|
262
|
+
// nine others carried the marker.
|
|
263
263
|
envs: { HUMANISH_STUDY_PARTICIPANT: "1" },
|
|
264
264
|
requestTimeoutMs,
|
|
265
265
|
timeoutMs: PRODUCT_SETUP_TIMEOUT_MS,
|
|
@@ -272,7 +272,7 @@ export class LiveTerminalSandbox {
|
|
|
272
272
|
setupError = toErrorMessage(error);
|
|
273
273
|
}
|
|
274
274
|
recordLifecycle("terminal-lab.product.prepared", setupError
|
|
275
|
-
? `Product setup
|
|
275
|
+
? `Product setup failed after ${Math.max(0, now() - setupStartedAt)}ms: ${sanitize(setupError)}`
|
|
276
276
|
: `Product setup completed in ${Math.max(0, now() - setupStartedAt)}ms (no runtime env; declared egress auth may already be available).`);
|
|
277
277
|
if (setupError) {
|
|
278
278
|
this.status = "failed";
|
|
@@ -292,15 +292,15 @@ export class LiveTerminalSandbox {
|
|
|
292
292
|
const { requestTimeoutMs, wallClockMs } = this;
|
|
293
293
|
// --- The keyed run: `codex exec --json` non-interactively (stdin disabled). ---
|
|
294
294
|
// openai-env passes the real key here; openai-egress passes an inert placeholder. stdin is
|
|
295
|
-
// never wired
|
|
296
|
-
// wall-clock is bounded by maxMinutes
|
|
295
|
+
// never wired: commands.run takes no stdin channel. The command's
|
|
296
|
+
// wall-clock is bounded by maxMinutes: commands.run timeoutMs +
|
|
297
297
|
// an injected-clock guard so a mock/real run that exceeds it is killed and fails closed.
|
|
298
298
|
const codexCommand = buildCodexExecCommand({
|
|
299
299
|
workdir: SANDBOX_WORKDIR,
|
|
300
300
|
prompt: composedPrompt,
|
|
301
301
|
runtimeAuth: runtimeEnv.mode,
|
|
302
302
|
version: runtime.observedVersion,
|
|
303
|
-
|
|
303
|
+
model,
|
|
304
304
|
...(reasoningEffort === undefined ? {} : { reasoningEffort }),
|
|
305
305
|
});
|
|
306
306
|
const commandDigest = digestText(codexCommand);
|
|
@@ -312,8 +312,7 @@ export class LiveTerminalSandbox {
|
|
|
312
312
|
const result = await runWithWallClock(this.sandbox.commands.run(codexCommand, {
|
|
313
313
|
// The selected command env (raw key or inert placeholder). The participant
|
|
314
314
|
// marker rides the same command: humanish telemetry from inside a study reads as a new
|
|
315
|
-
// adopter otherwise.
|
|
316
|
-
// participant's twelve commands arrived unmarked.
|
|
315
|
+
// adopter otherwise.
|
|
317
316
|
envs: { ...runtimeEnv.envs, HUMANISH_STUDY_PARTICIPANT: "1" },
|
|
318
317
|
requestTimeoutMs,
|
|
319
318
|
timeoutMs: wallClockMs,
|
|
@@ -342,13 +341,13 @@ export class LiveTerminalSandbox {
|
|
|
342
341
|
at: nowIso(),
|
|
343
342
|
label: "codex-exec",
|
|
344
343
|
commandDigest,
|
|
345
|
-
envNames: Object.keys(runtimeEnv.envs), //
|
|
344
|
+
envNames: Object.keys(runtimeEnv.envs), // Names only: the credential evidence (item 4).
|
|
346
345
|
...(exitCode === undefined ? {} : { exitCode }),
|
|
347
346
|
...(this.timedOut ? { timedOut: true } : {}),
|
|
348
347
|
durationMs,
|
|
349
348
|
});
|
|
350
|
-
// Score by the verdict-nonce marker over the
|
|
351
|
-
// exact same logic the local-actor
|
|
349
|
+
// Score by the verdict-nonce marker over the scrubbed, redacted and normalized transcript, with
|
|
350
|
+
// the exact same logic the local-actor routes use (extractLocalActorVerdict/normalizeLocalActorTranscript).
|
|
352
351
|
const rawTranscript = terminalEvents.map((e) => e.chunk).join("");
|
|
353
352
|
const normalizedTranscript = normalizeLocalActorTranscript(rawTranscript);
|
|
354
353
|
const markerStatus = extractLocalActorVerdict(normalizedTranscript, verdictNonce);
|
|
@@ -378,8 +377,8 @@ export class LiveTerminalSandbox {
|
|
|
378
377
|
}
|
|
379
378
|
else {
|
|
380
379
|
// No nonce-verified verdict: the agent did not (credibly) report a terminal status. A run
|
|
381
|
-
// that exited 0 but printed no verified marker is
|
|
382
|
-
// evidence
|
|
380
|
+
// that exited 0 but printed no verified marker is blocked evidence: the failure is the
|
|
381
|
+
// evidence, and it stays structurally verifiable.
|
|
383
382
|
this.status = "blocked";
|
|
384
383
|
this.completionReason = "gave_up";
|
|
385
384
|
this.reason = `codex exec exit=${exitCode ?? "null"} but no nonce-verified HUMANISH_ACTOR_VERDICT marker was emitted; recorded as blocked (the missing verdict is the evidence).`;
|
|
@@ -404,7 +403,7 @@ export class LiveTerminalSandbox {
|
|
|
404
403
|
const { now, sanitize, warnings } = this.inputs;
|
|
405
404
|
const { recordLifecycle } = this.inputs.recorder;
|
|
406
405
|
const { requestTimeoutMs } = this;
|
|
407
|
-
// ---
|
|
406
|
+
// --- Proven cleanup, by exact id, never Sandbox.list. ---
|
|
408
407
|
this.cleanup = await teardownSandbox({
|
|
409
408
|
allocation: this.allocation,
|
|
410
409
|
sandboxModule: this.module,
|
|
@@ -435,14 +434,14 @@ export class LiveTerminalSandbox {
|
|
|
435
434
|
}
|
|
436
435
|
/** Build the in-sandbox `codex exec` command (non-interactive, JSON, stdin disabled by mechanism). */
|
|
437
436
|
function buildCodexExecCommand(args) {
|
|
438
|
-
//
|
|
437
|
+
// stdin is disabled (item 7), so no heredoc on a wrapper's stdin carries the prompt;
|
|
439
438
|
// the prompt rides as the final positional arg, shell-quoted. codex exec --json runs once and
|
|
440
439
|
// exits (no interactive loop). --skip-git-repo-check: the workdir is a fresh scratch dir.
|
|
441
440
|
// Pinned via npx (never an ambient/preinstalled `codex` binary, which the stock @e2b/desktop
|
|
442
|
-
// image does not ship
|
|
441
|
+
// image does not ship); npm_config_update_notifier=false silences npx's own
|
|
443
442
|
// update check so it cannot leak into the captured stdout the scorer/redactor parse.
|
|
444
443
|
const quotedPrompt = shellQuote(args.prompt);
|
|
445
|
-
// --dangerously-bypass-approvals-and-sandbox: codex's
|
|
444
|
+
// --dangerously-bypass-approvals-and-sandbox: codex's own inner sandbox is
|
|
446
445
|
// redundant here and blocks the network/file access the study mission needs.
|
|
447
446
|
// The E2B sandbox is the trust boundary (the disposable machine), and exec mode has no
|
|
448
447
|
// interactive approval channel at all.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ActorTraceItem } from "../../actors/contract.js";
|
|
2
|
+
/** What the reader found in the agent's Codex JSON stdout. */
|
|
3
|
+
export interface TerminalParticipantText {
|
|
4
|
+
/** Message and reasoning items, the most recent kept under the aggregate limits, then a notice
|
|
5
|
+
* when older ones were left out. */
|
|
6
|
+
items: ActorTraceItem[];
|
|
7
|
+
/** Distinct agent_message items in the stream, kept or not. */
|
|
8
|
+
messages: number;
|
|
9
|
+
/** Distinct participant items: messages, reasoning, commands, web searches and file changes.
|
|
10
|
+
* Lifecycle, usage, launcher diagnostics and nested command output are not activity. Zero
|
|
11
|
+
* means no recognized item was retained, not that the participant succeeded. */
|
|
12
|
+
participantItems: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Read participant text from the raw stdout as the recorder receives it. Source redaction runs on
|
|
16
|
+
* the stored stream and can cut through JSON framing (a redacted URL takes the closing quote with
|
|
17
|
+
* it), so each line is parsed here, in memory, and only decoded text that has passed `sanitize`
|
|
18
|
+
* is kept. The raw bytes are never stored.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createTerminalParticipantReader(sanitize: (text: string) => string): {
|
|
21
|
+
append(raw: string): void;
|
|
22
|
+
finish(): TerminalParticipantText;
|
|
23
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { normalizeLocalActorTranscript } from "../../run/terminal-contract.js";
|
|
2
|
+
import { MESSAGE_CHARS, PENDING_LINE_CHARS, TEXT_ITEMS_BYTES, TEXT_ITEMS_MAX } from "./types.js";
|
|
3
|
+
const itemEvents = new Set(["item.started", "item.updated", "item.completed"]);
|
|
4
|
+
const nonempty = (value) => typeof value === "string" && value.trim().length > 0;
|
|
5
|
+
const object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
6
|
+
/** Each Codex item event in a run of complete JSON lines, in stream order. */
|
|
7
|
+
function* codexStreamItems(lines) {
|
|
8
|
+
for (const line of lines.split("\n")) {
|
|
9
|
+
let event;
|
|
10
|
+
try {
|
|
11
|
+
event = JSON.parse(line);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (!object(event) ||
|
|
17
|
+
typeof event.type !== "string" ||
|
|
18
|
+
!itemEvents.has(event.type) ||
|
|
19
|
+
!object(event.item) ||
|
|
20
|
+
!nonempty(event.item.id))
|
|
21
|
+
continue;
|
|
22
|
+
yield { event: event.type, id: event.item.id, item: event.item };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function isParticipantItem(item) {
|
|
26
|
+
return (((item.type === "agent_message" || item.type === "reasoning") && nonempty(item.text)) ||
|
|
27
|
+
(item.type === "command_execution" && nonempty(item.command)) ||
|
|
28
|
+
(item.type === "web_search" &&
|
|
29
|
+
(nonempty(item.query) || (object(item.action) && nonempty(item.action.type)))) ||
|
|
30
|
+
(item.type === "file_change" &&
|
|
31
|
+
Array.isArray(item.changes) &&
|
|
32
|
+
item.changes.some((change) => object(change) && nonempty(change.path) && nonempty(change.kind))));
|
|
33
|
+
}
|
|
34
|
+
// The verdict parser removes all whitespace before matching, so a line is a marker line when its
|
|
35
|
+
// whitespace-free form names either marker. The parser reads the stored stream, not these items.
|
|
36
|
+
const MARKER = /HUMANISH_ACTOR_(?:VERDICT|NONCE)=/i;
|
|
37
|
+
const withoutMarkerLines = (text) => text
|
|
38
|
+
.split("\n")
|
|
39
|
+
.filter((line) => !MARKER.test(line.replace(/\s+/g, "")))
|
|
40
|
+
.join("\n");
|
|
41
|
+
/**
|
|
42
|
+
* Read participant text from the raw stdout as the recorder receives it. Source redaction runs on
|
|
43
|
+
* the stored stream and can cut through JSON framing (a redacted URL takes the closing quote with
|
|
44
|
+
* it), so each line is parsed here, in memory, and only decoded text that has passed `sanitize`
|
|
45
|
+
* is kept. The raw bytes are never stored.
|
|
46
|
+
*/
|
|
47
|
+
export function createTerminalParticipantReader(sanitize) {
|
|
48
|
+
let pending = "";
|
|
49
|
+
// Set while the rest of an over-long line is skipped, up to its newline.
|
|
50
|
+
let skipping = false;
|
|
51
|
+
let droppedLines = 0;
|
|
52
|
+
const participantIds = new Set();
|
|
53
|
+
const messageIds = new Set();
|
|
54
|
+
const done = new Set();
|
|
55
|
+
// Completed or left-out items; later events for them are ignored.
|
|
56
|
+
const closed = new Set();
|
|
57
|
+
const texts = new Map();
|
|
58
|
+
const numbers = { message: 0, reasoning: 0 };
|
|
59
|
+
let left = 0;
|
|
60
|
+
let result;
|
|
61
|
+
const take = (lines) => {
|
|
62
|
+
for (const { event, id, item } of codexStreamItems(normalizeLocalActorTranscript(lines))) {
|
|
63
|
+
if (isParticipantItem(item))
|
|
64
|
+
participantIds.add(id);
|
|
65
|
+
const kind = item.type === "agent_message" ? "message" : item.type === "reasoning" ? "reasoning" : null;
|
|
66
|
+
if (kind === null || !nonempty(item.text) || closed.has(id))
|
|
67
|
+
continue;
|
|
68
|
+
if (kind === "message")
|
|
69
|
+
messageIds.add(id);
|
|
70
|
+
if (event === "item.completed") {
|
|
71
|
+
done.add(id);
|
|
72
|
+
closed.add(id);
|
|
73
|
+
}
|
|
74
|
+
// Redact the decoded text before cutting it, so a cut cannot split a value past the patterns.
|
|
75
|
+
const clean = [...sanitize(withoutMarkerLines(item.text))];
|
|
76
|
+
const text = (clean.length > MESSAGE_CHARS ? clean.slice(0, MESSAGE_CHARS) : clean).join("");
|
|
77
|
+
const previous = texts.get(id);
|
|
78
|
+
if (!text.trim()) {
|
|
79
|
+
texts.delete(id);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
texts.set(id, { kind, number: previous?.number ?? ++numbers[kind], text });
|
|
83
|
+
// The oldest item beyond the count limit is left out as the stream arrives, finished or not,
|
|
84
|
+
// so a long stream cannot hold every message in memory.
|
|
85
|
+
if (texts.size > TEXT_ITEMS_MAX) {
|
|
86
|
+
const oldest = texts.keys().next().value;
|
|
87
|
+
texts.delete(oldest);
|
|
88
|
+
closed.add(oldest);
|
|
89
|
+
left += 1;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
append(raw) {
|
|
95
|
+
if (result)
|
|
96
|
+
return;
|
|
97
|
+
if (skipping) {
|
|
98
|
+
const end = raw.indexOf("\n");
|
|
99
|
+
if (end < 0)
|
|
100
|
+
return;
|
|
101
|
+
skipping = false;
|
|
102
|
+
raw = raw.slice(end + 1);
|
|
103
|
+
}
|
|
104
|
+
pending += raw;
|
|
105
|
+
const end = pending.lastIndexOf("\n");
|
|
106
|
+
if (end >= 0) {
|
|
107
|
+
take(pending.slice(0, end));
|
|
108
|
+
pending = pending.slice(end + 1);
|
|
109
|
+
}
|
|
110
|
+
// A line with no newline in sight is dropped, so one runaway line cannot grow without bound.
|
|
111
|
+
if (pending.length > PENDING_LINE_CHARS) {
|
|
112
|
+
pending = "";
|
|
113
|
+
skipping = true;
|
|
114
|
+
droppedLines += 1;
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
finish() {
|
|
118
|
+
if (result)
|
|
119
|
+
return result;
|
|
120
|
+
if (!skipping)
|
|
121
|
+
take(pending);
|
|
122
|
+
pending = "";
|
|
123
|
+
const entries = [...texts.entries()];
|
|
124
|
+
let start = entries.length;
|
|
125
|
+
let bytes = 0;
|
|
126
|
+
while (start > 0 && entries.length - start < TEXT_ITEMS_MAX) {
|
|
127
|
+
const size = Buffer.byteLength(entries[start - 1][1].text);
|
|
128
|
+
if (bytes + size > TEXT_ITEMS_BYTES)
|
|
129
|
+
break;
|
|
130
|
+
bytes += size;
|
|
131
|
+
start -= 1;
|
|
132
|
+
}
|
|
133
|
+
left += start;
|
|
134
|
+
const kept = entries.slice(start);
|
|
135
|
+
const items = kept.map(([source, { kind, number, text }]) => ({
|
|
136
|
+
id: `${kind}-${String(number).padStart(3, "0")}`,
|
|
137
|
+
kind,
|
|
138
|
+
lifecycle: done.has(source) ? "completed" : "started",
|
|
139
|
+
title: kind === "message" ? "agent message" : "agent reasoning",
|
|
140
|
+
text,
|
|
141
|
+
}));
|
|
142
|
+
const notices = [];
|
|
143
|
+
if (left > 0)
|
|
144
|
+
notices.push([
|
|
145
|
+
"agent text truncated",
|
|
146
|
+
`Kept the last ${kept.length} of ${kept.length + left} agent message and reasoning items, within ${TEXT_ITEMS_MAX} items and ${TEXT_ITEMS_BYTES / 1024} KiB. The terminal transcript keeps the captured stream.`,
|
|
147
|
+
]);
|
|
148
|
+
if (droppedLines > 0)
|
|
149
|
+
notices.push([
|
|
150
|
+
"agent output lines skipped",
|
|
151
|
+
`Skipped ${droppedLines} stdout line(s) that ran past ${PENDING_LINE_CHARS} characters without a newline. Items on those lines are not in this trace or its counts.`,
|
|
152
|
+
]);
|
|
153
|
+
notices.forEach(([title, text], index) => items.push({
|
|
154
|
+
id: `notice-${String(index + 1).padStart(3, "0")}`,
|
|
155
|
+
kind: "notice",
|
|
156
|
+
lifecycle: "completed",
|
|
157
|
+
status: "truncated",
|
|
158
|
+
title,
|
|
159
|
+
text,
|
|
160
|
+
}));
|
|
161
|
+
result = { items, messages: messageIds.size, participantItems: participantIds.size };
|
|
162
|
+
return result;
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
@@ -10,7 +10,7 @@ import { prepareSelectedOutputDirectory } from "../../run/contained-output.js";
|
|
|
10
10
|
export async function resolveTerminalPersona(args) {
|
|
11
11
|
const personaId = args.plan.personaId ?? "autonomous-terminal-agent";
|
|
12
12
|
const physicalCwd = await realpath(args.cwd);
|
|
13
|
-
// Resolve the committed persona so its traits actually shape the agent prompt
|
|
13
|
+
// Resolve the committed persona so its traits actually shape the agent prompt; fail-safe to
|
|
14
14
|
// the bare persona id (no traits applied) when no persona file is committed.
|
|
15
15
|
const projectRoot = await prepareSelectedOutputDirectory(path.dirname(physicalCwd), physicalCwd);
|
|
16
16
|
const { persona, warnings } = await resolveCommittedPersona(projectRoot, personaId);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { RoutePlanResult, RouteRefusal, TerminalPlan } from "../../lab/plan-types.js";
|
|
2
2
|
import type { LabConfig } from "../../lab/types.js";
|
|
3
|
-
import type { RunLabProvenance } from "../../run/status.js";
|
|
4
3
|
import { type TerminalProductLabResult } from "./types.js";
|
|
5
4
|
/** The error a terminal lab returns before a run starts. `actor` names the registered actor. */
|
|
6
5
|
export interface TerminalRefusal extends RouteRefusal<"terminal", NonNullable<TerminalProductLabResult["error"]>["code"]> {
|
|
@@ -13,9 +12,6 @@ export type TerminalPlanResult = RoutePlanResult<TerminalPlan, TerminalRefusal>;
|
|
|
13
12
|
*/
|
|
14
13
|
export declare function planTerminalLab(config: LabConfig, input: {
|
|
15
14
|
readonly dryRun: boolean;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
readonly hooks?: {
|
|
19
|
-
readonly costProbe?: unknown;
|
|
20
|
-
};
|
|
15
|
+
/** A test's costProbe can measure spend lines, so a positive maxUsd can trip. */
|
|
16
|
+
readonly hasCostProbe?: boolean;
|
|
21
17
|
}): TerminalPlanResult;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// The terminal route's plan: every configuration refusal the route makes before a run starts, in
|
|
2
2
|
// its order and with its codes, then the plan the run uses. The route checks nothing here again;
|
|
3
3
|
// what stays in the route reads external state (keys, the runtime env, the sandbox).
|
|
4
|
+
import { DEFAULT_OPENAI_CU_MODEL } from "../../actors/computer-use/openai-provider.js";
|
|
4
5
|
import { resolveAutomaticAnalysis } from "../../analysis/automatic-config.js";
|
|
5
6
|
import { isReasoningEffort } from "../../actors/reasoning-effort.js";
|
|
6
7
|
import { actorRegistry, isTerminalActorDescriptor } from "../../actors/registry.js";
|
|
@@ -21,34 +22,33 @@ export function planTerminalLab(config, input) {
|
|
|
21
22
|
refusal: { route: "terminal", code, message, ...(actor === undefined ? {} : { actor }) },
|
|
22
23
|
});
|
|
23
24
|
if (String(config.comms?.email?.kind) === "real")
|
|
24
|
-
return refuse("
|
|
25
|
+
return refuse("HUMANISH_TERMINAL_SUBJECT_INVALID", "Real email receiving is unsupported on the terminal route. Use a supported hosted computer-use browser lab.");
|
|
25
26
|
const mediaReason = desktopMediaValidationReason(config);
|
|
26
27
|
if (mediaReason)
|
|
27
|
-
return refuse("
|
|
28
|
+
return refuse("HUMANISH_TERMINAL_SUBJECT_INVALID", mediaReason);
|
|
28
29
|
const analysis = resolveAutomaticAnalysis(config.review?.analysis);
|
|
29
30
|
if (!analysis.ok)
|
|
30
|
-
return refuse("
|
|
31
|
+
return refuse("HUMANISH_STUDY_ANALYSIS_INVALID", analysis.message);
|
|
31
32
|
const tasksReason = taskProtocolValidationReason(config, false);
|
|
32
33
|
if (tasksReason)
|
|
33
|
-
return refuse("
|
|
34
|
+
return refuse("HUMANISH_STUDY_TASKS_UNSUPPORTED", tasksReason);
|
|
34
35
|
const actorType = config.actors[0]?.type ?? "";
|
|
35
36
|
const descriptor = actorRegistry[actorType];
|
|
36
37
|
if (!descriptor || !isTerminalActorDescriptor(descriptor))
|
|
37
|
-
return refuse("
|
|
38
|
+
return refuse("HUMANISH_TERMINAL_ACTOR_UNSUPPORTED", `actors[0].type "${actorType}" is not a registered terminal actor.`);
|
|
38
39
|
const runtimeVersion = config.execution?.runtime?.version;
|
|
39
40
|
const actor = config.actors[0];
|
|
40
41
|
if ((config.execution?.runtime !== undefined && !isExactRuntimeVersion(runtimeVersion)) ||
|
|
41
42
|
(actor?.model !== undefined &&
|
|
42
43
|
(typeof actor.model !== "string" || actor.model.trim().length === 0)) ||
|
|
43
44
|
(actor?.reasoningEffort !== undefined && !isReasoningEffort(actor.reasoningEffort)))
|
|
44
|
-
return refuse("
|
|
45
|
+
return refuse("HUMANISH_TERMINAL_FAILED", "Terminal runtime settings require an exact Codex version, a nonempty model when declared, and a supported reasoning-effort value.");
|
|
45
46
|
const product = config.subject.product;
|
|
46
47
|
const surfaces = product?.publicSurfaces ?? [];
|
|
47
48
|
if (!product || !product.name || !isNonEmpty(surfaces))
|
|
48
|
-
return refuse("
|
|
49
|
+
return refuse("HUMANISH_TERMINAL_SUBJECT_INVALID", "terminal-product subjects require `subject.product` with a name and at least one public surface URL.", descriptor.id);
|
|
49
50
|
const base = planBase(config, {
|
|
50
51
|
dryRun: input.dryRun,
|
|
51
|
-
...(input.lab === undefined ? {} : { lab: input.lab }),
|
|
52
52
|
analysis,
|
|
53
53
|
});
|
|
54
54
|
const egressAllow = config.execution?.egressAllow;
|
|
@@ -62,7 +62,11 @@ export function planTerminalLab(config, input) {
|
|
|
62
62
|
...(actor?.mission === undefined ? {} : { mission: actor.mission }),
|
|
63
63
|
runtime: {
|
|
64
64
|
...(runtimeVersion === undefined ? {} : { version: runtimeVersion }),
|
|
65
|
-
|
|
65
|
+
// Codex's own default can change with any release and its JSON stream does not name it, so
|
|
66
|
+
// the route always passes a model: the declared one, else humanish's participant default.
|
|
67
|
+
...(actor?.model === undefined
|
|
68
|
+
? { model: DEFAULT_OPENAI_CU_MODEL, modelSource: "humanish_default" }
|
|
69
|
+
: { model: actor.model, modelSource: "declared" }),
|
|
66
70
|
...(actor?.reasoningEffort === undefined ? {} : { reasoningEffort: actor.reasoningEffort }),
|
|
67
71
|
...(config.execution?.runtimeAuth === undefined
|
|
68
72
|
? {}
|
|
@@ -74,23 +78,23 @@ export function planTerminalLab(config, input) {
|
|
|
74
78
|
const caps = config.scenario?.caps;
|
|
75
79
|
if (input.dryRun)
|
|
76
80
|
return { ok: true, plan: { ...shared, dryRun: true, ...(caps ? { caps } : {}) } };
|
|
77
|
-
// The live
|
|
81
|
+
// The live route injects the runtime key into one command only, and only a registered actor
|
|
78
82
|
// that declares that placement may run live.
|
|
79
83
|
const keyPlacement = descriptor.capabilities.keyPlacement;
|
|
80
84
|
if (keyPlacement !== "in-sandbox-command-scoped")
|
|
81
|
-
return refuse("
|
|
85
|
+
return refuse("HUMANISH_TERMINAL_KEYPLACEMENT_INVALID", `Terminal actor "${descriptor.id}" must declare keyPlacement "in-sandbox-command-scoped" for a live run (got "${String(keyPlacement)}"). The engine requires this registered default before applying the declared runtime-auth mode.`, descriptor.id);
|
|
82
86
|
// A live run grants the in-sandbox agent provider access, so a fail-closed cap must be in force.
|
|
83
87
|
const maxUsd = caps?.maxUsd;
|
|
84
88
|
const maxMinutes = caps?.maxMinutes;
|
|
85
89
|
if (caps === undefined || maxUsd === undefined || maxMinutes === undefined || maxMinutes <= 0)
|
|
86
|
-
return refuse("
|
|
90
|
+
return refuse("HUMANISH_TERMINAL_CAPS_MISSING", "A live terminal-product run gives the agent in the sandbox access to a model provider, so it needs a cap: set scenario.caps with maxUsd (0 means no spend) and a positive maxMinutes (the time limit for the codex command). The key is used only while the cap is in force.", descriptor.id);
|
|
87
91
|
// maxUsd is checked against the cost ledger after the session, and only known lines can trip it.
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
if (maxUsd > 0 && input.
|
|
93
|
-
return refuse("
|
|
92
|
+
// The ledger's provider line takes only provider-reported cost, which Codex does not report (the
|
|
93
|
+
// token estimate in run.json is not a measurement), and core has no product, media or payment
|
|
94
|
+
// signal, so without a costProbe every line is null and a positive maxUsd could never trip. That
|
|
95
|
+
// cap would promise a bound nothing enforces, so it is refused; maxMinutes bounds a live run.
|
|
96
|
+
if (maxUsd > 0 && input.hasCostProbe !== true)
|
|
97
|
+
return refuse("HUMANISH_TERMINAL_UNPRICED_CAP", `scenario.caps.maxUsd=${maxUsd} cannot be enforced: Codex reports no provider cost for the participant (its token cost is only estimated after the run) and no product, media or payment spend is measured, so a positive dollar cap can never trip. Set scenario.caps.maxUsd to 0 and bound the run with scenario.caps.maxMinutes, the codex command's wall-clock kill. No sandbox was created and the runtime key was not used.`, descriptor.id);
|
|
94
98
|
// The sandbox's timeout covers the steps before the codex command, maxMinutes and the teardown
|
|
95
99
|
// buffer, and E2B refuses a sandbox over an hour. Refuse here, with the arithmetic, rather than
|
|
96
100
|
// after the plan prints, from a provider 400 that names neither knob.
|
|
@@ -98,7 +102,7 @@ export function planTerminalLab(config, input) {
|
|
|
98
102
|
const sandboxTimeoutMs = terminalSandboxTimeoutMs({ maxMinutes, productInstall });
|
|
99
103
|
if (sandboxTimeoutMs > MAX_SANDBOX_MS) {
|
|
100
104
|
const headroomMinutes = (sandboxTimeoutMs - maxMinutes * 60_000) / 60_000;
|
|
101
|
-
return refuse("
|
|
105
|
+
return refuse("HUMANISH_TERMINAL_CAPS_INVALID", `scenario.caps.maxMinutes ${maxMinutes} derives a ${sandboxTimeoutMs / 60_000}m sandbox deadline, and a sandbox may not live longer than ${MAX_SANDBOX_MS / 60_000}m. The deadline is maxMinutes plus ${headroomMinutes}m: the Node bootstrap (${NODE_BOOTSTRAP_TIMEOUT_MS / 60_000}m), the runtime version check (${TERMINAL_RUNTIME_VERSION_TIMEOUT_MS / 60_000}m)${productInstall ? `, the product setup (${PRODUCT_SETUP_TIMEOUT_MS / 60_000}m)` : ""} and the teardown buffer (${TERMINAL_SANDBOX_TIMEOUT_BUFFER_MS / 60_000}m). Lower scenario.caps.maxMinutes to at most ${MAX_SANDBOX_MS / 60_000 - headroomMinutes}. No sandbox was created and the runtime key was not used.`, descriptor.id);
|
|
102
106
|
}
|
|
103
107
|
return {
|
|
104
108
|
ok: true,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type CommandLogRecord, type InterventionRecord, type LifecycleRecord, type TerminalEventRecord } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* The terminal run's ledgers and capture buffers, mutated through the live lifecycle. Every chunk
|
|
4
|
-
* is scrubbed and redacted as it is stored
|
|
4
|
+
* is scrubbed and redacted as it is stored. Raw bytes leave the append functions only for the
|
|
5
|
+
* in-memory participant reader, which keeps sanitized decoded text.
|
|
5
6
|
*/
|
|
6
7
|
export declare function createTerminalRecorder(args: {
|
|
7
8
|
nowIso: () => string;
|
|
@@ -17,6 +18,10 @@ export declare function createTerminalRecorder(args: {
|
|
|
17
18
|
stderr: string;
|
|
18
19
|
combined: string;
|
|
19
20
|
};
|
|
21
|
+
participantText: {
|
|
22
|
+
append(raw: string): void;
|
|
23
|
+
finish(): import("./participant-text.js").TerminalParticipantText;
|
|
24
|
+
};
|
|
20
25
|
recordLifecycle: (event: string, message: string) => void;
|
|
21
26
|
recordStreamedTerminalChunk: (stream: "stdout" | "stderr", raw: string) => void;
|
|
22
27
|
appendReturnedTerminalOutput: (stream: "stdout" | "stderr", raw: string) => void;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { createTerminalParticipantReader } from "./participant-text.js";
|
|
2
3
|
import { MAX_TRANSCRIPT_BYTES, } from "./types.js";
|
|
3
4
|
/**
|
|
4
5
|
* The terminal run's ledgers and capture buffers, mutated through the live lifecycle. Every chunk
|
|
5
|
-
* is scrubbed and redacted as it is stored
|
|
6
|
+
* is scrubbed and redacted as it is stored. Raw bytes leave the append functions only for the
|
|
7
|
+
* in-memory participant reader, which keeps sanitized decoded text.
|
|
6
8
|
*/
|
|
7
9
|
export function createTerminalRecorder(args) {
|
|
8
10
|
const { nowIso, sanitize, knownSecretValues } = args;
|
|
@@ -13,7 +15,9 @@ export function createTerminalRecorder(args) {
|
|
|
13
15
|
// cross-chunk redaction below; this overlap is never added to terminal events/artifacts.
|
|
14
16
|
const discardedPrefixes = { stdout: "", stderr: "", combined: "" };
|
|
15
17
|
const maxDiscardedPrefixChars = Math.max(0, ...knownSecretValues.map((value) => value.length - 1));
|
|
16
|
-
const interventions = []; //
|
|
18
|
+
const interventions = []; // Always empty while no assisted-input path ships.
|
|
19
|
+
// Reads the agent's text from the raw stdout in memory; it keeps only sanitized decoded text.
|
|
20
|
+
const participantText = createTerminalParticipantReader(sanitize);
|
|
17
21
|
let transcriptBytes = 0;
|
|
18
22
|
const recordLifecycle = (event, message) => {
|
|
19
23
|
lifecycle.push({ at: nowIso(), event, message: sanitize(message) });
|
|
@@ -28,10 +32,13 @@ export function createTerminalRecorder(args) {
|
|
|
28
32
|
return;
|
|
29
33
|
}
|
|
30
34
|
transcriptBytes += Buffer.byteLength(raw, "utf8");
|
|
31
|
-
// Scrub
|
|
35
|
+
// Scrub, then redact, at the source. Only the participant reader below
|
|
36
|
+
// sees the raw bytes, and it stores none of them.
|
|
32
37
|
terminalEvents.push({ at: nowIso(), stream, chunk: sanitize(raw) });
|
|
38
|
+
if (stream === "stdout")
|
|
39
|
+
participantText.append(raw);
|
|
33
40
|
};
|
|
34
|
-
// E2B can stream every byte through callbacks
|
|
41
|
+
// E2B can stream every byte through callbacks and return the same complete output.
|
|
35
42
|
// Track transport delivery, independently per stream, rather than deduplicating participant
|
|
36
43
|
// lines or equal usage records. Hash raw callback bytes before redaction/truncation so the
|
|
37
44
|
// comparison cannot confuse two values that redact identically or lose capped-away delivery.
|
|
@@ -70,6 +77,7 @@ export function createTerminalRecorder(args) {
|
|
|
70
77
|
terminalEvents,
|
|
71
78
|
interventions,
|
|
72
79
|
discardedPrefixes,
|
|
80
|
+
participantText,
|
|
73
81
|
recordLifecycle,
|
|
74
82
|
recordStreamedTerminalChunk,
|
|
75
83
|
appendReturnedTerminalOutput,
|