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
@@ -8,6 +8,7 @@ let _brainReloadTimer = null;
8
8
  let _providerStatus = null;
9
9
  let _providerPollTimer = null;
10
10
  let _cachedActiveModel = null; // { model, provider } from /api/setup/status
11
+ let _cachedSetupStatus = null;
11
12
  let _activeProviderIssue = null;
12
13
 
13
14
  const WalleCore = window.WalleCore || {};
@@ -107,6 +108,90 @@ WE._dismissProviderIssue = function() {
107
108
  renderChatUI();
108
109
  };
109
110
 
111
+ // --- Wall-E self-healing repair banner ---
112
+ // Service-level banner (Wall-E daemon is down), independent of the chat view.
113
+ // Driven by WebSocket 'walle-repair-needed' / 'walle-repair-cleared' events and
114
+ // restored on load via GET /api/walle/repair/status.
115
+ let _repairIncident = null;
116
+
117
+ WE.onRepairEvent = function(incident) {
118
+ _repairIncident = incident || null;
119
+ WE._renderRepairBanner();
120
+ };
121
+
122
+ WE._fetchRepairStatus = function() {
123
+ api('/api/walle/repair/status').then(function(resp) {
124
+ _repairIncident = (resp && resp.incident) || null;
125
+ WE._renderRepairBanner();
126
+ }).catch(function() {});
127
+ };
128
+
129
+ WE._renderRepairBanner = function() {
130
+ var el = document.getElementById('walle-repair-banner');
131
+ if (!el) return;
132
+ var inc = _repairIncident;
133
+ if (!inc || (inc.status !== 'detected' && inc.status !== 'repairing' && inc.status !== 'failed')) {
134
+ el.style.display = 'none';
135
+ el.innerHTML = '';
136
+ return;
137
+ }
138
+ var repairing = inc.status === 'repairing';
139
+ var failed = inc.status === 'failed';
140
+ var title = failed ? 'Wall-E auto-repair failed'
141
+ : repairing ? 'Wall-E auto-repair in progress'
142
+ : 'Wall-E is down and could not recover';
143
+ var tail = inc.crashLogTail ? '<details class="we-provider-issue-details"><summary>Crash log (tail)</summary><pre>' + esc(inc.crashLogTail) + '</pre></details>' : '';
144
+ var actions = '';
145
+ if (repairing) {
146
+ actions = inc.repairSessionId
147
+ ? '<button class="walle-btn primary" onclick="WE._openRepairSession(\'' + esc(inc.repairSessionId) + '\')">Open repair session</button>'
148
+ : '';
149
+ } else {
150
+ actions = '<button class="walle-btn primary" onclick="WE.startRepair()">Start auto-repair</button>'
151
+ + '<button class="walle-btn" onclick="WE.dismissRepair()">Dismiss</button>';
152
+ }
153
+ var html = '<div class="we-provider-issue ' + (failed ? 'error' : repairing ? 'warning' : 'error') + '" role="alert">';
154
+ html += '<div class="we-provider-issue-main">';
155
+ html += '<div class="we-provider-issue-title">' + esc(title) + '</div>';
156
+ html += '<div class="we-provider-issue-body">' + esc(inc.reason || '') + (inc.code ? ' (' + esc(inc.code) + ')' : '') + '</div>';
157
+ html += tail;
158
+ html += '</div>';
159
+ html += '<div class="we-provider-issue-actions">' + actions + '</div>';
160
+ html += '</div>';
161
+ el.innerHTML = html;
162
+ el.style.display = 'block';
163
+ };
164
+
165
+ WE.startRepair = function() {
166
+ apiPost('/api/walle/repair/start', {}).then(function(resp) {
167
+ if (resp && resp.ok) {
168
+ if (typeof showToast === 'function') showToast('Auto-repair started with ' + (resp.cli || 'a coding agent'), 'var(--accent)');
169
+ if (resp.sessionId) WE._openRepairSession(resp.sessionId);
170
+ } else {
171
+ var msg = (resp && resp.error) === 'no_cli_available'
172
+ ? 'No coding CLI (claude/codex/gemini) is available to run the repair.'
173
+ : 'Could not start auto-repair: ' + ((resp && (resp.message || resp.error)) || 'unknown');
174
+ if (typeof showToast === 'function') showToast(msg, '#e03131', 6000);
175
+ }
176
+ }).catch(function(err) {
177
+ if (typeof showToast === 'function') showToast('Repair request failed: ' + (err.message || 'unknown'), '#e03131');
178
+ });
179
+ };
180
+
181
+ WE.dismissRepair = function() {
182
+ apiPost('/api/walle/repair/dismiss', {}).then(function() {
183
+ _repairIncident = null;
184
+ WE._renderRepairBanner();
185
+ }).catch(function() {});
186
+ };
187
+
188
+ WE._openRepairSession = function(id) {
189
+ try {
190
+ if (typeof navTo === 'function') navTo('sessions');
191
+ if (typeof activateTab === 'function') activateTab(id);
192
+ } catch (e) {}
193
+ };
194
+
110
195
  // Render an assistant message that may begin with a `<think>...</think>`
111
196
  // chain-of-thought block (DeepSeek V4 deep-thinking, Anthropic extended
112
197
  // thinking, gemma4 native thinking). The thoughts render as a collapsible
@@ -149,6 +234,7 @@ function truncate(s, max) {
149
234
  WE.init = function() {
150
235
  try { var saved = localStorage.getItem('walle-view'); if (saved) currentView = saved; } catch(e) {}
151
236
  WE.showView(currentView);
237
+ WE._fetchRepairStatus();
152
238
  };
153
239
 
154
240
  WE.toggleMoreTabs = function() {
@@ -670,17 +756,18 @@ function renderQuestionsContent(pending, answered) {
670
756
  var body = document.getElementById('walle-body');
671
757
  if (!body) return;
672
758
 
759
+ // Digest-delivery panel (always shown). The CTM tab is the always-on surface; Slack DM
760
+ // and email are opt-in push channels toggled here.
761
+ var html = '<div id="walle-digest-settings" class="walle-digest-settings"></div>';
762
+
673
763
  if (pending.length === 0 && answered.length === 0) {
674
- body.textContent = '';
675
- var div = document.createElement('div');
676
- div.className = 'walle-empty';
677
- div.textContent = 'No questions yet.';
678
- body.appendChild(div);
764
+ html += '<div class="walle-empty">No questions right now.</div>';
765
+ safeSetHtml(body, html);
766
+ WE._renderDigestSettings();
679
767
  return;
680
768
  }
681
769
 
682
770
  // All user content is sanitized through esc()
683
- var html = '';
684
771
 
685
772
  if (pending.length > 0) {
686
773
  html += '<div class="walle-section-title">Pending Questions (' + esc(String(pending.length)) + ')</div>';
@@ -711,8 +798,9 @@ function renderQuestionsContent(pending, answered) {
711
798
  html += '</div>';
712
799
  } else {
713
800
  html += '<div class="walle-question-answer">';
714
- html += '<input class="walle-question-input" id="walle-qa-' + qId + '" placeholder="Type your answer..." autocomplete="off">';
801
+ html += '<input class="walle-question-input" id="walle-qa-' + qId + '" placeholder="Type your answer..." autocomplete="off" onkeydown="if(event.key===\'Enter\'){WE._answerQuestion(\'' + qId + '\')}">';
715
802
  html += '<button class="walle-btn primary" onclick="WE._answerQuestion(\'' + qId + '\')">Answer</button>';
803
+ html += '<button class="walle-btn" onclick="WE._answerQuestion(\'' + qId + '\',\'dismissed\')">Dismiss</button>';
716
804
  html += '</div>';
717
805
  }
718
806
  html += '</div>';
@@ -735,8 +823,47 @@ function renderQuestionsContent(pending, answered) {
735
823
  }
736
824
 
737
825
  safeSetHtml(body, html);
826
+ WE._renderDigestSettings();
738
827
  }
739
828
 
829
+ // Digest-delivery settings panel. CTM tab is always on; Slack/email are opt-in.
830
+ WE._renderDigestSettings = function() {
831
+ var el = document.getElementById('walle-digest-settings');
832
+ if (!el) return;
833
+ api('/questions/digest/settings').then(function(resp) {
834
+ var s = (resp && resp.settings) || {};
835
+ var html = '<div class="walle-digest-row">'
836
+ + '<span class="walle-digest-label">Question delivery</span>'
837
+ + '<span class="walle-digest-chip on" title="Always on">CTM tab ✓</span>'
838
+ + '<label class="walle-digest-chip"><input type="checkbox" id="dg-slack" ' + (s.slack_enabled ? 'checked' : '') + '> Slack DM</label>'
839
+ + '<label class="walle-digest-chip"><input type="checkbox" id="dg-email" ' + (s.email_enabled ? 'checked' : '') + '> Email</label>'
840
+ + '<button class="walle-btn" onclick="WE._saveDigestSettings()">Save</button>'
841
+ + '</div>'
842
+ + '<div class="walle-digest-row walle-digest-targets">'
843
+ + '<input class="walle-question-input" id="dg-slack-ch" placeholder="Slack channel/DM id (e.g. D0123)" value="' + esc(s.slack_channel || '') + '">'
844
+ + '<input class="walle-question-input" id="dg-email-to" placeholder="Email address" value="' + esc(s.email_to || '') + '">'
845
+ + '</div>';
846
+ safeSetHtml(el, html);
847
+ }).catch(function() {
848
+ safeSetHtml(el, '');
849
+ });
850
+ };
851
+
852
+ WE._saveDigestSettings = function() {
853
+ var get = function(id) { var e = document.getElementById(id); return e; };
854
+ var payload = {
855
+ slack_enabled: !!(get('dg-slack') && get('dg-slack').checked),
856
+ email_enabled: !!(get('dg-email') && get('dg-email').checked),
857
+ slack_channel: (get('dg-slack-ch') && get('dg-slack-ch').value.trim()) || '',
858
+ email_to: (get('dg-email-to') && get('dg-email-to').value.trim()) || ''
859
+ };
860
+ apiPost('/questions/digest/settings', payload).then(function() {
861
+ if (typeof showToast === 'function') showToast('Digest delivery saved', 'var(--accent)');
862
+ }).catch(function(err) {
863
+ if (typeof showToast === 'function') showToast('Error: ' + (err.message || 'unknown'), '#f00');
864
+ });
865
+ };
866
+
740
867
  WE._answerQuestion = function(id, directAnswer) {
741
868
  var answer = directAnswer;
742
869
  if (!answer) {
@@ -744,11 +871,16 @@ WE._answerQuestion = function(id, directAnswer) {
744
871
  if (!input || !input.value.trim()) return;
745
872
  answer = input.value.trim();
746
873
  }
874
+ // resolution_type must be one of brain.answerQuestion's accepted values
875
+ // (answered | inferred | dismissed | expired). The Dismiss button passes
876
+ // directAnswer='dismissed'; a typed/explicit answer resolves as 'answered'.
877
+ var resolutionType = directAnswer === 'dismissed' ? 'dismissed' : 'answered';
878
+ var isDismiss = resolutionType === 'dismissed';
747
879
  apiPost('/questions/' + id + '/answer', {
748
880
  answer: answer,
749
- resolution_type: directAnswer ? 'human' : 'answered'
881
+ resolution_type: resolutionType
750
882
  }).then(function() {
751
- if (typeof showToast === 'function') showToast('Answer submitted', 'var(--accent)');
883
+ if (typeof showToast === 'function') showToast(isDismiss ? 'Question dismissed' : 'Answer submitted', 'var(--accent)');
752
884
  WE.renderQuestions();
753
885
  }).catch(function(err) {
754
886
  if (typeof showToast === 'function') showToast('Error: ' + (err.message || 'unknown'), '#f00');
@@ -1927,6 +2059,7 @@ WE.renderChat = function() {
1927
2059
  // Fetch active model for badge (once, then cached)
1928
2060
  if (!_cachedActiveModel) {
1929
2061
  fetch('/api/setup/status').then(function(r) { return r.json(); }).then(function(d) {
2062
+ _cachedSetupStatus = d || null;
1930
2063
  if (d.walle_model || d.walle_provider) {
1931
2064
  _cachedActiveModel = { model: d.walle_model || '', provider: d.walle_provider || '' };
1932
2065
  var badge = document.querySelector('.we-model-badge');
@@ -6464,22 +6597,15 @@ checkProviderStatus();
6464
6597
 
6465
6598
  var _alertsPollTimer = null;
6466
6599
  var _serviceAlerts = [];
6600
+ var _serviceHealth = null;
6467
6601
  var _updatePromptShownVersions = {};
6468
6602
 
6469
6603
  function checkServiceAlerts() {
6470
6604
  api('/alerts').then(function(d) {
6471
6605
  var alerts = d.alerts || [];
6472
6606
  _serviceAlerts = alerts;
6473
- var providerIssue = null;
6474
- for (var i = 0; i < alerts.length; i++) {
6475
- var issue = _normalizeProviderIssue(alerts[i]);
6476
- if (issue) providerIssue = issue;
6477
- }
6478
- if (providerIssue) {
6479
- _activeProviderIssue = providerIssue;
6480
- if (currentView === 'chat') renderChatUI();
6481
- }
6482
- renderServiceAlerts(alerts);
6607
+ _serviceHealth = d.summary || buildClientServiceHealth(alerts);
6608
+ renderServiceAlerts(alerts, _serviceHealth);
6483
6609
  maybeShowUpdateWizard(alerts);
6484
6610
  clearTimeout(_alertsPollTimer);
6485
6611
  _alertsPollTimer = setTimeout(checkServiceAlerts, 60000);
@@ -6489,6 +6615,131 @@ function checkServiceAlerts() {
6489
6615
  });
6490
6616
  }
6491
6617
 
6618
+ function alertCreatedAtMs(alert) {
6619
+ var t = Date.parse(alert && alert.created_at || '');
6620
+ return Number.isFinite(t) ? t : 0;
6621
+ }
6622
+
6623
+ function serviceAlertSkillName(alert) {
6624
+ if (!alert) return '';
6625
+ if (alert.skill) return String(alert.skill);
6626
+ var service = String(alert.service || '');
6627
+ if (service && service !== 'ai_provider' && service !== 'system') return service;
6628
+ var msg = String(alert.message || '');
6629
+ var quoted = msg.match(/Skill\s+"([^"]+)"/i);
6630
+ if (quoted) return quoted[1];
6631
+ var named = msg.match(/Skill\s+([A-Za-z0-9_.-]+)/i);
6632
+ return named ? named[1] : '';
6633
+ }
6634
+
6635
+ function serviceAlertProviderIssueType(issue) {
6636
+ return String(issue && issue.type || '').toLowerCase();
6637
+ }
6638
+
6639
+ function serviceAlertIsStickyProviderIssue(issue) {
6640
+ var text = [
6641
+ serviceAlertProviderIssueType(issue),
6642
+ issue && issue.title,
6643
+ issue && issue.message,
6644
+ ].filter(Boolean).join(' ').toLowerCase();
6645
+ return /auth|quota|billing|credit|insufficient|invalid|forbidden|unauthorized|permission/.test(text);
6646
+ }
6647
+
6648
+ function serviceAlertMatchesActiveProvider(issue) {
6649
+ if (!issue) return false;
6650
+ var active = _cachedActiveModel || {};
6651
+ var activeProvider = String(active.provider || '').toLowerCase();
6652
+ var activeModel = String(active.model || '').toLowerCase();
6653
+ var provider = String(issue.provider || '').toLowerCase();
6654
+ var model = String(issue.model || '').toLowerCase();
6655
+ if (activeProvider && provider && activeProvider === provider) return true;
6656
+ if (activeModel && model && activeModel === model) return true;
6657
+ return !activeProvider && !activeModel;
6658
+ }
6659
+
6660
+ function serviceAlertIsCurrentProviderIssue(issue) {
6661
+ if (!serviceAlertMatchesActiveProvider(issue)) return false;
6662
+ if (serviceAlertIsStickyProviderIssue(issue)) return true;
6663
+ var created = Date.parse(issue.createdAt || issue.created_at || '');
6664
+ if (!Number.isFinite(created)) return true;
6665
+ return Date.now() - created <= 6 * 60 * 60 * 1000;
6666
+ }
6667
+
6668
+ function publicServiceAlert(alert) {
6669
+ return {
6670
+ id: alert.id || '',
6671
+ service: alert.service || '',
6672
+ type: alert.type || '',
6673
+ title: alert.title || '',
6674
+ message: alert.message || '',
6675
+ severity: alert.severity || '',
6676
+ action: alert.action || '',
6677
+ action_label: alert.action_label || '',
6678
+ action_url: alert.action_url || '',
6679
+ created_at: alert.created_at || '',
6680
+ skill: serviceAlertSkillName(alert),
6681
+ };
6682
+ }
6683
+
6684
+ function summarizeProviderIssueForHealth(issue) {
6685
+ return {
6686
+ id: issue.id || '',
6687
+ type: issue.type || '',
6688
+ severity: issue.severity || 'error',
6689
+ title: issue.title || 'AI provider issue',
6690
+ message: issue.message || '',
6691
+ provider: issue.provider || '',
6692
+ model: issue.model || '',
6693
+ status: issue.status || '',
6694
+ action_url: issue.actionUrl || issue.action_url || '/setup.html',
6695
+ action_label: issue.actionLabel || issue.action_label || 'Open Setup',
6696
+ created_at: issue.createdAt || issue.created_at || '',
6697
+ };
6698
+ }
6699
+
6700
+ function buildClientServiceHealth(alerts) {
6701
+ alerts = Array.isArray(alerts) ? alerts : [];
6702
+ var providerIssues = alerts.map(_normalizeProviderIssue).filter(Boolean).sort(function(a, b) {
6703
+ return Date.parse(b.createdAt || b.created_at || '') - Date.parse(a.createdAt || a.created_at || '');
6704
+ });
6705
+ var currentIssue = null;
6706
+ for (var i = 0; i < providerIssues.length; i++) {
6707
+ if (serviceAlertIsCurrentProviderIssue(providerIssues[i])) {
6708
+ currentIssue = providerIssues[i];
6709
+ break;
6710
+ }
6711
+ }
6712
+ var disabled = alerts.filter(function(a) { return String(a && a.type || '').toLowerCase() === 'skill_disabled'; }).map(publicServiceAlert);
6713
+ var integrations = alerts.filter(function(a) {
6714
+ return !_normalizeProviderIssue(a) && String(a && a.type || '').toLowerCase() !== 'skill_disabled' && isSessionsIntegrationAlert(a);
6715
+ }).map(publicServiceAlert);
6716
+ var systems = alerts.filter(function(a) {
6717
+ return !_normalizeProviderIssue(a) && String(a && a.type || '').toLowerCase() !== 'skill_disabled' && !isSessionsIntegrationAlert(a);
6718
+ }).map(publicServiceAlert);
6719
+ var history = providerIssues.filter(function(issue) {
6720
+ return !currentIssue || issue.id !== currentIssue.id;
6721
+ }).map(summarizeProviderIssueForHealth);
6722
+ var level = currentIssue ? (currentIssue.severity === 'warning' ? 'warning' : 'error') : ((disabled.length || integrations.length) ? 'warning' : ((history.length || systems.length) ? 'info' : 'ok'));
6723
+ return {
6724
+ level: level,
6725
+ title: currentIssue ? currentIssue.title : (level === 'ok' ? 'Wall-E services healthy' : (level === 'info' ? 'Older service history' : 'Background services need review')),
6726
+ message: currentIssue ? currentIssue.message : (level === 'ok' ? 'No current service blocker.' : 'Review provider history, disabled skills, or integrations below.'),
6727
+ current_issue: currentIssue ? summarizeProviderIssueForHealth(currentIssue) : null,
6728
+ disabled_skills: disabled,
6729
+ integration_alerts: integrations,
6730
+ provider_history: history,
6731
+ system_alerts: systems,
6732
+ counts: {
6733
+ total: alerts.length,
6734
+ current: currentIssue ? 1 : 0,
6735
+ disabled_skills: disabled.length,
6736
+ integration: integrations.length,
6737
+ provider_history: history.length,
6738
+ system: systems.length,
6739
+ },
6740
+ };
6741
+ }
6742
+
6492
6743
  function serviceAlertPresentation(alert) {
6493
6744
  var providerIssue = _normalizeProviderIssue(alert);
6494
6745
  var kind = providerIssue ? 'provider' : (alert.type === 'auth_expired' ? 'error' : alert.type === 'update_available' ? 'info' : 'warning');
@@ -6507,7 +6758,14 @@ function safeServiceAlertId(alert) {
6507
6758
  function serviceAlertActionHtml(alert, safeId) {
6508
6759
  var actionBtn = '';
6509
6760
  var actionLabel = esc(alert.action_label || 'Fix');
6510
- if (alert.action === 'repair_slack_owner') {
6761
+ var providerIssue = _normalizeProviderIssue(alert);
6762
+ if (providerIssue) {
6763
+ actionBtn = ' <button class="we-service-alert-action" type="button" onclick="WE._testProviderFromAlert(\'' + safeId + '\')">Test</button>'
6764
+ + ' <button class="we-service-alert-action" type="button" onclick="navTo(\'setup\')">Setup</button>';
6765
+ } else if (String(alert.type || '').toLowerCase() === 'skill_disabled') {
6766
+ actionBtn = ' <button class="we-service-alert-action" type="button" onclick="WE._reviewSkillAlert(\'' + safeId + '\')">Review</button>'
6767
+ + ' <button class="we-service-alert-action" type="button" onclick="WE._enableSkillFromAlert(\'' + safeId + '\')">Re-enable</button>';
6768
+ } else if (alert.action === 'repair_slack_owner') {
6511
6769
  var actionName = esc(alert.action || 'custom').replace(/'/g, '&#39;');
6512
6770
  actionBtn = ' <button class="we-service-alert-action" type="button" onclick="WE._runAlertAction(\'' + safeId + '\', \'' + actionName + '\')">' + actionLabel + '</button>';
6513
6771
  } else if (alert.action === 'gws_reauth') {
@@ -6530,6 +6788,96 @@ function serviceAlertItemHtml(alert) {
6530
6788
  + dismissBtn + '</div>';
6531
6789
  }
6532
6790
 
6791
+ function serviceAlertById(alertId) {
6792
+ for (var i = 0; i < _serviceAlerts.length; i++) {
6793
+ if (String(_serviceAlerts[i].id) === String(alertId)) return _serviceAlerts[i];
6794
+ }
6795
+ return null;
6796
+ }
6797
+
6798
+ function serviceAlertSummaryMeta(health) {
6799
+ var counts = (health && health.counts) || {};
6800
+ var parts = [];
6801
+ if (health && health.current_issue) parts.push('current blocker');
6802
+ if (counts.disabled_skills) parts.push(counts.disabled_skills + ' disabled skill' + (counts.disabled_skills === 1 ? '' : 's'));
6803
+ if (counts.integration) parts.push(counts.integration + ' integration');
6804
+ if (counts.provider_history) parts.push(counts.provider_history + ' older provider');
6805
+ if (counts.system) parts.push(counts.system + ' system');
6806
+ return parts.length ? parts.join(' · ') : 'No alerts';
6807
+ }
6808
+
6809
+ function serviceAlertDisplayTime(value) {
6810
+ var t = Date.parse(value || '');
6811
+ if (!Number.isFinite(t)) return '';
6812
+ try {
6813
+ return new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }).format(new Date(t));
6814
+ } catch {
6815
+ return new Date(t).toLocaleString();
6816
+ }
6817
+ }
6818
+
6819
+ function renderHealthIssue(issue) {
6820
+ if (!issue) return '';
6821
+ var safeId = esc(issue.id || '').replace(/'/g, '&#39;');
6822
+ var provider = [issue.provider, issue.model].filter(Boolean).join(' / ');
6823
+ var when = serviceAlertDisplayTime(issue.created_at);
6824
+ return '<div class="we-health-current">'
6825
+ + '<div class="we-health-current-copy">'
6826
+ + '<div class="we-health-current-title">' + esc(issue.title || 'Current provider issue') + '</div>'
6827
+ + '<div class="we-health-current-body">' + esc(issue.message || '') + '</div>'
6828
+ + '<div class="we-health-current-meta">' + esc([provider, when].filter(Boolean).join(' · ')) + '</div>'
6829
+ + '</div>'
6830
+ + '<div class="we-health-current-actions">'
6831
+ + '<button class="walle-btn primary" type="button" onclick="WE._testProviderFromAlert(\'' + safeId + '\')">Test provider</button>'
6832
+ + '<button class="walle-btn" type="button" onclick="navTo(\'setup\')">Open Setup</button>'
6833
+ + '<button class="we-service-alert-dismiss" type="button" onclick="WE._dismissAlert(\'' + safeId + '\')" title="Dismiss">&times;</button>'
6834
+ + '</div>'
6835
+ + '</div>';
6836
+ }
6837
+
6838
+ function renderHealthGroup(title, alerts, opts) {
6839
+ opts = opts || {};
6840
+ if (!alerts || !alerts.length) return '';
6841
+ var open = opts.open ? ' open' : '';
6842
+ var rows = alerts.map(function(alert) {
6843
+ var source = serviceAlertById(alert.id) || alert;
6844
+ return serviceAlertItemHtml(source);
6845
+ }).join('');
6846
+ return '<details class="we-health-group"' + open + '>'
6847
+ + '<summary><span>' + esc(title) + '</span><strong>' + alerts.length + '</strong></summary>'
6848
+ + '<div class="we-health-group-body">' + rows + '</div>'
6849
+ + '</details>';
6850
+ }
6851
+
6852
+ function renderServiceHealthPanel(alerts, health) {
6853
+ health = health || buildClientServiceHealth(alerts);
6854
+ if ((!alerts || !alerts.length) && (!health || health.level === 'ok')) return '';
6855
+ var level = health.level || 'info';
6856
+ var html = '<div id="walle-service-alerts" class="we-service-alerts we-health-card ' + esc(level) + '">';
6857
+ html += '<div class="we-health-header">';
6858
+ html += '<div class="we-health-status-dot" aria-hidden="true"></div>';
6859
+ html += '<div class="we-health-title-block"><div class="we-service-alerts-title">Service Health</div>'
6860
+ + '<div class="we-health-title">' + esc(health.title || 'Wall-E services') + '</div>'
6861
+ + '<div class="we-health-message">' + esc(health.message || '') + '</div></div>';
6862
+ html += '<div class="we-health-meta">' + esc(serviceAlertSummaryMeta(health)) + '</div>';
6863
+ html += '</div>';
6864
+ if (health.current_issue) html += renderHealthIssue(health.current_issue);
6865
+ if (health.integration_alerts && health.integration_alerts.length) {
6866
+ html += renderHealthGroup('Integrations', health.integration_alerts, { open: !health.current_issue });
6867
+ }
6868
+ if (health.disabled_skills && health.disabled_skills.length) {
6869
+ html += renderHealthGroup('Disabled background skills', health.disabled_skills, { open: !health.current_issue && !(health.integration_alerts || []).length });
6870
+ }
6871
+ if (health.provider_history && health.provider_history.length) {
6872
+ html += renderHealthGroup('Older provider history', health.provider_history, { open: false });
6873
+ }
6874
+ if (health.system_alerts && health.system_alerts.length) {
6875
+ html += renderHealthGroup('System alerts', health.system_alerts, { open: !health.current_issue && !(health.integration_alerts || []).length && !(health.disabled_skills || []).length });
6876
+ }
6877
+ html += '</div>';
6878
+ return html;
6879
+ }
6880
+
6533
6881
  function serviceAlertSearchText(alert) {
6534
6882
  return [
6535
6883
  alert && alert.id,
@@ -6580,18 +6928,14 @@ function renderStandupServiceAlerts(alerts) {
6580
6928
  + integrationAlerts.map(serviceAlertItemHtml).join('');
6581
6929
  }
6582
6930
 
6583
- function renderServiceAlerts(alerts) {
6931
+ function renderServiceAlerts(alerts, health) {
6584
6932
  var existing = document.getElementById('walle-service-alerts');
6585
6933
  renderStandupServiceAlerts(alerts);
6586
- if (!alerts || alerts.length === 0) {
6934
+ var html = renderServiceHealthPanel(alerts, health);
6935
+ if (!html) {
6587
6936
  if (existing) existing.remove();
6588
6937
  return;
6589
6938
  }
6590
- var items = alerts.map(serviceAlertItemHtml).join('');
6591
-
6592
- var html = '<div id="walle-service-alerts" class="we-service-alerts">'
6593
- + '<div class="we-service-alerts-title">Service Alerts</div>' + items + '</div>';
6594
-
6595
6939
  if (existing) {
6596
6940
  existing.outerHTML = html;
6597
6941
  } else {
@@ -6730,6 +7074,89 @@ WE._runAlertAction = function(alertId, actionName) {
6730
7074
  });
6731
7075
  };
6732
7076
 
7077
+ function providerForAlert(alert) {
7078
+ var issue = _normalizeProviderIssue(alert) || alert || {};
7079
+ return String(issue.provider || (_cachedActiveModel && _cachedActiveModel.provider) || '').trim();
7080
+ }
7081
+
7082
+ function providerLabelForTest(provider) {
7083
+ if (!provider) return 'provider';
7084
+ if (provider === 'deepseek') return 'DeepSeek';
7085
+ if (provider === 'openai') return 'OpenAI';
7086
+ if (provider === 'moonshot') return 'Moonshot / Kimi';
7087
+ return provider.charAt(0).toUpperCase() + provider.slice(1);
7088
+ }
7089
+
7090
+ function testSetupProvider(provider, alertId) {
7091
+ provider = String(provider || '').trim();
7092
+ if (!provider) {
7093
+ if (typeof showToast === 'function') showToast('No active provider to test', 'var(--yellow, #e0af68)', 2600);
7094
+ return;
7095
+ }
7096
+ var params = new URLSearchParams({ provider: provider });
7097
+ if (_cachedSetupStatus && _cachedSetupStatus.auth_method) params.set('auth_method', _cachedSetupStatus.auth_method);
7098
+ if (typeof showToast === 'function') showToast('Testing ' + providerLabelForTest(provider) + '...', 'var(--accent)', 1600);
7099
+ fetch('/api/setup/test-key?' + params.toString(), { cache: 'no-store' })
7100
+ .then(function(r) { return r.json().then(function(d) { return { ok: r.ok, data: d }; }); })
7101
+ .then(function(result) {
7102
+ var data = result.data || {};
7103
+ if (result.ok && data.ok) {
7104
+ if (typeof showToast === 'function') showToast(providerLabelForTest(provider) + ' is reachable', 'var(--green, #9ece6a)', 2600);
7105
+ if (alertId) WE._dismissAlert(alertId);
7106
+ else checkServiceAlerts();
7107
+ return;
7108
+ }
7109
+ var msg = data.error || 'Provider test failed';
7110
+ if (typeof showToast === 'function') showToast(msg, 'var(--red, #f7768e)', 4200);
7111
+ })
7112
+ .catch(function(err) {
7113
+ if (typeof showToast === 'function') showToast(err.message || 'Provider test failed', 'var(--red, #f7768e)', 4200);
7114
+ });
7115
+ }
7116
+
7117
+ WE._testProviderFromAlert = function(alertId) {
7118
+ var alert = serviceAlertById(alertId);
7119
+ if (!alert && _serviceHealth && _serviceHealth.current_issue && String(_serviceHealth.current_issue.id) === String(alertId)) {
7120
+ alert = _serviceHealth.current_issue;
7121
+ }
7122
+ testSetupProvider(providerForAlert(alert), alertId);
7123
+ };
7124
+
7125
+ WE._reviewSkillAlert = function(alertId) {
7126
+ var alert = serviceAlertById(alertId);
7127
+ var name = serviceAlertSkillName(alert);
7128
+ _skillsFilter.search = name || '';
7129
+ _skillsFilter.status = 'All';
7130
+ _skillsFilter.category = 'All';
7131
+ WE.showView('skills');
7132
+ };
7133
+
7134
+ WE._enableSkillFromAlert = function(alertId) {
7135
+ var alert = serviceAlertById(alertId);
7136
+ var name = serviceAlertSkillName(alert);
7137
+ if (!name) {
7138
+ if (typeof showToast === 'function') showToast('Could not identify the disabled skill', 'var(--red, #f7768e)', 3000);
7139
+ return;
7140
+ }
7141
+ api('/skills?enabled=0').then(function(resp) {
7142
+ var skills = resp.data || [];
7143
+ var match = null;
7144
+ for (var i = 0; i < skills.length; i++) {
7145
+ if (String(skills[i].name || '').toLowerCase() === name.toLowerCase()) {
7146
+ match = skills[i];
7147
+ break;
7148
+ }
7149
+ }
7150
+ if (!match) throw new Error('Skill is not disabled or was not found: ' + name);
7151
+ return apiPut('/skills/' + encodeURIComponent(match.id), { enabled: 1 });
7152
+ }).then(function() {
7153
+ if (typeof showToast === 'function') showToast('Re-enabled ' + name, 'var(--green, #9ece6a)', 2600);
7154
+ WE._dismissAlert(alertId);
7155
+ }).catch(function(err) {
7156
+ if (typeof showToast === 'function') showToast(err.message || 'Could not re-enable skill', 'var(--red, #f7768e)', 4200);
7157
+ });
7158
+ };
7159
+
6733
7160
  function findServiceAlert(alertId) {
6734
7161
  for (var i = 0; i < _serviceAlerts.length; i++) {
6735
7162
  if (String(_serviceAlerts[i].id) === String(alertId)) return _serviceAlerts[i];
@@ -8829,7 +9256,7 @@ WE.renderListening = function() {
8829
9256
  if (!list) return;
8830
9257
  var recordings = (result && result.data) || [];
8831
9258
  if (recordings.length === 0) {
8832
- safeSetHtml(list, '<div class="li-empty">No recordings yet. Click "New Recording" or press Cmd+Shift+R to start.</div>');
9259
+ safeSetHtml(list, '<div class="li-empty">No recordings yet. Click "New Recording" or press Ctrl+Shift+R to start.</div>');
8833
9260
  return;
8834
9261
  }
8835
9262
  var h = '';