humanish 0.106.1 → 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 +38 -32
- package/CHANGELOG.md +28 -0
- package/CONTEXT.md +51 -41
- package/README.md +152 -174
- 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-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-ui.js +1 -1
- package/dist/actors/codex/app-server.js +2 -1
- package/dist/actors/codex/codex-admission.d.ts +91 -0
- package/dist/actors/codex/codex-admission.js +150 -0
- 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/restricted-executable.d.ts +28 -4
- package/dist/actors/codex/restricted-executable.js +104 -29
- package/dist/actors/codex/restricted-launch.d.ts +9 -2
- package/dist/actors/codex/restricted-launch.js +43 -4
- 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 +66 -6
- package/dist/actors/codex/restricted-policy.d.ts +11 -3
- package/dist/actors/codex/restricted-policy.js +2 -2
- package/dist/actors/codex/restricted-session.d.ts +16 -3
- package/dist/actors/codex/restricted-session.js +60 -22
- 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 +17 -17
- package/dist/actors/computer-use/actor.js +6 -6
- 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 +15 -13
- package/dist/actors/computer-use/loop/ending.d.ts +7 -7
- package/dist/actors/computer-use/loop/ending.js +9 -9
- 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 +2 -2
- package/dist/actors/computer-use/loop/spend.js +4 -4
- package/dist/actors/computer-use/loop/trace.js +11 -10
- package/dist/actors/computer-use/loop/types.d.ts +37 -26
- package/dist/actors/computer-use/loop/usage.js +2 -2
- package/dist/actors/computer-use/loop.js +4 -4
- 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 +12 -9
- package/dist/actors/computer-use/openai-provider.js +47 -36
- 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 +86 -49
- 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/journey.js +15 -4
- package/dist/actors/scripted-browser/steps.js +19 -1
- package/dist/actors/scripted-browser/types.d.ts +12 -2
- package/dist/actors/stop-conditions.d.ts +1 -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/codex-config.d.ts +6 -2
- package/dist/analysis/codex-config.js +22 -14
- 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 +35 -16
- 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 +23 -18
- package/dist/cli/commands/codex.js +9 -9
- package/dist/cli/commands/comms.js +62 -34
- 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.d.ts +0 -2
- package/dist/cli/commands/lab-route-computer-use.js +32 -21
- package/dist/cli/commands/lab-route-preview.d.ts +1 -3
- package/dist/cli/commands/lab-route-preview.js +7 -7
- 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 +3 -4
- 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 +84 -54
- package/dist/cli/commands/lab-scorer.d.ts +2 -4
- 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 +168 -107
- package/dist/cli/commands/run-command.d.ts +10 -0
- package/dist/cli/commands/run-command.js +85 -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 +137 -136
- 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 +64 -77
- package/dist/cli/deprecations.d.ts +18 -0
- package/dist/cli/deprecations.js +48 -0
- package/dist/cli/doctor.d.ts +18 -5
- package/dist/cli/doctor.js +111 -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 +46 -10
- package/dist/cli/io.js +109 -30
- 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 +112 -43
- package/dist/cli/telemetry.d.ts +17 -17
- package/dist/cli/telemetry.js +49 -41
- package/dist/cli.js +1 -1
- package/dist/comms/capture-surface.d.ts +14 -13
- package/dist/comms/capture-surface.js +23 -22
- package/dist/comms/catch-host.d.ts +8 -8
- package/dist/comms/catch-host.js +14 -14
- package/dist/comms/connections.js +4 -4
- package/dist/comms/email-catch.d.ts +3 -3
- package/dist/comms/email-catch.js +8 -8
- package/dist/comms/external-evidence.d.ts +27 -0
- package/dist/comms/external-evidence.js +93 -0
- 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/lease-store.js +7 -7
- 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 +4 -4
- package/dist/evidence/browser-hygiene.d.ts +1 -1
- package/dist/evidence/browser-hygiene.js +1 -1
- 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 +5 -5
- package/dist/evidence/secret-scrub.d.ts +9 -0
- package/dist/evidence/secret-scrub.js +96 -0
- package/dist/feedback/draft.js +41 -85
- package/dist/feedback/export-bundle.js +5 -5
- package/dist/feedback/export.d.ts +5 -1
- package/dist/feedback/export.js +16 -17
- package/dist/feedback/feedback.d.ts +3 -3
- 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 +14 -15
- package/dist/index.js +10 -11
- package/dist/keys/key-resolution.d.ts +7 -5
- package/dist/keys/key-resolution.js +40 -38
- package/dist/lab/adapter-extension.d.ts +35 -13
- package/dist/lab/adapter-extension.js +50 -134
- package/dist/lab/adapter-scorer-loader.d.ts +32 -12
- package/dist/lab/adapter-scorer-loader.js +56 -32
- package/dist/lab/composition-rules.js +58 -58
- package/dist/lab/config.js +85 -43
- package/dist/lab/deprecated-fields.d.ts +10 -0
- package/dist/lab/deprecated-fields.js +24 -0
- package/dist/lab/device-presets.d.ts +10 -10
- package/dist/lab/device-presets.js +11 -11
- package/dist/lab/discover.d.ts +13 -9
- package/dist/lab/discover.js +118 -60
- package/dist/lab/doctor.d.ts +53 -11
- package/dist/lab/doctor.js +193 -47
- package/dist/lab/init-plan.js +1 -3
- 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 +43 -9
- package/dist/lab/lab-deps.d.ts +80 -0
- package/dist/lab/lab-deps.js +4 -0
- package/dist/lab/parse/actors.js +17 -16
- package/dist/lab/parse/comms.js +8 -7
- package/dist/lab/parse/execution.js +15 -14
- 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 +18 -17
- package/dist/lab/parse/subject.js +30 -29
- package/dist/lab/parse/values.d.ts +1 -2
- package/dist/lab/parse/values.js +3 -6
- package/dist/lab/persona-resolve.d.ts +7 -7
- package/dist/lab/persona-resolve.js +8 -8
- package/dist/lab/persona.js +1 -3
- package/dist/lab/plan-base.d.ts +0 -2
- package/dist/lab/plan-base.js +6 -4
- package/dist/lab/plan-participants.d.ts +7 -7
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +26 -8
- package/dist/lab/plan.d.ts +4 -18
- package/dist/lab/plan.js +24 -79
- package/dist/lab/preflight-probes.js +11 -11
- package/dist/lab/preflight-result.d.ts +2 -1
- package/dist/lab/preflight-result.js +5 -6
- package/dist/lab/preflight.d.ts +7 -8
- package/dist/lab/preflight.js +6 -6
- 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 +42 -41
- package/dist/lab/routing.js +66 -68
- package/dist/lab/run-lab-events.d.ts +3 -11
- package/dist/lab/run-lab-events.js +2 -16
- package/dist/lab/run-lab-homes.d.ts +76 -0
- package/dist/lab/run-lab-homes.js +7 -0
- package/dist/lab/run-lab-options.d.ts +12 -66
- package/dist/lab/run-lab-options.js +58 -285
- package/dist/lab/summary.d.ts +15 -9
- package/dist/lab/summary.js +24 -17
- package/dist/lab/tasks.d.ts +15 -15
- package/dist/lab/tasks.js +14 -14
- package/dist/lab/types.d.ts +201 -195
- package/dist/lab/types.js +2 -0
- package/dist/lab/validation.d.ts +21 -21
- package/dist/lab/validation.js +61 -59
- package/dist/lab/warnings.d.ts +10 -0
- package/dist/lab/warnings.js +70 -41
- package/dist/library-aliases.d.ts +56 -0
- package/dist/library-aliases.js +22 -0
- package/dist/observer/artifact.d.ts +2 -2
- package/dist/observer/artifact.js +9 -9
- package/dist/observer/data.d.ts +6 -6
- package/dist/observer/data.js +7 -6
- 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 +12 -7
- package/dist/observer/run-routes.d.ts +4 -4
- package/dist/observer/run-routes.js +6 -6
- package/dist/observer/serve.d.ts +17 -0
- package/dist/observer/serve.js +41 -6
- 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 +24 -17
- package/dist/routes/computer-use/bundle.d.ts +4 -11
- package/dist/routes/computer-use/bundle.js +12 -18
- 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 +11 -11
- package/dist/routes/computer-use/e2b-desktop/comms.js +24 -27
- package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/desktop.js +8 -11
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +16 -15
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +20 -19
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
- package/dist/routes/computer-use/e2b-desktop/prepare.js +40 -43
- package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/start.js +32 -30
- 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 +33 -20
- 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 +38 -42
- package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +33 -28
- 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 +20 -28
- package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +4 -2
- package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +17 -16
- 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 +40 -67
- 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} +11 -11
- package/dist/routes/computer-use/{lanes.js → participant-execution.js} +39 -26
- 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 +25 -11
- package/dist/routes/computer-use/participant-model.js +76 -34
- package/dist/routes/computer-use/participant-prompt.d.ts +13 -13
- package/dist/routes/computer-use/participant-prompt.js +8 -8
- package/dist/routes/computer-use/participant-runs.d.ts +11 -11
- package/dist/routes/computer-use/participant-runs.js +18 -18
- package/dist/routes/computer-use/plan.d.ts +21 -29
- package/dist/routes/computer-use/plan.js +70 -78
- package/dist/routes/computer-use/preflight.d.ts +3 -5
- package/dist/routes/computer-use/preflight.js +40 -36
- package/dist/routes/computer-use/rerun-selection.js +11 -7
- package/dist/routes/computer-use/result.d.ts +1 -1
- package/dist/routes/computer-use/result.js +48 -38
- package/dist/routes/computer-use/route.d.ts +5 -5
- package/dist/routes/computer-use/route.js +36 -33
- package/dist/routes/computer-use/self-report.d.ts +8 -8
- package/dist/routes/computer-use/self-report.js +33 -33
- package/dist/routes/computer-use/setup.d.ts +9 -15
- package/dist/routes/computer-use/setup.js +106 -83
- package/dist/routes/computer-use/single-bundle.d.ts +13 -16
- package/dist/routes/computer-use/single-bundle.js +46 -53
- package/dist/routes/computer-use/subject-projection.d.ts +6 -8
- package/dist/routes/computer-use/subject-projection.js +24 -23
- package/dist/routes/computer-use/types.d.ts +195 -238
- package/dist/routes/computer-use/types.js +21 -13
- package/dist/routes/preview.d.ts +8 -2
- package/dist/routes/preview.js +8 -5
- package/dist/routes/scripted/bundle.d.ts +5 -8
- package/dist/routes/scripted/bundle.js +23 -27
- package/dist/routes/scripted/plan.d.ts +6 -8
- package/dist/routes/scripted/plan.js +15 -13
- package/dist/routes/scripted/result.d.ts +4 -1
- package/dist/routes/scripted/result.js +15 -11
- package/dist/routes/scripted/route.js +15 -17
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +3 -3
- package/dist/routes/scripted/setup.d.ts +3 -2
- package/dist/routes/scripted/setup.js +27 -26
- package/dist/routes/scripted/subject.d.ts +8 -3
- package/dist/routes/scripted/subject.js +10 -6
- package/dist/routes/scripted/surface-records.js +4 -4
- 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 +21 -40
- package/dist/routes/scripted/types.js +2 -3
- package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +17 -16
- package/dist/routes/shared-world/bundle.d.ts +7 -7
- package/dist/routes/shared-world/bundle.js +60 -62
- package/dist/routes/shared-world/checkpoints.d.ts +5 -5
- package/dist/routes/shared-world/checkpoints.js +5 -5
- package/dist/routes/shared-world/comms.d.ts +8 -7
- package/dist/routes/shared-world/comms.js +38 -51
- package/dist/routes/shared-world/external-public.d.ts +6 -5
- package/dist/routes/shared-world/external-public.js +28 -25
- package/dist/routes/shared-world/handoff.d.ts +10 -9
- package/dist/routes/shared-world/handoff.js +89 -81
- package/dist/routes/shared-world/lobby-code.d.ts +7 -7
- package/dist/routes/shared-world/lobby-code.js +22 -22
- package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +15 -12
- package/dist/routes/shared-world/{seats.js → participant-specs.js} +65 -63
- package/dist/routes/shared-world/plan.d.ts +2 -6
- package/dist/routes/shared-world/plan.js +8 -9
- 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 +55 -48
- package/dist/routes/shared-world/result.js +47 -36
- package/dist/routes/shared-world/route.js +54 -57
- package/dist/routes/shared-world/setup.d.ts +6 -5
- package/dist/routes/shared-world/setup.js +16 -18
- package/dist/routes/shared-world/types.d.ts +70 -141
- package/dist/routes/shared-world/types.js +5 -5
- package/dist/routes/terminal/adapter.d.ts +10 -10
- package/dist/routes/terminal/adapter.js +32 -129
- package/dist/routes/terminal/bundle.d.ts +10 -15
- package/dist/routes/terminal/bundle.js +43 -52
- package/dist/routes/terminal/credentials.d.ts +4 -4
- package/dist/routes/terminal/credentials.js +20 -20
- package/dist/routes/terminal/dry-run.d.ts +1 -1
- package/dist/routes/terminal/dry-run.js +13 -15
- package/dist/routes/terminal/encoding.d.ts +1 -1
- package/dist/routes/terminal/encoding.js +4 -4
- package/dist/routes/terminal/ledger.d.ts +8 -8
- package/dist/routes/terminal/ledger.js +22 -22
- package/dist/routes/terminal/live-finish.d.ts +1 -2
- package/dist/routes/terminal/live-finish.js +24 -23
- package/dist/routes/terminal/live-sandbox.d.ts +3 -2
- package/dist/routes/terminal/live-sandbox.js +31 -32
- package/dist/routes/terminal/participant-text.d.ts +23 -0
- package/dist/routes/terminal/participant-text.js +165 -0
- package/dist/routes/terminal/persona.js +1 -1
- package/dist/routes/terminal/plan.d.ts +2 -6
- package/dist/routes/terminal/plan.js +23 -19
- package/dist/routes/terminal/recorder.d.ts +6 -1
- package/dist/routes/terminal/recorder.js +12 -4
- package/dist/routes/terminal/result.js +12 -12
- package/dist/routes/terminal/route.js +30 -31
- package/dist/routes/terminal/runtime.d.ts +3 -2
- package/dist/routes/terminal/runtime.js +3 -3
- package/dist/routes/terminal/sandbox.d.ts +4 -4
- package/dist/routes/terminal/sandbox.js +10 -10
- package/dist/routes/terminal/session.js +22 -19
- package/dist/routes/terminal/token-usage.d.ts +1 -1
- package/dist/routes/terminal/token-usage.js +10 -11
- package/dist/routes/terminal/trace.d.ts +7 -10
- package/dist/routes/terminal/trace.js +11 -66
- package/dist/routes/terminal/types.d.ts +104 -114
- package/dist/routes/terminal/types.js +12 -7
- 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 +7 -7
- package/dist/run/bundle.d.ts +99 -92
- package/dist/run/bundle.js +10 -8
- package/dist/run/cost-summary.js +6 -5
- package/dist/run/costs.d.ts +6 -6
- package/dist/run/costs.js +17 -11
- package/dist/run/detail.d.ts +9 -9
- package/dist/run/detail.js +10 -10
- package/dist/run/dry-run-inputs.js +1 -1
- package/dist/run/dry-run.js +23 -30
- 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 +34 -16
- package/dist/run/judge.js +41 -14
- 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.d.ts +1 -1
- package/dist/run/paths.js +2 -2
- package/dist/run/pricing.d.ts +30 -15
- package/dist/run/pricing.js +49 -30
- package/dist/run/projection.d.ts +27 -27
- package/dist/run/projection.js +23 -23
- package/dist/run/reclaim.d.ts +6 -0
- package/dist/run/reclaim.js +15 -5
- package/dist/run/results.d.ts +5 -5
- package/dist/run/run-index.d.ts +9 -7
- package/dist/run/run-index.js +24 -25
- 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 +7 -4
- package/dist/run/run.js +10 -6
- package/dist/run/sandbox-receipts.d.ts +5 -5
- package/dist/run/sandbox-receipts.js +6 -6
- package/dist/run/shared-world-evidence.d.ts +67 -66
- package/dist/run/shared-world-evidence.js +4 -4
- package/dist/run/shared-world-shape.d.ts +3 -3
- package/dist/run/shared-world-shape.js +16 -16
- package/dist/run/stats.d.ts +17 -11
- package/dist/run/stats.js +124 -66
- package/dist/run/status.d.ts +21 -32
- package/dist/run/status.js +34 -33
- package/dist/run/stored-runs.js +2 -1
- package/dist/run/stream-shape.js +1 -1
- package/dist/run/streams.d.ts +29 -22
- 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/terminal-contract.d.ts +5 -5
- package/dist/run/terminal-contract.js +4 -4
- package/dist/run/text.d.ts +2 -0
- package/dist/run/text.js +4 -0
- 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 +40 -38
- package/dist/run-lab.js +42 -40
- 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 +2 -2
- package/dist/subject/desktop-cli.js +3 -3
- package/dist/subject/local-tree-archive.d.ts +1 -1
- package/dist/subject/local-tree-archive.js +5 -5
- package/dist/subject/local-tree.d.ts +3 -3
- 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 +10 -11
- package/dist/subject/serve.d.ts +1 -1
- package/dist/subject/serve.js +4 -4
- package/dist/subject/state.d.ts +1 -1
- package/dist/subject/steps.d.ts +8 -8
- package/dist/subject/steps.js +7 -7
- 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 +11 -11
- package/dist/substrates/e2b/cdp-probe.js +15 -18
- package/dist/substrates/e2b/desktop-browser.d.ts +5 -5
- package/dist/substrates/e2b/desktop-browser.js +12 -12
- package/dist/substrates/e2b/desktop-cdp.d.ts +15 -15
- package/dist/substrates/e2b/desktop-cdp.js +11 -11
- 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 +6 -6
- package/dist/substrates/e2b/desktop-geometry.js +9 -9
- package/dist/substrates/e2b/desktop-media.d.ts +1 -1
- package/dist/substrates/e2b/desktop-media.js +3 -3
- 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 +2 -2
- package/dist/substrates/e2b/sdk.d.ts +11 -11
- package/dist/substrates/e2b/sdk.js +8 -8
- 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 +8 -6
- package/dist/tui/actions.js +31 -22
- 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 +83 -83
- package/dist/verify/actor.d.ts +14 -14
- package/dist/verify/actor.js +45 -45
- package/dist/verify/artifacts.d.ts +3 -3
- package/dist/verify/artifacts.js +6 -6
- package/dist/verify/context-growth.d.ts +9 -0
- package/dist/verify/context-growth.js +62 -0
- package/dist/verify/costs.d.ts +7 -7
- package/dist/verify/costs.js +9 -9
- 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-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 +18 -18
- package/dist/verify/subject.d.ts +4 -4
- package/dist/verify/subject.js +18 -18
- package/dist/verify/verify.js +98 -49
- package/docs/README.md +26 -33
- package/docs/architecture/actor-contract.md +105 -98
- package/docs/architecture/desktop-sessions.md +14 -14
- package/docs/architecture/external-public-shared-world.md +66 -59
- package/docs/architecture/github-feedback-loop.md +1 -4
- package/docs/architecture/guest-desktop.md +2 -2
- package/docs/architecture/observer.md +37 -37
- package/docs/architecture/restricted-codex-analysis.md +70 -30
- package/docs/architecture/serve.md +34 -37
- package/docs/architecture/state-driven-executor.md +55 -59
- package/docs/architecture/task-protocol-support.md +7 -9
- package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +83 -115
- 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 +54 -51
- package/docs/contracts/schemas.md +505 -390
- package/docs/contracts/study-analysis.md +26 -2
- 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/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
- 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 +8 -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 +63 -60
- 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 -45
- package/dist/actors/codex/qualified-versions.js +0 -87
- package/dist/cli/commands/lab.d.ts +0 -3
- package/dist/cli/commands/lab.js +0 -193
- 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/observer/static.d.ts +0 -39
- package/dist/observer/static.js +0 -369
- package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
- package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
- 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 -294
- 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
- /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
- /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface FileIdentity {
|
|
2
|
+
readonly dev: bigint;
|
|
3
|
+
readonly ino: bigint;
|
|
4
|
+
readonly size: bigint;
|
|
5
|
+
readonly sha256: string;
|
|
6
|
+
}
|
|
7
|
+
export interface DirectoryIdentity {
|
|
8
|
+
readonly physicalPath: string;
|
|
9
|
+
readonly dev: bigint;
|
|
10
|
+
readonly ino: bigint;
|
|
11
|
+
}
|
|
12
|
+
interface Inode {
|
|
13
|
+
readonly dev: bigint;
|
|
14
|
+
readonly ino: bigint;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A file this run creates. `inode` is set the moment the exclusive create succeeds, so a name that
|
|
18
|
+
* was already taken is never treated as this run's. `identity` is set once the bytes are written
|
|
19
|
+
* and read back through the same descriptor.
|
|
20
|
+
*/
|
|
21
|
+
export interface OwnedFile {
|
|
22
|
+
readonly path: string;
|
|
23
|
+
inode?: Inode | undefined;
|
|
24
|
+
identity?: FileIdentity | undefined;
|
|
25
|
+
}
|
|
26
|
+
export type LinkFile = (from: string, to: string) => Promise<void>;
|
|
27
|
+
export declare function sha256(bytes: Buffer): string;
|
|
28
|
+
export declare function fileIdentity(absolutePath: string, ours?: boolean): Promise<FileIdentity>;
|
|
29
|
+
export declare function sameFile(left: FileIdentity, right: FileIdentity): boolean;
|
|
30
|
+
export declare function bindDirectory(root: string, relativeDir: string, created?: string[]): Promise<DirectoryIdentity | undefined>;
|
|
31
|
+
export declare function assertDirectory(directory: DirectoryIdentity, root: string): Promise<void>;
|
|
32
|
+
export declare function exists(absolutePath: string): Promise<boolean>;
|
|
33
|
+
export declare function writeOwned(owned: OwnedFile, bytes: Buffer | string, mode: number): Promise<void>;
|
|
34
|
+
export declare function removeChecked(file: string, matches: (current: FileIdentity) => boolean, linkFile: LinkFile): Promise<string | undefined>;
|
|
35
|
+
export declare function removeOwned(owned: OwnedFile, linkFile: LinkFile): Promise<string | undefined>;
|
|
36
|
+
export declare const NO_HARD_LINKS: Set<string>;
|
|
37
|
+
export declare function restoreName(from: string, to: string, linkFile: LinkFile): Promise<boolean>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// File operations for humanish migrate that never replace or delete a file the run did not create.
|
|
2
|
+
// A new name is taken with an exclusive create or link(), which fail when the name is in use. A
|
|
3
|
+
// file is removed by renaming it to a random name first and checking it there, so a file saved over
|
|
4
|
+
// the name in the meantime keeps it.
|
|
5
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
6
|
+
import { constants } from "node:fs";
|
|
7
|
+
import { lstat, mkdir, open, readFile, rename, unlink } from "node:fs/promises";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { isNodeError } from "../run/type-guards.js";
|
|
10
|
+
export function sha256(bytes) {
|
|
11
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
12
|
+
}
|
|
13
|
+
// A source must be a single-link regular file. A file this run wrote may briefly have two links
|
|
14
|
+
// while a move is committed, so `ours` relaxes that.
|
|
15
|
+
export async function fileIdentity(absolutePath, ours = false) {
|
|
16
|
+
const stats = await lstat(absolutePath, { bigint: true });
|
|
17
|
+
if (!stats.isFile() || (!ours && stats.nlink !== 1n))
|
|
18
|
+
throw new Error("not a single-link regular file");
|
|
19
|
+
return {
|
|
20
|
+
dev: stats.dev,
|
|
21
|
+
ino: stats.ino,
|
|
22
|
+
size: stats.size,
|
|
23
|
+
sha256: sha256(await readFile(absolutePath)),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function sameFile(left, right) {
|
|
27
|
+
return (left.dev === right.dev &&
|
|
28
|
+
left.ino === right.ino &&
|
|
29
|
+
left.size === right.size &&
|
|
30
|
+
left.sha256 === right.sha256);
|
|
31
|
+
}
|
|
32
|
+
// Walk a directory below the project root one segment at a time, refusing a symbolic link or a
|
|
33
|
+
// non-directory. `create` makes missing segments and records each one it made.
|
|
34
|
+
export async function bindDirectory(root, relativeDir, created) {
|
|
35
|
+
let current = root;
|
|
36
|
+
for (const segment of relativeDir.split(path.sep).filter(Boolean)) {
|
|
37
|
+
current = path.join(current, segment);
|
|
38
|
+
let stats;
|
|
39
|
+
try {
|
|
40
|
+
stats = await lstat(current, { bigint: true });
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (!(isNodeError(error) && error.code === "ENOENT") || created === undefined) {
|
|
44
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
45
|
+
return undefined;
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
await mkdir(current, { mode: 0o755 });
|
|
49
|
+
created.push(current);
|
|
50
|
+
stats = await lstat(current, { bigint: true });
|
|
51
|
+
}
|
|
52
|
+
if (stats.isSymbolicLink() || !stats.isDirectory())
|
|
53
|
+
throw new Error(`${path.relative(root, current)} is not a plain directory`);
|
|
54
|
+
}
|
|
55
|
+
const stats = await lstat(current, { bigint: true });
|
|
56
|
+
return { physicalPath: current, dev: stats.dev, ino: stats.ino };
|
|
57
|
+
}
|
|
58
|
+
export async function assertDirectory(directory, root) {
|
|
59
|
+
const again = await bindDirectory(root, path.relative(root, directory.physicalPath));
|
|
60
|
+
if (again === undefined || again.dev !== directory.dev || again.ino !== directory.ino)
|
|
61
|
+
throw new Error(`${path.relative(root, directory.physicalPath)} changed`);
|
|
62
|
+
}
|
|
63
|
+
export async function exists(absolutePath) {
|
|
64
|
+
try {
|
|
65
|
+
await lstat(absolutePath);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
70
|
+
return false;
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Create a file exclusively and write it. Its inode is recorded the moment the create succeeds, so
|
|
75
|
+
// a failed write is still known to be this run's and a taken name never is. The bytes are read back
|
|
76
|
+
// through the same descriptor, so the identity recorded is this file's, whatever holds the name.
|
|
77
|
+
export async function writeOwned(owned, bytes, mode) {
|
|
78
|
+
const data = Buffer.from(bytes);
|
|
79
|
+
const handle = await open(owned.path, constants.O_CREAT | constants.O_EXCL | constants.O_RDWR | constants.O_NOFOLLOW, mode);
|
|
80
|
+
try {
|
|
81
|
+
const opened = await handle.stat({ bigint: true });
|
|
82
|
+
owned.inode = { dev: opened.dev, ino: opened.ino };
|
|
83
|
+
await handle.writeFile(data);
|
|
84
|
+
await handle.sync();
|
|
85
|
+
const stats = await handle.stat({ bigint: true });
|
|
86
|
+
const back = Buffer.alloc(Number(stats.size));
|
|
87
|
+
await handle.read(back, 0, back.length, 0);
|
|
88
|
+
owned.identity = { dev: stats.dev, ino: stats.ino, size: stats.size, sha256: sha256(back) };
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
await handle.close();
|
|
92
|
+
}
|
|
93
|
+
if (owned.identity.sha256 !== sha256(data))
|
|
94
|
+
throw new Error(`${path.basename(owned.path)} did not read back as written`);
|
|
95
|
+
}
|
|
96
|
+
// Remove the file at `file` only if `matches` says it is the expected one. The name is first renamed
|
|
97
|
+
// to a random one and the file checked there, so a file saved over the name in between is never
|
|
98
|
+
// deleted: it gets its name back, or keeps the random one. Returns the path kept, or undefined once
|
|
99
|
+
// the file is removed or was already gone.
|
|
100
|
+
export async function removeChecked(file, matches, linkFile) {
|
|
101
|
+
const aside = `${file}.migrate-${randomUUID()}.del`;
|
|
102
|
+
try {
|
|
103
|
+
await rename(file, aside);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
107
|
+
return undefined;
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
const current = await fileIdentity(aside, true).catch(() => undefined);
|
|
111
|
+
if (current !== undefined && matches(current)) {
|
|
112
|
+
await unlink(aside);
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
return (await restoreName(aside, file, linkFile)) ? file : aside;
|
|
116
|
+
}
|
|
117
|
+
// Remove a file this run created if it still holds this run's bytes, or was cut short while being
|
|
118
|
+
// written. Returns the path kept, if any.
|
|
119
|
+
export async function removeOwned(owned, linkFile) {
|
|
120
|
+
const inode = owned.inode;
|
|
121
|
+
if (inode === undefined)
|
|
122
|
+
return undefined;
|
|
123
|
+
return removeChecked(owned.path, (current) => current.dev === inode.dev &&
|
|
124
|
+
current.ino === inode.ino &&
|
|
125
|
+
(owned.identity === undefined || sameFile(current, owned.identity)), linkFile);
|
|
126
|
+
}
|
|
127
|
+
// Hard links need filesystem support. Without it a file is created exclusively and read back.
|
|
128
|
+
export const NO_HARD_LINKS = new Set(["EPERM", "ENOTSUP", "EOPNOTSUPP", "EXDEV"]);
|
|
129
|
+
// Give the file at `from` the name `to` without replacing anything there: link() fails on a taken
|
|
130
|
+
// name, and so does the exclusive create a filesystem without hard links gets instead. True once
|
|
131
|
+
// `to` holds the file and `from` is gone. False when `to` was taken, or was replaced before `from`
|
|
132
|
+
// could go, which leaves `from` as the file's only name.
|
|
133
|
+
export async function restoreName(from, to, linkFile) {
|
|
134
|
+
let placed;
|
|
135
|
+
let copied;
|
|
136
|
+
let owned;
|
|
137
|
+
try {
|
|
138
|
+
await linkFile(from, to);
|
|
139
|
+
const stats = await lstat(from, { bigint: true });
|
|
140
|
+
placed = { dev: stats.dev, ino: stats.ino };
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (isNodeError(error) && error.code === "EEXIST")
|
|
144
|
+
return false;
|
|
145
|
+
if (!(isNodeError(error) && NO_HARD_LINKS.has(error.code ?? "")))
|
|
146
|
+
throw error;
|
|
147
|
+
// Without hard links the file is copied. What was copied is recorded, so an edit made to
|
|
148
|
+
// `from` during the copy keeps `from`.
|
|
149
|
+
const stats = await lstat(from, { bigint: true });
|
|
150
|
+
// Only a regular file is copied; anything else keeps the name it has.
|
|
151
|
+
if (!stats.isFile())
|
|
152
|
+
return false;
|
|
153
|
+
const bytes = await readFile(from);
|
|
154
|
+
copied = { dev: stats.dev, ino: stats.ino, size: BigInt(bytes.length), sha256: sha256(bytes) };
|
|
155
|
+
const copy = { path: to };
|
|
156
|
+
try {
|
|
157
|
+
await writeOwned(copy, bytes, Number(stats.mode & 511n));
|
|
158
|
+
}
|
|
159
|
+
catch (copyError) {
|
|
160
|
+
if (copy.inode === undefined && isNodeError(copyError) && copyError.code === "EEXIST")
|
|
161
|
+
return false;
|
|
162
|
+
if (copy.inode !== undefined)
|
|
163
|
+
await removeOwned(copy, linkFile).catch(() => undefined);
|
|
164
|
+
throw copyError;
|
|
165
|
+
}
|
|
166
|
+
placed = copy.inode;
|
|
167
|
+
owned = copy;
|
|
168
|
+
}
|
|
169
|
+
const now = await lstat(to, { bigint: true }).catch(() => undefined);
|
|
170
|
+
if (now === undefined || now.dev !== placed.dev || now.ino !== placed.ino)
|
|
171
|
+
return false;
|
|
172
|
+
if (copied === undefined) {
|
|
173
|
+
await unlink(from);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
const expected = copied;
|
|
177
|
+
if ((await removeChecked(from, (current) => sameFile(current, expected), linkFile)) === undefined)
|
|
178
|
+
return true;
|
|
179
|
+
// `from` changed during the copy: it stays, and the stale copy goes.
|
|
180
|
+
await removeOwned(owned, linkFile).catch(() => undefined);
|
|
181
|
+
return false;
|
|
182
|
+
}
|
package/dist/subject/clone.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare function provisionCloneSubject(shell: Shell, args: {
|
|
|
25
25
|
state?: LabSubjectState;
|
|
26
26
|
hasGithubToken: boolean;
|
|
27
27
|
requestTimeoutMs: number;
|
|
28
|
-
/** Literal scrubber for known provisioned values, applied to log tails
|
|
28
|
+
/** Literal scrubber for known provisioned values, applied to log tails pre-truncation. */
|
|
29
29
|
scrub: (text: string) => string;
|
|
30
30
|
/** Called the moment the cloned commit resolves, so provenance survives later failures. */
|
|
31
31
|
onCommit?: (commit: string) => void;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Shell } from "../substrates/shell.js";
|
|
2
2
|
import { type SubjectPhaseEvent } from "./steps.js";
|
|
3
3
|
/**
|
|
4
|
-
* Prepare a CLI study's runtime and, only when declared, its product
|
|
4
|
+
* Prepare a CLI study's runtime and, only when declared, its product.
|
|
5
5
|
*
|
|
6
|
-
* The install runs
|
|
6
|
+
* The install runs unkeyed and before the session starts, for the same reason the clone route
|
|
7
7
|
* provisions its subject first: what is being studied begins when the participant looks at the
|
|
8
8
|
* screen. Omitting install deliberately studies product installation; Node/npm remain a
|
|
9
9
|
* harness prerequisite so the participant can follow the product's public npm instructions.
|
|
@@ -4,9 +4,9 @@ import { NODE_BOOTSTRAP_COMMAND, NODE_BOOTSTRAP_TIMEOUT_MS } from "./node-bootst
|
|
|
4
4
|
import { runDetachedStep } from "../substrates/detached.js";
|
|
5
5
|
import { emitPhaseCompleted, emitPhaseStarted, INSTALL_TIMEOUT_MS, } from "./steps.js";
|
|
6
6
|
/**
|
|
7
|
-
* Prepare a CLI study's runtime and, only when declared, its product
|
|
7
|
+
* Prepare a CLI study's runtime and, only when declared, its product.
|
|
8
8
|
*
|
|
9
|
-
* The install runs
|
|
9
|
+
* The install runs unkeyed and before the session starts, for the same reason the clone route
|
|
10
10
|
* provisions its subject first: what is being studied begins when the participant looks at the
|
|
11
11
|
* screen. Omitting install deliberately studies product installation; Node/npm remain a
|
|
12
12
|
* harness prerequisite so the participant can follow the product's public npm instructions.
|
|
@@ -44,7 +44,7 @@ export async function provisionDesktopCli(shell, args) {
|
|
|
44
44
|
if (!result.ok) {
|
|
45
45
|
// Fail closed: a participant handed a desktop where the product is not installed would produce
|
|
46
46
|
// a transcript about a missing command, and that finding belongs to the harness, not the tool.
|
|
47
|
-
// The tail rides along, scrubbed before truncation like every other provisioning failure
|
|
47
|
+
// The tail rides along, scrubbed before truncation like every other provisioning failure. A
|
|
48
48
|
// bare "install failed" is unactionable to whoever wrote the command.
|
|
49
49
|
throw new Error(args.scrub(`desktop-cli install failed for "${args.product}" (${result.timedOut ? "timed out" : `exit ${result.exitCode ?? "?"}`}): ${failureTail(args.scrub(result.logTail))}`));
|
|
50
50
|
}
|
|
@@ -74,7 +74,7 @@ export declare function createLocalTreeArchive(root: string, options?: CreateLoc
|
|
|
74
74
|
/**
|
|
75
75
|
* Normalize an author-supplied exclude entry to the relPath shape enumeration
|
|
76
76
|
* produces (no leading "./", no trailing "/"). Absolute paths and glob syntax
|
|
77
|
-
* are
|
|
77
|
+
* are rejected instead of silently ignored: an exclude the author believed in but
|
|
78
78
|
* that never matches anything is a leak vector, so unusable shapes fail
|
|
79
79
|
* closed at the packing boundary (and, for lab manifests, already at parse
|
|
80
80
|
* time in src/lab/parse/subject.ts).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Local working-tree packaging for `subject.source: local-tree`.
|
|
2
2
|
//
|
|
3
|
-
// Enumeration produces
|
|
3
|
+
// Enumeration produces one file list that drives both the tar archive and the
|
|
4
4
|
// content digest (archiveSha256), so the digest can never diverge from what
|
|
5
5
|
// actually gets packed. A prior in-house harness reimplemented exclusion in a
|
|
6
6
|
// second, independent digest walker that could drift from what its tar
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// that cannot happen: enumerateLocalTree() builds one entries array, and both
|
|
9
9
|
// the hash and the tar file list are derived from that same array.
|
|
10
10
|
//
|
|
11
|
-
// See docs/goals/local-tree-subject/goal.md ("Packing design") for the full
|
|
11
|
+
// See docs/history/goals/local-tree-subject/goal.md ("Packing design") for the full
|
|
12
12
|
// contract implemented here. Node builtins only, no npm dependencies.
|
|
13
13
|
import { execFileSync } from "node:child_process";
|
|
14
14
|
import { createHash } from "node:crypto";
|
|
@@ -113,7 +113,7 @@ export function createLocalTreeArchive(root, options = {}) {
|
|
|
113
113
|
(extraExclude.length > 0 ? " and extraExclude" : "") +
|
|
114
114
|
"; local-tree packing requires at least one non-denylisted file or symlink. (Paths in this message are basenames only; the packed root is the lab resolution cwd.)");
|
|
115
115
|
}
|
|
116
|
-
// Check the cap from enumerated sizes
|
|
116
|
+
// Check the cap from enumerated sizes before reading/hashing file bytes, so
|
|
117
117
|
// an oversized tree fails closed without the cost of hashing all of it.
|
|
118
118
|
const enumeratedBytes = entries.reduce((sum, entry) => (entry.kind === "file" ? sum + entry.size : sum), 0);
|
|
119
119
|
if (enumeratedBytes > maxArchiveBytes) {
|
|
@@ -200,7 +200,7 @@ function captureGitInfo(root) {
|
|
|
200
200
|
return undefined;
|
|
201
201
|
}
|
|
202
202
|
// Pathspec-scoped to the packed root: `git status --porcelain` without a
|
|
203
|
-
// pathspec reports the
|
|
203
|
+
// pathspec reports the whole enclosing repository, which would report a
|
|
204
204
|
// clean packed subtree as dirty whenever an unrelated sibling package in a
|
|
205
205
|
// monorepo has in-progress changes.
|
|
206
206
|
const status = execFileSync("git", ["status", "--porcelain", "--", "."], {
|
|
@@ -290,7 +290,7 @@ function isDenylistedSegment(relPath) {
|
|
|
290
290
|
/**
|
|
291
291
|
* Normalize an author-supplied exclude entry to the relPath shape enumeration
|
|
292
292
|
* produces (no leading "./", no trailing "/"). Absolute paths and glob syntax
|
|
293
|
-
* are
|
|
293
|
+
* are rejected instead of silently ignored: an exclude the author believed in but
|
|
294
294
|
* that never matches anything is a leak vector, so unusable shapes fail
|
|
295
295
|
* closed at the packing boundary (and, for lab manifests, already at parse
|
|
296
296
|
* time in src/lab/parse/subject.ts).
|
|
@@ -5,20 +5,20 @@ import type { Shell } from "../substrates/shell.js";
|
|
|
5
5
|
import { type SubjectPhaseEvent } from "./steps.js";
|
|
6
6
|
/**
|
|
7
7
|
* Provision a local-tree subject inside the sandbox: upload the once-per-run packed archive
|
|
8
|
-
* (identical bytes across every fan-out
|
|
8
|
+
* (identical bytes across every fan-out participant) → extract it into SUBJECT_DIR → the
|
|
9
9
|
* same shared serve pipeline provisionCloneSubject uses. Unlike the clone route there is no
|
|
10
10
|
* in-sandbox git refresh: the archive excludes .git entirely (see local-tree-archive.ts), so
|
|
11
11
|
* subject identity is the host-side LocalTreeArchive captured at pack time, never anything
|
|
12
12
|
* resolved in-sandbox.
|
|
13
13
|
*/
|
|
14
14
|
export declare function provisionLocalTreeSubject(shell: Shell, args: {
|
|
15
|
-
/** The once-per-run packed archive bytes (shared byte-identically across every
|
|
15
|
+
/** The once-per-run packed archive bytes (shared byte-identically across every participant). */
|
|
16
16
|
archiveBuffer: ArrayBuffer;
|
|
17
17
|
serve: LabSubjectServe;
|
|
18
18
|
/** Declared subject state (seed steps; external declaration is provenance-only). */
|
|
19
19
|
state?: LabSubjectState;
|
|
20
20
|
requestTimeoutMs: number;
|
|
21
|
-
/** Literal scrubber for known provisioned values, applied to log tails
|
|
21
|
+
/** Literal scrubber for known provisioned values, applied to log tails pre-truncation. */
|
|
22
22
|
scrub: (text: string) => string;
|
|
23
23
|
/** Called the moment each state step finishes, success or failure. */
|
|
24
24
|
onStateStep?: (record: RunSubjectStateStepRecord) => void;
|
|
@@ -7,7 +7,7 @@ import { SOURCE_TIMEOUT_MS, emitPhaseCompleted, emitPhaseStarted, SUBJECT_DIR, }
|
|
|
7
7
|
const LOCAL_TREE_REMOTE_ARCHIVE_PATH = "/home/user/.humanish-source.tar.gz";
|
|
8
8
|
/**
|
|
9
9
|
* Provision a local-tree subject inside the sandbox: upload the once-per-run packed archive
|
|
10
|
-
* (identical bytes across every fan-out
|
|
10
|
+
* (identical bytes across every fan-out participant) → extract it into SUBJECT_DIR → the
|
|
11
11
|
* same shared serve pipeline provisionCloneSubject uses. Unlike the clone route there is no
|
|
12
12
|
* in-sandbox git refresh: the archive excludes .git entirely (see local-tree-archive.ts), so
|
|
13
13
|
* subject identity is the host-side LocalTreeArchive captured at pack time, never anything
|
|
@@ -6,7 +6,7 @@ export declare const NODE_NPM_PREFIX_SCRIPT: string;
|
|
|
6
6
|
export declare const NODE_BOOTSTRAP_TIMEOUT_MS: number;
|
|
7
7
|
/**
|
|
8
8
|
* Install Node from the pinned official archive when the desktop has no working Node >=20 and
|
|
9
|
-
* npm. The terminal
|
|
9
|
+
* npm. The terminal route, desktop CLI studies and the subject serve pipeline share it. It needs no
|
|
10
10
|
* apt: every network call is one bounded curl, so a stalled mirror fails the step within minutes.
|
|
11
11
|
*/
|
|
12
12
|
export declare const NODE_BOOTSTRAP_COMMAND: string;
|
|
@@ -20,7 +20,7 @@ export const NODE_NPM_PREFIX_SCRIPT = [
|
|
|
20
20
|
export const NODE_BOOTSTRAP_TIMEOUT_MS = 5 * 60_000;
|
|
21
21
|
/**
|
|
22
22
|
* Install Node from the pinned official archive when the desktop has no working Node >=20 and
|
|
23
|
-
* npm. The terminal
|
|
23
|
+
* npm. The terminal route, desktop CLI studies and the subject serve pipeline share it. It needs no
|
|
24
24
|
* apt: every network call is one bounded curl, so a stalled mirror fails the step within minutes.
|
|
25
25
|
*/
|
|
26
26
|
export const NODE_BOOTSTRAP_COMMAND = [
|
|
@@ -54,13 +54,13 @@ export const NODE_BOOTSTRAP_COMMAND = [
|
|
|
54
54
|
"for executable in node npm npx; do",
|
|
55
55
|
` sudo -n ln -sfn "$node_target/bin/$executable" "/usr/local/bin/$executable"`,
|
|
56
56
|
"done",
|
|
57
|
-
// Keep global product executables on the existing ordinary/sudo PATH
|
|
57
|
+
// Keep global product executables on the existing ordinary/sudo `PATH`. The new
|
|
58
58
|
// versioned distribution is the only config we modify; no user/global npmrc or profile.
|
|
59
59
|
`sudo -n "$node_target/bin/node" -e '${NODE_NPM_PREFIX_SCRIPT}' "$node_target/lib/node_modules/npm/npmrc"`,
|
|
60
60
|
"hash -r",
|
|
61
61
|
`node -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 20 ? 0 : 1)' && npm --version >/dev/null`,
|
|
62
|
-
// Product installation already uses sudo; detect a template whose sudo PATH cannot see Node
|
|
63
|
-
// rather than changing global PATH or permissions to make it look supported.
|
|
62
|
+
// Product installation already uses sudo; detect a template whose sudo `PATH` cannot see Node
|
|
63
|
+
// rather than changing global `PATH` or permissions to make it look supported.
|
|
64
64
|
`sudo -n node -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 20 ? 0 : 1)' && sudo -n npm --version >/dev/null`,
|
|
65
65
|
"fi",
|
|
66
66
|
].join("\n");
|
package/dist/subject/runtime.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
// Provide the runtime a subject's serve pipeline needs, instead of failing at exit 127
|
|
1
|
+
// Provide the runtime a subject's serve pipeline needs, instead of failing at exit 127.
|
|
2
2
|
//
|
|
3
|
-
// The stock E2B `desktop` template ships python3 and curl but
|
|
4
|
-
//
|
|
5
|
-
// for
|
|
6
|
-
//
|
|
7
|
-
// `pnpm: command not found` AFTER a sandbox had been created and paid for.
|
|
3
|
+
// The stock E2B `desktop` template ships python3 and curl but no Node. So the in-sandbox comms
|
|
4
|
+
// catch runs on python3, the terminal route bootstraps Node explicitly, and this module provides
|
|
5
|
+
// Node for the computer-use clone/local-tree route. Without it, any study whose `serve.install`
|
|
6
|
+
// runs npm or pnpm dies with `pnpm: command not found` after its sandbox is created and paid for.
|
|
8
7
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
8
|
+
// That failure is invisible up front: `lab inspect` is clean, the plan prints normally, the sandbox
|
|
9
|
+
// provisions, and the first signal is a shell exit code attributed to "subject install failed".
|
|
11
10
|
// Nobody can debug that from the outside.
|
|
12
11
|
//
|
|
13
|
-
// The
|
|
14
|
-
// know which binaries the template happens to carry
|
|
15
|
-
//
|
|
12
|
+
// The harness provides the runtime instead of warning about it. An adopter writing a lab for a Node app should not have to
|
|
13
|
+
// know which binaries the template happens to carry. That is the harness's job, and the terminal
|
|
14
|
+
// route already treats it that way. Detection is conservative and the bootstrap is skipped whenever
|
|
16
15
|
// a runtime is already present, so a custom template that ships Node pays nothing.
|
|
17
16
|
/** Package managers and runtimes whose absence on the stock template breaks a serve pipeline. */
|
|
18
17
|
const NODE_COMMANDS = ["npm", "npx", "pnpm", "yarn", "bun", "node", "vite", "next", "tsx"];
|
package/dist/subject/serve.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare function runSubjectServePipeline(shell: Shell, args: {
|
|
|
25
25
|
/** Declared subject state (seed steps; external declaration is provenance-only). */
|
|
26
26
|
state?: LabSubjectState;
|
|
27
27
|
requestTimeoutMs: number;
|
|
28
|
-
/** Literal scrubber for known provisioned values, applied to log tails
|
|
28
|
+
/** Literal scrubber for known provisioned values, applied to log tails pre-truncation. */
|
|
29
29
|
scrub: (text: string) => string;
|
|
30
30
|
/** Called the moment each state step finishes, success or failure. */
|
|
31
31
|
onStateStep?: (record: RunSubjectStateStepRecord) => void;
|
package/dist/subject/serve.js
CHANGED
|
@@ -8,7 +8,7 @@ import { emitPhaseCompleted, emitPhaseStarted, INSTALL_TIMEOUT_MS, isoNow, SUBJE
|
|
|
8
8
|
const BUILD_TIMEOUT_MS = 10 * 60_000;
|
|
9
9
|
const DEFAULT_READY_TIMEOUT_MS = 180_000;
|
|
10
10
|
/**
|
|
11
|
-
* Run a provisioning step and, when it fails with an exit code, run it once more
|
|
11
|
+
* Run a provisioning step and, when it fails with an exit code, run it once more: a
|
|
12
12
|
* transient network error inside `npm install` is the common case. A timeout is not retried: its
|
|
13
13
|
* budget is already spent, and a second wait would double it. The retry runs under its own step
|
|
14
14
|
* name so both logs stay.
|
|
@@ -114,14 +114,14 @@ export async function runSubjectServePipeline(shell, args) {
|
|
|
114
114
|
await refresh();
|
|
115
115
|
await startSubject(step);
|
|
116
116
|
await waitForSubjectReady(step);
|
|
117
|
-
// after-ready: fixture loading through the
|
|
117
|
+
// after-ready: fixture loading through the running app (loopback curl from in-sandbox:
|
|
118
118
|
// steps are author-trusted provisioning, not actors, so no new URL policy surface). These
|
|
119
119
|
// complete before the caller opens the browser and the session timer starts.
|
|
120
120
|
await runState("after-ready");
|
|
121
121
|
await refresh();
|
|
122
122
|
}
|
|
123
123
|
/**
|
|
124
|
-
* Provide the runtime the pipeline needs before running it
|
|
124
|
+
* Provide the runtime the pipeline needs before running it. The stock desktop template
|
|
125
125
|
* ships python3 and curl but no Node. Probe first, so a template that ships its own Node pays
|
|
126
126
|
* nothing.
|
|
127
127
|
*/
|
|
@@ -187,7 +187,7 @@ async function installSubject(step, command) {
|
|
|
187
187
|
? "subject install failed twice"
|
|
188
188
|
: "subject install failed");
|
|
189
189
|
if (!install.ok) {
|
|
190
|
-
// Lead with the line a person can act on; npm's own trace follows it
|
|
190
|
+
// Lead with the line a person can act on; npm's own trace follows it.
|
|
191
191
|
const headline = install.timedOut
|
|
192
192
|
? `subject install timed out after ${step.serve.installTimeoutMs ?? INSTALL_TIMEOUT_MS}ms`
|
|
193
193
|
: install.attempts === 2
|
package/dist/subject/state.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare function commandDigestOf(command: string): string;
|
|
|
14
14
|
export declare function runStateSteps(shell: Shell, when: LabStateStepWhen, args: {
|
|
15
15
|
state?: LabSubjectState;
|
|
16
16
|
requestTimeoutMs: number;
|
|
17
|
-
/** Literal scrubber for known provisioned values, applied to log tails
|
|
17
|
+
/** Literal scrubber for known provisioned values, applied to log tails pre-truncation. */
|
|
18
18
|
scrub: (text: string) => string;
|
|
19
19
|
onStateStep?: (record: RunSubjectStateStepRecord) => void;
|
|
20
20
|
onPhase?: (event: SubjectPhaseEvent) => void;
|
package/dist/subject/steps.d.ts
CHANGED
|
@@ -24,14 +24,14 @@ export declare function isoNow(now: () => number): string;
|
|
|
24
24
|
export declare function emitPhaseStarted(onPhase: ((event: SubjectPhaseEvent) => void) | undefined, now: () => number, phase: string, message: string): void;
|
|
25
25
|
/** Emit the matching phase-completed event: always carries ok and durationMs (>= 0). */
|
|
26
26
|
export declare function emitPhaseCompleted(onPhase: ((event: SubjectPhaseEvent) => void) | undefined, now: () => number, startedAt: number, phase: string, ok: boolean, message: string): void;
|
|
27
|
-
/** Default phase-boundary sink (stderr): one line per event, prefixed with the
|
|
28
|
-
* when
|
|
29
|
-
*
|
|
30
|
-
* Overridable via
|
|
27
|
+
/** Default phase-boundary sink (stderr): one line per event, prefixed with the participant id
|
|
28
|
+
* only when the run has more than one participant. A single participant still gets every line:
|
|
29
|
+
* a silent clone, install, build and ready boot is the bug this event stream exists to close.
|
|
30
|
+
* Overridable via LabDeps.subjectPhaseSink so deterministic tests capture instead of writing to
|
|
31
31
|
* the real stderr. */
|
|
32
|
-
export declare function defaultSubjectPhaseSink(event: SubjectPhaseEvent,
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
export declare function defaultSubjectPhaseSink(event: SubjectPhaseEvent, participant: {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly count: number;
|
|
35
35
|
}): void;
|
|
36
|
-
/** The shared-world subject's phase line: one shared plane, so no
|
|
36
|
+
/** The shared-world subject's phase line: one shared plane, so no participant prefix. */
|
|
37
37
|
export declare function defaultSharedWorldPhaseSink(event: SubjectPhaseEvent): void;
|
package/dist/subject/steps.js
CHANGED
|
@@ -22,17 +22,17 @@ export function emitPhaseCompleted(onPhase, now, startedAt, phase, ok, message)
|
|
|
22
22
|
message,
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
-
/** Default phase-boundary sink (stderr): one line per event, prefixed with the
|
|
26
|
-
* when
|
|
27
|
-
*
|
|
28
|
-
* Overridable via
|
|
25
|
+
/** Default phase-boundary sink (stderr): one line per event, prefixed with the participant id
|
|
26
|
+
* only when the run has more than one participant. A single participant still gets every line:
|
|
27
|
+
* a silent clone, install, build and ready boot is the bug this event stream exists to close.
|
|
28
|
+
* Overridable via LabDeps.subjectPhaseSink so deterministic tests capture instead of writing to
|
|
29
29
|
* the real stderr. */
|
|
30
|
-
export function defaultSubjectPhaseSink(event,
|
|
30
|
+
export function defaultSubjectPhaseSink(event, participant) {
|
|
31
31
|
const durationSuffix = event.durationMs === undefined ? "" : ` (${event.durationMs}ms)`;
|
|
32
|
-
const prefix =
|
|
32
|
+
const prefix = participant.count > 1 ? `humanish computer-use [${participant.id}]` : "humanish computer-use";
|
|
33
33
|
process.stderr.write(`${prefix}: ${event.message}${durationSuffix}\n`);
|
|
34
34
|
}
|
|
35
|
-
/** The shared-world subject's phase line: one shared plane, so no
|
|
35
|
+
/** The shared-world subject's phase line: one shared plane, so no participant prefix. */
|
|
36
36
|
export function defaultSharedWorldPhaseSink(event) {
|
|
37
37
|
const durationSuffix = event.durationMs === undefined ? "" : ` (${event.durationMs}ms)`;
|
|
38
38
|
process.stderr.write(`humanish shared-world (concurrent): ${event.message}${durationSuffix}\n`);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* True when `error` is (structurally) the @e2b/desktop CommandExitError: a
|
|
3
|
-
* non-zero substrate command exit that the real Sandbox surfaces as a
|
|
3
|
+
* non-zero substrate command exit that the real Sandbox surfaces as a throw.
|
|
4
4
|
* Matches either the SDK class name (`name === "CommandExitError"`) or any object
|
|
5
5
|
* carrying a numeric `exitCode` (the same field `commandFailureInfo` reads, so a
|
|
6
6
|
* structural fake is covered without importing the SDK class).
|
|
7
7
|
*
|
|
8
|
-
* Deliberately conservative
|
|
8
|
+
* Deliberately conservative: it is the recoverability predicate the CUA loop uses
|
|
9
9
|
* to skip a single failed desktop action instead of ending the whole run: it must
|
|
10
|
-
*
|
|
10
|
+
* not match a deadline/abort control-flow signal (those subclass Error without a
|
|
11
11
|
* name override or an exitCode) or a generic Error with no exit signal, so only a
|
|
12
12
|
* genuine substrate-command failure is treated as recoverable.
|
|
13
13
|
*/
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
import { tailOf } from "./shell.js";
|
|
13
13
|
/**
|
|
14
14
|
* True when `error` is (structurally) the @e2b/desktop CommandExitError: a
|
|
15
|
-
* non-zero substrate command exit that the real Sandbox surfaces as a
|
|
15
|
+
* non-zero substrate command exit that the real Sandbox surfaces as a throw.
|
|
16
16
|
* Matches either the SDK class name (`name === "CommandExitError"`) or any object
|
|
17
17
|
* carrying a numeric `exitCode` (the same field `commandFailureInfo` reads, so a
|
|
18
18
|
* structural fake is covered without importing the SDK class).
|
|
19
19
|
*
|
|
20
|
-
* Deliberately conservative
|
|
20
|
+
* Deliberately conservative: it is the recoverability predicate the CUA loop uses
|
|
21
21
|
* to skip a single failed desktop action instead of ending the whole run: it must
|
|
22
|
-
*
|
|
22
|
+
* not match a deadline/abort control-flow signal (those subclass Error without a
|
|
23
23
|
* name override or an exitCode) or a generic Error with no exit signal, so only a
|
|
24
24
|
* genuine substrate-command failure is treated as recoverable.
|
|
25
25
|
*/
|
|
@@ -10,7 +10,7 @@ export declare function detachedTimersOf(options: DetachedTimers): DetachedTimer
|
|
|
10
10
|
export interface DetachedStepOptions extends DetachedTimers {
|
|
11
11
|
/** Short [a-z0-9-] label; names the script/status/log files under /tmp. */
|
|
12
12
|
name: string;
|
|
13
|
-
/** The shell command to run (the lab author's own command
|
|
13
|
+
/** The shell command to run (the lab author's own command: package.json-script trust). */
|
|
14
14
|
command: string;
|
|
15
15
|
cwd?: string;
|
|
16
16
|
/** Wall-clock budget for the step. */
|
|
@@ -22,19 +22,19 @@ export interface DetachedStepResult {
|
|
|
22
22
|
ok: boolean;
|
|
23
23
|
exitCode?: number;
|
|
24
24
|
timedOut: boolean;
|
|
25
|
-
/** Capped,
|
|
25
|
+
/** Capped, unredacted log tail; redact before persisting. */
|
|
26
26
|
logTail: string;
|
|
27
27
|
}
|
|
28
|
-
/** Read the capped log tail for a step (raw
|
|
28
|
+
/** Read the capped log tail for a step (raw; caller redacts). */
|
|
29
29
|
export declare function readDetachedLog(shell: Shell, name: string, requestTimeoutMs?: number): Promise<string>;
|
|
30
30
|
/**
|
|
31
|
-
* Run a
|
|
31
|
+
* Run a bounded step (install/build) detached, polling its atomic status file until it
|
|
32
32
|
* exits or the budget runs out. On timeout the process group is killed and the log tail is
|
|
33
33
|
* still captured so failures stay diagnosable.
|
|
34
34
|
*/
|
|
35
35
|
export declare function runDetachedStep(shell: Shell, options: DetachedStepOptions): Promise<DetachedStepResult>;
|
|
36
36
|
/**
|
|
37
|
-
* Launch a
|
|
37
|
+
* Launch a long-lived process (the subject's server) fully detached and return immediately.
|
|
38
38
|
* No status polling: liveness is the caller's readiness probe, and reclamation belongs to
|
|
39
39
|
* the sandbox lifecycle (create with kill-on-timeout).
|
|
40
40
|
*/
|
|
@@ -45,7 +45,7 @@ export declare function startDetachedProcess(shell: Shell, options: {
|
|
|
45
45
|
requestTimeoutMs?: number;
|
|
46
46
|
}): Promise<void>;
|
|
47
47
|
/**
|
|
48
|
-
* Poll a URL from
|
|
48
|
+
* Poll a URL from inside the sandbox until it answers 2xx/3xx or the budget runs out.
|
|
49
49
|
* Returns true when the subject is ready.
|
|
50
50
|
*/
|
|
51
51
|
export declare function probeUrl(shell: Shell, url: string, options: {
|