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.
Files changed (500) hide show
  1. package/README.md +27 -5
  2. package/package.json +2 -2
  3. package/template/CLAUDE.md +2 -2
  4. package/template/LICENSE +1 -1
  5. package/template/bin/ctm-dev-cleanup.js +24 -3
  6. package/template/bin/ctm-launch.sh +13 -0
  7. package/template/bin/dev.sh +156 -18
  8. package/template/bin/node-bin.sh +84 -0
  9. package/template/bin/pin-node.sh +51 -0
  10. package/template/claude-task-manager/api-prompts.js +1203 -182
  11. package/template/claude-task-manager/api-reviews.js +109 -15
  12. package/template/claude-task-manager/approval-agent.js +1360 -280
  13. package/template/claude-task-manager/bin/restart-ctm.sh +64 -23
  14. package/template/claude-task-manager/bin/storage-migration-supervisor.js +338 -0
  15. package/template/claude-task-manager/db.js +4417 -295
  16. package/template/claude-task-manager/docs/app-update-refresh-protocol.md +69 -0
  17. package/template/claude-task-manager/docs/approval-ai-refinement.md +138 -0
  18. package/template/claude-task-manager/docs/approval-rescue-loop.md +74 -0
  19. package/template/claude-task-manager/docs/codex-operational-warning-health.md +107 -0
  20. package/template/claude-task-manager/docs/codex-resume-state-guard-design.md +17 -12
  21. package/template/claude-task-manager/docs/codex-terminal-render-controller-handoff.md +311 -0
  22. package/template/claude-task-manager/docs/coding-agent-hooks-architecture.md +418 -0
  23. package/template/claude-task-manager/docs/conversation-import-freshness.md +20 -0
  24. package/template/claude-task-manager/docs/google-workspace-auth-health.md +77 -0
  25. package/template/claude-task-manager/docs/image-paste-ux.md +13 -0
  26. package/template/claude-task-manager/docs/ipad-web-preview.md +88 -0
  27. package/template/claude-task-manager/docs/main-loop-offload-architecture.md +66 -0
  28. package/template/claude-task-manager/docs/microsoft-dev-tunnel-phone-access-design.md +274 -519
  29. package/template/claude-task-manager/docs/mobile-live-streaming.md +27 -5
  30. package/template/claude-task-manager/docs/mobile-remote-submission-lifecycle.md +69 -0
  31. package/template/claude-task-manager/docs/phone-access-design.md +53 -15
  32. package/template/claude-task-manager/docs/phone-passkey-identity.md +122 -0
  33. package/template/claude-task-manager/docs/phone-setup.md +3 -0
  34. package/template/claude-task-manager/docs/prompt-editing-tree-design.md +25 -1
  35. package/template/claude-task-manager/docs/remote-desktop-access-design.md +268 -0
  36. package/template/claude-task-manager/docs/restart-lifecycle-architecture.md +95 -0
  37. package/template/claude-task-manager/docs/runtime-work-control-plane.md +53 -0
  38. package/template/claude-task-manager/docs/session-interactive-wait-surfaces.md +38 -0
  39. package/template/claude-task-manager/docs/session-needs-you-dismissal.md +84 -0
  40. package/template/claude-task-manager/docs/session-render-state-management-design.md +91 -3
  41. package/template/claude-task-manager/docs/session-standup-command-center-design.md +25 -1
  42. package/template/claude-task-manager/docs/session-title-authority.md +32 -0
  43. package/template/claude-task-manager/docs/session-workspace-binding.md +33 -0
  44. package/template/claude-task-manager/docs/skill-intent-resolution-design.md +72 -0
  45. package/template/claude-task-manager/docs/walle-mcp-supervisor-health.md +86 -0
  46. package/template/claude-task-manager/docs/walle-relay-phone-access-design.md +24 -15
  47. package/template/claude-task-manager/docs/walle-session-history-hydration.md +114 -0
  48. package/template/claude-task-manager/docs/walle-session-input-queue.md +104 -0
  49. package/template/claude-task-manager/docs/walle-session-model-catalog.md +90 -0
  50. package/template/claude-task-manager/docs/walle-session-model-preferences.md +15 -6
  51. package/template/claude-task-manager/git-utils.js +897 -27
  52. package/template/claude-task-manager/lib/agent-capabilities.js +33 -0
  53. package/template/claude-task-manager/lib/agent-cli-cache.js +37 -7
  54. package/template/claude-task-manager/lib/agent-hooks-installer.js +26 -2
  55. package/template/claude-task-manager/lib/agent-presets.js +17 -1
  56. package/template/claude-task-manager/lib/all-sessions-query.js +108 -0
  57. package/template/claude-task-manager/lib/approval-ai-refinement.js +488 -0
  58. package/template/claude-task-manager/lib/approval-self-adapt.js +168 -0
  59. package/template/claude-task-manager/lib/async-semaphore.js +44 -0
  60. package/template/claude-task-manager/lib/auth-context.js +5 -0
  61. package/template/claude-task-manager/lib/auth-rate-limit.js +47 -4
  62. package/template/claude-task-manager/lib/auth-rules.js +29 -2
  63. package/template/claude-task-manager/lib/auto-approval-verifier.js +129 -16
  64. package/template/claude-task-manager/lib/background-llm.js +144 -17
  65. package/template/claude-task-manager/lib/branch-inventory.js +212 -0
  66. package/template/claude-task-manager/lib/claude-desktop-sessions.js +15 -3
  67. package/template/claude-task-manager/lib/coalesce-sync-frames.js +151 -0
  68. package/template/claude-task-manager/lib/codex-launch-health.js +762 -0
  69. package/template/claude-task-manager/lib/codex-transcript-pager.js +51 -0
  70. package/template/claude-task-manager/lib/codex-zst.js +124 -0
  71. package/template/claude-task-manager/lib/coding-agent-models.js +233 -30
  72. package/template/claude-task-manager/lib/connection-health.js +232 -0
  73. package/template/claude-task-manager/lib/conversation-blob-parser.js +42 -0
  74. package/template/claude-task-manager/lib/conversation-tail-merge.js +89 -26
  75. package/template/claude-task-manager/lib/ctm-session-context-api.js +39 -10
  76. package/template/claude-task-manager/lib/cursor-conversation-store.js +354 -0
  77. package/template/claude-task-manager/lib/db-owner-worker-client.js +315 -0
  78. package/template/claude-task-manager/lib/document-review.js +141 -6
  79. package/template/claude-task-manager/lib/escalation-review.js +152 -0
  80. package/template/claude-task-manager/lib/graceful-shutdown.js +159 -0
  81. package/template/claude-task-manager/lib/headless-term-service.js +678 -0
  82. package/template/claude-task-manager/lib/heavy-worker-fallback.js +38 -0
  83. package/template/claude-task-manager/lib/jsonl-conversation-parser.js +542 -0
  84. package/template/claude-task-manager/lib/jsonl-range-reader.js +112 -0
  85. package/template/claude-task-manager/lib/main-db-census.js +216 -0
  86. package/template/claude-task-manager/lib/message-pagination.js +106 -4
  87. package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +750 -26
  88. package/template/claude-task-manager/lib/mobile-auth-api.js +274 -7
  89. package/template/claude-task-manager/lib/mobile-auth-store.js +592 -10
  90. package/template/claude-task-manager/lib/mobile-notification-dispatcher.js +15 -0
  91. package/template/claude-task-manager/lib/model-overview-brain-fallback.js +311 -0
  92. package/template/claude-task-manager/lib/model-overview-cache.js +141 -0
  93. package/template/claude-task-manager/lib/models-health-routing-notice.js +126 -0
  94. package/template/claude-task-manager/lib/node-pin-guard.js +93 -0
  95. package/template/claude-task-manager/lib/perf-tracker.js +242 -6
  96. package/template/claude-task-manager/lib/permission-match.js +76 -0
  97. package/template/claude-task-manager/lib/permission-sync.js +133 -20
  98. package/template/claude-task-manager/lib/process-title.js +35 -0
  99. package/template/claude-task-manager/lib/prompt-executions-query.js +25 -0
  100. package/template/claude-task-manager/lib/prompt-index-disk-cache.js +44 -0
  101. package/template/claude-task-manager/lib/prompt-intent.js +132 -0
  102. package/template/claude-task-manager/lib/provider-user-context.js +34 -0
  103. package/template/claude-task-manager/lib/read-pool-client.js +313 -0
  104. package/template/claude-task-manager/lib/readpool-breaker.js +31 -0
  105. package/template/claude-task-manager/lib/recent-sessions-breaker.js +12 -0
  106. package/template/claude-task-manager/lib/remote-feedback-client.js +72 -0
  107. package/template/claude-task-manager/lib/remote-relay-protocol.js +37 -4
  108. package/template/claude-task-manager/lib/remote-relay-store.js +159 -0
  109. package/template/claude-task-manager/lib/remote-submission-observer.js +278 -0
  110. package/template/claude-task-manager/lib/restart-guard.js +109 -0
  111. package/template/claude-task-manager/lib/restore-interruption-detector.js +439 -0
  112. package/template/claude-task-manager/lib/restore-policy.js +13 -0
  113. package/template/claude-task-manager/lib/restore-resume-batch.js +74 -0
  114. package/template/claude-task-manager/lib/restore-runtime.js +68 -0
  115. package/template/claude-task-manager/lib/restore-storm.js +34 -0
  116. package/template/claude-task-manager/lib/resume-cwd.js +36 -0
  117. package/template/claude-task-manager/lib/resume-preflight.js +313 -0
  118. package/template/claude-task-manager/lib/runtime-work-registry.js +444 -0
  119. package/template/claude-task-manager/lib/sanitize-openai-auth.js +31 -0
  120. package/template/claude-task-manager/lib/scheduler.js +21 -1
  121. package/template/claude-task-manager/lib/scrollback-snapshot-store.js +159 -0
  122. package/template/claude-task-manager/lib/serial-task-queue.js +64 -0
  123. package/template/claude-task-manager/lib/server-listeners.js +239 -0
  124. package/template/claude-task-manager/lib/session-capture.js +42 -7
  125. package/template/claude-task-manager/lib/session-content-backfill.js +131 -0
  126. package/template/claude-task-manager/lib/session-history.js +388 -43
  127. package/template/claude-task-manager/lib/session-host-manager.js +287 -0
  128. package/template/claude-task-manager/lib/session-image-refs.js +209 -0
  129. package/template/claude-task-manager/lib/session-jobs.js +399 -59
  130. package/template/claude-task-manager/lib/session-prompt-index.js +137 -0
  131. package/template/claude-task-manager/lib/session-restore.js +53 -0
  132. package/template/claude-task-manager/lib/session-standup.js +123 -23
  133. package/template/claude-task-manager/lib/session-state-bus.js +14 -0
  134. package/template/claude-task-manager/lib/session-stream.js +64 -16
  135. package/template/claude-task-manager/lib/session-timeline-summary.js +260 -0
  136. package/template/claude-task-manager/lib/session-token-usage.js +494 -0
  137. package/template/claude-task-manager/lib/session-workspace-binding.js +356 -0
  138. package/template/claude-task-manager/lib/setup-network-config.js +9 -0
  139. package/template/claude-task-manager/lib/size-cap.js +45 -0
  140. package/template/claude-task-manager/lib/size-cap.test.js +62 -0
  141. package/template/claude-task-manager/lib/skill-autocomplete.js +180 -1
  142. package/template/claude-task-manager/lib/skill-intent-resolver.js +304 -0
  143. package/template/claude-task-manager/lib/sqlite-driver.js +19 -3
  144. package/template/claude-task-manager/lib/standup-attention.js +7 -3
  145. package/template/claude-task-manager/lib/status-authority.js +39 -0
  146. package/template/claude-task-manager/lib/status-hooks.js +4 -0
  147. package/template/claude-task-manager/lib/storage-migration.js +235 -0
  148. package/template/claude-task-manager/lib/structured-capture.js +298 -0
  149. package/template/claude-task-manager/lib/sync-io-census.js +163 -0
  150. package/template/claude-task-manager/lib/tailscale-setup.js +6 -0
  151. package/template/claude-task-manager/lib/terminal-activity-evidence.js +33 -0
  152. package/template/claude-task-manager/lib/terminal-choice.js +364 -0
  153. package/template/claude-task-manager/lib/terminal-control-sanitize.js +17 -0
  154. package/template/claude-task-manager/lib/terminal-fingerprint.js +48 -0
  155. package/template/claude-task-manager/lib/terminal-output-flush.js +84 -0
  156. package/template/claude-task-manager/lib/timeline-order.js +122 -0
  157. package/template/claude-task-manager/lib/transcript-store.js +348 -43
  158. package/template/claude-task-manager/lib/transport-security.js +84 -1
  159. package/template/claude-task-manager/lib/wait-state.js +184 -0
  160. package/template/claude-task-manager/lib/walle-client.js +47 -5
  161. package/template/claude-task-manager/lib/walle-ctm-history.js +564 -4
  162. package/template/claude-task-manager/lib/walle-external-actions.js +135 -16
  163. package/template/claude-task-manager/lib/walle-history-hydration.js +46 -0
  164. package/template/claude-task-manager/lib/walle-native-health.js +403 -0
  165. package/template/claude-task-manager/lib/walle-repair.js +701 -0
  166. package/template/claude-task-manager/lib/walle-session-cache.js +109 -0
  167. package/template/claude-task-manager/lib/walle-session-context.js +57 -21
  168. package/template/claude-task-manager/lib/walle-session-model-catalog.js +34 -0
  169. package/template/claude-task-manager/lib/walle-supervisor.js +539 -63
  170. package/template/claude-task-manager/lib/walle-transcript.js +52 -0
  171. package/template/claude-task-manager/lib/worktree-active-sync.js +11 -7
  172. package/template/claude-task-manager/lib/worktree-cwd.js +32 -1
  173. package/template/claude-task-manager/package.json +1 -1
  174. package/template/claude-task-manager/prompt-harvest.js +89 -66
  175. package/template/claude-task-manager/providers/claude-code.js +51 -3
  176. package/template/claude-task-manager/providers/cursor.js +140 -45
  177. package/template/claude-task-manager/public/css/reviews.css +551 -61
  178. package/template/claude-task-manager/public/css/setup.css +191 -0
  179. package/template/claude-task-manager/public/css/walle-session.css +865 -10
  180. package/template/claude-task-manager/public/css/walle.css +154 -0
  181. package/template/claude-task-manager/public/designs/ai-providers-consolidation-v2.html +830 -0
  182. package/template/claude-task-manager/public/index.html +18516 -2058
  183. package/template/claude-task-manager/public/ipad.html +363 -0
  184. package/template/claude-task-manager/public/js/document-review-links.js +301 -0
  185. package/template/claude-task-manager/public/js/image-normalize.js +69 -36
  186. package/template/claude-task-manager/public/js/message-renderer.js +1265 -77
  187. package/template/claude-task-manager/public/js/prompts.js +66 -29
  188. package/template/claude-task-manager/public/js/reviews.js +901 -133
  189. package/template/claude-task-manager/public/js/session-activity-utils.js +11 -1
  190. package/template/claude-task-manager/public/js/session-search-utils.js +94 -10
  191. package/template/claude-task-manager/public/js/session-status-precedence.js +23 -5
  192. package/template/claude-task-manager/public/js/setup.js +1273 -176
  193. package/template/claude-task-manager/public/js/stream-view.js +691 -73
  194. package/template/claude-task-manager/public/js/terminal-reconciler.js +210 -0
  195. package/template/claude-task-manager/public/js/walle-session.js +2455 -158
  196. package/template/claude-task-manager/public/js/walle.js +455 -28
  197. package/template/claude-task-manager/public/m/app.css +2909 -262
  198. package/template/claude-task-manager/public/m/app.js +6601 -398
  199. package/template/claude-task-manager/public/m/claim.html +224 -17
  200. package/template/claude-task-manager/public/m/index.html +117 -21
  201. package/template/claude-task-manager/public/m/sw.js +3 -1
  202. package/template/claude-task-manager/public/manifest.json +2 -2
  203. package/template/claude-task-manager/public/prompts.html +30 -14
  204. package/template/claude-task-manager/queue-engine.js +507 -28
  205. package/template/claude-task-manager/scripts/repair-claude-session-images.js +27 -8
  206. package/template/claude-task-manager/server.js +14341 -2197
  207. package/template/claude-task-manager/session-integrity.js +160 -18
  208. package/template/claude-task-manager/session-search-ranking.js +1 -0
  209. package/template/claude-task-manager/session-utils.js +25 -5
  210. package/template/claude-task-manager/workers/approval-blocklist.js +96 -6
  211. package/template/claude-task-manager/workers/approval-widget-validator.js +14 -8
  212. package/template/claude-task-manager/workers/conversation-import-worker.js +11 -50
  213. package/template/claude-task-manager/workers/db-owner-worker.js +386 -0
  214. package/template/claude-task-manager/workers/harvest-worker.js +9 -55
  215. package/template/claude-task-manager/workers/headless-term-worker.js +9 -530
  216. package/template/claude-task-manager/workers/read-pool-worker.js +387 -0
  217. package/template/claude-task-manager/workers/scrollback-worker.js +11 -72
  218. package/template/claude-task-manager/workers/session-host-process.js +146 -0
  219. package/template/claude-task-manager/workers/session-integrity-worker.js +10 -54
  220. package/template/claude-task-manager/workers/state-detectors/base.js +18 -1
  221. package/template/claude-task-manager/workers/state-detectors/claude-code.js +182 -9
  222. package/template/claude-task-manager/workers/state-detectors/codex.js +150 -2
  223. package/template/claude-task-manager/workers/state-detectors/cursor.js +127 -0
  224. package/template/claude-task-manager/workers/state-detectors/gemini.js +21 -0
  225. package/template/claude-task-manager/workers/state-detectors/index.js +29 -0
  226. package/template/claude-task-manager/workers/state-detectors/opencode.js +103 -0
  227. package/template/docs/design/markdown-review-pane.md +206 -0
  228. package/template/docs/designs/2026-05-17-portkey-gateway-provider-ux.md +129 -38
  229. package/template/docs/designs/2026-05-20-mobile-worktree-finish-command.md +27 -0
  230. package/template/docs/designs/2026-05-22-ai-configuration-consolidation.md +248 -0
  231. package/template/docs/designs/ai-configuration-consolidation-mock.html +812 -0
  232. package/template/docs/private-memory-and-pii-policy.md +69 -0
  233. package/template/package.json +2 -1
  234. package/template/scripts/check-private-data.js +201 -0
  235. package/template/shared/sqlite-owner-guard.js +30 -0
  236. package/template/shared/sqlite-owner-write-queue.js +225 -0
  237. package/template/shared/sqlite-storage-policy.js +111 -0
  238. package/template/shared/sqlite-write-lock.js +428 -0
  239. package/template/wall-e/agent-runners/claude-code.js +5 -0
  240. package/template/wall-e/agent.js +166 -22
  241. package/template/wall-e/api-walle.js +524 -70
  242. package/template/wall-e/auth/provider-flows.js +11 -1
  243. package/template/wall-e/bin/walle-mcp-stdio.js +341 -17
  244. package/template/wall-e/brain.js +1614 -141
  245. package/template/wall-e/chat/attachment-blocks.js +96 -0
  246. package/template/wall-e/chat/attachments.js +2 -1
  247. package/template/wall-e/chat/capability-resolver.js +7 -7
  248. package/template/wall-e/chat/context-messages.js +28 -0
  249. package/template/wall-e/chat/conversation-frame.js +630 -0
  250. package/template/wall-e/chat/provider-messages.js +125 -0
  251. package/template/wall-e/chat.js +1002 -233
  252. package/template/wall-e/coding/acceptance-contract.js +170 -0
  253. package/template/wall-e/coding/acp-adapter.js +1 -1
  254. package/template/wall-e/coding/agent-catalog.js +3 -0
  255. package/template/wall-e/coding/artifact-store.js +93 -0
  256. package/template/wall-e/coding/capability-router.js +120 -0
  257. package/template/wall-e/coding/coding-run-controller.js +423 -0
  258. package/template/wall-e/coding/compaction-service.js +157 -12
  259. package/template/wall-e/coding/frontend-verification.js +258 -0
  260. package/template/wall-e/coding/lifecycle-hooks.js +75 -0
  261. package/template/wall-e/coding/local-preview-contract.js +157 -0
  262. package/template/wall-e/coding/permission-service.js +57 -13
  263. package/template/wall-e/coding/prompt-bundle.js +19 -1
  264. package/template/wall-e/coding/prompt-section-registry.js +227 -0
  265. package/template/wall-e/coding/provider-compat.js +15 -0
  266. package/template/wall-e/coding/runtime-events.js +224 -0
  267. package/template/wall-e/coding/runtime-mode.js +3 -0
  268. package/template/wall-e/coding/side-git-snapshot.js +160 -4
  269. package/template/wall-e/coding/snapshot-service.js +143 -1
  270. package/template/wall-e/coding/stream-processor.js +388 -34
  271. package/template/wall-e/coding/task-tool.js +141 -4
  272. package/template/wall-e/coding/tool-execution-controller.js +365 -0
  273. package/template/wall-e/coding/tool-registry.js +43 -5
  274. package/template/wall-e/coding/user-hooks.js +217 -0
  275. package/template/wall-e/coding-orchestrator.js +1330 -221
  276. package/template/wall-e/coding-prompts.js +20 -4
  277. package/template/wall-e/context/context-builder.js +15 -2
  278. package/template/wall-e/decision/confidence.js +1 -1
  279. package/template/wall-e/docs/coding-acceptance-contract.md +41 -0
  280. package/template/wall-e/docs/external-action-controller.md +26 -6
  281. package/template/wall-e/docs/telemetry-lifecycle.md +8 -2
  282. package/template/wall-e/embeddings.js +591 -53
  283. package/template/wall-e/external-action-controller.js +12 -0
  284. package/template/wall-e/http/auth.js +1 -0
  285. package/template/wall-e/http/chat-api.js +46 -11
  286. package/template/wall-e/http/model-admin.js +836 -34
  287. package/template/wall-e/lib/boot-profile.js +88 -0
  288. package/template/wall-e/lib/event-loop-monitor.js +93 -0
  289. package/template/wall-e/lib/service-health.js +194 -0
  290. package/template/wall-e/llm/anthropic.js +130 -5
  291. package/template/wall-e/llm/client.js +266 -63
  292. package/template/wall-e/llm/default-fallback.js +382 -0
  293. package/template/wall-e/llm/health.js +19 -0
  294. package/template/wall-e/llm/message-guard.js +78 -0
  295. package/template/wall-e/llm/model-catalog.js +252 -1
  296. package/template/wall-e/llm/openai.js +26 -4
  297. package/template/wall-e/llm/portkey-sync.js +654 -0
  298. package/template/wall-e/llm/provider-error.js +30 -2
  299. package/template/wall-e/llm/registry.js +5 -1
  300. package/template/wall-e/llm/request-compat.js +67 -0
  301. package/template/wall-e/loops/backfill.js +79 -23
  302. package/template/wall-e/loops/brain-optimize.js +67 -0
  303. package/template/wall-e/loops/ingest.js +25 -10
  304. package/template/wall-e/loops/question-digest.js +160 -0
  305. package/template/wall-e/loops/reflect.js +6 -4
  306. package/template/wall-e/loops/think.js +39 -12
  307. package/template/wall-e/mcp-server.js +318 -36
  308. package/template/wall-e/memory/ctm-context-client.js +52 -14
  309. package/template/wall-e/memory/ctm-operational-context.js +237 -0
  310. package/template/wall-e/memory/ctm-prompt-executions-client.js +128 -0
  311. package/template/wall-e/memory/ctm-session-context.js +111 -63
  312. package/template/wall-e/prompts/coding/deepseek.txt +3 -0
  313. package/template/wall-e/prompts/coding/gemini.txt +6 -0
  314. package/template/wall-e/prompts/coding/gpt.txt +6 -0
  315. package/template/wall-e/prompts/coding/local.txt +7 -0
  316. package/template/wall-e/runtime/decision-hooks.js +115 -0
  317. package/template/wall-e/runtime/devbox-gateway.js +82 -8
  318. package/template/wall-e/runtime/prompt-manifest.js +86 -0
  319. package/template/wall-e/runtime/tool-executor.js +269 -0
  320. package/template/wall-e/runtime/tool-result-envelope.js +138 -0
  321. package/template/wall-e/runtime/transcript-projection.js +60 -0
  322. package/template/wall-e/runtime/walle-runtime.js +224 -0
  323. package/template/wall-e/scripts/db-optimize/migrate.js +162 -0
  324. package/template/wall-e/scripts/db-optimize/recall-eval.js +117 -0
  325. package/template/wall-e/server.js +15 -0
  326. package/template/wall-e/session-files.js +9 -0
  327. package/template/wall-e/skills/_bundled/google-calendar/run.js +1 -1
  328. package/template/wall-e/skills/_bundled/gws-workspace/run.js +1 -1
  329. package/template/wall-e/skills/_bundled/slack-mentions/run.js +76 -6
  330. package/template/wall-e/skills/claude-code-reader.js +7 -3
  331. package/template/wall-e/skills/script-skill-runner.js +10 -0
  332. package/template/wall-e/skills/skill-planner.js +38 -0
  333. package/template/wall-e/tools/builtin-middleware.js +19 -9
  334. package/template/wall-e/tools/local-tools.js +1428 -16
  335. package/template/wall-e/tools/permission-checker.js +73 -5
  336. package/template/wall-e/tools/question-manager.js +117 -7
  337. package/template/wall-e/training/harvester.js +12 -28
  338. package/template/wall-e/training/replay.js +25 -80
  339. package/template/website/index.html +10 -10
  340. package/template/wall-e/eval/ab-test.js +0 -203
  341. package/template/wall-e/eval/agent-runner.js +0 -772
  342. package/template/wall-e/eval/agent-scorer.js +0 -461
  343. package/template/wall-e/eval/aggregator.js +0 -414
  344. package/template/wall-e/eval/allowed-test-commands.js +0 -34
  345. package/template/wall-e/eval/benchmark-generator.js +0 -113
  346. package/template/wall-e/eval/benchmarks/chat-eval.json +0 -1662
  347. package/template/wall-e/eval/benchmarks/chat.json +0 -82
  348. package/template/wall-e/eval/benchmarks/coding-agent-real.json +0 -1
  349. package/template/wall-e/eval/benchmarks/coding-agent.json +0 -1581
  350. package/template/wall-e/eval/benchmarks/coding.json +0 -122
  351. package/template/wall-e/eval/benchmarks/memory-retrieval.json +0 -234
  352. package/template/wall-e/eval/benchmarks/reasoning.json +0 -82
  353. package/template/wall-e/eval/benchmarks/swebench-lite-30.json +0 -212
  354. package/template/wall-e/eval/benchmarks.js +0 -669
  355. package/template/wall-e/eval/cc-replay.js +0 -719
  356. package/template/wall-e/eval/chat-eval.js +0 -525
  357. package/template/wall-e/eval/check-keys.js +0 -15
  358. package/template/wall-e/eval/check-providers.js +0 -42
  359. package/template/wall-e/eval/codex-cli-baseline.js +0 -669
  360. package/template/wall-e/eval/coding-agent-real.js +0 -570
  361. package/template/wall-e/eval/context-compactor.js +0 -251
  362. package/template/wall-e/eval/debug-agent003.js +0 -68
  363. package/template/wall-e/eval/diagnostics.js +0 -216
  364. package/template/wall-e/eval/eval-orchestrator.js +0 -642
  365. package/template/wall-e/eval/evaluate.js +0 -202
  366. package/template/wall-e/eval/evaluator.js +0 -373
  367. package/template/wall-e/eval/exporter.js +0 -212
  368. package/template/wall-e/eval/fixtures/express-basic/package.json +0 -9
  369. package/template/wall-e/eval/fixtures/express-basic/server.js +0 -115
  370. package/template/wall-e/eval/fixtures/express-basic/test.js +0 -83
  371. package/template/wall-e/eval/fixtures/express-buggy/package.json +0 -9
  372. package/template/wall-e/eval/fixtures/express-buggy/server.js +0 -113
  373. package/template/wall-e/eval/fixtures/express-buggy/test.js +0 -83
  374. package/template/wall-e/eval/fixtures/express-buggy-items/package.json +0 -9
  375. package/template/wall-e/eval/fixtures/express-buggy-items/server.js +0 -112
  376. package/template/wall-e/eval/fixtures/express-buggy-items/test.js +0 -83
  377. package/template/wall-e/eval/fixtures/express-buggy-search/package.json +0 -9
  378. package/template/wall-e/eval/fixtures/express-buggy-search/server.js +0 -121
  379. package/template/wall-e/eval/fixtures/express-buggy-search/test.js +0 -83
  380. package/template/wall-e/eval/fixtures/express-rename-data/data.js +0 -34
  381. package/template/wall-e/eval/fixtures/express-rename-data/package.json +0 -9
  382. package/template/wall-e/eval/fixtures/express-rename-data/server.js +0 -97
  383. package/template/wall-e/eval/fixtures/express-rename-data/test.js +0 -88
  384. package/template/wall-e/eval/fixtures/express-xss/package.json +0 -12
  385. package/template/wall-e/eval/fixtures/express-xss/server.js +0 -90
  386. package/template/wall-e/eval/fixtures/express-xss/test.js +0 -67
  387. package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +0 -9
  388. package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +0 -9
  389. package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +0 -13
  390. package/template/wall-e/eval/fixtures/fullstack-app/package.json +0 -11
  391. package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +0 -137
  392. package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +0 -46
  393. package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +0 -121
  394. package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +0 -71
  395. package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +0 -80
  396. package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +0 -46
  397. package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +0 -45
  398. package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +0 -38
  399. package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +0 -23
  400. package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +0 -46
  401. package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +0 -99
  402. package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +0 -94
  403. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +0 -19
  404. package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +0 -19
  405. package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +0 -50
  406. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +0 -69
  407. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +0 -23
  408. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +0 -88
  409. package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +0 -75
  410. package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +0 -198
  411. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +0 -34
  412. package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +0 -26
  413. package/template/wall-e/eval/fixtures/fullstack-app/server.js +0 -8
  414. package/template/wall-e/eval/fixtures/fullstack-app/test.js +0 -12
  415. package/template/wall-e/eval/fixtures/monorepo-basic/package.json +0 -8
  416. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +0 -58
  417. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +0 -46
  418. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +0 -8
  419. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +0 -64
  420. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +0 -56
  421. package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +0 -116
  422. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +0 -61
  423. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +0 -62
  424. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +0 -43
  425. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +0 -11
  426. package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +0 -44
  427. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +0 -43
  428. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +0 -12
  429. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +0 -5
  430. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +0 -55
  431. package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +0 -29
  432. package/template/wall-e/eval/fixtures/monorepo-basic/test.js +0 -46
  433. package/template/wall-e/eval/fixtures/node-cli/index.js +0 -78
  434. package/template/wall-e/eval/fixtures/node-cli/package.json +0 -10
  435. package/template/wall-e/eval/fixtures/node-cli/test.js +0 -57
  436. package/template/wall-e/eval/fixtures/node-typed/package.json +0 -8
  437. package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +0 -31
  438. package/template/wall-e/eval/fixtures/node-typed/src/utils.js +0 -33
  439. package/template/wall-e/eval/fixtures/node-typed/test.js +0 -36
  440. package/template/wall-e/eval/fixtures/python-flask/app.py +0 -14
  441. package/template/wall-e/eval/fixtures/python-flask/requirements.txt +0 -2
  442. package/template/wall-e/eval/fixtures/python-flask/test_app.py +0 -25
  443. package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +0 -105
  444. package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +0 -101
  445. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +0 -20
  446. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +0 -32
  447. package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +0 -64
  448. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +0 -6
  449. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +0 -31
  450. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +0 -18
  451. package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +0 -34
  452. package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +0 -104
  453. package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +0 -73
  454. package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +0 -134
  455. package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +0 -99
  456. package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +0 -63
  457. package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +0 -70
  458. package/template/wall-e/eval/fixtures/wall-e-subset/package.json +0 -10
  459. package/template/wall-e/eval/fixtures/wall-e-subset/test.js +0 -86
  460. package/template/wall-e/eval/harvester.js +0 -685
  461. package/template/wall-e/eval/head-to-head.js +0 -388
  462. package/template/wall-e/eval/humaneval-adapter.js +0 -321
  463. package/template/wall-e/eval/list-models.js +0 -31
  464. package/template/wall-e/eval/livecodebench-adapter.js +0 -291
  465. package/template/wall-e/eval/mail-integration.js +0 -443
  466. package/template/wall-e/eval/manifest.js +0 -186
  467. package/template/wall-e/eval/meta-harness/adapters/coding-agent.js +0 -57
  468. package/template/wall-e/eval/meta-harness/bootstrap-snapshot.js +0 -149
  469. package/template/wall-e/eval/meta-harness/candidate-store.js +0 -117
  470. package/template/wall-e/eval/meta-harness/cli.js +0 -86
  471. package/template/wall-e/eval/meta-harness/domain-spec.js +0 -154
  472. package/template/wall-e/eval/meta-harness/domains/coding-agent.domain.json +0 -84
  473. package/template/wall-e/eval/meta-harness/examples/env-bootstrap-candidate.js +0 -29
  474. package/template/wall-e/eval/meta-harness/experience-store.js +0 -174
  475. package/template/wall-e/eval/meta-harness/frontier.js +0 -96
  476. package/template/wall-e/eval/meta-harness/harness-interface.js +0 -90
  477. package/template/wall-e/eval/meta-harness/leakage-guard.js +0 -80
  478. package/template/wall-e/eval/meta-harness/optimizer.js +0 -207
  479. package/template/wall-e/eval/meta-harness/proposer-runner.js +0 -110
  480. package/template/wall-e/eval/meta-harness/reporting.js +0 -58
  481. package/template/wall-e/eval/meta-harness/telemetry.js +0 -27
  482. package/template/wall-e/eval/meta-harness/validation.js +0 -81
  483. package/template/wall-e/eval/promoter.js +0 -228
  484. package/template/wall-e/eval/provider-normalizer.js +0 -33
  485. package/template/wall-e/eval/replay.js +0 -395
  486. package/template/wall-e/eval/run-agent-benchmarks.js +0 -386
  487. package/template/wall-e/eval/run-codex-cli-baseline.js +0 -177
  488. package/template/wall-e/eval/run-coding-agent-real.js +0 -187
  489. package/template/wall-e/eval/run-eval.js +0 -435
  490. package/template/wall-e/eval/run-model-comparison.js +0 -142
  491. package/template/wall-e/eval/session-evaluator.js +0 -187
  492. package/template/wall-e/eval/session-miner.js +0 -207
  493. package/template/wall-e/eval/session-retrieval-benchmark.js +0 -150
  494. package/template/wall-e/eval/session-transcripts.js +0 -509
  495. package/template/wall-e/eval/shadow.js +0 -161
  496. package/template/wall-e/eval/swebench-adapter.js +0 -345
  497. package/template/wall-e/eval/swebench-docker.js +0 -192
  498. package/template/wall-e/eval/train.py +0 -320
  499. package/template/wall-e/eval/trainer.js +0 -232
  500. package/template/wall-e/eval/weekly-eval-loop.js +0 -241
@@ -2,10 +2,13 @@
2
2
 
3
3
  const { DEFAULT_TIER_MODELS } = require('../evaluation/tier-selector');
4
4
  const providerRegistry = require('./registry');
5
+ const { isPortkeyProviderConfig } = require('./portkey');
6
+ const { withProviderMessageGuard } = require('./message-guard');
5
7
 
6
8
  function normalizeProviderType(type) {
7
9
  const text = String(type || '').trim().toLowerCase().replace(/_/g, '-');
8
10
  if (text === 'kimi' || text === 'kimi-k2' || text === 'moonshot-ai') return 'moonshot';
11
+ if (text === 'openai-compatible' || text.startsWith('openai-compatible-')) return 'openai';
9
12
  return text;
10
13
  }
11
14
 
@@ -26,11 +29,19 @@ function normalizeProviderType(type) {
26
29
  function createClient(type, config = {}) {
27
30
  providerRegistry.ensureBootstrapped();
28
31
  const providerType = normalizeProviderType(type);
29
- const provider = providerRegistry.createProvider(providerType, config);
32
+ const providerConfig = { ...config };
33
+ const rawProviderType = String(type || '').trim().toLowerCase().replace(/_/g, '-');
34
+ if (rawProviderType === 'openai-compatible' || rawProviderType.startsWith('openai-compatible-')) {
35
+ providerConfig.allowUnknownModels = true;
36
+ }
37
+ let provider = providerRegistry.createProvider(providerType, providerConfig);
38
+ if (!provider && isPortkeyProviderConfig(config)) {
39
+ provider = providerRegistry.createProvider('openai', providerConfig);
40
+ }
30
41
  if (!provider) {
31
42
  throw new Error(`Unknown provider type: ${type}`);
32
43
  }
33
- return withStreamFallback(provider);
44
+ return withStreamFallback(withProviderMessageGuard(provider));
34
45
  }
35
46
 
36
47
  function withStreamFallback(provider) {
@@ -121,72 +132,185 @@ function _modelMatchesProvider(model, provider) {
121
132
  * Get or create the default LLM client based on WALLE_PROVIDER env var.
122
133
  * Falls back to Anthropic if not set. Cached after first call.
123
134
  */
124
- function getDefaultClient() {
125
- if (!_defaultClient) {
126
- providerRegistry.ensureBootstrapped();
127
- const providerType = getDefaultProviderType();
128
- const dbKey = _getProviderKeyFromDb(providerType);
129
- const authMethod = getDefaultAuthMethod(providerType);
130
-
131
- // Anthropic auth_method=claude_cli routes through the user's `claude`
132
- // CLI (subscription billing) instead of the SDK against api.anthropic.com.
133
- // Other providers ignore this — claude_cli only makes sense for Claude.
134
- if (providerType === 'anthropic' && authMethod === 'claude_cli') {
135
- _defaultClient = createClient('claude-cli', {});
136
- return _defaultClient;
137
- }
135
+ // Resolve ONLY the user's chosen default provider into a client + identity,
136
+ // applying the full auth_method handling (claude_cli / oauth_proxy / codex_cli /
137
+ // DB config / env). This is the FIRST link of the resilient chain.
138
+ function _resolvePrimaryDefault() {
139
+ providerRegistry.ensureBootstrapped();
140
+ const providerType = getDefaultProviderType();
141
+ const dbKey = _getProviderKeyFromDb(providerType);
142
+ const authMethod = getDefaultAuthMethod(providerType);
138
143
 
139
- // Anthropic auth_method=oauth_proxy points the SDK at the local proxy
140
- // (CTM-managed, see claude-task-manager/oauth-proxy.js). The proxy
141
- // forwards requests with the user's claude.ai OAuth Bearer token. We
142
- // pass an empty placeholder apiKey; the proxy ignores it and replaces
143
- // auth headers with its own.
144
- if (providerType === 'anthropic' && authMethod === 'oauth_proxy') {
145
- const port = process.env.OAUTH_PROXY_PORT || '3458';
146
- _defaultClient = createClient('anthropic', {
147
- apiKey: 'oauth-proxy-placeholder',
148
- baseUrl: `http://127.0.0.1:${port}`,
149
- });
150
- return _defaultClient;
151
- }
144
+ // Anthropic auth_method=claude_cli routes through the user's `claude`
145
+ // CLI (subscription billing) instead of the SDK against api.anthropic.com.
146
+ if (providerType === 'anthropic' && authMethod === 'claude_cli') {
147
+ return { id: 'claude-cli', type: 'claude-cli', client: createClient('claude-cli', {}) };
148
+ }
152
149
 
153
- // OpenAI auth_method=codex_cli routes through the user's `codex` CLI
154
- // (ChatGPT subscription billing) instead of api.openai.com. Mirrors the
155
- // Anthropic claude_cli path but with codex-cli as the underlying provider.
156
- if (providerType === 'openai' && authMethod === 'codex_cli') {
157
- _defaultClient = createClient('codex-cli', {});
158
- return _defaultClient;
159
- }
150
+ // Anthropic auth_method=oauth_proxy points the SDK at the local proxy
151
+ // (CTM-managed, see claude-task-manager/oauth-proxy.js). The proxy forwards
152
+ // requests with the user's claude.ai OAuth Bearer token.
153
+ if (providerType === 'anthropic' && authMethod === 'oauth_proxy') {
154
+ const port = process.env.OAUTH_PROXY_PORT || '3458';
155
+ return {
156
+ id: `${providerType}-oauth`,
157
+ type: providerType,
158
+ client: createClient('anthropic', { apiKey: 'oauth-proxy-placeholder', baseUrl: `http://127.0.0.1:${port}` }),
159
+ };
160
+ }
161
+
162
+ // OpenAI auth_method=codex_cli routes through the user's `codex` CLI
163
+ // (ChatGPT subscription billing) instead of api.openai.com.
164
+ if (providerType === 'openai' && authMethod === 'codex_cli') {
165
+ return { id: 'codex-cli', type: 'codex-cli', client: createClient('codex-cli', {}) };
166
+ }
160
167
 
161
- if (providerType === 'anthropic') {
168
+ let client;
169
+ if (providerType === 'anthropic') {
170
+ const config = _getProviderConfigFromDb(providerType);
171
+ const hasSpecificConfig = !!(config.apiKey || config.baseUrl || config.customHeaders);
172
+ if (hasSpecificConfig) {
173
+ if (!config.apiKey) config.apiKey = dbKey || process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
174
+ client = createClient('anthropic', config);
175
+ } else {
162
176
  // If DB has the key, set it in env so createAnthropicFromEnv picks it up
163
177
  if (dbKey && !process.env.ANTHROPIC_API_KEY) process.env.ANTHROPIC_API_KEY = dbKey;
164
178
  const fromEnv = providerRegistry.createProviderFromEnv('anthropic');
165
- _defaultClient = fromEnv || createClient('anthropic', { apiKey: dbKey });
166
- } else {
167
- const config = {};
168
- if (providerType === 'openai') {
169
- config.apiKey = dbKey || process.env.OPENAI_API_KEY;
170
- if (process.env.OPENAI_BASE_URL) config.baseUrl = process.env.OPENAI_BASE_URL;
171
- } else if (providerType === 'google') {
172
- config.apiKey = dbKey || process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY;
173
- if (process.env.GOOGLE_AUTH_MODE === 'oauth') {
174
- config.authMode = 'oauth';
175
- config.refreshToken = process.env.GOOGLE_REFRESH_TOKEN;
176
- }
177
- } else if (providerType === 'ollama') {
178
- if (process.env.OLLAMA_BASE_URL) config.baseUrl = process.env.OLLAMA_BASE_URL;
179
- } else if (providerType === 'mlx') {
180
- if (process.env.MLX_MODEL) config.model = process.env.MLX_MODEL;
181
- } else if (providerType === 'deepseek') {
182
- config.apiKey = dbKey || process.env.DEEPSEEK_API_KEY;
183
- if (process.env.DEEPSEEK_BASE_URL) config.baseUrl = process.env.DEEPSEEK_BASE_URL;
184
- } else if (providerType === 'moonshot') {
185
- config.apiKey = dbKey || process.env.MOONSHOT_API_KEY;
186
- if (process.env.MOONSHOT_BASE_URL) config.baseUrl = process.env.MOONSHOT_BASE_URL;
179
+ client = fromEnv || createClient('anthropic', { apiKey: dbKey });
180
+ }
181
+ } else {
182
+ const config = _getProviderConfigFromDb(providerType);
183
+ if (providerType === 'openai') {
184
+ config.apiKey = config.apiKey || dbKey || process.env.OPENAI_API_KEY;
185
+ if (!config.baseUrl && process.env.OPENAI_BASE_URL) config.baseUrl = process.env.OPENAI_BASE_URL;
186
+ } else if (providerType === 'google') {
187
+ config.apiKey = config.apiKey || dbKey || process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY;
188
+ if (process.env.GOOGLE_AUTH_MODE === 'oauth') {
189
+ config.authMode = 'oauth';
190
+ config.refreshToken = process.env.GOOGLE_REFRESH_TOKEN;
187
191
  }
188
- _defaultClient = createClient(providerType, config);
192
+ } else if (providerType === 'ollama') {
193
+ if (!config.baseUrl && process.env.OLLAMA_BASE_URL) config.baseUrl = process.env.OLLAMA_BASE_URL;
194
+ } else if (providerType === 'mlx') {
195
+ if (process.env.MLX_MODEL) config.model = process.env.MLX_MODEL;
196
+ } else if (providerType === 'deepseek') {
197
+ config.apiKey = config.apiKey || dbKey || process.env.DEEPSEEK_API_KEY;
198
+ if (!config.baseUrl && process.env.DEEPSEEK_BASE_URL) config.baseUrl = process.env.DEEPSEEK_BASE_URL;
199
+ } else if (providerType === 'moonshot') {
200
+ config.apiKey = config.apiKey || dbKey || process.env.MOONSHOT_API_KEY;
201
+ if (!config.baseUrl && process.env.MOONSHOT_BASE_URL) config.baseUrl = process.env.MOONSHOT_BASE_URL;
189
202
  }
203
+ client = createClient(providerType, config);
204
+ }
205
+
206
+ let id = `${providerType}-default`;
207
+ try {
208
+ const brain = require('../brain');
209
+ const preferred = brain.getPreferredModelProviderForType?.(providerType);
210
+ if (preferred?.id) id = preferred.id;
211
+ } catch {}
212
+ return { id, type: providerType, client };
213
+ }
214
+
215
+ // Surface a fallback to the user/operator: the live default was unreachable and a
216
+ // different set-up provider (or a CLI) answered. Logged + emitted on the health bus
217
+ // (consumed by chat-api / model-admin → UI). Never throws.
218
+ function _notifyDefaultFallback(from, to, error) {
219
+ const fromLabel = from?.label || from?.type || from?.id || 'default provider';
220
+ const toLabel = to?.label || to?.type || to?.id || 'fallback provider';
221
+ const message = `Default provider "${fromLabel}" is unreachable — answering via "${toLabel}" until it recovers.`;
222
+ // Surface WHY (secret-redacted) so a misconfig — e.g. a model/virtual-key mismatch —
223
+ // doesn't look like a generic outage in the routing-notice banner.
224
+ let detail = '';
225
+ try { detail = require('./provider-error').fallbackErrorDetail(error); } catch {}
226
+ // Steady-state path: once the primary is health-marked 'down', activeChain() skips
227
+ // it entirely so the fallback loop never re-throws — `error` is undefined and the
228
+ // banner would lose its reason. Recover it from the primary's stored health error
229
+ // (the failure that marked it down is exactly why we're still falling back).
230
+ if (!detail && from?.id) {
231
+ try {
232
+ const le = require('./health').default.getProviderHealth?.(from.id)?.lastError;
233
+ if (le && (le.message || le.code != null)) {
234
+ const synth = { message: le.message, code: le.code };
235
+ if (typeof le.code === 'number') synth.status = le.code;
236
+ detail = require('./provider-error').fallbackErrorDetail(synth);
237
+ }
238
+ } catch {}
239
+ }
240
+ try { console.warn(`[llm] ${message}${detail ? ' — ' + detail : ''}`); } catch {}
241
+ try {
242
+ const health = require('./health').default;
243
+ health.emit('default-provider-fallback', { from: { id: from?.id, type: from?.type }, to: { id: to?.id, type: to?.type }, detail });
244
+ health.recordRoutingNotice({ kind: 'fallback', severity: 'warning', from: { id: from?.id, type: from?.type, label: fromLabel }, to: { id: to?.id, type: to?.type, label: toLabel }, message, detail });
245
+ } catch {}
246
+ try { require('../lib/recovery-logger').warn('default-fallback', 'provider_unreachable', { from: from?.type, to: to?.type, detail }); } catch {}
247
+ }
248
+
249
+ function _notifyDefaultExhausted(error) {
250
+ // Secret-redacted detail (replaces the old raw error.message, which could echo creds).
251
+ let detail = '';
252
+ try { detail = require('./provider-error').fallbackErrorDetail(error); } catch {}
253
+ const message = `Every configured provider is unreachable. Check connectivity or Setup.${detail ? ' (' + detail + ')' : ''}`;
254
+ try { console.error(`[llm] ${message}`); } catch {}
255
+ try {
256
+ const health = require('./health').default;
257
+ health.emit('default-provider-unreachable', { error: detail || String(error?.message || error || '') });
258
+ health.recordRoutingNotice({ kind: 'unreachable', severity: 'error', message, detail });
259
+ } catch {}
260
+ }
261
+
262
+ function _clearDefaultRoutingNotice() {
263
+ try { require('./health').default.clearRoutingNotice(); } catch {}
264
+ }
265
+
266
+ function getDefaultClient() {
267
+ if (_defaultClient) return _defaultClient;
268
+
269
+ const primary = _resolvePrimaryDefault();
270
+
271
+ // Opt-out: behave exactly as before (single provider, no fallback).
272
+ if (String(process.env.WALLE_DEFAULT_FALLBACK || '').trim() === '0') {
273
+ _defaultClient = primary.client;
274
+ return _defaultClient;
275
+ }
276
+
277
+ // Wrap the default in a resilient chain: user default → other set-up providers
278
+ // → installed coding-agent CLIs. Any failure here falls back to the bare primary
279
+ // client so fallback wiring can never break basic operation.
280
+ try {
281
+ const { buildDefaultProviderChain, makeResilientClient } = require('./default-fallback');
282
+ const brain = require('../brain');
283
+ let health = null;
284
+ try { health = require('./health').default; } catch {}
285
+ const chain = buildDefaultProviderChain({
286
+ brain,
287
+ createClient,
288
+ buildPrimary: () => primary,
289
+ resolveModelForType: (type) => {
290
+ try { return getDefaultModelForProvider(type); } catch { return undefined; }
291
+ },
292
+ env: process.env,
293
+ });
294
+ if (!chain.length || (chain.length === 1 && chain[0].id === primary.id)) {
295
+ // Nothing to fall back to — still add transient retries around the primary.
296
+ _defaultClient = makeResilientClient([primary], {
297
+ health,
298
+ onExhausted: ({ error }) => _notifyDefaultExhausted(error),
299
+ });
300
+ return _defaultClient;
301
+ }
302
+ _defaultClient = makeResilientClient(chain, {
303
+ health,
304
+ isDown: (id) => {
305
+ try { return health?.getProviderHealth?.(id)?.status === 'down'; } catch { return false; }
306
+ },
307
+ onFallback: ({ from, to, error }) => _notifyDefaultFallback(from, to, error),
308
+ onPrimaryOk: () => _clearDefaultRoutingNotice(),
309
+ onExhausted: ({ error }) => _notifyDefaultExhausted(error),
310
+ });
311
+ } catch (e) {
312
+ try { console.error('[llm] resilient default wiring failed, using bare primary:', e.message); } catch {}
313
+ _defaultClient = primary.client;
190
314
  }
191
315
  return _defaultClient;
192
316
  }
@@ -198,13 +322,87 @@ function getDefaultClient() {
198
322
  function _getProviderKeyFromDb(type) {
199
323
  try {
200
324
  const brain = require('../brain');
201
- const row = brain.getDb().prepare(
202
- 'SELECT api_key_encrypted FROM model_providers WHERE type = ? AND enabled = 1 AND api_key_encrypted IS NOT NULL ORDER BY updated_at DESC LIMIT 1'
203
- ).get(type);
325
+ const row = typeof brain.getPreferredModelProviderForType === 'function'
326
+ ? brain.getPreferredModelProviderForType(type)
327
+ : brain.getDb().prepare(
328
+ 'SELECT api_key_encrypted FROM model_providers WHERE type = ? AND enabled = 1 AND api_key_encrypted IS NOT NULL ORDER BY updated_at DESC LIMIT 1'
329
+ ).get(type);
204
330
  return row?.api_key_encrypted || null;
205
331
  } catch { return null; }
206
332
  }
207
333
 
334
+ function _parseCustomHeaders(value) {
335
+ if (!value) return undefined;
336
+ if (typeof value === 'object' && !Array.isArray(value)) return value;
337
+ if (typeof value !== 'string') return undefined;
338
+ try { return JSON.parse(value); } catch { return undefined; }
339
+ }
340
+
341
+ function _hasProviderConnectionConfig(config = {}) {
342
+ return !!(
343
+ config.apiKey
344
+ || config.baseUrl
345
+ || config.customHeaders
346
+ || config.authMode
347
+ || config.refreshToken
348
+ );
349
+ }
350
+
351
+ function _applyProviderEnvConfig(providerType, config) {
352
+ if (providerType === 'openai') {
353
+ config.apiKey = config.apiKey || process.env.OPENAI_API_KEY;
354
+ if (!config.baseUrl && process.env.OPENAI_BASE_URL) config.baseUrl = process.env.OPENAI_BASE_URL;
355
+ } else if (providerType === 'google') {
356
+ config.apiKey = config.apiKey || process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY;
357
+ if (!config.authMode && process.env.GOOGLE_AUTH_MODE === 'oauth') {
358
+ config.authMode = 'oauth';
359
+ config.refreshToken = config.refreshToken || process.env.GOOGLE_REFRESH_TOKEN;
360
+ }
361
+ } else if (providerType === 'ollama') {
362
+ if (!config.baseUrl && process.env.OLLAMA_BASE_URL) config.baseUrl = process.env.OLLAMA_BASE_URL;
363
+ } else if (providerType === 'mlx') {
364
+ if (!config.model && process.env.MLX_MODEL) config.model = process.env.MLX_MODEL;
365
+ } else if (providerType === 'deepseek') {
366
+ config.apiKey = config.apiKey || process.env.DEEPSEEK_API_KEY;
367
+ if (!config.baseUrl && process.env.DEEPSEEK_BASE_URL) config.baseUrl = process.env.DEEPSEEK_BASE_URL;
368
+ } else if (providerType === 'moonshot') {
369
+ config.apiKey = config.apiKey || process.env.MOONSHOT_API_KEY;
370
+ if (!config.baseUrl && process.env.MOONSHOT_BASE_URL) config.baseUrl = process.env.MOONSHOT_BASE_URL;
371
+ } else if (providerType === 'anthropic') {
372
+ config.apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN;
373
+ if (!config.baseUrl && process.env.ANTHROPIC_BASE_URL) config.baseUrl = process.env.ANTHROPIC_BASE_URL;
374
+ }
375
+ return config;
376
+ }
377
+
378
+ function getProviderRuntimeConfig(type, config = {}) {
379
+ providerRegistry.ensureBootstrapped();
380
+ const providerType = normalizeProviderType(type);
381
+ const supplied = { ...(config || {}) };
382
+ const base = _hasProviderConnectionConfig(supplied)
383
+ ? {}
384
+ : _getProviderConfigFromDb(providerType);
385
+ return _applyProviderEnvConfig(providerType, { ...base, ...supplied });
386
+ }
387
+
388
+ function _getProviderConfigFromDb(type) {
389
+ try {
390
+ const brain = require('../brain');
391
+ const row = typeof brain.getPreferredModelProviderForType === 'function'
392
+ ? brain.getPreferredModelProviderForType(type)
393
+ : null;
394
+ if (!row) return {};
395
+ const config = {};
396
+ if (row.api_key_encrypted) config.apiKey = row.api_key_encrypted;
397
+ if (row.base_url) config.baseUrl = row.base_url;
398
+ const customHeaders = _parseCustomHeaders(row.custom_headers);
399
+ if (customHeaders && Object.keys(customHeaders).length > 0) config.customHeaders = customHeaders;
400
+ return config;
401
+ } catch {
402
+ return {};
403
+ }
404
+ }
405
+
208
406
  /**
209
407
  * Clear the cached default client (for testing or env changes).
210
408
  */
@@ -215,14 +413,19 @@ function resetDefaultClient() {
215
413
  module.exports = {
216
414
  createClient,
217
415
  withStreamFallback,
416
+ withProviderMessageGuard,
218
417
  getDefaultClient,
219
418
  getDefaultProviderType,
220
419
  getDefaultAuthMethod,
221
420
  getDefaultModel,
222
421
  getDefaultModelForProvider,
422
+ getProviderRuntimeConfig,
223
423
  resolveCompatibleModel,
224
424
  resetDefaultClient,
225
425
  DEFAULT_TIER_MODELS,
426
+ // Exported for tests: the routing-notice fallback notifier (verifies it recovers
427
+ // the reason from the primary's stored health error on the steady-state skip path).
428
+ _notifyDefaultFallback,
226
429
  // Re-exported for callers that want to introspect the manifest
227
430
  // (chat router, setup page) without poking at the registry directly.
228
431
  detectProviderForModel: (model) => {