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
|
@@ -9,6 +9,6 @@ export declare function startParticipantMedia(ctx: E2BParticipantContext, state:
|
|
|
9
9
|
export declare function openParticipantSurface(ctx: E2BParticipantContext, state: E2BParticipantState, desktop: E2BDesktopSandbox): Promise<void>;
|
|
10
10
|
/**
|
|
11
11
|
* Measure the browser window and start the live stream. A stream that cannot start is a warning;
|
|
12
|
-
* unusable browser geometry fails the
|
|
12
|
+
* unusable browser geometry fails the participant before any action.
|
|
13
13
|
*/
|
|
14
14
|
export declare function startParticipantStream(ctx: E2BParticipantContext, state: E2BParticipantState, desktop: E2BDesktopSandbox): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// The second half of an E2B desktop
|
|
1
|
+
// The second half of an E2B desktop participant's preparation, and the start of its session: speech and
|
|
2
2
|
// recording, then the browser or terminal the participant sees, then the live stream. Each step
|
|
3
|
-
// fills the
|
|
3
|
+
// fills the participant's state.
|
|
4
4
|
import { redactText, toErrorMessage } from "../../../evidence/redaction.js";
|
|
5
5
|
import { CHROME_DEVTOOLS_PORT, DESKTOP_SETTLE_MS, openDesktopBrowserTarget, openDesktopTerminal, startDesktopStream, } from "../../../substrates/e2b/desktop-browser.js";
|
|
6
6
|
import { captureDesktopBrowserGeometry } from "../../../substrates/e2b/desktop-geometry.js";
|
|
@@ -10,7 +10,7 @@ import { applyParticipantMobileFidelity, mobileLaunchFlags } from "./fidelity.js
|
|
|
10
10
|
/** Start the declared speech worker and screen recording. A recording that cannot start is a warning. */
|
|
11
11
|
export async function startParticipantMedia(ctx, state, desktop) {
|
|
12
12
|
const { spec, deps, warnings } = ctx;
|
|
13
|
-
const requestedMedia = deps.
|
|
13
|
+
const requestedMedia = deps.residual.execution?.desktop?.media;
|
|
14
14
|
if (!ctx.desktopCliRoute && requestedMedia?.microphone?.source === "speech") {
|
|
15
15
|
state.speech = await startE2BDesktopMedia({
|
|
16
16
|
desktop,
|
|
@@ -20,7 +20,7 @@ export async function startParticipantMedia(ctx, state, desktop) {
|
|
|
20
20
|
requestTimeoutMs: deps.requestTimeoutMs,
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
-
const requestedRecording = deps.
|
|
23
|
+
const requestedRecording = deps.residual.execution?.desktop?.recording;
|
|
24
24
|
if (requestedRecording) {
|
|
25
25
|
try {
|
|
26
26
|
state.recording = await startE2BDesktopRecording({
|
|
@@ -43,28 +43,28 @@ export async function startParticipantMedia(ctx, state, desktop) {
|
|
|
43
43
|
*/
|
|
44
44
|
export async function openParticipantSurface(ctx, state, desktop) {
|
|
45
45
|
const { spec, deps, warnings, targetUrl } = ctx;
|
|
46
|
-
const {
|
|
47
|
-
if (
|
|
46
|
+
const { residual, subject } = deps;
|
|
47
|
+
if (subject.kind === "desktop-cli") {
|
|
48
48
|
// A terminal window, opened the way the browser is opened on every other route: the
|
|
49
49
|
// participant arrives at a desktop with the thing they were asked to use already in front
|
|
50
50
|
// of them. They can still open another from the dock — that is the point of a desktop.
|
|
51
|
-
await openDesktopTerminal(desktop, deps.requestTimeoutMs,
|
|
51
|
+
await openDesktopTerminal(desktop, deps.requestTimeoutMs, subject.product.workdir);
|
|
52
52
|
await desktop.wait(DESKTOP_SETTLE_MS).catch(() => undefined);
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
|
-
const requestedMedia =
|
|
55
|
+
const requestedMedia = residual.execution?.desktop?.media;
|
|
56
56
|
// A declared camera (#509) is in place before the browser starts: the feed is generated or
|
|
57
|
-
// uploaded first, and a feed that cannot be produced fails the
|
|
57
|
+
// uploaded first, and a feed that cannot be produced fails the participant closed here.
|
|
58
58
|
const mediaEvidence = requestedMedia === undefined
|
|
59
59
|
? undefined
|
|
60
|
-
: await prepareDesktopMedia(desktop, requestedMedia,
|
|
61
|
-
const emulationFlags = mobileLaunchFlags(
|
|
62
|
-
const browserLaunch = await openDesktopBrowserTarget(desktop, targetUrl, deps.requestTimeoutMs,
|
|
60
|
+
: await prepareDesktopMedia(desktop, requestedMedia, residual.policies?.mediaPermission ?? "prompt", deps.labCwd, deps.requestTimeoutMs);
|
|
61
|
+
const emulationFlags = mobileLaunchFlags(residual, spec);
|
|
62
|
+
const browserLaunch = await openDesktopBrowserTarget(desktop, targetUrl, deps.requestTimeoutMs, residual.execution?.desktop?.browser, [...emulationFlags, ...(mediaEvidence?.flags ?? [])], state.speech?.env ?? state.recording?.env);
|
|
63
63
|
state.desktopBrowser =
|
|
64
64
|
mediaEvidence === undefined
|
|
65
65
|
? browserLaunch.evidence
|
|
66
66
|
: {
|
|
67
|
-
requested:
|
|
67
|
+
requested: residual.execution?.desktop?.browser ?? "default",
|
|
68
68
|
...browserLaunch.evidence,
|
|
69
69
|
media: mediaEvidence,
|
|
70
70
|
};
|
|
@@ -77,7 +77,7 @@ export async function openParticipantSurface(ctx, state, desktop) {
|
|
|
77
77
|
noteDevToolsReadiness(ctx, browserLaunch.devTools, emulationFlags.length > 0);
|
|
78
78
|
await desktop.wait(DESKTOP_SETTLE_MS).catch(() => undefined);
|
|
79
79
|
// Mobile fidelity (#221) is applied outside startParticipantStream's best-effort catch, so a request
|
|
80
|
-
// that cannot be applied fails the
|
|
80
|
+
// that cannot be applied fails the participant closed.
|
|
81
81
|
state.fidelity = await applyParticipantMobileFidelity({
|
|
82
82
|
desktop,
|
|
83
83
|
spec,
|
|
@@ -90,14 +90,14 @@ export async function openParticipantSurface(ctx, state, desktop) {
|
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
|
-
* DevTools answering later than this after launch is recorded as a warning on the
|
|
93
|
+
* DevTools answering later than this after launch is recorded as a warning on the participant. Six live
|
|
94
94
|
* launches answered in 4.8-7.7 s; the reads this wait now guards used to give up at about 11 s.
|
|
95
95
|
*/
|
|
96
96
|
const SLOW_DEVTOOLS_MS = 10_000;
|
|
97
97
|
/**
|
|
98
98
|
* Records how Chrome's DevTools port answered after launch, as a timed phase in the bundle. A
|
|
99
|
-
* device-emulated
|
|
100
|
-
* over DevTools. Other
|
|
99
|
+
* device-emulated participant fails closed when the port never answered, because emulation is applied
|
|
100
|
+
* over DevTools. Other participants continue with a warning: their DevTools reads already degrade to
|
|
101
101
|
* warnings of their own.
|
|
102
102
|
*/
|
|
103
103
|
function noteDevToolsReadiness(ctx, devTools, emulated) {
|
|
@@ -132,7 +132,7 @@ function noteDevToolsReadiness(ctx, devTools, emulated) {
|
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
134
134
|
* Measure the browser window and start the live stream. A stream that cannot start is a warning;
|
|
135
|
-
* unusable browser geometry fails the
|
|
135
|
+
* unusable browser geometry fails the participant before any action.
|
|
136
136
|
*/
|
|
137
137
|
export async function startParticipantStream(ctx, state, desktop) {
|
|
138
138
|
const { spec, deps, warnings } = ctx;
|
|
@@ -156,8 +156,8 @@ export async function startParticipantStream(ctx, state, desktop) {
|
|
|
156
156
|
state.browserWindowId = browserGeometry.browserWindowId;
|
|
157
157
|
state.browserTargetId = browserGeometry.browserTargetId;
|
|
158
158
|
}
|
|
159
|
-
// A browser
|
|
160
|
-
// and streams the whole desktop: a person studying a terminal app opens other windows, and
|
|
159
|
+
// A browser participant streams its browser window when one was found. A CLI participant has
|
|
160
|
+
// no window id and streams the whole desktop: a person studying a terminal app opens other windows, and
|
|
161
161
|
// a stream bound to the first one would quietly stop being evidence.
|
|
162
162
|
await startDesktopStream(desktop, state.browserWindowId);
|
|
163
163
|
const candidateStreamUrl = desktop.stream.getUrl({
|
|
@@ -168,8 +168,9 @@ export async function startParticipantStream(ctx, state, desktop) {
|
|
|
168
168
|
});
|
|
169
169
|
if (typeof candidateStreamUrl === "string" && candidateStreamUrl.trim().length > 0) {
|
|
170
170
|
state.streamUrl = candidateStreamUrl;
|
|
171
|
-
await deps.
|
|
172
|
-
|
|
171
|
+
await deps.onStream({
|
|
172
|
+
type: "ready",
|
|
173
|
+
participantId: spec.planned.id,
|
|
173
174
|
sandboxId: desktop.sandboxId,
|
|
174
175
|
simId: spec.recordId,
|
|
175
176
|
streamId: spec.streamId,
|
|
@@ -184,7 +185,7 @@ export async function startParticipantStream(ctx, state, desktop) {
|
|
|
184
185
|
warnings.push(`Live desktop stream unavailable (run continues; evidence still captured): ${redactText(deps.scrubKnownValues(toErrorMessage(error)))}`);
|
|
185
186
|
}
|
|
186
187
|
// This is outside the stream's best-effort catch: unusable geometry is a harness failure,
|
|
187
|
-
// never a participant finding about missing controls. Both
|
|
188
|
+
// never a participant finding about missing controls. Both computer-use and shared-world participants
|
|
188
189
|
// use this route.
|
|
189
190
|
if (state.initialBrowserGeometry?.unusable !== undefined) {
|
|
190
191
|
state.failureCode = "HUMANISH_CUA_LAB_DEVICE_GEOMETRY";
|
|
@@ -12,11 +12,11 @@ import type { E2BDesktopSandbox } from "../../../substrates/e2b/sdk.js";
|
|
|
12
12
|
import type { ParticipantDesktopEvidence } from "../participant-desktop.js";
|
|
13
13
|
import type { ParticipantComms, RunningCommsCatch } from "./comms.js";
|
|
14
14
|
import type { ParticipantFidelity } from "./fidelity.js";
|
|
15
|
-
import type { CuaActorLabErrorCode,
|
|
16
|
-
/** What every step of one
|
|
15
|
+
import type { CuaActorLabErrorCode, E2BDesktopDeps, DesktopParticipantRun, SandboxReleaseFact } from "../types.js";
|
|
16
|
+
/** What every step of one participant reads: its spec, the run's dependencies and where it points. */
|
|
17
17
|
export interface E2BParticipantContext {
|
|
18
18
|
readonly spec: DesktopParticipantRun;
|
|
19
|
-
readonly deps:
|
|
19
|
+
readonly deps: E2BDesktopDeps;
|
|
20
20
|
readonly warnings: string[];
|
|
21
21
|
readonly targetUrl: string;
|
|
22
22
|
readonly desktopCliRoute: boolean;
|
|
@@ -37,6 +37,7 @@ export interface E2BParticipantState {
|
|
|
37
37
|
sandboxTornDownAtMs: number | undefined;
|
|
38
38
|
desktopResources: DesktopResourceObservation | undefined;
|
|
39
39
|
released: boolean;
|
|
40
|
+
sandboxRelease: SandboxReleaseFact | undefined;
|
|
40
41
|
failureCode: CuaActorLabErrorCode | undefined;
|
|
41
42
|
commsCatch: RunningCommsCatch | undefined;
|
|
42
43
|
commsArtifactPath: string | undefined;
|
|
@@ -61,5 +62,5 @@ export interface E2BParticipantState {
|
|
|
61
62
|
streamUrl: string | undefined;
|
|
62
63
|
}
|
|
63
64
|
export declare function newParticipantState(spec: DesktopParticipantRun): E2BParticipantState;
|
|
64
|
-
/** The
|
|
65
|
+
/** The participant's outcome evidence, read from its state. */
|
|
65
66
|
export declare function desktopEvidenceOf(state: E2BParticipantState): ParticipantDesktopEvidence;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// What one E2B desktop
|
|
2
|
-
// record in order, and desktopEvidenceOf reads it for the
|
|
1
|
+
// What one E2B desktop participant records as it runs. The prepare, start and teardown steps fill one
|
|
2
|
+
// record in order, and desktopEvidenceOf reads it for the participant's outcome.
|
|
3
3
|
import { declaredScreenForRender, } from "../../../substrates/e2b/desktop-geometry.js";
|
|
4
4
|
export function newParticipantState(spec) {
|
|
5
5
|
const declaredScreen = declaredScreenForRender(spec.planned.device.preset, spec.planned.device.name, spec.planned.device.resolution);
|
|
@@ -11,6 +11,7 @@ export function newParticipantState(spec) {
|
|
|
11
11
|
sandboxTornDownAtMs: undefined,
|
|
12
12
|
desktopResources: undefined,
|
|
13
13
|
released: false,
|
|
14
|
+
sandboxRelease: undefined,
|
|
14
15
|
failureCode: undefined,
|
|
15
16
|
commsCatch: undefined,
|
|
16
17
|
commsArtifactPath: undefined,
|
|
@@ -42,7 +43,7 @@ export function newParticipantState(spec) {
|
|
|
42
43
|
streamUrl: undefined,
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
|
-
/** The
|
|
46
|
+
/** The participant's outcome evidence, read from its state. */
|
|
46
47
|
export function desktopEvidenceOf(state) {
|
|
47
48
|
// Host-side approximation of the E2B desktop's billed lifetime; feeds the desktop-minute cost
|
|
48
49
|
// estimate. Never negative.
|
|
@@ -54,6 +55,7 @@ export function desktopEvidenceOf(state) {
|
|
|
54
55
|
...(desktopDurationMs === undefined ? {} : { desktopDurationMs }),
|
|
55
56
|
...(state.desktopResources === undefined ? {} : { desktopResources: state.desktopResources }),
|
|
56
57
|
released: state.released,
|
|
58
|
+
...(state.sandboxRelease === undefined ? {} : { sandboxRelease: state.sandboxRelease }),
|
|
57
59
|
streamUrlPresent: state.streamUrl !== undefined,
|
|
58
60
|
...(state.subjectCommit === undefined ? {} : { subjectCommit: state.subjectCommit }),
|
|
59
61
|
...(state.desktopBrowser === undefined ? {} : { desktopBrowser: state.desktopBrowser }),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { E2BParticipantContext, E2BParticipantState } from "./state.js";
|
|
2
2
|
/**
|
|
3
|
-
* Finish a
|
|
3
|
+
* Finish a participant: collect its final geometry and comms evidence, then stop its media and release
|
|
4
4
|
* its sandbox. Evidence failures are warnings; the release always runs.
|
|
5
5
|
*/
|
|
6
6
|
export declare function finishE2BDesktop(ctx: E2BParticipantContext, state: E2BParticipantState, failed: boolean): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Teardown for one E2B desktop
|
|
1
|
+
// Teardown for one E2B desktop participant: its final geometry and comms evidence are collected, then the
|
|
2
2
|
// recording and speech worker, then the sandbox is released by id (or kept for debugging), with a
|
|
3
3
|
// warning for every outcome that is not a confirmed release.
|
|
4
4
|
import { collectDesktopRecording } from "../../../evidence/desktop-recording-artifact.js";
|
|
@@ -8,14 +8,14 @@ import { e2bShell } from "../../../substrates/e2b/shell.js";
|
|
|
8
8
|
import { drainCommsEvidence } from "./comms.js";
|
|
9
9
|
import { finalParticipantGeometry } from "./fidelity.js";
|
|
10
10
|
/**
|
|
11
|
-
* Each route's own keep flag gates its own
|
|
12
|
-
*
|
|
11
|
+
* Each route's own keep flag gates its own participants only: a clone.keep can never leak into a
|
|
12
|
+
* local-tree participant's teardown decision, and vice versa.
|
|
13
13
|
*/
|
|
14
14
|
function participantKeepReason(deps) {
|
|
15
|
-
const {
|
|
16
|
-
if (
|
|
15
|
+
const { residual, subject } = deps;
|
|
16
|
+
if (subject.kind === "clone" && residual.subject.clone?.keep === true)
|
|
17
17
|
return "subject.clone.keep";
|
|
18
|
-
if (
|
|
18
|
+
if (subject.kind === "local-tree" && residual.subject.localTree?.keep === true)
|
|
19
19
|
return "subject.localTree.keep";
|
|
20
20
|
return undefined;
|
|
21
21
|
}
|
|
@@ -38,17 +38,18 @@ async function stopParticipantMedia(args) {
|
|
|
38
38
|
return evidence;
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
* Release the
|
|
42
|
-
* only when the release is confirmed. A kept or
|
|
43
|
-
* which the warnings say.
|
|
41
|
+
* Release the participant's sandbox, or keep it when a keep flag is set and the participant failed. `released`
|
|
42
|
+
* is true only when the release is confirmed; otherwise `sandboxRelease` says why. A kept or
|
|
43
|
+
* unconfirmed sandbox can still accrue compute cost, which the warnings say.
|
|
44
44
|
*/
|
|
45
45
|
async function releaseParticipantDesktop(args) {
|
|
46
46
|
const { allocation, keepReason, deps, warnings } = args;
|
|
47
47
|
const keepForDebug = keepReason !== undefined && args.failed;
|
|
48
48
|
const released = await allocation.close({ retainForDebug: keepForDebug });
|
|
49
49
|
if (released.status === "retained") {
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
const warning = `Sandbox ${allocation.resourceId} kept for debugging (${keepReason} on failure); reclaim it via E2B or it will be killed on its server-side timeout.`;
|
|
51
|
+
warnings.push(warning);
|
|
52
|
+
return { released: false, sandboxRelease: { state: "retained", warning } };
|
|
52
53
|
}
|
|
53
54
|
const reading = readE2BRelease(released, {
|
|
54
55
|
label: "Sandbox",
|
|
@@ -57,10 +58,18 @@ async function releaseParticipantDesktop(args) {
|
|
|
57
58
|
});
|
|
58
59
|
if (reading.warning)
|
|
59
60
|
warnings.push(reading.warning);
|
|
60
|
-
|
|
61
|
+
if (reading.released)
|
|
62
|
+
return { released: true };
|
|
63
|
+
return {
|
|
64
|
+
released: false,
|
|
65
|
+
sandboxRelease: {
|
|
66
|
+
state: "unconfirmed",
|
|
67
|
+
warning: reading.warning ?? "Sandbox release is unconfirmed.",
|
|
68
|
+
},
|
|
69
|
+
};
|
|
61
70
|
}
|
|
62
71
|
/**
|
|
63
|
-
* Finish a
|
|
72
|
+
* Finish a participant: collect its final geometry and comms evidence, then stop its media and release
|
|
64
73
|
* its sandbox. Evidence failures are warnings; the release always runs.
|
|
65
74
|
*/
|
|
66
75
|
export async function finishE2BDesktop(ctx, state, failed) {
|
|
@@ -122,24 +131,27 @@ export async function finishE2BDesktop(ctx, state, failed) {
|
|
|
122
131
|
mediaStop: state.mediaStop,
|
|
123
132
|
warnings,
|
|
124
133
|
});
|
|
125
|
-
|
|
134
|
+
const release = await releaseParticipantDesktop({
|
|
126
135
|
allocation,
|
|
127
136
|
keepReason: participantKeepReason(deps),
|
|
128
137
|
failed,
|
|
129
138
|
deps,
|
|
130
139
|
warnings,
|
|
131
140
|
});
|
|
141
|
+
state.released = release.released;
|
|
142
|
+
state.sandboxRelease = release.sandboxRelease;
|
|
132
143
|
// Close the observed span. A kept or unconfirmed sandbox can still accrue compute cost; the
|
|
133
144
|
// summary records that remaining lifetime as unknown instead of calling this complete.
|
|
134
145
|
state.sandboxTornDownAtMs = deps.now();
|
|
135
|
-
// The
|
|
146
|
+
// The participant's live stream is now a dead page whichever teardown path ran (released, kept, or
|
|
136
147
|
// release-failed-awaiting-TTL); tell the watch overlay so the tile falls back to recorded
|
|
137
148
|
// evidence instead of "sandbox not found" (#357). Guarded: a viewer callback must never
|
|
138
149
|
// break teardown.
|
|
139
150
|
if (state.streamUrl !== undefined) {
|
|
140
151
|
try {
|
|
141
|
-
await deps.
|
|
142
|
-
|
|
152
|
+
await deps.onStream({
|
|
153
|
+
type: "ended",
|
|
154
|
+
participantId: spec.planned.id,
|
|
143
155
|
simId: spec.recordId,
|
|
144
156
|
streamId: spec.streamId,
|
|
145
157
|
});
|
|
@@ -2,12 +2,12 @@ import type { LabCommsEmail, LabCommsExternal } from "../../lab/types.js";
|
|
|
2
2
|
import type { PreparedRunArtifactPaths } from "../../run/paths.js";
|
|
3
3
|
import type { DesktopParticipantRun, ParticipantRunOutcome } from "./types.js";
|
|
4
4
|
/**
|
|
5
|
-
* Adopter-hosted drain (#380): once per RUN, after every
|
|
5
|
+
* Adopter-hosted drain (#380): once per RUN, after every participant finished — the catch is one
|
|
6
6
|
* shared external endpoint, not a per-sandbox file. Same routing and digest-only artifact as
|
|
7
|
-
* the in-sandbox drain; the artifact is registered on every
|
|
7
|
+
* the in-sandbox drain; the artifact is registered on every participant that declared a recipient
|
|
8
8
|
* address, since the thread carries each inbox's mail. A drain failure never fails the run.
|
|
9
9
|
*
|
|
10
|
-
* Returns the warnings the drain produced;
|
|
10
|
+
* Returns the warnings the drain produced; participants that received mail get `commsArtifactPath`.
|
|
11
11
|
*/
|
|
12
12
|
export declare function drainExternalComms(args: {
|
|
13
13
|
externalCommsConfig: LabCommsExternal;
|
|
@@ -16,5 +16,5 @@ export declare function drainExternalComms(args: {
|
|
|
16
16
|
runPaths: PreparedRunArtifactPaths;
|
|
17
17
|
participantRuns: readonly DesktopParticipantRun[];
|
|
18
18
|
outcomes: ParticipantRunOutcome[];
|
|
19
|
-
|
|
19
|
+
knownSecretValues: readonly string[];
|
|
20
20
|
}): Promise<string[]>;
|
|
@@ -1,55 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { collectExternalCommsThread } from "../../comms/sandbox-catch.js";
|
|
3
|
-
import { redactText, toErrorMessage } from "../../evidence/redaction.js";
|
|
4
|
-
import { writeContainedOutputFile } from "../../run/contained-output.js";
|
|
1
|
+
import { collectExternalCommsEvidence } from "../../comms/external-evidence.js";
|
|
5
2
|
import { participantHasInboxRecipient } from "./participant-desktop.js";
|
|
6
|
-
import { addressedRecipients } from "../../lab/parse/comms.js";
|
|
7
3
|
/**
|
|
8
|
-
* Adopter-hosted drain (#380): once per RUN, after every
|
|
4
|
+
* Adopter-hosted drain (#380): once per RUN, after every participant finished — the catch is one
|
|
9
5
|
* shared external endpoint, not a per-sandbox file. Same routing and digest-only artifact as
|
|
10
|
-
* the in-sandbox drain; the artifact is registered on every
|
|
6
|
+
* the in-sandbox drain; the artifact is registered on every participant that declared a recipient
|
|
11
7
|
* address, since the thread carries each inbox's mail. A drain failure never fails the run.
|
|
12
8
|
*
|
|
13
|
-
* Returns the warnings the drain produced;
|
|
9
|
+
* Returns the warnings the drain produced; participants that received mail get `commsArtifactPath`.
|
|
14
10
|
*/
|
|
15
11
|
export async function drainExternalComms(args) {
|
|
16
|
-
const {
|
|
17
|
-
const warnings =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
});
|
|
32
|
-
if (collected.artifact) {
|
|
33
|
-
const commsPath = "comms/thread.json";
|
|
34
|
-
await writeContainedOutputFile(runPaths, commsPath, `${JSON.stringify(collected.artifact, null, 2)}\n`, "utf8");
|
|
35
|
-
for (const [index, outcome] of outcomes.entries()) {
|
|
36
|
-
const participantId = participantRuns[index]?.planned.id;
|
|
37
|
-
if (participantId !== undefined &&
|
|
38
|
-
outcome.commsArtifactPath === undefined &&
|
|
39
|
-
participantHasInboxRecipient(externalCommsEmail, participantId)) {
|
|
40
|
-
outcome.commsArtifactPath = commsPath;
|
|
41
|
-
}
|
|
12
|
+
const { externalCommsEmail, participantRuns, outcomes } = args;
|
|
13
|
+
const { path: commsPath, warnings } = await collectExternalCommsEvidence({
|
|
14
|
+
external: args.externalCommsConfig,
|
|
15
|
+
email: externalCommsEmail,
|
|
16
|
+
env: args.env,
|
|
17
|
+
runPaths: args.runPaths,
|
|
18
|
+
knownSecretValues: args.knownSecretValues,
|
|
19
|
+
});
|
|
20
|
+
if (commsPath !== undefined) {
|
|
21
|
+
for (const [index, outcome] of outcomes.entries()) {
|
|
22
|
+
const participantId = participantRuns[index]?.planned.id;
|
|
23
|
+
if (participantId !== undefined &&
|
|
24
|
+
outcome.commsArtifactPath === undefined &&
|
|
25
|
+
participantHasInboxRecipient(externalCommsEmail, participantId)) {
|
|
26
|
+
outcome.commsArtifactPath = commsPath;
|
|
42
27
|
}
|
|
43
28
|
}
|
|
44
|
-
else if (collected.captured > 0) {
|
|
45
|
-
warnings.push(`Comms catch captured ${collected.captured} email send(s) but none matched a declared recipient inbox — no comms evidence written. Declare comms.email.recipients[].address to match the address the app sends to.`);
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
warnings.push(`Comms catch captured ZERO email sends — your app never delivered mail through the catch at ${externalCommsConfig.catchBaseUrl}. Verify the app's email-API base URL points at it and that the flow reached an email step.`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
warnings.push(`Comms evidence collection failed against the adopter-hosted catch (run continues): ${redactText(scrubKnownValues(toErrorMessage(error)))}`);
|
|
53
29
|
}
|
|
54
30
|
return warnings;
|
|
55
31
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type RunBundle } from "../../run/bundle.js";
|
|
2
2
|
import type { CuaFanoutBundleArgs } from "./types.js";
|
|
3
3
|
/**
|
|
4
|
-
* Project N>1 fan-out
|
|
5
|
-
* is a new producer for the multi-stream shape). One sim + one stream per
|
|
4
|
+
* Project N>1 fan-out participants into a humanish.run-bundle.v1 (the evidence schema is unchanged; this
|
|
5
|
+
* is a new producer for the multi-stream shape). One sim + one stream per participant; per-participant
|
|
6
6
|
* provenance/session events; a recorded `cua-lab.fanout.plan` event (and a `cua-lab.fanout.fail-fast`
|
|
7
|
-
* event when a harness error skipped queued
|
|
7
|
+
* event when a harness error skipped queued participants). N-ary verify/Observer already handle multiple
|
|
8
8
|
* streams. A single-participant run without a rerun never reaches here: buildCuaRunBundle
|
|
9
9
|
* (bundle.ts) sends it to buildSingleParticipantBundle (single-bundle.ts).
|
|
10
10
|
*/
|
|
@@ -3,27 +3,27 @@ import { receivingPublication } from "../../comms/receiving-runtime.js";
|
|
|
3
3
|
import { actorEnding } from "../../actors/stop-cause.js";
|
|
4
4
|
import { redactText } from "../../evidence/redaction.js";
|
|
5
5
|
import { REVIEW_SCHEMA, bundleArtifacts, bundleHead, } from "../../run/bundle.js";
|
|
6
|
-
import { aggregateTaskFunnels, formatParticipantOutcomes,
|
|
6
|
+
import { aggregateTaskFunnels, formatParticipantOutcomes, formatRunTaskFunnel, tallyParticipantOutcomes, withCuaReviewProvenance, } from "../../run/outcomes.js";
|
|
7
7
|
import { participantFeedbackCandidates, providerResourcesForOutcome } from "./bundle-parts.js";
|
|
8
8
|
import { participantFactsOf } from "./participant-facts.js";
|
|
9
9
|
import { participantPassed, participantStatus } from "../../run/judge.js";
|
|
10
10
|
import { buildRunCostSummary, desktopSpanToMinutes } from "../../run/cost-summary.js";
|
|
11
11
|
import { formatParticipantPlanEntry } from "./participant-runs.js";
|
|
12
|
-
import { fanoutParticipantRecords } from "./fanout-
|
|
12
|
+
import { fanoutParticipantRecords } from "./fanout-records.js";
|
|
13
13
|
/** The run's first two events: its creation and the fan-out plan. */
|
|
14
14
|
function fanoutPlanEvents(args) {
|
|
15
15
|
const { specs, plan } = args;
|
|
16
16
|
const events = [];
|
|
17
17
|
events.push({
|
|
18
18
|
id: "event-000-created",
|
|
19
|
-
at: args.createdAt,
|
|
19
|
+
at: args.run.createdAt,
|
|
20
20
|
level: "info",
|
|
21
21
|
type: "cua-lab.run.created",
|
|
22
22
|
message: `Created computer-use fan-out run for ${plan.labId} (actor ${args.descriptor.id}, ${specs.length} participants, one world each).`,
|
|
23
23
|
});
|
|
24
24
|
events.push({
|
|
25
25
|
id: "event-001-fanout-plan",
|
|
26
|
-
at: args.createdAt,
|
|
26
|
+
at: args.run.createdAt,
|
|
27
27
|
level: "info",
|
|
28
28
|
type: "cua-lab.fanout.plan",
|
|
29
29
|
message: `Fan-out plan: ${args.participantPlan.laneCount} participant(s) (${args.participantPlan.strategy}), concurrency ${args.participantPlan.concurrency}, ${args.participantPlan.waves} wave(s); session budget ${Math.round(args.participantPlan.perLaneSessionBudgetMs / 1000)}s per participant; worst-case ~${args.participantPlan.worstCaseSandboxMinutes} sandbox-minutes${args.dryRun ? " (dry-run: $0)" : ""}. Participants: ${args.participantPlan.lanes.map(formatParticipantPlanEntry).join(", ")}.`,
|
|
@@ -32,7 +32,7 @@ function fanoutPlanEvents(args) {
|
|
|
32
32
|
}
|
|
33
33
|
function fanoutReview(args, streams) {
|
|
34
34
|
const { specs, outcomes } = args;
|
|
35
|
-
// The judge's verdict: live fan-out must prove every
|
|
35
|
+
// The judge's verdict: live fan-out must prove every participant (judgeParticipants).
|
|
36
36
|
const verdict = args.verdict;
|
|
37
37
|
const passedParticipants = (outcomes ?? []).filter((outcome) => participantPassed(participantFactsOf(outcome))).length;
|
|
38
38
|
// What happened to the PARTICIPANTS, with the denominator attached. The verdict above has to
|
|
@@ -40,10 +40,10 @@ function fanoutReview(args, streams) {
|
|
|
40
40
|
const terminalOutcomes = (outcomes ?? []).filter((outcome) => outcome?.session?.status !== undefined);
|
|
41
41
|
const participants = terminalOutcomes.length > 0
|
|
42
42
|
? tallyParticipantOutcomes(
|
|
43
|
-
// A NO-ENGAGEMENT
|
|
43
|
+
// A NO-ENGAGEMENT participant is not one who reached the goal. It said "done" having
|
|
44
44
|
// taken zero actions and said nothing, and `passedParticipants` above already refuses to
|
|
45
45
|
// count it — but `reachedGoal` was reading the trace status directly, so one run could be both
|
|
46
|
-
// "not a passed
|
|
46
|
+
// "not a passed participant" AND "1/1 reached the goal". The headline number a researcher reads
|
|
47
47
|
// first was the dishonest one. Found by a provider bug that ended a study on turn one.
|
|
48
48
|
terminalOutcomes.map((outcome) => participantStatus(outcome.session.status, {
|
|
49
49
|
noEngagement: outcome.noEngagement === true,
|
|
@@ -58,7 +58,7 @@ function fanoutReview(args, streams) {
|
|
|
58
58
|
const participantFunnels = (outcomes ?? [])
|
|
59
59
|
.map((outcome) => outcome?.session?.trace.taskFunnel)
|
|
60
60
|
.filter((funnel) => funnel !== undefined);
|
|
61
|
-
const
|
|
61
|
+
const runTasks = args.inProgress === true ? undefined : aggregateTaskFunnels(participantFunnels);
|
|
62
62
|
const participantEndings = terminalOutcomes.map((outcome) => {
|
|
63
63
|
const ending = actorEnding(outcome.session.trace);
|
|
64
64
|
return {
|
|
@@ -70,12 +70,12 @@ function fanoutReview(args, streams) {
|
|
|
70
70
|
schema: REVIEW_SCHEMA,
|
|
71
71
|
verdict,
|
|
72
72
|
...(participants === undefined ? {} : { participants }),
|
|
73
|
-
...(
|
|
73
|
+
...(runTasks === undefined ? {} : { tasks: runTasks }),
|
|
74
74
|
summary: args.inProgress === true
|
|
75
75
|
? `Live computer-use fan-out is running (${specs.length} participants, one world each); terminal participant evidence has not been written yet.`
|
|
76
76
|
: args.dryRun
|
|
77
77
|
? `${args.rerun ? `Rerun contract from ${args.rerun.sourceRunId}: ` : ""}Dry-run fan-out contract: ${specs.length} participants composed for ${args.descriptor.id} against ${args.appUrl}, one world each; no desktops launched, $0 spend.`
|
|
78
|
-
: `${args.rerun ? `Rerun from ${args.rerun.sourceRunId}: ` : ""}Computer-use fan-out (${specs.length} participants, one world each): ${passedParticipants}/${specs.length} participant(s) reached a terminal, engaged verdict${participants ? `: ${formatParticipantOutcomes(participants, participantEndings)}` : ""}${
|
|
78
|
+
: `${args.rerun ? `Rerun from ${args.rerun.sourceRunId}: ` : ""}Computer-use fan-out (${specs.length} participants, one world each): ${passedParticipants}/${specs.length} participant(s) reached a terminal, engaged verdict${participants ? `: ${formatParticipantOutcomes(participants, participantEndings)}` : ""}${runTasks ? `; tasks: ${formatRunTaskFunnel(runTasks)}` : ""}.`,
|
|
79
79
|
gaps: args.inProgress === true
|
|
80
80
|
? ["Live fan-out session is still running."]
|
|
81
81
|
: args.dryRun
|
|
@@ -93,7 +93,7 @@ function fanoutReview(args, streams) {
|
|
|
93
93
|
}, streams);
|
|
94
94
|
return review;
|
|
95
95
|
}
|
|
96
|
-
/** The configured browser and, when every
|
|
96
|
+
/** The configured browser and, when every participant resolved the same one, that browser. */
|
|
97
97
|
function fanoutDesktopBrowser(args) {
|
|
98
98
|
const { outcomes, plan } = args;
|
|
99
99
|
const configuredBrowser = plan.residual.execution?.desktop?.browser;
|
|
@@ -112,9 +112,9 @@ function fanoutDesktopBrowser(args) {
|
|
|
112
112
|
}
|
|
113
113
|
function fanoutCost(args) {
|
|
114
114
|
const { specs, outcomes } = args;
|
|
115
|
-
// Run-level cost ESTIMATE: one model-token line per
|
|
115
|
+
// Run-level cost ESTIMATE: one model-token line per participant that ran a session (from its persisted
|
|
116
116
|
// trace.estimatedCost) + a desktop line per owned allocation, priced at its observed resources.
|
|
117
|
-
//
|
|
117
|
+
// `per-lane-worlds` participants have no shared provisioning to double-count. Omitted on a pure dry-run.
|
|
118
118
|
const costTraces = specs
|
|
119
119
|
.map((spec, index) => ({ participantId: spec.planned.id, outcome: outcomes?.[index] }))
|
|
120
120
|
.filter((entry) => entry.outcome?.session !== undefined)
|
|
@@ -135,7 +135,7 @@ function fanoutFeedbackCandidates(args) {
|
|
|
135
135
|
return args.dryRun || args.inProgress === true
|
|
136
136
|
? []
|
|
137
137
|
: participantFeedbackCandidates({
|
|
138
|
-
runId: args.runId,
|
|
138
|
+
runId: args.run.runId,
|
|
139
139
|
scenarioId: `cua-${plan.labId}`,
|
|
140
140
|
adapterId: plan.labId,
|
|
141
141
|
goal: redactText(specs[0].evidenceInstructions ?? specs[0].instructions),
|
|
@@ -159,10 +159,10 @@ function fanoutFeedbackCandidates(args) {
|
|
|
159
159
|
});
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
|
-
* Project N>1 fan-out
|
|
163
|
-
* is a new producer for the multi-stream shape). One sim + one stream per
|
|
162
|
+
* Project N>1 fan-out participants into a humanish.run-bundle.v1 (the evidence schema is unchanged; this
|
|
163
|
+
* is a new producer for the multi-stream shape). One sim + one stream per participant; per-participant
|
|
164
164
|
* provenance/session events; a recorded `cua-lab.fanout.plan` event (and a `cua-lab.fanout.fail-fast`
|
|
165
|
-
* event when a harness error skipped queued
|
|
165
|
+
* event when a harness error skipped queued participants). N-ary verify/Observer already handle multiple
|
|
166
166
|
* streams. A single-participant run without a rerun never reaches here: buildCuaRunBundle
|
|
167
167
|
* (bundle.ts) sends it to buildSingleParticipantBundle (single-bundle.ts).
|
|
168
168
|
*/
|
|
@@ -176,7 +176,7 @@ export function buildCuaFanoutBundle(args) {
|
|
|
176
176
|
if (args.rerun) {
|
|
177
177
|
events.push({
|
|
178
178
|
id: nextEventId("fanout-rerun"),
|
|
179
|
-
at: args.createdAt,
|
|
179
|
+
at: args.run.createdAt,
|
|
180
180
|
level: "info",
|
|
181
181
|
type: "cua-lab.fanout.rerun",
|
|
182
182
|
message: `Rerun selected ${args.rerun.selectedLaneIds.length} participant(s) from ${args.rerun.sourceRunId}: ${args.rerun.previous.map((prior) => `${prior.laneId} was ${prior.status}${prior.completionReason ? `/${prior.completionReason}` : ""}`).join(", ")}. This is a new linked run; the source run verdict is unchanged.`,
|
|
@@ -191,7 +191,7 @@ export function buildCuaFanoutBundle(args) {
|
|
|
191
191
|
if (args.failFastReason) {
|
|
192
192
|
events.push({
|
|
193
193
|
id: nextEventId("fanout-fail-fast"),
|
|
194
|
-
at: args.createdAt,
|
|
194
|
+
at: args.run.createdAt,
|
|
195
195
|
level: "warn",
|
|
196
196
|
type: "cua-lab.fanout.fail-fast",
|
|
197
197
|
message: `Fan-out fail-fast: ${args.failFastReason}. In-flight participants finished; queued participants were skipped (blocked); completed evidence is retained.`,
|
|
@@ -204,19 +204,15 @@ export function buildCuaFanoutBundle(args) {
|
|
|
204
204
|
const desktopBrowser = fanoutDesktopBrowser(args);
|
|
205
205
|
const providerResources = (outcomes ?? []).flatMap((outcome) => providerResourcesForOutcome({
|
|
206
206
|
outcome,
|
|
207
|
-
createdAt: args.createdAt,
|
|
207
|
+
createdAt: args.run.createdAt,
|
|
208
208
|
ids: outcome.spec,
|
|
209
209
|
participantId: outcome.spec.planned.id,
|
|
210
210
|
}));
|
|
211
211
|
const cost = fanoutCost(args);
|
|
212
212
|
return {
|
|
213
|
-
...bundleHead({
|
|
213
|
+
...bundleHead(args.run, {
|
|
214
214
|
...receivingPublication(args.plan.residual, args.dryRun),
|
|
215
|
-
runId: args.runId,
|
|
216
|
-
mode: args.dryRun ? "dry-run" : "live",
|
|
217
215
|
participants: specs.length,
|
|
218
|
-
createdAt: args.createdAt,
|
|
219
|
-
...(args.lab === undefined ? {} : { lab: args.lab }),
|
|
220
216
|
source: args.source,
|
|
221
217
|
}),
|
|
222
218
|
persona: {
|
|
@@ -228,9 +224,9 @@ export function buildCuaFanoutBundle(args) {
|
|
|
228
224
|
scenario: {
|
|
229
225
|
id: `cua-${plan.labId}`,
|
|
230
226
|
title: plan.title ?? `Computer-use fan-out: ${plan.labId}`,
|
|
231
|
-
// Redacted at WRITE time, like every other raw-text surface in the bundle.
|
|
232
|
-
// digest-only by design, but scenario.goal keeps one
|
|
233
|
-
// and an adopter whose authored
|
|
227
|
+
// Redacted at WRITE time, like every other raw-text surface in the bundle. Participant records are
|
|
228
|
+
// digest-only by design, but scenario.goal keeps one participant's composed instructions verbatim —
|
|
229
|
+
// and an adopter whose authored participant text must name a runtime world URL (an inbox on a route
|
|
234
230
|
// where the harness does not inject one) put an *.e2b.app address in it. That landed raw here
|
|
235
231
|
// and in observer-data.json, the sensitive-text scanner matched it, and verify failed a bundle
|
|
236
232
|
// this writer produced. The only adopter-side workaround was scanner evasion (#412).
|
|
@@ -242,7 +238,7 @@ export function buildCuaFanoutBundle(args) {
|
|
|
242
238
|
},
|
|
243
239
|
lifecycle: [
|
|
244
240
|
{
|
|
245
|
-
at: args.createdAt,
|
|
241
|
+
at: args.run.createdAt,
|
|
246
242
|
event: "cua-lab.run.created",
|
|
247
243
|
message: `Created computer-use fan-out run with ${specs.length} participants, each in its own desktop browser (actor ${args.descriptor.id}).`,
|
|
248
244
|
},
|