humanish 0.107.0 → 0.108.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/ARCHITECTURE.md +22 -17
- package/CHANGELOG.md +14 -0
- package/CONTEXT.md +51 -44
- package/README.md +145 -172
- package/SECURITY.md +16 -26
- package/TELEMETRY.md +8 -6
- package/dist/actors/affordance.d.ts +4 -4
- package/dist/actors/affordance.js +12 -12
- package/dist/actors/agent-session.d.ts +2 -2
- package/dist/actors/agent-session.js +7 -7
- package/dist/actors/codex/app-server-actor-trace.d.ts +1 -1
- package/dist/actors/codex/app-server-actor-trace.js +1 -1
- package/dist/actors/codex/app-server-ui.js +1 -1
- package/dist/actors/codex/codex-admission.d.ts +91 -0
- package/dist/actors/codex/codex-admission.js +150 -0
- package/dist/actors/codex/restricted-executable.d.ts +4 -4
- package/dist/actors/codex/restricted-executable.js +8 -8
- package/dist/actors/codex/restricted-launch.d.ts +2 -1
- package/dist/actors/codex/restricted-launch.js +1 -1
- package/dist/actors/codex/restricted-participant.js +8 -6
- package/dist/actors/codex/restricted-policy.d.ts +2 -2
- package/dist/actors/codex/restricted-policy.js +2 -2
- package/dist/actors/codex/restricted-session.d.ts +2 -2
- package/dist/actors/codex/restricted-session.js +10 -5
- package/dist/actors/computer-use/actor.d.ts +16 -16
- package/dist/actors/computer-use/actor.js +2 -2
- package/dist/actors/computer-use/admission-limit.d.ts +1 -1
- package/dist/actors/computer-use/admission-limit.js +1 -1
- package/dist/actors/computer-use/loop/actions.d.ts +3 -3
- package/dist/actors/computer-use/loop/actions.js +10 -10
- package/dist/actors/computer-use/loop/backstop.d.ts +3 -3
- package/dist/actors/computer-use/loop/backstop.js +14 -12
- package/dist/actors/computer-use/loop/ending.d.ts +5 -5
- package/dist/actors/computer-use/loop/ending.js +7 -7
- package/dist/actors/computer-use/loop/observation.d.ts +2 -2
- package/dist/actors/computer-use/loop/observation.js +9 -9
- package/dist/actors/computer-use/loop/provider-call.d.ts +1 -1
- package/dist/actors/computer-use/loop/provider-call.js +1 -1
- package/dist/actors/computer-use/loop/session.js +3 -3
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +1 -1
- package/dist/actors/computer-use/loop/trace.js +9 -8
- package/dist/actors/computer-use/loop/types.d.ts +25 -23
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/openai-context.d.ts +37 -0
- package/dist/actors/computer-use/openai-context.js +214 -0
- package/dist/actors/computer-use/openai-provider.d.ts +11 -8
- package/dist/actors/computer-use/openai-provider.js +45 -34
- package/dist/actors/computer-use/openai-requests.d.ts +36 -10
- package/dist/actors/computer-use/openai-requests.js +82 -15
- package/dist/actors/computer-use/openai-wire.d.ts +19 -7
- package/dist/actors/computer-use/openai-wire.js +36 -34
- package/dist/actors/contract.d.ts +78 -43
- package/dist/actors/contract.js +29 -23
- package/dist/actors/local-agent/claude-session.d.ts +1 -1
- package/dist/actors/local-agent/claude-session.js +10 -9
- package/dist/actors/local-agent/cli.d.ts +8 -6
- package/dist/actors/local-agent/cli.js +24 -28
- package/dist/actors/local-agent/readiness.d.ts +2 -2
- package/dist/actors/local-agent/readiness.js +4 -4
- package/dist/actors/reasoning-effort.js +6 -6
- package/dist/actors/registry.d.ts +10 -10
- package/dist/actors/registry.js +18 -17
- package/dist/actors/scripted-browser/actor.d.ts +8 -8
- package/dist/actors/scripted-browser/actor.js +16 -16
- package/dist/actors/scripted-browser/browser-command.js +1 -1
- package/dist/actors/scripted-browser/steps.js +1 -1
- package/dist/actors/scripted-browser/types.d.ts +1 -1
- package/dist/actors/stop-conditions.d.ts +1 -1
- package/dist/analysis/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- package/dist/analysis/service.js +5 -5
- package/dist/cli/commands/analyze.js +19 -16
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +54 -33
- package/dist/cli/commands/feedback.js +20 -21
- package/dist/cli/commands/lab-format.d.ts +5 -4
- package/dist/cli/commands/lab-format.js +35 -23
- package/dist/cli/commands/lab-route-computer-use.js +6 -7
- package/dist/cli/commands/lab-route-preview.js +4 -3
- package/dist/cli/commands/lab-route-shared-world.js +3 -3
- package/dist/cli/commands/lab-run.js +10 -11
- package/dist/cli/commands/lab-scorer.d.ts +2 -2
- package/dist/cli/commands/lab-scorer.js +1 -1
- package/dist/cli/commands/migrate.d.ts +4 -0
- package/dist/cli/commands/migrate.js +65 -0
- package/dist/cli/commands/observe.js +147 -108
- package/dist/cli/commands/run-command.d.ts +10 -0
- package/dist/cli/commands/run-command.js +85 -0
- package/dist/cli/commands/runs.js +137 -138
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/commands/setup.js +26 -21
- package/dist/cli/commands/study.d.ts +3 -0
- package/dist/cli/commands/study.js +182 -0
- package/dist/cli/commands/tui.d.ts +4 -4
- package/dist/cli/commands/tui.js +21 -21
- package/dist/cli/commands/watch.js +60 -75
- package/dist/cli/deprecations.d.ts +18 -0
- package/dist/cli/deprecations.js +48 -0
- package/dist/cli/doctor.d.ts +15 -5
- package/dist/cli/doctor.js +103 -48
- package/dist/cli/first-run-path.d.ts +12 -10
- package/dist/cli/first-run-path.js +30 -28
- package/dist/cli/io.d.ts +41 -6
- package/dist/cli/io.js +97 -22
- package/dist/cli/observer-follow.d.ts +2 -2
- package/dist/cli/observer-follow.js +5 -6
- package/dist/cli/orientation.d.ts +6 -3
- package/dist/cli/orientation.js +43 -39
- package/dist/cli/product-sentence.d.ts +6 -0
- package/dist/cli/product-sentence.js +6 -0
- package/dist/cli/program.d.ts +6 -1
- package/dist/cli/program.js +109 -40
- package/dist/cli/telemetry.d.ts +15 -15
- package/dist/cli/telemetry.js +48 -40
- package/dist/cli.js +1 -1
- package/dist/comms/capture-surface.d.ts +13 -12
- package/dist/comms/capture-surface.js +23 -22
- package/dist/comms/catch-host.d.ts +7 -7
- package/dist/comms/catch-host.js +14 -14
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.js +2 -2
- package/dist/comms/extract.js +2 -2
- package/dist/comms/fake-inbox.d.ts +2 -2
- package/dist/comms/fake-inbox.js +2 -2
- package/dist/comms/receiving-render.d.ts +1 -1
- package/dist/comms/receiving-render.js +2 -2
- package/dist/comms/sandbox-catch-script.d.ts +6 -6
- package/dist/comms/sandbox-catch-script.js +6 -6
- package/dist/comms/sandbox-catch.d.ts +36 -37
- package/dist/comms/sandbox-catch.js +34 -35
- package/dist/comms/setup.js +42 -8
- package/dist/comms/thread-evidence.d.ts +1 -1
- package/dist/comms/thread-evidence.js +6 -6
- package/dist/comms/types.d.ts +6 -6
- package/dist/comms/types.js +3 -3
- package/dist/evidence/frame-signature.d.ts +1 -1
- package/dist/evidence/frame-signature.js +4 -4
- package/dist/evidence/redaction.d.ts +3 -3
- package/dist/evidence/redaction.js +4 -4
- package/dist/feedback/draft.js +36 -78
- package/dist/feedback/export-bundle.js +1 -1
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +7 -8
- package/dist/feedback/feedback.d.ts +2 -2
- package/dist/feedback/feedback.js +21 -3
- package/dist/guest/chromium-text.js +2 -2
- package/dist/guest/desktop-native.d.ts +1 -1
- package/dist/guest/runtime.js +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +8 -6
- package/dist/keys/key-resolution.d.ts +5 -5
- package/dist/keys/key-resolution.js +23 -23
- package/dist/lab/adapter-extension.d.ts +7 -7
- package/dist/lab/adapter-extension.js +13 -36
- package/dist/lab/adapter-scorer-loader.d.ts +7 -7
- package/dist/lab/adapter-scorer-loader.js +32 -32
- package/dist/lab/composition-rules.js +42 -42
- package/dist/lab/config.js +65 -25
- package/dist/lab/deprecated-fields.d.ts +10 -0
- package/dist/lab/deprecated-fields.js +24 -0
- package/dist/lab/device-presets.d.ts +8 -8
- package/dist/lab/device-presets.js +11 -11
- package/dist/lab/discover.d.ts +13 -9
- package/dist/lab/discover.js +117 -57
- package/dist/lab/doctor.d.ts +10 -3
- package/dist/lab/doctor.js +47 -9
- package/dist/lab/init-templates.js +147 -147
- package/dist/lab/init.d.ts +1 -1
- package/dist/lab/init.js +41 -9
- package/dist/lab/keys.d.ts +2 -0
- package/dist/lab/keys.js +42 -8
- package/dist/lab/lab-deps.d.ts +7 -12
- package/dist/lab/parse/actors.js +9 -9
- package/dist/lab/parse/comms.js +5 -5
- package/dist/lab/parse/execution.js +13 -13
- package/dist/lab/parse/study-v3.d.ts +23 -0
- package/dist/lab/parse/study-v3.js +259 -0
- package/dist/lab/parse/subject-state.d.ts +7 -7
- package/dist/lab/parse/subject-state.js +16 -16
- package/dist/lab/parse/subject.js +28 -28
- package/dist/lab/parse/values.d.ts +1 -1
- package/dist/lab/parse/values.js +3 -3
- package/dist/lab/persona-resolve.d.ts +4 -4
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/plan-participants.d.ts +2 -2
- package/dist/lab/plan-types.d.ts +4 -4
- package/dist/lab/plan.d.ts +1 -7
- package/dist/lab/plan.js +10 -41
- package/dist/lab/preflight-probes.js +11 -11
- package/dist/lab/preflight-result.d.ts +2 -1
- package/dist/lab/preflight-result.js +5 -4
- package/dist/lab/preflight.d.ts +7 -5
- package/dist/lab/preflight.js +5 -5
- package/dist/lab/routing.d.ts +31 -25
- package/dist/lab/routing.js +60 -29
- package/dist/lab/run-lab-events.d.ts +0 -3
- package/dist/lab/run-lab-events.js +0 -6
- package/dist/lab/run-lab-homes.d.ts +22 -10
- package/dist/lab/run-lab-homes.js +5 -1
- package/dist/lab/run-lab-options.d.ts +1 -1
- package/dist/lab/run-lab-options.js +16 -13
- package/dist/lab/summary.d.ts +7 -6
- package/dist/lab/summary.js +10 -10
- package/dist/lab/tasks.d.ts +15 -15
- package/dist/lab/tasks.js +14 -14
- package/dist/lab/types.d.ts +101 -95
- package/dist/lab/types.js +2 -0
- package/dist/lab/validation.d.ts +13 -13
- package/dist/lab/validation.js +44 -42
- package/dist/lab/warnings.d.ts +10 -0
- package/dist/lab/warnings.js +61 -33
- package/dist/library-aliases.d.ts +56 -0
- package/dist/library-aliases.js +22 -0
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +6 -6
- package/dist/observer/data.d.ts +6 -6
- package/dist/observer/data.js +5 -4
- package/dist/observer/exposure.d.ts +1 -1
- package/dist/observer/exposure.js +11 -11
- package/dist/observer/http.js +1 -1
- package/dist/observer/library.d.ts +1 -1
- package/dist/observer/library.js +4 -2
- package/dist/observer/listen.js +5 -4
- package/dist/observer/render.d.ts +1 -1
- package/dist/observer/render.js +10 -5
- package/dist/observer/run-routes.d.ts +3 -3
- package/dist/observer/run-routes.js +1 -1
- package/dist/observer/serve.js +7 -3
- package/dist/observer/tunnel.js +1 -1
- package/dist/observer-app.html +4 -4
- package/dist/routes/computer-use/bundle-parts.d.ts +9 -9
- package/dist/routes/computer-use/bundle-parts.js +15 -15
- package/dist/routes/computer-use/bundle.js +3 -3
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.js +14 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -4
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +4 -3
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -10
- package/dist/routes/computer-use/e2b-desktop/prepare.js +7 -7
- package/dist/routes/computer-use/e2b-desktop/start.js +9 -8
- package/dist/routes/computer-use/e2b-desktop/teardown.js +5 -4
- package/dist/routes/computer-use/external-comms.d.ts +1 -1
- package/dist/routes/computer-use/external-comms.js +1 -1
- package/dist/routes/computer-use/fanout-bundle.js +18 -18
- package/dist/routes/computer-use/fanout-records.js +10 -11
- package/dist/routes/computer-use/live-flush.d.ts +1 -1
- package/dist/routes/computer-use/live-flush.js +6 -6
- package/dist/routes/computer-use/live-phase.d.ts +4 -2
- package/dist/routes/computer-use/live-phase.js +6 -6
- package/dist/routes/computer-use/local-vm.js +1 -1
- package/dist/routes/computer-use/participant-desktop.d.ts +4 -4
- package/dist/routes/computer-use/participant-desktop.js +4 -4
- package/dist/routes/computer-use/participant-execution.d.ts +4 -4
- package/dist/routes/computer-use/participant-execution.js +9 -9
- package/dist/routes/computer-use/participant-model.d.ts +6 -0
- package/dist/routes/computer-use/participant-model.js +31 -13
- package/dist/routes/computer-use/participant-prompt.d.ts +11 -11
- package/dist/routes/computer-use/participant-prompt.js +6 -6
- package/dist/routes/computer-use/participant-runs.d.ts +7 -7
- package/dist/routes/computer-use/participant-runs.js +13 -13
- package/dist/routes/computer-use/plan.js +22 -22
- package/dist/routes/computer-use/preflight.js +21 -21
- package/dist/routes/computer-use/rerun-selection.js +1 -1
- package/dist/routes/computer-use/result.js +11 -11
- package/dist/routes/computer-use/route.d.ts +2 -1
- package/dist/routes/computer-use/route.js +15 -14
- package/dist/routes/computer-use/self-report.d.ts +7 -7
- package/dist/routes/computer-use/self-report.js +31 -31
- package/dist/routes/computer-use/setup.d.ts +1 -1
- package/dist/routes/computer-use/setup.js +17 -18
- package/dist/routes/computer-use/single-bundle.d.ts +7 -7
- package/dist/routes/computer-use/single-bundle.js +28 -30
- package/dist/routes/computer-use/subject-projection.d.ts +1 -1
- package/dist/routes/computer-use/subject-projection.js +6 -6
- package/dist/routes/computer-use/types.d.ts +40 -42
- package/dist/routes/computer-use/types.js +10 -10
- package/dist/routes/preview.d.ts +8 -2
- package/dist/routes/preview.js +8 -4
- package/dist/routes/scripted/bundle.d.ts +2 -2
- package/dist/routes/scripted/bundle.js +13 -12
- package/dist/routes/scripted/plan.d.ts +1 -1
- package/dist/routes/scripted/plan.js +9 -9
- package/dist/routes/scripted/result.js +5 -5
- package/dist/routes/scripted/route.js +5 -6
- package/dist/routes/scripted/scenario.js +2 -2
- package/dist/routes/scripted/setup.js +7 -7
- package/dist/routes/scripted/subject.js +1 -1
- package/dist/routes/scripted/surface-records.js +3 -3
- package/dist/routes/scripted/types.d.ts +3 -5
- package/dist/routes/scripted/types.js +1 -1
- package/dist/routes/shared-world/bundle-records.js +9 -8
- package/dist/routes/shared-world/bundle.d.ts +5 -5
- package/dist/routes/shared-world/bundle.js +40 -38
- package/dist/routes/shared-world/checkpoints.d.ts +1 -1
- package/dist/routes/shared-world/checkpoints.js +1 -1
- package/dist/routes/shared-world/comms.d.ts +5 -5
- package/dist/routes/shared-world/comms.js +14 -14
- package/dist/routes/shared-world/external-public.d.ts +4 -3
- package/dist/routes/shared-world/external-public.js +16 -12
- package/dist/routes/shared-world/handoff.d.ts +7 -6
- package/dist/routes/shared-world/handoff.js +65 -57
- package/dist/routes/shared-world/lobby-code.d.ts +2 -2
- package/dist/routes/shared-world/lobby-code.js +9 -9
- package/dist/routes/shared-world/participant-specs.d.ts +7 -6
- package/dist/routes/shared-world/participant-specs.js +31 -24
- package/dist/routes/shared-world/plan.js +7 -7
- package/dist/routes/shared-world/provenance.d.ts +2 -2
- package/dist/routes/shared-world/provenance.js +2 -2
- package/dist/routes/shared-world/provisioned.js +14 -13
- package/dist/routes/shared-world/result.js +20 -21
- package/dist/routes/shared-world/route.js +23 -22
- package/dist/routes/shared-world/setup.d.ts +3 -3
- package/dist/routes/shared-world/setup.js +4 -4
- package/dist/routes/shared-world/types.d.ts +30 -28
- package/dist/routes/shared-world/types.js +4 -4
- package/dist/routes/terminal/adapter.d.ts +3 -3
- package/dist/routes/terminal/adapter.js +5 -5
- package/dist/routes/terminal/bundle.d.ts +3 -3
- package/dist/routes/terminal/bundle.js +22 -21
- package/dist/routes/terminal/credentials.d.ts +4 -4
- package/dist/routes/terminal/credentials.js +7 -7
- package/dist/routes/terminal/dry-run.js +4 -4
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +3 -3
- package/dist/routes/terminal/ledger.js +14 -14
- package/dist/routes/terminal/live-finish.js +3 -3
- package/dist/routes/terminal/live-sandbox.js +12 -13
- package/dist/routes/terminal/persona.js +1 -1
- package/dist/routes/terminal/plan.js +11 -11
- package/dist/routes/terminal/recorder.js +2 -2
- package/dist/routes/terminal/result.js +8 -8
- package/dist/routes/terminal/route.js +6 -7
- package/dist/routes/terminal/sandbox.d.ts +1 -1
- package/dist/routes/terminal/sandbox.js +1 -1
- package/dist/routes/terminal/session.js +8 -7
- package/dist/routes/terminal/token-usage.d.ts +1 -1
- package/dist/routes/terminal/token-usage.js +7 -8
- package/dist/routes/terminal/trace.d.ts +2 -2
- package/dist/routes/terminal/trace.js +2 -2
- package/dist/routes/terminal/types.d.ts +26 -28
- package/dist/routes/terminal/types.js +3 -3
- package/dist/run/bundle-shape.js +3 -3
- package/dist/run/bundle.d.ts +46 -46
- package/dist/run/bundle.js +2 -1
- package/dist/run/cost-summary.js +3 -3
- package/dist/run/costs.js +7 -1
- package/dist/run/detail.d.ts +6 -6
- package/dist/run/detail.js +4 -4
- package/dist/run/dry-run-inputs.js +1 -1
- package/dist/run/dry-run.js +18 -18
- package/dist/run/judge.d.ts +19 -13
- package/dist/run/judge.js +18 -8
- package/dist/run/paths.d.ts +1 -1
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +11 -6
- package/dist/run/pricing.js +20 -13
- package/dist/run/projection.d.ts +14 -14
- package/dist/run/projection.js +15 -15
- package/dist/run/reclaim.js +2 -2
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-index.d.ts +8 -6
- package/dist/run/run-index.js +15 -16
- package/dist/run/run-not-found.d.ts +5 -0
- package/dist/run/run-not-found.js +15 -0
- package/dist/run/run.d.ts +5 -4
- package/dist/run/run.js +1 -1
- package/dist/run/sandbox-receipts.d.ts +2 -2
- package/dist/run/sandbox-receipts.js +3 -3
- package/dist/run/shared-world-evidence.d.ts +36 -35
- package/dist/run/shared-world-evidence.js +4 -4
- package/dist/run/shared-world-shape.d.ts +1 -1
- package/dist/run/shared-world-shape.js +6 -6
- package/dist/run/stats.d.ts +12 -6
- package/dist/run/stats.js +116 -58
- package/dist/run/status.d.ts +8 -29
- package/dist/run/status.js +5 -27
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +6 -6
- package/dist/run/study-provenance.d.ts +47 -0
- package/dist/run/study-provenance.js +63 -0
- package/dist/run/study-result.d.ts +16 -0
- package/dist/run/study-result.js +9 -0
- package/dist/run/text.d.ts +2 -0
- package/dist/run/text.js +4 -0
- package/dist/run-lab.d.ts +7 -7
- package/dist/run-lab.js +1 -3
- package/dist/study/convert.d.ts +33 -0
- package/dist/study/convert.js +432 -0
- package/dist/study/field-paths.d.ts +12 -0
- package/dist/study/field-paths.js +126 -0
- package/dist/study/files.d.ts +26 -0
- package/dist/study/files.js +43 -0
- package/dist/study/migrate.d.ts +48 -0
- package/dist/study/migrate.js +408 -0
- package/dist/study/owned-files.d.ts +38 -0
- package/dist/study/owned-files.js +182 -0
- package/dist/subject/clone.d.ts +1 -1
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +2 -2
- package/dist/subject/local-tree-archive.js +1 -1
- package/dist/subject/local-tree.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +1 -1
- package/dist/subject/runtime.js +8 -9
- package/dist/subject/serve.d.ts +1 -1
- package/dist/subject/serve.js +3 -3
- package/dist/subject/state.d.ts +1 -1
- package/dist/subject/steps.d.ts +5 -5
- package/dist/subject/steps.js +4 -4
- package/dist/substrates/command-failure.d.ts +3 -3
- package/dist/substrates/command-failure.js +3 -3
- package/dist/substrates/detached.d.ts +6 -6
- package/dist/substrates/detached.js +7 -7
- package/dist/substrates/e2b/cdp-probe.d.ts +9 -9
- package/dist/substrates/e2b/cdp-probe.js +14 -17
- package/dist/substrates/e2b/desktop-browser.d.ts +2 -2
- package/dist/substrates/e2b/desktop-browser.js +8 -8
- package/dist/substrates/e2b/desktop-cdp.d.ts +9 -9
- package/dist/substrates/e2b/desktop-cdp.js +8 -8
- package/dist/substrates/e2b/desktop-executor.d.ts +1 -1
- package/dist/substrates/e2b/desktop-executor.js +1 -1
- package/dist/substrates/e2b/desktop-geometry.d.ts +3 -3
- package/dist/substrates/e2b/desktop-geometry.js +7 -7
- package/dist/substrates/e2b/desktop-media.d.ts +1 -1
- package/dist/substrates/e2b/desktop-media.js +1 -1
- package/dist/substrates/e2b/desktop-screenshot-cleanup.d.ts +3 -3
- package/dist/substrates/e2b/desktop-screenshot-cleanup.js +3 -3
- package/dist/substrates/e2b/sandbox.d.ts +1 -1
- package/dist/substrates/e2b/sandbox.js +1 -1
- package/dist/substrates/e2b/sdk.d.ts +11 -11
- package/dist/substrates/e2b/sdk.js +6 -6
- package/dist/tui/actions.d.ts +1 -1
- package/dist/tui/actions.js +13 -13
- package/dist/tui/contract.d.ts +16 -16
- package/dist/tui/contract.js +10 -10
- package/dist/tui/launch.d.ts +4 -4
- package/dist/tui/launch.js +18 -19
- package/dist/tui/project.js +5 -5
- package/dist/tui-app.js +82 -82
- package/dist/verify/actor.d.ts +8 -8
- package/dist/verify/actor.js +36 -36
- package/dist/verify/artifacts.d.ts +2 -2
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/context-growth.d.ts +9 -0
- package/dist/verify/context-growth.js +62 -0
- package/dist/verify/costs.d.ts +6 -6
- package/dist/verify/costs.js +8 -8
- package/dist/verify/shared-world-concurrent.d.ts +2 -2
- package/dist/verify/shared-world-concurrent.js +79 -76
- package/dist/verify/shared-world.d.ts +2 -2
- package/dist/verify/shared-world.js +16 -16
- package/dist/verify/subject.d.ts +4 -4
- package/dist/verify/subject.js +18 -18
- package/dist/verify/verify.js +92 -43
- package/docs/README.md +25 -32
- package/docs/architecture/actor-contract.md +56 -87
- package/docs/architecture/desktop-sessions.md +7 -7
- package/docs/architecture/external-public-shared-world.md +61 -59
- package/docs/architecture/github-feedback-loop.md +1 -4
- package/docs/architecture/guest-desktop.md +2 -2
- package/docs/architecture/observer.md +34 -34
- package/docs/architecture/restricted-codex-analysis.md +34 -28
- package/docs/architecture/serve.md +34 -37
- package/docs/architecture/state-driven-executor.md +55 -58
- package/docs/architecture/task-protocol-support.md +5 -5
- package/docs/architecture/terminal-product-route.md +67 -107
- package/docs/contracts/README.md +24 -0
- package/docs/contracts/adapter-admission.md +3 -3
- package/docs/contracts/adapter-fixtures.md +2 -5
- package/docs/contracts/core.md +1 -3
- package/docs/contracts/errors.md +62 -0
- package/docs/contracts/feedback.md +8 -9
- package/docs/contracts/policy.md +7 -12
- package/docs/contracts/run-bundle.md +45 -44
- package/docs/contracts/schemas.md +421 -362
- package/docs/contracts/study-analysis.md +3 -3
- package/docs/contracts/study-costs.md +11 -7
- package/docs/decisions/0001-run-bundle-is-the-source-of-truth.md +1 -1
- package/docs/decisions/0002-observer-is-one-self-contained-file.md +2 -2
- package/docs/decisions/0003-contained-paths-and-cleanup-authority.md +3 -3
- package/docs/principles/actor-fidelity.md +4 -4
- package/docs/principles/engineering.md +3 -3
- package/docs/principles/invariants-and-defaults.md +38 -38
- package/docs/principles/self-driving-harness.md +1 -5
- package/docs/principles/three-roles.md +1 -1
- package/docs/product/automatic-analysis.md +7 -7
- package/examples/participant/README.md +5 -5
- package/examples/participant/run.mjs +11 -10
- package/examples/scorer/README.md +3 -3
- package/examples/scorer/run.mjs +11 -12
- package/package.json +16 -17
- package/skills/humanish/SKILL.md +60 -58
- package/skills/humanish/agents/openai.yaml +1 -1
- package/AGENTS.md +0 -99
- package/CONTRIBUTING.md +0 -148
- package/dist/actors/codex/qualified-versions.d.ts +0 -72
- package/dist/actors/codex/qualified-versions.js +0 -132
- package/dist/cli/commands/lab.d.ts +0 -3
- package/dist/cli/commands/lab.js +0 -199
- package/dist/cli/renamed-options.d.ts +0 -11
- package/dist/cli/renamed-options.js +0 -18
- package/dist/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/docs/architecture/comms-inbox.md +0 -122
- package/docs/architecture/desktop-recording.md +0 -80
- package/docs/architecture/local-browser-runtime.md +0 -178
- package/docs/architecture/observer-review.md +0 -144
- package/docs/architecture/participant-media.md +0 -90
- package/docs/architecture/project-layout.md +0 -62
- package/docs/architecture/real-email-receiving.md +0 -136
- package/docs/assets/humanish-drawdb-hero.png +0 -0
- package/docs/assets/humanish-observer-hero.png +0 -0
- package/docs/goals/current.md +0 -207
- package/docs/product/lobby-trivia-3player-external-public.md +0 -77
- package/docs/product/open-source-install-experience.md +0 -240
- package/docs/ramp/README.md +0 -295
- package/docs/release/open-source-readiness.md +0 -222
- package/docs/release/public-readiness-standard.md +0 -210
- package/docs/roadmap/world-class-open-source-v0.md +0 -311
|
@@ -13,9 +13,10 @@ export interface ExternalPublicPlaneOutcome {
|
|
|
13
13
|
/**
|
|
14
14
|
* The operator-declared origin (from subject.appUrl), recorded for evidence and reference only. The
|
|
15
15
|
* operator-ownership claim rests on the subject.publicTarget.authorized attestation + this declared
|
|
16
|
-
* appUrl; digest equality plays no part
|
|
17
|
-
* lobby-trivia.example.test 307-redirects) makes the
|
|
18
|
-
* is expected and must not fail the run. Persisted digest-only (never the raw
|
|
16
|
+
* appUrl; digest equality plays no part: a normal cross-origin redirect (apex->www, http->https;
|
|
17
|
+
* lobby-trivia.example.test 307-redirects) makes the participants' observed origin differ from the
|
|
18
|
+
* declared one, which is expected and must not fail the run. Persisted digest-only (never the raw
|
|
19
|
+
* origin).
|
|
19
20
|
*/
|
|
20
21
|
export declare function declaredOriginDigestOf(publicAppUrl: string): string | undefined;
|
|
21
22
|
export declare function runExternalPublicPlane(ctx: PlaneContext, live: LiveParticipants, inbox: ExternalCommsWiring | undefined): Promise<ExternalPublicPlaneOutcome>;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
// External-public plane
|
|
2
|
-
//
|
|
3
|
-
// the shared session through the real UI. A host-first barrier extracts the /lobby/CODE
|
|
4
|
-
//
|
|
5
|
-
// closed without opening if the host never yields a code within the handoff
|
|
1
|
+
// External-public plane: no subject sandbox, no getHost, no prober. The shared plane is the
|
|
2
|
+
// operator-declared public deployment (publicAppUrl); each participant opens it directly and
|
|
3
|
+
// reaches the shared session through the real UI. A host-first barrier extracts the /lobby/CODE
|
|
4
|
+
// from the host's CDP-observed URL (onObservedUrl) and threads it into the follower missions; a
|
|
5
|
+
// follower fails closed without opening if the host never yields a code within the handoff
|
|
6
|
+
// deadline.
|
|
6
7
|
import { liveObserverResult } from "../../observer/live.js";
|
|
7
8
|
import { redactText, toErrorMessage } from "../../evidence/redaction.js";
|
|
8
9
|
import { mapWithConcurrency } from "../../run/concurrency.js";
|
|
@@ -15,9 +16,10 @@ import { participantRunDeps, startParticipantFlush } from "./participant-specs.j
|
|
|
15
16
|
/**
|
|
16
17
|
* The operator-declared origin (from subject.appUrl), recorded for evidence and reference only. The
|
|
17
18
|
* operator-ownership claim rests on the subject.publicTarget.authorized attestation + this declared
|
|
18
|
-
* appUrl; digest equality plays no part
|
|
19
|
-
* lobby-trivia.example.test 307-redirects) makes the
|
|
20
|
-
* is expected and must not fail the run. Persisted digest-only (never the raw
|
|
19
|
+
* appUrl; digest equality plays no part: a normal cross-origin redirect (apex->www, http->https;
|
|
20
|
+
* lobby-trivia.example.test 307-redirects) makes the participants' observed origin differ from the
|
|
21
|
+
* declared one, which is expected and must not fail the run. Persisted digest-only (never the raw
|
|
22
|
+
* origin).
|
|
21
23
|
*/
|
|
22
24
|
export function declaredOriginDigestOf(publicAppUrl) {
|
|
23
25
|
return publicAppUrl ? hostOriginDigest(publicAppUrl) : undefined;
|
|
@@ -35,8 +37,9 @@ export async function runExternalPublicPlane(ctx, live, inbox) {
|
|
|
35
37
|
timeoutMs: ctx.timeoutMs,
|
|
36
38
|
deadlineMs: seams.handoffDeadlineMs,
|
|
37
39
|
scrubKnownValues: ctx.scrubKnownValues,
|
|
38
|
-
// The per-
|
|
39
|
-
// so the barrier's handoff + convergence proof are testable without a live vision
|
|
40
|
+
// The per-participant vision lobby-code reader (default: the real single-frame OpenAI read).
|
|
41
|
+
// Injectable so the barrier's handoff + convergence proof are testable without a live vision
|
|
42
|
+
// call.
|
|
40
43
|
readLobbyCode: seams.readLobbyCodeFromFrame ?? readLobbyCodeFromFrame,
|
|
41
44
|
openaiApiKey: ctx.openaiApiKey,
|
|
42
45
|
});
|
|
@@ -62,8 +65,9 @@ export async function runExternalPublicPlane(ctx, live, inbox) {
|
|
|
62
65
|
subject: { source: "app-url", envNames: [], state: { provenance: "external-public" } },
|
|
63
66
|
seedDigest: ctx.seedDigest,
|
|
64
67
|
planeClass: "external-public",
|
|
65
|
-
// Pre-fan-out snapshot: no
|
|
66
|
-
// is not available; surface the declared origin for the live Observer's
|
|
68
|
+
// Pre-fan-out snapshot: no participant has observed an origin yet, so the observed
|
|
69
|
+
// publicOriginDigest is not available; surface the declared origin for the live Observer's
|
|
70
|
+
// reference.
|
|
67
71
|
...(declaredOriginDigest === undefined ? {} : { declaredOriginDigest }),
|
|
68
72
|
};
|
|
69
73
|
const inProgressBundle = buildConcurrentSharedWorldBundle({
|
|
@@ -9,10 +9,11 @@ export interface HandoffParticipantDeps {
|
|
|
9
9
|
now: () => number;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* The handoff latch, its deadline and what each
|
|
13
|
-
* are runtime-only and land in persisted metadata only as digests (origin + convergence). (The
|
|
14
|
-
* is a shareable game code, not a secret, and it still renders in the host's screenshots,
|
|
15
|
-
* full-fidelity unless redactScreenshots is set
|
|
12
|
+
* The handoff latch, its deadline and what each participant observed. The latched code and observed
|
|
13
|
+
* URLs are runtime-only and land in persisted metadata only as digests (origin + convergence). (The
|
|
14
|
+
* code is a shareable game code, not a secret, and it still renders in the host's screenshots,
|
|
15
|
+
* which are full-fidelity unless redactScreenshots is set. The digesting is about narration/URL
|
|
16
|
+
* metadata.)
|
|
16
17
|
*/
|
|
17
18
|
export declare class LobbyHandoff {
|
|
18
19
|
readonly observedFinalUrls: (string | undefined)[];
|
|
@@ -20,7 +21,7 @@ export declare class LobbyHandoff {
|
|
|
20
21
|
latchedLobbyCode: string | undefined;
|
|
21
22
|
/** A follower gave up because the deadline passed. */
|
|
22
23
|
timedOut: boolean;
|
|
23
|
-
/** Why the host
|
|
24
|
+
/** Why the host ended without producing a lobby code. */
|
|
24
25
|
hostFailure: string | undefined;
|
|
25
26
|
readonly deadlineMs: number;
|
|
26
27
|
private readonly lobbyCodeLatch;
|
|
@@ -52,7 +53,7 @@ export declare class LobbyHandoff {
|
|
|
52
53
|
waitForHostCode(): Promise<string>;
|
|
53
54
|
/** Releases waiting followers to fail closed when the host ended without a code. */
|
|
54
55
|
releaseFollowersIfUnlatched(outcome: ParticipantRunOutcome | undefined): void;
|
|
55
|
-
/** The digest-only convergence proofs over what the
|
|
56
|
+
/** The digest-only convergence proofs over what the participants observed. */
|
|
56
57
|
convergence(declaredOriginDigest: string | undefined): {
|
|
57
58
|
publicOriginDigest: string | undefined;
|
|
58
59
|
lobbyConvergenceDigest: string | undefined;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// The external-public plane's host-first handoff. The host
|
|
1
|
+
// The external-public plane's host-first handoff. The host opens a lobby; each follower waits
|
|
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
|
-
// Temporary shim
|
|
5
|
+
// Temporary shim: this CDP URL-relay handoff reads the host's /lobby/CODE off its
|
|
6
6
|
// own browser and threads it into the follower missions.
|
|
7
|
-
// It is to be augmented/replaced by the actor message bus (fake SMS/email invite)
|
|
7
|
+
// It is to be augmented/replaced by the actor message bus (fake SMS/email invite): the
|
|
8
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";
|
|
@@ -15,23 +15,24 @@ 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
17
|
import { makeBlockedFollowerOutcome, withLobbyCodeMission, } from "./participant-specs.js";
|
|
18
|
-
// The floor for the host-first handoff barrier deadline (ms). The host
|
|
18
|
+
// The floor for the host-first handoff barrier deadline (ms). The host 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 scales with the per-
|
|
21
|
-
// 2 min is too tight for a real create-a-lobby flow on a mobile-layout
|
|
22
|
-
//
|
|
23
|
-
// gave up. So use max(floor, 40% of the budget), capped at the budget. The latch
|
|
24
|
-
// instant the host actually reaches /lobby, so a generous ceiling only affects the
|
|
20
|
+
// opens. The effective deadline scales with the per-participant run budget (execution.timeoutMs): a
|
|
21
|
+
// fixed 2 min is too tight for a real create-a-lobby flow on a mobile-layout participant once you
|
|
22
|
+
// subtract the participant's own desktop provisioning: the host reaches /lobby/CODE, but after the
|
|
23
|
+
// followers already gave up. So use max(floor, 40% of the budget), capped at the budget. The latch
|
|
24
|
+
// resolves the instant the host actually reaches /lobby, so a generous ceiling only affects the
|
|
25
|
+
// fail-closed case.
|
|
25
26
|
const DEFAULT_HANDOFF_DEADLINE_MS = 120_000;
|
|
26
27
|
const HANDOFF_DEADLINE_BUDGET_FRACTION = 0.4;
|
|
27
|
-
// Per-
|
|
28
|
-
// handoff code, and by each follower to independently observe its own code for the
|
|
29
|
-
// at most this many single-frame reads before the
|
|
30
|
-
// reader stops the instant it has what it needs, so in practice only
|
|
31
|
-
// /lobby within a few turns). NOTE: these reads are
|
|
32
|
-
// only) and are left out of execution.caps.maxUsd,
|
|
33
|
-
// (each read is one cheap single-frame OCR call). If
|
|
34
|
-
// budget, fold the estimate in.
|
|
28
|
+
// Per-participant runaway backstop for the vision-off-frame lobby-code read (used by the host to
|
|
29
|
+
// latch the handoff code, and by each follower to independently observe its own code for the
|
|
30
|
+
// convergence proof): at most this many single-frame reads before the participant is assumed to be
|
|
31
|
+
// somewhere without a code. Each reader stops the instant it has what it needs, so in practice only
|
|
32
|
+
// a handful fire (a participant reaches its /lobby within a few turns). NOTE: these reads are
|
|
33
|
+
// out-of-band OpenAI calls (external-public route only) and are left out of execution.caps.maxUsd,
|
|
34
|
+
// so this hard cap is what bounds their spend (each read is one cheap single-frame OCR call). If
|
|
35
|
+
// this route ever runs under a strict budget, fold the estimate in.
|
|
35
36
|
const MAX_LOBBY_CODE_VISION_READS = 30;
|
|
36
37
|
// Idle/no-progress backstop for the host participant specifically (default is 6/8). The host legitimately sits
|
|
37
38
|
// on an unchanging waiting-room screen while followers provision and join; it must not give up first.
|
|
@@ -66,21 +67,23 @@ class HandoffTimeoutError extends Error {
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
/**
|
|
69
|
-
* The handoff latch, its deadline and what each
|
|
70
|
-
* are runtime-only and land in persisted metadata only as digests (origin + convergence). (The
|
|
71
|
-
* is a shareable game code, not a secret, and it still renders in the host's screenshots,
|
|
72
|
-
* full-fidelity unless redactScreenshots is set
|
|
70
|
+
* The handoff latch, its deadline and what each participant observed. The latched code and observed
|
|
71
|
+
* URLs are runtime-only and land in persisted metadata only as digests (origin + convergence). (The
|
|
72
|
+
* code is a shareable game code, not a secret, and it still renders in the host's screenshots,
|
|
73
|
+
* which are full-fidelity unless redactScreenshots is set. The digesting is about narration/URL
|
|
74
|
+
* metadata.)
|
|
73
75
|
*/
|
|
74
76
|
export class LobbyHandoff {
|
|
75
77
|
// Per-participant runtime-only observed state (never persisted raw): the last observed URL and the last
|
|
76
|
-
// observed /lobby/CODE per
|
|
77
|
-
// routeHostDigest (no code leaks); the codes drive the cross-
|
|
78
|
+
// observed /lobby/CODE per participant, fed by onObservedUrl. The URL is digested to its origin
|
|
79
|
+
// for each participant's routeHostDigest (no code leaks); the codes drive the cross-participant
|
|
80
|
+
// lobby-convergence digest.
|
|
78
81
|
observedFinalUrls;
|
|
79
82
|
observedLobbyCodes;
|
|
80
83
|
latchedLobbyCode;
|
|
81
84
|
/** A follower gave up because the deadline passed. */
|
|
82
85
|
timedOut = false;
|
|
83
|
-
/** Why the host
|
|
86
|
+
/** Why the host ended without producing a lobby code. */
|
|
84
87
|
hostFailure;
|
|
85
88
|
deadlineMs;
|
|
86
89
|
lobbyCodeLatch = deferred();
|
|
@@ -133,11 +136,12 @@ export class LobbyHandoff {
|
|
|
133
136
|
this.stopDeadline();
|
|
134
137
|
this.lobbyCodeLatch.resolve(code);
|
|
135
138
|
}
|
|
136
|
-
// Build an onScreenshot handler that vision-reads the lobby code off this
|
|
137
|
-
// CDP-independent observation). `done()` short-circuits once this
|
|
138
|
-
// once latched; a follower once it has recorded its own observed code), `onCode`
|
|
139
|
-
// result. One read in flight at a time, bounded by
|
|
140
|
-
// reaches a lobby can't rack up unbounded
|
|
139
|
+
// Build an onScreenshot handler that vision-reads the lobby code off this participant's own frame
|
|
140
|
+
// (the CDP-independent observation). `done()` short-circuits once this participant has what it
|
|
141
|
+
// needs (the host once latched; a follower once it has recorded its own observed code), `onCode`
|
|
142
|
+
// records/latches the result. One read in flight at a time, bounded by
|
|
143
|
+
// MAX_LOBBY_CODE_VISION_READS so a participant that never reaches a lobby can't rack up unbounded
|
|
144
|
+
// calls (fire-and-forget; the loop never awaits it).
|
|
141
145
|
makeLobbyCodeVisionReader(done, onCode) {
|
|
142
146
|
let inFlight = false;
|
|
143
147
|
let reads = 0;
|
|
@@ -184,32 +188,34 @@ export class LobbyHandoff {
|
|
|
184
188
|
this.lobbyCodeLatch.reject(new Error(this.hostFailure));
|
|
185
189
|
}
|
|
186
190
|
}
|
|
187
|
-
/** The digest-only convergence proofs over what the
|
|
191
|
+
/** The digest-only convergence proofs over what the participants observed. */
|
|
188
192
|
convergence(declaredOriginDigest) {
|
|
189
|
-
// Observed-origin convergence proof
|
|
190
|
-
// observed. Digest each observing
|
|
191
|
-
// the convergence proof and becomes plane.publicOriginDigest. A normal
|
|
192
|
-
// cross-origin redirect (declared apex -> observed www) is therefore tolerated: the
|
|
193
|
-
// converge on one observed origin. Leave it undefined (verify fails closed)
|
|
194
|
-
// not converge on a single observed origin (or none observed one).
|
|
193
|
+
// Observed-origin convergence proof: the convergence claim is about what the participants
|
|
194
|
+
// observed. Digest each observing participant's origin and require one shared origin; that
|
|
195
|
+
// agreement is the convergence proof and becomes plane.publicOriginDigest. A normal
|
|
196
|
+
// cross-origin redirect (declared apex -> observed www) is therefore tolerated: the
|
|
197
|
+
// participants still converge on one observed origin. Leave it undefined (verify fails closed)
|
|
198
|
+
// only if the participants did not converge on a single observed origin (or none observed one).
|
|
195
199
|
const observedOriginDigests = this.observedFinalUrls
|
|
196
200
|
.filter((url) => typeof url === "string" && url.length > 0)
|
|
197
201
|
.map((url) => hostOriginDigest(url));
|
|
198
202
|
const distinctObservedOrigins = new Set(observedOriginDigests);
|
|
199
203
|
const publicOriginDigest = distinctObservedOrigins.size === 1
|
|
200
204
|
? [...distinctObservedOrigins][0]
|
|
201
|
-
: // Nothing observed (e.g. a handoff-timeout run where no
|
|
202
|
-
// declared origin so a failed run's bundle stays structurally valid (every
|
|
203
|
-
// digests to the declared origin too). The run still fails
|
|
204
|
-
// (`HANDOFF_TIMEOUT`, no lobby convergence, no
|
|
205
|
-
//
|
|
205
|
+
: // Nothing observed (e.g. a handoff-timeout run where no participant ever navigated): fall
|
|
206
|
+
// back to the declared origin so a failed run's bundle stays structurally valid (every
|
|
207
|
+
// participant's route then digests to the declared origin too). The run still fails
|
|
208
|
+
// closed for its own reason (`HANDOFF_TIMEOUT`, no lobby convergence, no
|
|
209
|
+
// overlap-on-pass). Real divergence (≥2 distinct observed origins) leaves it undefined so
|
|
210
|
+
// verify fails closed on the non-convergence.
|
|
206
211
|
distinctObservedOrigins.size === 0
|
|
207
212
|
? declaredOriginDigest
|
|
208
213
|
: undefined;
|
|
209
|
-
// Lobby-convergence proof: a digest of the shared /lobby/CODE path iff every
|
|
210
|
-
// same code (a follower stuck on "/" yields no code, so no false convergence).
|
|
211
|
-
// observedLobbyCodes may be a sparse array (a
|
|
212
|
-
// Array.prototype.every skips holes, so count the defined codes
|
|
214
|
+
// Lobby-convergence proof: a digest of the shared /lobby/CODE path iff every participant
|
|
215
|
+
// converged on the same code (a follower stuck on "/" yields no code, so no false convergence).
|
|
216
|
+
// Digest-only. observedLobbyCodes may be a sparse array (a participant that never observed a
|
|
217
|
+
// code leaves a hole), and Array.prototype.every skips holes, so count the defined codes
|
|
218
|
+
// explicitly instead of every().
|
|
213
219
|
const definedCodes = this.observedLobbyCodes.filter((code) => code !== undefined);
|
|
214
220
|
const distinctCodes = new Set(definedCodes);
|
|
215
221
|
const lobbyConvergenceDigest = distinctCodes.size === 1 && definedCodes.length === this.observedLobbyCodes.length
|
|
@@ -218,7 +224,7 @@ export class LobbyHandoff {
|
|
|
218
224
|
return { publicOriginDigest, lobbyConvergenceDigest };
|
|
219
225
|
}
|
|
220
226
|
}
|
|
221
|
-
// Adopter-hosted inbox
|
|
227
|
+
// Adopter-hosted inbox: the persona is told its address and inbox URL on this plane.
|
|
222
228
|
function withParticipantInbox(spec, inbox) {
|
|
223
229
|
return inbox && participantHasInboxRecipient(inbox.email, spec.planned.id)
|
|
224
230
|
? withInboxMission(spec, inbox.inboxUrl, inboxRecipientFor(inbox.email, spec.planned.id)?.address)
|
|
@@ -235,11 +241,11 @@ function withParticipantInbox(spec, inbox) {
|
|
|
235
241
|
// (host + up to concurrency-1 followers), preserving the spend cap.
|
|
236
242
|
export async function runHost(handoff, deps, spec, participantIndex) {
|
|
237
243
|
const onObservedUrl = handoff.makeObservedUrl(participantIndex, true);
|
|
238
|
-
// CDP-
|
|
244
|
+
// CDP-independent handoff paths (the E2B-desktop CDP url-read the onObservedUrl path relies on is
|
|
239
245
|
// unreliable in practice). Two backups, both resolving the same latch; whichever sees the code first
|
|
240
246
|
// wins, all digest-only:
|
|
241
247
|
// (1) onMessage: scan the host's own narration if it happens to state the lobby URL; and
|
|
242
|
-
// (2) onScreenshot
|
|
248
|
+
// (2) onScreenshot: vision-read the code straight off the host's waiting-room frame. This is the
|
|
243
249
|
// robust one: the code is rendered on screen even when CDP fails and when the host never
|
|
244
250
|
// narrates it, and the host is never asked to announce anything, so it keeps
|
|
245
251
|
// running (create -> wait for players -> Start -> play) instead of ending on a stray message.
|
|
@@ -256,7 +262,8 @@ export async function runHost(handoff, deps, spec, participantIndex) {
|
|
|
256
262
|
// followers provision their own desktops and walk the Join flow (easily 15-30 turns of an
|
|
257
263
|
// unchanging "waiting for players" screen). At the default idle backstop (6) the host would give up
|
|
258
264
|
// before anyone arrives, orphaning the lobby (exactly the earlier failure). Raise the host's idle /
|
|
259
|
-
// no-progress tolerance so it waits patiently; the per-
|
|
265
|
+
// no-progress tolerance so it waits patiently; the per-participant timeout still bounds a truly
|
|
266
|
+
// stuck host.
|
|
260
267
|
const hostSpec = {
|
|
261
268
|
...withParticipantInbox(spec, deps.inbox),
|
|
262
269
|
backstop: {
|
|
@@ -310,9 +317,10 @@ export async function runFollower(handoff, deps, spec, participantIndex) {
|
|
|
310
317
|
route: deps.publicAppUrl,
|
|
311
318
|
};
|
|
312
319
|
}
|
|
313
|
-
// Followers also idle-wait
|
|
320
|
+
// Followers also idle-wait: in the waiting room until the host starts, and between rounds. Raise
|
|
314
321
|
// their idle backstop too (less than the host's: they wait less), so a follower that joins ahead of
|
|
315
|
-
// the other does not give up before the game begins. Per-
|
|
322
|
+
// the other does not give up before the game begins. Per-participant timeout still bounds a stuck
|
|
323
|
+
// follower.
|
|
316
324
|
const followerSpec = {
|
|
317
325
|
...withLobbyCodeMission(withParticipantInbox(spec, deps.inbox), code),
|
|
318
326
|
backstop: {
|
|
@@ -321,12 +329,12 @@ export async function runFollower(handoff, deps, spec, participantIndex) {
|
|
|
321
329
|
},
|
|
322
330
|
};
|
|
323
331
|
// Independently observe this follower's own lobby code by vision-reading its waiting-room frame,
|
|
324
|
-
// and record it for the cross-
|
|
325
|
-
// host's code). It fills this
|
|
326
|
-
// reliable signal instead of the flaky CDP url-read, so lobbyConvergenceDigest can prove all
|
|
327
|
-
// reached the same /lobby/CODE. If a follower somehow joined another lobby, it reads
|
|
328
|
-
// code and convergence correctly fails (no false proof); if it never reads one, the
|
|
329
|
-
// hole and convergence is
|
|
332
|
+
// and record it for the cross-participant convergence proof. This latches nothing (followers gate
|
|
333
|
+
// on the host's code). It fills this participant's observedLobbyCodes slot from a
|
|
334
|
+
// reliable signal instead of the flaky CDP url-read, so lobbyConvergenceDigest can prove all
|
|
335
|
+
// participants reached the same /lobby/CODE. If a follower somehow joined another lobby, it reads
|
|
336
|
+
// a different code and convergence correctly fails (no false proof); if it never reads one, the
|
|
337
|
+
// participant stays a hole and convergence is recorded as "not observed" for that participant.
|
|
330
338
|
const onScreenshot = handoff.makeLobbyCodeVisionReader(() => handoff.observedLobbyCodes[participantIndex] !== undefined, (observed) => {
|
|
331
339
|
handoff.observedLobbyCodes[participantIndex] = observed;
|
|
332
340
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/** Extract the shared-session code from a (runtime-only) observed URL, or undefined. Exported for the
|
|
2
|
-
* handoff regex table test
|
|
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
8
|
/** Parse a vision reply into a lobby code. Precision-first: accept only when the whole reply is the
|
|
9
|
-
* six-character code, or when it echoes an explicit /lobby/CODE
|
|
9
|
+
* six-character code, or when it echoes an explicit /lobby/CODE; never a bare 6-letter token buried in
|
|
10
10
|
* prose (e.g. "I see a home `SCREEN`"), because a wrong latch fails the entire run, whereas a miss just
|
|
11
11
|
* retries on the next frame while the host keeps waiting. `NONE` (the instructed "no code" reply) is
|
|
12
12
|
* rejected. Pure. */
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
// Reads a lobby code (the /lobby/CODE path segment) from a URL, from a
|
|
2
|
-
// a vision model call, from a
|
|
3
|
-
// host's lobby to the followers.
|
|
1
|
+
// Reads a lobby code (the /lobby/CODE path segment) from a URL, from a participant's narration or,
|
|
2
|
+
// through a vision model call, from a participant's screenshot. The external-public plane uses it
|
|
3
|
+
// to hand the host's lobby to the followers.
|
|
4
4
|
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
|
-
* the [A-Z2-9] class; a locale prefix (/en/lobby/…) and a query/hash suffix are tolerated.
|
|
7
|
+
* the [A-Z2-9] class; a locale prefix (/en/lobby/…) and a query/hash suffix are tolerated. Runtime-only
|
|
8
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
11
|
/** Extract the shared-session code from a (runtime-only) observed URL, or undefined. Exported for the
|
|
12
|
-
* handoff regex table test
|
|
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")
|
|
15
15
|
return undefined;
|
|
@@ -19,8 +19,8 @@ export function extractLobbyCode(url) {
|
|
|
19
19
|
/**
|
|
20
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
|
-
* newline) rather than end-of-string or
|
|
23
|
-
* negative-lookahead boundary (exactly 6 code chars). This is the CDP-
|
|
22
|
+
* newline) rather than end-of-string or /?#, so the strict LOBBY_CODE_PATTERN would miss it. Uses a
|
|
23
|
+
* negative-lookahead boundary (exactly 6 code chars). This is the CDP-independent handoff path: the
|
|
24
24
|
* host reads the code on screen and states it, and this reads it from the model's own text. Pure;
|
|
25
25
|
* input is runtime-only; only the code is used (as a digest).
|
|
26
26
|
*/
|
|
@@ -68,7 +68,7 @@ export function extractResponsesOutputText(parsed) {
|
|
|
68
68
|
return parts.length > 0 ? parts.join("\n") : undefined;
|
|
69
69
|
}
|
|
70
70
|
/** Parse a vision reply into a lobby code. Precision-first: accept only when the whole reply is the
|
|
71
|
-
* six-character code, or when it echoes an explicit /lobby/CODE
|
|
71
|
+
* six-character code, or when it echoes an explicit /lobby/CODE; never a bare 6-letter token buried in
|
|
72
72
|
* prose (e.g. "I see a home `SCREEN`"), because a wrong latch fails the entire run, whereas a miss just
|
|
73
73
|
* retries on the next frame while the host keeps waiting. `NONE` (the instructed "no code" reply) is
|
|
74
74
|
* rejected. Pure. */
|
|
@@ -89,7 +89,7 @@ const LOBBY_CODE_VISION_PROMPT = "This is a screenshot of a the example multipla
|
|
|
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
91
|
// A single-frame OCR-style read. gpt-5.5 (the computer-use default) is used deliberately: it reliably reads the
|
|
92
|
-
// 6-char code off a dense
|
|
92
|
+
// 6-char code off a dense mobile-viewport waiting room. A smaller/cheaper model (gpt-4.1-mini) was
|
|
93
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
95
|
// as the actor; the same full-fidelity frame is already sent to this API by the computer-use provider, so this
|
|
@@ -4,8 +4,8 @@ import type { RunBundle } from "../../run/bundle.js";
|
|
|
4
4
|
import type { CuaParticipantDeps, DesktopParticipantRun, ParticipantRunOutcome } from "../computer-use/types.js";
|
|
5
5
|
import type { LiveParticipants, PlaneContext } from "./types.js";
|
|
6
6
|
export declare function defaultSessionTimeoutMs(plan: SharedWorldPlan): number;
|
|
7
|
-
/** Resolve an actor's
|
|
8
|
-
* relative path, validated at parse against serve.url). */
|
|
7
|
+
/** Resolve an actor's participant URL against the harness-minted getHost base (entry is a
|
|
8
|
+
* same-origin 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
11
|
/** Thread the host-yielded lobby code into a follower's mission at runtime (external-public route).
|
|
@@ -19,9 +19,10 @@ export declare function makeBlockedFollowerOutcome(spec: DesktopParticipantRun,
|
|
|
19
19
|
/** The computer-use runner deps every participant shares, on either plane. */
|
|
20
20
|
export type ParticipantRunDeps = Omit<CuaParticipantDeps, "signalProvisioned" | "appUrl" | "onObservedUrl">;
|
|
21
21
|
/**
|
|
22
|
-
* A live run publishes an in-progress bundle before its
|
|
23
|
-
* is attached, and the
|
|
24
|
-
* run killed mid-way leaves that evidence on disk. The flush starts with the
|
|
22
|
+
* A live run publishes an in-progress bundle before its participants start, whether or not an
|
|
23
|
+
* Observer is attached, and the participants' live traces rewrite it as they go, as on the
|
|
24
|
+
* computer-use route. A run killed mid-way leaves that evidence on disk. The flush starts with the
|
|
25
|
+
* first snapshot.
|
|
25
26
|
*/
|
|
26
27
|
export declare function startParticipantFlush(ctx: PlaneContext, live: LiveParticipants, bundle: RunBundle): void;
|
|
27
28
|
/**
|
|
@@ -34,7 +35,7 @@ export declare function startParticipantFlush(ctx: PlaneContext, live: LiveParti
|
|
|
34
35
|
export declare function participantRunDeps(ctx: PlaneContext, live: LiveParticipants, scrubKnownValues: (text: string) => string): ParticipantRunDeps;
|
|
35
36
|
/**
|
|
36
37
|
* Each participant's actor spec, with committed personas compiled in so each prompt carries real
|
|
37
|
-
* behavioral directives
|
|
38
|
+
* behavioral directives. Evidence copies of the assignment, instructions and persona are
|
|
38
39
|
* scrubbed of the run's known secret values.
|
|
39
40
|
*/
|
|
40
41
|
export declare function buildParticipantSpecs(participants: readonly SharedWorldParticipant[], cwd: string, scrubKnownValues: (text: string) => string): Promise<DesktopParticipantRun[]>;
|
|
@@ -12,13 +12,14 @@ import { participantAssignment } from "../../lab/participant-assignment.js";
|
|
|
12
12
|
import { redactText } from "../../evidence/redaction.js";
|
|
13
13
|
import { MAX_SANDBOX_MS, SANDBOX_TIMEOUT_BUFFER_MS, SUBJECT_PROVISION_BUDGET_MS, } from "../../substrates/e2b/lifetime.js";
|
|
14
14
|
import { DEFAULT_STATE_STEP_TIMEOUT_MS } from "../../subject/state.js";
|
|
15
|
-
// The default per-
|
|
16
|
-
// constraint is the subject sandbox (it must outlive every
|
|
17
|
-
// seeding + teardown buffer, and E2B refuses a sandbox over one hour), so the
|
|
18
|
-
// each
|
|
19
|
-
// seed-heavy
|
|
20
|
-
// and default to 30 minutes (
|
|
21
|
-
// explicit execution.timeoutMs is never adjusted. The handoff
|
|
15
|
+
// The default per-participant session budget is derived from the route. On a provisioned route the
|
|
16
|
+
// binding constraint is the subject sandbox (it must outlive every participant: timeoutMs +
|
|
17
|
+
// provisioning + seeding + teardown buffer, and E2B refuses a sandbox over one hour), so the
|
|
18
|
+
// derivation hands each participant the most that cap allows, capped at 15 minutes, floored at the
|
|
19
|
+
// historical 300s so a seed-heavy study never gets less room than it always had. App-url
|
|
20
|
+
// participants have no subject sandbox and default to 30 minutes (participant sandbox: 30m + 10m
|
|
21
|
+
// buffer stays well under the hour). An explicit execution.timeoutMs is never adjusted. The handoff
|
|
22
|
+
// latch scales off this (40%).
|
|
22
23
|
const MAX_DERIVED_SESSION_MS = 15 * 60_000;
|
|
23
24
|
const MIN_DERIVED_SESSION_MS = 300_000;
|
|
24
25
|
const DEFAULT_APP_URL_SESSION_MS = 30 * 60_000;
|
|
@@ -29,9 +30,10 @@ export function defaultSessionTimeoutMs(plan) {
|
|
|
29
30
|
const room = MAX_SANDBOX_MS - SUBJECT_PROVISION_BUDGET_MS - stateBudgetMs - SANDBOX_TIMEOUT_BUFFER_MS;
|
|
30
31
|
return Math.max(MIN_DERIVED_SESSION_MS, Math.min(MAX_DERIVED_SESSION_MS, room));
|
|
31
32
|
}
|
|
33
|
+
// prose-check: model prompt (the participant model reads this, not a person)
|
|
32
34
|
const DEFAULT_MISSION = "You are one of MANY users hitting a shared web application at the same time. The browser is already open at the app. Accomplish your role's task, then stop.";
|
|
33
|
-
/** Resolve an actor's
|
|
34
|
-
* relative path, validated at parse against serve.url). */
|
|
35
|
+
/** Resolve an actor's participant URL against the harness-minted getHost base (entry is a
|
|
36
|
+
* same-origin relative path, validated at parse against serve.url). */
|
|
35
37
|
export function resolveActorEntryUrl(baseUrl, entry) {
|
|
36
38
|
if (!entry)
|
|
37
39
|
return baseUrl;
|
|
@@ -80,6 +82,7 @@ function buildActorSpec(participant, personas) {
|
|
|
80
82
|
* the model reads (never a raw bundle field), and the lab scrubs the code from all narration. The
|
|
81
83
|
* follower joins through the real UI (a direct /lobby/CODE visit does not auto-join a non-member). */
|
|
82
84
|
export function withLobbyCodeMission(spec, code) {
|
|
85
|
+
// prose-check: model prompt (the participant model reads this, not a person)
|
|
83
86
|
return {
|
|
84
87
|
...spec,
|
|
85
88
|
instructions: `${spec.instructions}\n\nThe multiplayer lobby code is ${code}. On the home screen choose Join, enter this lobby code, enter your name, and submit to join the shared game (do not open a lobby URL directly — go through the Join flow).`,
|
|
@@ -90,7 +93,7 @@ export function withLobbyCodeMission(spec, code) {
|
|
|
90
93
|
export function makeBlockedFollowerOutcome(spec, reason, timedOut) {
|
|
91
94
|
return {
|
|
92
95
|
spec,
|
|
93
|
-
sessionError: `handoff barrier: ${reason}; this follower
|
|
96
|
+
sessionError: `handoff barrier: ${reason}; this follower stopped before opening the app, so no turns were spent.`,
|
|
94
97
|
killed: false,
|
|
95
98
|
streamUrlPresent: false,
|
|
96
99
|
screenshots: [],
|
|
@@ -104,9 +107,10 @@ export function makeBlockedFollowerOutcome(spec, reason, timedOut) {
|
|
|
104
107
|
};
|
|
105
108
|
}
|
|
106
109
|
/**
|
|
107
|
-
* A live run publishes an in-progress bundle before its
|
|
108
|
-
* is attached, and the
|
|
109
|
-
* run killed mid-way leaves that evidence on disk. The flush starts with the
|
|
110
|
+
* A live run publishes an in-progress bundle before its participants start, whether or not an
|
|
111
|
+
* Observer is attached, and the participants' live traces rewrite it as they go, as on the
|
|
112
|
+
* computer-use route. A run killed mid-way leaves that evidence on disk. The flush starts with the
|
|
113
|
+
* first snapshot.
|
|
110
114
|
*/
|
|
111
115
|
export function startParticipantFlush(ctx, live, bundle) {
|
|
112
116
|
live.flush = startLiveTraceFlush({
|
|
@@ -117,14 +121,14 @@ export function startParticipantFlush(ctx, live, bundle) {
|
|
|
117
121
|
});
|
|
118
122
|
}
|
|
119
123
|
/**
|
|
120
|
-
* The runtime stream URLs each
|
|
121
|
-
* before the caller's onStream runs.
|
|
124
|
+
* The runtime stream URLs each participant reports to the live Observer. The Observer learns of a
|
|
125
|
+
* stream before the caller's onStream runs.
|
|
122
126
|
*/
|
|
123
127
|
function participantStreams(onStream, live) {
|
|
124
128
|
return (event) => {
|
|
125
129
|
if (event.type === "ready")
|
|
126
130
|
live.streamUrls.push({ streamId: event.streamId, url: event.url });
|
|
127
|
-
// Mark, never remove
|
|
131
|
+
// Mark, never remove: the tile falls back to recorded evidence and says why.
|
|
128
132
|
else
|
|
129
133
|
for (const entry of live.streamUrls)
|
|
130
134
|
if (entry.streamId === event.streamId)
|
|
@@ -164,33 +168,36 @@ export function participantRunDeps(ctx, live, scrubKnownValues) {
|
|
|
164
168
|
redactScreenshots: ctx.redactScreenshots,
|
|
165
169
|
scrubKnownValues,
|
|
166
170
|
runSession: ctx.runSession,
|
|
167
|
-
// A local-agent brain runs each
|
|
171
|
+
// A local-agent brain runs each participant on the operator's signed-in agent, as on computer
|
|
172
|
+
// use.
|
|
168
173
|
brain: ctx.plan.brain,
|
|
169
174
|
...(receiving ? { receiving } : {}),
|
|
170
175
|
now: ctx.now,
|
|
171
|
-
// The
|
|
176
|
+
// The participant's desktop seams, and the caller's prepareDesktop with the participant as its
|
|
177
|
+
// target.
|
|
172
178
|
...(ctx.deps.desktopModule === undefined ? {} : { desktopModule: ctx.deps.desktopModule }),
|
|
173
179
|
...(ctx.deps.detachedTimers === undefined ? {} : { detachedTimers: ctx.deps.detachedTimers }),
|
|
174
180
|
...(ctx.input.prepareDesktop === undefined ? {} : { prepareDesktop: ctx.input.prepareDesktop }),
|
|
175
181
|
onStream: participantStreams(ctx.input.onStream, live),
|
|
176
|
-
// A
|
|
182
|
+
// A participant visits the shared app and provisions no subject, so it reports no phase of its
|
|
183
|
+
// own.
|
|
177
184
|
reportSubjectPhase: defaultSubjectPhaseSink,
|
|
178
185
|
...(runBudget === undefined ? {} : { runBudget }),
|
|
179
|
-
// Concurrent participants are independent evidence
|
|
186
|
+
// Concurrent participants are independent evidence: a requested-vs-verified screen
|
|
180
187
|
// mismatch is recorded as separate facts + a warning instead of failing the participant's
|
|
181
|
-
// device claim closed, so one
|
|
188
|
+
// device claim closed, so one participant's window-manager drift cannot abort the whole
|
|
182
189
|
// live multi-actor world (the single-participant/fan-out routes keep fail-closed).
|
|
183
190
|
screenMismatchPolicy: "record-evidence",
|
|
184
191
|
};
|
|
185
192
|
}
|
|
186
193
|
/**
|
|
187
194
|
* Each participant's actor spec, with committed personas compiled in so each prompt carries real
|
|
188
|
-
* behavioral directives
|
|
195
|
+
* behavioral directives. Evidence copies of the assignment, instructions and persona are
|
|
189
196
|
* scrubbed of the run's known secret values.
|
|
190
197
|
*/
|
|
191
198
|
export async function buildParticipantSpecs(participants, cwd, scrubKnownValues) {
|
|
192
|
-
// Only the personas the participants use: an actors[0].persona that every
|
|
193
|
-
// never applied, so it is not read.
|
|
199
|
+
// Only the personas the participants use: an actors[0].persona that every participant overrides
|
|
200
|
+
// is never applied, so it is not read.
|
|
194
201
|
const personaResolution = await resolveCommittedPersonasForCwd(cwd, participants.map((participant) => participant.personaId));
|
|
195
202
|
const actorSpecs = participants.map((participant) => buildActorSpec(participant, personaResolution.personas));
|
|
196
203
|
for (const spec of actorSpecs) {
|
|
@@ -10,7 +10,7 @@ import { sharedWorldParticipants } from "../../lab/plan-participants.js";
|
|
|
10
10
|
import { PUBLIC_TARGET_OWNER_PATTERN } from "../../lab/parse/subject.js";
|
|
11
11
|
import { REPO_SLUG_PATTERN } from "../../lab/parse/values.js";
|
|
12
12
|
import { concurrentSharedWorldValidationReason, desktopMediaValidationReason, externalPublicSharedWorldValidationReason, outputTokenLimitValidationReason, receivingEmailValidationReason, scenarioCapsValidationReason, taskProtocolValidationReason, } from "../../lab/validation.js";
|
|
13
|
-
import { MODEL_RATES } from "../../run/pricing.js";
|
|
13
|
+
import { MODEL_RATES, unpricedCapMessage } from "../../run/pricing.js";
|
|
14
14
|
/** The registered descriptor for a planned actor; planSharedWorldLab checked the registry. */
|
|
15
15
|
export function sharedWorldDescriptorOf(actorType) {
|
|
16
16
|
const descriptor = actorRegistry[actorType];
|
|
@@ -27,20 +27,20 @@ export function planSharedWorldLab(config, input) {
|
|
|
27
27
|
ok: false,
|
|
28
28
|
refusal: { route: "shared-world", code, message, ...(actor === undefined ? {} : { actor }) },
|
|
29
29
|
});
|
|
30
|
-
const invalid = "
|
|
30
|
+
const invalid = "HUMANISH_SHARED_WORLD_INVALID";
|
|
31
31
|
const mediaReason = desktopMediaValidationReason(config, false);
|
|
32
32
|
if (mediaReason)
|
|
33
33
|
return refuse(invalid, mediaReason);
|
|
34
34
|
const analysis = resolveAutomaticAnalysis(config.review?.analysis);
|
|
35
35
|
if (!analysis.ok)
|
|
36
|
-
return refuse("
|
|
36
|
+
return refuse("HUMANISH_STUDY_ANALYSIS_INVALID", analysis.message);
|
|
37
37
|
const tasksReason = taskProtocolValidationReason(config, false);
|
|
38
38
|
if (tasksReason)
|
|
39
|
-
return refuse("
|
|
39
|
+
return refuse("HUMANISH_STUDY_TASKS_UNSUPPORTED", tasksReason);
|
|
40
40
|
const actorType = config.actors[0]?.type ?? "";
|
|
41
41
|
const descriptor = actorRegistry[actorType];
|
|
42
42
|
if (!descriptor || !isCuaActorDescriptor(descriptor))
|
|
43
|
-
return refuse("
|
|
43
|
+
return refuse("HUMANISH_SHARED_WORLD_ACTOR_UNSUPPORTED", `actors[0].type "${actorType}" is not a registered computer-use actor.`);
|
|
44
44
|
const actor = descriptor.id;
|
|
45
45
|
// An app-url subject is the external-public plane (a real operator-owned deployment used
|
|
46
46
|
// directly, with no getHost, clone, subject sandbox or seed); every other subject is the
|
|
@@ -61,7 +61,7 @@ export function planSharedWorldLab(config, input) {
|
|
|
61
61
|
if (!input.dryRun && (caps?.maxUsd !== undefined || caps?.maxTotalUsd !== undefined)) {
|
|
62
62
|
const model = (config.actors[0]?.model ?? DEFAULT_OPENAI_CU_MODEL).trim().toLowerCase();
|
|
63
63
|
if (!MODEL_RATES[model])
|
|
64
|
-
return refuse("
|
|
64
|
+
return refuse("HUMANISH_SHARED_WORLD_UNPRICED_CAP", unpricedCapMessage(model), actor);
|
|
65
65
|
}
|
|
66
66
|
const receivingReason = receivingEmailValidationReason(config);
|
|
67
67
|
if (receivingReason)
|
|
@@ -113,7 +113,7 @@ export function planSharedWorldLab(config, input) {
|
|
|
113
113
|
externalCatch: plane.kind === "external-public",
|
|
114
114
|
}),
|
|
115
115
|
// The external-public plane reads the host's lobby code with the OpenAI API, whatever
|
|
116
|
-
// brain drives the
|
|
116
|
+
// brain drives the participants.
|
|
117
117
|
...(plane.kind === "external-public" && brain.kind !== "openai"
|
|
118
118
|
? [{ kind: "key", name: "OPENAI_API_KEY" }]
|
|
119
119
|
: []),
|