humanish 0.106.0 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -2
- package/ARCHITECTURE.md +17 -16
- package/CHANGELOG.md +24 -0
- package/CONTEXT.md +42 -39
- package/CONTRIBUTING.md +8 -6
- 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 +31 -4
- package/dist/actors/codex/qualified-versions.js +51 -6
- 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 +10 -8
- package/dist/actors/contract.js +7 -1
- 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.d.ts +2 -0
- package/dist/lab/composition-rules.js +35 -26
- 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 +6 -2
- package/dist/lab/plan-base.js +22 -7
- package/dist/lab/plan-participants.d.ts +5 -5
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +33 -7
- 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/observer-app.html +1 -1
- 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} +14 -13
- 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 +58 -33
- 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 +59 -65
- package/dist/routes/computer-use/preflight.d.ts +6 -11
- package/dist/routes/computer-use/preflight.js +26 -18
- 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 -17
- package/dist/routes/computer-use/setup.js +98 -86
- 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 -211
- package/dist/routes/computer-use/types.js +13 -6
- 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 +11 -6
- 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} +46 -51
- 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 +48 -41
- 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 +4 -2
- package/dist/routes/terminal/live-sandbox.js +25 -21
- 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 +5 -3
- package/dist/routes/terminal/sandbox.js +13 -16
- 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 +7 -1
- package/dist/run/reclaim.js +24 -4
- 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/desktop-session.d.ts +2 -0
- 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.d.ts +2 -0
- package/dist/substrates/e2b/sandbox.js +22 -8
- package/dist/substrates/e2b/sdk.d.ts +12 -1
- package/dist/substrates/e2b/sdk.js +30 -9
- 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 +40 -4
- 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
|
@@ -6,15 +6,15 @@ import { resolveAutomaticAnalysis } from "../../analysis/automatic-config.js";
|
|
|
6
6
|
import { actorRegistry, isCuaActorDescriptor, } from "../../actors/registry.js";
|
|
7
7
|
import { isHttpUrl, isLoopbackUrl } from "../../lab/parse/subject.js";
|
|
8
8
|
import { subjectStateInvalidReason } from "../../lab/parse/subject-state.js";
|
|
9
|
-
import { brainOf, capsOf, desktopRequirements, planBase, provisionedSubject, } from "../../lab/plan-base.js";
|
|
9
|
+
import { brainOf, callerBrainOf, capsOf, desktopRequirements, planBase, provisionedSubject, } from "../../lab/plan-base.js";
|
|
10
10
|
import { computerUseParticipants, declaredTargets } from "../../lab/plan-participants.js";
|
|
11
11
|
import { MAX_CUA_LANES } from "../../lab/routing.js";
|
|
12
12
|
import { cloneTargetValidationReason, cuaLaneValidationReason, desktopMediaValidationReason, outputTokenLimitValidationReason, receivingEmailValidationReason, scenarioCapsValidationReason, taskProtocolValidationReason, } from "../../lab/validation.js";
|
|
13
|
+
import { desktopCliProductReason } from "../../lab/composition-rules.js";
|
|
13
14
|
import { isLocalBrowserLab } from "../../substrates/local/runtime-config.js";
|
|
14
15
|
import { boundedConcurrency, defaultSessionTimeoutMs, resolveParticipantSandboxMs, } from "./participant-runs.js";
|
|
15
16
|
import { MAX_SANDBOX_MS } from "../../substrates/e2b/lifetime.js";
|
|
16
17
|
import {} from "./types.js";
|
|
17
|
-
import { participantDesktopOf } from "./participant-desktop.js";
|
|
18
18
|
/** The registered descriptor for a planned actor id; planComputerUseLab checked the registry. */
|
|
19
19
|
export function cuaDescriptorOf(actor) {
|
|
20
20
|
const descriptor = actorRegistry[actor];
|
|
@@ -22,7 +22,7 @@ export function cuaDescriptorOf(actor) {
|
|
|
22
22
|
throw new Error(`planned actor "${actor}" is not a registered computer-use actor`);
|
|
23
23
|
return descriptor;
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
function declaredSubjectRoute(config, driving) {
|
|
26
26
|
const cloneRoute = config.subject.source === "clone";
|
|
27
27
|
const localTreeRoute = config.subject.source === "local-tree";
|
|
28
28
|
const provisionedRoute = cloneRoute || localTreeRoute;
|
|
@@ -33,34 +33,36 @@ export function cuaSubjectRoute(config, hooks) {
|
|
|
33
33
|
localTreeRoute,
|
|
34
34
|
provisionedRoute,
|
|
35
35
|
localAppSubject: config.subject.source === "local-app",
|
|
36
|
-
inProcessRoute:
|
|
36
|
+
inProcessRoute: driving.inProcess,
|
|
37
37
|
serve,
|
|
38
38
|
appUrl: (provisionedRoute ? serve?.url : config.subject.appUrl) ?? "",
|
|
39
39
|
subjectRepo: cloneRoute ? (config.subject.repos?.[0] ?? "") : undefined,
|
|
40
40
|
subjectEnvNames: provisionedRoute ? (config.subject.env ?? []) : [],
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
+
/** The driving a computer-use run's options carry. */
|
|
44
|
+
export function callerDrivingOf(options) {
|
|
45
|
+
return {
|
|
46
|
+
inProcess: options.inProcess !== undefined,
|
|
47
|
+
createProvider: options.createProvider !== undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
43
50
|
/** The state a planned run's provisioned subject declares. Other subjects declare none. */
|
|
44
51
|
export function cuaDeclaredState(plan) {
|
|
45
52
|
const { subject } = plan.runner;
|
|
46
53
|
return subject.kind === "clone" || subject.kind === "local-tree" ? subject.state : undefined;
|
|
47
54
|
}
|
|
48
|
-
/** The
|
|
49
|
-
export function
|
|
50
|
-
const {
|
|
51
|
-
const provisioned = subject.
|
|
52
|
-
return
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
serve: provisioned?.serve,
|
|
60
|
-
appUrl: provisioned?.serve.url ?? ("appUrl" in subject ? subject.appUrl : ""),
|
|
61
|
-
subjectRepo: subject.kind === "clone" ? subject.repo : undefined,
|
|
62
|
-
subjectEnvNames: [...(provisioned?.env ?? [])],
|
|
63
|
-
};
|
|
55
|
+
/** The URL a refused lab's result names, from its declaration: a provisioned subject's serve URL. */
|
|
56
|
+
export function declaredAppUrl(config) {
|
|
57
|
+
const { subject } = config;
|
|
58
|
+
const provisioned = subject.source === "clone" || subject.source === "local-tree";
|
|
59
|
+
return (provisioned ? subject.serve?.url : subject.appUrl) ?? "";
|
|
60
|
+
}
|
|
61
|
+
/** The URL a planned run's participants open: a provisioned subject's served URL, else its own. */
|
|
62
|
+
export function plannedAppUrl(subject) {
|
|
63
|
+
if (subject.kind === "clone" || subject.kind === "local-tree")
|
|
64
|
+
return subject.serve.url;
|
|
65
|
+
return "appUrl" in subject ? subject.appUrl : "";
|
|
64
66
|
}
|
|
65
67
|
const invalid = (message) => ({
|
|
66
68
|
code: "HUMANISH_CUA_LAB_SUBJECT_INVALID",
|
|
@@ -71,22 +73,22 @@ const invalid = (message) => ({
|
|
|
71
73
|
* is touched. The parser enforces most of these too; the engine repeats them for library callers
|
|
72
74
|
* that hand it a config directly. The groups run in this order, and each returns its first reason.
|
|
73
75
|
*/
|
|
74
|
-
function cuaLabRejection(config,
|
|
75
|
-
return (unsupportedDeclarationReason(config,
|
|
76
|
+
function cuaLabRejection(config, hasRunSession, driving, subjectRoute) {
|
|
77
|
+
return (unsupportedDeclarationReason(config, hasRunSession, driving, subjectRoute) ??
|
|
76
78
|
subjectStructureReason(config, subjectRoute) ??
|
|
77
79
|
entryTargetReason(config, subjectRoute) ??
|
|
78
|
-
driverReason(
|
|
80
|
+
driverReason(driving, subjectRoute) ??
|
|
79
81
|
rosterShapeReason(config));
|
|
80
82
|
}
|
|
81
83
|
/** A declaration this route cannot honor, for any subject or with the caller's own driver. */
|
|
82
|
-
function unsupportedDeclarationReason(config,
|
|
84
|
+
function unsupportedDeclarationReason(config, hasRunSession, driving, { inProcessRoute }) {
|
|
83
85
|
const reason = desktopMediaValidationReason(config) ||
|
|
84
86
|
outputTokenLimitValidationReason(config) ||
|
|
85
87
|
scenarioCapsValidationReason(config);
|
|
86
88
|
if (reason)
|
|
87
89
|
return invalid(reason);
|
|
88
90
|
if (config.actors[0]?.maxOutputTokens !== undefined &&
|
|
89
|
-
(
|
|
91
|
+
(hasRunSession || driving.createProvider || driving.inProcess))
|
|
90
92
|
return invalid("maxOutputTokens cannot be enforced by a custom runSession/provider/executor route.");
|
|
91
93
|
const receivingReason = receivingEmailValidationReason(config);
|
|
92
94
|
if (receivingReason)
|
|
@@ -150,14 +152,14 @@ function entryTargetReason(config, subjectRoute) {
|
|
|
150
152
|
: "subject.appUrl and actors[0].lanes[].target entries must be valid http(s) URLs.",
|
|
151
153
|
};
|
|
152
154
|
}
|
|
153
|
-
/** Something to drive the subject: the caller's executor with its provider
|
|
154
|
-
function driverReason(
|
|
155
|
+
/** Something to drive the subject: the caller's executor with its provider. */
|
|
156
|
+
function driverReason(driving, { localAppSubject, inProcessRoute }) {
|
|
155
157
|
// A custom executor needs a custom provider too: the default OpenAI provider is vision-based
|
|
156
158
|
// and would fail closed against an executor that returns no screenshot.
|
|
157
|
-
if (
|
|
159
|
+
if (driving.inProcess && !driving.createProvider)
|
|
158
160
|
return {
|
|
159
161
|
code: "HUMANISH_CUA_LAB_EXECUTOR_NO_PROVIDER",
|
|
160
|
-
message: "
|
|
162
|
+
message: "RunLabOptions.inProcess requires RunLabOptions.createProvider — a state-driven executor returns no screenshot, so it must be paired with a NON-vision provider (the default OpenAI computer-use provider is vision-based and would fail closed).",
|
|
161
163
|
};
|
|
162
164
|
// There is no built-in in-process driver for a local app.
|
|
163
165
|
if (localAppSubject && !inProcessRoute)
|
|
@@ -165,21 +167,12 @@ function driverReason(config, hooks, { localAppSubject, inProcessRoute }) {
|
|
|
165
167
|
code: "HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR",
|
|
166
168
|
message: "subject.source: local-app has no built-in driver. Supply one through runLab(config, { inProcess: { executor }, createProvider }); a state-driven executor needs a non-vision provider.",
|
|
167
169
|
};
|
|
168
|
-
// runLab gives a local browser study its desktop lane; a direct route call or an in-process
|
|
169
|
-
// executor on the same lab has none.
|
|
170
|
-
if (config.subject.source === "app-url" &&
|
|
171
|
-
config.execution?.target === "local" &&
|
|
172
|
-
participantDesktopOf(hooks) === undefined)
|
|
173
|
-
return {
|
|
174
|
-
code: "HUMANISH_CUA_LAB_LOCAL_DESKTOP_MISSING",
|
|
175
|
-
message: "An app-url lab with execution.target: local needs a local desktop. runLab starts one; a direct route call or an in-process executor does not.",
|
|
176
|
-
};
|
|
177
170
|
return undefined;
|
|
178
171
|
}
|
|
179
|
-
/** The
|
|
172
|
+
/** The participant roster, then the sandbox deadline its session budget derives. */
|
|
180
173
|
function rosterShapeReason(config) {
|
|
181
|
-
//
|
|
182
|
-
// allowPublicTargets with more than one
|
|
174
|
+
// `lanes` XOR `count`/`laneFocus`, device XOR raw resolution, cap, unique ids,
|
|
175
|
+
// allowPublicTargets with more than one participant, clone.fanout.
|
|
183
176
|
const fanoutReason = cuaLaneValidationReason(config);
|
|
184
177
|
if (fanoutReason)
|
|
185
178
|
return { code: "HUMANISH_CUA_LAB_FANOUT_INVALID", message: fanoutReason };
|
|
@@ -194,12 +187,17 @@ function rosterShapeReason(config) {
|
|
|
194
187
|
const headroomMs = derivedSandboxMs - sessionMs;
|
|
195
188
|
return invalid(`execution.timeoutMs ${Math.round(sessionMs / 60_000)}m derives a ${Math.round(derivedSandboxMs / 60_000)}m sandbox deadline, and a sandbox may not live longer than ${MAX_SANDBOX_MS / 60_000}m. The deadline is the session budget plus ${Math.round(headroomMs / 60_000)}m of provisioning and teardown headroom${provisionedRoute ? " (this route clones, installs, builds and serves the subject before the actor starts)" : ""}. Lower execution.timeoutMs to at most ${Math.round((MAX_SANDBOX_MS - headroomMs) / 60_000)}m, or set execution.desktop.sandboxTimeoutMs explicitly.`);
|
|
196
189
|
}
|
|
190
|
+
/** The plan's rerun: the source run and, when given, the participants to rerun. */
|
|
191
|
+
function rerunPlan({ sourceRunId, participantIds, }) {
|
|
192
|
+
return { sourceRunId, ...(participantIds === undefined ? {} : { participantIds }) };
|
|
193
|
+
}
|
|
197
194
|
/**
|
|
198
195
|
* Plan a computer-use lab. It is called for any config handed to the computer-use runner, not only
|
|
199
196
|
* one routeOf sends here, so a config for another route gets this route's refusal.
|
|
200
197
|
*/
|
|
201
198
|
export function planComputerUseLab(config, input) {
|
|
202
|
-
const
|
|
199
|
+
const hasRunSession = input.hasRunSession === true;
|
|
200
|
+
const driving = input.driving ?? { inProcess: false, createProvider: false };
|
|
203
201
|
const refuse = (stage, code, message, actor) => ({
|
|
204
202
|
ok: false,
|
|
205
203
|
refusal: {
|
|
@@ -222,10 +220,10 @@ export function planComputerUseLab(config, input) {
|
|
|
222
220
|
if (!descriptor || !isCuaActorDescriptor(descriptor))
|
|
223
221
|
return refuse("in-scope", "HUMANISH_CUA_LAB_ACTOR_UNSUPPORTED", `actors[0].type "${actorType}" is not a registered computer-use actor.`);
|
|
224
222
|
const actor = descriptor.id;
|
|
225
|
-
const rejection = cuaLabRejection(config,
|
|
223
|
+
const rejection = cuaLabRejection(config, hasRunSession, driving, declaredSubjectRoute(config, driving));
|
|
226
224
|
if (rejection)
|
|
227
225
|
return refuse("in-scope", rejection.code, rejection.message, actor);
|
|
228
|
-
// A shared world runs every seat against one app; this route would run them as separate
|
|
226
|
+
// A shared world runs every seat against one app; this route would run them as separate participants.
|
|
229
227
|
// It comes after the rules above, so a shared-world config that breaks one of them, which runLab
|
|
230
228
|
// sends here, still gets that rule's message.
|
|
231
229
|
if (config.subject.topology === "shared-world")
|
|
@@ -233,35 +231,39 @@ export function planComputerUseLab(config, input) {
|
|
|
233
231
|
// The in-process route drives subject.appUrl on this machine and creates no desktop, so it would
|
|
234
232
|
// skip the subject a clone, local-tree or desktop-cli lab declares.
|
|
235
233
|
const source = config.subject.source;
|
|
236
|
-
if (
|
|
234
|
+
if (driving.inProcess &&
|
|
237
235
|
(source === "clone" || source === "local-tree" || source === "desktop-cli"))
|
|
238
|
-
return refuse("in-scope", "HUMANISH_CUA_LAB_SUBJECT_INVALID", `
|
|
239
|
-
// The parser
|
|
240
|
-
|
|
241
|
-
|
|
236
|
+
return refuse("in-scope", "HUMANISH_CUA_LAB_SUBJECT_INVALID", `RunLabOptions.inProcess drives subject.appUrl in this process, and a ${source} subject needs the hosted desktop the in-process route never creates. Use an app-url or local-app subject with inProcess, or remove inProcess to run on a hosted desktop.`, actor);
|
|
237
|
+
// The parser's rule; without a product the desktop study fails later.
|
|
238
|
+
const productReason = desktopCliProductReason(config);
|
|
239
|
+
if (productReason)
|
|
240
|
+
return refuse("in-scope", "HUMANISH_CUA_LAB_SUBJECT_INVALID", productReason, actor);
|
|
242
241
|
const participants = computerUseParticipants(config, input.countOverride);
|
|
243
242
|
if (participants.length > MAX_CUA_LANES)
|
|
244
243
|
return refuse("after-personas", "HUMANISH_CUA_LAB_FANOUT_INVALID", `Computer-use fan-out is capped at ${MAX_CUA_LANES} participants (resolved ${participants.length}); N concurrent paid desktops is real spend.`, actor);
|
|
245
244
|
const [first, ...rest] = participants;
|
|
246
|
-
if (
|
|
247
|
-
return refuse("after-personas", "HUMANISH_CUA_LAB_FANOUT_INVALID", "Fan-out to more than one participant is not supported on the in-process route (RunLabOptions.inProcess
|
|
245
|
+
if (driving.inProcess && rest.length > 0)
|
|
246
|
+
return refuse("after-personas", "HUMANISH_CUA_LAB_FANOUT_INVALID", "Fan-out to more than one participant is not supported on the in-process route (RunLabOptions.inProcess): fan-out provisions one independent E2B desktop per participant, which the in-process route deliberately skips. Run a single in-process participant, or fan out on the E2B route.", actor);
|
|
248
247
|
if (first === undefined)
|
|
249
248
|
throw new Error("computerUseParticipants returned no participant");
|
|
250
249
|
const appUrl = config.subject.appUrl ?? "";
|
|
250
|
+
const declaredServeUrl = config.subject.serve?.url;
|
|
251
|
+
const serveUrl = declaredServeUrl === undefined ? {} : { serveUrl: declaredServeUrl };
|
|
251
252
|
const appUrlSubject = {
|
|
252
253
|
kind: "app-url",
|
|
253
254
|
appUrl,
|
|
254
255
|
publicTargets: config.policies?.allowPublicTargets === true,
|
|
256
|
+
...serveUrl,
|
|
255
257
|
};
|
|
256
258
|
const product = config.subject.product;
|
|
257
259
|
const hosted = source === "desktop-cli" && product !== undefined
|
|
258
|
-
? { kind: "desktop-cli", product }
|
|
260
|
+
? { kind: "desktop-cli", product, ...serveUrl }
|
|
259
261
|
: (provisionedSubject(config) ?? appUrlSubject);
|
|
260
|
-
const brain = brainOf(config,
|
|
261
|
-
const runner =
|
|
262
|
+
const brain = brainOf(config, driving.createProvider);
|
|
263
|
+
const runner = driving.inProcess
|
|
262
264
|
? {
|
|
263
265
|
desktop: "in-process",
|
|
264
|
-
brain:
|
|
266
|
+
brain: callerBrainOf(config),
|
|
265
267
|
participants: [first],
|
|
266
268
|
subject: source === "local-app" ? { kind: "local-app", appUrl } : appUrlSubject,
|
|
267
269
|
}
|
|
@@ -273,7 +275,6 @@ export function planComputerUseLab(config, input) {
|
|
|
273
275
|
const provisioned = source === "clone" || source === "local-tree";
|
|
274
276
|
const base = planBase(config, {
|
|
275
277
|
dryRun: input.dryRun,
|
|
276
|
-
...(input.lab === undefined ? {} : { lab: input.lab }),
|
|
277
278
|
analysis,
|
|
278
279
|
});
|
|
279
280
|
return {
|
|
@@ -287,18 +288,11 @@ export function planComputerUseLab(config, input) {
|
|
|
287
288
|
sessionBudgetMs: config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config),
|
|
288
289
|
sandboxMs: resolveParticipantSandboxMs(config),
|
|
289
290
|
caps: capsOf(config),
|
|
290
|
-
...(input.rerun === undefined
|
|
291
|
-
? {}
|
|
292
|
-
: {
|
|
293
|
-
rerun: {
|
|
294
|
-
sourceRunId: input.rerun.sourceRunId,
|
|
295
|
-
...(input.rerun.laneIds === undefined ? {} : { participantIds: input.rerun.laneIds }),
|
|
296
|
-
},
|
|
297
|
-
}),
|
|
291
|
+
...(input.rerun === undefined ? {} : { rerun: rerunPlan(input.rerun) }),
|
|
298
292
|
requirements: base.dryRun || runner.desktop === "in-process"
|
|
299
293
|
? []
|
|
300
294
|
: desktopRequirements(config, {
|
|
301
|
-
e2b: runner.desktop === "e2b-desktop"
|
|
295
|
+
e2b: runner.desktop === "e2b-desktop",
|
|
302
296
|
brain,
|
|
303
297
|
localVm: runner.desktop === "local-vm",
|
|
304
298
|
externalCatch: !provisioned,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { ComputerUsePlan } from "../../lab/plan-types.js";
|
|
1
|
+
import type { Brain, ComputerUsePlan } from "../../lab/plan-types.js";
|
|
2
2
|
import type { LabCommsExternal } from "../../lab/types.js";
|
|
3
|
-
import {
|
|
4
|
-
import type { CuaActorLabErrorCode, CuaActorLabHooks } from "./types.js";
|
|
3
|
+
import type { CuaActorLabErrorCode } from "./types.js";
|
|
5
4
|
/**
|
|
6
5
|
* The first reason a live computer-use run cannot start on this machine: missing keys, a missing
|
|
7
6
|
* or signed-out local agent, missing subject env, a spend cap with no price, or an unreachable
|
|
@@ -10,15 +9,11 @@ import type { CuaActorLabErrorCode, CuaActorLabHooks } from "./types.js";
|
|
|
10
9
|
*/
|
|
11
10
|
export declare function liveCuaRejection(args: {
|
|
12
11
|
caps: ComputerUsePlan["caps"];
|
|
13
|
-
/** The
|
|
14
|
-
|
|
15
|
-
hooks: CuaActorLabHooks;
|
|
12
|
+
/** The plan's brain: whether a local agent drives the participant, and the model a cap prices. */
|
|
13
|
+
brain: Brain;
|
|
16
14
|
env: Record<string, string | undefined>;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
localAgentRoute: boolean;
|
|
20
|
-
preferredLocalAgent: LocalAgentId;
|
|
21
|
-
subjectEnvNames: string[];
|
|
15
|
+
/** The plan's requirements: which keys and subject env names this run needs. */
|
|
16
|
+
requirements: ComputerUsePlan["requirements"];
|
|
22
17
|
externalCommsConfig: LabCommsExternal | undefined;
|
|
23
18
|
}): Promise<{
|
|
24
19
|
code: CuaActorLabErrorCode;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pricedModel } from "../../lab/plan-base.js";
|
|
2
|
+
import { missingKeys, missingSubjectEnv } from "../../lab/requirements.js";
|
|
2
3
|
import { detectLocalAgents } from "../../actors/local-agent/cli.js";
|
|
3
4
|
import { localAgentRefusal } from "../../actors/local-agent/readiness.js";
|
|
4
5
|
import { describeMissingKeys } from "../../keys/key-resolution.js";
|
|
6
|
+
import { catchTokenOf, catchTokenRefusal } from "../../comms/external-evidence.js";
|
|
5
7
|
import { externalCatchHealthy } from "../../comms/sandbox-catch.js";
|
|
6
8
|
import { MODEL_RATES } from "../../run/pricing.js";
|
|
7
|
-
import { participantDesktopOf } from "./participant-desktop.js";
|
|
8
9
|
/** The computer-use code for each local-agent refusal; shared-world keeps the same kinds. */
|
|
9
10
|
const LOCAL_AGENT_REFUSAL_CODES = {
|
|
10
11
|
"agent-missing": "HUMANISH_CUA_LAB_AGENT_MISSING",
|
|
@@ -19,16 +20,16 @@ const LOCAL_AGENT_REFUSAL_CODES = {
|
|
|
19
20
|
* already paid for a desktop.
|
|
20
21
|
*/
|
|
21
22
|
export async function liveCuaRejection(args) {
|
|
22
|
-
const { caps,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (
|
|
23
|
+
const { caps, brain, env, requirements, externalCommsConfig } = args;
|
|
24
|
+
// The plan lists OPENAI_API_KEY only for an openai brain (a signed-in local agent or the
|
|
25
|
+
// caller's provider needs none) and E2B_API_KEY only when this run creates hosted desktops.
|
|
26
|
+
const localAgent = brain.kind === "local-agent" ? brain.agent : undefined;
|
|
27
|
+
const missing = missingKeys(requirements, env);
|
|
28
|
+
if (missing.length > 0) {
|
|
28
29
|
// The moment someone new actually hits the wall. If a signed-in coding agent is sitting
|
|
29
30
|
// right there, say so HERE rather than making them go and find an API key — that detour is
|
|
30
31
|
// where most people trying humanish stop.
|
|
31
|
-
const suggestion =
|
|
32
|
+
const suggestion = missing.includes("OPENAI_API_KEY")
|
|
32
33
|
? await (async () => {
|
|
33
34
|
const ready = (await detectLocalAgents({ env })).filter((agent) => agent.authStatus === "authenticated");
|
|
34
35
|
return ready.length === 0
|
|
@@ -39,21 +40,22 @@ export async function liveCuaRejection(args) {
|
|
|
39
40
|
: "";
|
|
40
41
|
return {
|
|
41
42
|
code: "HUMANISH_CUA_LAB_KEYS_MISSING",
|
|
42
|
-
message: `Live computer-use labs need ${
|
|
43
|
+
message: `Live computer-use labs need ${missing.join(" and ")} in the environment (values are never persisted). ${describeMissingKeys(missing, env)}${suggestion}`,
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
+
// A caller's createProvider makes the brain `caller`, so only the lab's own local agent is checked.
|
|
47
|
+
if (localAgent) {
|
|
46
48
|
// Refuse HERE, before a sandbox exists. "codex is not installed" discovered after the
|
|
47
49
|
// machine is paid for is the same information delivered at the worst possible moment.
|
|
48
|
-
const refusal = await localAgentRefusal({ agent:
|
|
50
|
+
const refusal = await localAgentRefusal({ agent: localAgent, env, caps });
|
|
49
51
|
if (refusal)
|
|
50
52
|
return { code: LOCAL_AGENT_REFUSAL_CODES[refusal.kind], message: refusal.message };
|
|
51
53
|
}
|
|
52
|
-
const
|
|
53
|
-
if (
|
|
54
|
+
const unsetSubjectEnv = missingSubjectEnv(requirements, env);
|
|
55
|
+
if (unsetSubjectEnv.length > 0) {
|
|
54
56
|
return {
|
|
55
57
|
code: "HUMANISH_CUA_LAB_SUBJECT_ENV_MISSING",
|
|
56
|
-
message: `subject.env declares ${
|
|
58
|
+
message: `subject.env declares ${unsetSubjectEnv.join(", ")} but the environment does not provide ${unsetSubjectEnv.length === 1 ? "it" : "them"} (pass via --env-file; values are never persisted).`,
|
|
57
59
|
};
|
|
58
60
|
}
|
|
59
61
|
// FAIL-CLOSED CAP TENSION (discipline #3): a maxUsd cap needs a MEASURABLE per-turn estimate.
|
|
@@ -63,18 +65,24 @@ export async function liveCuaRejection(args) {
|
|
|
63
65
|
// uncapped: an unenforceable cap is more dangerous than none. The operator adds a rate to
|
|
64
66
|
// src/run/pricing.ts (the honest place) or removes the cap.
|
|
65
67
|
if (caps.maxUsd !== undefined || caps.maxTotalUsd !== undefined) {
|
|
66
|
-
const
|
|
68
|
+
const model = pricedModel(brain);
|
|
69
|
+
const capModelId = model.trim().toLowerCase();
|
|
67
70
|
if (!MODEL_RATES[capModelId]) {
|
|
68
71
|
return {
|
|
69
72
|
code: "HUMANISH_CUA_LAB_UNPRICED_CAP",
|
|
70
|
-
message: `execution.caps declares a spend cap (maxUsd/maxTotalUsd) but src/run/pricing.ts has no rate for model "${model
|
|
73
|
+
message: `execution.caps declares a spend cap (maxUsd/maxTotalUsd) but src/run/pricing.ts has no rate for model "${model}"; add a rate or remove the cap — an unenforceable cap is refused rather than run uncapped.`,
|
|
71
74
|
};
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
// Adopter-hosted comms catch (#380): fail closed BEFORE any sandbox is created — a comms lab
|
|
75
|
-
// whose catch is unreachable collects nothing while every
|
|
78
|
+
// whose catch is unreachable collects nothing while every participant still spends. The probe asserts
|
|
76
79
|
// OUR service marker in /health, so an adopter's proxy answering 200 for everything cannot
|
|
77
80
|
// pass for a catch.
|
|
81
|
+
const tokenRefusal = externalCommsConfig === undefined
|
|
82
|
+
? undefined
|
|
83
|
+
: catchTokenRefusal(catchTokenOf(externalCommsConfig, env));
|
|
84
|
+
if (tokenRefusal !== undefined)
|
|
85
|
+
return { code: "HUMANISH_CUA_LAB_COMMS_TOKEN_INVALID", message: tokenRefusal };
|
|
78
86
|
if (externalCommsConfig && !(await externalCatchHealthy(externalCommsConfig))) {
|
|
79
87
|
return {
|
|
80
88
|
code: "HUMANISH_CUA_LAB_COMMS_CATCH_UNREACHABLE",
|
|
@@ -99,13 +99,17 @@ function snapshotPriorParticipant(stream) {
|
|
|
99
99
|
const reason = stream.ui?.state ?? stream.actor?.reason;
|
|
100
100
|
const actions = stream.actor?.counts.actions ?? 0;
|
|
101
101
|
const messages = stream.actor?.counts.messages ?? 0;
|
|
102
|
+
// The judge's status decides, so a participant the review counts as blocked is rerunnable. A
|
|
103
|
+
// bundle written before streams carried it falls back to the trace status and counts.
|
|
102
104
|
const hollow = completionReason === "goal_satisfied" && actions === 0 && messages === 0;
|
|
103
|
-
const rerunnable = stream.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
const rerunnable = stream.judgedStatus !== undefined
|
|
106
|
+
? stream.judgedStatus !== "passed"
|
|
107
|
+
: stream.status !== "passed" ||
|
|
108
|
+
actorStatus === "failed" ||
|
|
109
|
+
actorStatus === "blocked" ||
|
|
110
|
+
actorStatus === "timed_out" ||
|
|
111
|
+
completionReason === "harness_error" ||
|
|
112
|
+
hollow;
|
|
109
113
|
return {
|
|
110
114
|
participantId: stream.laneId,
|
|
111
115
|
previous: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { runLabParticipants } from "./
|
|
1
|
+
import type { runLabParticipants } from "./live-phase.js";
|
|
2
2
|
import type { CuaFinishFacts, CuaRunSetup } from "./setup.js";
|
|
3
3
|
import { type CuaActorLabResult } from "./types.js";
|
|
4
4
|
/** Builds and publishes the final bundle, runs the adapter hooks, renders the Observer and returns the result. */
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { adapterScoreFailureMessage,
|
|
1
|
+
import { adapterScoreFailureMessage, applyBrowserScorer } from "../../lab/adapter-extension.js";
|
|
2
2
|
import { redactText } from "../../evidence/redaction.js";
|
|
3
3
|
import { round6 } from "../../run/pricing.js";
|
|
4
4
|
import { foldScorerFailures, judgeExecution, OUTCOME_POLICIES, participantHarnessFailed, resultOk, } from "../../run/judge.js";
|
|
5
|
-
import { participantFactsOf, participantOutcomeOk } from "./participant-facts.js";
|
|
5
|
+
import { participantFactsOf, participantOutcomeOk, unreleasedSandboxFailures, } from "./participant-facts.js";
|
|
6
6
|
import { summarizeCuaDiagnostics } from "./diagnostics.js";
|
|
7
|
-
import { toParticipantResult } from "./
|
|
7
|
+
import { toParticipantResult } from "./participant-execution.js";
|
|
8
8
|
import { buildCuaRunBundle, judgeComputerUseRun } from "./bundle.js";
|
|
9
9
|
import { aggregateCuaSubject, projectParticipantSubjects, subjectProvenanceArg, } from "./subject-projection.js";
|
|
10
|
-
import { CUA_ACTOR_LAB_SCHEMA, CUA_FANOUT_STRATEGY, } from "./types.js";
|
|
10
|
+
import { CUA_ACTOR_LAB_SCHEMA, CUA_FANOUT_STRATEGY, participantSubjectEnv, } from "./types.js";
|
|
11
|
+
import { plannedAppUrl } from "./plan.js";
|
|
11
12
|
/** Aggregate participant counts for the result projection. */
|
|
12
13
|
function buildParticipantSummary(outcomes, participantCount, participantPlan, dryRun) {
|
|
13
14
|
if (dryRun || !outcomes) {
|
|
@@ -51,13 +52,14 @@ function buildParticipantSummary(outcomes, participantCount, participantPlan, dr
|
|
|
51
52
|
}
|
|
52
53
|
/**
|
|
53
54
|
* The computer-use lab result for a finished run. The run passes only when the Observer rendered,
|
|
54
|
-
* every
|
|
55
|
+
* every participant passed (dry-run participants pass as contracts), and no adapter score or declared scorer
|
|
55
56
|
* verdict failed; otherwise the error names the first reason.
|
|
56
57
|
*/
|
|
57
58
|
function cuaLabResult(args) {
|
|
58
59
|
const { labId, cwd, runId, appUrl, dryRun, participantRuns, outcomes, subjects, aggregateSubject, participantPlan, rerunLineage, bundle, observer, receivingWarnings, aggregateWarnings, adapterWarnings, } = args;
|
|
59
60
|
const participantCount = participantRuns.length;
|
|
60
|
-
//
|
|
61
|
+
// Participant-level pass: dry-run participants are contract-ok; live ones need a passed,
|
|
62
|
+
// engaged session.
|
|
61
63
|
const participantOk = (outcome) => participantOutcomeOk(outcome, dryRun);
|
|
62
64
|
const adapterFailure = adapterScoreFailureMessage(bundle);
|
|
63
65
|
const ok = resultOk({
|
|
@@ -81,10 +83,7 @@ function cuaLabResult(args) {
|
|
|
81
83
|
if (ok)
|
|
82
84
|
return undefined;
|
|
83
85
|
if (adapterFailure !== undefined) {
|
|
84
|
-
return {
|
|
85
|
-
code: "HUMANISH_CUA_LAB_FAILED",
|
|
86
|
-
message: adapterFailure,
|
|
87
|
-
};
|
|
86
|
+
return { code: "HUMANISH_CUA_LAB_FAILED", message: adapterFailure };
|
|
88
87
|
}
|
|
89
88
|
if (participantCount === 1) {
|
|
90
89
|
const outcome = firstOutcome;
|
|
@@ -92,9 +91,10 @@ function cuaLabResult(args) {
|
|
|
92
91
|
code: outcome?.failureCode ?? "HUMANISH_CUA_LAB_FAILED",
|
|
93
92
|
message: outcome?.sessionError ??
|
|
94
93
|
outcome?.providerCleanupError ??
|
|
94
|
+
outcome?.providerPolicyError ??
|
|
95
95
|
(outcome?.noEngagement
|
|
96
96
|
? "Actor took no actions and produced no message (likely a blank/still-loading screen); not a credible goal_satisfied."
|
|
97
|
-
: // The
|
|
97
|
+
: // The participant result (toParticipantResult) named this refusal; the N=1 envelope fell through to
|
|
98
98
|
// "did not produce a terminal session", which is false — it produced one and refused it.
|
|
99
99
|
outcome?.selfReportedBlocker
|
|
100
100
|
? "Actor reported goal_satisfied while its final message described a blocker or asked for missing instructions; not a credible pass."
|
|
@@ -164,10 +164,11 @@ function cuaLabResult(args) {
|
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
166
|
/**
|
|
167
|
-
* The run's execution failures: each
|
|
168
|
-
* that
|
|
167
|
+
* The run's execution failures: each participant whose session failed in the harness, each provider whose
|
|
168
|
+
* cleanup is unconfirmed or that reported a disallowed item after its last request, each sandbox
|
|
169
|
+
* whose release is unconfirmed, and an Observer that failed.
|
|
169
170
|
*/
|
|
170
|
-
function computerUseExecutionFailures(outcomes, observer) {
|
|
171
|
+
function computerUseExecutionFailures(outcomes, observer, runId) {
|
|
171
172
|
return [
|
|
172
173
|
...(outcomes ?? [])
|
|
173
174
|
.filter((outcome) => participantHarnessFailed(participantFactsOf(outcome)))
|
|
@@ -183,6 +184,15 @@ function computerUseExecutionFailures(outcomes, observer) {
|
|
|
183
184
|
message: `${outcome.spec.planned.id}: ${outcome.providerCleanupError}`,
|
|
184
185
|
},
|
|
185
186
|
]),
|
|
187
|
+
...(outcomes ?? []).flatMap((outcome) => outcome.providerPolicyError === undefined
|
|
188
|
+
? []
|
|
189
|
+
: [
|
|
190
|
+
{
|
|
191
|
+
kind: "provider-policy",
|
|
192
|
+
message: `${outcome.spec.planned.id}: ${outcome.providerPolicyError}`,
|
|
193
|
+
},
|
|
194
|
+
]),
|
|
195
|
+
...unreleasedSandboxFailures(outcomes, runId),
|
|
186
196
|
...(observer.ok
|
|
187
197
|
? []
|
|
188
198
|
: [
|
|
@@ -194,33 +204,34 @@ function computerUseExecutionFailures(outcomes, observer) {
|
|
|
194
204
|
];
|
|
195
205
|
}
|
|
196
206
|
/**
|
|
197
|
-
* execution.caps.maxUsd is enforced inside each
|
|
198
|
-
* spend up to N × maxUsd before any
|
|
207
|
+
* execution.caps.maxUsd is enforced inside each participant's loop independently, so an
|
|
208
|
+
* N-participant fan-out can spend up to N × maxUsd before any participant aborts, while the run cost summary reports the larger
|
|
199
209
|
* aggregate. The warning names that ceiling, unless the study declared a shared maxTotalUsd budget.
|
|
200
210
|
*/
|
|
201
|
-
function participantCapWarning(
|
|
202
|
-
const capUsd =
|
|
211
|
+
function participantCapWarning(caps, participantCount) {
|
|
212
|
+
const capUsd = caps.maxUsd;
|
|
203
213
|
if (capUsd === undefined || participantCount <= 1)
|
|
204
214
|
return undefined;
|
|
205
|
-
if (
|
|
215
|
+
if (caps.maxTotalUsd !== undefined)
|
|
206
216
|
return undefined;
|
|
207
217
|
return `execution.caps.maxUsd ($${capUsd}) is a PER-PARTICIPANT cap; ${participantCount} participants may spend up to ${participantCount} × $${capUsd} (~$${round6(capUsd * participantCount)} total) before any participant aborts. Set execution.caps.maxTotalUsd for a shared study budget.`;
|
|
208
218
|
}
|
|
209
219
|
/** Builds and publishes the final bundle, runs the adapter hooks, renders the Observer and returns the result. */
|
|
210
220
|
export async function finishCuaRun(setup, finish, ran) {
|
|
211
|
-
const { plan, input,
|
|
221
|
+
const { plan, input, cwd, streams, descriptor, run } = setup;
|
|
212
222
|
const { participantRuns, participantPlan, scrubKnownValues, bundleBase } = setup;
|
|
213
|
-
const {
|
|
223
|
+
const { rerunLineage, publicRepo, subjectArgs } = finish;
|
|
214
224
|
const { dryRun } = plan;
|
|
215
|
-
const
|
|
225
|
+
const appUrl = plannedAppUrl(plan.runner.subject);
|
|
226
|
+
const subjectEnvNames = [...participantSubjectEnv(plan.runner.subject)];
|
|
216
227
|
const { runId } = run;
|
|
217
228
|
const participantCount = participantRuns.length;
|
|
218
229
|
const { outcomes, failFastReason, receiving, receivingWarnings, externalCommsWarnings } = ran;
|
|
219
|
-
// Per-
|
|
230
|
+
// Per-participant subject projections (invariant 5).
|
|
220
231
|
const subjects = projectParticipantSubjects({ ...subjectArgs, outcomes, dryRun });
|
|
221
232
|
const aggregate = aggregateCuaSubject({ subjects, outcomes, participantCount, dryRun });
|
|
222
233
|
const aggregateSubject = aggregate.subject;
|
|
223
|
-
const capWarning = participantCapWarning(
|
|
234
|
+
const capWarning = participantCapWarning(plan.caps, participantCount);
|
|
224
235
|
const aggregateWarnings = [
|
|
225
236
|
...externalCommsWarnings,
|
|
226
237
|
...(capWarning === undefined ? [] : [capWarning]),
|
|
@@ -239,8 +250,8 @@ export async function finishCuaRun(setup, finish, ran) {
|
|
|
239
250
|
...(failFastReason === undefined ? {} : { failFastReason }),
|
|
240
251
|
});
|
|
241
252
|
const adapterWarnings = [];
|
|
242
|
-
const scorerResult = await
|
|
243
|
-
|
|
253
|
+
const scorerResult = await applyBrowserScorer({
|
|
254
|
+
scorer: input.scorer,
|
|
244
255
|
bundle,
|
|
245
256
|
context: {
|
|
246
257
|
bundle,
|
|
@@ -248,13 +259,12 @@ export async function finishCuaRun(setup, finish, ran) {
|
|
|
248
259
|
labId: plan.labId,
|
|
249
260
|
runId,
|
|
250
261
|
actor: descriptor.id,
|
|
251
|
-
|
|
262
|
+
route: "computer-use",
|
|
252
263
|
dryRun,
|
|
253
|
-
|
|
264
|
+
participantCount,
|
|
254
265
|
},
|
|
255
266
|
sanitize: (text) => redactText(scrubKnownValues(text)),
|
|
256
267
|
warnings: adapterWarnings,
|
|
257
|
-
hookLabel: "cuaHooks",
|
|
258
268
|
...(input.scorerProvenance === undefined ? {} : { scorerProvenance: input.scorerProvenance }),
|
|
259
269
|
});
|
|
260
270
|
// The one final verdict fold: scoring can only make the judged verdict stricter.
|
|
@@ -264,7 +274,7 @@ export async function finishCuaRun(setup, finish, ran) {
|
|
|
264
274
|
const finished = await run.finish(bundle);
|
|
265
275
|
const observer = await finished.renderObserver();
|
|
266
276
|
streams.attachFinal(observer);
|
|
267
|
-
const execution = judgeExecution(computerUseExecutionFailures(outcomes, observer), OUTCOME_POLICIES["computer-use"]);
|
|
277
|
+
const execution = judgeExecution(computerUseExecutionFailures(outcomes, observer, runId), OUTCOME_POLICIES["computer-use"]);
|
|
268
278
|
const result = cuaLabResult({
|
|
269
279
|
labId: plan.labId,
|
|
270
280
|
cwd,
|
|
@@ -11,7 +11,7 @@ import { type ComputerUseRunInput, type CuaActorLabResult, type RunCuaActorLabOp
|
|
|
11
11
|
export declare function runCuaActorLab(options: RunCuaActorLabOptions): Promise<CuaActorLabResult>;
|
|
12
12
|
/**
|
|
13
13
|
* A refused computer-use lab's result, at the refusal's stage: a before-scope refusal has its own
|
|
14
|
-
* envelope and no analysis record; the others come after the cwd checks, and the
|
|
14
|
+
* envelope and no analysis record; the others come after the cwd checks, and the participant cap after
|
|
15
15
|
* the personas are read.
|
|
16
16
|
*/
|
|
17
17
|
export declare function computerUseLabRefusal(options: RunCuaActorLabOptions, refusal: ComputerUseRefusal): Promise<CuaActorLabResult>;
|
|
@@ -26,8 +26,7 @@ export declare function admitComputerUsePlan(plan: ComputerUsePlan, input: Compu
|
|
|
26
26
|
* Run a computer-use plan: its local checks, then the run. The run scope in runAdmittedCuaRun
|
|
27
27
|
* finalizes any status record the run opened, on every exit, so a test or library caller does not
|
|
28
28
|
* leave the 5 s status cadence writing into a directory something else is deleting (an unrelated
|
|
29
|
-
* ENOTEMPTY). Participants
|
|
30
|
-
*
|
|
31
|
-
* cap) and by the compatibility hooks, which take the whole config.
|
|
29
|
+
* ENOTEMPTY). Participants, the brain, the subject, the caps and the residual config come from the
|
|
30
|
+
* plan. `config` is what the caller's createProvider and inProcess executor receive.
|
|
32
31
|
*/
|
|
33
32
|
export declare function runComputerUsePlan(plan: ComputerUsePlan, input: ComputerUseRunInput, config: LabConfig): Promise<CuaActorLabResult>;
|