create-walle 0.9.21 → 0.9.23
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 +27 -5
- package/package.json +2 -2
- package/template/CLAUDE.md +2 -2
- package/template/LICENSE +1 -1
- package/template/bin/ctm-dev-cleanup.js +24 -3
- package/template/bin/ctm-launch.sh +13 -0
- package/template/bin/dev.sh +156 -18
- package/template/bin/node-bin.sh +84 -0
- package/template/bin/pin-node.sh +51 -0
- package/template/claude-task-manager/api-prompts.js +1203 -182
- package/template/claude-task-manager/api-reviews.js +109 -15
- package/template/claude-task-manager/approval-agent.js +1360 -280
- package/template/claude-task-manager/bin/restart-ctm.sh +64 -23
- package/template/claude-task-manager/bin/storage-migration-supervisor.js +338 -0
- package/template/claude-task-manager/db.js +4417 -295
- package/template/claude-task-manager/docs/app-update-refresh-protocol.md +69 -0
- package/template/claude-task-manager/docs/approval-ai-refinement.md +138 -0
- package/template/claude-task-manager/docs/approval-rescue-loop.md +74 -0
- package/template/claude-task-manager/docs/codex-operational-warning-health.md +107 -0
- package/template/claude-task-manager/docs/codex-resume-state-guard-design.md +17 -12
- package/template/claude-task-manager/docs/codex-terminal-render-controller-handoff.md +311 -0
- package/template/claude-task-manager/docs/coding-agent-hooks-architecture.md +418 -0
- package/template/claude-task-manager/docs/conversation-import-freshness.md +20 -0
- package/template/claude-task-manager/docs/google-workspace-auth-health.md +77 -0
- package/template/claude-task-manager/docs/image-paste-ux.md +13 -0
- package/template/claude-task-manager/docs/ipad-web-preview.md +88 -0
- package/template/claude-task-manager/docs/main-loop-offload-architecture.md +66 -0
- package/template/claude-task-manager/docs/microsoft-dev-tunnel-phone-access-design.md +274 -519
- package/template/claude-task-manager/docs/mobile-live-streaming.md +27 -5
- package/template/claude-task-manager/docs/mobile-remote-submission-lifecycle.md +69 -0
- package/template/claude-task-manager/docs/phone-access-design.md +53 -15
- package/template/claude-task-manager/docs/phone-passkey-identity.md +122 -0
- package/template/claude-task-manager/docs/phone-setup.md +3 -0
- package/template/claude-task-manager/docs/prompt-editing-tree-design.md +25 -1
- package/template/claude-task-manager/docs/remote-desktop-access-design.md +268 -0
- package/template/claude-task-manager/docs/restart-lifecycle-architecture.md +95 -0
- package/template/claude-task-manager/docs/runtime-work-control-plane.md +53 -0
- package/template/claude-task-manager/docs/session-interactive-wait-surfaces.md +38 -0
- package/template/claude-task-manager/docs/session-needs-you-dismissal.md +84 -0
- package/template/claude-task-manager/docs/session-render-state-management-design.md +91 -3
- package/template/claude-task-manager/docs/session-standup-command-center-design.md +25 -1
- package/template/claude-task-manager/docs/session-title-authority.md +32 -0
- package/template/claude-task-manager/docs/session-workspace-binding.md +33 -0
- package/template/claude-task-manager/docs/skill-intent-resolution-design.md +72 -0
- package/template/claude-task-manager/docs/walle-mcp-supervisor-health.md +86 -0
- package/template/claude-task-manager/docs/walle-relay-phone-access-design.md +24 -15
- package/template/claude-task-manager/docs/walle-session-history-hydration.md +114 -0
- package/template/claude-task-manager/docs/walle-session-input-queue.md +104 -0
- package/template/claude-task-manager/docs/walle-session-model-catalog.md +90 -0
- package/template/claude-task-manager/docs/walle-session-model-preferences.md +15 -6
- package/template/claude-task-manager/git-utils.js +897 -27
- package/template/claude-task-manager/lib/agent-capabilities.js +33 -0
- package/template/claude-task-manager/lib/agent-cli-cache.js +37 -7
- package/template/claude-task-manager/lib/agent-hooks-installer.js +26 -2
- package/template/claude-task-manager/lib/agent-presets.js +17 -1
- package/template/claude-task-manager/lib/all-sessions-query.js +108 -0
- package/template/claude-task-manager/lib/approval-ai-refinement.js +488 -0
- package/template/claude-task-manager/lib/approval-self-adapt.js +168 -0
- package/template/claude-task-manager/lib/async-semaphore.js +44 -0
- package/template/claude-task-manager/lib/auth-context.js +5 -0
- package/template/claude-task-manager/lib/auth-rate-limit.js +47 -4
- package/template/claude-task-manager/lib/auth-rules.js +29 -2
- package/template/claude-task-manager/lib/auto-approval-verifier.js +129 -16
- package/template/claude-task-manager/lib/background-llm.js +144 -17
- package/template/claude-task-manager/lib/branch-inventory.js +212 -0
- package/template/claude-task-manager/lib/claude-desktop-sessions.js +15 -3
- package/template/claude-task-manager/lib/coalesce-sync-frames.js +151 -0
- package/template/claude-task-manager/lib/codex-launch-health.js +762 -0
- package/template/claude-task-manager/lib/codex-transcript-pager.js +51 -0
- package/template/claude-task-manager/lib/codex-zst.js +124 -0
- package/template/claude-task-manager/lib/coding-agent-models.js +233 -30
- package/template/claude-task-manager/lib/connection-health.js +232 -0
- package/template/claude-task-manager/lib/conversation-blob-parser.js +42 -0
- package/template/claude-task-manager/lib/conversation-tail-merge.js +89 -26
- package/template/claude-task-manager/lib/ctm-session-context-api.js +39 -10
- package/template/claude-task-manager/lib/cursor-conversation-store.js +354 -0
- package/template/claude-task-manager/lib/db-owner-worker-client.js +315 -0
- package/template/claude-task-manager/lib/document-review.js +141 -6
- package/template/claude-task-manager/lib/escalation-review.js +152 -0
- package/template/claude-task-manager/lib/graceful-shutdown.js +159 -0
- package/template/claude-task-manager/lib/headless-term-service.js +678 -0
- package/template/claude-task-manager/lib/heavy-worker-fallback.js +38 -0
- package/template/claude-task-manager/lib/jsonl-conversation-parser.js +542 -0
- package/template/claude-task-manager/lib/jsonl-range-reader.js +112 -0
- package/template/claude-task-manager/lib/main-db-census.js +216 -0
- package/template/claude-task-manager/lib/message-pagination.js +106 -4
- package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +750 -26
- package/template/claude-task-manager/lib/mobile-auth-api.js +274 -7
- package/template/claude-task-manager/lib/mobile-auth-store.js +592 -10
- package/template/claude-task-manager/lib/mobile-notification-dispatcher.js +15 -0
- package/template/claude-task-manager/lib/model-overview-brain-fallback.js +311 -0
- package/template/claude-task-manager/lib/model-overview-cache.js +141 -0
- package/template/claude-task-manager/lib/models-health-routing-notice.js +126 -0
- package/template/claude-task-manager/lib/node-pin-guard.js +93 -0
- package/template/claude-task-manager/lib/perf-tracker.js +242 -6
- package/template/claude-task-manager/lib/permission-match.js +76 -0
- package/template/claude-task-manager/lib/permission-sync.js +133 -20
- package/template/claude-task-manager/lib/process-title.js +35 -0
- package/template/claude-task-manager/lib/prompt-executions-query.js +25 -0
- package/template/claude-task-manager/lib/prompt-index-disk-cache.js +44 -0
- package/template/claude-task-manager/lib/prompt-intent.js +132 -0
- package/template/claude-task-manager/lib/provider-user-context.js +34 -0
- package/template/claude-task-manager/lib/read-pool-client.js +313 -0
- package/template/claude-task-manager/lib/readpool-breaker.js +31 -0
- package/template/claude-task-manager/lib/recent-sessions-breaker.js +12 -0
- package/template/claude-task-manager/lib/remote-feedback-client.js +72 -0
- package/template/claude-task-manager/lib/remote-relay-protocol.js +37 -4
- package/template/claude-task-manager/lib/remote-relay-store.js +159 -0
- package/template/claude-task-manager/lib/remote-submission-observer.js +278 -0
- package/template/claude-task-manager/lib/restart-guard.js +109 -0
- package/template/claude-task-manager/lib/restore-interruption-detector.js +439 -0
- package/template/claude-task-manager/lib/restore-policy.js +13 -0
- package/template/claude-task-manager/lib/restore-resume-batch.js +74 -0
- package/template/claude-task-manager/lib/restore-runtime.js +68 -0
- package/template/claude-task-manager/lib/restore-storm.js +34 -0
- package/template/claude-task-manager/lib/resume-cwd.js +36 -0
- package/template/claude-task-manager/lib/resume-preflight.js +313 -0
- package/template/claude-task-manager/lib/runtime-work-registry.js +444 -0
- package/template/claude-task-manager/lib/sanitize-openai-auth.js +31 -0
- package/template/claude-task-manager/lib/scheduler.js +21 -1
- package/template/claude-task-manager/lib/scrollback-snapshot-store.js +159 -0
- package/template/claude-task-manager/lib/serial-task-queue.js +64 -0
- package/template/claude-task-manager/lib/server-listeners.js +239 -0
- package/template/claude-task-manager/lib/session-capture.js +42 -7
- package/template/claude-task-manager/lib/session-content-backfill.js +131 -0
- package/template/claude-task-manager/lib/session-history.js +388 -43
- package/template/claude-task-manager/lib/session-host-manager.js +287 -0
- package/template/claude-task-manager/lib/session-image-refs.js +209 -0
- package/template/claude-task-manager/lib/session-jobs.js +399 -59
- package/template/claude-task-manager/lib/session-prompt-index.js +137 -0
- package/template/claude-task-manager/lib/session-restore.js +53 -0
- package/template/claude-task-manager/lib/session-standup.js +123 -23
- package/template/claude-task-manager/lib/session-state-bus.js +14 -0
- package/template/claude-task-manager/lib/session-stream.js +64 -16
- package/template/claude-task-manager/lib/session-timeline-summary.js +260 -0
- package/template/claude-task-manager/lib/session-token-usage.js +494 -0
- package/template/claude-task-manager/lib/session-workspace-binding.js +356 -0
- package/template/claude-task-manager/lib/setup-network-config.js +9 -0
- package/template/claude-task-manager/lib/size-cap.js +45 -0
- package/template/claude-task-manager/lib/size-cap.test.js +62 -0
- package/template/claude-task-manager/lib/skill-autocomplete.js +180 -1
- package/template/claude-task-manager/lib/skill-intent-resolver.js +304 -0
- package/template/claude-task-manager/lib/sqlite-driver.js +19 -3
- package/template/claude-task-manager/lib/standup-attention.js +7 -3
- package/template/claude-task-manager/lib/status-authority.js +39 -0
- package/template/claude-task-manager/lib/status-hooks.js +4 -0
- package/template/claude-task-manager/lib/storage-migration.js +235 -0
- package/template/claude-task-manager/lib/structured-capture.js +298 -0
- package/template/claude-task-manager/lib/sync-io-census.js +163 -0
- package/template/claude-task-manager/lib/tailscale-setup.js +6 -0
- package/template/claude-task-manager/lib/terminal-activity-evidence.js +33 -0
- package/template/claude-task-manager/lib/terminal-choice.js +364 -0
- package/template/claude-task-manager/lib/terminal-control-sanitize.js +17 -0
- package/template/claude-task-manager/lib/terminal-fingerprint.js +48 -0
- package/template/claude-task-manager/lib/terminal-output-flush.js +84 -0
- package/template/claude-task-manager/lib/timeline-order.js +122 -0
- package/template/claude-task-manager/lib/transcript-store.js +348 -43
- package/template/claude-task-manager/lib/transport-security.js +84 -1
- package/template/claude-task-manager/lib/wait-state.js +184 -0
- package/template/claude-task-manager/lib/walle-client.js +47 -5
- package/template/claude-task-manager/lib/walle-ctm-history.js +564 -4
- package/template/claude-task-manager/lib/walle-external-actions.js +135 -16
- package/template/claude-task-manager/lib/walle-history-hydration.js +46 -0
- package/template/claude-task-manager/lib/walle-native-health.js +403 -0
- package/template/claude-task-manager/lib/walle-repair.js +701 -0
- package/template/claude-task-manager/lib/walle-session-cache.js +109 -0
- package/template/claude-task-manager/lib/walle-session-context.js +57 -21
- package/template/claude-task-manager/lib/walle-session-model-catalog.js +34 -0
- package/template/claude-task-manager/lib/walle-supervisor.js +539 -63
- package/template/claude-task-manager/lib/walle-transcript.js +52 -0
- package/template/claude-task-manager/lib/worktree-active-sync.js +11 -7
- package/template/claude-task-manager/lib/worktree-cwd.js +32 -1
- package/template/claude-task-manager/package.json +1 -1
- package/template/claude-task-manager/prompt-harvest.js +89 -66
- package/template/claude-task-manager/providers/claude-code.js +51 -3
- package/template/claude-task-manager/providers/cursor.js +140 -45
- package/template/claude-task-manager/public/css/reviews.css +551 -61
- package/template/claude-task-manager/public/css/setup.css +191 -0
- package/template/claude-task-manager/public/css/walle-session.css +865 -10
- package/template/claude-task-manager/public/css/walle.css +154 -0
- package/template/claude-task-manager/public/designs/ai-providers-consolidation-v2.html +830 -0
- package/template/claude-task-manager/public/index.html +18516 -2058
- package/template/claude-task-manager/public/ipad.html +363 -0
- package/template/claude-task-manager/public/js/document-review-links.js +301 -0
- package/template/claude-task-manager/public/js/image-normalize.js +69 -36
- package/template/claude-task-manager/public/js/message-renderer.js +1265 -77
- package/template/claude-task-manager/public/js/prompts.js +66 -29
- package/template/claude-task-manager/public/js/reviews.js +901 -133
- package/template/claude-task-manager/public/js/session-activity-utils.js +11 -1
- package/template/claude-task-manager/public/js/session-search-utils.js +94 -10
- package/template/claude-task-manager/public/js/session-status-precedence.js +23 -5
- package/template/claude-task-manager/public/js/setup.js +1273 -176
- package/template/claude-task-manager/public/js/stream-view.js +691 -73
- package/template/claude-task-manager/public/js/terminal-reconciler.js +210 -0
- package/template/claude-task-manager/public/js/walle-session.js +2455 -158
- package/template/claude-task-manager/public/js/walle.js +455 -28
- package/template/claude-task-manager/public/m/app.css +2909 -262
- package/template/claude-task-manager/public/m/app.js +6601 -398
- package/template/claude-task-manager/public/m/claim.html +224 -17
- package/template/claude-task-manager/public/m/index.html +117 -21
- package/template/claude-task-manager/public/m/sw.js +3 -1
- package/template/claude-task-manager/public/manifest.json +2 -2
- package/template/claude-task-manager/public/prompts.html +30 -14
- package/template/claude-task-manager/queue-engine.js +507 -28
- package/template/claude-task-manager/scripts/repair-claude-session-images.js +27 -8
- package/template/claude-task-manager/server.js +14341 -2197
- package/template/claude-task-manager/session-integrity.js +160 -18
- package/template/claude-task-manager/session-search-ranking.js +1 -0
- package/template/claude-task-manager/session-utils.js +25 -5
- package/template/claude-task-manager/workers/approval-blocklist.js +96 -6
- package/template/claude-task-manager/workers/approval-widget-validator.js +14 -8
- package/template/claude-task-manager/workers/conversation-import-worker.js +11 -50
- package/template/claude-task-manager/workers/db-owner-worker.js +386 -0
- package/template/claude-task-manager/workers/harvest-worker.js +9 -55
- package/template/claude-task-manager/workers/headless-term-worker.js +9 -530
- package/template/claude-task-manager/workers/read-pool-worker.js +387 -0
- package/template/claude-task-manager/workers/scrollback-worker.js +11 -72
- package/template/claude-task-manager/workers/session-host-process.js +146 -0
- package/template/claude-task-manager/workers/session-integrity-worker.js +10 -54
- package/template/claude-task-manager/workers/state-detectors/base.js +18 -1
- package/template/claude-task-manager/workers/state-detectors/claude-code.js +182 -9
- package/template/claude-task-manager/workers/state-detectors/codex.js +150 -2
- package/template/claude-task-manager/workers/state-detectors/cursor.js +127 -0
- package/template/claude-task-manager/workers/state-detectors/gemini.js +21 -0
- package/template/claude-task-manager/workers/state-detectors/index.js +29 -0
- package/template/claude-task-manager/workers/state-detectors/opencode.js +103 -0
- package/template/docs/design/markdown-review-pane.md +206 -0
- package/template/docs/designs/2026-05-17-portkey-gateway-provider-ux.md +129 -38
- package/template/docs/designs/2026-05-20-mobile-worktree-finish-command.md +27 -0
- package/template/docs/designs/2026-05-22-ai-configuration-consolidation.md +248 -0
- package/template/docs/designs/ai-configuration-consolidation-mock.html +812 -0
- package/template/docs/private-memory-and-pii-policy.md +69 -0
- package/template/package.json +2 -1
- package/template/scripts/check-private-data.js +201 -0
- package/template/shared/sqlite-owner-guard.js +30 -0
- package/template/shared/sqlite-owner-write-queue.js +225 -0
- package/template/shared/sqlite-storage-policy.js +111 -0
- package/template/shared/sqlite-write-lock.js +428 -0
- package/template/wall-e/agent-runners/claude-code.js +5 -0
- package/template/wall-e/agent.js +166 -22
- package/template/wall-e/api-walle.js +524 -70
- package/template/wall-e/auth/provider-flows.js +11 -1
- package/template/wall-e/bin/walle-mcp-stdio.js +341 -17
- package/template/wall-e/brain.js +1614 -141
- package/template/wall-e/chat/attachment-blocks.js +96 -0
- package/template/wall-e/chat/attachments.js +2 -1
- package/template/wall-e/chat/capability-resolver.js +7 -7
- package/template/wall-e/chat/context-messages.js +28 -0
- package/template/wall-e/chat/conversation-frame.js +630 -0
- package/template/wall-e/chat/provider-messages.js +125 -0
- package/template/wall-e/chat.js +1002 -233
- package/template/wall-e/coding/acceptance-contract.js +170 -0
- package/template/wall-e/coding/acp-adapter.js +1 -1
- package/template/wall-e/coding/agent-catalog.js +3 -0
- package/template/wall-e/coding/artifact-store.js +93 -0
- package/template/wall-e/coding/capability-router.js +120 -0
- package/template/wall-e/coding/coding-run-controller.js +423 -0
- package/template/wall-e/coding/compaction-service.js +157 -12
- package/template/wall-e/coding/frontend-verification.js +258 -0
- package/template/wall-e/coding/lifecycle-hooks.js +75 -0
- package/template/wall-e/coding/local-preview-contract.js +157 -0
- package/template/wall-e/coding/permission-service.js +57 -13
- package/template/wall-e/coding/prompt-bundle.js +19 -1
- package/template/wall-e/coding/prompt-section-registry.js +227 -0
- package/template/wall-e/coding/provider-compat.js +15 -0
- package/template/wall-e/coding/runtime-events.js +224 -0
- package/template/wall-e/coding/runtime-mode.js +3 -0
- package/template/wall-e/coding/side-git-snapshot.js +160 -4
- package/template/wall-e/coding/snapshot-service.js +143 -1
- package/template/wall-e/coding/stream-processor.js +388 -34
- package/template/wall-e/coding/task-tool.js +141 -4
- package/template/wall-e/coding/tool-execution-controller.js +365 -0
- package/template/wall-e/coding/tool-registry.js +43 -5
- package/template/wall-e/coding/user-hooks.js +217 -0
- package/template/wall-e/coding-orchestrator.js +1330 -221
- package/template/wall-e/coding-prompts.js +20 -4
- package/template/wall-e/context/context-builder.js +15 -2
- package/template/wall-e/decision/confidence.js +1 -1
- package/template/wall-e/docs/coding-acceptance-contract.md +41 -0
- package/template/wall-e/docs/external-action-controller.md +26 -6
- package/template/wall-e/docs/telemetry-lifecycle.md +8 -2
- package/template/wall-e/embeddings.js +591 -53
- package/template/wall-e/external-action-controller.js +12 -0
- package/template/wall-e/http/auth.js +1 -0
- package/template/wall-e/http/chat-api.js +46 -11
- package/template/wall-e/http/model-admin.js +836 -34
- package/template/wall-e/lib/boot-profile.js +88 -0
- package/template/wall-e/lib/event-loop-monitor.js +93 -0
- package/template/wall-e/lib/service-health.js +194 -0
- package/template/wall-e/llm/anthropic.js +130 -5
- package/template/wall-e/llm/client.js +266 -63
- package/template/wall-e/llm/default-fallback.js +382 -0
- package/template/wall-e/llm/health.js +19 -0
- package/template/wall-e/llm/message-guard.js +78 -0
- package/template/wall-e/llm/model-catalog.js +252 -1
- package/template/wall-e/llm/openai.js +26 -4
- package/template/wall-e/llm/portkey-sync.js +654 -0
- package/template/wall-e/llm/provider-error.js +30 -2
- package/template/wall-e/llm/registry.js +5 -1
- package/template/wall-e/llm/request-compat.js +67 -0
- package/template/wall-e/loops/backfill.js +79 -23
- package/template/wall-e/loops/brain-optimize.js +67 -0
- package/template/wall-e/loops/ingest.js +25 -10
- package/template/wall-e/loops/question-digest.js +160 -0
- package/template/wall-e/loops/reflect.js +6 -4
- package/template/wall-e/loops/think.js +39 -12
- package/template/wall-e/mcp-server.js +318 -36
- package/template/wall-e/memory/ctm-context-client.js +52 -14
- package/template/wall-e/memory/ctm-operational-context.js +237 -0
- package/template/wall-e/memory/ctm-prompt-executions-client.js +128 -0
- package/template/wall-e/memory/ctm-session-context.js +111 -63
- package/template/wall-e/prompts/coding/deepseek.txt +3 -0
- package/template/wall-e/prompts/coding/gemini.txt +6 -0
- package/template/wall-e/prompts/coding/gpt.txt +6 -0
- package/template/wall-e/prompts/coding/local.txt +7 -0
- package/template/wall-e/runtime/decision-hooks.js +115 -0
- package/template/wall-e/runtime/devbox-gateway.js +82 -8
- package/template/wall-e/runtime/prompt-manifest.js +86 -0
- package/template/wall-e/runtime/tool-executor.js +269 -0
- package/template/wall-e/runtime/tool-result-envelope.js +138 -0
- package/template/wall-e/runtime/transcript-projection.js +60 -0
- package/template/wall-e/runtime/walle-runtime.js +224 -0
- package/template/wall-e/scripts/db-optimize/migrate.js +162 -0
- package/template/wall-e/scripts/db-optimize/recall-eval.js +117 -0
- package/template/wall-e/server.js +15 -0
- package/template/wall-e/session-files.js +9 -0
- package/template/wall-e/skills/_bundled/google-calendar/run.js +1 -1
- package/template/wall-e/skills/_bundled/gws-workspace/run.js +1 -1
- package/template/wall-e/skills/_bundled/slack-mentions/run.js +76 -6
- package/template/wall-e/skills/claude-code-reader.js +7 -3
- package/template/wall-e/skills/script-skill-runner.js +10 -0
- package/template/wall-e/skills/skill-planner.js +38 -0
- package/template/wall-e/tools/builtin-middleware.js +19 -9
- package/template/wall-e/tools/local-tools.js +1428 -16
- package/template/wall-e/tools/permission-checker.js +73 -5
- package/template/wall-e/tools/question-manager.js +117 -7
- package/template/wall-e/training/harvester.js +12 -28
- package/template/wall-e/training/replay.js +25 -80
- package/template/website/index.html +10 -10
- package/template/wall-e/eval/ab-test.js +0 -203
- package/template/wall-e/eval/agent-runner.js +0 -772
- package/template/wall-e/eval/agent-scorer.js +0 -461
- package/template/wall-e/eval/aggregator.js +0 -414
- package/template/wall-e/eval/allowed-test-commands.js +0 -34
- package/template/wall-e/eval/benchmark-generator.js +0 -113
- package/template/wall-e/eval/benchmarks/chat-eval.json +0 -1662
- package/template/wall-e/eval/benchmarks/chat.json +0 -82
- package/template/wall-e/eval/benchmarks/coding-agent-real.json +0 -1
- package/template/wall-e/eval/benchmarks/coding-agent.json +0 -1581
- package/template/wall-e/eval/benchmarks/coding.json +0 -122
- package/template/wall-e/eval/benchmarks/memory-retrieval.json +0 -234
- package/template/wall-e/eval/benchmarks/reasoning.json +0 -82
- package/template/wall-e/eval/benchmarks/swebench-lite-30.json +0 -212
- package/template/wall-e/eval/benchmarks.js +0 -669
- package/template/wall-e/eval/cc-replay.js +0 -719
- package/template/wall-e/eval/chat-eval.js +0 -525
- package/template/wall-e/eval/check-keys.js +0 -15
- package/template/wall-e/eval/check-providers.js +0 -42
- package/template/wall-e/eval/codex-cli-baseline.js +0 -669
- package/template/wall-e/eval/coding-agent-real.js +0 -570
- package/template/wall-e/eval/context-compactor.js +0 -251
- package/template/wall-e/eval/debug-agent003.js +0 -68
- package/template/wall-e/eval/diagnostics.js +0 -216
- package/template/wall-e/eval/eval-orchestrator.js +0 -642
- package/template/wall-e/eval/evaluate.js +0 -202
- package/template/wall-e/eval/evaluator.js +0 -373
- package/template/wall-e/eval/exporter.js +0 -212
- package/template/wall-e/eval/fixtures/express-basic/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-basic/server.js +0 -115
- package/template/wall-e/eval/fixtures/express-basic/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy/server.js +0 -113
- package/template/wall-e/eval/fixtures/express-buggy/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy-items/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy-items/server.js +0 -112
- package/template/wall-e/eval/fixtures/express-buggy-items/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy-search/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy-search/server.js +0 -121
- package/template/wall-e/eval/fixtures/express-buggy-search/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-rename-data/data.js +0 -34
- package/template/wall-e/eval/fixtures/express-rename-data/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-rename-data/server.js +0 -97
- package/template/wall-e/eval/fixtures/express-rename-data/test.js +0 -88
- package/template/wall-e/eval/fixtures/express-xss/package.json +0 -12
- package/template/wall-e/eval/fixtures/express-xss/server.js +0 -90
- package/template/wall-e/eval/fixtures/express-xss/test.js +0 -67
- package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +0 -9
- package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +0 -9
- package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +0 -13
- package/template/wall-e/eval/fixtures/fullstack-app/package.json +0 -11
- package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +0 -137
- package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +0 -121
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +0 -71
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +0 -80
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +0 -45
- package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +0 -38
- package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +0 -23
- package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +0 -99
- package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +0 -94
- package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +0 -19
- package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +0 -19
- package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +0 -50
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +0 -69
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +0 -23
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +0 -88
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +0 -75
- package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +0 -198
- package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +0 -34
- package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +0 -26
- package/template/wall-e/eval/fixtures/fullstack-app/server.js +0 -8
- package/template/wall-e/eval/fixtures/fullstack-app/test.js +0 -12
- package/template/wall-e/eval/fixtures/monorepo-basic/package.json +0 -8
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +0 -58
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +0 -46
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +0 -8
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +0 -64
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +0 -56
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +0 -116
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +0 -61
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +0 -62
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +0 -43
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +0 -11
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +0 -44
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +0 -43
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +0 -12
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +0 -5
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +0 -55
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +0 -29
- package/template/wall-e/eval/fixtures/monorepo-basic/test.js +0 -46
- package/template/wall-e/eval/fixtures/node-cli/index.js +0 -78
- package/template/wall-e/eval/fixtures/node-cli/package.json +0 -10
- package/template/wall-e/eval/fixtures/node-cli/test.js +0 -57
- package/template/wall-e/eval/fixtures/node-typed/package.json +0 -8
- package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +0 -31
- package/template/wall-e/eval/fixtures/node-typed/src/utils.js +0 -33
- package/template/wall-e/eval/fixtures/node-typed/test.js +0 -36
- package/template/wall-e/eval/fixtures/python-flask/app.py +0 -14
- package/template/wall-e/eval/fixtures/python-flask/requirements.txt +0 -2
- package/template/wall-e/eval/fixtures/python-flask/test_app.py +0 -25
- package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +0 -105
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +0 -101
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +0 -20
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +0 -32
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +0 -64
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +0 -6
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +0 -31
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +0 -18
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +0 -34
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +0 -104
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +0 -73
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +0 -134
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +0 -99
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +0 -63
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +0 -70
- package/template/wall-e/eval/fixtures/wall-e-subset/package.json +0 -10
- package/template/wall-e/eval/fixtures/wall-e-subset/test.js +0 -86
- package/template/wall-e/eval/harvester.js +0 -685
- package/template/wall-e/eval/head-to-head.js +0 -388
- package/template/wall-e/eval/humaneval-adapter.js +0 -321
- package/template/wall-e/eval/list-models.js +0 -31
- package/template/wall-e/eval/livecodebench-adapter.js +0 -291
- package/template/wall-e/eval/mail-integration.js +0 -443
- package/template/wall-e/eval/manifest.js +0 -186
- package/template/wall-e/eval/meta-harness/adapters/coding-agent.js +0 -57
- package/template/wall-e/eval/meta-harness/bootstrap-snapshot.js +0 -149
- package/template/wall-e/eval/meta-harness/candidate-store.js +0 -117
- package/template/wall-e/eval/meta-harness/cli.js +0 -86
- package/template/wall-e/eval/meta-harness/domain-spec.js +0 -154
- package/template/wall-e/eval/meta-harness/domains/coding-agent.domain.json +0 -84
- package/template/wall-e/eval/meta-harness/examples/env-bootstrap-candidate.js +0 -29
- package/template/wall-e/eval/meta-harness/experience-store.js +0 -174
- package/template/wall-e/eval/meta-harness/frontier.js +0 -96
- package/template/wall-e/eval/meta-harness/harness-interface.js +0 -90
- package/template/wall-e/eval/meta-harness/leakage-guard.js +0 -80
- package/template/wall-e/eval/meta-harness/optimizer.js +0 -207
- package/template/wall-e/eval/meta-harness/proposer-runner.js +0 -110
- package/template/wall-e/eval/meta-harness/reporting.js +0 -58
- package/template/wall-e/eval/meta-harness/telemetry.js +0 -27
- package/template/wall-e/eval/meta-harness/validation.js +0 -81
- package/template/wall-e/eval/promoter.js +0 -228
- package/template/wall-e/eval/provider-normalizer.js +0 -33
- package/template/wall-e/eval/replay.js +0 -395
- package/template/wall-e/eval/run-agent-benchmarks.js +0 -386
- package/template/wall-e/eval/run-codex-cli-baseline.js +0 -177
- package/template/wall-e/eval/run-coding-agent-real.js +0 -187
- package/template/wall-e/eval/run-eval.js +0 -435
- package/template/wall-e/eval/run-model-comparison.js +0 -142
- package/template/wall-e/eval/session-evaluator.js +0 -187
- package/template/wall-e/eval/session-miner.js +0 -207
- package/template/wall-e/eval/session-retrieval-benchmark.js +0 -150
- package/template/wall-e/eval/session-transcripts.js +0 -509
- package/template/wall-e/eval/shadow.js +0 -161
- package/template/wall-e/eval/swebench-adapter.js +0 -345
- package/template/wall-e/eval/swebench-docker.js +0 -192
- package/template/wall-e/eval/train.py +0 -320
- package/template/wall-e/eval/trainer.js +0 -232
- package/template/wall-e/eval/weekly-eval-loop.js +0 -241
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
|
+
const http = require('http');
|
|
4
5
|
const net = require('net');
|
|
5
6
|
const os = require('os');
|
|
6
7
|
const path = require('path');
|
|
7
8
|
const { spawn, execFile } = require('child_process');
|
|
9
|
+
const { processTitle: formatProcessTitle, processTitleCandidates } = require('./process-title');
|
|
10
|
+
const {
|
|
11
|
+
checkWalleNativeDeps,
|
|
12
|
+
rebuildWalleNativeDeps,
|
|
13
|
+
shouldRebuildNativeDeps,
|
|
14
|
+
} = require('./walle-native-health');
|
|
8
15
|
|
|
9
16
|
const RESTART_DELAY_MS = 5000;
|
|
10
17
|
const RESTART_BURST = 5;
|
|
@@ -73,15 +80,318 @@ function createWalleSupervisor({
|
|
|
73
80
|
telemetry = { track() {} },
|
|
74
81
|
isDisabled = () => !!process.env.WALLE_DISABLED,
|
|
75
82
|
processOps = defaultProcessOps,
|
|
83
|
+
nativeDeps = { check: checkWalleNativeDeps, rebuild: rebuildWalleNativeDeps, shouldRebuild: shouldRebuildNativeDeps },
|
|
84
|
+
spawnProcess = spawn,
|
|
85
|
+
nativeCheckIntervalMs = 60000,
|
|
86
|
+
mcpReadyTimeoutMs = 30000,
|
|
87
|
+
mcpReadyRetryMs = 250,
|
|
88
|
+
mcpReadyProbe = null,
|
|
89
|
+
// How often getStatus() may re-probe a running Wall-E whose last verdict is
|
|
90
|
+
// not-ready, to self-heal a stale startup timeout (a too-short probe vs a slow
|
|
91
|
+
// brain boot). Throttled so frequent status polls don't hammer the MCP endpoint.
|
|
92
|
+
mcpReadySelfHealIntervalMs = 3000,
|
|
76
93
|
}) {
|
|
77
94
|
let intentionallyStopped = false;
|
|
78
95
|
let starting = false;
|
|
79
96
|
let child = null;
|
|
80
97
|
let childPid = null;
|
|
81
98
|
let restartHistory = [];
|
|
99
|
+
let lastNativeHealth = null;
|
|
100
|
+
let lastNativeHealthAt = 0;
|
|
101
|
+
let lastStartError = null;
|
|
102
|
+
let lastMcpReady = null;
|
|
103
|
+
let lastSelfHealProbeAt = 0;
|
|
82
104
|
|
|
83
105
|
const pidFile = () => path.join(configDir, 'walle.pid');
|
|
84
|
-
const processTitle = () =>
|
|
106
|
+
const processTitle = () => formatProcessTitle('walle', instanceTag || 'primary');
|
|
107
|
+
const processTitles = () => processTitleCandidates('walle', instanceTag || 'primary');
|
|
108
|
+
const walleDir = () => path.join(ctmDir, '..', 'wall-e');
|
|
109
|
+
|
|
110
|
+
function _nativeErrorPayload(health) {
|
|
111
|
+
const h = health || lastNativeHealth || {};
|
|
112
|
+
return {
|
|
113
|
+
ok: false,
|
|
114
|
+
code: h.code || 'walle_native_dependency_failed',
|
|
115
|
+
message: h.message || 'Wall-E native dependency check failed.',
|
|
116
|
+
nativeDependency: h,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function requestMcpJson(message, { timeoutMs = 1000 } = {}) {
|
|
121
|
+
const body = JSON.stringify(message);
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
const req = http.request({
|
|
124
|
+
hostname: '127.0.0.1',
|
|
125
|
+
port: wallePort,
|
|
126
|
+
path: '/mcp',
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
'Content-Length': Buffer.byteLength(body),
|
|
131
|
+
'MCP-Protocol-Version': '2025-06-18',
|
|
132
|
+
...(walleToken ? { Authorization: `Bearer ${walleToken}` } : {}),
|
|
133
|
+
},
|
|
134
|
+
timeout: timeoutMs,
|
|
135
|
+
}, (res) => {
|
|
136
|
+
let raw = '';
|
|
137
|
+
res.setEncoding('utf8');
|
|
138
|
+
res.on('data', chunk => { raw += chunk; });
|
|
139
|
+
res.on('end', () => {
|
|
140
|
+
if (res.statusCode < 200 || res.statusCode >= 300) {
|
|
141
|
+
reject(new Error(`Wall-E MCP returned HTTP ${res.statusCode}: ${raw.slice(0, 300)}`));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const parsed = raw.trim() ? JSON.parse(raw) : null;
|
|
146
|
+
if (parsed?.error) reject(new Error(`Wall-E MCP JSON-RPC error: ${parsed.error.message || parsed.error.code}`));
|
|
147
|
+
else resolve(parsed);
|
|
148
|
+
} catch (err) {
|
|
149
|
+
reject(new Error(`Wall-E MCP returned invalid JSON: ${err.message}`));
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
req.on('timeout', () => req.destroy(new Error('Wall-E MCP readiness request timed out')));
|
|
154
|
+
req.on('error', reject);
|
|
155
|
+
req.end(body);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function defaultMcpReadyProbe() {
|
|
160
|
+
const init = await requestMcpJson({
|
|
161
|
+
jsonrpc: '2.0',
|
|
162
|
+
id: 1,
|
|
163
|
+
method: 'initialize',
|
|
164
|
+
params: {
|
|
165
|
+
protocolVersion: '2025-06-18',
|
|
166
|
+
capabilities: {},
|
|
167
|
+
clientInfo: { name: 'ctm-walle-supervisor', version: '1.0.0' },
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
if (init?.result?.serverInfo?.name !== 'wall-e') {
|
|
171
|
+
throw new Error('Wall-E MCP initialize did not return serverInfo.name=wall-e');
|
|
172
|
+
}
|
|
173
|
+
const tools = await requestMcpJson({
|
|
174
|
+
jsonrpc: '2.0',
|
|
175
|
+
id: 2,
|
|
176
|
+
method: 'tools/list',
|
|
177
|
+
params: {},
|
|
178
|
+
});
|
|
179
|
+
const list = tools?.result?.tools;
|
|
180
|
+
if (!Array.isArray(list) || !list.some(tool => tool?.name === 'walle_memory_status')) {
|
|
181
|
+
throw new Error('Wall-E MCP tools/list did not include walle_memory_status');
|
|
182
|
+
}
|
|
183
|
+
const status = await requestMcpJson({
|
|
184
|
+
jsonrpc: '2.0',
|
|
185
|
+
id: 3,
|
|
186
|
+
method: 'tools/call',
|
|
187
|
+
params: { name: 'walle_memory_status', arguments: {} },
|
|
188
|
+
});
|
|
189
|
+
const result = status?.result || {};
|
|
190
|
+
if (result.isError) {
|
|
191
|
+
throw new Error('Wall-E MCP walle_memory_status returned an error result');
|
|
192
|
+
}
|
|
193
|
+
let structured = result.structuredContent;
|
|
194
|
+
if (!structured && Array.isArray(result.content)) {
|
|
195
|
+
const text = result.content.find(item => item?.type === 'text' && item.text)?.text;
|
|
196
|
+
if (text) {
|
|
197
|
+
try { structured = JSON.parse(text); } catch {}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (!structured || typeof structured !== 'object') {
|
|
201
|
+
throw new Error('Wall-E MCP walle_memory_status did not return structured health');
|
|
202
|
+
}
|
|
203
|
+
if (structured.ok === false) {
|
|
204
|
+
throw new Error(`Wall-E MCP walle_memory_status is not healthy: ${structured.code || structured.error || 'unknown'}`);
|
|
205
|
+
}
|
|
206
|
+
return { ok: true, toolCount: list.length, memoryStatusOk: true };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function waitForMcpReady(pid, source, options = {}) {
|
|
210
|
+
const timeoutMs = Math.max(0, Number(options.timeoutMs ?? mcpReadyTimeoutMs));
|
|
211
|
+
const retryMs = Math.max(25, Number(options.retryMs ?? mcpReadyRetryMs));
|
|
212
|
+
const deadline = Date.now() + timeoutMs;
|
|
213
|
+
const startedAt = Date.now();
|
|
214
|
+
const probe = mcpReadyProbe || defaultMcpReadyProbe;
|
|
215
|
+
let attempts = 0;
|
|
216
|
+
let lastErr = null;
|
|
217
|
+
|
|
218
|
+
while (attempts === 0 || Date.now() <= deadline) {
|
|
219
|
+
attempts += 1;
|
|
220
|
+
if (pid && !isAlive(pid)) {
|
|
221
|
+
lastMcpReady = {
|
|
222
|
+
ok: false,
|
|
223
|
+
code: 'walle_exited_before_mcp_ready',
|
|
224
|
+
message: `Wall-E process ${pid} exited before MCP became ready.`,
|
|
225
|
+
pid,
|
|
226
|
+
source,
|
|
227
|
+
attempts,
|
|
228
|
+
elapsedMs: Date.now() - startedAt,
|
|
229
|
+
};
|
|
230
|
+
lastStartError = {
|
|
231
|
+
ok: false,
|
|
232
|
+
code: lastMcpReady.code,
|
|
233
|
+
message: lastMcpReady.message,
|
|
234
|
+
};
|
|
235
|
+
return lastMcpReady;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
const result = await probe({
|
|
239
|
+
pid,
|
|
240
|
+
port: wallePort,
|
|
241
|
+
token: walleToken,
|
|
242
|
+
source,
|
|
243
|
+
requestMcpJson,
|
|
244
|
+
});
|
|
245
|
+
if (result && typeof result === 'object' && result.ok === false) {
|
|
246
|
+
const probeErr = new Error(result.message || result.error || result.code || 'Wall-E MCP readiness probe failed');
|
|
247
|
+
probeErr.code = result.code || 'walle_mcp_ready_failed';
|
|
248
|
+
throw probeErr;
|
|
249
|
+
}
|
|
250
|
+
lastMcpReady = {
|
|
251
|
+
ok: true,
|
|
252
|
+
code: 'ok',
|
|
253
|
+
message: 'Wall-E MCP is ready.',
|
|
254
|
+
pid,
|
|
255
|
+
source,
|
|
256
|
+
attempts,
|
|
257
|
+
elapsedMs: Date.now() - startedAt,
|
|
258
|
+
...(result && typeof result === 'object' ? result : {}),
|
|
259
|
+
};
|
|
260
|
+
lastStartError = null;
|
|
261
|
+
return lastMcpReady;
|
|
262
|
+
} catch (err) {
|
|
263
|
+
lastErr = err;
|
|
264
|
+
}
|
|
265
|
+
if (Date.now() > deadline) break;
|
|
266
|
+
await sleep(retryMs);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
lastMcpReady = {
|
|
270
|
+
ok: false,
|
|
271
|
+
code: 'walle_mcp_ready_timeout',
|
|
272
|
+
message: `Wall-E process ${pid || 'unknown'} did not become MCP-ready within ${timeoutMs}ms: ${lastErr?.message || 'unknown error'}`,
|
|
273
|
+
pid: pid || null,
|
|
274
|
+
source,
|
|
275
|
+
attempts,
|
|
276
|
+
elapsedMs: Date.now() - startedAt,
|
|
277
|
+
lastError: lastErr ? { message: lastErr.message, code: lastErr.code || '' } : null,
|
|
278
|
+
};
|
|
279
|
+
lastStartError = {
|
|
280
|
+
ok: false,
|
|
281
|
+
code: lastMcpReady.code,
|
|
282
|
+
message: lastMcpReady.message,
|
|
283
|
+
};
|
|
284
|
+
try {
|
|
285
|
+
telemetry.track('walle_mcp_ready_failed', {
|
|
286
|
+
source: source || 'unknown',
|
|
287
|
+
code: lastMcpReady.code,
|
|
288
|
+
attempts,
|
|
289
|
+
elapsed_ms: lastMcpReady.elapsedMs,
|
|
290
|
+
message: String(lastMcpReady.message || '').slice(0, 240),
|
|
291
|
+
});
|
|
292
|
+
} catch {}
|
|
293
|
+
return lastMcpReady;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async function getNativeDependencyStatus({ force = false } = {}) {
|
|
297
|
+
const now = Date.now();
|
|
298
|
+
if (!force && lastNativeHealth && now - lastNativeHealthAt < nativeCheckIntervalMs) {
|
|
299
|
+
return lastNativeHealth;
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
lastNativeHealth = await nativeDeps.check({
|
|
303
|
+
walleDir: walleDir(),
|
|
304
|
+
nodePath: process.execPath,
|
|
305
|
+
});
|
|
306
|
+
} catch (err) {
|
|
307
|
+
lastNativeHealth = {
|
|
308
|
+
ok: false,
|
|
309
|
+
code: 'native_dependency_check_failed',
|
|
310
|
+
message: err.message || String(err),
|
|
311
|
+
error: { message: err.message || String(err) },
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
lastNativeHealthAt = now;
|
|
315
|
+
return lastNativeHealth;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async function ensureNativeDependenciesReady(source, { allowRebuild = true } = {}) {
|
|
319
|
+
let health = await getNativeDependencyStatus({ force: true });
|
|
320
|
+
if (health.ok) {
|
|
321
|
+
lastStartError = null;
|
|
322
|
+
return { ok: true, health };
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (allowRebuild && nativeDeps.shouldRebuild(health)) {
|
|
326
|
+
let rebuild = null;
|
|
327
|
+
try {
|
|
328
|
+
rebuild = await nativeDeps.rebuild({
|
|
329
|
+
walleDir: walleDir(),
|
|
330
|
+
nodePath: process.execPath,
|
|
331
|
+
});
|
|
332
|
+
} catch (err) {
|
|
333
|
+
rebuild = {
|
|
334
|
+
ok: false,
|
|
335
|
+
code: 'native_dependency_rebuild_failed',
|
|
336
|
+
message: err.message || String(err),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
health = {
|
|
340
|
+
...(await getNativeDependencyStatus({ force: true })),
|
|
341
|
+
rebuild_attempted: true,
|
|
342
|
+
rebuild,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (!health.ok) {
|
|
347
|
+
lastStartError = _nativeErrorPayload(health);
|
|
348
|
+
try {
|
|
349
|
+
telemetry.track('walle_native_dependency_failed', {
|
|
350
|
+
source: source || 'unknown',
|
|
351
|
+
code: health.code || 'unknown',
|
|
352
|
+
message: String(health.message || '').slice(0, 240),
|
|
353
|
+
node: health.node || {},
|
|
354
|
+
rebuild_attempted: !!health.rebuild_attempted,
|
|
355
|
+
rebuild_ok: !!health.rebuild?.ok,
|
|
356
|
+
});
|
|
357
|
+
} catch {}
|
|
358
|
+
return { ok: false, health };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
lastStartError = null;
|
|
362
|
+
return { ok: true, health };
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async function statusWithDiagnostics(base, { checkNative = false } = {}) {
|
|
366
|
+
let nativeDependency = lastNativeHealth;
|
|
367
|
+
if (checkNative) nativeDependency = await getNativeDependencyStatus({ force: false });
|
|
368
|
+
// Self-heal a stale MCP-not-ready verdict. A startup probe can time out before a
|
|
369
|
+
// large brain finishes booting (e.g. the first daily-backup VACUUM), leaving a
|
|
370
|
+
// sticky false "MCP never became ready" even though the daemon is now serving. If
|
|
371
|
+
// the process is running but the last verdict is not-ok, re-probe (throttled) — a
|
|
372
|
+
// successful mcpReadyProbeOnce() clears it; a failed probe leaves the verdict intact.
|
|
373
|
+
if (base.running && base.pid && (!lastMcpReady || lastMcpReady.ok === false)) {
|
|
374
|
+
const now = Date.now();
|
|
375
|
+
if (now - lastSelfHealProbeAt >= mcpReadySelfHealIntervalMs) {
|
|
376
|
+
lastSelfHealProbeAt = now;
|
|
377
|
+
try { await mcpReadyProbeOnce({ pid: base.pid, source: 'watchdog', timeoutMs: 2500 }); } catch {}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
const stoppedNativeFailure = nativeDependency && nativeDependency.ok === false ? nativeDependency : null;
|
|
381
|
+
const effectiveError = base.running ? null : (lastStartError || (stoppedNativeFailure ? _nativeErrorPayload(stoppedNativeFailure) : null));
|
|
382
|
+
return {
|
|
383
|
+
...base,
|
|
384
|
+
code: effectiveError ? effectiveError.code : null,
|
|
385
|
+
error: effectiveError ? effectiveError.message : null,
|
|
386
|
+
nativeDependency: nativeDependency || null,
|
|
387
|
+
lastStartError: lastStartError || null,
|
|
388
|
+
mcpReady: lastMcpReady || null,
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function sleep(ms) {
|
|
393
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
394
|
+
}
|
|
85
395
|
|
|
86
396
|
function waitForPortFree() {
|
|
87
397
|
return new Promise((resolve) => {
|
|
@@ -110,11 +420,10 @@ function createWalleSupervisor({
|
|
|
110
420
|
if (savedPid && savedPid !== myPid) pidSet.add(savedPid);
|
|
111
421
|
} catch {}
|
|
112
422
|
|
|
113
|
-
const
|
|
114
|
-
const discovered = await Promise.all([
|
|
423
|
+
const discovered = await Promise.all(processTitles().flatMap(title => [
|
|
115
424
|
processOps.findPidsByExactCommand ? processOps.findPidsByExactCommand(title) : [],
|
|
116
425
|
processOps.findListeningPidsByExactCommand ? processOps.findListeningPidsByExactCommand(wallePort, title) : [],
|
|
117
|
-
]);
|
|
426
|
+
]));
|
|
118
427
|
for (const p of discovered.flat()) {
|
|
119
428
|
if (p && p !== myPid) pidSet.add(p);
|
|
120
429
|
}
|
|
@@ -194,6 +503,12 @@ function createWalleSupervisor({
|
|
|
194
503
|
return waitForPortFree();
|
|
195
504
|
}
|
|
196
505
|
|
|
506
|
+
async function stopForProcessExit(reason = 'process-exit') {
|
|
507
|
+
intentionallyStopped = true;
|
|
508
|
+
try { telemetry.track('walle_stop_for_process_exit', { reason, port: wallePort }); } catch {}
|
|
509
|
+
return killAll();
|
|
510
|
+
}
|
|
511
|
+
|
|
197
512
|
function inCrashLoop() {
|
|
198
513
|
const now = Date.now();
|
|
199
514
|
restartHistory = restartHistory.filter(t => now - t < RESTART_WINDOW_MS);
|
|
@@ -201,8 +516,8 @@ function createWalleSupervisor({
|
|
|
201
516
|
}
|
|
202
517
|
|
|
203
518
|
function spawnWalle(source) {
|
|
204
|
-
const
|
|
205
|
-
const agentScript = path.join(
|
|
519
|
+
const dir = walleDir();
|
|
520
|
+
const agentScript = path.join(dir, 'agent.js');
|
|
206
521
|
let stderrTarget = 'ignore';
|
|
207
522
|
let crashLogFd = null;
|
|
208
523
|
try {
|
|
@@ -218,17 +533,20 @@ function createWalleSupervisor({
|
|
|
218
533
|
CTM_API_BASE_URL: `http://127.0.0.1:${ctmPort}`,
|
|
219
534
|
WALL_E_PORT: String(wallePort),
|
|
220
535
|
WALLE_INSTANCE_TAG: instanceTag,
|
|
536
|
+
WALL_E_PROCESS_ROLE: 'walle-daemon',
|
|
221
537
|
};
|
|
538
|
+
delete childEnv.CTM_PROCESS_ROLE;
|
|
222
539
|
if (walleToken) childEnv.WALL_E_API_TOKEN = walleToken;
|
|
223
540
|
|
|
224
|
-
const nextChild =
|
|
541
|
+
const nextChild = spawnProcess(
|
|
225
542
|
process.execPath,
|
|
226
543
|
[agentScript],
|
|
227
544
|
{
|
|
228
|
-
cwd:
|
|
545
|
+
cwd: dir,
|
|
229
546
|
detached: true,
|
|
230
547
|
stdio: ['ignore', 'ignore', stderrTarget],
|
|
231
548
|
env: childEnv,
|
|
549
|
+
argv0: processTitle(),
|
|
232
550
|
}
|
|
233
551
|
);
|
|
234
552
|
nextChild.unref();
|
|
@@ -248,6 +566,11 @@ function createWalleSupervisor({
|
|
|
248
566
|
restartHistory.push(Date.now());
|
|
249
567
|
if (inCrashLoop()) {
|
|
250
568
|
console.error(`[wall-e] Crash loop detected (${RESTART_BURST} restarts in ${RESTART_WINDOW_MS / 1000}s) - giving up. Use /api/start/walle to retry.`);
|
|
569
|
+
lastStartError = {
|
|
570
|
+
ok: false,
|
|
571
|
+
code: 'walle_crash_loop',
|
|
572
|
+
message: `Wall-E crashed ${RESTART_BURST} times in ${RESTART_WINDOW_MS / 1000}s and the supervisor stopped retrying.`,
|
|
573
|
+
};
|
|
251
574
|
try { telemetry.track('walle_crash_loop', { lastPid: myPid, code, signal }); } catch {}
|
|
252
575
|
intentionallyStopped = true;
|
|
253
576
|
return;
|
|
@@ -271,48 +594,47 @@ function createWalleSupervisor({
|
|
|
271
594
|
let stalePid = null;
|
|
272
595
|
|
|
273
596
|
if (childPid && isAlive(childPid)) {
|
|
274
|
-
return {
|
|
597
|
+
return statusWithDiagnostics({
|
|
275
598
|
running: true,
|
|
276
599
|
pid: childPid,
|
|
277
600
|
pidSource: 'child',
|
|
278
601
|
stalePid: savedPid && savedPid !== childPid ? savedPid : null,
|
|
279
602
|
repairedPidFile: savedPid !== childPid ? writePidFile(childPid) : false,
|
|
280
|
-
};
|
|
603
|
+
});
|
|
281
604
|
}
|
|
282
605
|
|
|
283
606
|
if (savedPid && isAlive(savedPid)) {
|
|
284
|
-
return { running: true, pid: savedPid, pidSource: 'pid_file' };
|
|
607
|
+
return statusWithDiagnostics({ running: true, pid: savedPid, pidSource: 'pid_file' });
|
|
285
608
|
}
|
|
286
609
|
if (savedPid) stalePid = savedPid;
|
|
287
610
|
|
|
288
|
-
const title = processTitle();
|
|
289
611
|
let discovered = [];
|
|
290
612
|
try {
|
|
291
|
-
const results = await Promise.all([
|
|
613
|
+
const results = await Promise.all(processTitles().flatMap(title => [
|
|
292
614
|
processOps.findPidsByExactCommand ? processOps.findPidsByExactCommand(title) : [],
|
|
293
615
|
processOps.findListeningPidsByExactCommand ? processOps.findListeningPidsByExactCommand(wallePort, title) : [],
|
|
294
|
-
]);
|
|
616
|
+
]));
|
|
295
617
|
discovered = [...new Set(results.flat().filter(pid => pid && isAlive(pid)))];
|
|
296
618
|
} catch {}
|
|
297
619
|
|
|
298
620
|
if (discovered.length > 0) {
|
|
299
621
|
const pid = discovered[0];
|
|
300
|
-
return {
|
|
622
|
+
return statusWithDiagnostics({
|
|
301
623
|
running: true,
|
|
302
624
|
pid,
|
|
303
625
|
pidSource: 'discovered',
|
|
304
626
|
stalePid,
|
|
305
627
|
repairedPidFile: writePidFile(pid),
|
|
306
|
-
};
|
|
628
|
+
});
|
|
307
629
|
}
|
|
308
630
|
|
|
309
|
-
return {
|
|
631
|
+
return statusWithDiagnostics({
|
|
310
632
|
running: false,
|
|
311
633
|
pid: null,
|
|
312
634
|
pidSource: stalePid ? 'stale_pid_file' : 'none',
|
|
313
635
|
stalePid,
|
|
314
636
|
removedStalePidFile: stalePid ? removePidFile() : false,
|
|
315
|
-
};
|
|
637
|
+
}, { checkNative: true });
|
|
316
638
|
}
|
|
317
639
|
|
|
318
640
|
function apiStop(req, res) {
|
|
@@ -321,77 +643,227 @@ function createWalleSupervisor({
|
|
|
321
643
|
killAll().then(() => writeJson(res, 200, { ok: true, message: 'Wall-E stopped' }));
|
|
322
644
|
}
|
|
323
645
|
|
|
324
|
-
function apiStart(req, res) {
|
|
646
|
+
async function apiStart(req, res) {
|
|
325
647
|
if (starting) {
|
|
326
648
|
return writeJson(res, 409, { ok: false, message: 'Wall-E start already in progress' });
|
|
327
649
|
}
|
|
328
650
|
starting = true;
|
|
329
651
|
intentionallyStopped = false;
|
|
330
652
|
restartHistory = [];
|
|
331
|
-
if (childPid) {
|
|
332
|
-
try {
|
|
333
|
-
process.kill(childPid, 0);
|
|
334
|
-
starting = false;
|
|
335
|
-
return writeJson(res, 200, { ok: true, message: 'Wall-E is already running on port ' + wallePort });
|
|
336
|
-
} catch {}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
let orphanPid = null;
|
|
340
653
|
try {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
654
|
+
if (childPid && isAlive(childPid)) {
|
|
655
|
+
const readyStatus = await mcpReadyProbeOnce({ pid: childPid, source: 'start_api_existing', timeoutMs: 2500 });
|
|
656
|
+
if (readyStatus.ok) {
|
|
657
|
+
return writeJson(res, 200, {
|
|
658
|
+
ok: true,
|
|
659
|
+
message: 'Wall-E is already running and MCP-ready on port ' + wallePort,
|
|
660
|
+
pid: childPid,
|
|
661
|
+
nativeDependency: lastNativeHealth || null,
|
|
662
|
+
mcpReady: readyStatus,
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
return writeJson(res, 503, {
|
|
666
|
+
ok: false,
|
|
667
|
+
code: readyStatus.code,
|
|
668
|
+
message: readyStatus.message,
|
|
669
|
+
pid: childPid,
|
|
670
|
+
nativeDependency: lastNativeHealth || null,
|
|
671
|
+
mcpReady: readyStatus,
|
|
672
|
+
});
|
|
345
673
|
}
|
|
346
|
-
} catch {}
|
|
347
674
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
675
|
+
const ready = await ensureNativeDependenciesReady('start_api');
|
|
676
|
+
if (!ready.ok) {
|
|
677
|
+
return writeJson(res, 503, {
|
|
678
|
+
..._nativeErrorPayload(ready.health),
|
|
679
|
+
ok: false,
|
|
680
|
+
message: `Wall-E cannot start because its native dependencies are not loadable: ${ready.health.message}`,
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
let orphanPid = null;
|
|
685
|
+
try {
|
|
686
|
+
const saved = parseInt(fs.readFileSync(pidFile(), 'utf8').trim(), 10);
|
|
687
|
+
if (saved && isAlive(saved)) orphanPid = saved;
|
|
688
|
+
} catch {}
|
|
689
|
+
|
|
690
|
+
if (orphanPid) {
|
|
691
|
+
console.log(`[wall-e] Found orphan process on port ${wallePort}: ${orphanPid} - killing before fresh start`);
|
|
692
|
+
try { processOps.kill(orphanPid, 'SIGTERM'); } catch {}
|
|
693
|
+
await sleep(3000);
|
|
352
694
|
try {
|
|
353
|
-
|
|
354
|
-
|
|
695
|
+
processOps.kill(orphanPid, 0);
|
|
696
|
+
processOps.kill(orphanPid, 'SIGKILL');
|
|
355
697
|
} catch {}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
writeJson(res, 200, {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
698
|
+
await sleep(2000);
|
|
699
|
+
const pid = spawnWalle('start_api_after_orphan_kill');
|
|
700
|
+
const readyStatus = await waitForMcpReady(pid, 'start_api_after_orphan_kill');
|
|
701
|
+
if (readyStatus.ok) {
|
|
702
|
+
return writeJson(res, 200, {
|
|
703
|
+
ok: true,
|
|
704
|
+
message: 'Wall-E started and MCP is ready on port ' + wallePort + ' (killed orphan).',
|
|
705
|
+
pid,
|
|
706
|
+
nativeDependency: ready.health,
|
|
707
|
+
mcpReady: readyStatus,
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
return writeJson(res, 503, {
|
|
711
|
+
ok: false,
|
|
712
|
+
code: readyStatus.code,
|
|
713
|
+
message: readyStatus.message,
|
|
714
|
+
pid,
|
|
715
|
+
nativeDependency: ready.health,
|
|
716
|
+
mcpReady: readyStatus,
|
|
717
|
+
});
|
|
718
|
+
}
|
|
365
719
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
720
|
+
const pid = spawnWalle('start_api');
|
|
721
|
+
const readyStatus = await waitForMcpReady(pid, 'start_api');
|
|
722
|
+
if (readyStatus.ok) {
|
|
723
|
+
return writeJson(res, 200, {
|
|
724
|
+
ok: true,
|
|
725
|
+
message: 'Wall-E started and MCP is ready on port ' + wallePort + '.',
|
|
726
|
+
pid,
|
|
727
|
+
nativeDependency: ready.health,
|
|
728
|
+
mcpReady: readyStatus,
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
return writeJson(res, 503, {
|
|
732
|
+
ok: false,
|
|
733
|
+
code: readyStatus.code,
|
|
734
|
+
message: readyStatus.message,
|
|
735
|
+
pid,
|
|
736
|
+
nativeDependency: ready.health,
|
|
737
|
+
mcpReady: readyStatus,
|
|
738
|
+
});
|
|
739
|
+
} catch (err) {
|
|
740
|
+
lastStartError = {
|
|
741
|
+
ok: false,
|
|
742
|
+
code: 'walle_spawn_failed',
|
|
743
|
+
message: err.message || String(err),
|
|
744
|
+
};
|
|
745
|
+
return writeJson(res, 500, lastStartError);
|
|
746
|
+
} finally {
|
|
747
|
+
starting = false;
|
|
748
|
+
}
|
|
370
749
|
}
|
|
371
750
|
|
|
372
751
|
function restartQuiet() {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
752
|
+
ensureNativeDependenciesReady('config_change').then((ready) => {
|
|
753
|
+
if (!ready.ok) {
|
|
754
|
+
console.error(`[setup] Wall-E restart blocked: ${ready.health.message}`);
|
|
755
|
+
return null;
|
|
756
|
+
}
|
|
757
|
+
intentionallyStopped = true;
|
|
758
|
+
return killAll().then(() => sleep(2000)).then(() => {
|
|
376
759
|
intentionallyStopped = false;
|
|
377
760
|
const pid = spawnWalle('config_change');
|
|
378
|
-
|
|
379
|
-
|
|
761
|
+
return waitForMcpReady(pid, 'config_change').then((readyStatus) => {
|
|
762
|
+
if (readyStatus.ok) {
|
|
763
|
+
console.log('[setup] Restarted Wall-E (PID ' + pid + ') and MCP is ready to pick up new API config');
|
|
764
|
+
} else {
|
|
765
|
+
console.error(`[setup] Wall-E restarted for config change but MCP readiness failed: ${readyStatus.message}`);
|
|
766
|
+
}
|
|
767
|
+
return pid;
|
|
768
|
+
});
|
|
769
|
+
});
|
|
770
|
+
}).catch((err) => {
|
|
771
|
+
intentionallyStopped = false;
|
|
772
|
+
lastStartError = {
|
|
773
|
+
ok: false,
|
|
774
|
+
code: 'walle_restart_failed',
|
|
775
|
+
message: err.message || String(err),
|
|
776
|
+
};
|
|
777
|
+
console.error(`[setup] Wall-E restart failed: ${lastStartError.message}`);
|
|
380
778
|
});
|
|
381
779
|
}
|
|
382
780
|
|
|
383
|
-
function apiRestart(req, res) {
|
|
781
|
+
async function apiRestart(req, res) {
|
|
782
|
+
const ready = await ensureNativeDependenciesReady('restart_api');
|
|
783
|
+
if (!ready.ok) {
|
|
784
|
+
return writeJson(res, 503, {
|
|
785
|
+
..._nativeErrorPayload(ready.health),
|
|
786
|
+
ok: false,
|
|
787
|
+
message: `Wall-E cannot restart because its native dependencies are not loadable: ${ready.health.message}`,
|
|
788
|
+
});
|
|
789
|
+
}
|
|
384
790
|
intentionallyStopped = true;
|
|
385
|
-
|
|
791
|
+
try {
|
|
792
|
+
await killAll();
|
|
386
793
|
intentionallyStopped = false;
|
|
387
794
|
const pid = spawnWalle('restart_api');
|
|
388
|
-
|
|
389
|
-
|
|
795
|
+
const readyStatus = await waitForMcpReady(pid, 'restart_api');
|
|
796
|
+
if (readyStatus.ok) {
|
|
797
|
+
return writeJson(res, 200, {
|
|
798
|
+
ok: true,
|
|
799
|
+
message: 'Wall-E restarted and MCP is ready.',
|
|
800
|
+
pid,
|
|
801
|
+
nativeDependency: ready.health,
|
|
802
|
+
mcpReady: readyStatus,
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
return writeJson(res, 503, {
|
|
806
|
+
ok: false,
|
|
807
|
+
code: readyStatus.code,
|
|
808
|
+
message: readyStatus.message,
|
|
809
|
+
pid,
|
|
810
|
+
nativeDependency: ready.health,
|
|
811
|
+
mcpReady: readyStatus,
|
|
812
|
+
});
|
|
813
|
+
} catch (err) {
|
|
814
|
+
intentionallyStopped = false;
|
|
815
|
+
lastStartError = {
|
|
816
|
+
ok: false,
|
|
817
|
+
code: 'walle_restart_failed',
|
|
818
|
+
message: err.message || String(err),
|
|
819
|
+
};
|
|
820
|
+
return writeJson(res, 500, lastStartError);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// One-shot, no-retry MCP readiness probe for external health watchdogs.
|
|
825
|
+
// Unlike waitForMcpReady (which loops until a deadline), this performs a
|
|
826
|
+
// single probe. A successful probe is authoritative enough to clear stale
|
|
827
|
+
// startup/MCP errors left behind by an earlier timeout; otherwise service
|
|
828
|
+
// status can keep reporting a dead Wall-E after the daemon has recovered.
|
|
829
|
+
async function mcpReadyProbeOnce({ timeoutMs = 2000, source = 'watchdog', pid = childPid } = {}) {
|
|
830
|
+
const probe = mcpReadyProbe || defaultMcpReadyProbe;
|
|
831
|
+
try {
|
|
832
|
+
const result = await probe({
|
|
833
|
+
pid,
|
|
834
|
+
port: wallePort,
|
|
835
|
+
token: walleToken,
|
|
836
|
+
source,
|
|
837
|
+
requestMcpJson: (message, opts = {}) => requestMcpJson(message, { timeoutMs, ...opts }),
|
|
838
|
+
});
|
|
839
|
+
if (result && typeof result === 'object' && result.ok === false) {
|
|
840
|
+
return { ok: false, code: result.code || 'walle_mcp_ready_failed', message: result.message || result.error || 'Wall-E MCP readiness probe failed' };
|
|
841
|
+
}
|
|
842
|
+
lastMcpReady = { ok: true, code: 'ok', message: 'Wall-E MCP is ready.', pid, source, ...(result && typeof result === 'object' ? result : {}) };
|
|
843
|
+
lastStartError = null;
|
|
844
|
+
return lastMcpReady;
|
|
845
|
+
} catch (err) {
|
|
846
|
+
return { ok: false, code: err.code || 'walle_mcp_probe_failed', message: err.message || String(err), pid, source };
|
|
847
|
+
}
|
|
390
848
|
}
|
|
391
849
|
|
|
392
|
-
function bootStart() {
|
|
850
|
+
async function bootStart() {
|
|
393
851
|
if (intentionallyStopped || isDisabled()) return Promise.resolve(null);
|
|
394
|
-
|
|
852
|
+
const ready = await ensureNativeDependenciesReady('boot');
|
|
853
|
+
if (!ready.ok) {
|
|
854
|
+
console.error(`[wall-e] Boot start blocked: ${ready.health.message}`);
|
|
855
|
+
return null;
|
|
856
|
+
}
|
|
857
|
+
await killAll();
|
|
858
|
+
const pid = spawnWalle('boot');
|
|
859
|
+
waitForMcpReady(pid, 'boot').then((readyStatus) => {
|
|
860
|
+
if (!readyStatus.ok) {
|
|
861
|
+
console.error(`[wall-e] Boot start MCP readiness failed: ${readyStatus.message}`);
|
|
862
|
+
}
|
|
863
|
+
}).catch((err) => {
|
|
864
|
+
console.error(`[wall-e] Boot start MCP readiness check threw: ${err.message}`);
|
|
865
|
+
});
|
|
866
|
+
return pid;
|
|
395
867
|
}
|
|
396
868
|
|
|
397
869
|
return {
|
|
@@ -400,10 +872,14 @@ function createWalleSupervisor({
|
|
|
400
872
|
apiStop,
|
|
401
873
|
bootStart,
|
|
402
874
|
getStatus,
|
|
875
|
+
getNativeDependencyStatus,
|
|
403
876
|
isIntentionallyStopped: () => intentionallyStopped,
|
|
404
877
|
killAll,
|
|
878
|
+
mcpReadyProbeOnce,
|
|
405
879
|
restartQuiet,
|
|
880
|
+
stopForProcessExit,
|
|
406
881
|
spawnWalle,
|
|
882
|
+
waitForMcpReady,
|
|
407
883
|
};
|
|
408
884
|
}
|
|
409
885
|
|