humanish 0.106.0 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -2
- package/ARCHITECTURE.md +17 -16
- package/CHANGELOG.md +24 -0
- package/CONTEXT.md +42 -39
- package/CONTRIBUTING.md +8 -6
- package/README.md +8 -3
- package/dist/actors/codex/app-server-client.js +2 -1
- package/dist/actors/codex/app-server-trace.d.ts +0 -1
- package/dist/actors/codex/app-server-trace.js +1 -3
- package/dist/actors/codex/app-server.js +2 -1
- package/dist/actors/codex/protocol-compat.d.ts +27 -0
- package/dist/actors/codex/protocol-compat.js +357 -0
- package/dist/actors/codex/protocol-contract.d.ts +61 -0
- package/dist/actors/codex/protocol-contract.js +471 -0
- package/dist/actors/codex/qualified-versions.d.ts +31 -4
- package/dist/actors/codex/qualified-versions.js +51 -6
- package/dist/actors/codex/restricted-executable.d.ts +24 -0
- package/dist/actors/codex/restricted-executable.js +97 -22
- package/dist/actors/codex/restricted-launch.d.ts +7 -1
- package/dist/actors/codex/restricted-launch.js +42 -3
- package/dist/actors/codex/restricted-notifications.d.ts +101 -0
- package/dist/actors/codex/restricted-notifications.js +277 -0
- package/dist/actors/codex/restricted-participant.d.ts +30 -0
- package/dist/actors/codex/restricted-participant.js +60 -2
- package/dist/actors/codex/restricted-policy.d.ts +9 -1
- package/dist/actors/codex/restricted-session.d.ts +14 -1
- package/dist/actors/codex/restricted-session.js +50 -17
- package/dist/actors/codex/restricted-transport.d.ts +29 -0
- package/dist/actors/codex/restricted-transport.js +139 -27
- package/dist/actors/codex/restricted-turn.d.ts +19 -4
- package/dist/actors/codex/restricted-turn.js +43 -30
- package/dist/actors/computer-use/actor.d.ts +1 -1
- package/dist/actors/computer-use/actor.js +4 -4
- package/dist/actors/computer-use/loop/backstop.js +1 -1
- package/dist/actors/computer-use/loop/ending.d.ts +2 -2
- package/dist/actors/computer-use/loop/ending.js +2 -2
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +3 -3
- package/dist/actors/computer-use/loop/trace.js +2 -2
- package/dist/actors/computer-use/loop/types.d.ts +14 -5
- package/dist/actors/computer-use/loop.js +4 -4
- package/dist/actors/computer-use/openai-provider.d.ts +1 -1
- package/dist/actors/computer-use/openai-provider.js +2 -2
- package/dist/actors/contract.d.ts +10 -8
- package/dist/actors/contract.js +7 -1
- package/dist/actors/local-agent/cli.js +1 -1
- package/dist/actors/scripted-browser/actor.d.ts +2 -2
- package/dist/actors/scripted-browser/journey.js +15 -4
- package/dist/actors/scripted-browser/steps.js +18 -0
- package/dist/actors/scripted-browser/types.d.ts +11 -1
- package/dist/actors/stop-conditions.js +1 -3
- package/dist/analysis/automatic-completion.d.ts +13 -8
- package/dist/analysis/automatic-completion.js +14 -8
- package/dist/analysis/automatic-config.d.ts +1 -1
- package/dist/analysis/automatic-config.js +2 -2
- package/dist/analysis/automatic.d.ts +10 -4
- package/dist/analysis/automatic.js +17 -13
- package/dist/analysis/diagnostics.d.ts +23 -0
- package/dist/analysis/diagnostics.js +112 -0
- package/dist/analysis/evidence-sources.js +2 -2
- package/dist/analysis/evidence.js +6 -6
- package/dist/analysis/execute.d.ts +7 -1
- package/dist/analysis/execute.js +39 -12
- package/dist/analysis/job.d.ts +8 -5
- package/dist/analysis/job.js +15 -14
- package/dist/analysis/load.d.ts +1 -1
- package/dist/analysis/load.js +5 -5
- package/dist/analysis/provider.d.ts +9 -1
- package/dist/analysis/restricted-codex.d.ts +2 -0
- package/dist/analysis/restricted-codex.js +10 -1
- package/dist/analysis/service.d.ts +2 -0
- package/dist/analysis/service.js +31 -12
- package/dist/analysis/sharing.d.ts +2 -2
- package/dist/analysis/sharing.js +5 -5
- package/dist/analysis/store-executions.d.ts +5 -5
- package/dist/analysis/store-executions.js +12 -12
- package/dist/analysis/store.d.ts +4 -4
- package/dist/analysis/store.js +13 -13
- package/dist/cli/commands/analysis-signals.d.ts +2 -1
- package/dist/cli/commands/analysis-signals.js +4 -1
- package/dist/cli/commands/analyze.js +4 -2
- package/dist/cli/commands/comms.js +8 -1
- package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
- package/dist/cli/commands/lab-route-computer-use.js +26 -14
- package/dist/cli/commands/lab-route-preview.d.ts +1 -3
- package/dist/cli/commands/lab-route-preview.js +3 -4
- package/dist/cli/commands/lab-route-run.d.ts +6 -4
- package/dist/cli/commands/lab-route-run.js +6 -2
- package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
- package/dist/cli/commands/lab-route-scripted.js +0 -1
- package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
- package/dist/cli/commands/lab-route-shared-world.js +0 -1
- package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
- package/dist/cli/commands/lab-route-terminal.js +0 -1
- package/dist/cli/commands/lab-run.js +76 -45
- package/dist/cli/commands/lab-scorer.d.ts +0 -2
- package/dist/cli/commands/lab.js +12 -6
- package/dist/cli/commands/observe.js +22 -0
- package/dist/cli/commands/run-signals.d.ts +30 -0
- package/dist/cli/commands/run-signals.js +146 -0
- package/dist/cli/commands/runs.js +10 -8
- package/dist/cli/commands/watch.js +12 -10
- package/dist/cli/doctor.d.ts +3 -0
- package/dist/cli/doctor.js +10 -2
- package/dist/cli/io.d.ts +5 -4
- package/dist/cli/io.js +12 -8
- package/dist/cli/program.js +3 -3
- package/dist/cli/renamed-options.d.ts +11 -0
- package/dist/cli/renamed-options.js +18 -0
- package/dist/cli/telemetry.d.ts +2 -2
- package/dist/cli/telemetry.js +1 -1
- package/dist/comms/capture-surface.d.ts +1 -1
- package/dist/comms/catch-host.d.ts +1 -1
- package/dist/comms/connections.js +4 -4
- package/dist/comms/external-evidence.d.ts +27 -0
- package/dist/comms/external-evidence.js +93 -0
- package/dist/comms/lease-store.js +7 -7
- package/dist/comms/types.js +1 -1
- package/dist/evidence/browser-hygiene.d.ts +1 -1
- package/dist/evidence/browser-hygiene.js +1 -1
- package/dist/evidence/redaction.js +1 -1
- package/dist/evidence/secret-scrub.d.ts +9 -0
- package/dist/evidence/secret-scrub.js +96 -0
- package/dist/feedback/draft.js +7 -9
- package/dist/feedback/export-bundle.js +4 -4
- package/dist/feedback/export.js +9 -9
- package/dist/feedback/feedback.d.ts +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.js +3 -6
- package/dist/keys/key-resolution.d.ts +3 -1
- package/dist/keys/key-resolution.js +18 -16
- package/dist/lab/adapter-extension.d.ts +28 -6
- package/dist/lab/adapter-extension.js +65 -126
- package/dist/lab/adapter-scorer-loader.d.ts +25 -5
- package/dist/lab/adapter-scorer-loader.js +24 -0
- package/dist/lab/composition-rules.d.ts +2 -0
- package/dist/lab/composition-rules.js +35 -26
- package/dist/lab/config.js +28 -26
- package/dist/lab/device-presets.d.ts +2 -2
- package/dist/lab/discover.js +1 -3
- package/dist/lab/doctor.d.ts +44 -9
- package/dist/lab/doctor.js +149 -41
- package/dist/lab/init-plan.js +1 -3
- package/dist/lab/keys.js +1 -1
- package/dist/lab/lab-deps.d.ts +85 -0
- package/dist/lab/lab-deps.js +4 -0
- package/dist/lab/parse/actors.js +8 -7
- package/dist/lab/parse/comms.js +3 -2
- package/dist/lab/parse/execution.js +3 -2
- package/dist/lab/parse/subject-state.js +2 -1
- package/dist/lab/parse/subject.js +2 -1
- package/dist/lab/parse/values.d.ts +0 -1
- package/dist/lab/parse/values.js +0 -3
- package/dist/lab/persona-resolve.d.ts +3 -3
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/persona.js +1 -3
- package/dist/lab/plan-base.d.ts +6 -2
- package/dist/lab/plan-base.js +22 -7
- package/dist/lab/plan-participants.d.ts +5 -5
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +33 -7
- package/dist/lab/plan.d.ts +3 -11
- package/dist/lab/plan.js +18 -42
- package/dist/lab/preflight-result.js +0 -2
- package/dist/lab/preflight.d.ts +0 -3
- package/dist/lab/preflight.js +1 -1
- package/dist/lab/requirements.d.ts +20 -0
- package/dist/lab/requirements.js +54 -0
- package/dist/lab/route-inputs.d.ts +23 -12
- package/dist/lab/route-inputs.js +48 -51
- package/dist/lab/routing.d.ts +19 -24
- package/dist/lab/routing.js +14 -47
- package/dist/lab/run-lab-events.d.ts +6 -11
- package/dist/lab/run-lab-events.js +3 -11
- package/dist/lab/run-lab-homes.d.ts +64 -0
- package/dist/lab/run-lab-homes.js +3 -0
- package/dist/lab/run-lab-options.d.ts +12 -66
- package/dist/lab/run-lab-options.js +45 -275
- package/dist/lab/summary.d.ts +9 -4
- package/dist/lab/summary.js +15 -8
- package/dist/lab/types.d.ts +132 -132
- package/dist/lab/validation.d.ts +15 -15
- package/dist/lab/validation.js +28 -28
- package/dist/lab/warnings.js +20 -19
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +3 -3
- package/dist/observer/data.js +2 -2
- package/dist/observer/render.js +2 -2
- package/dist/observer/run-routes.d.ts +1 -1
- package/dist/observer/run-routes.js +5 -5
- package/dist/observer/serve.d.ts +17 -0
- package/dist/observer/serve.js +34 -3
- package/dist/observer-app.html +1 -1
- package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
- package/dist/routes/computer-use/bundle-parts.js +10 -3
- package/dist/routes/computer-use/bundle.d.ts +4 -11
- package/dist/routes/computer-use/bundle.js +9 -15
- package/dist/routes/computer-use/diagnostics.d.ts +1 -1
- package/dist/routes/computer-use/diagnostics.js +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
- package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
- package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
- package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
- package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
- package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
- package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
- package/dist/routes/computer-use/external-comms.d.ts +4 -4
- package/dist/routes/computer-use/external-comms.js +19 -43
- package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
- package/dist/routes/computer-use/fanout-bundle.js +25 -29
- package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
- package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
- package/dist/routes/computer-use/in-process-desktop.js +3 -9
- package/dist/routes/computer-use/live-flush.d.ts +7 -5
- package/dist/routes/computer-use/live-flush.js +19 -27
- package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +14 -13
- package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
- package/dist/routes/computer-use/local-tree-pack.js +4 -5
- package/dist/routes/computer-use/local-vm.d.ts +11 -8
- package/dist/routes/computer-use/local-vm.js +39 -66
- package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
- package/dist/routes/computer-use/participant-desktop.js +5 -25
- package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
- package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
- package/dist/routes/computer-use/participant-facts.d.ts +7 -1
- package/dist/routes/computer-use/participant-facts.js +12 -1
- package/dist/routes/computer-use/participant-model.d.ts +19 -11
- package/dist/routes/computer-use/participant-model.js +58 -33
- package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
- package/dist/routes/computer-use/participant-prompt.js +4 -4
- package/dist/routes/computer-use/participant-runs.d.ts +6 -6
- package/dist/routes/computer-use/participant-runs.js +8 -8
- package/dist/routes/computer-use/plan.d.ts +21 -29
- package/dist/routes/computer-use/plan.js +59 -65
- package/dist/routes/computer-use/preflight.d.ts +6 -11
- package/dist/routes/computer-use/preflight.js +26 -18
- package/dist/routes/computer-use/rerun-selection.js +10 -6
- package/dist/routes/computer-use/result.d.ts +1 -1
- package/dist/routes/computer-use/result.js +40 -30
- package/dist/routes/computer-use/route.d.ts +3 -4
- package/dist/routes/computer-use/route.js +21 -19
- package/dist/routes/computer-use/self-report.d.ts +2 -2
- package/dist/routes/computer-use/self-report.js +4 -4
- package/dist/routes/computer-use/setup.d.ts +8 -17
- package/dist/routes/computer-use/setup.js +98 -86
- package/dist/routes/computer-use/single-bundle.d.ts +8 -11
- package/dist/routes/computer-use/single-bundle.js +20 -25
- package/dist/routes/computer-use/subject-projection.d.ts +5 -7
- package/dist/routes/computer-use/subject-projection.js +20 -19
- package/dist/routes/computer-use/types.d.ts +169 -211
- package/dist/routes/computer-use/types.js +13 -6
- package/dist/routes/preview.js +0 -1
- package/dist/routes/scripted/bundle.d.ts +3 -6
- package/dist/routes/scripted/bundle.js +11 -16
- package/dist/routes/scripted/plan.d.ts +5 -7
- package/dist/routes/scripted/plan.js +6 -4
- package/dist/routes/scripted/result.d.ts +4 -1
- package/dist/routes/scripted/result.js +10 -6
- package/dist/routes/scripted/route.js +10 -11
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +1 -1
- package/dist/routes/scripted/setup.d.ts +3 -2
- package/dist/routes/scripted/setup.js +22 -21
- package/dist/routes/scripted/subject.d.ts +8 -3
- package/dist/routes/scripted/subject.js +11 -6
- package/dist/routes/scripted/surface-records.js +1 -1
- package/dist/routes/scripted/surface-sessions.d.ts +2 -2
- package/dist/routes/scripted/surface-sessions.js +4 -4
- package/dist/routes/scripted/types.d.ts +19 -36
- package/dist/routes/scripted/types.js +1 -2
- package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
- package/dist/routes/shared-world/bundle.d.ts +2 -2
- package/dist/routes/shared-world/bundle.js +22 -26
- package/dist/routes/shared-world/checkpoints.d.ts +4 -4
- package/dist/routes/shared-world/checkpoints.js +4 -4
- package/dist/routes/shared-world/comms.d.ts +5 -4
- package/dist/routes/shared-world/comms.js +28 -41
- package/dist/routes/shared-world/external-public.d.ts +5 -5
- package/dist/routes/shared-world/external-public.js +19 -20
- package/dist/routes/shared-world/handoff.d.ts +4 -4
- package/dist/routes/shared-world/handoff.js +50 -50
- package/dist/routes/shared-world/lobby-code.d.ts +5 -5
- package/dist/routes/shared-world/lobby-code.js +13 -13
- package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
- package/dist/routes/shared-world/{seats.js → participant-specs.js} +46 -51
- package/dist/routes/shared-world/plan.d.ts +2 -6
- package/dist/routes/shared-world/plan.js +1 -2
- package/dist/routes/shared-world/provenance.d.ts +4 -4
- package/dist/routes/shared-world/provenance.js +4 -4
- package/dist/routes/shared-world/provisioned.d.ts +3 -2
- package/dist/routes/shared-world/provisioned.js +48 -41
- package/dist/routes/shared-world/result.js +31 -19
- package/dist/routes/shared-world/route.js +37 -41
- package/dist/routes/shared-world/setup.d.ts +5 -4
- package/dist/routes/shared-world/setup.js +12 -14
- package/dist/routes/shared-world/types.d.ts +53 -126
- package/dist/routes/shared-world/types.js +2 -2
- package/dist/routes/terminal/adapter.d.ts +8 -8
- package/dist/routes/terminal/adapter.js +28 -125
- package/dist/routes/terminal/bundle.d.ts +7 -12
- package/dist/routes/terminal/bundle.js +24 -34
- package/dist/routes/terminal/credentials.d.ts +2 -2
- package/dist/routes/terminal/credentials.js +16 -16
- package/dist/routes/terminal/dry-run.d.ts +1 -1
- package/dist/routes/terminal/dry-run.js +9 -11
- package/dist/routes/terminal/encoding.d.ts +1 -1
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +6 -6
- package/dist/routes/terminal/ledger.js +9 -9
- package/dist/routes/terminal/live-finish.d.ts +1 -2
- package/dist/routes/terminal/live-finish.js +21 -20
- package/dist/routes/terminal/live-sandbox.d.ts +4 -2
- package/dist/routes/terminal/live-sandbox.js +25 -21
- package/dist/routes/terminal/participant-text.d.ts +23 -0
- package/dist/routes/terminal/participant-text.js +165 -0
- package/dist/routes/terminal/plan.d.ts +2 -6
- package/dist/routes/terminal/plan.js +13 -9
- package/dist/routes/terminal/recorder.d.ts +6 -1
- package/dist/routes/terminal/recorder.js +12 -4
- package/dist/routes/terminal/result.js +4 -4
- package/dist/routes/terminal/route.js +26 -26
- package/dist/routes/terminal/runtime.d.ts +3 -2
- package/dist/routes/terminal/runtime.js +3 -3
- package/dist/routes/terminal/sandbox.d.ts +5 -3
- package/dist/routes/terminal/sandbox.js +13 -16
- package/dist/routes/terminal/session.js +16 -14
- package/dist/routes/terminal/token-usage.js +5 -5
- package/dist/routes/terminal/trace.d.ts +5 -8
- package/dist/routes/terminal/trace.js +9 -64
- package/dist/routes/terminal/types.d.ts +85 -93
- package/dist/routes/terminal/types.js +9 -4
- package/dist/run/active-runs.d.ts +13 -0
- package/dist/run/active-runs.js +12 -0
- package/dist/run/bundle-shape.d.ts +2 -1
- package/dist/run/bundle-shape.js +4 -4
- package/dist/run/bundle.d.ts +63 -56
- package/dist/run/bundle.js +9 -8
- package/dist/run/cost-summary.js +3 -2
- package/dist/run/costs.d.ts +6 -6
- package/dist/run/costs.js +10 -10
- package/dist/run/detail.d.ts +5 -5
- package/dist/run/detail.js +6 -6
- package/dist/run/dry-run.js +5 -12
- package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
- package/dist/run/{study-files.js → evidence-files.js} +5 -5
- package/dist/run/feedback-shape.js +1 -1
- package/dist/run/judge.d.ts +16 -4
- package/dist/run/judge.js +24 -7
- package/dist/run/locate.d.ts +2 -0
- package/dist/run/locate.js +3 -1
- package/dist/run/outcomes.d.ts +3 -3
- package/dist/run/outcomes.js +3 -3
- package/dist/run/participant-records.d.ts +2 -2
- package/dist/run/participant-records.js +2 -2
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +19 -9
- package/dist/run/pricing.js +30 -18
- package/dist/run/projection.d.ts +13 -13
- package/dist/run/projection.js +8 -8
- package/dist/run/reclaim.d.ts +7 -1
- package/dist/run/reclaim.js +24 -4
- package/dist/run/results.d.ts +1 -1
- package/dist/run/run-index.d.ts +1 -1
- package/dist/run/run-index.js +11 -11
- package/dist/run/run.d.ts +4 -2
- package/dist/run/run.js +9 -5
- package/dist/run/sandbox-receipts.d.ts +4 -4
- package/dist/run/sandbox-receipts.js +4 -4
- package/dist/run/shared-world-evidence.d.ts +47 -47
- package/dist/run/shared-world-shape.d.ts +3 -3
- package/dist/run/shared-world-shape.js +11 -11
- package/dist/run/stats.d.ts +5 -5
- package/dist/run/stats.js +8 -8
- package/dist/run/status.d.ts +16 -6
- package/dist/run/status.js +31 -8
- package/dist/run/streams.d.ts +26 -19
- package/dist/run/terminal-contract.d.ts +5 -5
- package/dist/run/terminal-contract.js +4 -4
- package/dist/run/transient-comms-secrets.d.ts +5 -0
- package/dist/run/transient-comms-secrets.js +12 -0
- package/dist/run-lab.d.ts +36 -34
- package/dist/run-lab.js +41 -37
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +1 -1
- package/dist/subject/local-tree-archive.d.ts +1 -1
- package/dist/subject/local-tree-archive.js +4 -4
- package/dist/subject/local-tree.d.ts +2 -2
- package/dist/subject/local-tree.js +1 -1
- package/dist/subject/node-bootstrap.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +4 -4
- package/dist/subject/runtime.js +5 -5
- package/dist/subject/serve.js +1 -1
- package/dist/subject/steps.d.ts +4 -4
- package/dist/subject/steps.js +5 -5
- package/dist/substrates/desktop-session.d.ts +2 -0
- package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
- package/dist/substrates/e2b/cdp-probe.js +1 -1
- package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
- package/dist/substrates/e2b/desktop-browser.js +4 -4
- package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
- package/dist/substrates/e2b/desktop-cdp.js +4 -4
- package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
- package/dist/substrates/e2b/desktop-geometry.js +3 -3
- package/dist/substrates/e2b/desktop-media.js +2 -2
- package/dist/substrates/e2b/sandbox.d.ts +2 -0
- package/dist/substrates/e2b/sandbox.js +22 -8
- package/dist/substrates/e2b/sdk.d.ts +12 -1
- package/dist/substrates/e2b/sdk.js +30 -9
- package/dist/substrates/local/runtime-host.d.ts +2 -0
- package/dist/substrates/local/runtime-host.js +6 -0
- package/dist/tui/actions.d.ts +7 -5
- package/dist/tui/actions.js +18 -9
- package/dist/tui-app.js +42 -42
- package/dist/verify/actor.d.ts +10 -10
- package/dist/verify/actor.js +15 -15
- package/dist/verify/artifacts.d.ts +1 -1
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/costs.d.ts +2 -2
- package/dist/verify/costs.js +2 -2
- package/dist/verify/liveness.d.ts +1 -1
- package/dist/verify/liveness.js +4 -1
- package/dist/verify/rerun.d.ts +1 -1
- package/dist/verify/rerun.js +1 -1
- package/dist/verify/shared-world.js +2 -2
- package/dist/verify/verify.js +6 -6
- package/docs/README.md +1 -1
- package/docs/architecture/actor-contract.md +60 -22
- package/docs/architecture/desktop-sessions.md +9 -9
- package/docs/architecture/external-public-shared-world.md +5 -0
- package/docs/architecture/observer.md +4 -4
- package/docs/architecture/restricted-codex-analysis.md +40 -4
- package/docs/architecture/state-driven-executor.md +4 -5
- package/docs/architecture/task-protocol-support.md +3 -5
- package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
- package/docs/contracts/run-bundle.md +10 -8
- package/docs/contracts/schemas.md +109 -53
- package/docs/contracts/study-analysis.md +24 -0
- package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
- package/docs/product/automatic-analysis.md +1 -0
- package/docs/ramp/README.md +2 -1
- package/package.json +4 -4
- package/skills/humanish/SKILL.md +3 -2
- package/skills/humanish/agents/openai.yaml +1 -1
- package/dist/deprecated.d.ts +0 -90
- package/dist/deprecated.js +0 -106
- package/dist/lab/bag-overrides.d.ts +0 -18
- package/dist/lab/bag-overrides.js +0 -121
- package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
- package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
- /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
- /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
- /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
//
|
|
1
|
+
// External-public plane (#164 phase 2): no subject sandbox, no getHost, no prober. The shared plane
|
|
2
2
|
// is the operator-declared public deployment (publicAppUrl); each seat opens it directly and reaches
|
|
3
3
|
// the shared session through the real UI. A host-first barrier extracts the /lobby/CODE from the host
|
|
4
4
|
// seat's CDP-observed URL (onObservedUrl) and threads it into the follower missions; a follower fails
|
|
5
|
-
// closed
|
|
5
|
+
// closed without opening if the host never yields a code within the handoff deadline.
|
|
6
6
|
import { liveObserverResult } from "../../observer/live.js";
|
|
7
7
|
import { redactText, toErrorMessage } from "../../evidence/redaction.js";
|
|
8
8
|
import { mapWithConcurrency } from "../../run/concurrency.js";
|
|
@@ -11,37 +11,37 @@ import { drainExternalComms } from "./comms.js";
|
|
|
11
11
|
import { LobbyHandoff, runFollower, runHost } from "./handoff.js";
|
|
12
12
|
import { readLobbyCodeFromFrame } from "./lobby-code.js";
|
|
13
13
|
import { hostOriginDigest } from "./provenance.js";
|
|
14
|
-
import { participantRunDeps, startParticipantFlush } from "./
|
|
14
|
+
import { participantRunDeps, startParticipantFlush } from "./participant-specs.js";
|
|
15
15
|
/**
|
|
16
|
-
* The operator-
|
|
17
|
-
* operator-
|
|
18
|
-
* appUrl
|
|
19
|
-
* lobby-trivia.example.test 307-redirects) makes the seats'
|
|
20
|
-
* is expected and
|
|
16
|
+
* The operator-declared origin (from subject.appUrl), recorded for evidence and reference only. The
|
|
17
|
+
* operator-ownership claim rests on the subject.publicTarget.authorized attestation + this declared
|
|
18
|
+
* appUrl; digest equality plays no part (blocker 2): a normal cross-origin redirect (apex->www, http->https;
|
|
19
|
+
* lobby-trivia.example.test 307-redirects) makes the seats' observed origin differ from the declared one, which
|
|
20
|
+
* is expected and must not fail the run. Persisted digest-only (never the raw origin).
|
|
21
21
|
*/
|
|
22
22
|
export function declaredOriginDigestOf(publicAppUrl) {
|
|
23
23
|
return publicAppUrl ? hostOriginDigest(publicAppUrl) : undefined;
|
|
24
24
|
}
|
|
25
25
|
export async function runExternalPublicPlane(ctx, live, inbox) {
|
|
26
|
-
const { plan,
|
|
26
|
+
const { plan, deps: seams, actorSpecs, concurrency, warnings } = ctx;
|
|
27
27
|
const participants = plan.plane.participants;
|
|
28
|
-
// publicAppUrl is the operator-declared shared plane; its
|
|
29
|
-
// (publicOriginDigest), never raw (the raw URL
|
|
30
|
-
//
|
|
28
|
+
// publicAppUrl is the operator-declared shared plane; its origin is persisted digest-only
|
|
29
|
+
// (publicOriginDigest), never raw (the raw URL and the runtime observed lobby code never land in
|
|
30
|
+
// the bundle). The latch code is scrubbed from all narration.
|
|
31
31
|
const publicAppUrl = plan.plane.kind === "external-public" ? plan.plane.appUrl : "";
|
|
32
32
|
const declaredOriginDigest = declaredOriginDigestOf(publicAppUrl);
|
|
33
33
|
const handoff = new LobbyHandoff({
|
|
34
34
|
participantCount: participants.length,
|
|
35
35
|
timeoutMs: ctx.timeoutMs,
|
|
36
|
-
deadlineMs:
|
|
36
|
+
deadlineMs: seams.handoffDeadlineMs,
|
|
37
37
|
scrubKnownValues: ctx.scrubKnownValues,
|
|
38
38
|
// The per-seat vision lobby-code reader (default: the real single-frame OpenAI read). Injectable
|
|
39
39
|
// so the barrier's handoff + convergence proof are testable without a live vision call.
|
|
40
|
-
readLobbyCode:
|
|
40
|
+
readLobbyCode: seams.readLobbyCodeFromFrame ?? readLobbyCodeFromFrame,
|
|
41
41
|
openaiApiKey: ctx.openaiApiKey,
|
|
42
42
|
});
|
|
43
43
|
const deps = {
|
|
44
|
-
// Scrub the latched lobby
|
|
44
|
+
// Scrub the latched lobby code (known once the host resolves it) from all narration.
|
|
45
45
|
runDeps: participantRunDeps(ctx, live, handoff.scrub),
|
|
46
46
|
publicAppUrl,
|
|
47
47
|
inbox,
|
|
@@ -51,11 +51,10 @@ export async function runExternalPublicPlane(ctx, live, inbox) {
|
|
|
51
51
|
// provisioned path.
|
|
52
52
|
const snapshotArgs = {
|
|
53
53
|
plan,
|
|
54
|
+
run: ctx.run,
|
|
54
55
|
descriptor: ctx.descriptor,
|
|
55
|
-
createdAt: ctx.createdAt,
|
|
56
56
|
dryRun: false,
|
|
57
57
|
inProgress: true,
|
|
58
|
-
runId: ctx.runId,
|
|
59
58
|
source: ctx.source,
|
|
60
59
|
actorSpecs,
|
|
61
60
|
actorResults: [],
|
|
@@ -63,8 +62,8 @@ export async function runExternalPublicPlane(ctx, live, inbox) {
|
|
|
63
62
|
subject: { source: "app-url", envNames: [], state: { provenance: "external-public" } },
|
|
64
63
|
seedDigest: ctx.seedDigest,
|
|
65
64
|
planeClass: "external-public",
|
|
66
|
-
// Pre-fan-out snapshot: no seat has observed an origin yet, so the
|
|
67
|
-
// is not available; surface the
|
|
65
|
+
// Pre-fan-out snapshot: no seat has observed an origin yet, so the observed publicOriginDigest
|
|
66
|
+
// is not available; surface the declared origin for the live Observer's reference.
|
|
68
67
|
...(declaredOriginDigest === undefined ? {} : { declaredOriginDigest }),
|
|
69
68
|
};
|
|
70
69
|
const inProgressBundle = buildConcurrentSharedWorldBundle({
|
|
@@ -85,7 +84,7 @@ export async function runExternalPublicPlane(ctx, live, inbox) {
|
|
|
85
84
|
let runError;
|
|
86
85
|
let commsArtifactPath;
|
|
87
86
|
// Split the roster into the designated host and the followers, preserving each follower's
|
|
88
|
-
//
|
|
87
|
+
// original plan index so results land back in plan order (validation allows exactly one host).
|
|
89
88
|
const hostIndex = participants.findIndex((participant) => participant.host === true);
|
|
90
89
|
const followerEntries = actorSpecs
|
|
91
90
|
.map((spec, index) => ({ spec, index }))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DesktopParticipantRun, ParticipantRunOutcome } from "../computer-use/types.js";
|
|
2
|
-
import { type ParticipantRunDeps } from "./
|
|
2
|
+
import { type ParticipantRunDeps } from "./participant-specs.js";
|
|
3
3
|
import type { ActorRunResult, ExternalCommsWiring } from "./types.js";
|
|
4
|
-
/** What the host and follower
|
|
4
|
+
/** What the host and follower participants need besides the handoff. */
|
|
5
5
|
export interface HandoffParticipantDeps {
|
|
6
6
|
runDeps: ParticipantRunDeps;
|
|
7
7
|
publicAppUrl: string;
|
|
@@ -10,7 +10,7 @@ export interface HandoffParticipantDeps {
|
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* The handoff latch, its deadline and what each seat observed. The latched code and observed URLs
|
|
13
|
-
* are runtime-only and land in persisted
|
|
13
|
+
* are runtime-only and land in persisted metadata only as digests (origin + convergence). (The code
|
|
14
14
|
* is a shareable game code, not a secret, and it still renders in the host's screenshots, which are
|
|
15
15
|
* full-fidelity unless redactScreenshots is set — the digesting is about narration/URL metadata.)
|
|
16
16
|
*/
|
|
@@ -38,7 +38,7 @@ export declare class LobbyHandoff {
|
|
|
38
38
|
openaiApiKey: string;
|
|
39
39
|
});
|
|
40
40
|
/**
|
|
41
|
-
* Scrubs the latched lobby
|
|
41
|
+
* Scrubs the latched lobby code from any persisted narration once the host resolves it (the
|
|
42
42
|
* 6-char code has no detectable secret shape, so shape-only redaction cannot catch it).
|
|
43
43
|
*/
|
|
44
44
|
readonly scrub: (text: string) => string;
|
|
@@ -2,38 +2,38 @@
|
|
|
2
2
|
// for the host's lobby code, read from the host's URL, narration or screen, and then joins with it.
|
|
3
3
|
// A follower fails closed without opening if the host never yields a code within the deadline.
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
5
|
+
// Temporary shim (tracked by #296): this CDP URL-relay handoff reads the host's /lobby/CODE off its
|
|
6
|
+
// own browser and threads it into the follower missions.
|
|
7
7
|
// It is to be augmented/replaced by the actor message bus (fake SMS/email invite) in #297: the
|
|
8
|
-
// human-realistic version is the
|
|
8
|
+
// human-realistic version is the host sending the invite link and followers receiving and tapping
|
|
9
9
|
// it, rather than the orchestrator relaying the code out-of-band.
|
|
10
10
|
import { commandDigestOf } from "../../subject/state.js";
|
|
11
11
|
import { toErrorMessage } from "../../evidence/redaction.js";
|
|
12
12
|
import { inboxRecipientFor, participantHasInboxRecipient, } from "../computer-use/participant-desktop.js";
|
|
13
13
|
import { withInboxMission } from "../computer-use/participant-prompt.js";
|
|
14
|
-
import { runCuaParticipant } from "../computer-use/
|
|
14
|
+
import { runCuaParticipant } from "../computer-use/participant-execution.js";
|
|
15
15
|
import { extractLobbyCode, extractLobbyCodeFromNarration } from "./lobby-code.js";
|
|
16
16
|
import { hostOriginDigest } from "./provenance.js";
|
|
17
|
-
import { makeBlockedFollowerOutcome, withLobbyCodeMission, } from "./
|
|
18
|
-
// The
|
|
17
|
+
import { makeBlockedFollowerOutcome, withLobbyCodeMission, } from "./participant-specs.js";
|
|
18
|
+
// The floor for the host-first handoff barrier deadline (ms). The host seat must surface a
|
|
19
19
|
// shared-session (/lobby/CODE) URL within the deadline or the run fails closed and no follower
|
|
20
|
-
// opens. The effective deadline
|
|
20
|
+
// opens. The effective deadline scales with the per-seat run budget (execution.timeoutMs): a fixed
|
|
21
21
|
// 2 min is too tight for a real create-a-lobby flow on a mobile-layout seat once you subtract the
|
|
22
22
|
// seat's own desktop provisioning — the host reaches /lobby/CODE, but after the followers already
|
|
23
|
-
// gave up. So use max(
|
|
23
|
+
// gave up. So use max(floor, 40% of the budget), capped at the budget. The latch resolves the
|
|
24
24
|
// instant the host actually reaches /lobby, so a generous ceiling only affects the fail-closed case.
|
|
25
25
|
const DEFAULT_HANDOFF_DEADLINE_MS = 120_000;
|
|
26
26
|
const HANDOFF_DEADLINE_BUDGET_FRACTION = 0.4;
|
|
27
|
-
// Per-seat runaway backstop for the vision-off-frame lobby-code read (used by the host to
|
|
28
|
-
// handoff code, and by each follower to independently
|
|
27
|
+
// Per-seat runaway backstop for the vision-off-frame lobby-code read (used by the host to latch the
|
|
28
|
+
// handoff code, and by each follower to independently observe its own code for the convergence proof):
|
|
29
29
|
// at most this many single-frame reads before the seat is assumed to be somewhere without a code. Each
|
|
30
30
|
// reader stops the instant it has what it needs, so in practice only a handful fire (a seat reaches its
|
|
31
31
|
// /lobby within a few turns). NOTE: these reads are out-of-band OpenAI calls (external-public route
|
|
32
|
-
// only) and are
|
|
33
|
-
//
|
|
32
|
+
// only) and are left out of execution.caps.maxUsd, so this hard cap is what bounds their spend
|
|
33
|
+
// (each read is one cheap single-frame OCR call). If this route ever runs under a strict
|
|
34
34
|
// budget, fold the estimate in.
|
|
35
35
|
const MAX_LOBBY_CODE_VISION_READS = 30;
|
|
36
|
-
// Idle/no-progress backstop for the
|
|
36
|
+
// Idle/no-progress backstop for the host participant specifically (default is 6/8). The host legitimately sits
|
|
37
37
|
// on an unchanging waiting-room screen while followers provision and join; it must not give up first.
|
|
38
38
|
const HOST_WAIT_IDLE_STEPS = 80;
|
|
39
39
|
const FOLLOWER_WAIT_IDLE_STEPS = 40;
|
|
@@ -67,13 +67,13 @@ class HandoffTimeoutError extends Error {
|
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* The handoff latch, its deadline and what each seat observed. The latched code and observed URLs
|
|
70
|
-
* are runtime-only and land in persisted
|
|
70
|
+
* are runtime-only and land in persisted metadata only as digests (origin + convergence). (The code
|
|
71
71
|
* is a shareable game code, not a secret, and it still renders in the host's screenshots, which are
|
|
72
72
|
* full-fidelity unless redactScreenshots is set — the digesting is about narration/URL metadata.)
|
|
73
73
|
*/
|
|
74
74
|
export class LobbyHandoff {
|
|
75
|
-
// Per-
|
|
76
|
-
// observed /lobby/CODE per seat, fed by onObservedUrl. The URL is digested to
|
|
75
|
+
// Per-participant runtime-only observed state (never persisted raw): the last observed URL and the last
|
|
76
|
+
// observed /lobby/CODE per seat, fed by onObservedUrl. The URL is digested to its origin for each seat's
|
|
77
77
|
// routeHostDigest (no code leaks); the codes drive the cross-seat lobby-convergence digest.
|
|
78
78
|
observedFinalUrls;
|
|
79
79
|
observedLobbyCodes;
|
|
@@ -100,7 +100,7 @@ export class LobbyHandoff {
|
|
|
100
100
|
this.openaiApiKey = options.openaiApiKey;
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
|
-
* Scrubs the latched lobby
|
|
103
|
+
* Scrubs the latched lobby code from any persisted narration once the host resolves it (the
|
|
104
104
|
* 6-char code has no detectable secret shape, so shape-only redaction cannot catch it).
|
|
105
105
|
*/
|
|
106
106
|
scrub = (text) => {
|
|
@@ -122,7 +122,7 @@ export class LobbyHandoff {
|
|
|
122
122
|
this.deadlineTimer = undefined;
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
// Resolve the host->follower handoff latch from
|
|
125
|
+
// Resolve the host->follower handoff latch from whichever path sees the code first (CDP url-read,
|
|
126
126
|
// host narration, or vision-off-frame). Idempotent: only the first code wins, and it is also stashed
|
|
127
127
|
// as latchedLobbyCode so it gets scrubbed from any later narration.
|
|
128
128
|
latchLobbyCode(code, participantIndex) {
|
|
@@ -133,7 +133,7 @@ export class LobbyHandoff {
|
|
|
133
133
|
this.stopDeadline();
|
|
134
134
|
this.lobbyCodeLatch.resolve(code);
|
|
135
135
|
}
|
|
136
|
-
// Build an onScreenshot handler that vision-reads the lobby code off
|
|
136
|
+
// Build an onScreenshot handler that vision-reads the lobby code off this seat's own frame (the
|
|
137
137
|
// CDP-independent observation). `done()` short-circuits once this seat has what it needs (the host
|
|
138
138
|
// once latched; a follower once it has recorded its own observed code), `onCode` records/latches the
|
|
139
139
|
// result. One read in flight at a time, bounded by MAX_LOBBY_CODE_VISION_READS so a seat that never
|
|
@@ -187,10 +187,10 @@ export class LobbyHandoff {
|
|
|
187
187
|
/** The digest-only convergence proofs over what the seats observed. */
|
|
188
188
|
convergence(declaredOriginDigest) {
|
|
189
189
|
// Observed-origin convergence proof (blocker 2): the convergence claim is about what the seats
|
|
190
|
-
//
|
|
191
|
-
//
|
|
190
|
+
// observed. Digest each observing seat's origin and require one shared origin; that agreement is
|
|
191
|
+
// the convergence proof and becomes plane.publicOriginDigest. A normal
|
|
192
192
|
// cross-origin redirect (declared apex -> observed www) is therefore tolerated: the seats still
|
|
193
|
-
// converge on
|
|
193
|
+
// converge on one observed origin. Leave it undefined (verify fails closed) only if the seats did
|
|
194
194
|
// not converge on a single observed origin (or none observed one).
|
|
195
195
|
const observedOriginDigests = this.observedFinalUrls
|
|
196
196
|
.filter((url) => typeof url === "string" && url.length > 0)
|
|
@@ -198,18 +198,18 @@ export class LobbyHandoff {
|
|
|
198
198
|
const distinctObservedOrigins = new Set(observedOriginDigests);
|
|
199
199
|
const publicOriginDigest = distinctObservedOrigins.size === 1
|
|
200
200
|
? [...distinctObservedOrigins][0]
|
|
201
|
-
: //
|
|
202
|
-
//
|
|
203
|
-
// digests to the declared origin too). The run still fails closed for its own reason
|
|
204
|
-
//
|
|
201
|
+
: // Nothing observed (e.g. a handoff-timeout run where no seat ever navigated): fall back to the
|
|
202
|
+
// declared origin so a failed run's bundle stays structurally valid (every seat's route then
|
|
203
|
+
// digests to the declared origin too). The run still fails closed for its own reason
|
|
204
|
+
// (`HANDOFF_TIMEOUT`, no lobby convergence, no overlap-on-pass). Real divergence (≥2 distinct observed
|
|
205
205
|
// origins) leaves it undefined so verify fails closed on the non-convergence.
|
|
206
206
|
distinctObservedOrigins.size === 0
|
|
207
207
|
? declaredOriginDigest
|
|
208
208
|
: undefined;
|
|
209
|
-
// Lobby-convergence proof: a digest of the shared /lobby/CODE path iff
|
|
210
|
-
//
|
|
211
|
-
// observedLobbyCodes may be a
|
|
212
|
-
// Array.prototype.every
|
|
209
|
+
// Lobby-convergence proof: a digest of the shared /lobby/CODE path iff every seat converged on the
|
|
210
|
+
// same code (a follower stuck on "/" yields no code, so no false convergence). Digest-only.
|
|
211
|
+
// observedLobbyCodes may be a sparse array (a seat that never observed a code leaves a hole), and
|
|
212
|
+
// Array.prototype.every skips holes, so count the defined codes explicitly instead of every().
|
|
213
213
|
const definedCodes = this.observedLobbyCodes.filter((code) => code !== undefined);
|
|
214
214
|
const distinctCodes = new Set(definedCodes);
|
|
215
215
|
const lobbyConvergenceDigest = distinctCodes.size === 1 && definedCodes.length === this.observedLobbyCodes.length
|
|
@@ -218,30 +218,30 @@ export class LobbyHandoff {
|
|
|
218
218
|
return { publicOriginDigest, lobbyConvergenceDigest };
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
|
-
// Adopter-hosted inbox (#387): the persona is told its address and inbox URL on
|
|
221
|
+
// Adopter-hosted inbox (#387): the persona is told its address and inbox URL on this plane.
|
|
222
222
|
function withParticipantInbox(spec, inbox) {
|
|
223
223
|
return inbox && participantHasInboxRecipient(inbox.email, spec.planned.id)
|
|
224
224
|
? withInboxMission(spec, inbox.inboxUrl, inboxRecipientFor(inbox.email, spec.planned.id)?.address)
|
|
225
225
|
: spec;
|
|
226
226
|
}
|
|
227
|
-
// The
|
|
228
|
-
// slot, and the
|
|
229
|
-
// followers block on the host's code while holding a worker slot, so if the host
|
|
230
|
-
// scheduled
|
|
231
|
-
// `concurrency` workers) and the run would die with a spurious HANDOFF_TIMEOUT (e.g.
|
|
232
|
-
// [p2,p3,host] with concurrency 2). Giving the host its own slot, started
|
|
233
|
-
// the follower pool,
|
|
234
|
-
//
|
|
227
|
+
// The host participant (which yields the /lobby/CODE the followers wait on) runs on its own dedicated
|
|
228
|
+
// slot, and the followers run through a bounded pool of size concurrency-1 (blockers 1 & 4):
|
|
229
|
+
// followers block on the host's code while holding a worker slot, so if the host participant were
|
|
230
|
+
// scheduled inside the same bounded pool it could be starved (never scheduled among the first
|
|
231
|
+
// `concurrency` workers) and the run would die with a spurious HANDOFF_TIMEOUT (e.g. participants
|
|
232
|
+
// [p2,p3,host] with concurrency 2). Giving the host its own slot, started immediately and outside
|
|
233
|
+
// the follower pool, keeps it schedulable regardless of its roster position or of concurrency vs
|
|
234
|
+
// participant count, while total in-flight paid desktops stay ≤ the declared concurrency
|
|
235
235
|
// (host + up to concurrency-1 followers), preserving the spend cap.
|
|
236
236
|
export async function runHost(handoff, deps, spec, participantIndex) {
|
|
237
237
|
const onObservedUrl = handoff.makeObservedUrl(participantIndex, true);
|
|
238
238
|
// CDP-INDEPENDENT handoff paths (the E2B-desktop CDP url-read the onObservedUrl path relies on is
|
|
239
|
-
// unreliable in practice). Two backups, both resolving the
|
|
239
|
+
// unreliable in practice). Two backups, both resolving the same latch; whichever sees the code first
|
|
240
240
|
// wins, all digest-only:
|
|
241
|
-
// (1) onMessage
|
|
241
|
+
// (1) onMessage: scan the host's own narration if it happens to state the lobby URL; and
|
|
242
242
|
// (2) onScreenshot — vision-read the code straight off the host's waiting-room frame. This is the
|
|
243
|
-
// robust one: the code is rendered on screen even when CDP fails
|
|
244
|
-
// narrates it, and
|
|
243
|
+
// robust one: the code is rendered on screen even when CDP fails and when the host never
|
|
244
|
+
// narrates it, and the host is never asked to announce anything, so it keeps
|
|
245
245
|
// running (create -> wait for players -> Start -> play) instead of ending on a stray message.
|
|
246
246
|
const onMessage = (text) => {
|
|
247
247
|
if (handoff.latchedLobbyCode !== undefined)
|
|
@@ -250,9 +250,9 @@ export async function runHost(handoff, deps, spec, participantIndex) {
|
|
|
250
250
|
if (code !== undefined)
|
|
251
251
|
handoff.latchLobbyCode(code, participantIndex);
|
|
252
252
|
};
|
|
253
|
-
// Vision-read the host's waiting-room frame and
|
|
253
|
+
// Vision-read the host's waiting-room frame and latch the code for the followers (stops once latched).
|
|
254
254
|
const onScreenshot = handoff.makeLobbyCodeVisionReader(() => handoff.latchedLobbyCode !== undefined, (code) => handoff.latchLobbyCode(code, participantIndex));
|
|
255
|
-
// The host's job includes a long
|
|
255
|
+
// The host's job includes a long, legitimate idle wait: sitting in the waiting room while the
|
|
256
256
|
// followers provision their own desktops and walk the Join flow (easily 15-30 turns of an
|
|
257
257
|
// unchanging "waiting for players" screen). At the default idle backstop (6) the host would give up
|
|
258
258
|
// before anyone arrives, orphaning the lobby (exactly the earlier failure). Raise the host's idle /
|
|
@@ -291,7 +291,7 @@ export async function runHost(handoff, deps, spec, participantIndex) {
|
|
|
291
291
|
}
|
|
292
292
|
export async function runFollower(handoff, deps, spec, participantIndex) {
|
|
293
293
|
const onObservedUrl = handoff.makeObservedUrl(participantIndex, false);
|
|
294
|
-
//
|
|
294
|
+
// Follower: compose no mission and open no target until the host yields a lobby code.
|
|
295
295
|
let code;
|
|
296
296
|
try {
|
|
297
297
|
code = await handoff.waitForHostCode();
|
|
@@ -320,11 +320,11 @@ export async function runFollower(handoff, deps, spec, participantIndex) {
|
|
|
320
320
|
noProgressSteps: spec.backstop?.noProgressSteps ?? FOLLOWER_WAIT_IDLE_STEPS,
|
|
321
321
|
},
|
|
322
322
|
};
|
|
323
|
-
// Independently
|
|
324
|
-
// and record it for the cross-seat convergence proof. This
|
|
325
|
-
//
|
|
323
|
+
// Independently observe this follower's own lobby code by vision-reading its waiting-room frame,
|
|
324
|
+
// and record it for the cross-seat convergence proof. This latches nothing (followers gate on the
|
|
325
|
+
// host's code). It fills this seat's observedLobbyCodes slot from a
|
|
326
326
|
// reliable signal instead of the flaky CDP url-read, so lobbyConvergenceDigest can prove all seats
|
|
327
|
-
// reached the
|
|
327
|
+
// reached the same /lobby/CODE. If a follower somehow joined another lobby, it reads a different
|
|
328
328
|
// code and convergence correctly fails (no false proof); if it never reads one, the seat stays a
|
|
329
329
|
// hole and convergence is honestly "not observed" for that seat.
|
|
330
330
|
const onScreenshot = handoff.makeLobbyCodeVisionReader(() => handoff.observedLobbyCodes[participantIndex] !== undefined, (observed) => {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
/** Extract the shared-session
|
|
1
|
+
/** Extract the shared-session code from a (runtime-only) observed URL, or undefined. Exported for the
|
|
2
2
|
* handoff regex table test — pure, no side effects, never persists its input. */
|
|
3
3
|
export declare function extractLobbyCode(url: string | undefined): string | undefined;
|
|
4
4
|
export declare function extractLobbyCodeFromNarration(text: string | undefined): string | undefined;
|
|
5
5
|
/** Pull the assistant's plain text out of an OpenAI Responses API body (`output_text` convenience
|
|
6
6
|
* field, else the concatenated `output[].content[].text`). Tolerant of shape drift; pure. */
|
|
7
7
|
export declare function extractResponsesOutputText(parsed: unknown): string | undefined;
|
|
8
|
-
/** Parse a vision reply into a lobby
|
|
8
|
+
/** Parse a vision reply into a lobby code. Precision-first: accept only when the whole reply is the
|
|
9
9
|
* six-character code, or when it echoes an explicit /lobby/CODE — never a bare 6-letter token buried in
|
|
10
|
-
* prose (e.g. "I see a home SCREEN"), because a wrong latch fails the entire run, whereas a miss just
|
|
11
|
-
* retries on the next frame while the host keeps waiting. NONE (the instructed "no code" reply) is
|
|
10
|
+
* prose (e.g. "I see a home `SCREEN`"), because a wrong latch fails the entire run, whereas a miss just
|
|
11
|
+
* retries on the next frame while the host keeps waiting. `NONE` (the instructed "no code" reply) is
|
|
12
12
|
* rejected. Pure. */
|
|
13
13
|
export declare function parseLobbyCodeReply(reply: string | undefined): string | undefined;
|
|
14
14
|
export interface ReadLobbyCodeOptions {
|
|
@@ -18,7 +18,7 @@ export interface ReadLobbyCodeOptions {
|
|
|
18
18
|
signal?: AbortSignal;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Vision-read a lobby
|
|
21
|
+
* Vision-read a lobby code straight off a host waiting-room frame (the robust, CDP-independent handoff
|
|
22
22
|
* relay). Fail-soft: any network/HTTP/parse problem returns undefined so the caller simply retries on
|
|
23
23
|
* the next frame. The frame is runtime-only; only the extracted code is used (as a digest downstream).
|
|
24
24
|
*/
|
|
@@ -5,10 +5,10 @@ import { OPENAI_RESPONSES_URL } from "../../actors/openai-endpoint.js";
|
|
|
5
5
|
/**
|
|
6
6
|
* The lobby-trivia (and general "/lobby/CODE") shared-session URL matcher. A code is exactly 6 chars of
|
|
7
7
|
* the [A-Z2-9] class; a locale prefix (/en/lobby/…) and a query/hash suffix are tolerated. RUNTIME-ONLY
|
|
8
|
-
* input (a live location.href); only the extracted
|
|
8
|
+
* input (a live location.href); only the extracted code is used, and it lands only as a digest.
|
|
9
9
|
*/
|
|
10
10
|
const LOBBY_CODE_PATTERN = /\/lobby\/([A-Z2-9]{6})(?:$|[/?#])/;
|
|
11
|
-
/** Extract the shared-session
|
|
11
|
+
/** Extract the shared-session code from a (runtime-only) observed URL, or undefined. Exported for the
|
|
12
12
|
* handoff regex table test — pure, no side effects, never persists its input. */
|
|
13
13
|
export function extractLobbyCode(url) {
|
|
14
14
|
if (typeof url !== "string")
|
|
@@ -17,7 +17,7 @@ export function extractLobbyCode(url) {
|
|
|
17
17
|
return match ? match[1] : undefined;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* Extract a lobby
|
|
20
|
+
* Extract a lobby code from free-form actor narration (the host's reasoning/message where it states
|
|
21
21
|
* the lobby URL it sees), where the /lobby/CODE is followed by arbitrary prose (a space, backtick,
|
|
22
22
|
* newline) rather than end-of-string or /?# — so the strict LOBBY_CODE_PATTERN would miss it. Uses a
|
|
23
23
|
* negative-lookahead boundary (exactly 6 code chars). This is the CDP-INDEPENDENT handoff path: the
|
|
@@ -32,10 +32,10 @@ export function extractLobbyCodeFromNarration(text) {
|
|
|
32
32
|
if (inUrl)
|
|
33
33
|
return inUrl[1];
|
|
34
34
|
// Fallback: an explicitly-labeled bare code (e.g. "LOBBY_CODE=ABC123"), which the host may state
|
|
35
|
-
// if it copied the code rather than the URL. The label is matched case-insensitively, but the
|
|
36
|
-
// itself must be
|
|
35
|
+
// if it copied the code rather than the URL. The label is matched case-insensitively, but the code
|
|
36
|
+
// itself must be uppercase [A-Z2-9]: a real lobby code always renders uppercase, whereas an /i match
|
|
37
37
|
// on the code class would also grab an ordinary lowercase word after "lobby code " (e.g. "the lobby
|
|
38
|
-
// code screen") and latch a
|
|
38
|
+
// code screen") and latch a wrong code. Precision-first, matching parseLobbyCodeReply's rationale.
|
|
39
39
|
const labeled = text.match(/lobby[ _-]?code[=:\s]+([A-Z2-9]{6})(?![A-Za-z2-9])/i);
|
|
40
40
|
return labeled && labeled[1] && /^[A-Z2-9]{6}$/.test(labeled[1]) ? labeled[1] : undefined;
|
|
41
41
|
}
|
|
@@ -67,10 +67,10 @@ export function extractResponsesOutputText(parsed) {
|
|
|
67
67
|
}
|
|
68
68
|
return parts.length > 0 ? parts.join("\n") : undefined;
|
|
69
69
|
}
|
|
70
|
-
/** Parse a vision reply into a lobby
|
|
70
|
+
/** Parse a vision reply into a lobby code. Precision-first: accept only when the whole reply is the
|
|
71
71
|
* six-character code, or when it echoes an explicit /lobby/CODE — never a bare 6-letter token buried in
|
|
72
|
-
* prose (e.g. "I see a home SCREEN"), because a wrong latch fails the entire run, whereas a miss just
|
|
73
|
-
* retries on the next frame while the host keeps waiting. NONE (the instructed "no code" reply) is
|
|
72
|
+
* prose (e.g. "I see a home `SCREEN`"), because a wrong latch fails the entire run, whereas a miss just
|
|
73
|
+
* retries on the next frame while the host keeps waiting. `NONE` (the instructed "no code" reply) is
|
|
74
74
|
* rejected. Pure. */
|
|
75
75
|
export function parseLobbyCodeReply(reply) {
|
|
76
76
|
if (typeof reply !== "string")
|
|
@@ -88,11 +88,11 @@ const LOBBY_CODE_VISION_PROMPT = "This is a screenshot of a the example multipla
|
|
|
88
88
|
"code'/'room code' label or inside an invite link of the form /lobby/CODE. Your entire reply MUST be " +
|
|
89
89
|
"exactly those 6 characters in uppercase and NOTHING else (no words, no punctuation). If no lobby " +
|
|
90
90
|
"code is visible on this screen (e.g. it is the home screen or a game round), reply exactly NONE.";
|
|
91
|
-
// A single-frame OCR-style read. gpt-5.5 (the
|
|
91
|
+
// A single-frame OCR-style read. gpt-5.5 (the computer-use default) is used deliberately: it reliably reads the
|
|
92
92
|
// 6-char code off a dense MOBILE-viewport waiting room — a smaller/cheaper model (gpt-4.1-mini) was
|
|
93
|
-
// tried and could
|
|
93
|
+
// tried and could not read it. reasoning.effort stays "low" (minimal) and the output budget is small
|
|
94
94
|
// but comfortably clear of the "incomplete on reasoning overflow" edge. Kept on the same account/key
|
|
95
|
-
// as the actor; the same full-fidelity frame is already sent to this API by the
|
|
95
|
+
// as the actor; the same full-fidelity frame is already sent to this API by the computer-use provider, so this
|
|
96
96
|
// adds no new data-exposure surface. See onScreenshot in runHost.
|
|
97
97
|
const LOBBY_CODE_VISION_MODEL = "gpt-5.5";
|
|
98
98
|
// Output-token budget for the read. The answer is 6 chars, but leave clear margin over any low-effort
|
|
@@ -102,7 +102,7 @@ const LOBBY_CODE_VISION_MAX_OUTPUT_TOKENS = 64;
|
|
|
102
102
|
// visionInFlight pinned true and silently kill the relay for the rest of the host run.
|
|
103
103
|
const LOBBY_CODE_VISION_TIMEOUT_MS = 15_000;
|
|
104
104
|
/**
|
|
105
|
-
* Vision-read a lobby
|
|
105
|
+
* Vision-read a lobby code straight off a host waiting-room frame (the robust, CDP-independent handoff
|
|
106
106
|
* relay). Fail-soft: any network/HTTP/parse problem returns undefined so the caller simply retries on
|
|
107
107
|
* the next frame. The frame is runtime-only; only the extracted code is used (as a digest downstream).
|
|
108
108
|
*/
|
|
@@ -8,9 +8,9 @@ export declare function defaultSessionTimeoutMs(plan: SharedWorldPlan): number;
|
|
|
8
8
|
* relative path, validated at parse against serve.url). */
|
|
9
9
|
export declare function resolveActorEntryUrl(baseUrl: string, entry: string | undefined): string;
|
|
10
10
|
export declare function participantTaxonomyLabel(labels: Participant["labels"]): string;
|
|
11
|
-
/** Thread the host-yielded lobby
|
|
12
|
-
* The
|
|
13
|
-
* the model reads (never a raw bundle field), and the lab scrubs the
|
|
11
|
+
/** Thread the host-yielded lobby code into a follower's mission at runtime (external-public route).
|
|
12
|
+
* The code flows into the follower's join instruction; it is persisted only as the composed prompt
|
|
13
|
+
* the model reads (never a raw bundle field), and the lab scrubs the code from all narration. The
|
|
14
14
|
* follower joins through the real UI (a direct /lobby/CODE visit does not auto-join a non-member). */
|
|
15
15
|
export declare function withLobbyCodeMission(spec: DesktopParticipantRun, code: string): DesktopParticipantRun;
|
|
16
16
|
/** A follower blocked by an expired deadline or an ended host. It never opened a browser;
|
|
@@ -25,9 +25,11 @@ export type ParticipantRunDeps = Omit<CuaParticipantDeps, "signalProvisioned" |
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function startParticipantFlush(ctx: PlaneContext, live: LiveParticipants, bundle: RunBundle): void;
|
|
27
27
|
/**
|
|
28
|
-
* The runner deps both planes give every participant.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* The runner deps both planes give every participant. The `shared-app` subject keeps three things
|
|
29
|
+
* out of every actor sandbox: the subject env names' values, the GitHub token, and clone
|
|
30
|
+
* or local-tree provisioning. The committed subject.envValues still reach it, non-secret by parse.
|
|
31
|
+
* `scrubKnownValues` is the plane's scrub: the external-public plane also scrubs the latched lobby
|
|
32
|
+
* code.
|
|
31
33
|
*/
|
|
32
34
|
export declare function participantRunDeps(ctx: PlaneContext, live: LiveParticipants, scrubKnownValues: (text: string) => string): ParticipantRunDeps;
|
|
33
35
|
/**
|