create-walle 0.10.1 → 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 +7 -1
- package/lib/owner-write-safety.js +135 -0
- package/lib/public-runtime.js +13 -5
- package/lib/release-schema.json +3 -2
- package/lib/runtime-closure-policy.json +11 -8
- package/package.json +1 -1
- package/template/bin/deps-doctor.js +1 -1
- package/template/bin/node-bin.sh +11 -0
- package/template/coding-task-manager/api-prompts.js +55 -29
- package/template/coding-task-manager/bin/claude-hook.js +62 -4
- package/template/coding-task-manager/bin/claude-table-parity.js +307 -0
- package/template/coding-task-manager/bin/conversation-storage-auto-migration-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-generation-evidence.js +9 -2
- package/template/coding-task-manager/bin/conversation-storage-service-entry-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-walle-owner.js +247 -0
- package/template/coding-task-manager/bin/ctm-machine-pair.js +160 -0
- 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/lead-wait-census.js +1348 -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/bin/repair-foreign-clone.js +564 -0
- package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
- package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
- package/template/coding-task-manager/db.js +860 -317
- package/template/coding-task-manager/git-utils.js +44 -0
- 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 -7
- 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 +99 -1
- package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
- package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
- 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/host-stats.js +98 -0
- package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
- package/template/coding-task-manager/lib/api/ingress.js +43 -12
- package/template/coding-task-manager/lib/api/landing.js +403 -0
- package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
- package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
- package/template/coding-task-manager/lib/api/machines.js +1150 -0
- package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +25 -5
- package/template/coding-task-manager/lib/api/providers.js +53 -6
- package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
- package/template/coding-task-manager/lib/api/resume-from-store.js +25 -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 +237 -59
- 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/transcript-history.js +17 -4
- package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
- package/template/coding-task-manager/lib/api/worktrees.js +38 -37
- package/template/coding-task-manager/lib/approval-drift.js +16 -1
- package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
- package/template/coding-task-manager/lib/approval-scope.js +68 -4
- package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
- package/template/coding-task-manager/lib/auth-context.js +32 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +64 -1
- package/template/coding-task-manager/lib/auth-rules.js +474 -62
- 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 +7 -1
- package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
- package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
- package/template/coding-task-manager/lib/build-info.js +4 -2
- package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
- package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
- package/template/coding-task-manager/lib/claude-session-title.js +6 -30
- package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
- package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
- package/template/coding-task-manager/lib/client-diag-handler.js +69 -2
- package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
- package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
- package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
- package/template/coding-task-manager/lib/codex-harness-qualification.js +55 -20
- package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
- package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
- package/template/coding-task-manager/lib/codex-paths.js +2 -1
- package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
- package/template/coding-task-manager/lib/coding-agent-models.js +48 -42
- package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +70 -4
- package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
- package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
- package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +24 -6
- package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
- package/template/coding-task-manager/lib/coding-session-model-state.js +17 -0
- package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
- package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
- package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -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 +104 -13
- 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-boot-lifecycle.js +17 -1
- package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
- package/template/coding-task-manager/lib/db-domain-tables.js +8 -0
- package/template/coding-task-manager/lib/db-domains.js +22 -2
- package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
- package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -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 +6 -0
- package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
- package/template/coding-task-manager/lib/feature-manifest.js +5 -1
- 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 +61 -44
- package/template/coding-task-manager/lib/harness-history-transition.js +52 -11
- package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
- package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
- package/template/coding-task-manager/lib/headless-term-service.js +139 -25
- 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-control-dial.js +167 -0
- 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-orchestrator.js +16 -2
- package/template/coding-task-manager/lib/host-handoff.js +50 -15
- package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
- package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
- package/template/coding-task-manager/lib/host-stats.js +475 -0
- package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
- package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
- package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
- package/template/coding-task-manager/lib/hosted-sync-worker.js +141 -310
- 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 +12 -0
- package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
- package/template/coding-task-manager/lib/instance-manifest.js +18 -2
- package/template/coding-task-manager/lib/instance-sync-status.js +33 -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 +193 -8
- 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/launch-plan-worker.js +59 -2
- 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 +409 -72
- package/template/coding-task-manager/lib/lead-model-switch.js +115 -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 +85 -9
- 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/legacy-draft-cancellation-recovery.js +111 -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/login-tripwire.js +1 -0
- package/template/coding-task-manager/lib/machine-pairing.js +238 -0
- package/template/coding-task-manager/lib/machine-pool.js +409 -0
- package/template/coding-task-manager/lib/machine-registry.js +1494 -0
- package/template/coding-task-manager/lib/machine-self.js +66 -0
- package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +485 -57
- 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/media-journal-control-reader.js +473 -0
- package/template/coding-task-manager/lib/media-journal.js +84 -27
- package/template/coding-task-manager/lib/media-store-options.js +43 -15
- 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/v56-host-samples-and-machine-pool.js +76 -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/mirror-feed-sanitize.js +12 -3
- 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 +8 -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 +6 -0
- package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
- package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
- 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/lead-worker-picks.js +25 -0
- package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
- package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
- package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -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/stream-accounting.js +205 -0
- package/template/coding-task-manager/lib/model-proxy/tokens.js +147 -5
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +18 -0
- package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
- package/template/coding-task-manager/lib/native-history-control.js +7 -5
- package/template/coding-task-manager/lib/native-lead-settings-client.js +46 -5
- package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +776 -75
- 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 +15 -1
- package/template/coding-task-manager/lib/painted-row-recorder.js +9 -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/prompt-submission-contract.js +21 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +264 -24
- package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
- package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
- package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
- package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
- package/template/coding-task-manager/lib/read-pool-client.js +94 -4
- package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
- package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
- package/template/coding-task-manager/lib/recent-catalog-query.js +41 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +76 -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-command-context.js +12 -0
- package/template/coding-task-manager/lib/remote-command-runtime.js +13 -1
- package/template/coding-task-manager/lib/remote-machine-catalog.js +1357 -0
- package/template/coding-task-manager/lib/remote-machine-create.js +1233 -0
- package/template/coding-task-manager/lib/remote-machine-link.js +1426 -0
- package/template/coding-task-manager/lib/remote-machine-proxy.js +654 -0
- package/template/coding-task-manager/lib/remote-session-forward.js +364 -0
- package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
- 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/restart-outcome-truth.js +20 -3
- package/template/coding-task-manager/lib/restart-preflight.js +9 -2
- package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
- package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
- package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
- 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/resume-blocked-wire.js +62 -1
- package/template/coding-task-manager/lib/resume-cwd.js +13 -0
- package/template/coding-task-manager/lib/resume-from-store.js +12 -1
- package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
- package/template/coding-task-manager/lib/resume-preflight.js +21 -16
- package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
- package/template/coding-task-manager/lib/review-repo-registry.js +74 -18
- package/template/coding-task-manager/lib/root-delivery-runtime.js +74 -17
- package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
- package/template/coding-task-manager/lib/root-prompt-admission.js +33 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +168 -34
- 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/scrollback-archive-store.js +7 -4
- package/template/coding-task-manager/lib/session-analysis-memory.js +2 -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/codex-native-provider-gate.js +218 -0
- package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
- package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +179 -20
- package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
- package/template/coding-task-manager/lib/session-create/identity.js +20 -1
- 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 +201 -9
- package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
- package/template/coding-task-manager/lib/session-create/provider-process.js +193 -64
- package/template/coding-task-manager/lib/session-create/response.js +37 -19
- 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 +14 -5
- 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 +50 -2
- package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
- package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
- package/template/coding-task-manager/lib/session-create/worker-observability.js +101 -9
- package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
- package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
- package/template/coding-task-manager/lib/session-empty.js +13 -10
- package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
- package/template/coding-task-manager/lib/session-host-manager.js +212 -206
- package/template/coding-task-manager/lib/session-jobs.js +20 -10
- package/template/coding-task-manager/lib/session-lifecycle.js +28 -4
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +15 -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-resource-sampler.js +19 -9
- package/template/coding-task-manager/lib/session-standup.js +67 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +147 -6
- package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
- package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
- package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
- 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/startup-pointer-write.js +57 -0
- 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/state-sync/painted-frame-field.js +11 -0
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +25 -23
- 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/surviving-owner-bootstrap.js +7 -2
- package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
- 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-http-status.js +25 -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-archiver.js +229 -229
- package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
- package/template/coding-task-manager/lib/transcript-frame-cache.js +20 -5
- package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
- package/template/coding-task-manager/lib/transcript-link.js +77 -0
- package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
- package/template/coding-task-manager/lib/transcript-source.js +44 -7
- package/template/coding-task-manager/lib/transcript-store.js +49 -0
- package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
- package/template/coding-task-manager/lib/typing-interaction-trace.js +198 -3
- package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
- 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/visible-revision-watchdog.js +8 -12
- package/template/coding-task-manager/lib/wake-skip-reasons.js +47 -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 +130 -27
- package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
- package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
- 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 +125 -6
- package/template/coding-task-manager/lib/ws/terminal-attach.js +123 -1
- package/template/coding-task-manager/lib/ws-router.js +68 -1
- package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
- package/template/coding-task-manager/oauth-proxy.js +211 -170
- package/template/coding-task-manager/package-lock.json +34 -94
- package/template/coding-task-manager/package.json +7 -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/providers/codex-mcp-extract.js +121 -19
- package/template/coding-task-manager/providers/codex-mcp.js +14 -5
- package/template/coding-task-manager/public/css/app.css +449 -1
- package/template/coding-task-manager/public/css/reviews.css +4 -0
- package/template/coding-task-manager/public/css/walle-session.css +4 -0
- package/template/coding-task-manager/public/index.html +766 -465
- 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 +2572 -0
- package/template/coding-task-manager/public/js/app/models-tab.js +658 -73
- package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +191 -7
- package/template/coding-task-manager/public/js/background-work.js +203 -28
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +181 -13
- 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 +847 -5
- package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
- 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 +48 -4
- package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
- package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
- package/template/coding-task-manager/public/js/history-scroller.js +187 -9
- package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
- package/template/coding-task-manager/public/js/machine-pool-shared.js +991 -0
- 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/private-state-scope.js +31 -3
- package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -8
- package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
- 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/queue-panel-submission-reconcile.js +174 -1
- package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
- package/template/coding-task-manager/public/js/reviews.js +7 -3
- package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
- package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
- package/template/coding-task-manager/public/js/row-join.js +4 -2
- package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
- package/template/coding-task-manager/public/js/session-search-utils.js +64 -21
- 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 +14 -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-02.js +16 -7
- package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
- package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
- 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 +60 -3
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +16 -12
- package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
- package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +211 -74
- package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
- package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
- package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
- package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -1
- package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
- package/template/coding-task-manager/public/js/terminal-wheel.js +62 -5
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +15 -7
- package/template/coding-task-manager/public/js/walle-session.js +30 -7
- 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 +366 -8
- package/template/coding-task-manager/public/m/app.js +1006 -74
- package/template/coding-task-manager/public/m/index.html +55 -1
- package/template/coding-task-manager/public/m/machines.js +2147 -0
- package/template/coding-task-manager/public/m/pool-failover.js +391 -0
- package/template/coding-task-manager/public/m/private-api.js +31 -1
- package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
- package/template/coding-task-manager/public/m/sw.js +5 -0
- package/template/coding-task-manager/public/usage.html +1 -0
- package/template/coding-task-manager/queue-engine.js +13 -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/approvals.js +5 -6
- package/template/coding-task-manager/server/boot.js +136 -17
- package/template/coding-task-manager/server.js +2819 -11885
- package/template/coding-task-manager/session-integrity.js +71 -13
- package/template/coding-task-manager/workers/db-owner-worker.js +72 -9
- 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 +93 -12
- package/template/coding-task-manager/workers/session-host-pool-process.js +24 -10
- package/template/coding-task-manager/workers/session-host-process.js +19 -8
- package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
- package/template/coding-task-manager/workers/watch-worker.js +105 -0
- package/template/coding-task-manager/workers/worktree-worker.js +202 -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/scripts/conversation-storage-v2-migration.js +78 -11
- 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 +47 -6
- package/template/shared/fixtures/worker-status-payloads.json +392 -0
- package/template/shared/git-remote-key.js +83 -0
- package/template/shared/host-identity.js +98 -2
- 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/owner-write-safety.js +135 -0
- package/template/shared/public-runtime.js +13 -5
- package/template/shared/release-schema.json +3 -2
- package/template/shared/report-citations.js +14 -0
- package/template/shared/sqlite-write-lock.js +361 -223
- package/template/shared/storage/contract.js +38 -3
- package/template/wall-e/adapters/imessage.js +12 -0
- package/template/wall-e/agent.js +92 -4
- package/template/wall-e/api-walle.js +26 -1
- package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +14 -8
- 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/helper-rules-schema.js +129 -0
- package/template/wall-e/brain/memories.js +2 -2
- package/template/wall-e/brain/migrations.js +91 -28
- package/template/wall-e/brain/model-deployment-facts.js +31 -1
- package/template/wall-e/brain/model-identity-migration.js +1 -1
- package/template/wall-e/brain/owner-call-whitelist.js +39 -7
- package/template/wall-e/brain/schema-ensures.js +22 -0
- package/template/wall-e/brain/schema.js +45 -85
- package/template/wall-e/brain.js +172 -36
- package/template/wall-e/chat.js +3 -3
- package/template/wall-e/coding/agent-shell-env.js +7 -2
- package/template/wall-e/coding/journal-dispatcher.js +51 -0
- package/template/wall-e/coding/prompt-bundle.js +66 -21
- package/template/wall-e/coding/session-journal.js +28 -40
- package/template/wall-e/coding-orchestrator.js +23 -26
- 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/auth.js +18 -1
- package/template/wall-e/http/blog-views-api.js +318 -0
- package/template/wall-e/http/gws-api.js +4 -0
- package/template/wall-e/http/helper-rules-api.js +327 -0
- 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 +177 -2
- 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/http/telemetry-api.js +12 -0
- package/template/wall-e/jobs/job-runner.js +28 -1
- package/template/wall-e/lib/blog-view-policy.js +88 -0
- package/template/wall-e/lib/blog-view-store.js +169 -0
- package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
- package/template/wall-e/lib/client-config-lock.js +2 -1
- package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
- 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/error-kinds.js +10 -1
- package/template/wall-e/lib/feature-manifest.js +1 -1
- package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +398 -0
- package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
- package/template/wall-e/lib/helper-rules/grade.js +320 -0
- package/template/wall-e/lib/helper-rules/label.js +247 -0
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +555 -0
- package/template/wall-e/lib/helper-rules/store.js +669 -0
- 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 +63 -19
- package/template/wall-e/lib/parent-death.js +7 -1
- package/template/wall-e/lib/runtime-worker-pool.js +1 -0
- package/template/wall-e/lib/scheduler-worker-jobs.js +12 -4
- package/template/wall-e/lib/telemetry-db-schema.js +37 -0
- package/template/wall-e/lib/telemetry-process-client.js +76 -1
- package/template/wall-e/llm/default-fallback.js +4 -0
- 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-catalog.js +13 -4
- package/template/wall-e/llm/model-roles.js +7 -1
- package/template/wall-e/llm/native-delegate-selection.js +56 -8
- package/template/wall-e/llm/portkey-http.js +150 -0
- package/template/wall-e/llm/portkey-sync.js +15 -145
- package/template/wall-e/llm/worker-delegate-args.js +72 -7
- package/template/wall-e/llm/worker-mcp-routing.js +117 -7
- package/template/wall-e/llm/worker-route.js +43 -1
- package/template/wall-e/loops/brain-custom-writes.js +64 -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 +77 -2
- package/template/wall-e/mcp-server.js +141 -31
- package/template/wall-e/mcp-worker-schemas.js +25 -7
- package/template/wall-e/memory/ctm-context-client.js +110 -5
- 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 +3 -2
- package/template/wall-e/shared/sqlite-file-set.js +39 -0
- package/template/wall-e/shared/sqlite-write-lock.js +361 -223
- package/template/wall-e/shared/storage/contract.js +38 -3
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +13 -1
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +11 -6
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +13 -8
- 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/tools/local-tools.js +6 -4
- package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
- package/template/wall-e/workers/brain-owner-worker.js +27 -4
- package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
- package/template/wall-e/workers/mcp-gateway-process.js +5 -5
- package/template/wall-e/workers/telemetry-worker.js +8 -0
|
@@ -18,6 +18,31 @@
|
|
|
18
18
|
// all three move here VERBATIM (misc-ops.js's workspace handlers are the
|
|
19
19
|
// precedent for a verbatim body living alongside dispatch-only wiring in the
|
|
20
20
|
// same module).
|
|
21
|
+
//
|
|
22
|
+
// Landing-throughput WP-5 shard S2 (design doc §5 D-10 "move-only", §6 "Shard
|
|
23
|
+
// module seam", §8 WP-5, §9 S-21..S-27): three more setup handlers move out of
|
|
24
|
+
// server.js VERBATIM -- apiSetupTestKey (GET /api/setup/test-key),
|
|
25
|
+
// apiSetupDetectKey (GET /api/setup/detect-key) and apiSetupSave
|
|
26
|
+
// (POST /api/setup/save). Each body is identical to server.js's declaration
|
|
27
|
+
// except for the `_deps.` prefix on every identifier that used to resolve to a
|
|
28
|
+
// server.js top-level binding (D-10 rule 1), proven by
|
|
29
|
+
// `node bin/move-only-check.js`. Injected deps, per function:
|
|
30
|
+
// apiSetupTestKey: CONFIG_DIR, MODEL_PROBE_ORDER, codexPaths, fs,
|
|
31
|
+
// getWalleStatusData, hostIdentityAccessAllowed, missingBinaryChild,
|
|
32
|
+
// oauthProxySupervisor, probeModel, resolveAgentCliCommand,
|
|
33
|
+
// sanitizeSetupProviderType, serverConfig, walleClient
|
|
34
|
+
// apiSetupDetectKey: CONFIG_DIR, codexPaths, execFileSync, fs,
|
|
35
|
+
// hostIdentityAccessAllowed, path, probeModel, readUserShellEnv,
|
|
36
|
+
// resolveAgentCliCommand, sanitizeSetupProviderType, serverConfig
|
|
37
|
+
// apiSetupSave: CONFIG_DIR, SETUP_PROVIDER_TYPES, __dirname,
|
|
38
|
+
// atomicWriteFileSync, fs, path, resolveEnvFilePath,
|
|
39
|
+
// sanitizeSetupProviderType, serverConfig, setup, setupProviderTypeList,
|
|
40
|
+
// telemetry, walleClient, walleSupervisor
|
|
41
|
+
// `__dirname` is injected although it is NOT a server.js top-level binding: it
|
|
42
|
+
// is the CommonJS wrapper parameter, so left bare in this file it would resolve
|
|
43
|
+
// to lib/api/ instead of server.js's own directory and silently change
|
|
44
|
+
// resolveEnvFilePath's repoRoot (D-10 rule 9, "behaviour: none changes"). It is
|
|
45
|
+
// passed by value, same as every immutable binding.
|
|
21
46
|
|
|
22
47
|
const { registerApiRoutes } = require('../api-router');
|
|
23
48
|
|
|
@@ -25,15 +50,12 @@ let _deps = null;
|
|
|
25
50
|
|
|
26
51
|
function configure({
|
|
27
52
|
apiSetupStatus,
|
|
28
|
-
apiSetupTestKey,
|
|
29
53
|
apiSetupDetectCodexCli,
|
|
30
|
-
apiSetupDetectKey,
|
|
31
54
|
apiSetupDetectGeminiCli,
|
|
32
55
|
apiSetupDetectClaudeCli,
|
|
33
56
|
apiSetupOauthProxyStart,
|
|
34
57
|
apiSetupOauthProxyStop,
|
|
35
58
|
apiSetupOauthProxyStatus,
|
|
36
|
-
apiSetupSave,
|
|
37
59
|
apiSetupProviders,
|
|
38
60
|
apiSetupSaveProvider,
|
|
39
61
|
apiSetupTestProvider,
|
|
@@ -49,18 +71,40 @@ function configure({
|
|
|
49
71
|
listWalleModelsViaOwner,
|
|
50
72
|
walleOwnerWrite,
|
|
51
73
|
serverConfig,
|
|
74
|
+
// WP-5 shard S2 move-only deps (see this file's header): the top-level
|
|
75
|
+
// server.js bindings apiSetupTestKey/apiSetupDetectKey/apiSetupSave used to
|
|
76
|
+
// close over. Immutable bindings, passed by value; `__dirname` is
|
|
77
|
+
// server.js's own module-wrapper directory (see header).
|
|
78
|
+
CONFIG_DIR,
|
|
79
|
+
MODEL_PROBE_ORDER,
|
|
80
|
+
codexPaths,
|
|
81
|
+
execFileSync,
|
|
82
|
+
fs,
|
|
83
|
+
path,
|
|
84
|
+
getWalleStatusData,
|
|
85
|
+
hostIdentityAccessAllowed,
|
|
86
|
+
missingBinaryChild,
|
|
87
|
+
oauthProxySupervisor,
|
|
88
|
+
probeModel,
|
|
89
|
+
readUserShellEnv,
|
|
90
|
+
resolveAgentCliCommand,
|
|
91
|
+
atomicWriteFileSync,
|
|
92
|
+
resolveEnvFilePath,
|
|
93
|
+
setup,
|
|
94
|
+
setupProviderTypeList,
|
|
95
|
+
telemetry,
|
|
96
|
+
walleClient,
|
|
97
|
+
walleSupervisor,
|
|
98
|
+
__dirname,
|
|
52
99
|
} = {}) {
|
|
53
100
|
_deps = {
|
|
54
101
|
apiSetupStatus,
|
|
55
|
-
apiSetupTestKey,
|
|
56
102
|
apiSetupDetectCodexCli,
|
|
57
|
-
apiSetupDetectKey,
|
|
58
103
|
apiSetupDetectGeminiCli,
|
|
59
104
|
apiSetupDetectClaudeCli,
|
|
60
105
|
apiSetupOauthProxyStart,
|
|
61
106
|
apiSetupOauthProxyStop,
|
|
62
107
|
apiSetupOauthProxyStatus,
|
|
63
|
-
apiSetupSave,
|
|
64
108
|
apiSetupProviders,
|
|
65
109
|
apiSetupSaveProvider,
|
|
66
110
|
apiSetupTestProvider,
|
|
@@ -76,6 +120,27 @@ function configure({
|
|
|
76
120
|
listWalleModelsViaOwner,
|
|
77
121
|
walleOwnerWrite,
|
|
78
122
|
serverConfig,
|
|
123
|
+
CONFIG_DIR,
|
|
124
|
+
MODEL_PROBE_ORDER,
|
|
125
|
+
codexPaths,
|
|
126
|
+
execFileSync,
|
|
127
|
+
fs,
|
|
128
|
+
path,
|
|
129
|
+
getWalleStatusData,
|
|
130
|
+
hostIdentityAccessAllowed,
|
|
131
|
+
missingBinaryChild,
|
|
132
|
+
oauthProxySupervisor,
|
|
133
|
+
probeModel,
|
|
134
|
+
readUserShellEnv,
|
|
135
|
+
resolveAgentCliCommand,
|
|
136
|
+
atomicWriteFileSync,
|
|
137
|
+
resolveEnvFilePath,
|
|
138
|
+
setup,
|
|
139
|
+
setupProviderTypeList,
|
|
140
|
+
telemetry,
|
|
141
|
+
walleClient,
|
|
142
|
+
walleSupervisor,
|
|
143
|
+
__dirname,
|
|
79
144
|
};
|
|
80
145
|
}
|
|
81
146
|
|
|
@@ -226,15 +291,15 @@ async function handleSetupModelsByType(req, res, type) {
|
|
|
226
291
|
function register() {
|
|
227
292
|
registerApiRoutes('setup', [
|
|
228
293
|
{ method: 'GET', path: '/api/setup/status', handler: (req, res, url) => _deps.apiSetupStatus(req, res, url) },
|
|
229
|
-
{ method: 'GET', path: '/api/setup/test-key', handler: (req, res, url) =>
|
|
294
|
+
{ method: 'GET', path: '/api/setup/test-key', handler: (req, res, url) => apiSetupTestKey(req, res, url) },
|
|
230
295
|
{ method: 'GET', path: '/api/setup/detect-codex-cli', handler: (req, res, url) => _deps.apiSetupDetectCodexCli(req, res, url) },
|
|
231
|
-
{ method: 'GET', path: '/api/setup/detect-key', handler: (req, res, url) =>
|
|
296
|
+
{ method: 'GET', path: '/api/setup/detect-key', handler: (req, res, url) => apiSetupDetectKey(req, res, url) },
|
|
232
297
|
{ method: 'GET', path: '/api/setup/detect-gemini-cli', handler: (req, res, url) => _deps.apiSetupDetectGeminiCli(req, res, url) },
|
|
233
298
|
{ method: 'GET', path: '/api/setup/detect-claude-cli', handler: (req, res, url) => _deps.apiSetupDetectClaudeCli(req, res, url) },
|
|
234
299
|
{ method: 'POST', path: '/api/setup/oauth-proxy/start', handler: (req, res, url) => _deps.apiSetupOauthProxyStart(req, res, url) },
|
|
235
300
|
{ method: 'POST', path: '/api/setup/oauth-proxy/stop', handler: (req, res, url) => _deps.apiSetupOauthProxyStop(req, res, url) },
|
|
236
301
|
{ method: 'GET', path: '/api/setup/oauth-proxy/status', handler: (req, res, url) => _deps.apiSetupOauthProxyStatus(req, res, url) },
|
|
237
|
-
{ method: 'POST', path: '/api/setup/save', handler: (req, res, url) =>
|
|
302
|
+
{ method: 'POST', path: '/api/setup/save', handler: (req, res, url) => apiSetupSave(req, res, url) },
|
|
238
303
|
{ method: 'GET', path: '/api/setup/providers', handler: (req, res, url) => _deps.apiSetupProviders(req, res, url) },
|
|
239
304
|
{ method: 'POST', path: '/api/setup/save-provider', handler: (req, res, url) => _deps.apiSetupSaveProvider(req, res, url) },
|
|
240
305
|
{ method: 'POST', path: '/api/setup/test-provider', handler: (req, res, url) => _deps.apiSetupTestProvider(req, res, url) },
|
|
@@ -267,4 +332,758 @@ function register() {
|
|
|
267
332
|
]);
|
|
268
333
|
}
|
|
269
334
|
|
|
270
|
-
|
|
335
|
+
async function apiSetupTestKey(req, res, url) {
|
|
336
|
+
const providerParam = _deps.sanitizeSetupProviderType(url.searchParams.get('provider') || '');
|
|
337
|
+
const authMethodParam = url.searchParams.get('auth_method') || '';
|
|
338
|
+
const walleStatus = await _deps.getWalleStatusData().catch(() => ({}));
|
|
339
|
+
const walleProvider = walleStatus.walle_provider || 'anthropic';
|
|
340
|
+
const walleModel = walleStatus.walle_model || '';
|
|
341
|
+
|
|
342
|
+
// ── auth_method=claude_cli: shell out to `claude auth status` (JSON
|
|
343
|
+
// output, no API call, no tokens burned). Tells us whether the CLI
|
|
344
|
+
// is installed AND authenticated, plus the user's email + plan.
|
|
345
|
+
if (providerParam === 'anthropic' && authMethodParam === 'claude_cli') {
|
|
346
|
+
const respond = (data) => {
|
|
347
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
348
|
+
res.end(JSON.stringify(data));
|
|
349
|
+
};
|
|
350
|
+
const { spawn } = require('child_process');
|
|
351
|
+
// Scrub ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN so the CLI reports the
|
|
352
|
+
// subscription auth (claude.ai login) we actually want to validate
|
|
353
|
+
// here — otherwise it just echoes back "apiKeySource": "ANTHROPIC_API_KEY"
|
|
354
|
+
// and we'd be testing the wrong path.
|
|
355
|
+
const childEnv = { ...process.env };
|
|
356
|
+
delete childEnv.ANTHROPIC_API_KEY;
|
|
357
|
+
delete childEnv.ANTHROPIC_AUTH_TOKEN;
|
|
358
|
+
let proc;
|
|
359
|
+
try {
|
|
360
|
+
proc = spawn(_deps.resolveAgentCliCommand('claude'), ['auth', 'status'], {
|
|
361
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
362
|
+
timeout: 15000,
|
|
363
|
+
env: childEnv,
|
|
364
|
+
});
|
|
365
|
+
} catch (err) {
|
|
366
|
+
return respond({ ok: false, error: 'Could not spawn claude: ' + err.message });
|
|
367
|
+
}
|
|
368
|
+
let stdout = '';
|
|
369
|
+
let stderr = '';
|
|
370
|
+
proc.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
371
|
+
proc.stderr.on('data', (d) => { stderr += d.toString(); });
|
|
372
|
+
proc.on('error', (err) => {
|
|
373
|
+
respond({
|
|
374
|
+
ok: false,
|
|
375
|
+
error: err.code === 'ENOENT'
|
|
376
|
+
? 'claude CLI not on PATH. Install Claude Code from claude.com/claude-code.'
|
|
377
|
+
: 'spawn failed: ' + err.message,
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
proc.on('close', (code) => {
|
|
381
|
+
if (code !== 0) {
|
|
382
|
+
return respond({ ok: false, error: 'claude auth status exited ' + code + ': ' + (stderr || stdout).slice(0, 300) });
|
|
383
|
+
}
|
|
384
|
+
let parsed;
|
|
385
|
+
try {
|
|
386
|
+
parsed = JSON.parse(stdout);
|
|
387
|
+
} catch (parseErr) {
|
|
388
|
+
return respond({ ok: false, error: 'claude auth status stdout not JSON: ' + stdout.slice(0, 200) });
|
|
389
|
+
}
|
|
390
|
+
if (!parsed.loggedIn) {
|
|
391
|
+
return respond({ ok: false, error: 'CLI installed but not signed in. Run `claude auth login`.' });
|
|
392
|
+
}
|
|
393
|
+
// Display "email · subscription" e.g. "user@example.com · pro"
|
|
394
|
+
const label = [parsed.email, parsed.subscriptionType].filter(Boolean).join(' · ');
|
|
395
|
+
respond({ ok: true, model: label || 'claude.ai', reply: parsed.authMethod || 'subscription' });
|
|
396
|
+
});
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ── auth_method=oauth_proxy: probe the running proxy on its loopback
|
|
401
|
+
// port, then send a minimal /v1/messages request through it. Flips
|
|
402
|
+
// `running=false` to a clear error so the user knows to enable it.
|
|
403
|
+
if (providerParam === 'anthropic' && authMethodParam === 'oauth_proxy') {
|
|
404
|
+
const respond = (data) => {
|
|
405
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
406
|
+
res.end(JSON.stringify(data));
|
|
407
|
+
};
|
|
408
|
+
const proxyStatus = await _deps.oauthProxySupervisor.status();
|
|
409
|
+
if (!proxyStatus.running) {
|
|
410
|
+
return respond({ ok: false, error: 'OAuth proxy is not running yet. Save the Anthropic card to start it, then test again.', proxy_status: proxyStatus, remediation: 'save_provider' });
|
|
411
|
+
}
|
|
412
|
+
const port = proxyStatus.port;
|
|
413
|
+
try {
|
|
414
|
+
const r = await fetch(`http://127.0.0.1:${port}/v1/messages`, {
|
|
415
|
+
method: 'POST',
|
|
416
|
+
headers: {
|
|
417
|
+
'Content-Type': 'application/json',
|
|
418
|
+
'anthropic-version': '2023-06-01',
|
|
419
|
+
},
|
|
420
|
+
body: JSON.stringify({
|
|
421
|
+
model: 'claude-haiku-4-5-20251001',
|
|
422
|
+
max_tokens: 20,
|
|
423
|
+
messages: [{ role: 'user', content: 'reply with the literal string OK and nothing else' }],
|
|
424
|
+
}),
|
|
425
|
+
signal: AbortSignal.timeout(20000),
|
|
426
|
+
});
|
|
427
|
+
if (!r.ok) {
|
|
428
|
+
const txt = await r.text().catch(() => '');
|
|
429
|
+
return respond({ ok: false, error: `Proxy returned ${r.status}: ${txt.slice(0, 250)}` });
|
|
430
|
+
}
|
|
431
|
+
const d = await r.json();
|
|
432
|
+
const reply = (d.content || []).filter((b) => b.type === 'text').map((b) => b.text).join('').trim();
|
|
433
|
+
return respond({
|
|
434
|
+
ok: reply.length > 0,
|
|
435
|
+
model: d.model || 'claude-haiku-4-5',
|
|
436
|
+
reply: reply.slice(0, 50),
|
|
437
|
+
});
|
|
438
|
+
} catch (err) {
|
|
439
|
+
return respond({ ok: false, error: 'Proxy probe failed: ' + err.message });
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const _testStoredProvider = async (type, fallbackModel, extraBody = {}) => {
|
|
444
|
+
try {
|
|
445
|
+
const providersResp = await _deps.walleClient.requestJson('/api/models/providers');
|
|
446
|
+
const providers = Array.isArray(providersResp.json?.providers) ? providersResp.json.providers : [];
|
|
447
|
+
const keylessProvider = type === 'ollama' || type === 'mlx';
|
|
448
|
+
const provider = providers.find((item) => item.type === type && item.enabled !== 0 && (keylessProvider || item.has_key));
|
|
449
|
+
if (!provider) return null;
|
|
450
|
+
const testResp = await _deps.walleClient.requestJson('/api/models/test-connection', {
|
|
451
|
+
method: 'POST',
|
|
452
|
+
body: { type, instance_id: provider.id, ...extraBody },
|
|
453
|
+
});
|
|
454
|
+
if (testResp.status >= 200 && testResp.status < 300 && testResp.json?.ok) {
|
|
455
|
+
const firstModel = Array.isArray(testResp.json.models) && testResp.json.models[0]?.id;
|
|
456
|
+
return { ok: true, model: testResp.json.probe?.model || firstModel || fallbackModel, probe: testResp.json.probe || null };
|
|
457
|
+
}
|
|
458
|
+
return { ok: false, error: testResp.json?.error || 'Provider not available', probe: testResp.json?.probe || null };
|
|
459
|
+
} catch {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
// ── Ollama test (local runtime, no API key) ──
|
|
465
|
+
if (providerParam === 'ollama') {
|
|
466
|
+
const ollamaModel = (walleProvider === 'ollama' && walleModel) ? walleModel : (url.searchParams.get('model') || process.env.OLLAMA_MODEL || 'gemma4:e4b');
|
|
467
|
+
const stored = await _testStoredProvider('ollama', ollamaModel, { model: ollamaModel });
|
|
468
|
+
if (stored) {
|
|
469
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
470
|
+
res.end(JSON.stringify(stored));
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
try {
|
|
474
|
+
const testResp = await _deps.walleClient.requestJson('/api/models/test-connection', {
|
|
475
|
+
method: 'POST',
|
|
476
|
+
body: {
|
|
477
|
+
type: 'ollama',
|
|
478
|
+
model: ollamaModel,
|
|
479
|
+
baseUrl: process.env.OLLAMA_BASE_URL || 'http://127.0.0.1:11434',
|
|
480
|
+
},
|
|
481
|
+
});
|
|
482
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
483
|
+
if (testResp.status >= 200 && testResp.status < 300 && testResp.json?.ok) {
|
|
484
|
+
res.end(JSON.stringify({
|
|
485
|
+
ok: true,
|
|
486
|
+
model: testResp.json.probe?.model || ollamaModel,
|
|
487
|
+
probe: testResp.json.probe || null,
|
|
488
|
+
}));
|
|
489
|
+
} else {
|
|
490
|
+
res.end(JSON.stringify({
|
|
491
|
+
ok: false,
|
|
492
|
+
error: testResp.json?.error || `Ollama probe failed with HTTP ${testResp.status}`,
|
|
493
|
+
probe: testResp.json?.probe || null,
|
|
494
|
+
}));
|
|
495
|
+
}
|
|
496
|
+
} catch (e) {
|
|
497
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
498
|
+
res.end(JSON.stringify({ ok: false, error: e.message }));
|
|
499
|
+
}
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// ── Google key test ──
|
|
504
|
+
if (providerParam === 'google') {
|
|
505
|
+
const googleKey = _deps.serverConfig.GOOGLE_API_KEY || '';
|
|
506
|
+
if (!googleKey) {
|
|
507
|
+
const stored = await _testStoredProvider('google', 'gemini-2.5-flash');
|
|
508
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
509
|
+
res.end(JSON.stringify(stored || { ok: false, error: 'No Google API key configured.' }));
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
// Detect stale ya29 access tokens — these are short-lived and can't be refreshed without GOOGLE_AUTH_MODE=oauth
|
|
513
|
+
if (googleKey.startsWith('ya29.') && _deps.serverConfig.GOOGLE_AUTH_MODE !== 'oauth') {
|
|
514
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
515
|
+
res.end(JSON.stringify({ ok: false, error: 'Stored key is a stale Gemini CLI OAuth token (ya29.*). Get an API key from aistudio.google.com/apikey or use "Use Gemini CLI Credentials" on the setup page.' }));
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const isOAuth = _deps.serverConfig.GOOGLE_AUTH_MODE === 'oauth';
|
|
519
|
+
const testUrl = isOAuth
|
|
520
|
+
? 'https://generativelanguage.googleapis.com/v1beta/models?pageSize=1'
|
|
521
|
+
: `https://generativelanguage.googleapis.com/v1beta/models?key=${encodeURIComponent(googleKey)}&pageSize=1`;
|
|
522
|
+
const headers = isOAuth ? { 'Authorization': `Bearer ${googleKey}` } : {};
|
|
523
|
+
const googleModel = (walleProvider === 'google' && walleModel && walleModel.startsWith('gemini')) ? walleModel : 'gemini-2.5-flash';
|
|
524
|
+
fetch(testUrl, { headers }).then(async (resp) => {
|
|
525
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
526
|
+
if (resp.ok) { res.end(JSON.stringify({ ok: true, model: googleModel })); }
|
|
527
|
+
else { const body = await resp.json().catch(() => ({})); res.end(JSON.stringify({ ok: false, error: body?.error?.message || `HTTP ${resp.status}` })); }
|
|
528
|
+
}).catch(e => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: false, error: e.message })); });
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// ── OpenAI codex_cli test: shell out to `codex login status` (free, no
|
|
533
|
+
// API call, no tokens). Mirrors anthropic's claude_cli test pattern.
|
|
534
|
+
if (providerParam === 'openai' && authMethodParam === 'codex_cli') {
|
|
535
|
+
const respond = (data) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)); };
|
|
536
|
+
const spawn = _deps.hostIdentityAccessAllowed({ configDir: _deps.CONFIG_DIR }) ? require('child_process').spawn : _deps.missingBinaryChild;
|
|
537
|
+
const childEnv = { ...process.env };
|
|
538
|
+
delete childEnv.OPENAI_API_KEY; // force ChatGPT subscription path
|
|
539
|
+
let proc;
|
|
540
|
+
try {
|
|
541
|
+
proc = spawn(_deps.resolveAgentCliCommand('codex'), ['login', 'status'], { stdio: ['ignore', 'pipe', 'pipe'], timeout: 10000, env: childEnv });
|
|
542
|
+
} catch (err) {
|
|
543
|
+
return respond({ ok: false, error: 'Could not spawn codex: ' + err.message });
|
|
544
|
+
}
|
|
545
|
+
let stdout = '';
|
|
546
|
+
let stderr = '';
|
|
547
|
+
proc.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
548
|
+
proc.stderr.on('data', (d) => { stderr += d.toString(); });
|
|
549
|
+
proc.on('error', (err) => {
|
|
550
|
+
respond({
|
|
551
|
+
ok: false,
|
|
552
|
+
error: err.code === 'ENOENT'
|
|
553
|
+
? 'codex CLI not on PATH. Install Codex from chatgpt.com/codex.'
|
|
554
|
+
: 'spawn failed: ' + err.message,
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
proc.on('close', (code) => {
|
|
558
|
+
if (code !== 0) {
|
|
559
|
+
return respond({ ok: false, error: 'codex login status exited ' + code + ': ' + (stderr || stdout).slice(0, 300) });
|
|
560
|
+
}
|
|
561
|
+
// codex login status prints to stderr; combine streams for the match.
|
|
562
|
+
const combined = stdout + '\n' + stderr;
|
|
563
|
+
const loggedIn = /logged in/i.test(combined);
|
|
564
|
+
if (!loggedIn) {
|
|
565
|
+
return respond({ ok: false, error: 'Codex installed but not logged in. Run `codex login`.' });
|
|
566
|
+
}
|
|
567
|
+
// Parse plan from auth.json JWT (best-effort, same as detect)
|
|
568
|
+
let plan = null;
|
|
569
|
+
try {
|
|
570
|
+
const auth = JSON.parse(_deps.fs.readFileSync(_deps.codexPaths.codexAuthPath(), 'utf8'));
|
|
571
|
+
const accessToken = auth?.tokens?.access_token;
|
|
572
|
+
if (accessToken) {
|
|
573
|
+
const parts = accessToken.split('.');
|
|
574
|
+
if (parts.length >= 2) {
|
|
575
|
+
const pad = '='.repeat((-parts[1].length) & 3);
|
|
576
|
+
const payload = JSON.parse(Buffer.from(parts[1] + pad, 'base64url').toString('utf8'));
|
|
577
|
+
plan = payload?.['https://api.openai.com/auth']?.chatgpt_plan_type || null;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
} catch { /* best-effort */ }
|
|
581
|
+
const emailMatch = combined.match(/[\w.+-]+@[\w-]+\.[\w.-]+/);
|
|
582
|
+
const label = [emailMatch ? emailMatch[0] : null, plan].filter(Boolean).join(' · ');
|
|
583
|
+
respond({ ok: true, model: label || 'ChatGPT subscription', reply: 'codex' });
|
|
584
|
+
});
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// ── DeepSeek key test (api_key — direct API, OpenAI-compatible) ──
|
|
589
|
+
if (providerParam === 'deepseek') {
|
|
590
|
+
const deepseekKey = _deps.serverConfig.DEEPSEEK_API_KEY || '';
|
|
591
|
+
if (!deepseekKey) {
|
|
592
|
+
const stored = await _testStoredProvider('deepseek', 'deepseek-v4-flash');
|
|
593
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
594
|
+
res.end(JSON.stringify(stored || { ok: false, error: 'No DeepSeek API key configured.' }));
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
const dsModel = (walleProvider === 'deepseek' && walleModel && /^deepseek-/.test(walleModel)) ? walleModel : 'deepseek-v4-flash';
|
|
598
|
+
// /models is OpenAI-compatible at api.deepseek.com — single GET, no token burn.
|
|
599
|
+
fetch('https://api.deepseek.com/v1/models', { headers: { 'Authorization': `Bearer ${deepseekKey}` } }).then(async (resp) => {
|
|
600
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
601
|
+
if (resp.ok) { res.end(JSON.stringify({ ok: true, model: dsModel })); }
|
|
602
|
+
else { const body = await resp.json().catch(() => ({})); res.end(JSON.stringify({ ok: false, error: body?.error?.message || `HTTP ${resp.status}` })); }
|
|
603
|
+
}).catch(e => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: false, error: e.message })); });
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// ── Moonshot / Kimi key test (api_key — direct API, OpenAI-compatible) ──
|
|
608
|
+
if (providerParam === 'moonshot') {
|
|
609
|
+
const moonshotKey = _deps.serverConfig.MOONSHOT_API_KEY || '';
|
|
610
|
+
if (!moonshotKey) {
|
|
611
|
+
const stored = await _testStoredProvider('moonshot', 'kimi-k2.6');
|
|
612
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
613
|
+
res.end(JSON.stringify(stored || { ok: false, error: 'No Moonshot API key configured.' }));
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
const moonshotModel = (walleProvider === 'moonshot' && walleModel && /^(kimi-|moonshot-)/.test(walleModel)) ? walleModel : 'kimi-k2.6';
|
|
617
|
+
const base = process.env.MOONSHOT_BASE_URL || 'https://api.moonshot.ai/v1';
|
|
618
|
+
fetch(base.replace(/\/+$/, '') + '/models', { headers: { 'Authorization': `Bearer ${moonshotKey}` } }).then(async (resp) => {
|
|
619
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
620
|
+
if (resp.ok) { res.end(JSON.stringify({ ok: true, model: moonshotModel })); }
|
|
621
|
+
else { const body = await resp.json().catch(() => ({})); res.end(JSON.stringify({ ok: false, error: body?.error?.message || `HTTP ${resp.status}` })); }
|
|
622
|
+
}).catch(e => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: false, error: e.message })); });
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// ── Z.AI key test (api_key — direct API, OpenAI-compatible) ──
|
|
627
|
+
if (providerParam === 'zai') {
|
|
628
|
+
const zaiKey = _deps.serverConfig.ZAI_API_KEY || '';
|
|
629
|
+
if (!zaiKey) {
|
|
630
|
+
const stored = await _testStoredProvider('zai', 'glm-5.2');
|
|
631
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
632
|
+
res.end(JSON.stringify(stored || { ok: false, error: 'No Z.AI API key configured.' }));
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
const zaiModel = (walleProvider === 'zai' && walleModel && /^glm-/.test(walleModel)) ? walleModel : 'glm-5.2';
|
|
636
|
+
const base = process.env.ZAI_BASE_URL || 'https://api.z.ai/api/paas/v4/';
|
|
637
|
+
fetch(base.replace(/\/+$/, '') + '/models', { headers: { 'Authorization': `Bearer ${zaiKey}` } }).then(async (resp) => {
|
|
638
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
639
|
+
if (resp.ok) { res.end(JSON.stringify({ ok: true, model: zaiModel })); }
|
|
640
|
+
else { const body = await resp.json().catch(() => ({})); res.end(JSON.stringify({ ok: false, error: body?.error?.message || `HTTP ${resp.status}` })); }
|
|
641
|
+
}).catch(e => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: false, error: e.message })); });
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// ── OpenAI key test (api_key — direct API) ──
|
|
646
|
+
if (providerParam === 'openai') {
|
|
647
|
+
const openaiKey = _deps.serverConfig.OPENAI_API_KEY || '';
|
|
648
|
+
if (!openaiKey) {
|
|
649
|
+
const stored = await _testStoredProvider('openai', 'gpt-4o-mini');
|
|
650
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
651
|
+
res.end(JSON.stringify(stored || { ok: false, error: 'No OpenAI API key configured.' }));
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
const openaiModel = (walleProvider === 'openai' && walleModel && /^(gpt|o[1-9])/.test(walleModel)) ? walleModel : 'gpt-4o-mini';
|
|
655
|
+
fetch('https://api.openai.com/v1/models?limit=1', { headers: { 'Authorization': `Bearer ${openaiKey}` } }).then(async (resp) => {
|
|
656
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
657
|
+
if (resp.ok) { res.end(JSON.stringify({ ok: true, model: openaiModel })); }
|
|
658
|
+
else { const body = await resp.json().catch(() => ({})); res.end(JSON.stringify({ ok: false, error: body?.error?.message || `HTTP ${resp.status}` })); }
|
|
659
|
+
}).catch(e => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: false, error: e.message })); });
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// ── Anthropic key test (default) ──
|
|
664
|
+
const apiKey = _deps.serverConfig.ANTHROPIC_API_KEY || _deps.serverConfig.ANTHROPIC_AUTH_TOKEN || '';
|
|
665
|
+
const baseUrl = _deps.serverConfig.ANTHROPIC_BASE_URL || 'https://api.anthropic.com';
|
|
666
|
+
const customHeadersB64 = _deps.serverConfig.ANTHROPIC_CUSTOM_HEADERS_B64 || '';
|
|
667
|
+
const configuredModel = _deps.MODEL_PROBE_ORDER[0];
|
|
668
|
+
if (!apiKey) {
|
|
669
|
+
const stored = await _testStoredProvider('anthropic', configuredModel);
|
|
670
|
+
if (stored) {
|
|
671
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
672
|
+
res.end(JSON.stringify(stored));
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
676
|
+
res.end(JSON.stringify({ ok: false, error: 'No API key configured.' }));
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
// Try the configured model first; only probe for an alternative if it fails.
|
|
680
|
+
// Build probe order with configured model at the front (deduplicated)
|
|
681
|
+
const probeOrder = [configuredModel, ..._deps.MODEL_PROBE_ORDER.filter(m => m !== configuredModel)];
|
|
682
|
+
_deps.probeModel(apiKey, baseUrl, customHeadersB64, probeOrder).then(({ model, authError }) => {
|
|
683
|
+
if (model) {
|
|
684
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
685
|
+
res.end(JSON.stringify({ ok: true, model }));
|
|
686
|
+
} else if (authError) {
|
|
687
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
688
|
+
res.end(JSON.stringify({ ok: false, error: 'Invalid API key — double-check the key and try again.' }));
|
|
689
|
+
} else {
|
|
690
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
691
|
+
res.end(JSON.stringify({ ok: false, error: 'No accessible model found for this key. Check that your key has inference permissions.' }));
|
|
692
|
+
}
|
|
693
|
+
}).catch(e => {
|
|
694
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
695
|
+
res.end(JSON.stringify({ ok: false, error: e.message }));
|
|
696
|
+
});
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
async function apiSetupDetectKey(req, res, url) {
|
|
701
|
+
// Detect API credentials from external sources (NOT .env — that's what we're trying to populate).
|
|
702
|
+
// Provider-aware: ?provider=openai|google|anthropic. Defaults to anthropic for back-compat.
|
|
703
|
+
const detectProvider = _deps.sanitizeSetupProviderType(url.searchParams.get('provider') || 'anthropic') || 'anthropic';
|
|
704
|
+
|
|
705
|
+
// Helper: read a shell env var via the user's login shell so we get values
|
|
706
|
+
// sourced from .zshrc / .bashrc / etc., not just our parent process.
|
|
707
|
+
const readShellEnv = (varName) => {
|
|
708
|
+
return _deps.readUserShellEnv(varName, 6);
|
|
709
|
+
};
|
|
710
|
+
|
|
711
|
+
// ── OpenAI branch: shell env OPENAI_API_KEY → fallback to codex CLI suggestion
|
|
712
|
+
if (detectProvider === 'openai') {
|
|
713
|
+
const respond = (data) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)); };
|
|
714
|
+
const openaiKey = readShellEnv('OPENAI_API_KEY');
|
|
715
|
+
if (openaiKey && openaiKey.startsWith('sk-')) {
|
|
716
|
+
return respond({ found: true, key: openaiKey, source: 'shell environment (OPENAI_API_KEY)', provider: 'openai' });
|
|
717
|
+
}
|
|
718
|
+
// No API key — probe codex CLI as a Strategy-2 (subscription) suggestion.
|
|
719
|
+
try {
|
|
720
|
+
if (!_deps.hostIdentityAccessAllowed({ configDir: _deps.CONFIG_DIR })) throw new Error('host identity access not allowed');
|
|
721
|
+
const proc = require('child_process').spawnSync(_deps.resolveAgentCliCommand('codex'), ['login', 'status'], { encoding: 'utf8', timeout: 8000 });
|
|
722
|
+
if (proc.status === 0) {
|
|
723
|
+
const stdout = (proc.stdout || '').trim();
|
|
724
|
+
// Output is freeform like "Logged in using ChatGPT". Surface presence + try to parse account email.
|
|
725
|
+
const emailMatch = stdout.match(/[\w.+-]+@[\w-]+\.[\w.-]+/);
|
|
726
|
+
let plan = null;
|
|
727
|
+
try {
|
|
728
|
+
const auth = JSON.parse(require('fs').readFileSync(_deps.codexPaths.codexAuthPath(), 'utf8'));
|
|
729
|
+
const accessToken = auth?.tokens?.access_token;
|
|
730
|
+
if (accessToken) {
|
|
731
|
+
const parts = accessToken.split('.');
|
|
732
|
+
if (parts.length >= 2) {
|
|
733
|
+
const pad = '='.repeat((-parts[1].length) & 3);
|
|
734
|
+
const payload = JSON.parse(Buffer.from(parts[1] + pad, 'base64url').toString('utf8'));
|
|
735
|
+
plan = payload?.['https://api.openai.com/auth']?.chatgpt_plan_type || null;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
} catch { /* best-effort */ }
|
|
739
|
+
return respond({
|
|
740
|
+
found: false,
|
|
741
|
+
provider: 'openai',
|
|
742
|
+
codex_available: true,
|
|
743
|
+
codex_status: stdout,
|
|
744
|
+
codex_email: emailMatch ? emailMatch[0] : null,
|
|
745
|
+
codex_plan: plan,
|
|
746
|
+
hint: 'No OPENAI_API_KEY in shell env. Codex CLI is logged in — use it for subscription billing instead.',
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
} catch { /* codex not on PATH — fine */ }
|
|
750
|
+
return respond({ found: false, provider: 'openai', hint: 'No OPENAI_API_KEY in shell env. Get a key at platform.openai.com OR install Codex CLI from chatgpt.com/codex' });
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// ── DeepSeek branch: shell env DEEPSEEK_API_KEY only (no CLI subscription path).
|
|
754
|
+
if (detectProvider === 'deepseek') {
|
|
755
|
+
const respond = (data) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)); };
|
|
756
|
+
const dsKey = readShellEnv('DEEPSEEK_API_KEY');
|
|
757
|
+
if (dsKey && dsKey.startsWith('sk-')) {
|
|
758
|
+
return respond({ found: true, key: dsKey, source: 'shell environment (DEEPSEEK_API_KEY)', provider: 'deepseek' });
|
|
759
|
+
}
|
|
760
|
+
return respond({ found: false, provider: 'deepseek', hint: 'No DEEPSEEK_API_KEY in shell env. Get a key at platform.deepseek.com (prepaid — top up first).' });
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// ── Moonshot / Kimi branch: shell env MOONSHOT_API_KEY only.
|
|
764
|
+
if (detectProvider === 'moonshot') {
|
|
765
|
+
const respond = (data) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)); };
|
|
766
|
+
const moonshotKey = readShellEnv('MOONSHOT_API_KEY');
|
|
767
|
+
if (moonshotKey) {
|
|
768
|
+
return respond({ found: true, key: moonshotKey, source: 'shell environment (MOONSHOT_API_KEY)', provider: 'moonshot' });
|
|
769
|
+
}
|
|
770
|
+
return respond({ found: false, provider: 'moonshot', hint: 'No MOONSHOT_API_KEY in shell env. Get a key from the Kimi Open Platform console.' });
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// ── Z.AI branch: shell env ZAI_API_KEY only.
|
|
774
|
+
if (detectProvider === 'zai') {
|
|
775
|
+
const respond = (data) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)); };
|
|
776
|
+
const zaiKey = readShellEnv('ZAI_API_KEY');
|
|
777
|
+
if (zaiKey) {
|
|
778
|
+
return respond({ found: true, key: zaiKey, source: 'shell environment (ZAI_API_KEY)', provider: 'zai' });
|
|
779
|
+
}
|
|
780
|
+
return respond({ found: false, provider: 'zai', hint: 'No ZAI_API_KEY in shell env. Get a key from the Z.AI Open Platform.' });
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// ── Google branch: shell env GOOGLE_API_KEY / GEMINI_API_KEY → fallback to Gemini CLI OAuth
|
|
784
|
+
if (detectProvider === 'google') {
|
|
785
|
+
const respond = (data) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)); };
|
|
786
|
+
const googleKey = readShellEnv('GOOGLE_API_KEY') || readShellEnv('GEMINI_API_KEY');
|
|
787
|
+
if (googleKey && !googleKey.startsWith('ya29.')) {
|
|
788
|
+
const which = readShellEnv('GOOGLE_API_KEY') ? 'GOOGLE_API_KEY' : 'GEMINI_API_KEY';
|
|
789
|
+
return respond({ found: true, key: googleKey, source: `shell environment (${which})`, provider: 'google' });
|
|
790
|
+
}
|
|
791
|
+
// Fallback to Gemini CLI's OAuth file (existing /api/setup/detect-gemini-cli handles this richly).
|
|
792
|
+
return respond({ found: false, provider: 'google', hint: 'No GOOGLE_API_KEY/GEMINI_API_KEY in shell env. Use the Gemini CLI auto-detection if installed, or get a key at aistudio.google.com/apikey' });
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// ── Anthropic branch: existing logic (devbox / Keychain / shell env). Falls through.
|
|
796
|
+
let key = '';
|
|
797
|
+
let source = '';
|
|
798
|
+
let gateway = null;
|
|
799
|
+
|
|
800
|
+
// 1. Devbox corporate gateway (reads auth headers file directly)
|
|
801
|
+
if (process.platform === 'darwin') {
|
|
802
|
+
try {
|
|
803
|
+
const authFile = _deps.path.join(_deps.serverConfig.HOME, '.devbox', 'secrets', 'claude', 'auth_headers');
|
|
804
|
+
const headers = _deps.fs.readFileSync(authFile, 'utf8').trim();
|
|
805
|
+
if (headers) {
|
|
806
|
+
let baseUrl = '';
|
|
807
|
+
try {
|
|
808
|
+
const claudeScript = _deps.fs.readFileSync(_deps.path.join(_deps.serverConfig.HOME, '.devbox', 'ai', 'claude', 'claude'), 'utf8');
|
|
809
|
+
const m = claudeScript.match(/VPN_CHECK_URL="(https?:\/\/[^"]+)"/);
|
|
810
|
+
if (m) baseUrl = m[1] + '/v1';
|
|
811
|
+
} catch {}
|
|
812
|
+
if (baseUrl) {
|
|
813
|
+
gateway = {
|
|
814
|
+
base_url: baseUrl,
|
|
815
|
+
auth_token: 'sk-ant-api03-unused',
|
|
816
|
+
custom_headers_b64: Buffer.from(headers).toString('base64'),
|
|
817
|
+
};
|
|
818
|
+
source = 'Claude Code devbox (' + baseUrl.replace(/https?:\/\//, '').split('/')[0] + ')';
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
} catch {}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// 2. Claude Code OAuth token from macOS Keychain (checked before shell env — always freshest)
|
|
825
|
+
if (!gateway && !key && process.platform === 'darwin' && _deps.hostIdentityAccessAllowed({ configDir: _deps.CONFIG_DIR })) {
|
|
826
|
+
try {
|
|
827
|
+
const credJson = _deps.execFileSync('security', ['find-generic-password', '-s', 'Claude Code-credentials', '-w'], { encoding: 'utf8', timeout: 3000 }).trim();
|
|
828
|
+
if (credJson) {
|
|
829
|
+
const cred = JSON.parse(credJson);
|
|
830
|
+
const oauth = cred.claudeAiOauth;
|
|
831
|
+
if (oauth && oauth.accessToken) {
|
|
832
|
+
const expired = oauth.expiresAt && oauth.expiresAt < Date.now();
|
|
833
|
+
if (!expired) {
|
|
834
|
+
key = oauth.accessToken;
|
|
835
|
+
source = 'Claude Code (OAuth)';
|
|
836
|
+
} else {
|
|
837
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
838
|
+
res.end(JSON.stringify({ found: false, claude_code_expired: true, hint: 'Found Claude Code, but the OAuth token has expired. Run "claude" in your terminal once to refresh it, then click Detect again.' }));
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
} catch {}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// 3. Shell environment (fallback — may be stale if sourced from a previous .env)
|
|
847
|
+
if (!gateway && !key) {
|
|
848
|
+
try {
|
|
849
|
+
const result = _deps.readUserShellEnv('ANTHROPIC_API_KEY', 6);
|
|
850
|
+
if (result && result.length > 5 && result !== 'sk-ant-api03-unused') {
|
|
851
|
+
key = result;
|
|
852
|
+
source = 'shell environment';
|
|
853
|
+
}
|
|
854
|
+
} catch {}
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
if (!gateway && !key) {
|
|
858
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
859
|
+
res.end(JSON.stringify({ found: false, hint: 'No API key found. Checked: Claude Code keychain, shell environment, devbox auth. Enter your key manually or get one at console.anthropic.com' }));
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// Probe API to discover the best model accessible with this key
|
|
864
|
+
const probeKey = key || (gateway ? gateway.auth_token : '');
|
|
865
|
+
const probeBase = gateway ? gateway.base_url : 'https://api.anthropic.com';
|
|
866
|
+
const probeHeaders = gateway ? gateway.custom_headers_b64 : null;
|
|
867
|
+
_deps.probeModel(probeKey, probeBase, probeHeaders).then(({ model: detectedModel }) => {
|
|
868
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
869
|
+
if (gateway) {
|
|
870
|
+
res.end(JSON.stringify({ found: true, gateway, source, ...(detectedModel ? { model: detectedModel } : {}) }));
|
|
871
|
+
} else {
|
|
872
|
+
res.end(JSON.stringify({ found: true, key, source, ...(detectedModel ? { model: detectedModel } : {}) }));
|
|
873
|
+
}
|
|
874
|
+
}).catch(() => {
|
|
875
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
876
|
+
if (gateway) {
|
|
877
|
+
res.end(JSON.stringify({ found: true, gateway, source }));
|
|
878
|
+
} else {
|
|
879
|
+
res.end(JSON.stringify({ found: true, key, source }));
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
async function apiSetupSave(req, res, url) {
|
|
886
|
+
let body = '';
|
|
887
|
+
let bodyLen = 0;
|
|
888
|
+
req.on('data', c => {
|
|
889
|
+
bodyLen += c.length;
|
|
890
|
+
if (bodyLen > 8192) { req.destroy(); return; } // 8KB limit
|
|
891
|
+
body += c;
|
|
892
|
+
});
|
|
893
|
+
req.on('end', async () => {
|
|
894
|
+
try {
|
|
895
|
+
const data = JSON.parse(body);
|
|
896
|
+
// Validate and sanitize inputs
|
|
897
|
+
const ownerName = typeof data.owner_name === 'string'
|
|
898
|
+
? data.owner_name.replace(/[\r\n=]/g, '').trim().slice(0, 200)
|
|
899
|
+
: '';
|
|
900
|
+
const apiKey = typeof data.api_key === 'string'
|
|
901
|
+
? data.api_key.replace(/[\r\n\s]/g, '').slice(0, 200)
|
|
902
|
+
: '';
|
|
903
|
+
// Gateway config (corporate Portkey/cybertron setups) — sanitize values
|
|
904
|
+
let gw = null;
|
|
905
|
+
if (data.gateway && data.gateway.base_url) {
|
|
906
|
+
gw = {
|
|
907
|
+
base_url: String(data.gateway.base_url).replace(/[\r\n]/g, '').slice(0, 500),
|
|
908
|
+
auth_token: String(data.gateway.auth_token || 'sk-ant-api03-unused').replace(/[\r\n]/g, '').slice(0, 500),
|
|
909
|
+
custom_headers_b64: String(data.gateway.custom_headers_b64 || '').replace(/[\r\n\s]/g, '').slice(0, 2000),
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
const walleModel = typeof data.model === 'string'
|
|
913
|
+
? data.model.replace(/[\r\n\s]/g, '').slice(0, 100)
|
|
914
|
+
: '';
|
|
915
|
+
const walleProvider = _deps.sanitizeSetupProviderType(data.provider);
|
|
916
|
+
if (walleProvider && !_deps.SETUP_PROVIDER_TYPES.includes(walleProvider)) {
|
|
917
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
918
|
+
res.end(JSON.stringify({ error: 'Invalid provider type. Must be one of: ' + _deps.setupProviderTypeList() }));
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
const providerForApiKey = walleProvider || 'anthropic';
|
|
922
|
+
// Anthropic auth_method picker: 'api_key' (default), 'claude_cli', or
|
|
923
|
+
// 'oauth_proxy'. Anything else gets normalized to '' (= cleared).
|
|
924
|
+
// OpenAI auth_method picker: 'api_key' (default) or 'codex_cli'.
|
|
925
|
+
const anthropicAuthMethods = new Set(['api_key', 'claude_cli', 'oauth_proxy']);
|
|
926
|
+
const openaiAuthMethods = new Set(['api_key', 'codex_cli']);
|
|
927
|
+
const validForProvider = walleProvider === 'anthropic'
|
|
928
|
+
? anthropicAuthMethods
|
|
929
|
+
: walleProvider === 'openai'
|
|
930
|
+
? openaiAuthMethods
|
|
931
|
+
: new Set();
|
|
932
|
+
const authMethod = validForProvider.has(data.auth_method) ? data.auth_method : '';
|
|
933
|
+
// coding_via_cli: route the coding agent through `claude -p` (subscription
|
|
934
|
+
// billing) even when the primary auth is api_key. Stored as
|
|
935
|
+
// WALLE_CODING_USE_CLI=true|false to match what coding-orchestrator reads.
|
|
936
|
+
const codingViaCli = walleProvider === 'anthropic' && data.coding_via_cli === true;
|
|
937
|
+
// Accept any non-empty key (Anthropic, Portkey, or other providers)
|
|
938
|
+
const envPath = _deps.resolveEnvFilePath({ repoRoot: _deps.path.resolve(_deps.__dirname, '..'), dataDir: _deps.CONFIG_DIR });
|
|
939
|
+
const lines = [];
|
|
940
|
+
// Build set of keys to strip
|
|
941
|
+
const keysToReplace = new Set();
|
|
942
|
+
if (ownerName) keysToReplace.add('WALLE_OWNER_NAME');
|
|
943
|
+
// WALLE_AUTH_METHOD applies to anthropic (api_key/claude_cli/oauth_proxy)
|
|
944
|
+
// AND openai (api_key/codex_cli). WALLE_CODING_USE_CLI is anthropic-only.
|
|
945
|
+
if (walleProvider === 'anthropic' || walleProvider === 'openai') {
|
|
946
|
+
keysToReplace.add('WALLE_AUTH_METHOD');
|
|
947
|
+
}
|
|
948
|
+
if (walleProvider === 'anthropic') {
|
|
949
|
+
keysToReplace.add('WALLE_CODING_USE_CLI');
|
|
950
|
+
}
|
|
951
|
+
if (gw) {
|
|
952
|
+
// Gateway: strip Anthropic direct key vars
|
|
953
|
+
keysToReplace.add('ANTHROPIC_API_KEY');
|
|
954
|
+
keysToReplace.add('ANTHROPIC_BASE_URL');
|
|
955
|
+
keysToReplace.add('ANTHROPIC_AUTH_TOKEN');
|
|
956
|
+
keysToReplace.add('ANTHROPIC_CUSTOM_HEADERS_B64');
|
|
957
|
+
} else if (apiKey) {
|
|
958
|
+
// Only strip the key for the provider being configured — preserve others
|
|
959
|
+
if (providerForApiKey === 'openai') { keysToReplace.add('OPENAI_API_KEY'); }
|
|
960
|
+
else if (providerForApiKey === 'google') { keysToReplace.add('GOOGLE_API_KEY'); keysToReplace.add('GEMINI_API_KEY'); keysToReplace.add('GOOGLE_AUTH_MODE'); keysToReplace.add('GOOGLE_REFRESH_TOKEN'); }
|
|
961
|
+
else if (providerForApiKey === 'deepseek') { keysToReplace.add('DEEPSEEK_API_KEY'); }
|
|
962
|
+
else if (providerForApiKey === 'moonshot') { keysToReplace.add('MOONSHOT_API_KEY'); }
|
|
963
|
+
else if (providerForApiKey === 'zai') { keysToReplace.add('ZAI_API_KEY'); }
|
|
964
|
+
else if (providerForApiKey === 'anthropic') { keysToReplace.add('ANTHROPIC_API_KEY'); keysToReplace.add('ANTHROPIC_BASE_URL'); keysToReplace.add('ANTHROPIC_AUTH_TOKEN'); keysToReplace.add('ANTHROPIC_CUSTOM_HEADERS_B64'); }
|
|
965
|
+
}
|
|
966
|
+
// Read existing .env, keep lines that aren't being replaced
|
|
967
|
+
try {
|
|
968
|
+
const existing = _deps.fs.readFileSync(envPath, 'utf8');
|
|
969
|
+
for (const line of existing.split('\n')) {
|
|
970
|
+
const m = line.match(/^\s*#?\s*([A-Z0-9_]+)\s*=/);
|
|
971
|
+
if (m && keysToReplace.has(m[1])) continue; // skip — will re-add below
|
|
972
|
+
lines.push(line);
|
|
973
|
+
}
|
|
974
|
+
} catch { lines.push('# Wall-E configuration'); lines.push(''); }
|
|
975
|
+
// Strip trailing blank lines
|
|
976
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === '') lines.pop();
|
|
977
|
+
lines.push('');
|
|
978
|
+
// Add new values
|
|
979
|
+
if (ownerName) {
|
|
980
|
+
lines.push(`WALLE_OWNER_NAME=${ownerName}`);
|
|
981
|
+
_deps.serverConfig.override("WALLE_OWNER_NAME", ownerName, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
982
|
+
}
|
|
983
|
+
// WALLE_AUTH_METHOD persistence — applies to anthropic AND openai.
|
|
984
|
+
if (walleProvider === 'anthropic' || walleProvider === 'openai') {
|
|
985
|
+
if (authMethod) {
|
|
986
|
+
lines.push(`WALLE_AUTH_METHOD=${authMethod}`);
|
|
987
|
+
_deps.serverConfig.override("WALLE_AUTH_METHOD", authMethod, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
988
|
+
} else {
|
|
989
|
+
delete _deps.serverConfig.WALLE_AUTH_METHOD;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
// WALLE_CODING_USE_CLI is anthropic-only (claude -p override for the
|
|
993
|
+
// coding agent). Codex's equivalent path is auth_method=codex_cli itself.
|
|
994
|
+
if (walleProvider === 'anthropic') {
|
|
995
|
+
if (codingViaCli) {
|
|
996
|
+
lines.push(`WALLE_CODING_USE_CLI=true`);
|
|
997
|
+
_deps.serverConfig.override("WALLE_CODING_USE_CLI", 'true', 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
998
|
+
} else {
|
|
999
|
+
delete _deps.serverConfig.WALLE_CODING_USE_CLI;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
if (gw) {
|
|
1003
|
+
// Gateway setup: save gateway vars, clear direct API key
|
|
1004
|
+
lines.push(`ANTHROPIC_BASE_URL=${gw.base_url}`);
|
|
1005
|
+
lines.push(`ANTHROPIC_AUTH_TOKEN=${gw.auth_token}`);
|
|
1006
|
+
lines.push(`ANTHROPIC_CUSTOM_HEADERS_B64=${gw.custom_headers_b64}`);
|
|
1007
|
+
_deps.serverConfig.override("ANTHROPIC_BASE_URL", gw.base_url, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1008
|
+
_deps.serverConfig.override("ANTHROPIC_AUTH_TOKEN", gw.auth_token, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1009
|
+
_deps.serverConfig.override("ANTHROPIC_CUSTOM_HEADERS_B64", gw.custom_headers_b64, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1010
|
+
delete _deps.serverConfig.ANTHROPIC_API_KEY;
|
|
1011
|
+
} else if (apiKey) {
|
|
1012
|
+
// Save key under the correct provider env var
|
|
1013
|
+
if (providerForApiKey === 'openai') {
|
|
1014
|
+
lines.push(`OPENAI_API_KEY=${apiKey}`);
|
|
1015
|
+
_deps.serverConfig.override("OPENAI_API_KEY", apiKey, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1016
|
+
} else if (providerForApiKey === 'google') {
|
|
1017
|
+
const googleAuthMode = typeof data.google_auth_mode === 'string' ? data.google_auth_mode.replace(/[^a-z]/g, '') : '';
|
|
1018
|
+
const googleRefreshToken = typeof data.google_refresh_token === 'string' ? data.google_refresh_token.replace(/[\r\n]/g, '').slice(0, 2000) : '';
|
|
1019
|
+
lines.push(`GOOGLE_API_KEY=${apiKey}`);
|
|
1020
|
+
_deps.serverConfig.override("GOOGLE_API_KEY", apiKey, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1021
|
+
if (googleAuthMode === 'oauth' && googleRefreshToken) {
|
|
1022
|
+
lines.push(`GOOGLE_AUTH_MODE=oauth`);
|
|
1023
|
+
lines.push(`GOOGLE_REFRESH_TOKEN=${googleRefreshToken}`);
|
|
1024
|
+
_deps.serverConfig.override("GOOGLE_AUTH_MODE", 'oauth', 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1025
|
+
_deps.serverConfig.override("GOOGLE_REFRESH_TOKEN", googleRefreshToken, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1026
|
+
} else {
|
|
1027
|
+
delete _deps.serverConfig.GOOGLE_AUTH_MODE;
|
|
1028
|
+
delete _deps.serverConfig.GOOGLE_REFRESH_TOKEN;
|
|
1029
|
+
}
|
|
1030
|
+
} else if (providerForApiKey === 'deepseek') {
|
|
1031
|
+
lines.push(`DEEPSEEK_API_KEY=${apiKey}`);
|
|
1032
|
+
_deps.serverConfig.override("DEEPSEEK_API_KEY", apiKey, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1033
|
+
} else if (providerForApiKey === 'moonshot') {
|
|
1034
|
+
lines.push(`MOONSHOT_API_KEY=${apiKey}`);
|
|
1035
|
+
_deps.serverConfig.override("MOONSHOT_API_KEY", apiKey, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1036
|
+
} else if (providerForApiKey === 'zai') {
|
|
1037
|
+
lines.push(`ZAI_API_KEY=${apiKey}`);
|
|
1038
|
+
_deps.serverConfig.override("ZAI_API_KEY", apiKey, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1039
|
+
} else if (providerForApiKey === 'anthropic') {
|
|
1040
|
+
// Default: Anthropic
|
|
1041
|
+
lines.push(`ANTHROPIC_API_KEY=${apiKey}`);
|
|
1042
|
+
_deps.serverConfig.override("ANTHROPIC_API_KEY", apiKey, 'ctm-config-seam: migrated write site (WP-4 AC-4c)');
|
|
1043
|
+
delete _deps.serverConfig.ANTHROPIC_BASE_URL;
|
|
1044
|
+
delete _deps.serverConfig.ANTHROPIC_AUTH_TOKEN;
|
|
1045
|
+
delete _deps.serverConfig.ANTHROPIC_CUSTOM_HEADERS_B64;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
_deps.atomicWriteFileSync(envPath, lines.join('\n') + '\n', { mode: 0o600 });
|
|
1049
|
+
_deps.setup.clearSetupCache(); // so next / request goes to dashboard
|
|
1050
|
+
_deps.telemetry.track('ctm_setup_save', { has_key: !!(apiKey || gw), has_model: !!walleModel });
|
|
1051
|
+
|
|
1052
|
+
// Persist provider config through Wall-E, which owns its brain DB.
|
|
1053
|
+
try {
|
|
1054
|
+
await _deps.walleClient.requestJson('/api/wall-e/setup/config', {
|
|
1055
|
+
method: 'POST',
|
|
1056
|
+
body: {
|
|
1057
|
+
provider: walleProvider,
|
|
1058
|
+
model: walleModel,
|
|
1059
|
+
ownerName,
|
|
1060
|
+
providerConfig: walleProvider ? {
|
|
1061
|
+
id: `${walleProvider}-default`,
|
|
1062
|
+
baseUrl: gw ? gw.base_url : null,
|
|
1063
|
+
apiKeyEncrypted: gw ? gw.auth_token : (apiKey || null),
|
|
1064
|
+
customHeaders: gw ? gw.custom_headers_b64 : null,
|
|
1065
|
+
} : null,
|
|
1066
|
+
},
|
|
1067
|
+
});
|
|
1068
|
+
} catch (dbErr) {
|
|
1069
|
+
console.error('[setup] Failed to persist Wall-E config:', dbErr.message);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// Restart Wall-E so it picks up new config
|
|
1073
|
+
if (apiKey || gw || walleModel || walleProvider) {
|
|
1074
|
+
_deps.walleSupervisor.restartQuiet();
|
|
1075
|
+
}
|
|
1076
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1077
|
+
res.end(JSON.stringify({ ok: true }));
|
|
1078
|
+
} catch (e) {
|
|
1079
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1080
|
+
res.end(JSON.stringify({ error: e.message }));
|
|
1081
|
+
}
|
|
1082
|
+
});
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// WP-5 shard S2: the three verbatim bodies above are appended here by
|
|
1087
|
+
// bin/move-only-check.js's proof (identical to server.js's declarations up to
|
|
1088
|
+
// the `_deps.` prefix).
|
|
1089
|
+
module.exports = { configure, register, apiSetupTestKey, apiSetupDetectKey, apiSetupSave };
|