create-walle 0.10.2 → 0.10.3
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/README.md +3 -1
- package/lib/release-schema.json +2 -2
- package/lib/runtime-closure-policy.json +8 -7
- package/package.json +1 -1
- package/template/coding-task-manager/api-prompts.js +45 -7
- package/template/coding-task-manager/bin/claude-hook.js +55 -1
- package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
- package/template/coding-task-manager/bin/land.js +2069 -0
- package/template/coding-task-manager/bin/memory-census.js +4 -2
- package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
- package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
- package/template/coding-task-manager/db.js +156 -32
- package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
- package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
- package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
- package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
- package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
- package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
- package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
- package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
- package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
- package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
- package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
- package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
- package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
- package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
- package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
- package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
- package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
- package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
- package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
- package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
- package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
- package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
- package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
- package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
- package/template/coding-task-manager/lib/agent-definitions.js +19 -0
- package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
- package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
- package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
- package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
- package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
- package/template/coding-task-manager/lib/agent-presets.js +84 -1
- package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
- package/template/coding-task-manager/lib/agent-version-service.js +74 -11
- package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
- package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
- package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
- package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
- package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
- package/template/coding-task-manager/lib/api/fleet.js +118 -0
- package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
- package/template/coding-task-manager/lib/api/ingress.js +9 -1
- package/template/coding-task-manager/lib/api/landing.js +403 -0
- package/template/coding-task-manager/lib/api/machines.js +691 -2
- package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
- package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
- package/template/coding-task-manager/lib/api/session-attach.js +623 -0
- package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
- package/template/coding-task-manager/lib/api/sessions.js +77 -51
- package/template/coding-task-manager/lib/api/setup-network.js +544 -16
- package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
- package/template/coding-task-manager/lib/api/setup.js +829 -10
- package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
- package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
- package/template/coding-task-manager/lib/auth-rules.js +292 -21
- package/template/coding-task-manager/lib/background-stop.js +369 -0
- package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
- package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
- package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
- package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
- package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
- package/template/coding-task-manager/lib/build-info.js +4 -2
- package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
- package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
- package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
- package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
- package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
- package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
- package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
- package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
- package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
- package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
- package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
- package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
- package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
- package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
- package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
- package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
- package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
- package/template/coding-task-manager/lib/conversation-sync.js +355 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
- package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
- package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
- package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
- package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
- package/template/coding-task-manager/lib/db-domains.js +1 -0
- package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
- package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
- package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
- package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
- package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
- package/template/coding-task-manager/lib/feature-manifest.js +4 -0
- package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
- package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
- package/template/coding-task-manager/lib/fleet-hub.js +762 -0
- package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
- package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
- package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
- package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
- package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
- package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
- package/template/coding-task-manager/lib/fleet-update.js +798 -0
- package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
- package/template/coding-task-manager/lib/fs-watcher.js +58 -42
- package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
- package/template/coding-task-manager/lib/headless-term-service.js +84 -8
- package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
- package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
- package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
- package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
- package/template/coding-task-manager/lib/host-handoff.js +16 -19
- package/template/coding-task-manager/lib/host-stats.js +150 -3
- package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
- package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
- package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
- package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
- package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
- package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
- package/template/coding-task-manager/lib/hub-bridge.js +398 -0
- package/template/coding-task-manager/lib/idle-notify.js +491 -0
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
- package/template/coding-task-manager/lib/instance-manifest.js +5 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
- package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
- package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
- package/template/coding-task-manager/lib/landing/config.js +536 -0
- package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
- package/template/coding-task-manager/lib/landing/gate.js +360 -0
- package/template/coding-task-manager/lib/landing/git.js +344 -0
- package/template/coding-task-manager/lib/landing/lease.js +247 -0
- package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
- package/template/coding-task-manager/lib/landing/proof.js +223 -0
- package/template/coding-task-manager/lib/landing/queue.js +998 -0
- package/template/coding-task-manager/lib/landing/radar.js +489 -0
- package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
- package/template/coding-task-manager/lib/landing/state.js +263 -0
- package/template/coding-task-manager/lib/landing/stop.js +49 -0
- package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
- package/template/coding-task-manager/lib/landing/sync.js +456 -0
- package/template/coding-task-manager/lib/landing/train.js +885 -0
- package/template/coding-task-manager/lib/landing/window.js +57 -0
- package/template/coding-task-manager/lib/launch-environment.js +121 -0
- package/template/coding-task-manager/lib/launch-model-override.js +36 -10
- package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
- package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
- package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
- package/template/coding-task-manager/lib/lead-model-options.js +160 -3
- package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
- package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
- package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
- package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
- package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
- package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
- package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
- package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
- package/template/coding-task-manager/lib/machine-registry.js +750 -5
- package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
- package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
- package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
- package/template/coding-task-manager/lib/memory-join.js +337 -0
- package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
- package/template/coding-task-manager/lib/memory-sync.js +565 -0
- package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
- package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
- package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
- package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
- package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
- package/template/coding-task-manager/lib/model-availability.js +727 -0
- package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
- package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
- package/template/coding-task-manager/lib/model-id-rule.js +19 -0
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
- package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
- package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
- package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
- package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
- package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
- package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
- package/template/coding-task-manager/lib/native-history-control.js +6 -4
- package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
- package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
- package/template/coding-task-manager/lib/opencode-cli.js +480 -0
- package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
- package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
- package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
- package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
- package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
- package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
- package/template/coding-task-manager/lib/perf-summary.js +7 -0
- package/template/coding-task-manager/lib/perf-tracker.js +63 -2
- package/template/coding-task-manager/lib/project-config.js +7 -0
- package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
- package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
- package/template/coding-task-manager/lib/read-pool-client.js +89 -2
- package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
- package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
- package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
- package/template/coding-task-manager/lib/relay-client.js +57 -3
- package/template/coding-task-manager/lib/relink-audit.js +34 -5
- package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
- package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
- package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
- package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
- package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
- package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
- package/template/coding-task-manager/lib/restart-guard.js +18 -6
- package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
- package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
- package/template/coding-task-manager/lib/resume-admission.js +17 -3
- package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
- package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
- package/template/coding-task-manager/lib/runtime-contract.js +3 -1
- package/template/coding-task-manager/lib/schema-indexes.js +1 -0
- package/template/coding-task-manager/lib/session-context-locator.js +742 -0
- package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
- package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
- package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
- package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
- package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
- package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
- package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
- package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
- package/template/coding-task-manager/lib/session-create/response.js +7 -7
- package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
- package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
- package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
- package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
- package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
- package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
- package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
- package/template/coding-task-manager/lib/session-empty.js +13 -10
- package/template/coding-task-manager/lib/session-host-manager.js +60 -0
- package/template/coding-task-manager/lib/session-jobs.js +3 -1
- package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
- package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
- package/template/coding-task-manager/lib/session-park.js +738 -0
- package/template/coding-task-manager/lib/session-path-grant.js +13 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
- package/template/coding-task-manager/lib/session-transport.js +17 -0
- package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
- package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
- package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
- package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
- package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
- package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
- package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
- package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
- package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
- package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
- package/template/coding-task-manager/lib/submission-ack.js +90 -2
- package/template/coding-task-manager/lib/systemd-scope.js +115 -0
- package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
- package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
- package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
- package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
- package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
- package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
- package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
- package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
- package/template/coding-task-manager/lib/transcript-source.js +36 -4
- package/template/coding-task-manager/lib/transcript-store.js +9 -0
- package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
- package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
- package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
- package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
- package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
- package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
- package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
- package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
- package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
- package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
- package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
- package/template/coding-task-manager/lib/walle/turn.js +1 -1
- package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
- package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
- package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
- package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
- package/template/coding-task-manager/lib/walle-row-history.js +495 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
- package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
- package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
- package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
- package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
- package/template/coding-task-manager/lib/ws/misc.js +1 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
- package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
- package/template/coding-task-manager/oauth-proxy.js +112 -115
- package/template/coding-task-manager/package-lock.json +10 -94
- package/template/coding-task-manager/package.json +4 -3
- package/template/coding-task-manager/protocol/message-table.json +10 -0
- package/template/coding-task-manager/protocol/messages.js +10 -0
- package/template/coding-task-manager/protocol/ws-schema.json +20 -0
- package/template/coding-task-manager/protocol/ws-schema.md +2 -0
- package/template/coding-task-manager/public/css/app.css +170 -0
- package/template/coding-task-manager/public/css/walle-session.css +4 -0
- package/template/coding-task-manager/public/index.html +473 -243
- package/template/coding-task-manager/public/js/agent-command.js +86 -0
- package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
- package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
- package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
- package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
- package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
- package/template/coding-task-manager/public/js/background-work.js +196 -27
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
- package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
- package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
- package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
- package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
- package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
- package/template/coding-task-manager/public/js/document-review-links.js +9 -1
- package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
- package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
- package/template/coding-task-manager/public/js/message-renderer.js +4 -3
- package/template/coding-task-manager/public/js/model-picker.js +3 -1
- package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
- package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
- package/template/coding-task-manager/public/js/pasted-content.js +236 -0
- package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
- package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
- package/template/coding-task-manager/public/js/prompts.js +11 -10
- package/template/coding-task-manager/public/js/protocol.js +10 -0
- package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
- package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
- package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
- package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
- package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
- package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
- package/template/coding-task-manager/public/js/stream-view.js +6 -5
- package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
- package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
- package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
- package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
- package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
- package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
- package/template/coding-task-manager/public/js/walle.js +6 -0
- package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
- package/template/coding-task-manager/public/m/app.css +140 -0
- package/template/coding-task-manager/public/m/app.js +507 -68
- package/template/coding-task-manager/public/m/index.html +17 -0
- package/template/coding-task-manager/public/m/machines.js +838 -4
- package/template/coding-task-manager/public/m/private-api.js +31 -1
- package/template/coding-task-manager/public/usage.html +1 -0
- package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
- package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
- package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
- package/template/coding-task-manager/server.js +1950 -11679
- package/template/coding-task-manager/session-integrity.js +64 -4
- package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
- package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
- package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
- package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
- package/template/coding-task-manager/workers/session-host-process.js +5 -5
- package/template/coding-task-manager/workers/watch-worker.js +105 -0
- package/template/coding-task-manager/workers/worktree-worker.js +168 -33
- package/template/ctm-relay/lib/protocol.js +14 -1
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/shared/backup-retention.js +82 -0
- package/template/shared/conversation-admission.js +2 -0
- package/template/shared/conversation-provenance.js +3 -7
- package/template/shared/conversation-storage-v2-contract.js +5 -0
- package/template/shared/linked-worktree.js +51 -0
- package/template/shared/macos-fda-target.js +57 -0
- package/template/shared/orphan-parents.js +55 -0
- package/template/shared/release-schema.json +2 -2
- package/template/shared/storage/contract.js +3 -0
- package/template/wall-e/adapters/imessage.js +12 -0
- package/template/wall-e/agent.js +71 -4
- package/template/wall-e/api-walle.js +21 -1
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
- package/template/wall-e/brain/brain-join.js +859 -0
- package/template/wall-e/brain/brain-sync-membership.js +20 -0
- package/template/wall-e/brain/brain-sync-store.js +131 -77
- package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
- package/template/wall-e/brain/brain-sync-v2.js +578 -0
- package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
- package/template/wall-e/brain/deterministic-id.js +51 -0
- package/template/wall-e/brain/memories.js +2 -2
- package/template/wall-e/brain/migrations.js +40 -6
- package/template/wall-e/brain/model-identity-migration.js +1 -1
- package/template/wall-e/brain/owner-call-whitelist.js +23 -7
- package/template/wall-e/brain/schema.js +45 -85
- package/template/wall-e/brain.js +171 -35
- package/template/wall-e/chat.js +3 -3
- package/template/wall-e/coding/agent-shell-env.js +7 -2
- package/template/wall-e/coding/prompt-bundle.js +66 -21
- package/template/wall-e/config/main-loop-exemptions.json +2 -2
- package/template/wall-e/http/admin-api.js +37 -0
- package/template/wall-e/http/gws-api.js +4 -0
- package/template/wall-e/http/helper-rules-api.js +7 -1
- package/template/wall-e/http/model-admin.js +8 -1
- package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
- package/template/wall-e/http/model-proxy-providers.js +174 -1
- package/template/wall-e/http/model-route-health.js +157 -0
- package/template/wall-e/http/sync-api.js +278 -464
- package/template/wall-e/jobs/job-runner.js +28 -1
- package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
- package/template/wall-e/lib/ctm-data-dir.js +26 -0
- package/template/wall-e/lib/derivation-home.js +147 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
- package/template/wall-e/lib/helper-rules/grade.js +51 -8
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
- package/template/wall-e/lib/helper-rules/store.js +4 -2
- package/template/wall-e/lib/landing-mcp-tools.js +170 -0
- package/template/wall-e/lib/mcp-client-config.js +133 -14
- package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
- package/template/wall-e/lib/mcp-integration.js +58 -13
- package/template/wall-e/lib/parent-death.js +7 -1
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
- package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
- package/template/wall-e/llm/delegate-vendor-default.js +12 -5
- package/template/wall-e/llm/model-roles.js +1 -1
- package/template/wall-e/llm/native-delegate-selection.js +56 -8
- package/template/wall-e/llm/worker-delegate-args.js +72 -7
- package/template/wall-e/llm/worker-mcp-routing.js +66 -17
- package/template/wall-e/loops/brain-custom-writes.js +19 -0
- package/template/wall-e/loops/ingest.js +17 -1
- package/template/wall-e/loops/think.js +19 -4
- package/template/wall-e/mcp-contract.js +222 -6
- package/template/wall-e/mcp-protocol-contract.js +40 -5
- package/template/wall-e/mcp-server.js +128 -29
- package/template/wall-e/mcp-worker-schemas.js +5 -5
- package/template/wall-e/memory/ctm-context-client.js +85 -0
- package/template/wall-e/memory/ctm-session-context.js +9 -3
- package/template/wall-e/memory/hub-bridge-client.js +388 -0
- package/template/wall-e/memory/replica-origin.js +56 -0
- package/template/wall-e/memory/session-pool.js +135 -0
- package/template/wall-e/runtime/live-capabilities.js +8 -3
- package/template/wall-e/server.js +4 -2
- package/template/wall-e/shared/release-schema.json +2 -2
- package/template/wall-e/shared/sqlite-file-set.js +39 -0
- package/template/wall-e/shared/storage/contract.js +3 -0
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
- package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
- package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
- package/template/wall-e/tools/chrome-automation.js +6 -0
- package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
- package/template/wall-e/workers/brain-owner-worker.js +18 -4
- package/template/wall-e/workers/mcp-gateway-process.js +5 -5
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// WP-1 (docs/landing-pipeline-batched-multi-host-2026-10-30.html §5 D-3, §6, §8 WP-1, §9 S-1):
|
|
3
|
+
// the adaptive batch window.
|
|
4
|
+
//
|
|
5
|
+
// The window is how many runnable queued jobs one gate is asked to cover. It is Zuul's rule: +1 on a
|
|
6
|
+
// batch PASS (up to `landing.batch.max`), halve on a batch FAIL (never below 1). A window of 1 is
|
|
7
|
+
// exactly the serial queue that existed before this change, so a repository that never writes the
|
|
8
|
+
// file keeps today's behaviour.
|
|
9
|
+
//
|
|
10
|
+
// State lives at `<landing-dir>/window.json` — the same directory, the same atomic writer and the
|
|
11
|
+
// same `contract` stamp as every other file the queue owns (`state.js`). Nothing here reads git,
|
|
12
|
+
// spawns a process or knows about jobs: it is one integer and one transition.
|
|
13
|
+
|
|
14
|
+
const path = require('path');
|
|
15
|
+
|
|
16
|
+
const state = require('./state');
|
|
17
|
+
|
|
18
|
+
const DEFAULT_SIZE = 1;
|
|
19
|
+
const FILE = 'window.json';
|
|
20
|
+
|
|
21
|
+
function windowFile(root) {
|
|
22
|
+
return path.join(root, FILE);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function normalize(raw) {
|
|
26
|
+
if (!raw || typeof raw !== 'object') return DEFAULT_SIZE;
|
|
27
|
+
// Strictly a number: a `"8"` written by hand is a malformed window, and the safe reading of a
|
|
28
|
+
// malformed window is the serial one.
|
|
29
|
+
if (typeof raw.size !== 'number' || !Number.isInteger(raw.size) || raw.size < 1) return DEFAULT_SIZE;
|
|
30
|
+
return raw.size;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// `{ size }`, defaulting to `{ size: 1 }` when the file is absent, unreadable or malformed — an
|
|
34
|
+
// unknown window is the conservative one (today's serial behaviour), never a silent batch of eight.
|
|
35
|
+
function readWindow(root) {
|
|
36
|
+
return { size: normalize(state.readJsonSafe(windowFile(root))) };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// D-3: the transition, read-modify-write inside the queue's mutex (the runner is the only writer, but
|
|
40
|
+
// the file lives beside every other piece of shared state and gets the same protection). `max` is the
|
|
41
|
+
// ceiling (`landing.batch.max`, ≥ 1): a PASS never grows past it and a FAIL never shrinks below 1.
|
|
42
|
+
function bumpWindow(root, verdict, max) {
|
|
43
|
+
const ceiling = Number.isInteger(max) && max >= 1 ? max : DEFAULT_SIZE;
|
|
44
|
+
return state.withMutex(root, () => {
|
|
45
|
+
const before = readWindow(root).size;
|
|
46
|
+
const size = verdict === 'PASS' ? Math.min(before + 1, ceiling) : Math.max(Math.floor(before / 2), 1);
|
|
47
|
+
state.writeJsonAtomic(windowFile(root), { contract: state.CONTRACT, size });
|
|
48
|
+
return { size, before };
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = {
|
|
53
|
+
DEFAULT_SIZE,
|
|
54
|
+
windowFile,
|
|
55
|
+
readWindow,
|
|
56
|
+
bumpWindow,
|
|
57
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-0 of docs/launch-environment-host-carried-adoption-2026-10-26.html (§5 D-1, §6).
|
|
4
|
+
//
|
|
5
|
+
// ONE rule-versioned capture function for the per-session launch environment. The record it produces is a
|
|
6
|
+
// self-describing OBSERVATION -- { rule, state, values, reason } -- never a verdict about the session: it
|
|
7
|
+
// carries the rule that produced it (LAUNCH_ENV_RULE) so a later reader can convert a record written under
|
|
8
|
+
// an older rule (see lib/adopted-launch-environment.js, WP-2) instead of guessing. `rule` is an ordinal,
|
|
9
|
+
// not a content hash; the hash of the rule's inputs lives in tests/launch-environment.test.js
|
|
10
|
+
// (launchEnvironmentRuleDigest) so changing a projected key, a bound or the credential regex without
|
|
11
|
+
// bumping LAUNCH_ENV_RULE fails loudly.
|
|
12
|
+
//
|
|
13
|
+
// Dependency-free on purpose: node:crypto (rule digest) and node:buffer (byte bounds). No fs, no config.
|
|
14
|
+
|
|
15
|
+
const crypto = require('node:crypto');
|
|
16
|
+
const { Buffer } = require('node:buffer');
|
|
17
|
+
|
|
18
|
+
// Rule 2 = "the projected launch-context keys HOME/CODEX_HOME/TMPDIR are not private" (the rule since
|
|
19
|
+
// 4768eeced3); rule 1 = the pre-2026-10-25 reading.
|
|
20
|
+
const LAUNCH_ENV_RULE = 2;
|
|
21
|
+
|
|
22
|
+
// The keys a lead-model switch re-projects into the launch context (lib/lead-model-restore-reconciliation.js
|
|
23
|
+
// projectDeferredRestoreLaunch: HOME / CODEX_HOME from the launch context, TMPDIR alongside them). They are
|
|
24
|
+
// PROJECTED launch context, not per-session private overrides: a spawn still receives them, but their presence
|
|
25
|
+
// must never turn an otherwise empty override set into a private environment that only a surviving owner can
|
|
26
|
+
// reproduce. Anything else in the env is private and is captured by value.
|
|
27
|
+
const PROJECTED_LAUNCH_CONTEXT_KEYS = Object.freeze(['HOME', 'CODEX_HOME', 'TMPDIR']);
|
|
28
|
+
|
|
29
|
+
// Bounds of a capturable private environment (moved here from lib/lead-model-restore-reconciliation.js).
|
|
30
|
+
const MAX_SOURCE_ENV_ENTRIES = 64;
|
|
31
|
+
const MAX_SOURCE_ENV_BYTES = 32 * 1024;
|
|
32
|
+
const MAX_SOURCE_ENV_VALUE_BYTES = 8 * 1024;
|
|
33
|
+
|
|
34
|
+
// A key whose value is credential-shaped must never be written to a handoff manifest file.
|
|
35
|
+
const CREDENTIAL_KEY_RE = /(?:API_KEY|AUTH_TOKEN|_TOKEN|SECRET|PASSWORD|CREDENTIAL)/i;
|
|
36
|
+
|
|
37
|
+
const LAUNCH_ENV_STATES = Object.freeze(['captured', 'captured-empty', 'unavailable']);
|
|
38
|
+
const LAUNCH_ENV_REASONS = Object.freeze(['not_object', 'too_many_entries', 'bad_key', 'bad_value',
|
|
39
|
+
'too_many_bytes', 'credential_keys', 'legacy_worker_private_env', 'legacy_no_receipt']);
|
|
40
|
+
|
|
41
|
+
const ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]{0,127}$/;
|
|
42
|
+
|
|
43
|
+
/** Returns a NEW object holding only the non-projected entries of `env`; never mutates its input and maps a
|
|
44
|
+
* non-object to `{}`. */
|
|
45
|
+
function privateOverridesFromEnv(env) {
|
|
46
|
+
if (!env || typeof env !== 'object' || Array.isArray(env)) return {};
|
|
47
|
+
const out = {};
|
|
48
|
+
for (const [key, value] of Object.entries(env)) {
|
|
49
|
+
if (!PROJECTED_LAUNCH_CONTEXT_KEYS.includes(key)) out[key] = value;
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function unavailable(reason) {
|
|
55
|
+
return Object.freeze({ rule: LAUNCH_ENV_RULE, state: 'unavailable', values: null, reason });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Captures a raw per-session private environment. Frozen result; never throws. */
|
|
59
|
+
function captureLaunchEnvironment(privateEnv) {
|
|
60
|
+
if (!privateEnv || typeof privateEnv !== 'object' || Array.isArray(privateEnv)) return unavailable('not_object');
|
|
61
|
+
const entries = Object.entries(privateEnv);
|
|
62
|
+
if (entries.length > MAX_SOURCE_ENV_ENTRIES) return unavailable('too_many_entries');
|
|
63
|
+
const values = {};
|
|
64
|
+
let bytes = 0;
|
|
65
|
+
for (const [key, value] of entries) {
|
|
66
|
+
if (!ENV_KEY_RE.test(key)) return unavailable('bad_key');
|
|
67
|
+
if (typeof value !== 'string' || value.includes('\0')
|
|
68
|
+
|| Buffer.byteLength(value, 'utf8') > MAX_SOURCE_ENV_VALUE_BYTES) return unavailable('bad_value');
|
|
69
|
+
bytes += Buffer.byteLength(key, 'utf8') + Buffer.byteLength(value, 'utf8');
|
|
70
|
+
if (bytes > MAX_SOURCE_ENV_BYTES) return unavailable('too_many_bytes');
|
|
71
|
+
values[key] = value;
|
|
72
|
+
}
|
|
73
|
+
const state = entries.length ? 'captured' : 'captured-empty';
|
|
74
|
+
return Object.freeze({ rule: LAUNCH_ENV_RULE, state, values: Object.freeze(values), reason: null });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// A record is a NEW frozen object rebuilt from validated fields: a tampered record (extra fields, a
|
|
78
|
+
// non-frozen values object, values that no longer satisfy the bounds) never reaches a caller as itself.
|
|
79
|
+
function normalizeLaunchEnvironment(value) {
|
|
80
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
|
|
81
|
+
if (value.rule !== LAUNCH_ENV_RULE || !LAUNCH_ENV_STATES.includes(value.state)) return null;
|
|
82
|
+
if (value.state === 'unavailable') {
|
|
83
|
+
if (typeof value.reason !== 'string' || !LAUNCH_ENV_REASONS.includes(value.reason)) return null;
|
|
84
|
+
if (value.values !== null) return null;
|
|
85
|
+
return Object.freeze({ rule: LAUNCH_ENV_RULE, state: 'unavailable', values: null, reason: value.reason });
|
|
86
|
+
}
|
|
87
|
+
if (value.reason !== null) return null;
|
|
88
|
+
const recaptured = captureLaunchEnvironment(value.values);
|
|
89
|
+
if (recaptured.state !== value.state) return null;
|
|
90
|
+
return Object.freeze({ rule: LAUNCH_ENV_RULE, state: value.state, values: recaptured.values, reason: null });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Validator in the `modelStorageRootsMetadata` style: `{}` or `{ launchEnvironment: frozenRecord }` so a
|
|
94
|
+
* caller spreads it. Only rule-2 records whose declared state agrees with a re-capture are accepted. With
|
|
95
|
+
* `{ manifest: true }` a record whose values hold a CREDENTIAL_KEY_RE key is REWRITTEN to
|
|
96
|
+
* `{ rule, state:'unavailable', values:null, reason:'credential_keys' }` (so no secret reaches the 0600
|
|
97
|
+
* manifest file); the other record keeps its values. */
|
|
98
|
+
function launchEnvironmentMetadata(value, { manifest = false } = {}) {
|
|
99
|
+
const record = normalizeLaunchEnvironment(value);
|
|
100
|
+
if (!record) return {};
|
|
101
|
+
if (manifest && record.values && Object.keys(record.values).some((key) => CREDENTIAL_KEY_RE.test(key))) {
|
|
102
|
+
return { launchEnvironment: Object.freeze({ rule: LAUNCH_ENV_RULE, state: 'unavailable', values: null,
|
|
103
|
+
reason: 'credential_keys' }) };
|
|
104
|
+
}
|
|
105
|
+
return { launchEnvironment: record };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** sha256 over the rule's inputs: projected keys, bounds and the credential regex. Pinned in
|
|
109
|
+
* tests/launch-environment.test.js -- bump LAUNCH_ENV_RULE and add a converter case when it changes. */
|
|
110
|
+
function launchEnvironmentRuleDigest() {
|
|
111
|
+
return crypto.createHash('sha256').update(JSON.stringify({
|
|
112
|
+
rule: LAUNCH_ENV_RULE,
|
|
113
|
+
projected: PROJECTED_LAUNCH_CONTEXT_KEYS,
|
|
114
|
+
limits: [MAX_SOURCE_ENV_ENTRIES, MAX_SOURCE_ENV_BYTES, MAX_SOURCE_ENV_VALUE_BYTES],
|
|
115
|
+
credentialRe: CREDENTIAL_KEY_RE.source,
|
|
116
|
+
})).digest('hex');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = { LAUNCH_ENV_RULE, PROJECTED_LAUNCH_CONTEXT_KEYS, LAUNCH_ENV_STATES, LAUNCH_ENV_REASONS,
|
|
120
|
+
privateOverridesFromEnv, captureLaunchEnvironment, launchEnvironmentMetadata, launchEnvironmentRuleDigest,
|
|
121
|
+
MAX_SOURCE_ENV_ENTRIES, MAX_SOURCE_ENV_BYTES, MAX_SOURCE_ENV_VALUE_BYTES, CREDENTIAL_KEY_RE };
|
|
@@ -23,12 +23,8 @@ const {
|
|
|
23
23
|
CLAUDE_OPTION_SIGNATURES, CLAUDE_SHORT_OPTIONS, locateClaudeSettingsArg,
|
|
24
24
|
} = require('./native-lead-settings-argv');
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
function isValidOverrideModel(model) {
|
|
30
|
-
return typeof model === 'string' && model.length > 0 && model.length <= MAX_MODEL_ID_LENGTH && MODEL_ID_RE.test(model);
|
|
31
|
-
}
|
|
26
|
+
// The ONE model-id rule lives in a leaf module (the session host loads it); re-exported here.
|
|
27
|
+
const { isValidOverrideModel } = require('./model-id-rule');
|
|
32
28
|
|
|
33
29
|
// Drops an existing `--model X` / `--model=X` / `-m X` / `-m=X` so the override is the only model flag.
|
|
34
30
|
function stripModelFlags(args) {
|
|
@@ -42,12 +38,30 @@ function stripModelFlags(args) {
|
|
|
42
38
|
return out;
|
|
43
39
|
}
|
|
44
40
|
|
|
41
|
+
// OpenCode's OWN launcher form (docs/opencode-lead-and-delegate-model-selection-2026-10-28.html §6.3,
|
|
42
|
+
// R-8): the TUI's global flags come first and `--model` is spelled the long way only. Kept separate
|
|
43
|
+
// from `stripModelFlags` above so the Claude/Codex argv grammar (where `-m` is the Codex global and
|
|
44
|
+
// the model flag is appended/anchored) is never changed by an OpenCode-only rule.
|
|
45
|
+
function stripOpencodeModelFlags(args) {
|
|
46
|
+
const out = [];
|
|
47
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
48
|
+
const arg = String(args[i]);
|
|
49
|
+
if (arg === '--model' || arg === '-m') { i += 1; continue; }
|
|
50
|
+
if (arg.startsWith('--model=') || arg.startsWith('-m=')) continue;
|
|
51
|
+
out.push(args[i]);
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
|
|
45
56
|
/**
|
|
46
|
-
* @param {{ agentType: string, args: string[], model: unknown }} input
|
|
57
|
+
* @param {{ agentType: string, args: string[], model: unknown, line?: 'v1'|'v2'|null }} input
|
|
58
|
+
* `line` is the OpenCode binary's shape (lib/opencode-cli.js). It matters ONLY for
|
|
59
|
+
* `agentType === 'opencode'`; every other agent ignores it, and `null`/absent keeps the 1.x
|
|
60
|
+
* behaviour byte-identical.
|
|
47
61
|
* @returns {{ args: string[], applied: boolean, reason: string }}
|
|
48
62
|
* applied=false returns the input args untouched (same array) with the reason why.
|
|
49
63
|
*/
|
|
50
|
-
function applyLaunchModelOverride({ agentType, args, model } = {}) {
|
|
64
|
+
function applyLaunchModelOverride({ agentType, args, model, line } = {}) {
|
|
51
65
|
const list = Array.isArray(args) ? args : [];
|
|
52
66
|
if (model == null || model === '') return { args: list, applied: false, reason: 'none' };
|
|
53
67
|
if (!isValidOverrideModel(model)) return { args: list, applied: false, reason: 'invalid_model' };
|
|
@@ -68,6 +82,18 @@ function applyLaunchModelOverride({ agentType, args, model } = {}) {
|
|
|
68
82
|
const head = stripModelFlags(list.slice(0, resumeIdx));
|
|
69
83
|
return { args: [...head, '-m', model, ...list.slice(resumeIdx)], applied: true, reason: '' };
|
|
70
84
|
}
|
|
85
|
+
if (agentType === 'opencode') {
|
|
86
|
+
// 2.x (R-4, WP-4): the TUI rejects `--model`, so the target never touches this argv. Strip every
|
|
87
|
+
// prior model flag so a stale one cannot survive either; the model rides the inline config +
|
|
88
|
+
// plugin `switch_model` the spawn path writes (lib/session-create/subagent-pick.js
|
|
89
|
+
// opencodeV2PluginEnv). `applied:true` records that the switch IS carried, just not here.
|
|
90
|
+
if (line === 'v2') return { args: stripOpencodeModelFlags(list), applied: true, reason: 'opencode-v2-plugin-carrier' };
|
|
91
|
+
// 1.x: OpenCode takes its global flags first; strip every prior model flag (`--model X`,
|
|
92
|
+
// `--model=X`, `-m X`, `-m=X`). This rides a FRESH relaunch only (a resumed 1.x conversation
|
|
93
|
+
// keeps the model its last user message recorded -- §5 R-4), so the launcher never has to
|
|
94
|
+
// reconcile a resume.
|
|
95
|
+
return { args: ['--model', model, ...stripOpencodeModelFlags(list)], applied: true, reason: '' };
|
|
96
|
+
}
|
|
71
97
|
return { args: list, applied: false, reason: 'unsupported_agent' };
|
|
72
98
|
}
|
|
73
99
|
|
|
@@ -482,5 +508,5 @@ function applyLaunchEffortOverride(argv, agent, effort) {
|
|
|
482
508
|
}
|
|
483
509
|
|
|
484
510
|
module.exports = { applyLaunchModelOverride, isValidOverrideModel, applyLaunchEffortOverride, isValidEffort,
|
|
485
|
-
applyLaunchModelPin, stripModelFlags, insertBeforeCodexResume, rebindCodexForkLaunchPlan,
|
|
486
|
-
ensureClaudeResumeTarget };
|
|
511
|
+
applyLaunchModelPin, stripModelFlags, stripOpencodeModelFlags, insertBeforeCodexResume, rebindCodexForkLaunchPlan,
|
|
512
|
+
ensureCodexResumeTarget, ensureClaudeResumeTarget };
|
|
@@ -1172,7 +1172,8 @@ function createLaunchPlanCoordinator(options = {}) {
|
|
|
1172
1172
|
// (or clearing it themselves) is an implicit "always recompute".
|
|
1173
1173
|
// An explicit replacement bypasses the cache: the caller is saying the previous plan is no
|
|
1174
1174
|
// longer valid, so replaying it would defeat the retry it asked for.
|
|
1175
|
-
const warmKey = !replacement && warmPlanCacheEnabled && spec?.warmPlanInputs ? buildWarmPlanKey(spec.warmPlanInputs
|
|
1175
|
+
const warmKey = !replacement && warmPlanCacheEnabled && spec?.warmPlanInputs ? buildWarmPlanKey({ ...spec.warmPlanInputs,
|
|
1176
|
+
requestedLaunch: JSON.stringify([String(spec.cmd || ''), Array.isArray(spec.args) ? spec.args.map(String) : [], String(spec.modelId || '')]) }) : '';
|
|
1176
1177
|
if (warmKey) {
|
|
1177
1178
|
const cachedPlan = warmPlanCache.get(sessionId, warmKey);
|
|
1178
1179
|
if (cachedPlan && states.get(sessionId)?.generation === generation
|
|
@@ -32,6 +32,11 @@ function buildWarmPlanKey({
|
|
|
32
32
|
// full-MCP argv and silently ignore the setting. Defaults to '' so a caller that never
|
|
33
33
|
// sets a profile keeps a stable key.
|
|
34
34
|
mcpProfile = '',
|
|
35
|
+
// The REQUESTED launch (cmd, argv, model) the plan is built from. A plan is a function of the
|
|
36
|
+
// argv it was handed, so a restore asking for `--session <id>` must never be served the plan of
|
|
37
|
+
// the earlier fresh launch: an OpenCode tab has no CTM transcript, so the other inputs never move
|
|
38
|
+
// after its first prompt (opencode-v2-model-switch-standalone-plugin-2026-10-30.html revision 2).
|
|
39
|
+
requestedLaunch = '',
|
|
35
40
|
} = {}) {
|
|
36
41
|
return [
|
|
37
42
|
Number(transcriptMtimeMs) || 0,
|
|
@@ -40,6 +45,7 @@ function buildWarmPlanKey({
|
|
|
40
45
|
Number(codexConfigMtimeMs) || 0,
|
|
41
46
|
String(cliVersionStamp || ''),
|
|
42
47
|
String(mcpProfile || ''),
|
|
48
|
+
String(requestedLaunch || ''),
|
|
43
49
|
].join('\u241F');
|
|
44
50
|
}
|
|
45
51
|
|
|
@@ -53,10 +53,40 @@ function provenTurnOutcome(turn) {
|
|
|
53
53
|
return outcome && SETTLED_OUTCOMES.has(outcome) ? outcome : null;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// WP-1: the owner fields every Claude observation derives from its result (`withCapturedRouteOwner`
|
|
57
|
+
// then overrides them from the item's captured owner when it has one).
|
|
58
|
+
function claudeObservedOwner(result) {
|
|
59
|
+
return {
|
|
60
|
+
...(Number.isSafeInteger(result.processGeneration) ? { processGeneration: result.processGeneration } : {}),
|
|
61
|
+
...(typeof result.providerSessionId === 'string' ? { providerThreadId: result.providerSessionId } : {}),
|
|
62
|
+
...(typeof result.profileFingerprint === 'string' ? { profileFingerprint: result.profileFingerprint } : {}),
|
|
63
|
+
...(typeof result.routeId === 'string' ? { routeId: result.routeId } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/*
|
|
68
|
+
* WP-1/D-1: a REFUSED Claude turn, as the switch consumes it. `model` is EMPTY on purpose -- the
|
|
69
|
+
* refusal names no model, which is exactly why the switch's `no_model` guard used to swallow it. The
|
|
70
|
+
* failure is only open while it is NEWER than the newest successful turn; a good turn after it wins.
|
|
71
|
+
*/
|
|
72
|
+
function claudeFailureObservation(failure, observedOwner) {
|
|
73
|
+
const atMs = Number(failure.atMs) || 0;
|
|
74
|
+
const status = Number.isSafeInteger(failure.status) ? failure.status : null;
|
|
75
|
+
return {
|
|
76
|
+
model: '', outcome: 'failed', apiErrorStatus: status, error: `API Error ${status == null ? 'unknown' : status}`,
|
|
77
|
+
source: 'transcript:turn', observedAtMs: atMs,
|
|
78
|
+
...(failure.turnId ? { turnId: String(failure.turnId) } : {}),
|
|
79
|
+
...observedOwner,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
56
83
|
function turnObservationFrom(item, result) {
|
|
57
84
|
if (!result) return null;
|
|
58
85
|
if (item?.agentType === 'claude') {
|
|
59
86
|
const truth = result.modelTruth;
|
|
87
|
+
if (truth && truth.lastTurnFailure && Number(truth.lastTurnFailure.atMs) > Number(truth.lastTurnAtMs || 0)) {
|
|
88
|
+
return withCapturedRouteOwner(claudeFailureObservation(truth.lastTurnFailure, claudeObservedOwner(result)), item);
|
|
89
|
+
}
|
|
60
90
|
if (truth && truth.lastTurn && Number(truth.lastTurnAtMs) > 0) {
|
|
61
91
|
return withCapturedRouteOwner({
|
|
62
92
|
model: String(truth.lastTurn), effort: truth.effort || null, source: 'transcript:turn', observedAtMs: Number(truth.lastTurnAtMs),
|
|
@@ -116,8 +146,20 @@ function nativeTurnObservation(item, result) {
|
|
|
116
146
|
const source = item?.agentType === 'claude' ? 'transcript:turn' : item?.agentType === 'codex' ? 'codex:turn-context' : null;
|
|
117
147
|
if (!source || !Array.isArray(result.observations)) return null;
|
|
118
148
|
let best = null;
|
|
149
|
+
// WP-1/D-1: a refused turn arrives as its OWN observation kind; it is not a turn, so it never
|
|
150
|
+
// competes for `best` -- it only wins by being newer than the newest completed turn.
|
|
151
|
+
let bestFailure = null;
|
|
119
152
|
for (const o of result.observations) {
|
|
120
|
-
if (!o || o.
|
|
153
|
+
if (!o || o.source !== source) continue;
|
|
154
|
+
if (o.kind === 'failed-turn') {
|
|
155
|
+
const at = Number(o.observedAtMs);
|
|
156
|
+
if (!Number.isFinite(at) || at < 0) continue;
|
|
157
|
+
if (!bestFailure || at > bestFailure.at) bestFailure = { at, status: o.apiErrorStatus, turnId: o.sourceRevision || null,
|
|
158
|
+
processGeneration: o.processGeneration, providerThreadId: o.providerSessionId || null,
|
|
159
|
+
profileFingerprint: o.profileFingerprint || null, routeId: o.routeId || null };
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (o.kind !== 'completed-turn') continue;
|
|
121
163
|
if (typeof o.value !== 'string' || !o.value.length) continue;
|
|
122
164
|
const at = Number(o.observedAtMs);
|
|
123
165
|
if (!Number.isFinite(at) || at < 0) continue;
|
|
@@ -128,6 +170,20 @@ function nativeTurnObservation(item, result) {
|
|
|
128
170
|
profileFingerprint: o.profileFingerprint || null, routeId: o.routeId || null,
|
|
129
171
|
};
|
|
130
172
|
}
|
|
173
|
+
// A refusal newer than the newest successful turn is the answer; equal timestamps keep the
|
|
174
|
+
// completed turn, matching the decoder's own (timestamp, index) preference.
|
|
175
|
+
if (bestFailure && (!best || bestFailure.at > best.observedAtMs)) {
|
|
176
|
+
return withCapturedRouteOwner({
|
|
177
|
+
model: '', outcome: 'failed', apiErrorStatus: Number.isSafeInteger(bestFailure.status) ? bestFailure.status : null,
|
|
178
|
+
error: `API Error ${Number.isSafeInteger(bestFailure.status) ? bestFailure.status : 'unknown'}`,
|
|
179
|
+
source, observedAtMs: bestFailure.at,
|
|
180
|
+
...(bestFailure.turnId ? { turnId: String(bestFailure.turnId) } : {}),
|
|
181
|
+
...(Number.isSafeInteger(bestFailure.processGeneration) ? { processGeneration: bestFailure.processGeneration } : {}),
|
|
182
|
+
...(bestFailure.providerThreadId ? { providerThreadId: String(bestFailure.providerThreadId) } : {}),
|
|
183
|
+
...(bestFailure.profileFingerprint ? { profileFingerprint: String(bestFailure.profileFingerprint) } : {}),
|
|
184
|
+
...(bestFailure.routeId ? { routeId: String(bestFailure.routeId) } : {}),
|
|
185
|
+
}, item);
|
|
186
|
+
}
|
|
131
187
|
if (!best) return null;
|
|
132
188
|
const obs = { model: String(best.model), effort: best.effort, source: best.source, observedAtMs: best.observedAtMs };
|
|
133
189
|
if (best.turnId) obs.turnId = String(best.turnId);
|
|
@@ -34,6 +34,10 @@ const { isValidOverrideModel, isValidEffort } = require('./launch-model-override
|
|
|
34
34
|
const { parseClaudeModel, resolveReasoningControl } = require('../../shared/reasoning-control');
|
|
35
35
|
const { scanTomlStatements } = require('./agent-hooks-codex-toml');
|
|
36
36
|
const { projectNativeModelArguments } = require('./session-model-launch-policy');
|
|
37
|
+
// WP-8 step 4 (§9b M-12): the ONE ACP config-option readers (lib/session-create/dsh-session.js), so the
|
|
38
|
+
// picker read, the owner bind and the runtime's setModel/setEffort agree on what the bridge offers.
|
|
39
|
+
const { findModelOption, findEffortOption, plainModelIdFromConfigValue, configOptionEntries } = require('./session-create/dsh-session');
|
|
40
|
+
const { servesAnthropicMessages, anthropicDeployments } = require('./acp/dsh-route-patch');
|
|
37
41
|
|
|
38
42
|
const fs = require('fs');
|
|
39
43
|
const os = require('os');
|
|
@@ -41,7 +45,7 @@ const path = require('path');
|
|
|
41
45
|
const { codexHome } = require('./codex-paths');
|
|
42
46
|
|
|
43
47
|
const CACHE_TTL_MS = 5 * 60 * 1000;
|
|
44
|
-
const SUPPORTED_AGENTS = ['claude', 'codex'];
|
|
48
|
+
const SUPPORTED_AGENTS = ['claude', 'codex', 'opencode', 'dsh'];
|
|
45
49
|
const ALIAS_LABELS = Object.freeze({ opus: 'Opus', sonnet: 'Sonnet', haiku: 'Haiku', fable: 'Fable' });
|
|
46
50
|
// C3: the configured global is SMALL. Both the production reader and the injected-reader normalizer
|
|
47
51
|
// apply this same UTF-8 byte bound, so "over the cap" is one state, not two.
|
|
@@ -374,11 +378,84 @@ function codexRows(models) {
|
|
|
374
378
|
}));
|
|
375
379
|
}
|
|
376
380
|
|
|
381
|
+
// --- DeepSeek Harness routes (WP-8 step 4, §9b M-12; D-12) ------------------------------------------
|
|
382
|
+
// dsh takes NO argv model (D-12) and has no CLI catalog of its own: its Lead rows are the Wall-E routes
|
|
383
|
+
// that can carry an ACP child, one row per (route, model). The predicate is lib/acp/dsh-route-patch.js's
|
|
384
|
+
// own pair — the route advertises `anthropic-messages` in `upstream_apis` AND has at least one
|
|
385
|
+
// `anthropic-messages` deployment (pi-ai's Bearer path exists only on that wire, D-21) — so the picker,
|
|
386
|
+
// the create card and `prepareDshRoute` can never disagree about which routes exist. Read from the SAME
|
|
387
|
+
// redacted worker-route feed the dsh launch uses (`oauthProxySupervisor.listWorkerRoutes()`, the
|
|
388
|
+
// `dshRouteDeps.listRoutes` wiring in server.js).
|
|
389
|
+
function dshRoutesFromFeed(routes) {
|
|
390
|
+
const out = [];
|
|
391
|
+
for (const route of (Array.isArray(routes) ? routes : [])) {
|
|
392
|
+
if (!route || typeof route.id !== 'string' || !route.id) continue;
|
|
393
|
+
if (route.enabled === false || route.enabled === 0 || route.routable === false) continue;
|
|
394
|
+
if (!servesAnthropicMessages(route)) continue;
|
|
395
|
+
const models = [];
|
|
396
|
+
for (const deployment of anthropicDeployments(route)) {
|
|
397
|
+
const wire = deployment.wireModelId.trim();
|
|
398
|
+
if (wire && !models.includes(wire)) models.push(wire);
|
|
399
|
+
}
|
|
400
|
+
if (!models.length) continue;
|
|
401
|
+
out.push({ routeAlias: String(route.id), name: String(route.name || route.display_name || route.id), models });
|
|
402
|
+
}
|
|
403
|
+
return out;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Production's route reader: the worker-route feed above, projected into `[{routeAlias, name, models}]`.
|
|
407
|
+
// Lazy for the same reason as `listOpencodeModels` below: a caller that injects its own reader (every
|
|
408
|
+
// test, and a host that already holds one) never loads the proxy supervisor.
|
|
409
|
+
async function defaultListDshRoutes() {
|
|
410
|
+
return dshRoutesFromFeed(await require('./oauth-proxy-supervisor').listWorkerRoutes());
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// The live ACP child's own `configOptions` for this session, or null when it is not running. The
|
|
414
|
+
// production runtime holds them in memory on its own process entry
|
|
415
|
+
// (`lib/acp/dsh-session-runtime.js` `get(id).configOptions`, §9b M-16), so the wiring belongs where
|
|
416
|
+
// that runtime instance is in scope (the `createLeadModelOptions` call site). With no reader the tab
|
|
417
|
+
// still answers (gateway rows only), which is exactly what a parked/childless dsh session gets.
|
|
418
|
+
const noDshConfigOptions = () => null;
|
|
419
|
+
|
|
420
|
+
// WP-8 step 4 (§9b M-12): a dsh tab ALSO offers the models ITS OWN live child advertises on the route
|
|
421
|
+
// it is running right now. Those rows carry NO `route_id` (the same route), so a pick from them is an
|
|
422
|
+
// in-place `session/set_config_option` and never a relaunch (WP-8 step 3). Built fresh on every get —
|
|
423
|
+
// never cached with the route rows, which describe Wall-E's catalog, not this child — and the caller's
|
|
424
|
+
// cached `value` object is never mutated.
|
|
425
|
+
function dshSessionRows(agent, value, sessionId, getDshConfigOptions) {
|
|
426
|
+
if (agent !== 'dsh') return value;
|
|
427
|
+
let configOptions = null;
|
|
428
|
+
try { configOptions = getDshConfigOptions(String(sessionId || '')); }
|
|
429
|
+
catch (error) { void error; /* REPORT: a failing reader means "no live child", i.e. gateway rows only */ }
|
|
430
|
+
if (!Array.isArray(configOptions) || !configOptions.length) return value;
|
|
431
|
+
const modelOption = findModelOption(configOptions);
|
|
432
|
+
const rows = [];
|
|
433
|
+
for (const entry of configOptionEntries(modelOption)) {
|
|
434
|
+
const plain = plainModelIdFromConfigValue(entry.value);
|
|
435
|
+
if (!plain) continue;
|
|
436
|
+
rows.push({ kind: 'model', value: plain, label: entry.name || plain });
|
|
437
|
+
}
|
|
438
|
+
const effortOption = findEffortOption(configOptions);
|
|
439
|
+
const levels = configOptionEntries(effortOption).map((entry) => entry.value);
|
|
440
|
+
return {
|
|
441
|
+
...value,
|
|
442
|
+
rows: rows.concat(Array.isArray(value.rows) ? value.rows : []),
|
|
443
|
+
efforts: { values: levels, model_default: null },
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
377
447
|
/**
|
|
378
448
|
* @param {object} deps
|
|
379
449
|
* @param {(sessionId: string) => ({ type: string, agent: string|null }|null)} deps.getSessionInfo
|
|
380
450
|
* @param {() => Promise<object[]>} deps.loadCatalog Wall-E coding-catalog rows (rejects when Wall-E is unreachable)
|
|
381
451
|
* @param {() => Promise<{ state: string, reason?: string, error?: string, models: object[] }>} deps.listCodexModels
|
|
452
|
+
* @param {(opts?: object) => Promise<object[]>} [deps.listOpencodeModels] `<opencode> models --verbose`
|
|
453
|
+
* rows (lib/opencode-cli.js `opencodeCatalog`). Rejects with `.code === 'opencode_catalog_unavailable'`.
|
|
454
|
+
* @param {() => Promise<object[]>} [deps.listDshRoutes] the Anthropic-messages routes a dsh child may
|
|
455
|
+
* run on, `[{ routeAlias, name, models: string[] }]`. Absent = the real worker-route feed
|
|
456
|
+
* (lib/oauth-proxy-supervisor.js `listWorkerRoutes()`); rejects into `list_error`.
|
|
457
|
+
* @param {(sessionId: string) => (object[]|null)} [deps.getDshConfigOptions] the live dsh child's own
|
|
458
|
+
* ACP `configOptions`, or null/absent when it is not running (gateway rows only).
|
|
382
459
|
* @param {() => ({ path?: string, text: string }|{ state: string }|null|Promise<object|null>)} [deps.readClaudeSettings]
|
|
383
460
|
* `$CLAUDE_CONFIG_DIR/settings.json`, else `~/.claude/settings.json`. The legacy `{ path, text }` shape
|
|
384
461
|
* is still accepted (the path is ignored); `null` means "no config file".
|
|
@@ -388,6 +465,9 @@ function codexRows(models) {
|
|
|
388
465
|
*/
|
|
389
466
|
function createLeadModelOptions({
|
|
390
467
|
getSessionInfo, loadCatalog, listCodexModels,
|
|
468
|
+
listOpencodeModels = () => require('./opencode-cli').opencodeCatalog(),
|
|
469
|
+
listDshRoutes = defaultListDshRoutes,
|
|
470
|
+
getDshConfigOptions = noDshConfigOptions,
|
|
391
471
|
readClaudeSettings = defaultReadClaudeSettings,
|
|
392
472
|
readCodexConfigToml = defaultReadCodexConfigToml,
|
|
393
473
|
now = Date.now,
|
|
@@ -405,6 +485,13 @@ function createLeadModelOptions({
|
|
|
405
485
|
let generation = 0;
|
|
406
486
|
|
|
407
487
|
async function build(agent) {
|
|
488
|
+
// OpenCode (docs/opencode-lead-and-delegate-model-selection-2026-10-28.html §6.2, R-5): the rows
|
|
489
|
+
// are the CLI's OWN `models --verbose` catalog -- Wall-E's coding catalog describes Anthropic
|
|
490
|
+
// routes, not OpenCode providers, so it is neither read nor counted here.
|
|
491
|
+
if (agent === 'opencode') return buildOpencode();
|
|
492
|
+
// dsh (docs/deepseek-harness-acp-agent-2026-10-28.html §9b M-12): its rows are the routes that can
|
|
493
|
+
// carry an ACP child, never Wall-E's coding-catalog rows (which describe Anthropic CLI providers).
|
|
494
|
+
if (agent === 'dsh') return buildDsh();
|
|
408
495
|
let catalogRows = null;
|
|
409
496
|
let catalogError = '';
|
|
410
497
|
let catalogErrorCode = '';
|
|
@@ -456,6 +543,66 @@ function createLeadModelOptions({
|
|
|
456
543
|
return forAgentOf(entryFor(agent));
|
|
457
544
|
}
|
|
458
545
|
|
|
546
|
+
// The OpenCode rows: whatever the installed CLI lists, or none plus the typed reason (R-5 says a
|
|
547
|
+
// pick must equal a catalog row, so an unreadable catalog yields NO clickable rows -- never a
|
|
548
|
+
// guessed one). `not_switchable_count` is null on purpose: Wall-E's catalog says nothing about
|
|
549
|
+
// OpenCode providers, so there is no honest count to publish.
|
|
550
|
+
async function buildOpencode() {
|
|
551
|
+
let rows = [];
|
|
552
|
+
let listError = '';
|
|
553
|
+
try {
|
|
554
|
+
const listed = await listOpencodeModels();
|
|
555
|
+
rows = Array.isArray(listed) ? listed : [];
|
|
556
|
+
} catch (error) {
|
|
557
|
+
// REPORT: the picker footer shows this (same `list_error` field Codex uses); nothing is thrown.
|
|
558
|
+
const code = String((error && error.code) || 'opencode_catalog_unavailable');
|
|
559
|
+
const message = String((error && error.message) || error || '').trim();
|
|
560
|
+
listError = (message.startsWith(code) ? message : `${code}: ${message}`).slice(0, 200);
|
|
561
|
+
}
|
|
562
|
+
return {
|
|
563
|
+
agent: 'opencode',
|
|
564
|
+
source: 'opencode-cli',
|
|
565
|
+
rows,
|
|
566
|
+
not_switchable_count: null,
|
|
567
|
+
...(listError ? { list_error: listError } : {}),
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// The dsh rows: one `gateway` row per (route, model), labelled with the model id and sub-labelled with
|
|
572
|
+
// the route's display name (the same two strings a Claude gateway row shows). `not_switchable_count`
|
|
573
|
+
// is null for the same reason as OpenCode's: Wall-E's coding catalog says nothing about which models a
|
|
574
|
+
// dsh child may run, so there is no honest count of "hidden" rows.
|
|
575
|
+
async function buildDsh() {
|
|
576
|
+
let routes = [];
|
|
577
|
+
let listError = '';
|
|
578
|
+
try {
|
|
579
|
+
const listed = await listDshRoutes();
|
|
580
|
+
routes = Array.isArray(listed) ? listed : [];
|
|
581
|
+
} catch (error) {
|
|
582
|
+
// REPORT: the picker footer shows this (the same `list_error` field Codex and OpenCode use).
|
|
583
|
+
const code = String((error && error.code) || 'dsh_routes_unavailable');
|
|
584
|
+
const message = String((error && error.message) || error || '').trim();
|
|
585
|
+
listError = (message.startsWith(code) ? message : `${code}: ${message}`).slice(0, 200);
|
|
586
|
+
}
|
|
587
|
+
const rows = [];
|
|
588
|
+
for (const route of routes) {
|
|
589
|
+
if (!route || typeof route.routeAlias !== 'string' || !route.routeAlias) continue;
|
|
590
|
+
const name = String(route.name || route.routeAlias);
|
|
591
|
+
for (const model of (Array.isArray(route.models) ? route.models : [])) {
|
|
592
|
+
const value = String(model || '').trim();
|
|
593
|
+
if (!value) continue;
|
|
594
|
+
rows.push({ kind: 'gateway', value, route_id: route.routeAlias, label: value, sublabel: name });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return {
|
|
598
|
+
agent: 'dsh',
|
|
599
|
+
source: 'dsh-routes',
|
|
600
|
+
rows,
|
|
601
|
+
not_switchable_count: null,
|
|
602
|
+
...(listError ? { list_error: listError } : {}),
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
459
606
|
// The per-generation entry holder. It is deliberately ONE object per (agent, generation): a
|
|
460
607
|
// background revalidation mutates this object in place, so an answer already delivered under the
|
|
461
608
|
// same generation keeps matching the accepted expensive entry (C5) even while a revalidation runs.
|
|
@@ -573,6 +720,13 @@ function createLeadModelOptions({
|
|
|
573
720
|
function beginConfigRead(agent, gen) {
|
|
574
721
|
const ordinal = (configInvocation.get(agent) || 0) + 1;
|
|
575
722
|
configInvocation.set(agent, ordinal);
|
|
723
|
+
// OpenCode has no configured-global CTM may read: R-6 forbids writing (or inferring from) its
|
|
724
|
+
// user config/state, so `absent` is the one honest record and NEITHER reader above runs. A dsh tab
|
|
725
|
+
// is the same: the DeepSeek Harness has no CLI config file at all (D-12 — CTM never injects a model
|
|
726
|
+
// into dsh), so its record is the state-only `absent` one, published without opening any path.
|
|
727
|
+
if (agent === 'opencode' || agent === 'dsh') {
|
|
728
|
+
return { ordinal, gen, promise: Promise.resolve({ gen, ordinal, record: finalizeConfigRecord(stateOnlyConfigRecord('absent')) }) };
|
|
729
|
+
}
|
|
576
730
|
const reader = agent === 'claude' ? readClaudeSettings : readCodexConfigToml;
|
|
577
731
|
const promise = readConfigRecordFor(agent, reader).then(
|
|
578
732
|
(record) => ({ gen, ordinal, record }),
|
|
@@ -672,7 +826,10 @@ function createLeadModelOptions({
|
|
|
672
826
|
if (read.gen !== generation) return supersededResponse();
|
|
673
827
|
const record = acceptConfigRecord(agent, read.ordinal, applyCodexListFallback(read.record, agent, value));
|
|
674
828
|
if (record === SUPERSEDED) return supersededResponse();
|
|
675
|
-
|
|
829
|
+
// WP-8 step 4 (§9b M-12): a dsh tab's answer is the cached route rows PLUS the live child's own
|
|
830
|
+
// in-route rows and effort levels. Only the dsh branch touches the cached object, and it returns a
|
|
831
|
+
// fresh one, so the agent-level cache stays exactly what `buildDsh()` produced.
|
|
832
|
+
return publish(agent, entry, dshSessionRows(agent, value, sessionId, getDshConfigOptions), record);
|
|
676
833
|
}
|
|
677
834
|
|
|
678
835
|
// D-7: Wall-E POSTs /api/internal/model-registry/changed whenever the model registry or pricing
|
|
@@ -692,4 +849,4 @@ function createLeadModelOptions({
|
|
|
692
849
|
return { get, invalidate, isCurrent };
|
|
693
850
|
}
|
|
694
851
|
|
|
695
|
-
module.exports = { createLeadModelOptions, claudeModelValue, claudeCatalogRows, aliasRows, CACHE_TTL_MS, claudeEfforts, CLI_EFFORTS };
|
|
852
|
+
module.exports = { createLeadModelOptions, claudeModelValue, claudeCatalogRows, aliasRows, CACHE_TTL_MS, claudeEfforts, CLI_EFFORTS, dshRoutesFromFeed };
|