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
|
@@ -5,8 +5,8 @@ import { type RunRerunLineage } from "../../run/bundle.js";
|
|
|
5
5
|
import type { PreparedSelectedOutputDirectory } from "../../run/contained-output.js";
|
|
6
6
|
import { type CuaActorLabErrorCode, type CuaParticipantPlan, type CuaParticipantPlanEntry, type DesktopParticipantRun } from "./types.js";
|
|
7
7
|
export declare function defaultSessionTimeoutMs(config: LabConfig): number;
|
|
8
|
-
/** Per-
|
|
9
|
-
* verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
|
|
8
|
+
/** Per-participant sandbox deadline (each one owns its own desktop). Mirrors the
|
|
9
|
+
* single-participant formula verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
|
|
10
10
|
* or local-tree: provision budget + Σ state-step budgets) + the server-side
|
|
11
11
|
* reclamation buffer. Local-tree shares the clone route's provisioning budget: it swaps a
|
|
12
12
|
* git clone for an upload+extract, but the shared install/build/state/start/probe pipeline
|
|
@@ -21,8 +21,8 @@ export declare function resolveParticipantSandboxMs(config: LabConfig): number;
|
|
|
21
21
|
*/
|
|
22
22
|
export declare function boundedConcurrency(declared: number | undefined, participantCount: number): number;
|
|
23
23
|
/**
|
|
24
|
-
* Pure pre-flight plan resolver (runs in dry-run AND live). Returns the
|
|
25
|
-
* effective concurrency, the wave count, the per-
|
|
24
|
+
* Pure pre-flight plan resolver (runs in dry-run AND live). Returns the participant table, the
|
|
25
|
+
* effective concurrency, the wave count, the per-participant session budget, and the worst-case total
|
|
26
26
|
* sandbox-minutes — BEFORE any sandbox or provider call. The same plan appears in dry-run,
|
|
27
27
|
* marked $0 (dryRun: true).
|
|
28
28
|
*/
|
|
@@ -32,7 +32,7 @@ export declare function resolveCuaParticipantPlan(config: LabConfig, opts?: {
|
|
|
32
32
|
dryRun?: boolean;
|
|
33
33
|
personas?: Map<string, ResolvedPersona>;
|
|
34
34
|
}): CuaParticipantPlan;
|
|
35
|
-
/** Print the
|
|
35
|
+
/** Print the participant plan to stderr BEFORE any sandbox/provider call (public-safe: ids, devices,
|
|
36
36
|
* digests, and budgets only — no prompt text, no secrets). */
|
|
37
37
|
export declare function emitPreflightPlan(participantPlan: CuaParticipantPlan, labId: string): void;
|
|
38
38
|
export declare function formatParticipantPlanEntry(entry: CuaParticipantPlanEntry): string;
|
|
@@ -63,5 +63,5 @@ export declare function loadCuaParticipants(args: {
|
|
|
63
63
|
code: CuaActorLabErrorCode;
|
|
64
64
|
message: string;
|
|
65
65
|
}>;
|
|
66
|
-
/** Scrub known secret values from each
|
|
66
|
+
/** Scrub known secret values from each participant's declarative snapshot before any bundle uses it. */
|
|
67
67
|
export declare function sanitizeParticipantRuns(runs: readonly DesktopParticipantRun[], scrub: (text: string) => string): void;
|
|
@@ -26,8 +26,8 @@ export function defaultSessionTimeoutMs(config) {
|
|
|
26
26
|
const room = MAX_SANDBOX_MS - SUBJECT_PROVISION_BUDGET_MS - stateBudgetMs - SANDBOX_TIMEOUT_BUFFER_MS;
|
|
27
27
|
return Math.max(MIN_DERIVED_SESSION_TIMEOUT_MS, Math.min(DEFAULT_APP_URL_SESSION_TIMEOUT_MS, room));
|
|
28
28
|
}
|
|
29
|
-
/** Per-
|
|
30
|
-
* verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
|
|
29
|
+
/** Per-participant sandbox deadline (each one owns its own desktop). Mirrors the
|
|
30
|
+
* single-participant formula verbatim so N=1 stays byte-stable: explicit sandboxTimeoutMs, else session budget + (clone
|
|
31
31
|
* or local-tree: provision budget + Σ state-step budgets) + the server-side
|
|
32
32
|
* reclamation buffer. Local-tree shares the clone route's provisioning budget: it swaps a
|
|
33
33
|
* git clone for an upload+extract, but the shared install/build/state/start/probe pipeline
|
|
@@ -162,8 +162,8 @@ function participantRunsAndPlan(planned, opts = {}) {
|
|
|
162
162
|
return { runs, participantPlan };
|
|
163
163
|
}
|
|
164
164
|
/**
|
|
165
|
-
* Pure pre-flight plan resolver (runs in dry-run AND live). Returns the
|
|
166
|
-
* effective concurrency, the wave count, the per-
|
|
165
|
+
* Pure pre-flight plan resolver (runs in dry-run AND live). Returns the participant table, the
|
|
166
|
+
* effective concurrency, the wave count, the per-participant session budget, and the worst-case total
|
|
167
167
|
* sandbox-minutes — BEFORE any sandbox or provider call. The same plan appears in dry-run,
|
|
168
168
|
* marked $0 (dryRun: true).
|
|
169
169
|
*/
|
|
@@ -171,11 +171,11 @@ export function resolveCuaParticipantPlan(config, opts = {}) {
|
|
|
171
171
|
const { countOverride, ...rest } = opts;
|
|
172
172
|
return participantRunsAndPlan(plannedParticipantsOf(config, countOverride), rest).participantPlan;
|
|
173
173
|
}
|
|
174
|
-
/** Print the
|
|
174
|
+
/** Print the participant plan to stderr BEFORE any sandbox/provider call (public-safe: ids, devices,
|
|
175
175
|
* digests, and budgets only — no prompt text, no secrets). */
|
|
176
176
|
export function emitPreflightPlan(participantPlan, labId) {
|
|
177
177
|
const lines = [];
|
|
178
|
-
lines.push(`humanish
|
|
178
|
+
lines.push(`humanish computer-use fan-out plan (${labId}): ${participantPlan.laneCount} participant(s), strategy ${participantPlan.strategy}, concurrency ${participantPlan.concurrency}${participantPlan.envLoweredConcurrencyFrom === undefined ? "" : ` (lowered from ${participantPlan.envLoweredConcurrencyFrom} by ${CUA_MAX_CONCURRENCY_ENV})`}, ${participantPlan.waves} wave(s).`);
|
|
179
179
|
lines.push(` session budget ${Math.round(participantPlan.perLaneSessionBudgetMs / 1000)}s per participant; worst-case ~${participantPlan.worstCaseSandboxMinutes} sandbox-minutes total${participantPlan.dryRun ? " (dry-run: $0)" : ""}.`);
|
|
180
180
|
for (const entry of participantPlan.lanes) {
|
|
181
181
|
lines.push(` - ${formatParticipantPlanEntry(entry)}`);
|
|
@@ -212,7 +212,7 @@ export async function compileParticipantPersonas(projectRoot, personaIds) {
|
|
|
212
212
|
export async function loadCuaParticipants(args) {
|
|
213
213
|
const { plan } = args;
|
|
214
214
|
const { participants } = plan.runner;
|
|
215
|
-
// Compile any committed personas BEFORE planning, so the plan builder stays pure and each
|
|
215
|
+
// Compile any committed personas BEFORE planning, so the plan builder stays pure and each participant's
|
|
216
216
|
// prompt carries real behavioral directives rather than a bare `Persona: <id>.` label (#381).
|
|
217
217
|
const personas = await compileParticipantPersonas(args.projectRoot, participants.map((participant) => participant.personaId));
|
|
218
218
|
const { runs: participantRuns, participantPlan } = participantRunsAndPlan({
|
|
@@ -244,7 +244,7 @@ export async function loadCuaParticipants(args) {
|
|
|
244
244
|
rerunLineage: selected.rerun,
|
|
245
245
|
};
|
|
246
246
|
}
|
|
247
|
-
/** Scrub known secret values from each
|
|
247
|
+
/** Scrub known secret values from each participant's declarative snapshot before any bundle uses it. */
|
|
248
248
|
export function sanitizeParticipantRuns(runs, scrub) {
|
|
249
249
|
for (const spec of runs) {
|
|
250
250
|
if (spec.evidenceAssignment)
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { type CuaActorDescriptor } from "../../actors/registry.js";
|
|
2
|
-
import type { ComputerUsePlan, RoutePlanResult, RouteRefusal } from "../../lab/plan-types.js";
|
|
3
|
-
import type { LabConfig,
|
|
4
|
-
import type
|
|
5
|
-
import { type CuaActorLabErrorCode, type CuaActorLabHooks, type RunCuaActorLabOptions } from "./types.js";
|
|
2
|
+
import type { ComputerUsePlan, ComputerUseRunner, RoutePlanResult, RouteRefusal } from "../../lab/plan-types.js";
|
|
3
|
+
import type { LabConfig, LabSubjectState } from "../../lab/types.js";
|
|
4
|
+
import { type CuaActorLabErrorCode, type RunCuaActorLabOptions } from "./types.js";
|
|
6
5
|
/** The error a computer-use lab returns before a run starts. */
|
|
7
6
|
export interface ComputerUseRefusal extends RouteRefusal<"computer-use", CuaActorLabErrorCode> {
|
|
8
7
|
/**
|
|
9
8
|
* Where the route returns it. "before-scope": analysis and tasks, returned before the run scope
|
|
10
9
|
* with no automatic-analysis record. "in-scope": after the cwd checks. "after-personas": after
|
|
11
|
-
* the route reads committed persona files, so a persona-file error still wins over the
|
|
10
|
+
* the route reads committed persona files, so a persona-file error still wins over the participant cap
|
|
12
11
|
* and in-process fan-out.
|
|
13
12
|
*/
|
|
14
13
|
readonly stage: "before-scope" | "in-scope" | "after-personas";
|
|
@@ -18,39 +17,32 @@ export interface ComputerUseRefusal extends RouteRefusal<"computer-use", CuaActo
|
|
|
18
17
|
export type ComputerUsePlanResult = RoutePlanResult<ComputerUsePlan, ComputerUseRefusal>;
|
|
19
18
|
/** The registered descriptor for a planned actor id; planComputerUseLab checked the registry. */
|
|
20
19
|
export declare function cuaDescriptorOf(actor: string): CuaActorDescriptor;
|
|
21
|
-
/** Which
|
|
22
|
-
export interface
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
desktopCliRoute: boolean;
|
|
26
|
-
localTreeRoute: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* Clone and local-tree both provision the subject in-sandbox (clone via git, local-tree via
|
|
29
|
-
* pack+upload) and share the install/build/state/start/probe pipeline, so every seam that gates
|
|
30
|
-
* on "does this route provision a subject" is keyed on this union.
|
|
31
|
-
*/
|
|
32
|
-
provisionedRoute: boolean;
|
|
33
|
-
localAppSubject: boolean;
|
|
34
|
-
/** A caller-supplied executor drives the subject in-process; no desktop is created. */
|
|
35
|
-
inProcessRoute: boolean;
|
|
36
|
-
serve: LabSubjectServe | undefined;
|
|
37
|
-
appUrl: string;
|
|
38
|
-
subjectRepo: string | undefined;
|
|
39
|
-
subjectEnvNames: string[];
|
|
20
|
+
/** Which of the caller's driving homes, createProvider and inProcess, a run has. */
|
|
21
|
+
export interface CallerDriving {
|
|
22
|
+
readonly inProcess: boolean;
|
|
23
|
+
readonly createProvider: boolean;
|
|
40
24
|
}
|
|
41
|
-
|
|
25
|
+
/** The driving a computer-use run's options carry. */
|
|
26
|
+
export declare function callerDrivingOf(options: {
|
|
27
|
+
readonly inProcess?: unknown;
|
|
28
|
+
readonly createProvider?: unknown;
|
|
29
|
+
}): CallerDriving;
|
|
42
30
|
/** The state a planned run's provisioned subject declares. Other subjects declare none. */
|
|
43
31
|
export declare function cuaDeclaredState(plan: ComputerUsePlan): LabSubjectState | undefined;
|
|
44
|
-
/** The
|
|
45
|
-
export declare function
|
|
32
|
+
/** The URL a refused lab's result names, from its declaration: a provisioned subject's serve URL. */
|
|
33
|
+
export declare function declaredAppUrl(config: LabConfig): string;
|
|
34
|
+
/** The URL a planned run's participants open: a provisioned subject's served URL, else its own. */
|
|
35
|
+
export declare function plannedAppUrl(subject: ComputerUseRunner["subject"]): string;
|
|
46
36
|
/**
|
|
47
37
|
* Plan a computer-use lab. It is called for any config handed to the computer-use runner, not only
|
|
48
38
|
* one routeOf sends here, so a config for another route gets this route's refusal.
|
|
49
39
|
*/
|
|
50
40
|
export declare function planComputerUseLab(config: LabConfig, input: {
|
|
51
41
|
readonly dryRun: boolean;
|
|
52
|
-
|
|
53
|
-
readonly
|
|
42
|
+
/** Whether deps.runSession is set: a caller's session runner cannot enforce maxOutputTokens. */
|
|
43
|
+
readonly hasRunSession?: boolean;
|
|
44
|
+
/** Which of the caller's driving homes are set; neither when absent. */
|
|
45
|
+
readonly driving?: CallerDriving;
|
|
54
46
|
readonly countOverride?: number;
|
|
55
47
|
readonly rerun?: RunCuaActorLabOptions["rerun"];
|
|
56
48
|
}): ComputerUsePlanResult;
|
|
@@ -15,7 +15,6 @@ import { isLocalBrowserLab } from "../../substrates/local/runtime-config.js";
|
|
|
15
15
|
import { boundedConcurrency, defaultSessionTimeoutMs, resolveParticipantSandboxMs, } from "./participant-runs.js";
|
|
16
16
|
import { MAX_SANDBOX_MS } from "../../substrates/e2b/lifetime.js";
|
|
17
17
|
import {} from "./types.js";
|
|
18
|
-
import { participantDesktopOf } from "./participant-desktop.js";
|
|
19
18
|
/** The registered descriptor for a planned actor id; planComputerUseLab checked the registry. */
|
|
20
19
|
export function cuaDescriptorOf(actor) {
|
|
21
20
|
const descriptor = actorRegistry[actor];
|
|
@@ -23,7 +22,7 @@ export function cuaDescriptorOf(actor) {
|
|
|
23
22
|
throw new Error(`planned actor "${actor}" is not a registered computer-use actor`);
|
|
24
23
|
return descriptor;
|
|
25
24
|
}
|
|
26
|
-
|
|
25
|
+
function declaredSubjectRoute(config, driving) {
|
|
27
26
|
const cloneRoute = config.subject.source === "clone";
|
|
28
27
|
const localTreeRoute = config.subject.source === "local-tree";
|
|
29
28
|
const provisionedRoute = cloneRoute || localTreeRoute;
|
|
@@ -34,34 +33,36 @@ export function cuaSubjectRoute(config, hooks) {
|
|
|
34
33
|
localTreeRoute,
|
|
35
34
|
provisionedRoute,
|
|
36
35
|
localAppSubject: config.subject.source === "local-app",
|
|
37
|
-
inProcessRoute:
|
|
36
|
+
inProcessRoute: driving.inProcess,
|
|
38
37
|
serve,
|
|
39
38
|
appUrl: (provisionedRoute ? serve?.url : config.subject.appUrl) ?? "",
|
|
40
39
|
subjectRepo: cloneRoute ? (config.subject.repos?.[0] ?? "") : undefined,
|
|
41
40
|
subjectEnvNames: provisionedRoute ? (config.subject.env ?? []) : [],
|
|
42
41
|
};
|
|
43
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
|
+
}
|
|
44
50
|
/** The state a planned run's provisioned subject declares. Other subjects declare none. */
|
|
45
51
|
export function cuaDeclaredState(plan) {
|
|
46
52
|
const { subject } = plan.runner;
|
|
47
53
|
return subject.kind === "clone" || subject.kind === "local-tree" ? subject.state : undefined;
|
|
48
54
|
}
|
|
49
|
-
/** The
|
|
50
|
-
export function
|
|
51
|
-
const {
|
|
52
|
-
const provisioned = subject.
|
|
53
|
-
return
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
serve: provisioned?.serve,
|
|
61
|
-
appUrl: provisioned?.serve.url ?? ("appUrl" in subject ? subject.appUrl : ""),
|
|
62
|
-
subjectRepo: subject.kind === "clone" ? subject.repo : undefined,
|
|
63
|
-
subjectEnvNames: [...(provisioned?.env ?? [])],
|
|
64
|
-
};
|
|
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 : "";
|
|
65
66
|
}
|
|
66
67
|
const invalid = (message) => ({
|
|
67
68
|
code: "HUMANISH_CUA_LAB_SUBJECT_INVALID",
|
|
@@ -72,22 +73,22 @@ const invalid = (message) => ({
|
|
|
72
73
|
* is touched. The parser enforces most of these too; the engine repeats them for library callers
|
|
73
74
|
* that hand it a config directly. The groups run in this order, and each returns its first reason.
|
|
74
75
|
*/
|
|
75
|
-
function cuaLabRejection(config,
|
|
76
|
-
return (unsupportedDeclarationReason(config,
|
|
76
|
+
function cuaLabRejection(config, hasRunSession, driving, subjectRoute) {
|
|
77
|
+
return (unsupportedDeclarationReason(config, hasRunSession, driving, subjectRoute) ??
|
|
77
78
|
subjectStructureReason(config, subjectRoute) ??
|
|
78
79
|
entryTargetReason(config, subjectRoute) ??
|
|
79
|
-
driverReason(
|
|
80
|
+
driverReason(driving, subjectRoute) ??
|
|
80
81
|
rosterShapeReason(config));
|
|
81
82
|
}
|
|
82
83
|
/** A declaration this route cannot honor, for any subject or with the caller's own driver. */
|
|
83
|
-
function unsupportedDeclarationReason(config,
|
|
84
|
+
function unsupportedDeclarationReason(config, hasRunSession, driving, { inProcessRoute }) {
|
|
84
85
|
const reason = desktopMediaValidationReason(config) ||
|
|
85
86
|
outputTokenLimitValidationReason(config) ||
|
|
86
87
|
scenarioCapsValidationReason(config);
|
|
87
88
|
if (reason)
|
|
88
89
|
return invalid(reason);
|
|
89
90
|
if (config.actors[0]?.maxOutputTokens !== undefined &&
|
|
90
|
-
(
|
|
91
|
+
(hasRunSession || driving.createProvider || driving.inProcess))
|
|
91
92
|
return invalid("maxOutputTokens cannot be enforced by a custom runSession/provider/executor route.");
|
|
92
93
|
const receivingReason = receivingEmailValidationReason(config);
|
|
93
94
|
if (receivingReason)
|
|
@@ -151,14 +152,14 @@ function entryTargetReason(config, subjectRoute) {
|
|
|
151
152
|
: "subject.appUrl and actors[0].lanes[].target entries must be valid http(s) URLs.",
|
|
152
153
|
};
|
|
153
154
|
}
|
|
154
|
-
/** Something to drive the subject: the caller's executor with its provider
|
|
155
|
-
function driverReason(
|
|
155
|
+
/** Something to drive the subject: the caller's executor with its provider. */
|
|
156
|
+
function driverReason(driving, { localAppSubject, inProcessRoute }) {
|
|
156
157
|
// A custom executor needs a custom provider too: the default OpenAI provider is vision-based
|
|
157
158
|
// and would fail closed against an executor that returns no screenshot.
|
|
158
|
-
if (
|
|
159
|
+
if (driving.inProcess && !driving.createProvider)
|
|
159
160
|
return {
|
|
160
161
|
code: "HUMANISH_CUA_LAB_EXECUTOR_NO_PROVIDER",
|
|
161
|
-
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).",
|
|
162
163
|
};
|
|
163
164
|
// There is no built-in in-process driver for a local app.
|
|
164
165
|
if (localAppSubject && !inProcessRoute)
|
|
@@ -166,21 +167,12 @@ function driverReason(config, hooks, { localAppSubject, inProcessRoute }) {
|
|
|
166
167
|
code: "HUMANISH_CUA_LAB_LOCAL_APP_NO_EXECUTOR",
|
|
167
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.",
|
|
168
169
|
};
|
|
169
|
-
// runLab gives a local browser study its desktop lane; a direct route call or an in-process
|
|
170
|
-
// executor on the same lab has none.
|
|
171
|
-
if (config.subject.source === "app-url" &&
|
|
172
|
-
config.execution?.target === "local" &&
|
|
173
|
-
participantDesktopOf(hooks) === undefined)
|
|
174
|
-
return {
|
|
175
|
-
code: "HUMANISH_CUA_LAB_LOCAL_DESKTOP_MISSING",
|
|
176
|
-
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.",
|
|
177
|
-
};
|
|
178
170
|
return undefined;
|
|
179
171
|
}
|
|
180
|
-
/** The
|
|
172
|
+
/** The participant roster, then the sandbox deadline its session budget derives. */
|
|
181
173
|
function rosterShapeReason(config) {
|
|
182
|
-
//
|
|
183
|
-
// 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.
|
|
184
176
|
const fanoutReason = cuaLaneValidationReason(config);
|
|
185
177
|
if (fanoutReason)
|
|
186
178
|
return { code: "HUMANISH_CUA_LAB_FANOUT_INVALID", message: fanoutReason };
|
|
@@ -195,12 +187,17 @@ function rosterShapeReason(config) {
|
|
|
195
187
|
const headroomMs = derivedSandboxMs - sessionMs;
|
|
196
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.`);
|
|
197
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
|
+
}
|
|
198
194
|
/**
|
|
199
195
|
* Plan a computer-use lab. It is called for any config handed to the computer-use runner, not only
|
|
200
196
|
* one routeOf sends here, so a config for another route gets this route's refusal.
|
|
201
197
|
*/
|
|
202
198
|
export function planComputerUseLab(config, input) {
|
|
203
|
-
const
|
|
199
|
+
const hasRunSession = input.hasRunSession === true;
|
|
200
|
+
const driving = input.driving ?? { inProcess: false, createProvider: false };
|
|
204
201
|
const refuse = (stage, code, message, actor) => ({
|
|
205
202
|
ok: false,
|
|
206
203
|
refusal: {
|
|
@@ -223,10 +220,10 @@ export function planComputerUseLab(config, input) {
|
|
|
223
220
|
if (!descriptor || !isCuaActorDescriptor(descriptor))
|
|
224
221
|
return refuse("in-scope", "HUMANISH_CUA_LAB_ACTOR_UNSUPPORTED", `actors[0].type "${actorType}" is not a registered computer-use actor.`);
|
|
225
222
|
const actor = descriptor.id;
|
|
226
|
-
const rejection = cuaLabRejection(config,
|
|
223
|
+
const rejection = cuaLabRejection(config, hasRunSession, driving, declaredSubjectRoute(config, driving));
|
|
227
224
|
if (rejection)
|
|
228
225
|
return refuse("in-scope", rejection.code, rejection.message, actor);
|
|
229
|
-
// 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.
|
|
230
227
|
// It comes after the rules above, so a shared-world config that breaks one of them, which runLab
|
|
231
228
|
// sends here, still gets that rule's message.
|
|
232
229
|
if (config.subject.topology === "shared-world")
|
|
@@ -234,9 +231,9 @@ export function planComputerUseLab(config, input) {
|
|
|
234
231
|
// The in-process route drives subject.appUrl on this machine and creates no desktop, so it would
|
|
235
232
|
// skip the subject a clone, local-tree or desktop-cli lab declares.
|
|
236
233
|
const source = config.subject.source;
|
|
237
|
-
if (
|
|
234
|
+
if (driving.inProcess &&
|
|
238
235
|
(source === "clone" || source === "local-tree" || source === "desktop-cli"))
|
|
239
|
-
return refuse("in-scope", "HUMANISH_CUA_LAB_SUBJECT_INVALID", `
|
|
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);
|
|
240
237
|
// The parser's rule; without a product the desktop study fails later.
|
|
241
238
|
const productReason = desktopCliProductReason(config);
|
|
242
239
|
if (productReason)
|
|
@@ -245,22 +242,25 @@ export function planComputerUseLab(config, input) {
|
|
|
245
242
|
if (participants.length > MAX_CUA_LANES)
|
|
246
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);
|
|
247
244
|
const [first, ...rest] = participants;
|
|
248
|
-
if (
|
|
249
|
-
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);
|
|
250
247
|
if (first === undefined)
|
|
251
248
|
throw new Error("computerUseParticipants returned no participant");
|
|
252
249
|
const appUrl = config.subject.appUrl ?? "";
|
|
250
|
+
const declaredServeUrl = config.subject.serve?.url;
|
|
251
|
+
const serveUrl = declaredServeUrl === undefined ? {} : { serveUrl: declaredServeUrl };
|
|
253
252
|
const appUrlSubject = {
|
|
254
253
|
kind: "app-url",
|
|
255
254
|
appUrl,
|
|
256
255
|
publicTargets: config.policies?.allowPublicTargets === true,
|
|
256
|
+
...serveUrl,
|
|
257
257
|
};
|
|
258
258
|
const product = config.subject.product;
|
|
259
259
|
const hosted = source === "desktop-cli" && product !== undefined
|
|
260
|
-
? { kind: "desktop-cli", product }
|
|
260
|
+
? { kind: "desktop-cli", product, ...serveUrl }
|
|
261
261
|
: (provisionedSubject(config) ?? appUrlSubject);
|
|
262
|
-
const brain = brainOf(config,
|
|
263
|
-
const runner =
|
|
262
|
+
const brain = brainOf(config, driving.createProvider);
|
|
263
|
+
const runner = driving.inProcess
|
|
264
264
|
? {
|
|
265
265
|
desktop: "in-process",
|
|
266
266
|
brain: callerBrainOf(config),
|
|
@@ -275,7 +275,6 @@ export function planComputerUseLab(config, input) {
|
|
|
275
275
|
const provisioned = source === "clone" || source === "local-tree";
|
|
276
276
|
const base = planBase(config, {
|
|
277
277
|
dryRun: input.dryRun,
|
|
278
|
-
...(input.lab === undefined ? {} : { lab: input.lab }),
|
|
279
278
|
analysis,
|
|
280
279
|
});
|
|
281
280
|
return {
|
|
@@ -289,18 +288,11 @@ export function planComputerUseLab(config, input) {
|
|
|
289
288
|
sessionBudgetMs: config.execution?.timeoutMs ?? defaultSessionTimeoutMs(config),
|
|
290
289
|
sandboxMs: resolveParticipantSandboxMs(config),
|
|
291
290
|
caps: capsOf(config),
|
|
292
|
-
...(input.rerun === undefined
|
|
293
|
-
? {}
|
|
294
|
-
: {
|
|
295
|
-
rerun: {
|
|
296
|
-
sourceRunId: input.rerun.sourceRunId,
|
|
297
|
-
...(input.rerun.laneIds === undefined ? {} : { participantIds: input.rerun.laneIds }),
|
|
298
|
-
},
|
|
299
|
-
}),
|
|
291
|
+
...(input.rerun === undefined ? {} : { rerun: rerunPlan(input.rerun) }),
|
|
300
292
|
requirements: base.dryRun || runner.desktop === "in-process"
|
|
301
293
|
? []
|
|
302
294
|
: desktopRequirements(config, {
|
|
303
|
-
e2b: runner.desktop === "e2b-desktop"
|
|
295
|
+
e2b: runner.desktop === "e2b-desktop",
|
|
304
296
|
brain,
|
|
305
297
|
localVm: runner.desktop === "local-vm",
|
|
306
298
|
externalCatch: !provisioned,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Brain, ComputerUsePlan } from "../../lab/plan-types.js";
|
|
2
2
|
import type { LabCommsExternal } from "../../lab/types.js";
|
|
3
|
-
import type { CuaActorLabErrorCode
|
|
3
|
+
import type { CuaActorLabErrorCode } from "./types.js";
|
|
4
4
|
/**
|
|
5
5
|
* The first reason a live computer-use run cannot start on this machine: missing keys, a missing
|
|
6
6
|
* or signed-out local agent, missing subject env, a spend cap with no price, or an unreachable
|
|
@@ -11,11 +11,9 @@ export declare function liveCuaRejection(args: {
|
|
|
11
11
|
caps: ComputerUsePlan["caps"];
|
|
12
12
|
/** The plan's brain: whether a local agent drives the participant, and the model a cap prices. */
|
|
13
13
|
brain: Brain;
|
|
14
|
-
hooks: CuaActorLabHooks;
|
|
15
14
|
env: Record<string, string | undefined>;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
subjectEnvNames: string[];
|
|
15
|
+
/** The plan's requirements: which keys and subject env names this run needs. */
|
|
16
|
+
requirements: ComputerUsePlan["requirements"];
|
|
19
17
|
externalCommsConfig: LabCommsExternal | undefined;
|
|
20
18
|
}): Promise<{
|
|
21
19
|
code: CuaActorLabErrorCode;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
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,19 +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, brain,
|
|
23
|
-
// The
|
|
24
|
-
//
|
|
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.
|
|
25
26
|
const localAgent = brain.kind === "local-agent" ? brain.agent : undefined;
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
...(e2bApiKey || participantDesktopOf(hooks) !== undefined ? [] : ["E2B_API_KEY"]),
|
|
29
|
-
];
|
|
30
|
-
if (missingKeys.length > 0) {
|
|
27
|
+
const missing = missingKeys(requirements, env);
|
|
28
|
+
if (missing.length > 0) {
|
|
31
29
|
// The moment someone new actually hits the wall. If a signed-in coding agent is sitting
|
|
32
30
|
// right there, say so HERE rather than making them go and find an API key — that detour is
|
|
33
31
|
// where most people trying humanish stop.
|
|
34
|
-
const suggestion =
|
|
32
|
+
const suggestion = missing.includes("OPENAI_API_KEY")
|
|
35
33
|
? await (async () => {
|
|
36
34
|
const ready = (await detectLocalAgents({ env })).filter((agent) => agent.authStatus === "authenticated");
|
|
37
35
|
return ready.length === 0
|
|
@@ -42,21 +40,22 @@ export async function liveCuaRejection(args) {
|
|
|
42
40
|
: "";
|
|
43
41
|
return {
|
|
44
42
|
code: "HUMANISH_CUA_LAB_KEYS_MISSING",
|
|
45
|
-
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}`,
|
|
46
44
|
};
|
|
47
45
|
}
|
|
48
|
-
|
|
46
|
+
// A caller's createProvider makes the brain `caller`, so only the lab's own local agent is checked.
|
|
47
|
+
if (localAgent) {
|
|
49
48
|
// Refuse HERE, before a sandbox exists. "codex is not installed" discovered after the
|
|
50
49
|
// machine is paid for is the same information delivered at the worst possible moment.
|
|
51
50
|
const refusal = await localAgentRefusal({ agent: localAgent, env, caps });
|
|
52
51
|
if (refusal)
|
|
53
52
|
return { code: LOCAL_AGENT_REFUSAL_CODES[refusal.kind], message: refusal.message };
|
|
54
53
|
}
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
54
|
+
const unsetSubjectEnv = missingSubjectEnv(requirements, env);
|
|
55
|
+
if (unsetSubjectEnv.length > 0) {
|
|
57
56
|
return {
|
|
58
57
|
code: "HUMANISH_CUA_LAB_SUBJECT_ENV_MISSING",
|
|
59
|
-
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).`,
|
|
60
59
|
};
|
|
61
60
|
}
|
|
62
61
|
// FAIL-CLOSED CAP TENSION (discipline #3): a maxUsd cap needs a MEASURABLE per-turn estimate.
|
|
@@ -76,9 +75,14 @@ export async function liveCuaRejection(args) {
|
|
|
76
75
|
}
|
|
77
76
|
}
|
|
78
77
|
// Adopter-hosted comms catch (#380): fail closed BEFORE any sandbox is created — a comms lab
|
|
79
|
-
// whose catch is unreachable collects nothing while every
|
|
78
|
+
// whose catch is unreachable collects nothing while every participant still spends. The probe asserts
|
|
80
79
|
// OUR service marker in /health, so an adopter's proxy answering 200 for everything cannot
|
|
81
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 };
|
|
82
86
|
if (externalCommsConfig && !(await externalCatchHealthy(externalCommsConfig))) {
|
|
83
87
|
return {
|
|
84
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. */
|