humanish 0.106.0 → 0.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -2
- package/ARCHITECTURE.md +17 -16
- package/CHANGELOG.md +24 -0
- package/CONTEXT.md +42 -39
- package/CONTRIBUTING.md +8 -6
- package/README.md +8 -3
- package/dist/actors/codex/app-server-client.js +2 -1
- package/dist/actors/codex/app-server-trace.d.ts +0 -1
- package/dist/actors/codex/app-server-trace.js +1 -3
- package/dist/actors/codex/app-server.js +2 -1
- package/dist/actors/codex/protocol-compat.d.ts +27 -0
- package/dist/actors/codex/protocol-compat.js +357 -0
- package/dist/actors/codex/protocol-contract.d.ts +61 -0
- package/dist/actors/codex/protocol-contract.js +471 -0
- package/dist/actors/codex/qualified-versions.d.ts +31 -4
- package/dist/actors/codex/qualified-versions.js +51 -6
- package/dist/actors/codex/restricted-executable.d.ts +24 -0
- package/dist/actors/codex/restricted-executable.js +97 -22
- package/dist/actors/codex/restricted-launch.d.ts +7 -1
- package/dist/actors/codex/restricted-launch.js +42 -3
- package/dist/actors/codex/restricted-notifications.d.ts +101 -0
- package/dist/actors/codex/restricted-notifications.js +277 -0
- package/dist/actors/codex/restricted-participant.d.ts +30 -0
- package/dist/actors/codex/restricted-participant.js +60 -2
- package/dist/actors/codex/restricted-policy.d.ts +9 -1
- package/dist/actors/codex/restricted-session.d.ts +14 -1
- package/dist/actors/codex/restricted-session.js +50 -17
- package/dist/actors/codex/restricted-transport.d.ts +29 -0
- package/dist/actors/codex/restricted-transport.js +139 -27
- package/dist/actors/codex/restricted-turn.d.ts +19 -4
- package/dist/actors/codex/restricted-turn.js +43 -30
- package/dist/actors/computer-use/actor.d.ts +1 -1
- package/dist/actors/computer-use/actor.js +4 -4
- package/dist/actors/computer-use/loop/backstop.js +1 -1
- package/dist/actors/computer-use/loop/ending.d.ts +2 -2
- package/dist/actors/computer-use/loop/ending.js +2 -2
- package/dist/actors/computer-use/loop/spend.d.ts +1 -1
- package/dist/actors/computer-use/loop/spend.js +3 -3
- package/dist/actors/computer-use/loop/trace.js +2 -2
- package/dist/actors/computer-use/loop/types.d.ts +14 -5
- package/dist/actors/computer-use/loop.js +4 -4
- package/dist/actors/computer-use/openai-provider.d.ts +1 -1
- package/dist/actors/computer-use/openai-provider.js +2 -2
- package/dist/actors/contract.d.ts +10 -8
- package/dist/actors/contract.js +7 -1
- package/dist/actors/local-agent/cli.js +1 -1
- package/dist/actors/scripted-browser/actor.d.ts +2 -2
- package/dist/actors/scripted-browser/journey.js +15 -4
- package/dist/actors/scripted-browser/steps.js +18 -0
- package/dist/actors/scripted-browser/types.d.ts +11 -1
- package/dist/actors/stop-conditions.js +1 -3
- package/dist/analysis/automatic-completion.d.ts +13 -8
- package/dist/analysis/automatic-completion.js +14 -8
- package/dist/analysis/automatic-config.d.ts +1 -1
- package/dist/analysis/automatic-config.js +2 -2
- package/dist/analysis/automatic.d.ts +10 -4
- package/dist/analysis/automatic.js +17 -13
- package/dist/analysis/diagnostics.d.ts +23 -0
- package/dist/analysis/diagnostics.js +112 -0
- package/dist/analysis/evidence-sources.js +2 -2
- package/dist/analysis/evidence.js +6 -6
- package/dist/analysis/execute.d.ts +7 -1
- package/dist/analysis/execute.js +39 -12
- package/dist/analysis/job.d.ts +8 -5
- package/dist/analysis/job.js +15 -14
- package/dist/analysis/load.d.ts +1 -1
- package/dist/analysis/load.js +5 -5
- package/dist/analysis/provider.d.ts +9 -1
- package/dist/analysis/restricted-codex.d.ts +2 -0
- package/dist/analysis/restricted-codex.js +10 -1
- package/dist/analysis/service.d.ts +2 -0
- package/dist/analysis/service.js +31 -12
- package/dist/analysis/sharing.d.ts +2 -2
- package/dist/analysis/sharing.js +5 -5
- package/dist/analysis/store-executions.d.ts +5 -5
- package/dist/analysis/store-executions.js +12 -12
- package/dist/analysis/store.d.ts +4 -4
- package/dist/analysis/store.js +13 -13
- package/dist/cli/commands/analysis-signals.d.ts +2 -1
- package/dist/cli/commands/analysis-signals.js +4 -1
- package/dist/cli/commands/analyze.js +4 -2
- package/dist/cli/commands/comms.js +8 -1
- package/dist/cli/commands/lab-route-computer-use.d.ts +0 -2
- package/dist/cli/commands/lab-route-computer-use.js +26 -14
- package/dist/cli/commands/lab-route-preview.d.ts +1 -3
- package/dist/cli/commands/lab-route-preview.js +3 -4
- package/dist/cli/commands/lab-route-run.d.ts +6 -4
- package/dist/cli/commands/lab-route-run.js +6 -2
- package/dist/cli/commands/lab-route-scripted.d.ts +0 -2
- package/dist/cli/commands/lab-route-scripted.js +0 -1
- package/dist/cli/commands/lab-route-shared-world.d.ts +0 -2
- package/dist/cli/commands/lab-route-shared-world.js +0 -1
- package/dist/cli/commands/lab-route-terminal.d.ts +0 -2
- package/dist/cli/commands/lab-route-terminal.js +0 -1
- package/dist/cli/commands/lab-run.js +76 -45
- package/dist/cli/commands/lab-scorer.d.ts +0 -2
- package/dist/cli/commands/lab.js +12 -6
- package/dist/cli/commands/observe.js +22 -0
- package/dist/cli/commands/run-signals.d.ts +30 -0
- package/dist/cli/commands/run-signals.js +146 -0
- package/dist/cli/commands/runs.js +10 -8
- package/dist/cli/commands/watch.js +12 -10
- package/dist/cli/doctor.d.ts +3 -0
- package/dist/cli/doctor.js +10 -2
- package/dist/cli/io.d.ts +5 -4
- package/dist/cli/io.js +12 -8
- package/dist/cli/program.js +3 -3
- package/dist/cli/renamed-options.d.ts +11 -0
- package/dist/cli/renamed-options.js +18 -0
- package/dist/cli/telemetry.d.ts +2 -2
- package/dist/cli/telemetry.js +1 -1
- package/dist/comms/capture-surface.d.ts +1 -1
- package/dist/comms/catch-host.d.ts +1 -1
- package/dist/comms/connections.js +4 -4
- package/dist/comms/external-evidence.d.ts +27 -0
- package/dist/comms/external-evidence.js +93 -0
- package/dist/comms/lease-store.js +7 -7
- package/dist/comms/types.js +1 -1
- package/dist/evidence/browser-hygiene.d.ts +1 -1
- package/dist/evidence/browser-hygiene.js +1 -1
- package/dist/evidence/redaction.js +1 -1
- package/dist/evidence/secret-scrub.d.ts +9 -0
- package/dist/evidence/secret-scrub.js +96 -0
- package/dist/feedback/draft.js +7 -9
- package/dist/feedback/export-bundle.js +4 -4
- package/dist/feedback/export.js +9 -9
- package/dist/feedback/feedback.d.ts +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.js +3 -6
- package/dist/keys/key-resolution.d.ts +3 -1
- package/dist/keys/key-resolution.js +18 -16
- package/dist/lab/adapter-extension.d.ts +28 -6
- package/dist/lab/adapter-extension.js +65 -126
- package/dist/lab/adapter-scorer-loader.d.ts +25 -5
- package/dist/lab/adapter-scorer-loader.js +24 -0
- package/dist/lab/composition-rules.d.ts +2 -0
- package/dist/lab/composition-rules.js +35 -26
- package/dist/lab/config.js +28 -26
- package/dist/lab/device-presets.d.ts +2 -2
- package/dist/lab/discover.js +1 -3
- package/dist/lab/doctor.d.ts +44 -9
- package/dist/lab/doctor.js +149 -41
- package/dist/lab/init-plan.js +1 -3
- package/dist/lab/keys.js +1 -1
- package/dist/lab/lab-deps.d.ts +85 -0
- package/dist/lab/lab-deps.js +4 -0
- package/dist/lab/parse/actors.js +8 -7
- package/dist/lab/parse/comms.js +3 -2
- package/dist/lab/parse/execution.js +3 -2
- package/dist/lab/parse/subject-state.js +2 -1
- package/dist/lab/parse/subject.js +2 -1
- package/dist/lab/parse/values.d.ts +0 -1
- package/dist/lab/parse/values.js +0 -3
- package/dist/lab/persona-resolve.d.ts +3 -3
- package/dist/lab/persona-resolve.js +4 -4
- package/dist/lab/persona.js +1 -3
- package/dist/lab/plan-base.d.ts +6 -2
- package/dist/lab/plan-base.js +22 -7
- package/dist/lab/plan-participants.d.ts +5 -5
- package/dist/lab/plan-participants.js +2 -2
- package/dist/lab/plan-types.d.ts +33 -7
- package/dist/lab/plan.d.ts +3 -11
- package/dist/lab/plan.js +18 -42
- package/dist/lab/preflight-result.js +0 -2
- package/dist/lab/preflight.d.ts +0 -3
- package/dist/lab/preflight.js +1 -1
- package/dist/lab/requirements.d.ts +20 -0
- package/dist/lab/requirements.js +54 -0
- package/dist/lab/route-inputs.d.ts +23 -12
- package/dist/lab/route-inputs.js +48 -51
- package/dist/lab/routing.d.ts +19 -24
- package/dist/lab/routing.js +14 -47
- package/dist/lab/run-lab-events.d.ts +6 -11
- package/dist/lab/run-lab-events.js +3 -11
- package/dist/lab/run-lab-homes.d.ts +64 -0
- package/dist/lab/run-lab-homes.js +3 -0
- package/dist/lab/run-lab-options.d.ts +12 -66
- package/dist/lab/run-lab-options.js +45 -275
- package/dist/lab/summary.d.ts +9 -4
- package/dist/lab/summary.js +15 -8
- package/dist/lab/types.d.ts +132 -132
- package/dist/lab/validation.d.ts +15 -15
- package/dist/lab/validation.js +28 -28
- package/dist/lab/warnings.js +20 -19
- package/dist/observer/artifact.d.ts +1 -1
- package/dist/observer/artifact.js +3 -3
- package/dist/observer/data.js +2 -2
- package/dist/observer/render.js +2 -2
- package/dist/observer/run-routes.d.ts +1 -1
- package/dist/observer/run-routes.js +5 -5
- package/dist/observer/serve.d.ts +17 -0
- package/dist/observer/serve.js +34 -3
- package/dist/observer-app.html +1 -1
- package/dist/routes/computer-use/bundle-parts.d.ts +1 -1
- package/dist/routes/computer-use/bundle-parts.js +10 -3
- package/dist/routes/computer-use/bundle.d.ts +4 -11
- package/dist/routes/computer-use/bundle.js +9 -15
- package/dist/routes/computer-use/diagnostics.d.ts +1 -1
- package/dist/routes/computer-use/diagnostics.js +1 -1
- package/dist/routes/computer-use/e2b-desktop/comms.d.ts +10 -10
- package/dist/routes/computer-use/e2b-desktop/comms.js +11 -14
- package/dist/routes/computer-use/e2b-desktop/desktop.d.ts +2 -2
- package/dist/routes/computer-use/e2b-desktop/desktop.js +4 -7
- package/dist/routes/computer-use/e2b-desktop/fidelity.d.ts +13 -13
- package/dist/routes/computer-use/e2b-desktop/fidelity.js +11 -11
- package/dist/routes/computer-use/e2b-desktop/prepare.d.ts +3 -3
- package/dist/routes/computer-use/e2b-desktop/prepare.js +33 -36
- package/dist/routes/computer-use/e2b-desktop/start.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/start.js +24 -23
- package/dist/routes/computer-use/e2b-desktop/state.d.ts +5 -4
- package/dist/routes/computer-use/e2b-desktop/state.js +5 -3
- package/dist/routes/computer-use/e2b-desktop/teardown.d.ts +1 -1
- package/dist/routes/computer-use/e2b-desktop/teardown.js +29 -17
- package/dist/routes/computer-use/external-comms.d.ts +4 -4
- package/dist/routes/computer-use/external-comms.js +19 -43
- package/dist/routes/computer-use/fanout-bundle.d.ts +3 -3
- package/dist/routes/computer-use/fanout-bundle.js +25 -29
- package/dist/routes/computer-use/{fanout-lanes.js → fanout-records.js} +25 -19
- package/dist/routes/computer-use/in-process-desktop.d.ts +3 -10
- package/dist/routes/computer-use/in-process-desktop.js +3 -9
- package/dist/routes/computer-use/live-flush.d.ts +7 -5
- package/dist/routes/computer-use/live-flush.js +19 -27
- package/dist/routes/computer-use/{run-lanes.js → live-phase.js} +14 -13
- package/dist/routes/computer-use/local-tree-pack.d.ts +3 -3
- package/dist/routes/computer-use/local-tree-pack.js +4 -5
- package/dist/routes/computer-use/local-vm.d.ts +11 -8
- package/dist/routes/computer-use/local-vm.js +39 -66
- package/dist/routes/computer-use/participant-desktop.d.ts +8 -23
- package/dist/routes/computer-use/participant-desktop.js +5 -25
- package/dist/routes/computer-use/{lanes.d.ts → participant-execution.d.ts} +10 -10
- package/dist/routes/computer-use/{lanes.js → participant-execution.js} +35 -22
- package/dist/routes/computer-use/participant-facts.d.ts +7 -1
- package/dist/routes/computer-use/participant-facts.js +12 -1
- package/dist/routes/computer-use/participant-model.d.ts +19 -11
- package/dist/routes/computer-use/participant-model.js +58 -33
- package/dist/routes/computer-use/participant-prompt.d.ts +3 -3
- package/dist/routes/computer-use/participant-prompt.js +4 -4
- package/dist/routes/computer-use/participant-runs.d.ts +6 -6
- package/dist/routes/computer-use/participant-runs.js +8 -8
- package/dist/routes/computer-use/plan.d.ts +21 -29
- package/dist/routes/computer-use/plan.js +59 -65
- package/dist/routes/computer-use/preflight.d.ts +6 -11
- package/dist/routes/computer-use/preflight.js +26 -18
- package/dist/routes/computer-use/rerun-selection.js +10 -6
- package/dist/routes/computer-use/result.d.ts +1 -1
- package/dist/routes/computer-use/result.js +40 -30
- package/dist/routes/computer-use/route.d.ts +3 -4
- package/dist/routes/computer-use/route.js +21 -19
- package/dist/routes/computer-use/self-report.d.ts +2 -2
- package/dist/routes/computer-use/self-report.js +4 -4
- package/dist/routes/computer-use/setup.d.ts +8 -17
- package/dist/routes/computer-use/setup.js +98 -86
- package/dist/routes/computer-use/single-bundle.d.ts +8 -11
- package/dist/routes/computer-use/single-bundle.js +20 -25
- package/dist/routes/computer-use/subject-projection.d.ts +5 -7
- package/dist/routes/computer-use/subject-projection.js +20 -19
- package/dist/routes/computer-use/types.d.ts +169 -211
- package/dist/routes/computer-use/types.js +13 -6
- package/dist/routes/preview.js +0 -1
- package/dist/routes/scripted/bundle.d.ts +3 -6
- package/dist/routes/scripted/bundle.js +11 -16
- package/dist/routes/scripted/plan.d.ts +5 -7
- package/dist/routes/scripted/plan.js +6 -4
- package/dist/routes/scripted/result.d.ts +4 -1
- package/dist/routes/scripted/result.js +10 -6
- package/dist/routes/scripted/route.js +10 -11
- package/dist/routes/scripted/scenario.d.ts +1 -1
- package/dist/routes/scripted/scenario.js +1 -1
- package/dist/routes/scripted/setup.d.ts +3 -2
- package/dist/routes/scripted/setup.js +22 -21
- package/dist/routes/scripted/subject.d.ts +8 -3
- package/dist/routes/scripted/subject.js +11 -6
- package/dist/routes/scripted/surface-records.js +1 -1
- package/dist/routes/scripted/surface-sessions.d.ts +2 -2
- package/dist/routes/scripted/surface-sessions.js +4 -4
- package/dist/routes/scripted/types.d.ts +19 -36
- package/dist/routes/scripted/types.js +1 -2
- package/dist/routes/shared-world/{seat-records.js → bundle-records.js} +8 -8
- package/dist/routes/shared-world/bundle.d.ts +2 -2
- package/dist/routes/shared-world/bundle.js +22 -26
- package/dist/routes/shared-world/checkpoints.d.ts +4 -4
- package/dist/routes/shared-world/checkpoints.js +4 -4
- package/dist/routes/shared-world/comms.d.ts +5 -4
- package/dist/routes/shared-world/comms.js +28 -41
- package/dist/routes/shared-world/external-public.d.ts +5 -5
- package/dist/routes/shared-world/external-public.js +19 -20
- package/dist/routes/shared-world/handoff.d.ts +4 -4
- package/dist/routes/shared-world/handoff.js +50 -50
- package/dist/routes/shared-world/lobby-code.d.ts +5 -5
- package/dist/routes/shared-world/lobby-code.js +13 -13
- package/dist/routes/shared-world/{seats.d.ts → participant-specs.d.ts} +8 -6
- package/dist/routes/shared-world/{seats.js → participant-specs.js} +46 -51
- package/dist/routes/shared-world/plan.d.ts +2 -6
- package/dist/routes/shared-world/plan.js +1 -2
- package/dist/routes/shared-world/provenance.d.ts +4 -4
- package/dist/routes/shared-world/provenance.js +4 -4
- package/dist/routes/shared-world/provisioned.d.ts +3 -2
- package/dist/routes/shared-world/provisioned.js +48 -41
- package/dist/routes/shared-world/result.js +31 -19
- package/dist/routes/shared-world/route.js +37 -41
- package/dist/routes/shared-world/setup.d.ts +5 -4
- package/dist/routes/shared-world/setup.js +12 -14
- package/dist/routes/shared-world/types.d.ts +53 -126
- package/dist/routes/shared-world/types.js +2 -2
- package/dist/routes/terminal/adapter.d.ts +8 -8
- package/dist/routes/terminal/adapter.js +28 -125
- package/dist/routes/terminal/bundle.d.ts +7 -12
- package/dist/routes/terminal/bundle.js +24 -34
- package/dist/routes/terminal/credentials.d.ts +2 -2
- package/dist/routes/terminal/credentials.js +16 -16
- package/dist/routes/terminal/dry-run.d.ts +1 -1
- package/dist/routes/terminal/dry-run.js +9 -11
- package/dist/routes/terminal/encoding.d.ts +1 -1
- package/dist/routes/terminal/encoding.js +2 -2
- package/dist/routes/terminal/ledger.d.ts +6 -6
- package/dist/routes/terminal/ledger.js +9 -9
- package/dist/routes/terminal/live-finish.d.ts +1 -2
- package/dist/routes/terminal/live-finish.js +21 -20
- package/dist/routes/terminal/live-sandbox.d.ts +4 -2
- package/dist/routes/terminal/live-sandbox.js +25 -21
- package/dist/routes/terminal/participant-text.d.ts +23 -0
- package/dist/routes/terminal/participant-text.js +165 -0
- package/dist/routes/terminal/plan.d.ts +2 -6
- package/dist/routes/terminal/plan.js +13 -9
- package/dist/routes/terminal/recorder.d.ts +6 -1
- package/dist/routes/terminal/recorder.js +12 -4
- package/dist/routes/terminal/result.js +4 -4
- package/dist/routes/terminal/route.js +26 -26
- package/dist/routes/terminal/runtime.d.ts +3 -2
- package/dist/routes/terminal/runtime.js +3 -3
- package/dist/routes/terminal/sandbox.d.ts +5 -3
- package/dist/routes/terminal/sandbox.js +13 -16
- package/dist/routes/terminal/session.js +16 -14
- package/dist/routes/terminal/token-usage.js +5 -5
- package/dist/routes/terminal/trace.d.ts +5 -8
- package/dist/routes/terminal/trace.js +9 -64
- package/dist/routes/terminal/types.d.ts +85 -93
- package/dist/routes/terminal/types.js +9 -4
- package/dist/run/active-runs.d.ts +13 -0
- package/dist/run/active-runs.js +12 -0
- package/dist/run/bundle-shape.d.ts +2 -1
- package/dist/run/bundle-shape.js +4 -4
- package/dist/run/bundle.d.ts +63 -56
- package/dist/run/bundle.js +9 -8
- package/dist/run/cost-summary.js +3 -2
- package/dist/run/costs.d.ts +6 -6
- package/dist/run/costs.js +10 -10
- package/dist/run/detail.d.ts +5 -5
- package/dist/run/detail.js +6 -6
- package/dist/run/dry-run.js +5 -12
- package/dist/run/{study-files.d.ts → evidence-files.d.ts} +4 -4
- package/dist/run/{study-files.js → evidence-files.js} +5 -5
- package/dist/run/feedback-shape.js +1 -1
- package/dist/run/judge.d.ts +16 -4
- package/dist/run/judge.js +24 -7
- package/dist/run/locate.d.ts +2 -0
- package/dist/run/locate.js +3 -1
- package/dist/run/outcomes.d.ts +3 -3
- package/dist/run/outcomes.js +3 -3
- package/dist/run/participant-records.d.ts +2 -2
- package/dist/run/participant-records.js +2 -2
- package/dist/run/paths.js +1 -1
- package/dist/run/pricing.d.ts +19 -9
- package/dist/run/pricing.js +30 -18
- package/dist/run/projection.d.ts +13 -13
- package/dist/run/projection.js +8 -8
- package/dist/run/reclaim.d.ts +7 -1
- package/dist/run/reclaim.js +24 -4
- package/dist/run/results.d.ts +1 -1
- package/dist/run/run-index.d.ts +1 -1
- package/dist/run/run-index.js +11 -11
- package/dist/run/run.d.ts +4 -2
- package/dist/run/run.js +9 -5
- package/dist/run/sandbox-receipts.d.ts +4 -4
- package/dist/run/sandbox-receipts.js +4 -4
- package/dist/run/shared-world-evidence.d.ts +47 -47
- package/dist/run/shared-world-shape.d.ts +3 -3
- package/dist/run/shared-world-shape.js +11 -11
- package/dist/run/stats.d.ts +5 -5
- package/dist/run/stats.js +8 -8
- package/dist/run/status.d.ts +16 -6
- package/dist/run/status.js +31 -8
- package/dist/run/streams.d.ts +26 -19
- package/dist/run/terminal-contract.d.ts +5 -5
- package/dist/run/terminal-contract.js +4 -4
- package/dist/run/transient-comms-secrets.d.ts +5 -0
- package/dist/run/transient-comms-secrets.js +12 -0
- package/dist/run-lab.d.ts +36 -34
- package/dist/run-lab.js +41 -37
- package/dist/subject/desktop-cli.d.ts +1 -1
- package/dist/subject/desktop-cli.js +1 -1
- package/dist/subject/local-tree-archive.d.ts +1 -1
- package/dist/subject/local-tree-archive.js +4 -4
- package/dist/subject/local-tree.d.ts +2 -2
- package/dist/subject/local-tree.js +1 -1
- package/dist/subject/node-bootstrap.d.ts +1 -1
- package/dist/subject/node-bootstrap.js +4 -4
- package/dist/subject/runtime.js +5 -5
- package/dist/subject/serve.js +1 -1
- package/dist/subject/steps.d.ts +4 -4
- package/dist/subject/steps.js +5 -5
- package/dist/substrates/desktop-session.d.ts +2 -0
- package/dist/substrates/e2b/cdp-probe.d.ts +2 -2
- package/dist/substrates/e2b/cdp-probe.js +1 -1
- package/dist/substrates/e2b/desktop-browser.d.ts +3 -3
- package/dist/substrates/e2b/desktop-browser.js +4 -4
- package/dist/substrates/e2b/desktop-cdp.d.ts +7 -7
- package/dist/substrates/e2b/desktop-cdp.js +4 -4
- package/dist/substrates/e2b/desktop-geometry.d.ts +4 -4
- package/dist/substrates/e2b/desktop-geometry.js +3 -3
- package/dist/substrates/e2b/desktop-media.js +2 -2
- package/dist/substrates/e2b/sandbox.d.ts +2 -0
- package/dist/substrates/e2b/sandbox.js +22 -8
- package/dist/substrates/e2b/sdk.d.ts +12 -1
- package/dist/substrates/e2b/sdk.js +30 -9
- package/dist/substrates/local/runtime-host.d.ts +2 -0
- package/dist/substrates/local/runtime-host.js +6 -0
- package/dist/tui/actions.d.ts +7 -5
- package/dist/tui/actions.js +18 -9
- package/dist/tui-app.js +42 -42
- package/dist/verify/actor.d.ts +10 -10
- package/dist/verify/actor.js +15 -15
- package/dist/verify/artifacts.d.ts +1 -1
- package/dist/verify/artifacts.js +3 -3
- package/dist/verify/costs.d.ts +2 -2
- package/dist/verify/costs.js +2 -2
- package/dist/verify/liveness.d.ts +1 -1
- package/dist/verify/liveness.js +4 -1
- package/dist/verify/rerun.d.ts +1 -1
- package/dist/verify/rerun.js +1 -1
- package/dist/verify/shared-world.js +2 -2
- package/dist/verify/verify.js +6 -6
- package/docs/README.md +1 -1
- package/docs/architecture/actor-contract.md +60 -22
- package/docs/architecture/desktop-sessions.md +9 -9
- package/docs/architecture/external-public-shared-world.md +5 -0
- package/docs/architecture/observer.md +4 -4
- package/docs/architecture/restricted-codex-analysis.md +40 -4
- package/docs/architecture/state-driven-executor.md +4 -5
- package/docs/architecture/task-protocol-support.md +3 -5
- package/docs/architecture/{terminal-product-lane.md → terminal-product-route.md} +24 -16
- package/docs/contracts/run-bundle.md +10 -8
- package/docs/contracts/schemas.md +109 -53
- package/docs/contracts/study-analysis.md +24 -0
- package/docs/decisions/0004-participant-desktops-stay-in-the-route.md +2 -1
- package/docs/product/automatic-analysis.md +1 -0
- package/docs/ramp/README.md +2 -1
- package/package.json +4 -4
- package/skills/humanish/SKILL.md +3 -2
- package/skills/humanish/agents/openai.yaml +1 -1
- package/dist/deprecated.d.ts +0 -90
- package/dist/deprecated.js +0 -106
- package/dist/lab/bag-overrides.d.ts +0 -18
- package/dist/lab/bag-overrides.js +0 -121
- package/dist/routes/computer-use/legacy-lane-spec.d.ts +0 -62
- package/dist/routes/computer-use/legacy-lane-spec.js +0 -39
- /package/dist/routes/computer-use/{fanout-lanes.d.ts → fanout-records.d.ts} +0 -0
- /package/dist/routes/computer-use/{run-lanes.d.ts → live-phase.d.ts} +0 -0
- /package/dist/routes/shared-world/{seat-records.d.ts → bundle-records.d.ts} +0 -0
|
@@ -50,39 +50,72 @@ export function restrictedCodexNpmTarget(platform, arch) {
|
|
|
50
50
|
/** Resolve PATH without running a shell. The npm launcher is resolved to its
|
|
51
51
|
* native optional package so cleanup owns the real app-server child. */
|
|
52
52
|
export async function resolveExecutable(options, env) {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
const located = await locateExecutable(options, env);
|
|
54
|
+
// The stop carries only its code; doctor asks refusedCodexExecutable for the file and reason.
|
|
55
|
+
if ("refused" in located)
|
|
56
|
+
throw new RestrictedCodexStop("codex_unavailable");
|
|
57
|
+
return located.file;
|
|
58
|
+
}
|
|
59
|
+
/** The `codex` resolveExecutable turns down and why, or undefined when it finds one to run. */
|
|
60
|
+
export async function refusedCodexExecutable(env, options = {}) {
|
|
61
|
+
const located = await locateExecutable(options, env);
|
|
62
|
+
return "refused" in located ? located.refused : undefined;
|
|
63
|
+
}
|
|
64
|
+
/** The first executable `codex` on `PATH`, as resolveExecutable picks it. */
|
|
65
|
+
async function firstCodexOnPath(env) {
|
|
66
|
+
for (const directory of (env.PATH ?? "")
|
|
67
|
+
.split(path.delimiter)
|
|
68
|
+
.filter((entry) => path.isAbsolute(entry))) {
|
|
69
|
+
const candidate = path.join(directory, "codex");
|
|
70
|
+
try {
|
|
71
|
+
await access(candidate, constants.X_OK);
|
|
72
|
+
return candidate;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
/* Continue PATH. */
|
|
68
76
|
}
|
|
69
77
|
}
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The `codex` resolveExecutable picks from `PATH`, runnable or not, and the file it resolves to:
|
|
82
|
+
* what decides the command that replaces it. Undefined when `PATH` has none that resolves.
|
|
83
|
+
*/
|
|
84
|
+
export async function foundCodexExecutable(env) {
|
|
85
|
+
const selected = await firstCodexOnPath(env);
|
|
86
|
+
if (selected === undefined)
|
|
87
|
+
return undefined;
|
|
88
|
+
try {
|
|
89
|
+
return { path: selected, resolved: await realpath(selected) };
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function locateExecutable(options, env) {
|
|
96
|
+
const platform = options.platform ?? process.platform, arch = options.arch ?? process.arch;
|
|
97
|
+
const selected = options.executable ?? (await firstCodexOnPath(env));
|
|
98
|
+
const refused = (reason, file) => ({
|
|
99
|
+
refused: { ...(file === undefined ? {} : { path: file }), reason },
|
|
100
|
+
});
|
|
101
|
+
if (selected === undefined)
|
|
102
|
+
return refused("no executable `codex` is on PATH");
|
|
103
|
+
if (!path.isAbsolute(selected))
|
|
104
|
+
return refused("it is not an absolute path", selected);
|
|
72
105
|
let resolved;
|
|
73
106
|
try {
|
|
74
107
|
resolved = await realpath(selected);
|
|
75
108
|
}
|
|
76
109
|
catch {
|
|
77
|
-
|
|
110
|
+
return refused("it does not resolve to a file", selected);
|
|
78
111
|
}
|
|
79
112
|
if (await isNativeExecutable(resolved, platform))
|
|
80
|
-
return resolved;
|
|
113
|
+
return { file: resolved };
|
|
81
114
|
if (path.basename(resolved) === "codex.js" && path.basename(path.dirname(resolved)) === "bin") {
|
|
82
115
|
const packageRoot = path.dirname(path.dirname(resolved));
|
|
83
116
|
const target = restrictedCodexNpmTarget(platform, arch);
|
|
84
117
|
if (!target)
|
|
85
|
-
|
|
118
|
+
return refused(`the npm package has no native build for ${platform}-${arch}`, resolved);
|
|
86
119
|
const { triple, packageName: nativePackage } = target;
|
|
87
120
|
const candidates = [];
|
|
88
121
|
try {
|
|
@@ -97,10 +130,52 @@ export async function resolveExecutable(options, env) {
|
|
|
97
130
|
candidates.push(path.join(packageRoot, "vendor", triple, "bin", "codex"));
|
|
98
131
|
for (const candidate of candidates) {
|
|
99
132
|
if (await isNativeExecutable(candidate, platform))
|
|
100
|
-
return realpath(candidate);
|
|
133
|
+
return { file: await realpath(candidate) };
|
|
134
|
+
}
|
|
135
|
+
return refused(`the npm package's native ${nativePackage} build is missing`, resolved);
|
|
136
|
+
}
|
|
137
|
+
return refused("it is neither a native Codex executable nor the @openai/codex npm launcher", resolved);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Writes this release's app-server schema (`app-server generate-json-schema --experimental`) into
|
|
141
|
+
* `out`, for the protocol check. False when the release exits without one. Bounded like the
|
|
142
|
+
* version check: 15 seconds, and a few kilobytes of output, which it does not otherwise read.
|
|
143
|
+
*/
|
|
144
|
+
export async function generateProtocolSchema(file, env, cwd, out, spawnFn, deadline) {
|
|
145
|
+
deadline.check();
|
|
146
|
+
const owned = ownCodexProcess(spawnFn(file, ["app-server", "generate-json-schema", "--experimental", "--out", out], {
|
|
147
|
+
cwd,
|
|
148
|
+
env,
|
|
149
|
+
detached: false,
|
|
150
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
151
|
+
}));
|
|
152
|
+
let bytes = 0, exitCode = null;
|
|
153
|
+
const timer = setTimeout(() => deadline.stop("timeout"), 15_000);
|
|
154
|
+
const count = (chunk) => {
|
|
155
|
+
bytes += chunk.length;
|
|
156
|
+
if (bytes > 65_536)
|
|
157
|
+
deadline.stop("response_too_large");
|
|
158
|
+
};
|
|
159
|
+
owned.child.on("error", () => deadline.stop("codex_unavailable"));
|
|
160
|
+
owned.child.stdin.on("error", () => deadline.stop("codex_unavailable"));
|
|
161
|
+
owned.child.stdout.on("data", count);
|
|
162
|
+
owned.child.stderr.on("data", count);
|
|
163
|
+
owned.child.on("exit", (code) => {
|
|
164
|
+
exitCode = code;
|
|
165
|
+
});
|
|
166
|
+
try {
|
|
167
|
+
owned.child.stdin.end();
|
|
168
|
+
await deadline.wait(owned.closed);
|
|
169
|
+
return exitCode === 0;
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
clearTimeout(timer);
|
|
173
|
+
if (!(await closeOwnedCodexProcess(owned))) {
|
|
174
|
+
retainUnclosedChild(owned.closed);
|
|
175
|
+
// oxlint-disable-next-line no-unsafe-finally -- a Codex process that did not close invalidates the check
|
|
176
|
+
throw new RestrictedCodexStop("codex_cleanup_failed");
|
|
101
177
|
}
|
|
102
178
|
}
|
|
103
|
-
throw new RestrictedCodexStop("codex_unavailable");
|
|
104
179
|
}
|
|
105
180
|
/** Returns the detected release after checking it against the admitted list. */
|
|
106
181
|
export async function checkVersion(file, env, cwd, spawnFn, deadline, admitted, expected) {
|
|
@@ -46,6 +46,12 @@ export interface LaunchState {
|
|
|
46
46
|
resolvedModel: string | undefined;
|
|
47
47
|
authentication: "chatgpt-account" | "api-key" | undefined;
|
|
48
48
|
cliVersion: string | undefined;
|
|
49
|
+
/** Notification methods this humanish does not know that carried no item, by count. */
|
|
50
|
+
unknownNotifications: Map<string, number>;
|
|
51
|
+
/** How the release's schema differs from the fields humanish reads; set when that refuses. */
|
|
52
|
+
protocolIncompatibilities: string[] | undefined;
|
|
53
|
+
/** Schema values beyond the baseline, recorded at launch. */
|
|
54
|
+
protocolAdditions: string[] | undefined;
|
|
49
55
|
}
|
|
50
56
|
/** An admitted value, or the refusal a launch stops with. */
|
|
51
57
|
export type Admission<T> = {
|
|
@@ -112,5 +118,5 @@ export declare function admitMcpStatus(reply: Record<string, unknown>): Admissio
|
|
|
112
118
|
* The session's one-time launch: a private home, the auth link, the version check and the spawn,
|
|
113
119
|
* then initialize, config, account, thread and MCP admission.
|
|
114
120
|
*/
|
|
115
|
-
export declare function launchAdmittedAppServer(settings: LaunchSettings, state: LaunchState, request: RestrictedCodexRequest, deadline: RestrictedCodexDeadline, frameLimit: number, enter: (phase: CuaProviderFailurePhase) => void): Promise<RestrictedCodexTransport>;
|
|
121
|
+
export declare function launchAdmittedAppServer(settings: LaunchSettings, state: LaunchState, request: RestrictedCodexRequest, deadline: RestrictedCodexDeadline, frameLimit: number, enter: (phase: CuaProviderFailurePhase) => void, install: (transport: RestrictedCodexTransport) => void): Promise<RestrictedCodexTransport>;
|
|
116
122
|
export {};
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
// none of them touches the session. launchAdmittedAppServer sends the requests in order, stops on
|
|
5
5
|
// the first refusal, and records each piece of state as soon as it exists so the session's
|
|
6
6
|
// teardown (restricted-session.ts) cleans up a launch that fails partway.
|
|
7
|
-
import { chmod, mkdir, mkdtemp, realpath, stat, symlink, writeFile } from "node:fs/promises";
|
|
7
|
+
import { chmod, mkdir, mkdtemp, realpath, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
8
8
|
import { homedir, tmpdir } from "node:os";
|
|
9
9
|
import path from "node:path";
|
|
10
|
-
import { checkVersion, childEnvironment, resolveExecutable } from "./restricted-executable.js";
|
|
10
|
+
import { checkVersion, childEnvironment, generateProtocolSchema, resolveExecutable, } from "./restricted-executable.js";
|
|
11
|
+
import { checkProtocol, loadProtocolSchema } from "./protocol-compat.js";
|
|
12
|
+
import { protocolContract } from "./protocol-contract.js";
|
|
11
13
|
import { admitsRestrictedCodexConfig, admitsRestrictedCodexThread, codexRecord, restrictedCodexConfig, } from "./restricted-policy.js";
|
|
12
14
|
import { RestrictedCodexDeadline, RestrictedCodexStop, RestrictedCodexTransport, ownCodexProcess, } from "./restricted-transport.js";
|
|
13
15
|
/** The admitted value; a refusal stops the launch. */
|
|
@@ -114,6 +116,37 @@ export function admitMcpStatus(reply) {
|
|
|
114
116
|
return { refusal: "codex_unsafe_configuration" };
|
|
115
117
|
return { value: undefined };
|
|
116
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* The release's own app-server schema against the fields humanish reads and sends
|
|
121
|
+
* (protocol-contract.ts), generated into the private work directory on every launch. A change
|
|
122
|
+
* there refuses as codex_incompatible_release; a value beyond the baseline is recorded when the
|
|
123
|
+
* launch is admitted. Reading the schema waits on the deadline; a stop leaves the directory to
|
|
124
|
+
* the session's teardown, which removes the whole work directory.
|
|
125
|
+
*/
|
|
126
|
+
async function admitProtocol(file, env, state, spawnFn, deadline, host) {
|
|
127
|
+
const directory = path.join(state.work, "schema");
|
|
128
|
+
const generated = await generateProtocolSchema(file, env, state.cwd, directory, spawnFn, deadline);
|
|
129
|
+
const schema = generated
|
|
130
|
+
? await deadline.wait(loadProtocolSchema(directory).catch(() => undefined))
|
|
131
|
+
: undefined;
|
|
132
|
+
const result = schema === undefined
|
|
133
|
+
? {
|
|
134
|
+
incompatibilities: [
|
|
135
|
+
generated
|
|
136
|
+
? "its generated app-server schema could not be read"
|
|
137
|
+
: "it did not generate an app-server schema",
|
|
138
|
+
],
|
|
139
|
+
additions: [],
|
|
140
|
+
}
|
|
141
|
+
: checkProtocol(schema, protocolContract(host));
|
|
142
|
+
await rm(directory, { recursive: true, force: true });
|
|
143
|
+
deadline.check();
|
|
144
|
+
if (result.incompatibilities.length > 0) {
|
|
145
|
+
state.protocolIncompatibilities = result.incompatibilities;
|
|
146
|
+
throw new RestrictedCodexStop("codex_incompatible_release");
|
|
147
|
+
}
|
|
148
|
+
state.protocolAdditions = result.additions;
|
|
149
|
+
}
|
|
117
150
|
/** The host's Codex auth.json, which a private home links to instead of copying. */
|
|
118
151
|
async function hostAuthFile(options, sourceEnv) {
|
|
119
152
|
const authHome = options.authHome ?? sourceEnv.CODEX_HOME ?? path.join(sourceEnv.HOME ?? homedir(), ".codex");
|
|
@@ -133,7 +166,7 @@ async function hostAuthFile(options, sourceEnv) {
|
|
|
133
166
|
* The session's one-time launch: a private home, the auth link, the version check and the spawn,
|
|
134
167
|
* then initialize, config, account, thread and MCP admission.
|
|
135
168
|
*/
|
|
136
|
-
export async function launchAdmittedAppServer(settings, state, request, deadline, frameLimit, enter) {
|
|
169
|
+
export async function launchAdmittedAppServer(settings, state, request, deadline, frameLimit, enter, install) {
|
|
137
170
|
const { options, sourceEnv, participant, operatorAuth, reasoningEffort, spawnFn } = settings;
|
|
138
171
|
const file = await resolveExecutable(options, sourceEnv);
|
|
139
172
|
deadline.check();
|
|
@@ -147,6 +180,10 @@ export async function launchAdmittedAppServer(settings, state, request, deadline
|
|
|
147
180
|
await mkdir(directory, { mode: 0o700 });
|
|
148
181
|
const env = childEnvironment(sourceEnv, home, state.scratch);
|
|
149
182
|
state.cliVersion = await checkVersion(file, env, state.cwd, spawnFn, deadline, settings.admittedVersions, options.cliVersion);
|
|
183
|
+
await admitProtocol(file, env, state, spawnFn, deadline, {
|
|
184
|
+
reasoningEffort,
|
|
185
|
+
platform: settings.platform,
|
|
186
|
+
});
|
|
150
187
|
const configMode = {
|
|
151
188
|
participantCodeMode: participant !== undefined,
|
|
152
189
|
reasoningEffort,
|
|
@@ -173,6 +210,8 @@ export async function launchAdmittedAppServer(settings, state, request, deadline
|
|
|
173
210
|
stdio: ["pipe", "pipe", "pipe"],
|
|
174
211
|
}));
|
|
175
212
|
const launched = new RestrictedCodexTransport(owned, deadline, frameLimit);
|
|
213
|
+
// The session's handlers check output from the first byte, before initialize returns.
|
|
214
|
+
install(launched);
|
|
176
215
|
state.transport = launched;
|
|
177
216
|
enter("initialize");
|
|
178
217
|
const initialize = await launched.rpc("initialize", {
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { type RestrictedCodexAnalysisErrorCode } from "./restricted-policy.js";
|
|
2
|
+
import { type RestrictedCodexDeadline, type RestrictedCodexTransport } from "./restricted-transport.js";
|
|
3
|
+
/** Raw response item types an analyst turn may produce. */
|
|
4
|
+
export declare const ANALYST_RAW_ITEM_TYPES: readonly string[];
|
|
5
|
+
/** A participant also runs Code Mode: `exec` custom tool calls and `wait` function calls. */
|
|
6
|
+
export declare const PARTICIPANT_RAW_ITEM_TYPES: readonly string[];
|
|
7
|
+
/** Thread item types an analyst turn may produce. */
|
|
8
|
+
export declare const ANALYST_ITEM_TYPES: readonly string[];
|
|
9
|
+
/** A participant also has its one dynamic tool. */
|
|
10
|
+
export declare const PARTICIPANT_ITEM_TYPES: readonly string[];
|
|
11
|
+
/**
|
|
12
|
+
* Server notification methods in Codex CLI 0.160.0's app-server schema
|
|
13
|
+
* (`codex app-server generate-json-schema --experimental`, ServerNotification), plus two it sends
|
|
14
|
+
* outside that union: rawResponseItem/completed, and rawResponse/completed, whose v2 definition
|
|
15
|
+
* (RawResponseCompletedNotification) carries only a response id and usage.
|
|
16
|
+
*/
|
|
17
|
+
export declare const KNOWN_CODEX_NOTIFICATIONS: ReadonlySet<string>;
|
|
18
|
+
/** What the item policy depends on: the session's role and, for a participant, its tool. */
|
|
19
|
+
export interface NotificationPolicy {
|
|
20
|
+
readonly participant: boolean;
|
|
21
|
+
/** The participant's tool name, read at each use; undefined for an analyst. */
|
|
22
|
+
toolName(): string | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** The item policy for a session: a participant's tool name is read at each use. */
|
|
25
|
+
export declare function notificationPolicyOf(participant: {
|
|
26
|
+
readonly tool: {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
};
|
|
29
|
+
} | undefined): NotificationPolicy;
|
|
30
|
+
/** Adds one notification of `method` to a session's unknown-method counts. */
|
|
31
|
+
export declare function countUnknownNotification(counts: Map<string, number>, method: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* The items a notification carries, each with the method whose policy it takes, or null when one
|
|
34
|
+
* is malformed. 0.160.0's schema puts a ThreadItem in `params.item` (item/started,
|
|
35
|
+
* item/completed), `params.turn.items` (turn/started, turn/completed) and
|
|
36
|
+
* `params.thread.turns[].items` (thread/started). An `item` array and an `items` array are read
|
|
37
|
+
* too, for a release that adds them. A nested ThreadItem takes the item/completed policy.
|
|
38
|
+
*/
|
|
39
|
+
export declare function notificationItems(method: string, params: Record<string, unknown>): {
|
|
40
|
+
method: string;
|
|
41
|
+
item: Record<string, unknown>;
|
|
42
|
+
}[] | null;
|
|
43
|
+
/**
|
|
44
|
+
* How a notification fares under the item policy: it carries no item, only allowed items, or a
|
|
45
|
+
* disallowed or malformed one.
|
|
46
|
+
*/
|
|
47
|
+
export declare function itemPolicyOf(method: string, params: Record<string, unknown>, policy: NotificationPolicy): "none" | "allowed" | "violation";
|
|
48
|
+
/**
|
|
49
|
+
* True when an item breaks the item policy. rawResponseItem/completed, and an item of a raw type
|
|
50
|
+
* under any method other than item/started or item/completed, use the raw-item policy. Every
|
|
51
|
+
* other item uses the thread-item policy: an allowed type, the participant's one dynamic tool, and
|
|
52
|
+
* no agent message that delivers asynchronously or asks a question.
|
|
53
|
+
*/
|
|
54
|
+
export declare function itemPolicyViolation(method: string, item: Record<string, unknown>, policy: NotificationPolicy): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* The handler for notifications outside a dispatched turn: during the handshake, before
|
|
57
|
+
* turn/start, between requests and while closing. A disallowed or malformed item refuses; an
|
|
58
|
+
* unknown method without an item is counted; anything else is ignored, as there is no turn to
|
|
59
|
+
* apply it to.
|
|
60
|
+
*/
|
|
61
|
+
export declare function idleNotificationHandler(policy: NotificationPolicy, recordUnknown: (method: string) => void, refuse: (code: RestrictedCodexAnalysisErrorCode) => void): (method: string, params: Record<string, unknown>) => void;
|
|
62
|
+
/** The run warning for unknown notification methods, or undefined when there were none. */
|
|
63
|
+
export declare function unknownNotificationsWarning(counts: Readonly<Record<string, number>> | undefined, cliVersion: string | undefined): string | undefined;
|
|
64
|
+
/** The run warning for a last frame cut off by humanish's own stop, or undefined when none was. */
|
|
65
|
+
export declare function truncatedFrameWarning(bytes: number | undefined): string | undefined;
|
|
66
|
+
/** The session fields its handlers outside a turn read and write (restricted-session). */
|
|
67
|
+
export interface NotificationSessionState {
|
|
68
|
+
readonly unknownNotifications: Map<string, number>;
|
|
69
|
+
/** The request in flight's deadline, or undefined between requests. */
|
|
70
|
+
readonly activeDeadline: RestrictedCodexDeadline | undefined;
|
|
71
|
+
readonly transport: RestrictedCodexTransport | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* The first policy refusal or unchecked output in the session, whenever it happened and whether
|
|
74
|
+
* or not a request reported it: a caller that tolerates a request's failure (the debrief) must
|
|
75
|
+
* not absorb it.
|
|
76
|
+
*/
|
|
77
|
+
policyRefusal: RestrictedCodexAnalysisErrorCode | undefined;
|
|
78
|
+
/** Bytes of last frames cut off after humanish stopped the app-server: a warning only. */
|
|
79
|
+
truncatedFrameBytes: number | undefined;
|
|
80
|
+
}
|
|
81
|
+
type Participant = {
|
|
82
|
+
readonly tool: {
|
|
83
|
+
readonly name: string;
|
|
84
|
+
};
|
|
85
|
+
} | undefined;
|
|
86
|
+
/**
|
|
87
|
+
* A policy refusal: it is recorded, the active request stops with `code`, pending RPCs are
|
|
88
|
+
* rejected, and between requests the next request fails with it.
|
|
89
|
+
*/
|
|
90
|
+
export declare function refuseSession(state: NotificationSessionState, code: RestrictedCodexAnalysisErrorCode): void;
|
|
91
|
+
/** The session's handler for notifications outside a dispatched turn, on its current transport. */
|
|
92
|
+
export declare function idleNotifications(participant: Participant, state: NotificationSessionState): (method: string, params: Record<string, unknown>) => void;
|
|
93
|
+
/**
|
|
94
|
+
* Installs the session's handlers on a new transport, before its first request: notifications
|
|
95
|
+
* outside a turn, notifications once the transport stopped or is closing, and policy failures
|
|
96
|
+
* the transport finds itself.
|
|
97
|
+
*/
|
|
98
|
+
export declare function installSessionHandlers(participant: Participant, state: NotificationSessionState, transport: RestrictedCodexTransport): void;
|
|
99
|
+
/** After a request: the turn's handlers come off the transport, and the idle handlers go on. */
|
|
100
|
+
export declare function detachTurn(participant: Participant, state: NotificationSessionState): void;
|
|
101
|
+
export {};
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
// The policy every app-server notification passes, whenever it arrives: during the launch
|
|
2
|
+
// handshake, before a turn is dispatched, during a turn, or between requests. A notification that
|
|
3
|
+
// carries an item is checked against the item policy whatever its method, so a new method cannot
|
|
4
|
+
// carry a native operation past it. A method this humanish does not know that carries no item is
|
|
5
|
+
// counted and reported, not refused, so a release's new progress events do not break a run.
|
|
6
|
+
import { codexRecord, toolPolicyViolation, } from "./restricted-policy.js";
|
|
7
|
+
import { RestrictedCodexStop, } from "./restricted-transport.js";
|
|
8
|
+
const rawCompactionTypes = ["compaction", "compaction_summary", "context_compaction"];
|
|
9
|
+
/** Raw response item types an analyst turn may produce. */
|
|
10
|
+
export const ANALYST_RAW_ITEM_TYPES = [
|
|
11
|
+
"message",
|
|
12
|
+
"reasoning",
|
|
13
|
+
...rawCompactionTypes,
|
|
14
|
+
];
|
|
15
|
+
/** A participant also runs Code Mode: `exec` custom tool calls and `wait` function calls. */
|
|
16
|
+
export const PARTICIPANT_RAW_ITEM_TYPES = [
|
|
17
|
+
...ANALYST_RAW_ITEM_TYPES,
|
|
18
|
+
"custom_tool_call",
|
|
19
|
+
"custom_tool_call_output",
|
|
20
|
+
"function_call",
|
|
21
|
+
"function_call_output",
|
|
22
|
+
];
|
|
23
|
+
/** Thread item types an analyst turn may produce. */
|
|
24
|
+
export const ANALYST_ITEM_TYPES = [
|
|
25
|
+
"userMessage",
|
|
26
|
+
"agentMessage",
|
|
27
|
+
"reasoning",
|
|
28
|
+
"contextCompaction",
|
|
29
|
+
];
|
|
30
|
+
/** A participant also has its one dynamic tool. */
|
|
31
|
+
export const PARTICIPANT_ITEM_TYPES = [...ANALYST_ITEM_TYPES, "dynamicToolCall"];
|
|
32
|
+
/**
|
|
33
|
+
* Server notification methods in Codex CLI 0.160.0's app-server schema
|
|
34
|
+
* (`codex app-server generate-json-schema --experimental`, ServerNotification), plus two it sends
|
|
35
|
+
* outside that union: rawResponseItem/completed, and rawResponse/completed, whose v2 definition
|
|
36
|
+
* (RawResponseCompletedNotification) carries only a response id and usage.
|
|
37
|
+
*/
|
|
38
|
+
export const KNOWN_CODEX_NOTIFICATIONS = new Set([
|
|
39
|
+
"account/gatewayOAuth/changed",
|
|
40
|
+
"account/login/completed",
|
|
41
|
+
"account/rateLimits/updated",
|
|
42
|
+
"account/updated",
|
|
43
|
+
"app/list/updated",
|
|
44
|
+
"autoApprovalReview/strictReviewRequired",
|
|
45
|
+
"command/exec/outputDelta",
|
|
46
|
+
"configWarning",
|
|
47
|
+
"deprecationNotice",
|
|
48
|
+
"error",
|
|
49
|
+
"externalAgentConfig/import/completed",
|
|
50
|
+
"externalAgentConfig/import/progress",
|
|
51
|
+
"fs/changed",
|
|
52
|
+
"fuzzyFileSearch/sessionCompleted",
|
|
53
|
+
"fuzzyFileSearch/sessionUpdated",
|
|
54
|
+
"guardianWarning",
|
|
55
|
+
"hook/completed",
|
|
56
|
+
"hook/started",
|
|
57
|
+
"item/agentMessage/delta",
|
|
58
|
+
"item/autoApprovalReview/completed",
|
|
59
|
+
"item/autoApprovalReview/started",
|
|
60
|
+
"item/commandExecution/outputDelta",
|
|
61
|
+
"item/commandExecution/terminalInteraction",
|
|
62
|
+
"item/completed",
|
|
63
|
+
"item/fileChange/outputDelta",
|
|
64
|
+
"item/fileChange/patchUpdated",
|
|
65
|
+
"item/mcpToolCall/progress",
|
|
66
|
+
"item/plan/delta",
|
|
67
|
+
"item/reasoning/summaryPartAdded",
|
|
68
|
+
"item/reasoning/summaryTextDelta",
|
|
69
|
+
"item/reasoning/textDelta",
|
|
70
|
+
"item/started",
|
|
71
|
+
"mcpServer/event/stream/notification",
|
|
72
|
+
"mcpServer/oauthLogin/completed",
|
|
73
|
+
"mcpServer/startupStatus/updated",
|
|
74
|
+
"model/rerouted",
|
|
75
|
+
"model/safetyBuffering/updated",
|
|
76
|
+
"model/verification",
|
|
77
|
+
"modelProvider/authRecoveryCompleted",
|
|
78
|
+
"modelProvider/authRecoveryStarted",
|
|
79
|
+
"process/exited",
|
|
80
|
+
"process/outputDelta",
|
|
81
|
+
"project/changed",
|
|
82
|
+
"rawResponse/completed",
|
|
83
|
+
"rawResponseItem/completed",
|
|
84
|
+
"remoteControl/status/changed",
|
|
85
|
+
"serverRequest/resolved",
|
|
86
|
+
"skills/changed",
|
|
87
|
+
"thread/archived",
|
|
88
|
+
"thread/attachment/updated",
|
|
89
|
+
"thread/closed",
|
|
90
|
+
"thread/compacted",
|
|
91
|
+
"thread/deleted",
|
|
92
|
+
"thread/environment/connected",
|
|
93
|
+
"thread/environment/disconnected",
|
|
94
|
+
"thread/goal/cleared",
|
|
95
|
+
"thread/goal/updated",
|
|
96
|
+
"thread/name/updated",
|
|
97
|
+
"thread/project/updated",
|
|
98
|
+
"thread/queue/changed",
|
|
99
|
+
"thread/realtime/closed",
|
|
100
|
+
"thread/realtime/error",
|
|
101
|
+
"thread/realtime/item/completed",
|
|
102
|
+
"thread/realtime/item/started",
|
|
103
|
+
"thread/realtime/item/transcript/delta",
|
|
104
|
+
"thread/realtime/itemAdded",
|
|
105
|
+
"thread/realtime/outputAudio/delta",
|
|
106
|
+
"thread/realtime/sdp",
|
|
107
|
+
"thread/realtime/started",
|
|
108
|
+
"thread/realtime/transcript/delta",
|
|
109
|
+
"thread/realtime/transcript/done",
|
|
110
|
+
"thread/reverted",
|
|
111
|
+
"thread/settings/updated",
|
|
112
|
+
"thread/started",
|
|
113
|
+
"thread/status/changed",
|
|
114
|
+
"thread/tokenUsage/updated",
|
|
115
|
+
"thread/unarchived",
|
|
116
|
+
"turn/completed",
|
|
117
|
+
"turn/diff/updated",
|
|
118
|
+
"turn/moderationMetadata",
|
|
119
|
+
"turn/plan/updated",
|
|
120
|
+
"turn/started",
|
|
121
|
+
"warning",
|
|
122
|
+
"windows/worldWritableWarning",
|
|
123
|
+
"windowsSandbox/setupCompleted",
|
|
124
|
+
]);
|
|
125
|
+
/** The item policy for a session: a participant's tool name is read at each use. */
|
|
126
|
+
export function notificationPolicyOf(participant) {
|
|
127
|
+
return { participant: participant !== undefined, toolName: () => participant?.tool.name };
|
|
128
|
+
}
|
|
129
|
+
/** Adds one notification of `method` to a session's unknown-method counts. */
|
|
130
|
+
export function countUnknownNotification(counts, method) {
|
|
131
|
+
counts.set(method, (counts.get(method) ?? 0) + 1);
|
|
132
|
+
}
|
|
133
|
+
const isItem = (value) => value !== null &&
|
|
134
|
+
typeof value === "object" &&
|
|
135
|
+
!Array.isArray(value) &&
|
|
136
|
+
typeof value.type === "string";
|
|
137
|
+
/**
|
|
138
|
+
* The items a notification carries, each with the method whose policy it takes, or null when one
|
|
139
|
+
* is malformed. 0.160.0's schema puts a ThreadItem in `params.item` (item/started,
|
|
140
|
+
* item/completed), `params.turn.items` (turn/started, turn/completed) and
|
|
141
|
+
* `params.thread.turns[].items` (thread/started). An `item` array and an `items` array are read
|
|
142
|
+
* too, for a release that adds them. A nested ThreadItem takes the item/completed policy.
|
|
143
|
+
*/
|
|
144
|
+
export function notificationItems(method, params) {
|
|
145
|
+
const found = [];
|
|
146
|
+
let malformed = false;
|
|
147
|
+
const add = (value, itemMethod) => {
|
|
148
|
+
if (isItem(value))
|
|
149
|
+
found.push({ method: itemMethod, item: value });
|
|
150
|
+
else
|
|
151
|
+
malformed = true;
|
|
152
|
+
};
|
|
153
|
+
const addAll = (value, itemMethod) => {
|
|
154
|
+
if (Array.isArray(value))
|
|
155
|
+
for (const item of value)
|
|
156
|
+
add(item, itemMethod);
|
|
157
|
+
};
|
|
158
|
+
if (Array.isArray(params.item))
|
|
159
|
+
addAll(params.item, method);
|
|
160
|
+
else if (params.item !== undefined && params.item !== null)
|
|
161
|
+
add(params.item, method);
|
|
162
|
+
addAll(params.items, method);
|
|
163
|
+
addAll(codexRecord(params.turn).items, "item/completed");
|
|
164
|
+
const turns = codexRecord(params.thread).turns;
|
|
165
|
+
if (Array.isArray(turns))
|
|
166
|
+
for (const turn of turns)
|
|
167
|
+
addAll(codexRecord(turn).items, "item/completed");
|
|
168
|
+
return malformed ? null : found;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* How a notification fares under the item policy: it carries no item, only allowed items, or a
|
|
172
|
+
* disallowed or malformed one.
|
|
173
|
+
*/
|
|
174
|
+
export function itemPolicyOf(method, params, policy) {
|
|
175
|
+
const found = notificationItems(method, params);
|
|
176
|
+
if (found === null)
|
|
177
|
+
return "violation";
|
|
178
|
+
if (found.length === 0)
|
|
179
|
+
return "none";
|
|
180
|
+
return found.some((entry) => itemPolicyViolation(entry.method, entry.item, policy))
|
|
181
|
+
? "violation"
|
|
182
|
+
: "allowed";
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* True when an item breaks the item policy. rawResponseItem/completed, and an item of a raw type
|
|
186
|
+
* under any method other than item/started or item/completed, use the raw-item policy. Every
|
|
187
|
+
* other item uses the thread-item policy: an allowed type, the participant's one dynamic tool, and
|
|
188
|
+
* no agent message that delivers asynchronously or asks a question.
|
|
189
|
+
*/
|
|
190
|
+
export function itemPolicyViolation(method, item, policy) {
|
|
191
|
+
const rawTypes = policy.participant ? PARTICIPANT_RAW_ITEM_TYPES : ANALYST_RAW_ITEM_TYPES;
|
|
192
|
+
const threadItemMethod = method === "item/started" || method === "item/completed";
|
|
193
|
+
const type = String(item.type);
|
|
194
|
+
if (method === "rawResponseItem/completed" || (!threadItemMethod && rawTypes.includes(type)))
|
|
195
|
+
return toolPolicyViolation("rawResponseItem/completed", item, rawTypes);
|
|
196
|
+
const itemTypes = policy.participant ? PARTICIPANT_ITEM_TYPES : ANALYST_ITEM_TYPES;
|
|
197
|
+
if (!itemTypes.includes(type))
|
|
198
|
+
return true;
|
|
199
|
+
if (type === "dynamicToolCall" && (item.tool !== policy.toolName() || item.namespace !== null))
|
|
200
|
+
return true;
|
|
201
|
+
return toolPolicyViolation("item/completed", item, rawTypes);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The handler for notifications outside a dispatched turn: during the handshake, before
|
|
205
|
+
* turn/start, between requests and while closing. A disallowed or malformed item refuses; an
|
|
206
|
+
* unknown method without an item is counted; anything else is ignored, as there is no turn to
|
|
207
|
+
* apply it to.
|
|
208
|
+
*/
|
|
209
|
+
export function idleNotificationHandler(policy, recordUnknown, refuse) {
|
|
210
|
+
return (method, params) => {
|
|
211
|
+
const items = itemPolicyOf(method, params, policy);
|
|
212
|
+
if (items === "violation")
|
|
213
|
+
refuse("codex_tool_call");
|
|
214
|
+
else if (items === "none" && !KNOWN_CODEX_NOTIFICATIONS.has(method))
|
|
215
|
+
recordUnknown(method);
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/** The run warning for unknown notification methods, or undefined when there were none. */
|
|
219
|
+
export function unknownNotificationsWarning(counts, cliVersion) {
|
|
220
|
+
const entries = Object.entries(counts ?? {}).sort(([a], [b]) => a.localeCompare(b));
|
|
221
|
+
if (entries.length === 0)
|
|
222
|
+
return undefined;
|
|
223
|
+
const list = entries.map(([method, count]) => `${method} ×${count}`).join(", ");
|
|
224
|
+
return `Codex CLI${cliVersion === undefined ? "" : ` ${cliVersion}`} sent notification methods humanish does not know: ${list}. They carried no item and were ignored.`;
|
|
225
|
+
}
|
|
226
|
+
/** The run warning for a last frame cut off by humanish's own stop, or undefined when none was. */
|
|
227
|
+
export function truncatedFrameWarning(bytes) {
|
|
228
|
+
return bytes === undefined
|
|
229
|
+
? undefined
|
|
230
|
+
: `Codex output was cut off when humanish stopped the app-server: ${bytes} bytes of an unfinished last frame were not checked.`;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* A policy refusal: it is recorded, the active request stops with `code`, pending RPCs are
|
|
234
|
+
* rejected, and between requests the next request fails with it.
|
|
235
|
+
*/
|
|
236
|
+
export function refuseSession(state, code) {
|
|
237
|
+
state.policyRefusal ??= code;
|
|
238
|
+
state.activeDeadline?.stop(code);
|
|
239
|
+
state.transport?.refuse(code);
|
|
240
|
+
}
|
|
241
|
+
/** The session's handler for notifications outside a dispatched turn, on its current transport. */
|
|
242
|
+
export function idleNotifications(participant, state) {
|
|
243
|
+
return idleNotificationHandler(notificationPolicyOf(participant), (method) => countUnknownNotification(state.unknownNotifications, method), (code) => refuseSession(state, code));
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Installs the session's handlers on a new transport, before its first request: notifications
|
|
247
|
+
* outside a turn, notifications once the transport stopped or is closing, and policy failures
|
|
248
|
+
* the transport finds itself.
|
|
249
|
+
*/
|
|
250
|
+
export function installSessionHandlers(participant, state, transport) {
|
|
251
|
+
transport.onNotification = idleNotifications(participant, state);
|
|
252
|
+
transport.onPolicyOnlyNotification = idleNotificationHandler(notificationPolicyOf(participant), (method) => countUnknownNotification(state.unknownNotifications, method), (code) => {
|
|
253
|
+
state.policyRefusal ??= code;
|
|
254
|
+
});
|
|
255
|
+
transport.onPolicyFailure = (code) => {
|
|
256
|
+
state.policyRefusal ??= code;
|
|
257
|
+
};
|
|
258
|
+
transport.onTruncatedFrame = (bytes) => {
|
|
259
|
+
state.truncatedFrameBytes = (state.truncatedFrameBytes ?? 0) + bytes;
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/** A server request outside a turn is refused; the transport answers it and stops the request. */
|
|
263
|
+
function idleRequests(state) {
|
|
264
|
+
return async () => {
|
|
265
|
+
state.policyRefusal ??= "codex_tool_call";
|
|
266
|
+
throw new RestrictedCodexStop("codex_tool_call");
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/** After a request: the turn's handlers come off the transport, and the idle handlers go on. */
|
|
270
|
+
export function detachTurn(participant, state) {
|
|
271
|
+
const transport = state.transport;
|
|
272
|
+
if (!transport)
|
|
273
|
+
return;
|
|
274
|
+
transport.onNotification = idleNotifications(participant, state);
|
|
275
|
+
transport.onRequest = idleRequests(state);
|
|
276
|
+
transport.onRequestComplete = undefined;
|
|
277
|
+
}
|