create-walle 0.10.1 → 0.10.2
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 +4 -0
- 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 +6 -4
- 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 +10 -22
- package/template/coding-task-manager/bin/claude-hook.js +7 -3
- 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/lead-wait-census.js +1348 -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 +705 -286
- package/template/coding-task-manager/git-utils.js +44 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +4 -0
- package/template/coding-task-manager/lib/agent-presets.js +15 -0
- 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/api/host-stats.js +98 -0
- package/template/coding-task-manager/lib/api/ingress.js +35 -12
- 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 +461 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +20 -5
- package/template/coding-task-manager/lib/api/providers.js +53 -6
- package/template/coding-task-manager/lib/api/resume-from-store.js +25 -0
- package/template/coding-task-manager/lib/api/sessions.js +160 -8
- package/template/coding-task-manager/lib/api/transcript-history.js +17 -4
- 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/auth-context.js +32 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +41 -1
- package/template/coding-task-manager/lib/auth-rules.js +186 -45
- package/template/coding-task-manager/lib/broadcast-serialize.js +2 -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/claude-markdown-ansi.js +27 -85
- 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/client-diag-handler.js +5 -0
- package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
- package/template/coding-task-manager/lib/codex-harness-qualification.js +12 -0
- 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/coding-agent-models.js +21 -30
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +27 -2
- package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +1 -2
- package/template/coding-task-manager/lib/coding-session-model-state.js +10 -0
- package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
- package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +8 -1
- package/template/coding-task-manager/lib/ctm-boot-lifecycle.js +17 -1
- package/template/coding-task-manager/lib/db-domain-tables.js +7 -0
- package/template/coding-task-manager/lib/db-domains.js +21 -2
- package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -0
- package/template/coding-task-manager/lib/db-schema-source-files.js +1 -0
- package/template/coding-task-manager/lib/feature-manifest.js +1 -1
- package/template/coding-task-manager/lib/fs-watcher.js +3 -2
- package/template/coding-task-manager/lib/harness-history-transition.js +3 -3
- 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 +55 -17
- package/template/coding-task-manager/lib/host-control-dial.js +167 -0
- package/template/coding-task-manager/lib/host-handoff-orchestrator.js +16 -2
- package/template/coding-task-manager/lib/host-handoff.js +51 -13
- 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 +328 -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 +113 -5
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +4 -0
- package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
- package/template/coding-task-manager/lib/instance-manifest.js +13 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +15 -0
- package/template/coding-task-manager/lib/launch-model-override.js +160 -1
- package/template/coding-task-manager/lib/launch-plan-worker.js +59 -2
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +57 -4
- package/template/coding-task-manager/lib/lead-model-switch.js +3 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +61 -3
- package/template/coding-task-manager/lib/legacy-draft-cancellation-recovery.js +111 -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 +749 -0
- package/template/coding-task-manager/lib/machine-self.js +66 -0
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +52 -4
- 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/migrations/v56-host-samples-and-machine-pool.js +76 -0
- package/template/coding-task-manager/lib/mirror-feed-sanitize.js +12 -3
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -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/stream-accounting.js +205 -0
- package/template/coding-task-manager/lib/model-proxy/tokens.js +78 -0
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-history-control.js +2 -2
- package/template/coding-task-manager/lib/native-lead-settings-client.js +2 -1
- package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +628 -64
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +14 -0
- package/template/coding-task-manager/lib/painted-row-recorder.js +9 -1
- package/template/coding-task-manager/lib/prompt-submission-contract.js +21 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +192 -9
- package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
- 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 +5 -2
- package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
- package/template/coding-task-manager/lib/recent-catalog-query.js +26 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +9 -0
- 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 +1062 -0
- package/template/coding-task-manager/lib/remote-machine-create.js +693 -0
- package/template/coding-task-manager/lib/remote-machine-link.js +939 -0
- package/template/coding-task-manager/lib/remote-machine-proxy.js +520 -0
- package/template/coding-task-manager/lib/remote-session-forward.js +306 -0
- package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
- 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/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 +17 -0
- package/template/coding-task-manager/lib/root-delivery-runtime.js +72 -15
- 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 +167 -33
- 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-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/delegate-worker.js +95 -6
- package/template/coding-task-manager/lib/session-create/identity.js +20 -1
- package/template/coding-task-manager/lib/session-create/prepared.js +69 -1
- 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 +34 -37
- package/template/coding-task-manager/lib/session-create/response.js +30 -12
- package/template/coding-task-manager/lib/session-create/transcript.js +13 -4
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +43 -1
- package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
- package/template/coding-task-manager/lib/session-create/worker-observability.js +99 -7
- 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-geometry-authority-handler.js +10 -1
- package/template/coding-task-manager/lib/session-host-manager.js +152 -206
- package/template/coding-task-manager/lib/session-jobs.js +17 -9
- package/template/coding-task-manager/lib/session-lifecycle.js +18 -0
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +9 -0
- 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 +42 -3
- 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/startup-pointer-write.js +57 -0
- 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 +21 -22
- 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/terminal-draft-http-status.js +25 -0
- package/template/coding-task-manager/lib/transcript-archiver.js +229 -229
- package/template/coding-task-manager/lib/transcript-frame-cache.js +12 -2
- 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 +8 -3
- package/template/coding-task-manager/lib/transcript-store.js +40 -0
- package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
- package/template/coding-task-manager/lib/typing-interaction-trace.js +92 -0
- package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
- package/template/coding-task-manager/lib/visible-revision-watchdog.js +8 -12
- package/template/coding-task-manager/lib/wake-skip-reasons.js +46 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +98 -14
- package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +19 -2
- package/template/coding-task-manager/lib/ws/terminal-attach.js +32 -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 +99 -55
- package/template/coding-task-manager/package-lock.json +24 -0
- package/template/coding-task-manager/package.json +3 -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 +279 -1
- package/template/coding-task-manager/public/css/reviews.css +4 -0
- package/template/coding-task-manager/public/index.html +294 -223
- package/template/coding-task-manager/public/js/app/machines-page.js +1252 -0
- package/template/coding-task-manager/public/js/app/models-tab.js +546 -36
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +7 -5
- package/template/coding-task-manager/public/js/background-work.js +13 -7
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +44 -4
- package/template/coding-task-manager/public/js/core/session-commands.js +676 -0
- package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +26 -2
- 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 +436 -0
- 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/queue-panel-submission-reconcile.js +174 -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 +1 -1
- package/template/coding-task-manager/public/js/session-search-utils.js +46 -19
- package/template/coding-task-manager/public/js/state-sync-client.js +4 -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-12.js +52 -2
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +12 -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 +210 -73
- 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-history-viewport.js +1 -1
- package/template/coding-task-manager/public/js/terminal-wheel.js +39 -2
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +11 -3
- package/template/coding-task-manager/public/js/walle-session.js +30 -7
- package/template/coding-task-manager/public/m/app.css +226 -8
- package/template/coding-task-manager/public/m/app.js +502 -9
- package/template/coding-task-manager/public/m/index.html +38 -1
- package/template/coding-task-manager/public/m/machines.js +1313 -0
- package/template/coding-task-manager/public/m/pool-failover.js +391 -0
- 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/queue-engine.js +13 -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 +902 -239
- package/template/coding-task-manager/session-integrity.js +7 -9
- package/template/coding-task-manager/workers/db-owner-worker.js +53 -7
- package/template/coding-task-manager/workers/read-pool-worker.js +17 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +18 -4
- package/template/coding-task-manager/workers/session-host-process.js +14 -3
- package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
- package/template/coding-task-manager/workers/worktree-worker.js +34 -0
- 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/conversation-storage-v2-contract.js +42 -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/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 +35 -3
- package/template/wall-e/agent.js +21 -0
- package/template/wall-e/api-walle.js +5 -0
- package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +12 -6
- package/template/wall-e/brain/helper-rules-schema.js +129 -0
- package/template/wall-e/brain/migrations.js +51 -22
- package/template/wall-e/brain/model-deployment-facts.js +31 -1
- package/template/wall-e/brain/owner-call-whitelist.js +16 -0
- package/template/wall-e/brain/schema-ensures.js +22 -0
- package/template/wall-e/brain.js +1 -1
- package/template/wall-e/coding/journal-dispatcher.js +51 -0
- package/template/wall-e/coding/session-journal.js +28 -40
- package/template/wall-e/coding-orchestrator.js +23 -26
- 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/helper-rules-api.js +321 -0
- package/template/wall-e/http/model-proxy-providers.js +3 -1
- package/template/wall-e/http/telemetry-api.js +12 -0
- 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/client-config-lock.js +2 -1
- package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
- 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 +357 -0
- package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
- package/template/wall-e/lib/helper-rules/grade.js +277 -0
- package/template/wall-e/lib/helper-rules/label.js +247 -0
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +522 -0
- package/template/wall-e/lib/helper-rules/store.js +667 -0
- package/template/wall-e/lib/mcp-integration.js +5 -6
- package/template/wall-e/lib/runtime-worker-pool.js +1 -0
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -0
- 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/model-catalog.js +13 -4
- package/template/wall-e/llm/model-roles.js +6 -0
- 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-mcp-routing.js +61 -0
- package/template/wall-e/llm/worker-route.js +43 -1
- package/template/wall-e/loops/brain-custom-writes.js +45 -0
- package/template/wall-e/mcp-protocol-contract.js +41 -1
- package/template/wall-e/mcp-server.js +13 -2
- package/template/wall-e/mcp-worker-schemas.js +20 -2
- package/template/wall-e/memory/ctm-context-client.js +25 -5
- package/template/wall-e/shared/release-schema.json +3 -2
- package/template/wall-e/shared/sqlite-write-lock.js +361 -223
- package/template/wall-e/shared/storage/contract.js +35 -3
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +6 -0
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +7 -2
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +7 -2
- package/template/wall-e/tools/local-tools.js +6 -4
- package/template/wall-e/workers/brain-owner-worker.js +9 -0
- package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
- package/template/wall-e/workers/telemetry-worker.js +8 -0
|
@@ -53,7 +53,6 @@ const http = require('node:http');
|
|
|
53
53
|
const os = require('node:os');
|
|
54
54
|
const path = require('node:path');
|
|
55
55
|
const { execFile } = require('node:child_process');
|
|
56
|
-
const readline = require('node:readline');
|
|
57
56
|
const { hostIdentityAccessAllowed } = require('./lib/host-identity-access');
|
|
58
57
|
|
|
59
58
|
const { effectiveOutputCap } = require('./lib/model-proxy/output-cap');
|
|
@@ -73,6 +72,9 @@ const { getDataDir } = require('./lib/data-dir');
|
|
|
73
72
|
const { validateLeadWorkerTarget, safeRefusalReason } = require('./lib/model-proxy/lead-request-validation');
|
|
74
73
|
const { buildCodexModelsResponse } = require('./lib/harness-model-profile');
|
|
75
74
|
const legacyRelay = require('./lib/model-proxy/legacy-relay');
|
|
75
|
+
const streamAccountingMod = require('./lib/model-proxy/stream-accounting');
|
|
76
|
+
const instanceRecord = require('./lib/model-proxy/proxy-instance-record');
|
|
77
|
+
const handoff = require('./lib/model-proxy/handoff');
|
|
76
78
|
const {
|
|
77
79
|
unsupportedSafeguards, logReviewDiagnostic,
|
|
78
80
|
} = require('./lib/model-proxy/auto-mode-review');
|
|
@@ -88,6 +90,10 @@ const EBIND_NOT_LOOPBACK = 'EBIND_NOT_LOOPBACK';
|
|
|
88
90
|
// `_health` answer reports it, and it is intentionally NOT per-instance.
|
|
89
91
|
let _abortedStreams = 0;
|
|
90
92
|
|
|
93
|
+
// The context of the server this process started. Read only by the CLI's SIGTERM handler (bottom of
|
|
94
|
+
// this file) — an embedded caller installs no such handler, so nothing else can observe it.
|
|
95
|
+
let _cliExitTarget = null;
|
|
96
|
+
|
|
91
97
|
// ── per-instance context (WP-1 §5 D-3, review item 2) ───────────────────────────────────────────
|
|
92
98
|
//
|
|
93
99
|
// Every start() captures its OWN immutable context: the admin secret, the OAuth resolver, the native
|
|
@@ -120,6 +126,14 @@ function createProxyContext({ adminSecret = null, resolveOauthToken, dataDir, na
|
|
|
120
126
|
// registration and closed by (and only by) this instance's wrapped HTTP server close. It holds the
|
|
121
127
|
// loaded authority's private material and never exposes it.
|
|
122
128
|
nativeListener: null,
|
|
129
|
+
// §5 D-9: THIS server's in-flight stream counter, created here so both the plaintext and the native
|
|
130
|
+
// server feed one number, and so a test can reach it through the context.
|
|
131
|
+
streamAccounting: streamAccountingMod.createStreamAccounting(),
|
|
132
|
+
// §5 D-7 (WP-2): what a handoff hands over -- the listening server, its ports, its generation.
|
|
133
|
+
httpServer: null,
|
|
134
|
+
boundPort: null,
|
|
135
|
+
nativePort: null,
|
|
136
|
+
generation: 1,
|
|
123
137
|
};
|
|
124
138
|
}
|
|
125
139
|
|
|
@@ -319,10 +333,15 @@ async function _handleAdmin(req, res, pathName, ctx) {
|
|
|
319
333
|
// servers each authenticate against their own secret, so A's admin surface can never be opened with
|
|
320
334
|
// B's secret (and B's credential resolver can never be reached through A).
|
|
321
335
|
if (!ctx.adminSecret || typeof suppliedSecret !== 'string' || suppliedSecret !== ctx.adminSecret) {
|
|
336
|
+
// §9 S-9: one line, the finite reason only — never the supplied header value.
|
|
337
|
+
console.log('[model-proxy] refused status=401 reason=admin_unauthorized');
|
|
322
338
|
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
323
339
|
res.end(JSON.stringify({ error: 'admin_unauthorized' }));
|
|
324
340
|
return;
|
|
325
341
|
}
|
|
342
|
+
// §5 D-8 (WP-3): this authenticated request -- and only this -- is "admin contact". `/_health`,
|
|
343
|
+
// `/_status` and a refused secret never reach it, so none of them can hold this proxy open.
|
|
344
|
+
handoff.noteAdminContact();
|
|
326
345
|
|
|
327
346
|
const probeMatch = pathName.match(ADMIN_PROBE_RE);
|
|
328
347
|
if (probeMatch && req.method === 'GET') {
|
|
@@ -364,6 +383,26 @@ async function _handleAdmin(req, res, pathName, ctx) {
|
|
|
364
383
|
}
|
|
365
384
|
}
|
|
366
385
|
|
|
386
|
+
// §5 D-7 (WP-2): upgrade by handoff. The successor is always spawned from THIS file's path on disk and
|
|
387
|
+
// the body may carry the two bounded deadlines (test overrides), never a script or a port; a 409
|
|
388
|
+
// leaves this proxy serving exactly as it was.
|
|
389
|
+
if (pathName === '/_admin/handoff' && req.method === 'POST') {
|
|
390
|
+
const result = await handoff.initiateHandoff({
|
|
391
|
+
ctx, httpServer: ctx.httpServer, nativeListener: ctx.nativeListener, dataDir: ctx.dataDir,
|
|
392
|
+
port: ctx.boundPort, nativePort: ctx.nativePort, adminSecret: ctx.adminSecret,
|
|
393
|
+
generation: ctx.generation,
|
|
394
|
+
readyDeadlineMs: body ? body.readyDeadlineMs : undefined,
|
|
395
|
+
drainDeadlineMs: body ? body.drainDeadlineMs : undefined,
|
|
396
|
+
});
|
|
397
|
+
res.writeHead(result.ok ? 202 : 409, { 'Content-Type': 'application/json' });
|
|
398
|
+
res.end(JSON.stringify(result.ok
|
|
399
|
+
? { ok: true, generation: result.generation, successorPid: result.successorPid, handoffMs: result.handoffMs }
|
|
400
|
+
: { ok: false, reason: result.reason }));
|
|
401
|
+
// The 202 is on the wire BEFORE step 7 is armed, so its exit can never preempt the caller's response.
|
|
402
|
+
if (result.ok) result.armDrain();
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
367
406
|
const workerLeaseMatch = pathName.match(ADMIN_WORKER_LEASE_RE);
|
|
368
407
|
if (workerLeaseMatch && req.method === 'POST') {
|
|
369
408
|
if (!body || !Number.isSafeInteger(body.generation) || !Number.isSafeInteger(body.lease)) {
|
|
@@ -779,6 +818,8 @@ async function _handleRouted(req, res, pathName, trusted = null, ctx = null) {
|
|
|
779
818
|
: null);
|
|
780
819
|
const authz = tokens.authorize(token, alias);
|
|
781
820
|
if (!authz.ok) {
|
|
821
|
+
// §9 S-9: the same finite reason the body carries — never the presented token.
|
|
822
|
+
console.log(`[model-proxy] refused status=401 reason=token ${authz.reason}`);
|
|
782
823
|
faceModule.writeJson(res, 401, faceModule.errorEnvelope('authentication_error', `token ${authz.reason}`));
|
|
783
824
|
return;
|
|
784
825
|
}
|
|
@@ -788,6 +829,7 @@ async function _handleRouted(req, res, pathName, trusted = null, ctx = null) {
|
|
|
788
829
|
// keychain the incident was about. (The reverse direction — a legacy-bearer owner on the TLS lane —
|
|
789
830
|
// is refused by the listener's carrier check.)
|
|
790
831
|
if (!nativeTrusted && tokens.leadTokenNativeTransport(token) === tokens.NATIVE_TRANSPORT_MTLS) {
|
|
832
|
+
console.log('[model-proxy] refused status=401 reason=token native_transport_mismatch'); // §9 S-9
|
|
791
833
|
faceModule.writeJson(res, 401, faceModule.errorEnvelope('authentication_error', 'token native_transport_mismatch'));
|
|
792
834
|
return;
|
|
793
835
|
}
|
|
@@ -1305,6 +1347,11 @@ async function handleRequest(req, res, trusted = null, ctx = null) {
|
|
|
1305
1347
|
if (pathName.startsWith('/r/')) {
|
|
1306
1348
|
return _handleRouted(req, res, pathName, trusted, context);
|
|
1307
1349
|
}
|
|
1350
|
+
if (pathName === '/_health' || pathName === '/_status') {
|
|
1351
|
+
// WP-0 §9 S-8: the relay still builds its own fields; the wrapper merges this process's identity
|
|
1352
|
+
// and live stream count into that same JSON body.
|
|
1353
|
+
return _legacyHandleRequest(req, streamAccountingMod.withHealthFields(res, context.streamAccounting));
|
|
1354
|
+
}
|
|
1308
1355
|
// Legacy: today's OAuth passthrough, byte-for-byte unchanged (AC-0a).
|
|
1309
1356
|
return _legacyHandleRequest(req, res);
|
|
1310
1357
|
}
|
|
@@ -1319,34 +1366,6 @@ async function _handleNativeAuthorizedRequest(req, res, { token, binding, suffix
|
|
|
1319
1366
|
return _handleRouted(req, res, pathName, { native: true, token, binding, suffix, query }, ctx);
|
|
1320
1367
|
}
|
|
1321
1368
|
|
|
1322
|
-
// ── D-4 stdin secret (CLI mode only) ────────────────────────────────────
|
|
1323
|
-
// Reads exactly one line from stdin at process start. Never env, never argv.
|
|
1324
|
-
// Resolves null (no admin secret; admin endpoints stay locked) if stdin is a
|
|
1325
|
-
// TTY or closes without producing a line.
|
|
1326
|
-
function _readAdminSecretFromStdin() {
|
|
1327
|
-
return new Promise((resolve) => {
|
|
1328
|
-
if (!process.stdin || process.stdin.isTTY) {
|
|
1329
|
-
resolve(null);
|
|
1330
|
-
return;
|
|
1331
|
-
}
|
|
1332
|
-
const rl = readline.createInterface({ input: process.stdin, terminal: false });
|
|
1333
|
-
let resolved = false;
|
|
1334
|
-
const finish = (value) => {
|
|
1335
|
-
if (resolved) return;
|
|
1336
|
-
resolved = true;
|
|
1337
|
-
rl.close();
|
|
1338
|
-
resolve(value);
|
|
1339
|
-
};
|
|
1340
|
-
rl.once('line', (line) => finish((line || '').trim() || null));
|
|
1341
|
-
rl.once('close', () => finish(null));
|
|
1342
|
-
});
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
|
-
function _resolveHost() {
|
|
1346
|
-
const raw = process.env.OAUTH_PROXY_HOST;
|
|
1347
|
-
return typeof raw === 'string' && raw.length > 0 ? raw : HOST;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
1369
|
// D-1: bind 127.0.0.1 only. Throws a named error (never a bare listen()
|
|
1351
1370
|
// failure) so both start() callers and the CLI entry can refuse cleanly.
|
|
1352
1371
|
function _assertLoopbackHost(host) {
|
|
@@ -1357,7 +1376,7 @@ function _assertLoopbackHost(host) {
|
|
|
1357
1376
|
}
|
|
1358
1377
|
}
|
|
1359
1378
|
|
|
1360
|
-
function start({ port = PORT, host = HOST, adminSecret = null, resolveOauthToken, dataDir, nativeUpstreamRequest, nativeLoadAuthority } = {}) {
|
|
1379
|
+
function start({ port = PORT, host = HOST, adminSecret = null, resolveOauthToken, dataDir, nativeUpstreamRequest, nativeLoadAuthority, inherited = null, lingerMs = null } = {}) {
|
|
1361
1380
|
try {
|
|
1362
1381
|
_assertLoopbackHost(host);
|
|
1363
1382
|
} catch (err) {
|
|
@@ -1369,6 +1388,7 @@ function start({ port = PORT, host = HOST, adminSecret = null, resolveOauthToken
|
|
|
1369
1388
|
// and gets lib/data-dir's resolver (CTM_DATA_DIR, then WALL_E_DATA_DIR, then the default). None of it
|
|
1370
1389
|
// is ever read from a request, and none of it is shared with another live server.
|
|
1371
1390
|
const ctx = createProxyContext({ adminSecret, resolveOauthToken, dataDir, nativeUpstreamRequest, nativeLoadAuthority });
|
|
1391
|
+
_cliExitTarget = ctx;
|
|
1372
1392
|
const server = http.createServer((req, res) => {
|
|
1373
1393
|
handleRequest(req, res, null, ctx).catch((err) => {
|
|
1374
1394
|
try {
|
|
@@ -1379,24 +1399,31 @@ function start({ port = PORT, host = HOST, adminSecret = null, resolveOauthToken
|
|
|
1379
1399
|
} catch {}
|
|
1380
1400
|
});
|
|
1381
1401
|
});
|
|
1402
|
+
// §5 D-9: this server's plaintext requests feed the same counter the exit record reads.
|
|
1403
|
+
ctx.streamAccounting.track(server);
|
|
1382
1404
|
server.on('error', (err) => {
|
|
1383
1405
|
console.error('[oauth-proxy] server error:', err.message);
|
|
1384
1406
|
});
|
|
1385
1407
|
return new Promise((resolve, reject) => {
|
|
1386
1408
|
server.once('error', reject);
|
|
1387
|
-
|
|
1409
|
+
const onListening = () => {
|
|
1388
1410
|
// The native port is derived from the ACTUAL bound port (never the requested one), so a lease of
|
|
1389
1411
|
// 0 or a config mismatch cannot desynchronize the pair the fixture reserved.
|
|
1390
1412
|
const boundPort = server.address().port;
|
|
1391
1413
|
try {
|
|
1392
1414
|
// This instance's OWN controller, closed by this instance's wrapped server close. A second live
|
|
1393
|
-
// server has its own, so neither can serve the other's registrations.
|
|
1415
|
+
// server has its own, so neither can serve the other's registrations. §5 D-7: a successor binds
|
|
1416
|
+
// the TLS listening socket it was handed instead of the port (S-6), so the native lane has no
|
|
1417
|
+
// re-bind window either.
|
|
1394
1418
|
ctx.nativeListener = createNativeLeadListener({
|
|
1395
1419
|
httpPort: boundPort,
|
|
1396
1420
|
dataDir: ctx.dataDir,
|
|
1421
|
+
// §5 D-9: the native lane is the same process carrying the same requests — one counter.
|
|
1422
|
+
streamAccounting: ctx.streamAccounting,
|
|
1397
1423
|
// The default is the unowned library loader; a host test fixture may inject a gated loader to
|
|
1398
1424
|
// force the admin readiness race at the real HTTP boundary (review item 9).
|
|
1399
1425
|
loadAuthority: ctx.nativeLoadAuthority || undefined,
|
|
1426
|
+
inheritedHandle: inherited ? inherited.nativeHandle : null,
|
|
1400
1427
|
onAuthorizedRequest: (req, res, payload) => _handleNativeAuthorizedRequest(req, res, payload, ctx),
|
|
1401
1428
|
});
|
|
1402
1429
|
// Closing the HTTP server starts the native close immediately (see the wrapper for why the
|
|
@@ -1409,9 +1436,42 @@ function start({ port = PORT, host = HOST, adminSecret = null, resolveOauthToken
|
|
|
1409
1436
|
ctx.nativeListener = null;
|
|
1410
1437
|
console.error(`[oauth-proxy] native lead listener unavailable: ${(err && err.code) || 'native_lead_listener_input_invalid'}`);
|
|
1411
1438
|
}
|
|
1439
|
+
// §5 D-7 step 4: the state that has no other authority arrives with the sockets and is registered
|
|
1440
|
+
// BEFORE this process answers anything -- the token table and the per-token last lead model.
|
|
1441
|
+
if (inherited && inherited.state) {
|
|
1442
|
+
tokens.importAll(inherited.state.tokens);
|
|
1443
|
+
leadWorkerPicks.importLastLeadModel(inherited.state.lastLeadModel);
|
|
1444
|
+
}
|
|
1412
1445
|
console.log(`[oauth-proxy] listening on http://${host}:${port}`);
|
|
1413
|
-
|
|
1414
|
-
|
|
1446
|
+
// §5 D-2/D-3: publish this process's durable identity and hand the same closure to /_health. A
|
|
1447
|
+
// successor publishes generation n+1 and the pid it took over from, so the record names the owner.
|
|
1448
|
+
const record = instanceRecord.publishInstanceRecord({
|
|
1449
|
+
dataDir: ctx.dataDir,
|
|
1450
|
+
port: boundPort,
|
|
1451
|
+
nativePort: ctx.nativeListener ? boundPort + 1 : null,
|
|
1452
|
+
accounting: ctx.streamAccounting,
|
|
1453
|
+
generation: inherited ? inherited.generation : 1,
|
|
1454
|
+
predecessorPid: inherited ? inherited.predecessorPid : null,
|
|
1455
|
+
});
|
|
1456
|
+
ctx.httpServer = server;
|
|
1457
|
+
ctx.boundPort = boundPort;
|
|
1458
|
+
ctx.nativePort = ctx.nativeListener ? boundPort + 1 : null;
|
|
1459
|
+
ctx.generation = record.generation;
|
|
1460
|
+
// §5 D-8: the CLI arms the proxy's own linger once the record is published; an embedded start()
|
|
1461
|
+
// passes no lingerMs, so it can never exit the process that called it.
|
|
1462
|
+
if (lingerMs) handoff.armLinger({ lingerMs, ctx });
|
|
1463
|
+
if (!inherited) {
|
|
1464
|
+
resolve(server);
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
// §5 D-7 step 5: `ready` is the predecessor's permission to stop accepting, so handoff.js sends it
|
|
1468
|
+
// only once this process is genuinely serving (state imported, identity published, TLS re-bound).
|
|
1469
|
+
handoff.announceInheritedStart({ ctx, inherited, record }).then(() => resolve(server));
|
|
1470
|
+
};
|
|
1471
|
+
// §5 D-7 step 4: a successor binds the listening socket it was handed, never (port, host) again --
|
|
1472
|
+
// there is no moment in which the port has no owner.
|
|
1473
|
+
if (inherited && inherited.httpHandle) server.listen(inherited.httpHandle, onListening);
|
|
1474
|
+
else server.listen(port, host, onListening);
|
|
1415
1475
|
});
|
|
1416
1476
|
}
|
|
1417
1477
|
|
|
@@ -1431,26 +1491,10 @@ module.exports = {
|
|
|
1431
1491
|
// failure so exactly-once finalization and listener cleanup are provable without a live relay.
|
|
1432
1492
|
_relayLegacyObserved: legacyRelay._relayLegacyObserved,
|
|
1433
1493
|
EBIND_NOT_LOOPBACK,
|
|
1494
|
+
// WP-2 test seam: the context of the server THIS process started (null for an embedded caller that
|
|
1495
|
+
// never ran the CLI block). proxy-cli's SIGTERM handler reads it; nothing else may.
|
|
1496
|
+
_startedContext: () => _cliExitTarget,
|
|
1434
1497
|
};
|
|
1435
1498
|
|
|
1436
|
-
// CLI mode: `node oauth-proxy.js`
|
|
1437
|
-
if (require.main === module)
|
|
1438
|
-
const host = _resolveHost();
|
|
1439
|
-
if (host !== '127.0.0.1') {
|
|
1440
|
-
// D-1: refuse before ever touching stdin, so a bad --host/env doesn't
|
|
1441
|
-
// hang waiting for an admin secret that will never matter.
|
|
1442
|
-
console.error(`[oauth-proxy] ${EBIND_NOT_LOOPBACK}: refusing to bind to "${host}" — must be 127.0.0.1 (D-1)`);
|
|
1443
|
-
process.exit(78);
|
|
1444
|
-
}
|
|
1445
|
-
_readAdminSecretFromStdin()
|
|
1446
|
-
.catch(() => null)
|
|
1447
|
-
.then((adminSecret) => start({ host, adminSecret }))
|
|
1448
|
-
.catch((err) => {
|
|
1449
|
-
if (err && err.code === EBIND_NOT_LOOPBACK) {
|
|
1450
|
-
console.error(`[oauth-proxy] ${err.code}: ${err.message}`);
|
|
1451
|
-
process.exit(78);
|
|
1452
|
-
}
|
|
1453
|
-
console.error('[oauth-proxy] failed to start:', err.message);
|
|
1454
|
-
process.exit(1);
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1499
|
+
// CLI mode: `node oauth-proxy.js` (or a handoff successor, spawned with an IPC channel).
|
|
1500
|
+
if (require.main === module) require('./lib/model-proxy/proxy-cli').runCli();
|
|
@@ -28,10 +28,13 @@
|
|
|
28
28
|
"proxy-agent": "8.0.2",
|
|
29
29
|
"puppeteer": "25.14.0",
|
|
30
30
|
"qrcode": "^1.5.4",
|
|
31
|
+
"stream-chain": "4.2.6",
|
|
32
|
+
"stream-json": "3.7.0",
|
|
31
33
|
"strip-ansi": "^6.0.1",
|
|
32
34
|
"tree-sitter-bash": "^0.25.1",
|
|
33
35
|
"web-push": "^3.6.7",
|
|
34
36
|
"web-tree-sitter": "^0.26.13",
|
|
37
|
+
"wrap-ansi": "^9.0.2",
|
|
35
38
|
"ws": "8.22.0",
|
|
36
39
|
"yauzl": "3.4.0"
|
|
37
40
|
},
|
|
@@ -3517,6 +3520,27 @@
|
|
|
3517
3520
|
"node": ">= 0.8"
|
|
3518
3521
|
}
|
|
3519
3522
|
},
|
|
3523
|
+
"node_modules/stream-chain": {
|
|
3524
|
+
"version": "4.2.6",
|
|
3525
|
+
"resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-4.2.6.tgz",
|
|
3526
|
+
"integrity": "sha512-1zeJ8CrtJfmiba26ui8jXkq/xLRFvhzkdH02D5QLO9Cnovgeb28IJxg88DdraWnjnkbOol/++uIAybJbJhk7ig==",
|
|
3527
|
+
"license": "BSD-3-Clause",
|
|
3528
|
+
"funding": {
|
|
3529
|
+
"url": "https://github.com/sponsors/uhop"
|
|
3530
|
+
}
|
|
3531
|
+
},
|
|
3532
|
+
"node_modules/stream-json": {
|
|
3533
|
+
"version": "3.7.0",
|
|
3534
|
+
"resolved": "https://registry.npmjs.org/stream-json/-/stream-json-3.7.0.tgz",
|
|
3535
|
+
"integrity": "sha512-rCSBdcBP/bPk6T8QFcxAj1MSzAuc5i49cYW6IE7sYObNEPccBJIUiL6fU9c9BWt40aJK0siVynLX7lWaW8alXw==",
|
|
3536
|
+
"license": "BSD-3-Clause",
|
|
3537
|
+
"dependencies": {
|
|
3538
|
+
"stream-chain": "^4.2.5"
|
|
3539
|
+
},
|
|
3540
|
+
"funding": {
|
|
3541
|
+
"url": "https://github.com/sponsors/uhop"
|
|
3542
|
+
}
|
|
3543
|
+
},
|
|
3520
3544
|
"node_modules/string_decoder": {
|
|
3521
3545
|
"version": "1.3.0",
|
|
3522
3546
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
|
@@ -87,10 +87,13 @@
|
|
|
87
87
|
"puppeteer": "25.14.0",
|
|
88
88
|
"proxy-agent": "8.0.2",
|
|
89
89
|
"qrcode": "^1.5.4",
|
|
90
|
+
"stream-chain": "4.2.6",
|
|
91
|
+
"stream-json": "3.7.0",
|
|
90
92
|
"strip-ansi": "^6.0.1",
|
|
91
93
|
"tree-sitter-bash": "^0.25.1",
|
|
92
94
|
"web-push": "^3.6.7",
|
|
93
95
|
"web-tree-sitter": "^0.26.13",
|
|
96
|
+
"wrap-ansi": "^9.0.2",
|
|
94
97
|
"ws": "8.22.0",
|
|
95
98
|
"yauzl": "3.4.0"
|
|
96
99
|
},
|
|
@@ -1,33 +1,135 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
// Shared extraction of the (server, tool) pair from Codex MCP approval prompts.
|
|
4
|
+
//
|
|
5
|
+
// Codex builds the approval question with
|
|
6
|
+
// format!("Allow {actor} to run tool \"{tool_name}\"?")
|
|
7
|
+
// (codex-rs/core/src/mcp_tool_call.rs), where `actor` is one of
|
|
8
|
+
// - "the <server> MCP server" — an ordinary MCP server (e.g. "the wall-e MCP server"),
|
|
9
|
+
// - "this app" — the built-in app/connector server, connector unnamed,
|
|
10
|
+
// - the connector's display name, e.g. "Google Drive" — also server `codex_apps`.
|
|
4
11
|
// Two on-screen shapes carry the verb:
|
|
5
|
-
//
|
|
6
|
-
//
|
|
12
|
+
// 'Allow <actor> to run tool "<tool>"?' → parseApprovalQuestion
|
|
13
|
+
// "Calling <qualified>" (with or without "({...})") → parseCallingEcho
|
|
14
|
+
//
|
|
15
|
+
// The actor is matched STRUCTURALLY: "the <x> MCP server" / "this app" /
|
|
16
|
+
// anything else. It is never checked against a list of connector names — new
|
|
17
|
+
// connectors must not need a code change to be recognized.
|
|
7
18
|
//
|
|
8
|
-
// Reused by providers/codex-mcp.js (the specific handler)
|
|
9
|
-
// (the generic fallback). This keeps the
|
|
10
|
-
// codex-mcp parser doesn't fire — e.g. a
|
|
11
|
-
// "enter to submit" anchor falls back to
|
|
12
|
-
// bare toolName='MCP' with no verb,
|
|
13
|
-
// from the read/write classifier
|
|
19
|
+
// Reused by providers/codex-mcp.js (the specific handler), providers/codex.js
|
|
20
|
+
// (the generic fallback) AND workers/state-detectors/codex.js. This keeps the
|
|
21
|
+
// MCP verb visible even when the specific codex-mcp parser doesn't fire — e.g. a
|
|
22
|
+
// viewport-wrapped prompt that drops the "enter to submit" anchor falls back to
|
|
23
|
+
// codex.js, which would otherwise emit a bare toolName='MCP' with no verb,
|
|
24
|
+
// hiding read-only calls (search_graph, get_*) from the read/write classifier
|
|
25
|
+
// and stranding them on a manual banner.
|
|
26
|
+
|
|
27
|
+
// The built-in app/connector MCP server id (codex-rs/codex-mcp/src/mcp/mod.rs).
|
|
28
|
+
const CODEX_APPS_SERVER = 'codex_apps';
|
|
29
|
+
|
|
30
|
+
// 'Allow <actor> to run tool "<tool>"?' → the two captures. Anchored at the line
|
|
31
|
+
// start (that guards against prose that merely mentions the question) but tolerant
|
|
32
|
+
// of leading UI decoration: Codex's ratatui borders/footers paint box, bullet and
|
|
33
|
+
// cursor glyphs before the text ("│ Allow …, "• Calling …").
|
|
34
|
+
const APPROVAL_QUESTION_RE = /^[\s│┃║|•◦›❯>*-]*Allow\s+(.+?)\s+to run tool\s+["']?([A-Za-z0-9_.-]+)["']?\s*\?/i;
|
|
35
|
+
// Ordinary MCP servers name themselves in the actor: "the <server> MCP server".
|
|
36
|
+
// Case-insensitive so it agrees with APPROVAL_QUESTION_RE, which accepts "Allow".
|
|
37
|
+
const MCP_SERVER_ACTOR_RE = /^the (\S+) MCP server$/i;
|
|
38
|
+
// The unnamed connector actor.
|
|
39
|
+
const APP_FALLBACK_ACTOR = 'this app';
|
|
40
|
+
// "Calling <qualified>" — a DOTTED token ("server.tool"), as Codex always renders
|
|
41
|
+
// it. The "({...})" argument list is optional (and absent in current builds), but
|
|
42
|
+
// the dot is not: a bare "Calling foo" is prose, not an MCP approval signal.
|
|
43
|
+
const CALLING_ECHO_RE = /\bCalling\s+([A-Za-z0-9_-]+\.[A-Za-z0-9_.-]+)/i;
|
|
14
44
|
|
|
15
|
-
|
|
16
|
-
|
|
45
|
+
// 'Allow <actor> to run tool "<tool>"?' → { actorKind, actor, tool } | null
|
|
46
|
+
// actorKind: 'mcp_server' when actor matches MCP_SERVER_ACTOR_RE (the server
|
|
47
|
+
// name is that capture),
|
|
48
|
+
// 'app_fallback' when actor === 'this app',
|
|
49
|
+
// 'connector' otherwise (any non-empty text).
|
|
50
|
+
function parseApprovalQuestion(line) {
|
|
51
|
+
const match = String(line || '').match(APPROVAL_QUESTION_RE);
|
|
52
|
+
if (!match) return null;
|
|
53
|
+
const actor = match[1].trim();
|
|
54
|
+
const tool = match[2];
|
|
55
|
+
if (!actor || !tool) return null;
|
|
56
|
+
const actorKind = MCP_SERVER_ACTOR_RE.test(actor)
|
|
57
|
+
? 'mcp_server'
|
|
58
|
+
: (actor.toLowerCase() === APP_FALLBACK_ACTOR ? 'app_fallback' : 'connector');
|
|
59
|
+
return { actorKind, actor, tool };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 'Calling <qualified>' with or without a following '(' → { qualified } | null
|
|
63
|
+
// qualified = the dotted token after "Calling " ([A-Za-z0-9_-]+\.[A-Za-z0-9_.-]+),
|
|
64
|
+
// e.g. 'codex_apps.google_drive.update_file'. A dotless "Calling foo" is null.
|
|
65
|
+
function parseCallingEcho(line) {
|
|
66
|
+
const match = String(line || '').match(CALLING_ECHO_RE);
|
|
67
|
+
if (!match) return null;
|
|
68
|
+
return { qualified: match[1] };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// The server for a question whose actor does not name it: the connector/app
|
|
72
|
+
// server is `codex_apps`, but a "Calling" echo above the prompt can still spell
|
|
73
|
+
// out the qualified name — 'codex_apps.google_drive.update_file' with tool
|
|
74
|
+
// 'google_drive.update_file' → 'codex_apps'.
|
|
75
|
+
function serverForQuestion(question, rows) {
|
|
76
|
+
if (question.actorKind === 'mcp_server') {
|
|
77
|
+
const named = MCP_SERVER_ACTOR_RE.exec(question.actor);
|
|
78
|
+
if (named) return named[1];
|
|
79
|
+
}
|
|
80
|
+
const suffix = `.${question.tool}`;
|
|
81
|
+
for (let i = rows.length - 1; i >= 0; i--) {
|
|
82
|
+
const echo = parseCallingEcho(rows[i]);
|
|
83
|
+
if (!echo) continue;
|
|
84
|
+
if (echo.qualified.length > suffix.length && echo.qualified.endsWith(suffix)) {
|
|
85
|
+
return echo.qualified.slice(0, -suffix.length);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return CODEX_APPS_SERVER;
|
|
89
|
+
}
|
|
17
90
|
|
|
18
91
|
// Scan bottom-up (the live prompt is at the end of the viewport). Prefer the
|
|
19
|
-
// explicit
|
|
20
|
-
// "Calling
|
|
92
|
+
// explicit question — its quoted tool name is authoritative — and fall back to
|
|
93
|
+
// the "Calling <qualified>" echo Codex prints just above the approval widget.
|
|
94
|
+
//
|
|
95
|
+
// Returns { server, tool, questionIdx, actorKind } | null. `actorKind` is null
|
|
96
|
+
// on the echo-only path (there is no question actor to classify).
|
|
21
97
|
function extractMcpServerTool(lines) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
98
|
+
const rows = Array.isArray(lines) ? lines : [];
|
|
99
|
+
|
|
100
|
+
for (let i = rows.length - 1; i >= 0; i--) {
|
|
101
|
+
const question = parseApprovalQuestion(rows[i]);
|
|
102
|
+
if (!question) continue;
|
|
103
|
+
return {
|
|
104
|
+
server: serverForQuestion(question, rows),
|
|
105
|
+
tool: question.tool,
|
|
106
|
+
questionIdx: i,
|
|
107
|
+
actorKind: question.actorKind,
|
|
108
|
+
};
|
|
25
109
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
110
|
+
|
|
111
|
+
for (let i = rows.length - 1; i >= 0; i--) {
|
|
112
|
+
const echo = parseCallingEcho(rows[i]);
|
|
113
|
+
if (!echo) continue;
|
|
114
|
+
// Split at the FIRST dot: 'codex_apps.google_drive.update_file' is server
|
|
115
|
+
// 'codex_apps' + tool 'google_drive.update_file' (a greedy split at the last
|
|
116
|
+
// dot silently truncated the tool to 'update_file').
|
|
117
|
+
const dot = echo.qualified.indexOf('.');
|
|
118
|
+
if (dot <= 0) continue;
|
|
119
|
+
return {
|
|
120
|
+
server: echo.qualified.slice(0, dot),
|
|
121
|
+
tool: echo.qualified.slice(dot + 1),
|
|
122
|
+
questionIdx: -1,
|
|
123
|
+
actorKind: null,
|
|
124
|
+
};
|
|
29
125
|
}
|
|
126
|
+
|
|
30
127
|
return null;
|
|
31
128
|
}
|
|
32
129
|
|
|
33
|
-
module.exports = {
|
|
130
|
+
module.exports = {
|
|
131
|
+
CODEX_APPS_SERVER,
|
|
132
|
+
parseApprovalQuestion,
|
|
133
|
+
parseCallingEcho,
|
|
134
|
+
extractMcpServerTool,
|
|
135
|
+
};
|
|
@@ -10,8 +10,17 @@
|
|
|
10
10
|
// 3. Always allow
|
|
11
11
|
// 4. Cancel
|
|
12
12
|
// enter to submit | esc to cancel
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
//
|
|
14
|
+
// The question's actor is structural, not a fixed list: "the <server> MCP
|
|
15
|
+
// server" (ordinary MCP server), "this app" (server `codex_apps`, connector
|
|
16
|
+
// unnamed) or the connector's display name (e.g. "Google Drive", also server
|
|
17
|
+
// `codex_apps`). The echo line may carry no "({...})" argument list.
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
parseApprovalQuestion,
|
|
21
|
+
parseCallingEcho,
|
|
22
|
+
extractMcpServerTool,
|
|
23
|
+
} = require('./codex-mcp-extract');
|
|
15
24
|
const ALLOW_RE = /^\s*[❯›> ]?\s*1\.\s*Allow\b/i;
|
|
16
25
|
// At least one of the "remember this" options — the structural twin of "1. Allow"
|
|
17
26
|
// that distinguishes a live MCP approval menu from a stray "Allow" in prose.
|
|
@@ -47,13 +56,13 @@ module.exports = {
|
|
|
47
56
|
const lines = String(text || '').split('\n').map(l => l.trim()).filter(Boolean);
|
|
48
57
|
if (lines.length < 3) return false;
|
|
49
58
|
|
|
50
|
-
// The MCP question ("Allow
|
|
51
|
-
// "Calling server.tool
|
|
59
|
+
// The MCP question ("Allow <actor> to run tool …?") or the
|
|
60
|
+
// "Calling server.tool" echo is the strongest, most stable signal. Codex's
|
|
52
61
|
// footer hint ("enter to submit | esc to cancel") was DROPPED in newer builds
|
|
53
62
|
// (0.142.x) — anchoring detection on that cosmetic string silently broke every
|
|
54
63
|
// MCP auto-approval when the UI changed, so it is no longer used at all. Detect
|
|
55
64
|
// on the invariant structure instead.
|
|
56
|
-
const hasQuestion = lines.some(l =>
|
|
65
|
+
const hasQuestion = lines.some(l => parseApprovalQuestion(l) || parseCallingEcho(l));
|
|
57
66
|
if (!hasQuestion) return false;
|
|
58
67
|
|
|
59
68
|
// Require a LIVE Allow-option block near the viewport bottom: "1. Allow" plus at
|