humanish 0.106.1 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -4
- package/ARCHITECTURE.md +17 -16
- package/CHANGELOG.md +14 -0
- package/CONTEXT.md +42 -39
- package/CONTRIBUTING.md +8 -8
- package/README.md +8 -3
- 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.js +2 -1
- 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/qualified-versions.d.ts +30 -3
- package/dist/actors/codex/qualified-versions.js +50 -5
- package/dist/actors/codex/restricted-executable.d.ts +24 -0
- package/dist/actors/codex/restricted-executable.js +97 -22
- package/dist/actors/codex/restricted-launch.d.ts +7 -1
- package/dist/actors/codex/restricted-launch.js +42 -3
- 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 +60 -2
- package/dist/actors/codex/restricted-policy.d.ts +9 -1
- package/dist/actors/codex/restricted-session.d.ts +14 -1
- package/dist/actors/codex/restricted-session.js +50 -17
- 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 +1 -1
- package/dist/actors/computer-use/actor.js +4 -4
- package/dist/actors/computer-use/loop/backstop.js +1 -1
- package/dist/actors/computer-use/loop/ending.d.ts +2 -2
- package/dist/actors/computer-use/loop/ending.js +2 -2
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +3 -3
- package/dist/actors/computer-use/loop/trace.js +2 -2
- package/dist/actors/computer-use/loop/types.d.ts +14 -5
- package/dist/actors/computer-use/loop.js +4 -4
- package/dist/actors/computer-use/openai-provider.d.ts +1 -1
- package/dist/actors/computer-use/openai-provider.js +2 -2
- package/dist/actors/contract.d.ts +9 -7
- package/dist/actors/local-agent/cli.js +1 -1
- package/dist/actors/scripted-browser/actor.d.ts +2 -2
- package/dist/actors/scripted-browser/journey.js +15 -4
- package/dist/actors/scripted-browser/steps.js +18 -0
- package/dist/actors/scripted-browser/types.d.ts +11 -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/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 +31 -12
- 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 +4 -2
- package/dist/cli/commands/comms.js +8 -1
- package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
- package/dist/cli/commands/lab-route-computer-use.js +26 -14
- package/dist/cli/commands/lab-route-preview.d.ts +1 -3
- package/dist/cli/commands/lab-route-preview.js +3 -4
- 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 +0 -1
- 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 +76 -45
- package/dist/cli/commands/lab-scorer.d.ts +0 -2
- package/dist/cli/commands/lab.js +12 -6
- package/dist/cli/commands/observe.js +22 -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 +10 -8
- package/dist/cli/commands/watch.js +12 -10
- package/dist/cli/doctor.d.ts +3 -0
- package/dist/cli/doctor.js +10 -2
- package/dist/cli/io.d.ts +5 -4
- package/dist/cli/io.js +12 -8
- package/dist/cli/program.js +3 -3
- package/dist/cli/renamed-options.d.ts +11 -0
- package/dist/cli/renamed-options.js +18 -0
- package/dist/cli/telemetry.d.ts +2 -2
- package/dist/cli/telemetry.js +1 -1
- package/dist/comms/capture-surface.d.ts +1 -1
- package/dist/comms/catch-host.d.ts +1 -1
- package/dist/comms/connections.js +4 -4
- package/dist/comms/external-evidence.d.ts +27 -0
- package/dist/comms/external-evidence.js +93 -0
- package/dist/comms/lease-store.js +7 -7
- package/dist/comms/types.js +1 -1
- package/dist/evidence/browser-hygiene.d.ts +1 -1
- package/dist/evidence/browser-hygiene.js +1 -1
- package/dist/evidence/redaction.js +1 -1
- package/dist/evidence/secret-scrub.d.ts +9 -0
- package/dist/evidence/secret-scrub.js +96 -0
- package/dist/feedback/draft.js +7 -9
- package/dist/feedback/export-bundle.js +4 -4
- package/dist/feedback/export.js +9 -9
- package/dist/feedback/feedback.d.ts +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.js +3 -6
- package/dist/keys/key-resolution.d.ts +3 -1
- package/dist/keys/key-resolution.js +18 -16
- package/dist/lab/adapter-extension.d.ts +28 -6
- package/dist/lab/adapter-extension.js +65 -126
- package/dist/lab/adapter-scorer-loader.d.ts +25 -5
- package/dist/lab/adapter-scorer-loader.js +24 -0
- package/dist/lab/composition-rules.js +20 -20
- package/dist/lab/config.js +28 -26
- package/dist/lab/device-presets.d.ts +2 -2
- package/dist/lab/discover.js +1 -3
- package/dist/lab/doctor.d.ts +44 -9
- package/dist/lab/doctor.js +149 -41
- package/dist/lab/init-plan.js +1 -3
- package/dist/lab/keys.js +1 -1
- package/dist/lab/lab-deps.d.ts +85 -0
- package/dist/lab/lab-deps.js +4 -0
- package/dist/lab/parse/actors.js +8 -7
- package/dist/lab/parse/comms.js +3 -2
- package/dist/lab/parse/execution.js +3 -2
- package/dist/lab/parse/subject-state.js +2 -1
- package/dist/lab/parse/subject.js +2 -1
- package/dist/lab/parse/values.d.ts +0 -1
- package/dist/lab/parse/values.js +0 -3
- package/dist/lab/persona-resolve.d.ts +3 -3
- package/dist/lab/persona-resolve.js +4 -4
- 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 +5 -5
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +22 -4
- package/dist/lab/plan.d.ts +3 -11
- package/dist/lab/plan.js +18 -42
- package/dist/lab/preflight-result.js +0 -2
- package/dist/lab/preflight.d.ts +0 -3
- package/dist/lab/preflight.js +1 -1
- 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 +19 -24
- package/dist/lab/routing.js +14 -47
- package/dist/lab/run-lab-events.d.ts +6 -11
- package/dist/lab/run-lab-events.js +3 -11
- package/dist/lab/run-lab-homes.d.ts +64 -0
- package/dist/lab/run-lab-homes.js +3 -0
- package/dist/lab/run-lab-options.d.ts +12 -66
- package/dist/lab/run-lab-options.js +45 -275
- package/dist/lab/summary.d.ts +9 -4
- package/dist/lab/summary.js +15 -8
- package/dist/lab/types.d.ts +132 -132
- package/dist/lab/validation.d.ts +15 -15
- package/dist/lab/validation.js +28 -28
- package/dist/lab/warnings.js +20 -19
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +3 -3
- package/dist/observer/data.js +2 -2
- package/dist/observer/render.js +2 -2
- package/dist/observer/run-routes.d.ts +1 -1
- package/dist/observer/run-routes.js +5 -5
- package/dist/observer/serve.d.ts +17 -0
- package/dist/observer/serve.js +34 -3
- package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
- package/dist/routes/computer-use/bundle-parts.js +10 -3
- package/dist/routes/computer-use/bundle.d.ts +4 -11
- package/dist/routes/computer-use/bundle.js +9 -15
- 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 +10 -10
- package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
- package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
- package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
- 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 +29 -17
- 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 +25 -29
- package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
- 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 +19 -27
- package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +12 -11
- 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 +39 -66
- 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} +10 -10
- package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
- 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 +19 -11
- package/dist/routes/computer-use/participant-model.js +49 -25
- package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
- package/dist/routes/computer-use/participant-prompt.js +4 -4
- package/dist/routes/computer-use/participant-runs.d.ts +6 -6
- package/dist/routes/computer-use/participant-runs.js +8 -8
- package/dist/routes/computer-use/plan.d.ts +21 -29
- package/dist/routes/computer-use/plan.js +52 -60
- package/dist/routes/computer-use/preflight.d.ts +3 -5
- package/dist/routes/computer-use/preflight.js +20 -16
- package/dist/routes/computer-use/rerun-selection.js +10 -6
- package/dist/routes/computer-use/result.d.ts +1 -1
- package/dist/routes/computer-use/result.js +40 -30
- package/dist/routes/computer-use/route.d.ts +3 -4
- package/dist/routes/computer-use/route.js +21 -19
- package/dist/routes/computer-use/self-report.d.ts +2 -2
- package/dist/routes/computer-use/self-report.js +4 -4
- package/dist/routes/computer-use/setup.d.ts +8 -14
- package/dist/routes/computer-use/setup.js +96 -72
- package/dist/routes/computer-use/single-bundle.d.ts +8 -11
- package/dist/routes/computer-use/single-bundle.js +20 -25
- package/dist/routes/computer-use/subject-projection.d.ts +5 -7
- package/dist/routes/computer-use/subject-projection.js +20 -19
- package/dist/routes/computer-use/types.d.ts +169 -210
- package/dist/routes/computer-use/types.js +13 -5
- package/dist/routes/preview.js +0 -1
- package/dist/routes/scripted/bundle.d.ts +3 -6
- package/dist/routes/scripted/bundle.js +11 -16
- package/dist/routes/scripted/plan.d.ts +5 -7
- package/dist/routes/scripted/plan.js +6 -4
- package/dist/routes/scripted/result.d.ts +4 -1
- package/dist/routes/scripted/result.js +10 -6
- package/dist/routes/scripted/route.js +10 -11
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +1 -1
- package/dist/routes/scripted/setup.d.ts +3 -2
- package/dist/routes/scripted/setup.js +22 -21
- package/dist/routes/scripted/subject.d.ts +8 -3
- package/dist/routes/scripted/subject.js +9 -5
- package/dist/routes/scripted/surface-records.js +1 -1
- 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 +19 -36
- package/dist/routes/scripted/types.js +1 -2
- package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
- package/dist/routes/shared-world/bundle.d.ts +2 -2
- package/dist/routes/shared-world/bundle.js +22 -26
- package/dist/routes/shared-world/checkpoints.d.ts +4 -4
- package/dist/routes/shared-world/checkpoints.js +4 -4
- package/dist/routes/shared-world/comms.d.ts +5 -4
- package/dist/routes/shared-world/comms.js +28 -41
- package/dist/routes/shared-world/external-public.d.ts +5 -5
- package/dist/routes/shared-world/external-public.js +19 -20
- package/dist/routes/shared-world/handoff.d.ts +4 -4
- package/dist/routes/shared-world/handoff.js +50 -50
- package/dist/routes/shared-world/lobby-code.d.ts +5 -5
- package/dist/routes/shared-world/lobby-code.js +13 -13
- package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
- package/dist/routes/shared-world/{seats.js → participant-specs.js} +43 -48
- package/dist/routes/shared-world/plan.d.ts +2 -6
- package/dist/routes/shared-world/plan.js +1 -2
- 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 +46 -40
- package/dist/routes/shared-world/result.js +31 -19
- package/dist/routes/shared-world/route.js +37 -41
- package/dist/routes/shared-world/setup.d.ts +5 -4
- package/dist/routes/shared-world/setup.js +12 -14
- package/dist/routes/shared-world/types.d.ts +53 -126
- package/dist/routes/shared-world/types.js +2 -2
- package/dist/routes/terminal/adapter.d.ts +8 -8
- package/dist/routes/terminal/adapter.js +28 -125
- package/dist/routes/terminal/bundle.d.ts +7 -12
- package/dist/routes/terminal/bundle.js +24 -34
- package/dist/routes/terminal/credentials.d.ts +2 -2
- package/dist/routes/terminal/credentials.js +16 -16
- package/dist/routes/terminal/dry-run.d.ts +1 -1
- package/dist/routes/terminal/dry-run.js +9 -11
- package/dist/routes/terminal/encoding.d.ts +1 -1
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +6 -6
- package/dist/routes/terminal/ledger.js +9 -9
- package/dist/routes/terminal/live-finish.d.ts +1 -2
- package/dist/routes/terminal/live-finish.js +21 -20
- package/dist/routes/terminal/live-sandbox.d.ts +3 -2
- package/dist/routes/terminal/live-sandbox.js +20 -20
- package/dist/routes/terminal/participant-text.d.ts +23 -0
- package/dist/routes/terminal/participant-text.js +165 -0
- package/dist/routes/terminal/plan.d.ts +2 -6
- package/dist/routes/terminal/plan.js +13 -9
- package/dist/routes/terminal/recorder.d.ts +6 -1
- package/dist/routes/terminal/recorder.js +12 -4
- package/dist/routes/terminal/result.js +4 -4
- package/dist/routes/terminal/route.js +26 -26
- package/dist/routes/terminal/runtime.d.ts +3 -2
- package/dist/routes/terminal/runtime.js +3 -3
- package/dist/routes/terminal/sandbox.d.ts +3 -3
- package/dist/routes/terminal/sandbox.js +9 -9
- package/dist/routes/terminal/session.js +16 -14
- package/dist/routes/terminal/token-usage.js +5 -5
- package/dist/routes/terminal/trace.d.ts +5 -8
- package/dist/routes/terminal/trace.js +9 -64
- package/dist/routes/terminal/types.d.ts +85 -93
- package/dist/routes/terminal/types.js +9 -4
- 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 +4 -4
- package/dist/run/bundle.d.ts +63 -56
- package/dist/run/bundle.js +9 -8
- package/dist/run/cost-summary.js +3 -2
- package/dist/run/costs.d.ts +6 -6
- package/dist/run/costs.js +10 -10
- package/dist/run/detail.d.ts +5 -5
- package/dist/run/detail.js +6 -6
- package/dist/run/dry-run.js +5 -12
- 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 +16 -4
- package/dist/run/judge.js +24 -7
- 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.js +1 -1
- package/dist/run/pricing.d.ts +19 -9
- package/dist/run/pricing.js +30 -18
- package/dist/run/projection.d.ts +13 -13
- package/dist/run/projection.js +8 -8
- package/dist/run/reclaim.d.ts +6 -0
- package/dist/run/reclaim.js +13 -3
- package/dist/run/results.d.ts +1 -1
- package/dist/run/run-index.d.ts +1 -1
- package/dist/run/run-index.js +11 -11
- package/dist/run/run.d.ts +4 -2
- package/dist/run/run.js +9 -5
- package/dist/run/sandbox-receipts.d.ts +4 -4
- package/dist/run/sandbox-receipts.js +4 -4
- package/dist/run/shared-world-evidence.d.ts +47 -47
- package/dist/run/shared-world-shape.d.ts +3 -3
- package/dist/run/shared-world-shape.js +11 -11
- package/dist/run/stats.d.ts +5 -5
- package/dist/run/stats.js +8 -8
- package/dist/run/status.d.ts +16 -6
- package/dist/run/status.js +31 -8
- package/dist/run/streams.d.ts +26 -19
- package/dist/run/terminal-contract.d.ts +5 -5
- package/dist/run/terminal-contract.js +4 -4
- 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 +36 -34
- package/dist/run-lab.js +41 -37
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +1 -1
- package/dist/subject/local-tree-archive.d.ts +1 -1
- package/dist/subject/local-tree-archive.js +4 -4
- package/dist/subject/local-tree.d.ts +2 -2
- 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 +5 -5
- package/dist/subject/serve.js +1 -1
- package/dist/subject/steps.d.ts +4 -4
- package/dist/subject/steps.js +5 -5
- package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
- package/dist/substrates/e2b/cdp-probe.js +1 -1
- package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
- package/dist/substrates/e2b/desktop-browser.js +4 -4
- package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
- package/dist/substrates/e2b/desktop-cdp.js +4 -4
- package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
- package/dist/substrates/e2b/desktop-geometry.js +3 -3
- package/dist/substrates/e2b/desktop-media.js +2 -2
- package/dist/substrates/e2b/sandbox.js +1 -1
- package/dist/substrates/e2b/sdk.js +2 -2
- 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 +7 -5
- package/dist/tui/actions.js +18 -9
- package/dist/tui-app.js +42 -42
- package/dist/verify/actor.d.ts +10 -10
- package/dist/verify/actor.js +15 -15
- package/dist/verify/artifacts.d.ts +1 -1
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/costs.d.ts +2 -2
- package/dist/verify/costs.js +2 -2
- 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.js +2 -2
- package/dist/verify/verify.js +6 -6
- package/docs/README.md +1 -1
- package/docs/architecture/actor-contract.md +60 -22
- package/docs/architecture/desktop-sessions.md +9 -9
- package/docs/architecture/external-public-shared-world.md +5 -0
- package/docs/architecture/observer.md +4 -4
- package/docs/architecture/restricted-codex-analysis.md +36 -2
- package/docs/architecture/state-driven-executor.md +4 -5
- package/docs/architecture/task-protocol-support.md +3 -5
- package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
- package/docs/contracts/run-bundle.md +10 -8
- package/docs/contracts/schemas.md +109 -53
- package/docs/contracts/study-analysis.md +24 -0
- package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
- package/docs/product/automatic-analysis.md +1 -0
- package/docs/ramp/README.md +2 -1
- package/package.json +4 -4
- package/skills/humanish/SKILL.md +3 -2
- package/skills/humanish/agents/openai.yaml +1 -1
- 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/routes/computer-use/legacy-lane-spec.d.ts +0 -62
- package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
- /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
- /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
- /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type RestrictedCodexResult, type RestrictedCodexUsage } from "./restricted-policy.js";
|
|
1
|
+
import { type RestrictedCodexAnalysisErrorCode, type RestrictedCodexResult, type RestrictedCodexUsage } from "./restricted-policy.js";
|
|
2
2
|
import { type RestrictedCodexDeadline, type RestrictedCodexTransport } from "./restricted-transport.js";
|
|
3
|
+
import { type NotificationPolicy } from "./restricted-notifications.js";
|
|
3
4
|
/** What a turn reads from and reports to its session. */
|
|
4
5
|
export interface RestrictedCodexTurnContext {
|
|
5
6
|
readonly deadline: RestrictedCodexDeadline;
|
|
@@ -23,11 +24,23 @@ export interface RestrictedCodexTurnContext {
|
|
|
23
24
|
reportUsage(usage: RestrictedCodexUsage | undefined, inference: RestrictedCodexUsage[] | undefined): void;
|
|
24
25
|
/** The turn the session interrupts if it closes now. */
|
|
25
26
|
turnStarted(turnId: string): void;
|
|
27
|
+
/** The item policy every notification's item passes, whatever its method. */
|
|
28
|
+
readonly policy: NotificationPolicy;
|
|
29
|
+
/** The session's handler for notifications that arrive before this turn is dispatched. */
|
|
30
|
+
idle(method: string, params: Record<string, unknown>): void;
|
|
31
|
+
/** Counts a notification method this humanish does not know that carried no item. */
|
|
32
|
+
recordUnknown(method: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* A policy refusal: stops this request with `code`, and the session records it when the
|
|
35
|
+
* request already stopped for another reason, such as a close.
|
|
36
|
+
*/
|
|
37
|
+
refuse(code: RestrictedCodexAnalysisErrorCode): void;
|
|
26
38
|
}
|
|
27
39
|
/**
|
|
28
|
-
* Drain: every notification and tool request of one turn.
|
|
29
|
-
* events that arrive before turn/start's reply
|
|
30
|
-
*
|
|
40
|
+
* Drain: every notification and tool request of one turn. Before `dispatched`, notifications go
|
|
41
|
+
* to the session's idle handler; events that arrive after dispatch but before turn/start's reply
|
|
42
|
+
* pass the item policy at once, then wait until acknowledge() and are checked in order.
|
|
43
|
+
* `finished` resolves only with a completed, validated final answer.
|
|
31
44
|
*/
|
|
32
45
|
export declare class RestrictedCodexTurn {
|
|
33
46
|
private readonly context;
|
|
@@ -53,6 +66,8 @@ export declare class RestrictedCodexTurn {
|
|
|
53
66
|
acknowledge(returnedTurnId: unknown): void;
|
|
54
67
|
readonly onNotification: RestrictedCodexTransport["onNotification"];
|
|
55
68
|
readonly onRequest: NonNullable<RestrictedCodexTransport["onRequest"]>;
|
|
69
|
+
/** Refuses a tool request: the session records the refusal, and the transport answers it. */
|
|
70
|
+
private refuseRequest;
|
|
56
71
|
readonly onRequestComplete: () => void;
|
|
57
72
|
private handleTurnEvent;
|
|
58
73
|
private recordUsage;
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
// One restricted Codex request's turn: the notifications and tool requests the app-server sends
|
|
2
2
|
// while the turn runs. Each is checked against the tool policy, the turn's identity and the output
|
|
3
|
-
// limits, and any violation stops the request's deadline with a refusal code.
|
|
3
|
+
// limits, and any violation stops the request's deadline with a refusal code. A policy violation
|
|
4
|
+
// goes through the session, which records it when the request can no longer report it.
|
|
4
5
|
import { CODEX_MAX_OUTPUT_BYTES, CODEX_MAX_REQUEST_BYTES, codexRecord, restrictedCodexUsage, toolPolicyViolation, } from "./restricted-policy.js";
|
|
5
6
|
import { RestrictedCodexStop, } from "./restricted-transport.js";
|
|
7
|
+
import { ANALYST_ITEM_TYPES, ANALYST_RAW_ITEM_TYPES, KNOWN_CODEX_NOTIFICATIONS, PARTICIPANT_ITEM_TYPES, PARTICIPANT_RAW_ITEM_TYPES, itemPolicyOf, } from "./restricted-notifications.js";
|
|
6
8
|
const rawCompactionTypes = ["compaction", "compaction_summary", "context_compaction"];
|
|
7
|
-
const analystRawItemTypes = ["message", "reasoning", ...rawCompactionTypes];
|
|
8
|
-
const participantRawItemTypes = [
|
|
9
|
-
...analystRawItemTypes,
|
|
10
|
-
"custom_tool_call",
|
|
11
|
-
"custom_tool_call_output",
|
|
12
|
-
"function_call",
|
|
13
|
-
"function_call_output",
|
|
14
|
-
];
|
|
15
9
|
function hasScopedIdentity(method, params, threadId, turnId) {
|
|
16
10
|
if (method === "turn/started" || method === "turn/completed") {
|
|
17
11
|
const id = codexRecord(params.turn).id;
|
|
@@ -28,8 +22,10 @@ function hasScopedIdentity(method, params, threadId, turnId) {
|
|
|
28
22
|
typeof params.turnId === "string" &&
|
|
29
23
|
params.turnId.length > 0 &&
|
|
30
24
|
(turnId === undefined || params.turnId === turnId));
|
|
25
|
+
// Before the turn's id is known, an event that names a turn waits in the early buffer, and
|
|
26
|
+
// handleTurnEvent checks it again against the acknowledged id.
|
|
31
27
|
return ((params.threadId === undefined || params.threadId === threadId) &&
|
|
32
|
-
(params.turnId === undefined || params.turnId === turnId));
|
|
28
|
+
(params.turnId === undefined || turnId === undefined || params.turnId === turnId));
|
|
33
29
|
}
|
|
34
30
|
function usageDelta(total, baseline) {
|
|
35
31
|
const delta = {
|
|
@@ -44,9 +40,10 @@ function usageDelta(total, baseline) {
|
|
|
44
40
|
: null;
|
|
45
41
|
}
|
|
46
42
|
/**
|
|
47
|
-
* Drain: every notification and tool request of one turn.
|
|
48
|
-
* events that arrive before turn/start's reply
|
|
49
|
-
*
|
|
43
|
+
* Drain: every notification and tool request of one turn. Before `dispatched`, notifications go
|
|
44
|
+
* to the session's idle handler; events that arrive after dispatch but before turn/start's reply
|
|
45
|
+
* pass the item policy at once, then wait until acknowledge() and are checked in order.
|
|
46
|
+
* `finished` resolves only with a completed, validated final answer.
|
|
50
47
|
*/
|
|
51
48
|
export class RestrictedCodexTurn {
|
|
52
49
|
context;
|
|
@@ -70,7 +67,9 @@ export class RestrictedCodexTurn {
|
|
|
70
67
|
constructor(context) {
|
|
71
68
|
this.context = context;
|
|
72
69
|
this.inferenceUsage = context.participant ? [] : null;
|
|
73
|
-
this.allowedRawItemTypes = context.participant
|
|
70
|
+
this.allowedRawItemTypes = context.participant
|
|
71
|
+
? PARTICIPANT_RAW_ITEM_TYPES
|
|
72
|
+
: ANALYST_RAW_ITEM_TYPES;
|
|
74
73
|
this.finished = new Promise((resolve) => {
|
|
75
74
|
this.resolveFinished = resolve;
|
|
76
75
|
});
|
|
@@ -94,8 +93,21 @@ export class RestrictedCodexTurn {
|
|
|
94
93
|
}
|
|
95
94
|
onNotification = (method, params) => {
|
|
96
95
|
const { deadline } = this.context;
|
|
97
|
-
if (!this.dispatched)
|
|
96
|
+
if (!this.dispatched) {
|
|
97
|
+
this.context.idle(method, params);
|
|
98
98
|
return;
|
|
99
|
+
}
|
|
100
|
+
// The single tool-policy check, first: an event that also fails the identity or delta checks
|
|
101
|
+
// below still has its items recorded. Tool requests must fail even if the turn-start
|
|
102
|
+
// acknowledgment is lost, and every event reaches handleTurnEvent only from here, directly or
|
|
103
|
+
// through the early buffer, so no event skips it. Every item is checked, whatever the method
|
|
104
|
+
// that carries it and wherever the schema nests it.
|
|
105
|
+
const items = itemPolicyOf(method, params, this.context.policy);
|
|
106
|
+
if (toolPolicyViolation(method, codexRecord(params.item), this.allowedRawItemTypes) ||
|
|
107
|
+
items === "violation") {
|
|
108
|
+
this.context.refuse("codex_tool_call");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
99
111
|
if (!hasScopedIdentity(method, params, this.context.threadId(), this.turnId ?? this.earlyTurnId)) {
|
|
100
112
|
deadline.stop("codex_protocol_error");
|
|
101
113
|
return;
|
|
@@ -111,13 +123,8 @@ export class RestrictedCodexTurn {
|
|
|
111
123
|
return;
|
|
112
124
|
}
|
|
113
125
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
// or through the early buffer, so no event skips it.
|
|
117
|
-
if (toolPolicyViolation(method, codexRecord(params.item), this.allowedRawItemTypes)) {
|
|
118
|
-
deadline.stop("codex_tool_call");
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
126
|
+
if (items === "none" && !KNOWN_CODEX_NOTIFICATIONS.has(method))
|
|
127
|
+
this.context.recordUnknown(method);
|
|
121
128
|
if (method === "turn/started") {
|
|
122
129
|
const value = codexRecord(params.turn).id;
|
|
123
130
|
if (typeof value !== "string" ||
|
|
@@ -137,7 +144,10 @@ export class RestrictedCodexTurn {
|
|
|
137
144
|
onRequest = async (method, params) => {
|
|
138
145
|
const { deadline, participant, toolCallIds } = this.context;
|
|
139
146
|
const callId = params.callId;
|
|
140
|
-
|
|
147
|
+
// A request before turn/start is sent, or after the turn completed, is outside the turn.
|
|
148
|
+
if (!this.dispatched ||
|
|
149
|
+
this.completed ||
|
|
150
|
+
!participant ||
|
|
141
151
|
method !== "item/tool/call" ||
|
|
142
152
|
params.threadId !== this.context.threadId() ||
|
|
143
153
|
typeof params.turnId !== "string" ||
|
|
@@ -150,13 +160,13 @@ export class RestrictedCodexTurn {
|
|
|
150
160
|
callId.length > 200 ||
|
|
151
161
|
toolCallIds.has(callId) ||
|
|
152
162
|
this.toolRequestPending)
|
|
153
|
-
|
|
163
|
+
this.refuseRequest();
|
|
154
164
|
// Mark the request outstanding before waiting for a same-chunk turn/start
|
|
155
165
|
// acknowledgment, so an early completion can never be accepted.
|
|
156
166
|
this.toolRequestPending = true;
|
|
157
167
|
const activeTurnId = this.turnId ?? this.earlyTurnId ?? (await deadline.wait(this.turnReady));
|
|
158
168
|
if (params.turnId !== activeTurnId)
|
|
159
|
-
|
|
169
|
+
this.refuseRequest();
|
|
160
170
|
toolCallIds.add(callId);
|
|
161
171
|
deadline.pause();
|
|
162
172
|
const text = await deadline.wait(this.context.tool().call(params.arguments));
|
|
@@ -170,6 +180,11 @@ export class RestrictedCodexTurn {
|
|
|
170
180
|
}
|
|
171
181
|
return { success: true, contentItems: [{ type: "inputText", text }] };
|
|
172
182
|
};
|
|
183
|
+
/** Refuses a tool request: the session records the refusal, and the transport answers it. */
|
|
184
|
+
refuseRequest() {
|
|
185
|
+
this.context.refuse("codex_tool_call");
|
|
186
|
+
throw new RestrictedCodexStop("codex_tool_call");
|
|
187
|
+
}
|
|
173
188
|
onRequestComplete = () => {
|
|
174
189
|
this.toolRequestPending = false;
|
|
175
190
|
};
|
|
@@ -220,11 +235,9 @@ export class RestrictedCodexTurn {
|
|
|
220
235
|
/** The item allowlist, the participant's one dynamic tool and the final answer's shape. */
|
|
221
236
|
admitsItem(method, item) {
|
|
222
237
|
const { deadline, participant } = this.context;
|
|
223
|
-
const allowedItems = participant
|
|
224
|
-
? ["userMessage", "agentMessage", "reasoning", "contextCompaction", "dynamicToolCall"]
|
|
225
|
-
: ["userMessage", "agentMessage", "reasoning", "contextCompaction"];
|
|
238
|
+
const allowedItems = participant ? PARTICIPANT_ITEM_TYPES : ANALYST_ITEM_TYPES;
|
|
226
239
|
if (!allowedItems.includes(String(item.type))) {
|
|
227
|
-
|
|
240
|
+
this.context.refuse("codex_tool_call");
|
|
228
241
|
return false;
|
|
229
242
|
}
|
|
230
243
|
if (item.type === "dynamicToolCall" &&
|
|
@@ -232,7 +245,7 @@ export class RestrictedCodexTurn {
|
|
|
232
245
|
item.namespace !== null ||
|
|
233
246
|
(method === "item/started" && item.status !== "inProgress") ||
|
|
234
247
|
(method === "item/completed" && (item.status !== "completed" || item.success !== true)))) {
|
|
235
|
-
|
|
248
|
+
this.context.refuse("codex_tool_call");
|
|
236
249
|
return false;
|
|
237
250
|
}
|
|
238
251
|
if (item.type === "agentMessage" &&
|
|
@@ -6,7 +6,7 @@ import { type RedactionHooks } from "../../evidence/redaction.js";
|
|
|
6
6
|
import type { DwellWindow, StopWhen } from "../stop-conditions.js";
|
|
7
7
|
import type { LabTask } from "../../lab/tasks.js";
|
|
8
8
|
export interface CuaActorSessionOptions {
|
|
9
|
-
/** The composed mission (persona + scenario/
|
|
9
|
+
/** The composed mission (persona + scenario/participant instruction) handed to the model. */
|
|
10
10
|
instructions: string;
|
|
11
11
|
/** Provenance of the persona this actor embodies (id + applied traits + prompt digest). */
|
|
12
12
|
persona: ActorPersonaRef;
|
|
@@ -18,8 +18,8 @@ export async function runCuaActorSession(options) {
|
|
|
18
18
|
}
|
|
19
19
|
const strictSpend = options.requireReportedUsageForSpendCap === true &&
|
|
20
20
|
(options.maxUsd !== undefined || options.overRunBudget !== undefined);
|
|
21
|
-
const provider = options.provider ??
|
|
22
|
-
const executor = options.executor ??
|
|
21
|
+
const provider = options.provider ?? defaultProvider(options.openai, strictSpend);
|
|
22
|
+
const executor = options.executor ?? defaultExecutor(options.desktop, options.executorOptions);
|
|
23
23
|
const loopOptions = {
|
|
24
24
|
instructions: options.instructions,
|
|
25
25
|
provider,
|
|
@@ -61,7 +61,7 @@ export async function runCuaActorSession(options) {
|
|
|
61
61
|
}
|
|
62
62
|
return result;
|
|
63
63
|
}
|
|
64
|
-
function
|
|
64
|
+
function defaultProvider(openai, strictSpend = false) {
|
|
65
65
|
if (!openai) {
|
|
66
66
|
throw new Error("runCuaActorSession requires either `provider` (injected) or `openai` provider options.");
|
|
67
67
|
}
|
|
@@ -70,7 +70,7 @@ function buildProvider(openai, strictSpend = false) {
|
|
|
70
70
|
...(strictSpend ? { singleDispatch: true } : {}),
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
|
-
function
|
|
73
|
+
function defaultExecutor(desktop, executorOptions) {
|
|
74
74
|
if (!desktop) {
|
|
75
75
|
throw new Error("runCuaActorSession requires either `executor` (injected) or `desktop` to build one.");
|
|
76
76
|
}
|
|
@@ -130,7 +130,7 @@ export function advanceBackstop(previous, turn, limits) {
|
|
|
130
130
|
// CORROBORATION (#383). A stale frame alone is NOT evidence of a stuck agent. The frame hash is
|
|
131
131
|
// a coarse whole-screen measure, and on a light-themed web app it can miss a renamed row, a new
|
|
132
132
|
// list item, or an opened panel — a measured run had 9 visibly different consecutive frames hash
|
|
133
|
-
// identically while the agent was a foreign key away from finishing. Ending a
|
|
133
|
+
// identically while the agent was a foreign key away from finishing. Ending a participant on that
|
|
134
134
|
// signal alone recorded working sessions as `gave_up`, capping every browser run at roughly
|
|
135
135
|
// noProgressSteps turns and writing harness artifacts into evidence as actor behavior.
|
|
136
136
|
//
|
|
@@ -28,7 +28,7 @@ export declare function declaredOutcomeOf(turn: CuaTurn): ParticipantDeclaredOut
|
|
|
28
28
|
/**
|
|
29
29
|
* The participant reported a natural endpoint. "not_reached" is a participant who stopped without
|
|
30
30
|
* finishing: gave_up, which tallies as abandoned. "blocked" keeps goal_satisfied here (the actor
|
|
31
|
-
* did stop on purpose) and the
|
|
31
|
+
* did stop on purpose) and the route's credibility read turns it into a blocked participant, the
|
|
32
32
|
* same path a narrated blocker takes.
|
|
33
33
|
*/
|
|
34
34
|
export declare function participantEnded(turn: CuaTurn, declaredOutcome: ParticipantDeclaredOutcome | undefined, redactNarration: (text: string) => string): Stop;
|
|
@@ -47,7 +47,7 @@ export declare function timeLimit(session: LoopSession): Stop;
|
|
|
47
47
|
export declare function spendLimit(session: LoopSession, estimate: number, maxUsd: number): Stop;
|
|
48
48
|
export declare const nonFiniteEstimate: Stop;
|
|
49
49
|
/** A study-level stop is a recruiting decision hitting its limit, not this participant's runaway. */
|
|
50
|
-
export declare function
|
|
50
|
+
export declare function runSpendLimit(reason: string): Stop;
|
|
51
51
|
export declare const accountBilledCaps: Stop;
|
|
52
52
|
export declare const adapterLimit: Stop;
|
|
53
53
|
export declare const usageUnreported: Stop;
|
|
@@ -32,7 +32,7 @@ export function declaredOutcomeOf(turn) {
|
|
|
32
32
|
/**
|
|
33
33
|
* The participant reported a natural endpoint. "not_reached" is a participant who stopped without
|
|
34
34
|
* finishing: gave_up, which tallies as abandoned. "blocked" keeps goal_satisfied here (the actor
|
|
35
|
-
* did stop on purpose) and the
|
|
35
|
+
* did stop on purpose) and the route's credibility read turns it into a blocked participant, the
|
|
36
36
|
* same path a narrated blocker takes.
|
|
37
37
|
*/
|
|
38
38
|
export function participantEnded(turn, declaredOutcome, redactNarration) {
|
|
@@ -98,7 +98,7 @@ export const nonFiniteEstimate = {
|
|
|
98
98
|
reason: "the injected estimateTurnCostUsd returned a non-finite estimate while execution.caps.maxUsd is set; the estimator receives one ActorTokenUsage object. Failing closed instead of running uncapped.",
|
|
99
99
|
};
|
|
100
100
|
/** A study-level stop is a recruiting decision hitting its limit, not this participant's runaway. */
|
|
101
|
-
export function
|
|
101
|
+
export function runSpendLimit(reason) {
|
|
102
102
|
return { completionReason: "budget_reached", reason, stopCause: "study_spend_limit" };
|
|
103
103
|
}
|
|
104
104
|
// A host-authenticated provider may learn its account billing class during startup. Never price
|
|
@@ -8,7 +8,7 @@ export declare class LostRequestRefused extends Error {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* The spend caps, checked before the next provider request so a model stuck retrying cannot keep
|
|
11
|
-
* spending. The
|
|
11
|
+
* spending. The per-participant cap stops the session once the running estimate crosses maxUsd; a null
|
|
12
12
|
* estimate cannot trip it, because preflight guaranteed a rate. The study budget (#299) is checked
|
|
13
13
|
* next.
|
|
14
14
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as stops from "./ending.js";
|
|
2
2
|
import { notice } from "./trace.js";
|
|
3
|
-
// The spend guards. The
|
|
3
|
+
// The spend guards. The per-participant cap (maxUsd) and the study budget (overRunBudget) are priced from
|
|
4
4
|
// the usage each reply reports, plus a worst-case charge booked for each request lost without a
|
|
5
5
|
// reply. A request whose cost is unknown and unbounded stops a capped session before the next one.
|
|
6
6
|
/** Thrown through the provider when a lost attempt may not be sent again; carries the stop. */
|
|
@@ -13,7 +13,7 @@ export class LostRequestRefused extends Error {
|
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* The spend caps, checked before the next provider request so a model stuck retrying cannot keep
|
|
16
|
-
* spending. The
|
|
16
|
+
* spending. The per-participant cap stops the session once the running estimate crosses maxUsd; a null
|
|
17
17
|
* estimate cannot trip it, because preflight guaranteed a rate. The study budget (#299) is checked
|
|
18
18
|
* next.
|
|
19
19
|
*/
|
|
@@ -29,7 +29,7 @@ export function spendStop(session) {
|
|
|
29
29
|
if (overRunBudget) {
|
|
30
30
|
const runStop = overRunBudget(session.usage.forCap());
|
|
31
31
|
if (runStop !== null)
|
|
32
|
-
return stops.
|
|
32
|
+
return stops.runSpendLimit(runStop);
|
|
33
33
|
}
|
|
34
34
|
return undefined;
|
|
35
35
|
}
|
|
@@ -37,7 +37,7 @@ export class TraceRecorder {
|
|
|
37
37
|
export function statusForCompletionReason(reason) {
|
|
38
38
|
switch (reason) {
|
|
39
39
|
case "goal_satisfied":
|
|
40
|
-
case "turn_completed": // turn_completed is a Codex
|
|
40
|
+
case "turn_completed": // turn_completed is a Codex reason; this loop emits goal_satisfied
|
|
41
41
|
return "passed";
|
|
42
42
|
// A session that ran out of time or budget did not reach its goal, whatever it achieved along
|
|
43
43
|
// the way. Calling that `passed` is how a truncated study came to be reported as a green one —
|
|
@@ -56,7 +56,7 @@ export function statusForCompletionReason(reason) {
|
|
|
56
56
|
return "abandoned";
|
|
57
57
|
// Only the harness failing is a harness failure.
|
|
58
58
|
case "actor_error":
|
|
59
|
-
case "step_failed": // step_failed is the scripted-browser
|
|
59
|
+
case "step_failed": // step_failed is the scripted-browser route's reason; this loop never emits it
|
|
60
60
|
case "harness_error":
|
|
61
61
|
return "failed";
|
|
62
62
|
}
|
|
@@ -229,7 +229,7 @@ export interface CuaProvider {
|
|
|
229
229
|
nextTurn(req: CuaTurnRequest, signal: AbortSignal, spend?: CuaSpendGate): Promise<CuaTurn>;
|
|
230
230
|
/** Optional read-only closing report. Implementations must disable tools and make no retries. */
|
|
231
231
|
debrief?: ((req: CuaTurnRequest, signal: AbortSignal) => Promise<CuaTurn>) | undefined;
|
|
232
|
-
/** Release
|
|
232
|
+
/** Release the participant's model resources. Idempotent; reject if cleanup is unconfirmed. */
|
|
233
233
|
close?(): Promise<void>;
|
|
234
234
|
}
|
|
235
235
|
/** The desktop side of the loop. */
|
|
@@ -261,7 +261,7 @@ export interface CuaLoopOptions {
|
|
|
261
261
|
/**
|
|
262
262
|
* Per-attempt bound on the provider call (#469), so a hung request is told apart from a
|
|
263
263
|
* participant still thinking. A stalled turn is retried once with a notice; a second stall ends
|
|
264
|
-
* the
|
|
264
|
+
* the participant as harness_error.
|
|
265
265
|
*/
|
|
266
266
|
turnTimeoutMs?: number;
|
|
267
267
|
/**
|
|
@@ -308,7 +308,7 @@ export interface CuaLoopOptions {
|
|
|
308
308
|
writeScreenshot?: (name: string, bytes: Buffer) => Promise<string>;
|
|
309
309
|
/**
|
|
310
310
|
* Deterministic harness-owned success guards. Evaluated after the initial observation and after
|
|
311
|
-
* every post-action observation, before another model turn is requested. This keeps a
|
|
311
|
+
* every post-action observation, before another model turn is requested. This keeps a participant from
|
|
312
312
|
* wandering after the product already reached an app-visible endpoint.
|
|
313
313
|
*/
|
|
314
314
|
stopWhen?: StopWhen;
|
|
@@ -346,8 +346,8 @@ export interface CuaLoopOptions {
|
|
|
346
346
|
*/
|
|
347
347
|
estimateTurnCostUsd?: (usage: ActorTokenUsage) => number | null;
|
|
348
348
|
/**
|
|
349
|
-
* RUN-LEVEL spend guard (#299): called with this
|
|
350
|
-
* point the per-
|
|
349
|
+
* RUN-LEVEL spend guard (#299): called with this participant's running usage each turn, at the same
|
|
350
|
+
* point the per-participant cap is checked. Returns a human-readable reason when the STUDY's shared
|
|
351
351
|
* budget is exhausted, else null. On a non-null return the loop stops with `budget_reached`
|
|
352
352
|
* regardless of material progress — a study-level stop is a recruiting decision hitting its
|
|
353
353
|
* limit, not this participant's runaway, so it never reads as `gave_up`.
|
|
@@ -368,6 +368,9 @@ export interface CuaLoopOptions {
|
|
|
368
368
|
*
|
|
369
369
|
* Built-in caller: the external-public shared-world handoff (src/routes/shared-world/handoff.ts)
|
|
370
370
|
* latches the host participant's lobby URL and checks that each follower reached the same lobby.
|
|
371
|
+
*
|
|
372
|
+
* @deprecated Wrap the executor's `observe` and read `url` from each observation it returns. The
|
|
373
|
+
* next minor removes this option.
|
|
371
374
|
*/
|
|
372
375
|
onObservedUrl?: (url: string | undefined) => void;
|
|
373
376
|
/**
|
|
@@ -378,6 +381,9 @@ export interface CuaLoopOptions {
|
|
|
378
381
|
*
|
|
379
382
|
* Built-in caller: the external-public handoff scans the host's narration for the lobby code,
|
|
380
383
|
* because the E2B desktop's CDP URL read behind onObservedUrl is unreliable.
|
|
384
|
+
*
|
|
385
|
+
* @deprecated Wrap the provider's `nextTurn` and read `reasoning` and `message` from each turn it
|
|
386
|
+
* returns. The next minor removes this option.
|
|
381
387
|
*/
|
|
382
388
|
onMessage?: (text: string) => void;
|
|
383
389
|
/**
|
|
@@ -387,6 +393,9 @@ export interface CuaLoopOptions {
|
|
|
387
393
|
*
|
|
388
394
|
* Built-in caller: the external-public handoff reads the lobby code off each participant's own
|
|
389
395
|
* frame until that participant has one: the host's latch, or a follower's convergence observation.
|
|
396
|
+
*
|
|
397
|
+
* @deprecated Wrap the executor's `observe` and read `screenshot` from each observation it
|
|
398
|
+
* returns. The next minor removes this option.
|
|
390
399
|
*/
|
|
391
400
|
onScreenshot?: (frame: Buffer) => void;
|
|
392
401
|
/**
|
|
@@ -187,11 +187,11 @@ function stopBeforeActing(session, turn, turnNumber) {
|
|
|
187
187
|
return stops.accountBilledCaps;
|
|
188
188
|
if (turn.interruption !== undefined) {
|
|
189
189
|
// Preserve usage and partial narration of an interrupted response. Its usage still counts
|
|
190
|
-
// toward the study budget; when that exhausts it, sibling
|
|
191
|
-
const
|
|
190
|
+
// toward the study budget; when that exhausts it, sibling participants stop, so this trace says why.
|
|
191
|
+
const runBudgetStop = overRunBudget?.(session.usage.forCap());
|
|
192
192
|
recordNarration(session, turn, turnNumber, "interrupted");
|
|
193
|
-
if (
|
|
194
|
-
session.trace.record("notice", () => notice("warn", "study budget reached during an interrupted response",
|
|
193
|
+
if (runBudgetStop != null) {
|
|
194
|
+
session.trace.record("notice", () => notice("warn", "study budget reached during an interrupted response", runBudgetStop));
|
|
195
195
|
}
|
|
196
196
|
return stops.providerInterrupted(turn.interruption);
|
|
197
197
|
}
|
|
@@ -46,7 +46,7 @@ export declare const RETRY_AFTER_CAP_MS = 60000;
|
|
|
46
46
|
* Parse a Retry-After header (delay-seconds or an HTTP-date) into milliseconds from `now`;
|
|
47
47
|
* undefined when absent or unreadable. OpenAI's 2026-09-02 change added `429 slow_down` and
|
|
48
48
|
* `503 server_is_overloaded`, both of which may carry it; a fixed 200/400/800 ms backoff against
|
|
49
|
-
* a 20 s hint burns every retry inside the hint and ends the
|
|
49
|
+
* a 20 s hint burns every retry inside the hint and ends the participant's session for nothing.
|
|
50
50
|
*/
|
|
51
51
|
export declare function retryAfterMs(value: string | null | undefined, now: number): number | undefined;
|
|
52
52
|
/**
|
|
@@ -93,7 +93,7 @@ export const RETRY_AFTER_CAP_MS = 60_000;
|
|
|
93
93
|
* Parse a Retry-After header (delay-seconds or an HTTP-date) into milliseconds from `now`;
|
|
94
94
|
* undefined when absent or unreadable. OpenAI's 2026-09-02 change added `429 slow_down` and
|
|
95
95
|
* `503 server_is_overloaded`, both of which may carry it; a fixed 200/400/800 ms backoff against
|
|
96
|
-
* a 20 s hint burns every retry inside the hint and ends the
|
|
96
|
+
* a 20 s hint burns every retry inside the hint and ends the participant's session for nothing.
|
|
97
97
|
*/
|
|
98
98
|
export function retryAfterMs(value, now) {
|
|
99
99
|
if (value === null || value === undefined)
|
|
@@ -109,7 +109,7 @@ export function retryAfterMs(value, now) {
|
|
|
109
109
|
return Math.max(0, at - now);
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
|
-
* The provider error codes a
|
|
112
|
+
* The provider error codes a participant's reason may name. Read from a non-ok body, which is never
|
|
113
113
|
* kept or logged (it can echo the input); only a code on this list crosses over.
|
|
114
114
|
*/
|
|
115
115
|
const NAMED_PROVIDER_ERROR_CODES = [
|
|
@@ -24,7 +24,7 @@ export type ActorStatus = (typeof ACTOR_STATUSES)[number];
|
|
|
24
24
|
/**
|
|
25
25
|
* What the PARTICIPANT said happened, in a field rather than a paragraph (#570). Providers whose
|
|
26
26
|
* reply is schema-constrained (the local-agent routes) fill it on their final turn; a free-text
|
|
27
|
-
* provider leaves it absent and the
|
|
27
|
+
* provider leaves it absent and the route falls back to reading the closing message. `reached`:
|
|
28
28
|
* the task is finished. `blocked`: something in the app stopped the participant. `not_reached`:
|
|
29
29
|
* the participant stopped for another reason (gave up, ran out of ideas).
|
|
30
30
|
*/
|
|
@@ -193,7 +193,9 @@ export interface ActorRuntimeProvenance {
|
|
|
193
193
|
observedVersion?: string;
|
|
194
194
|
versionStatus: "unobserved" | "verified" | "failed";
|
|
195
195
|
requestedModel?: string;
|
|
196
|
-
|
|
196
|
+
/** Where requestedModel came from. Bundles written before humanish always passed a model record
|
|
197
|
+
* `runtime_default_unobserved`, with no requestedModel. */
|
|
198
|
+
modelStatus: "declared" | "humanish_default" | "runtime_default_unobserved";
|
|
197
199
|
requestedReasoningEffort?: string;
|
|
198
200
|
/** Codex turn.completed aggregates requests; it cannot establish per-request pricing tiers. */
|
|
199
201
|
usageGranularity: "runtime_turn";
|
|
@@ -231,7 +233,7 @@ export interface ActorTrace {
|
|
|
231
233
|
/**
|
|
232
234
|
* ADDITIVE + OPTIONAL record of HOW the model was asked to run (humanish.model-settings.v1,
|
|
233
235
|
* #497). `ids.model` says which model; this says the reasoning effort the request actually
|
|
234
|
-
* carried. Present on
|
|
236
|
+
* carried. Present on traces whose provider declares settings; absent everywhere else and on
|
|
235
237
|
* every pre-existing bundle, and its absence is tolerated by verify.
|
|
236
238
|
*
|
|
237
239
|
* It exists because effort was a silent constant: unreachable from a lab, so every run took the
|
|
@@ -248,7 +250,7 @@ export interface ActorTrace {
|
|
|
248
250
|
* ADDITIVE + OPTIONAL affordance record (humanish.affordance-use.v1, #369): which KIND of route
|
|
249
251
|
* this actor took — pointer, keyboard, url-navigation, script-execution, devtools,
|
|
250
252
|
* browser-internal, observation — as per-class counts over the run's dispatched actions.
|
|
251
|
-
* Present on computer-use
|
|
253
|
+
* Present on computer-use traces that dispatched at least one action; absent elsewhere and on
|
|
252
254
|
* every pre-existing bundle (its absence is tolerated by verify). The harness records the class
|
|
253
255
|
* and states NO verdict: whether a class is faithful depends on the population the study
|
|
254
256
|
* declares, which is product semantics and belongs to the adopter's scorer. See
|
|
@@ -266,7 +268,7 @@ export interface ActorTrace {
|
|
|
266
268
|
/**
|
|
267
269
|
* ADDITIVE + OPTIONAL (#570): the outcome the participant declared on its final turn, when its
|
|
268
270
|
* provider's reply carries the field. Absent on free-text providers and on every older bundle.
|
|
269
|
-
* The
|
|
271
|
+
* The route reads this before it reads the closing paragraph; three regex patches in one month
|
|
270
272
|
* (#453, #549, #565) each fixed a false refusal and each left the next shape unhandled.
|
|
271
273
|
*/
|
|
272
274
|
declaredOutcome?: ParticipantDeclaredOutcome;
|
|
@@ -287,11 +289,11 @@ export interface ActorTrace {
|
|
|
287
289
|
* Known tokenUsage remains usable as a partial total. Absence is not proof of completeness. */
|
|
288
290
|
interactionUsageIncomplete?: true;
|
|
289
291
|
/**
|
|
290
|
-
* ADDITIVE + OPTIONAL token-derived cost ESTIMATE for this
|
|
292
|
+
* ADDITIVE + OPTIONAL token-derived cost ESTIMATE for this trace (humanish.actor-estimated-cost.v1).
|
|
291
293
|
* Distinct from `tokenUsage.costUsd`, which is RESERVED for a real provider-returned charge: a
|
|
292
294
|
* bare `costUsd` always means "the provider billed this", while `estimatedCost.estimatedCostUsd`
|
|
293
295
|
* is a rate-table multiply named honestly as an estimate (invariant 6). Absent on the Codex
|
|
294
|
-
* app-server and scripted
|
|
296
|
+
* app-server and scripted traces and on every pre-existing bundle; the terminal trace records a
|
|
295
297
|
* null estimate. Its absence is tolerated by verify (fail-open on display). A `null`
|
|
296
298
|
* estimatedCostUsd is DECLARED ABSENT (unknown rate / no usage), never 0.
|
|
297
299
|
*/
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
//
|
|
19
19
|
// WHERE IT IS SAFE, and this inverts the intuitive reading: the local agent only DECIDES. humanish
|
|
20
20
|
// executes the action inside the desktop sandbox, so nothing the persona chooses ever runs on the
|
|
21
|
-
// operator's machine. The same trick on the TERMINAL
|
|
21
|
+
// operator's machine. The same trick on the TERMINAL route would be the opposite — it would move
|
|
22
22
|
// code execution out of the sandbox and onto a real disk — which is why this is a computer-use
|
|
23
23
|
// provider and nothing else. Even so, these are coding agents with their own shell and file tools,
|
|
24
24
|
// so each one is spawned tool-restricted, in a scratch directory, with a per-turn timeout.
|
|
@@ -10,10 +10,10 @@ export interface ScriptedBrowserSessionOptions {
|
|
|
10
10
|
urlPolicy?: ScriptedBrowserEvidenceUrlPolicy;
|
|
11
11
|
/** Parsed + validated by the backend (scenario.ref is consumed there, fail-closed). */
|
|
12
12
|
journey: BrowserPersonaJourney;
|
|
13
|
-
/** ONE session per surface
|
|
13
|
+
/** ONE session per surface. */
|
|
14
14
|
surface: BrowserSurface;
|
|
15
15
|
/** id = actors[0].persona ?? "scripted-journey"; promptDigest = journey.sourceDigest prefix
|
|
16
|
-
* (the step manifest IS the "prompt" — no model prompt exists on this
|
|
16
|
+
* (the step manifest IS the "prompt" — no model prompt exists on this route). */
|
|
17
17
|
persona: ActorPersonaRef;
|
|
18
18
|
/** Journey wall-clock budget in ms; the lab route passes execution.timeoutMs or 300_000. */
|
|
19
19
|
timeoutMs: number;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Parse a scenario's `browser.steps` into a BrowserPersonaJourney: the actions, text assertions and
|
|
2
2
|
// expectations the scripted browser runs. The journey is the actor's whole behavior.
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { isRecord } from "../../run/type-guards.js";
|
|
4
5
|
export function parseBrowserPersonaJourneyFromScenario(args) {
|
|
5
6
|
if (!isRecord(args.raw)) {
|
|
6
7
|
return {};
|
|
@@ -86,7 +87,16 @@ function parseBrowserPersonaStep(rawStep, index) {
|
|
|
86
87
|
const selector = stringValue(source.selector);
|
|
87
88
|
const pathValue = stringValue(source.path);
|
|
88
89
|
const value = stringValue(source.value);
|
|
90
|
+
const key = stringValue(source.key);
|
|
89
91
|
const expectation = browserStepExpectationValue(source.expect ?? source.expectation);
|
|
92
|
+
if (action === "press" && !key) {
|
|
93
|
+
return { failure: `${id} press action requires key (for example Enter).` };
|
|
94
|
+
}
|
|
95
|
+
if (action !== "press" && "key" in source) {
|
|
96
|
+
return {
|
|
97
|
+
failure: `${id} sets key, which only a press step sends. Supported actions: ${SUPPORTED_ACTIONS}.`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
90
100
|
if (action === "fill" && !selector) {
|
|
91
101
|
return { failure: `${id} fill action requires selector.` };
|
|
92
102
|
}
|
|
@@ -105,12 +115,14 @@ function parseBrowserPersonaStep(rawStep, index) {
|
|
|
105
115
|
...(pathValue === undefined ? {} : { path: pathValue }),
|
|
106
116
|
...(selector === undefined ? {} : { selector }),
|
|
107
117
|
...(value === undefined ? {} : { value }),
|
|
118
|
+
...(key === undefined ? {} : { key }),
|
|
108
119
|
},
|
|
109
120
|
};
|
|
110
121
|
}
|
|
111
122
|
function hasInlineBrowserSteps(value) {
|
|
112
123
|
return Array.isArray(value) && value.some((entry) => isRecord(entry) && isRecord(entry.browser));
|
|
113
124
|
}
|
|
125
|
+
const SUPPORTED_ACTIONS = "goto, fill, click, press, assertText, waitForText, waitForSelector";
|
|
114
126
|
function browserPersonaActionValue(value) {
|
|
115
127
|
if (typeof value !== "string") {
|
|
116
128
|
return null;
|
|
@@ -121,8 +133,10 @@ function browserPersonaActionValue(value) {
|
|
|
121
133
|
.replace(/[-_\s]+/g, "");
|
|
122
134
|
if (normalized === "goto" || normalized === "open" || normalized === "navigate")
|
|
123
135
|
return "goto";
|
|
124
|
-
if (normalized === "click"
|
|
136
|
+
if (normalized === "click")
|
|
125
137
|
return "click";
|
|
138
|
+
if (normalized === "press")
|
|
139
|
+
return "press";
|
|
126
140
|
if (normalized === "fill" || normalized === "type")
|
|
127
141
|
return "fill";
|
|
128
142
|
if (normalized === "asserttext" || normalized === "expecttext")
|
|
@@ -152,9 +166,6 @@ function browserStepExpectationValue(value) {
|
|
|
152
166
|
};
|
|
153
167
|
return Object.keys(expectation).length === 0 ? undefined : expectation;
|
|
154
168
|
}
|
|
155
|
-
function isRecord(value) {
|
|
156
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
157
|
-
}
|
|
158
169
|
function stringValue(value) {
|
|
159
170
|
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
160
171
|
}
|
|
@@ -52,6 +52,24 @@ export async function executeBrowserPersonaStep(args) {
|
|
|
52
52
|
await target.click({ timeout: stepTimeoutMs });
|
|
53
53
|
await args.page.waitForTimeout(300);
|
|
54
54
|
}
|
|
55
|
+
else if (args.step.action === "press") {
|
|
56
|
+
if (!args.step.key) {
|
|
57
|
+
throw new Error(`${args.step.id} press step is missing key`);
|
|
58
|
+
}
|
|
59
|
+
// With a selector, Playwright focuses that element first; without one, the key goes to
|
|
60
|
+
// whatever has focus, such as the input a fill step just typed into.
|
|
61
|
+
if (args.step.selector) {
|
|
62
|
+
const target = args.page.locator(args.step.selector).first();
|
|
63
|
+
if ((await target.count()) === 0) {
|
|
64
|
+
throw new Error(`${args.step.id} press step found no target`);
|
|
65
|
+
}
|
|
66
|
+
await target.press(args.step.key, { timeout: stepTimeoutMs });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
await args.page.keyboard.press(args.step.key);
|
|
70
|
+
}
|
|
71
|
+
await args.page.waitForTimeout(300);
|
|
72
|
+
}
|
|
55
73
|
else if (args.step.action === "assertText" || args.step.action === "waitForText") {
|
|
56
74
|
const expectedText = args.step.expectation?.text ?? args.step.value;
|
|
57
75
|
if (!expectedText) {
|