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
@@ -13,6 +13,55 @@ const { ArtifactStore } = require('./artifact-store');
13
13
  const { normalizeResponse, transformRequest, providerId } = require('./provider-transform');
14
14
  const { Confidence, EventName, FailureClass, Provenance, createLaneEvent } = require('./lane-events');
15
15
  const { reviewExternalActionGateway } = require('../external-action-gateway');
16
+ const { isSuccessfulVerificationToolCall, normalizeToolCallEvidence } = require('./acceptance-contract');
17
+ const { RuntimeToolExecutor } = require('../runtime/tool-executor');
18
+ const { buildRuntimeToolResultEnvelope } = require('../runtime/tool-result-envelope');
19
+ const { attachProjectionFlags } = require('../runtime/transcript-projection');
20
+ const { isRetryable, parseRetryDelay } = require('../llm/retry');
21
+ const { decorateProviderError } = require('../llm/provider-error');
22
+
23
+ // Transient provider failures (e.g. a "fetch failed" network blip) shouldn't kill
24
+ // a whole coding turn. We retry at stream *establishment* only — see
25
+ // streamWithEstablishmentRetry — which covers both non-streaming providers
26
+ // (streamFromChat) and any native chatStream provider, without risking duplicated
27
+ // output from a mid-stream retry.
28
+ const CODING_PROVIDER_RETRIES = 2;
29
+
30
+ /**
31
+ * Retry a stream's establishment (the first event) on transient errors, then
32
+ * drain the rest without retry. A failure before the first event is yielded is a
33
+ * connection-level failure and is safe to retry; a failure after output has begun
34
+ * is not (retrying would duplicate already-emitted deltas).
35
+ *
36
+ * @param {() => AsyncIterable} makeStream Creates a fresh stream per attempt.
37
+ * @param {{ signal?: AbortSignal, retries?: number }} [opts]
38
+ */
39
+ async function* streamWithEstablishmentRetry(makeStream, { signal, retries = CODING_PROVIDER_RETRIES } = {}) {
40
+ let attempt = 0;
41
+ for (;;) {
42
+ const iterator = makeStream()[Symbol.asyncIterator]();
43
+ let first;
44
+ try {
45
+ first = await iterator.next();
46
+ } catch (err) {
47
+ const status = err?.status || err?.code || 0;
48
+ if (!signal?.aborted && attempt < retries && isRetryable(status, err?.message || '')) {
49
+ attempt += 1;
50
+ await new Promise((resolve) => setTimeout(resolve, parseRetryDelay(null, attempt - 1)));
51
+ continue;
52
+ }
53
+ throw err;
54
+ }
55
+ if (first.done) return;
56
+ yield first.value;
57
+ for (;;) {
58
+ // Mid-stream: never retry — propagate so the caller fails the turn cleanly.
59
+ const next = await iterator.next();
60
+ if (next.done) return;
61
+ yield next.value;
62
+ }
63
+ }
64
+ }
16
65
 
17
66
  async function* streamFromChat(provider, request) {
18
67
  const response = normalizeResponse(recoverAllowedTextToolCalls(await provider.chat(request), request.tools), {
@@ -72,9 +121,10 @@ class StreamProcessor extends EventEmitter {
72
121
  temperature,
73
122
  signal,
74
123
  });
75
- const stream = typeof this.provider.chatStream === 'function'
76
- ? this.provider.chatStream(request)
77
- : streamFromChat(this.provider, request);
124
+ const makeStream = typeof this.provider.chatStream === 'function'
125
+ ? () => this.provider.chatStream(request)
126
+ : () => streamFromChat(this.provider, request);
127
+ const stream = streamWithEstablishmentRetry(makeStream, { signal });
78
128
 
79
129
  const assistantMessageId = newId('assistant');
80
130
  const threadId = String(requestOptions.threadId || sessionId);
@@ -153,9 +203,25 @@ class StreamProcessor extends EventEmitter {
153
203
  await this._handleEvent(event, state, { sessionId, cwd, tools });
154
204
  }
155
205
  if (state.toolCalls.length > 0 && this.toolExecutor) {
156
- for (const call of state.toolCalls) {
157
- await this._runTool(call, state, { sessionId, cwd });
158
- }
206
+ const executor = new RuntimeToolExecutor({
207
+ toolSpecs: tools,
208
+ executeToolCall: async (call) => this._runTool(call, state, { sessionId, cwd }),
209
+ runtimeProfile: {
210
+ profileId: 'coding',
211
+ permissionProfile: 'coding-workspace',
212
+ persistenceProfile: 'jsonl-transcript',
213
+ outputContract: 'coding-acceptance',
214
+ toolsets: ['coding', 'memory', 'mcp', 'skills', 'local'],
215
+ },
216
+ now: this.now,
217
+ });
218
+ await executor.run(state.toolCalls, {
219
+ sessionId,
220
+ cwd,
221
+ provider: state.provider,
222
+ model: state.model,
223
+ });
224
+ orderToolResultsByCalls(state, state.toolCalls);
159
225
  }
160
226
  if (this.snapshotService?.captureStepFinish) {
161
227
  const snapshot = await this.snapshotService.captureStepFinish({ sessionId, cwd, messageId: assistantMessageId });
@@ -164,8 +230,19 @@ class StreamProcessor extends EventEmitter {
164
230
  state.status = 'finished';
165
231
  } catch (err) {
166
232
  state.status = 'error';
167
- state.errors.push(err.message);
168
- await this._record(sessionId, cwd, 'error', { message: err.message });
233
+ // Classify the raw provider error (e.g. "fetch failed") into a friendly,
234
+ // actionable message parity with the chat path. The raw message is kept
235
+ // as rawError for debugging; providerError carries the rich block + action.
236
+ const { providerError } = decorateProviderError(err, { provider: state.provider, model: state.model });
237
+ const friendly = providerError.userMessage || err.message;
238
+ const rawError = err.message;
239
+ // Keep the RAW message in state.errors: the orchestrator pattern-matches it
240
+ // (isProviderFailureRecoverableByCli) to decide CLI fallback. Surface the
241
+ // friendly, classified text on the user-facing record/lane/emit, and expose
242
+ // providerError on the returned turn so the orchestrator can render it too.
243
+ state.errors.push(rawError);
244
+ state.providerError = providerError;
245
+ await this._record(sessionId, cwd, 'error', { message: friendly, providerError, rawError });
169
246
  await this._laneEvent({
170
247
  name: EventName.SESSION_FAILED,
171
248
  sessionId,
@@ -174,11 +251,11 @@ class StreamProcessor extends EventEmitter {
174
251
  model: state.model,
175
252
  runId: assistantMessageId,
176
253
  failureClass: FailureClass.PROVIDER,
177
- reason: err.message,
254
+ reason: friendly,
178
255
  confidence: Confidence.HIGH,
179
- data: { error: err.message },
256
+ data: { error: friendly, providerError, rawError },
180
257
  });
181
- this._emit({ type: 'error', sessionId, messageId: assistantMessageId, error: err.message });
258
+ this._emit({ type: 'error', sessionId, messageId: assistantMessageId, error: friendly, providerError });
182
259
  } finally {
183
260
  await this._runtimeItem(sessionId, cwd, {
184
261
  threadId,
@@ -336,6 +413,7 @@ class StreamProcessor extends EventEmitter {
336
413
  }
337
414
 
338
415
  async _runTool(call, state, { sessionId, cwd }) {
416
+ const toolStartedAt = Date.now();
339
417
  try {
340
418
  await this._runtimeItem(sessionId, cwd, {
341
419
  threadId: state.threadId,
@@ -346,13 +424,30 @@ class StreamProcessor extends EventEmitter {
346
424
  name: call.name,
347
425
  data: { input: call.input },
348
426
  });
427
+ this._emit({
428
+ type: 'tool_call',
429
+ id: call.id,
430
+ toolCallId: call.id,
431
+ tool: call.name,
432
+ name: call.name,
433
+ summary: `Running ${call.name}`,
434
+ input: call.input,
435
+ });
349
436
  const gatewayReview = reviewExternalActionGateway({
350
437
  toolName: call.name,
351
438
  input: call.input,
352
439
  });
353
440
  if (!gatewayReview.admitted) {
354
441
  const result = gatewayReview.result;
355
- state.toolResults.push({ toolCallId: call.id, name: call.name, result });
442
+ const envelope = buildRuntimeToolResultEnvelope({
443
+ call,
444
+ spec: { name: call.name },
445
+ result,
446
+ startedAt: toolStartedAt,
447
+ endedAt: Date.now(),
448
+ now: this.now,
449
+ });
450
+ state.toolResults.push({ toolCallId: call.id, name: call.name, result, envelope });
356
451
  await this._runtimeItem(sessionId, cwd, {
357
452
  threadId: state.threadId,
358
453
  turnId: state.turnId,
@@ -360,7 +455,7 @@ class StreamProcessor extends EventEmitter {
360
455
  role: 'tool',
361
456
  status: 'completed',
362
457
  name: call.name,
363
- data: { result },
458
+ data: { result, envelope },
364
459
  });
365
460
  await this._record(sessionId, cwd, 'tool', {
366
461
  state: 'blocked',
@@ -368,6 +463,17 @@ class StreamProcessor extends EventEmitter {
368
463
  name: call.name,
369
464
  input: call.input,
370
465
  result,
466
+ envelope,
467
+ });
468
+ this._emit({
469
+ type: 'tool_result',
470
+ id: call.id,
471
+ toolCallId: call.id,
472
+ tool: call.name,
473
+ name: call.name,
474
+ summary: `Blocked ${call.name}`,
475
+ result,
476
+ error: result?.reason || result?.error || '',
371
477
  });
372
478
  await this._laneEvent({
373
479
  name: EventName.TOOL_FINISHED,
@@ -388,15 +494,105 @@ class StreamProcessor extends EventEmitter {
388
494
  name: call.name,
389
495
  input: call.input,
390
496
  });
391
- const permission = await this.permissionService.authorize({
392
- sessionId,
393
- tool: call.name,
394
- input: call.input,
395
- cwd,
396
- projectRoot: cwd,
397
- headless: this.headless,
398
- metadata: { toolCallId: call.id },
497
+ // When a request actually needs the user (interactive ask), surface it: flip
498
+ // the lane to "waiting" so the session reads as "Needs You" (not a silent hang
499
+ // while the agent waits indefinitely), and persist a durable, actionable
500
+ // approval card part (carrying permId) that survives reload. onAsked fires
501
+ // synchronously inside ask(), before authorize() blocks.
502
+ const permEvents = this.permissionService.events;
503
+ let askedPermId = null;
504
+ const onAsked = (entry) => {
505
+ if (!entry || String(entry.metadata?.toolCallId || '') !== String(call.id)) return;
506
+ askedPermId = entry.id;
507
+ this._laneEvent({
508
+ name: EventName.SESSION_WAITING,
509
+ sessionId,
510
+ cwd,
511
+ provider: state.provider,
512
+ model: state.model,
513
+ runId: state.messageId,
514
+ confidence: Confidence.HIGH,
515
+ reason: 'Waiting for your approval',
516
+ data: { toolCallId: call.id, name: call.name, permId: entry.id, waitingFor: 'permission' },
517
+ });
518
+ this._record(sessionId, cwd, 'permission_request', {
519
+ permId: entry.id,
520
+ permissionContextId: entry.permissionContextId || '',
521
+ toolCallId: call.id,
522
+ tool: call.name,
523
+ permission: entry.permission || '',
524
+ patterns: entry.patterns || (entry.pattern ? [entry.pattern] : []),
525
+ command: (call.input && call.input.command) || '',
526
+ input: call.input,
527
+ reason: entry.metadata?.evaluated?.reason || 'Requires approval',
528
+ });
529
+ // Live event so a watching client renders the approval card immediately
530
+ // (the durable part above covers reload). Shape matches the chat permission
531
+ // card the CTM frontend already knows how to render.
532
+ this._emit({
533
+ type: 'permission_request',
534
+ sessionId,
535
+ permId: entry.id,
536
+ tool: call.name,
537
+ command: (call.input && call.input.command) || '',
538
+ args: Array.isArray(call.input && call.input.args) ? call.input.args : [],
539
+ input: call.input,
540
+ reason: entry.metadata?.evaluated?.reason || 'Requires approval',
541
+ });
542
+ };
543
+ if (permEvents?.on) permEvents.on('permission.asked', onAsked);
544
+ let permission;
545
+ try {
546
+ permission = await this.permissionService.authorize({
547
+ sessionId,
548
+ tool: call.name,
549
+ input: call.input,
550
+ cwd,
551
+ projectRoot: cwd,
552
+ headless: this.headless,
553
+ metadata: { toolCallId: call.id },
554
+ });
555
+ } finally {
556
+ if (permEvents?.off) permEvents.off('permission.asked', onAsked);
557
+ }
558
+ await this._record(sessionId, cwd, 'tool', {
559
+ state: permission.decision === 'allow' ? 'permission_allowed' : 'permission_denied',
560
+ toolCallId: call.id,
561
+ name: call.name,
562
+ permissionContextId: permission.permissionContextId || '',
563
+ decision: permission.decision,
564
+ source: permission.source || '',
565
+ reason: permission.reason || permission.message || '',
399
566
  });
567
+ // If a waiting card was surfaced, clear it and return the lane to running.
568
+ if (askedPermId) {
569
+ await this._record(sessionId, cwd, 'permission_resolved', {
570
+ permId: askedPermId,
571
+ toolCallId: call.id,
572
+ tool: call.name,
573
+ decision: permission.decision,
574
+ source: permission.source || '',
575
+ });
576
+ // Live event so a watching client clears/marks the card without a reload.
577
+ this._emit({
578
+ type: 'permission_resolved',
579
+ sessionId,
580
+ permId: askedPermId,
581
+ tool: call.name,
582
+ decision: permission.decision,
583
+ source: permission.source || '',
584
+ });
585
+ this._laneEvent({
586
+ name: EventName.SESSION_RUNNING,
587
+ sessionId,
588
+ cwd,
589
+ provider: state.provider,
590
+ model: state.model,
591
+ runId: state.messageId,
592
+ confidence: Confidence.HIGH,
593
+ data: { toolCallId: call.id, name: call.name },
594
+ });
595
+ }
400
596
  if (permission.decision !== 'allow') {
401
597
  throw new Error(`Permission denied: ${permission.reason || permission.message || permission.decision}`);
402
598
  }
@@ -429,11 +625,20 @@ class StreamProcessor extends EventEmitter {
429
625
  });
430
626
  let result = await this.toolExecutor(call, { sessionId, cwd, model: state.model, provider: state.provider });
431
627
  await this._recordDiagnostics(sessionId, cwd, call, result);
628
+ const typedArtifacts = this._storeTypedArtifacts(result, { sessionId, cwd, call });
432
629
  const routed = this._routeToolOutput(result, { sessionId, cwd, call });
433
630
  result = routed.result;
631
+ const envelope = buildRuntimeToolResultEnvelope({
632
+ call,
633
+ spec: { name: call.name },
634
+ result,
635
+ startedAt: toolStartedAt,
636
+ endedAt: Date.now(),
637
+ now: this.now,
638
+ });
434
639
  if (isEditTool(call.name) && !result?.error) state.hadEdit = true;
435
640
  if (isSuccessfulTestCommand(call, result)) state.verified = true;
436
- state.toolResults.push({ toolCallId: call.id, name: call.name, result });
641
+ state.toolResults.push({ toolCallId: call.id, name: call.name, result, envelope });
437
642
  if (routed.artifact) {
438
643
  await this._record(sessionId, cwd, 'artifact', {
439
644
  type: 'tool_output',
@@ -442,6 +647,14 @@ class StreamProcessor extends EventEmitter {
442
647
  artifact: routed.artifact,
443
648
  });
444
649
  }
650
+ for (const artifact of typedArtifacts) {
651
+ await this._record(sessionId, cwd, 'artifact', {
652
+ type: artifact.kind || 'artifact',
653
+ toolCallId: call.id,
654
+ name: call.name,
655
+ artifact,
656
+ });
657
+ }
445
658
  await this._runtimeItem(sessionId, cwd, {
446
659
  threadId: state.threadId,
447
660
  turnId: state.turnId,
@@ -449,13 +662,23 @@ class StreamProcessor extends EventEmitter {
449
662
  role: 'tool',
450
663
  status: 'completed',
451
664
  name: call.name,
452
- data: { result },
665
+ data: { result, envelope },
453
666
  });
454
667
  await this._record(sessionId, cwd, 'tool', {
455
668
  state: 'completed',
456
669
  toolCallId: call.id,
457
670
  name: call.name,
458
671
  result,
672
+ envelope,
673
+ });
674
+ this._emit({
675
+ type: 'tool_result',
676
+ id: call.id,
677
+ toolCallId: call.id,
678
+ tool: call.name,
679
+ name: call.name,
680
+ summary: `Completed ${call.name}`,
681
+ result,
459
682
  });
460
683
  await this._laneEvent({
461
684
  name: EventName.TOOL_FINISHED,
@@ -468,8 +691,17 @@ class StreamProcessor extends EventEmitter {
468
691
  data: { toolCallId: call.id, name: call.name },
469
692
  });
470
693
  } catch (err) {
694
+ const envelope = buildRuntimeToolResultEnvelope({
695
+ call,
696
+ spec: { name: call.name },
697
+ result: { error: err.message },
698
+ error: err,
699
+ startedAt: toolStartedAt,
700
+ endedAt: Date.now(),
701
+ now: this.now,
702
+ });
471
703
  state.toolErrors.push(err.message);
472
- state.toolResults.push({ toolCallId: call.id, name: call.name, error: err.message });
704
+ state.toolResults.push({ toolCallId: call.id, name: call.name, error: err.message, envelope });
473
705
  await this._runtimeItem(sessionId, cwd, {
474
706
  threadId: state.threadId,
475
707
  turnId: state.turnId,
@@ -477,13 +709,23 @@ class StreamProcessor extends EventEmitter {
477
709
  role: 'tool',
478
710
  status: 'failed',
479
711
  name: call.name,
480
- data: { error: err.message },
712
+ data: { error: err.message, envelope },
481
713
  });
482
714
  await this._record(sessionId, cwd, 'tool', {
483
715
  state: 'error',
484
716
  toolCallId: call.id,
485
717
  name: call.name,
486
718
  error: err.message,
719
+ envelope,
720
+ });
721
+ this._emit({
722
+ type: 'tool_result',
723
+ id: call.id,
724
+ toolCallId: call.id,
725
+ tool: call.name,
726
+ name: call.name,
727
+ summary: `Failed ${call.name}`,
728
+ error: err.message,
487
729
  });
488
730
  await this._laneEvent({
489
731
  name: EventName.TOOL_FAILED,
@@ -509,6 +751,36 @@ class StreamProcessor extends EventEmitter {
509
751
  });
510
752
  }
511
753
 
754
+ _storeTypedArtifacts(result, { sessionId, call }) {
755
+ const descriptors = extractTypedArtifactDescriptors(result, call);
756
+ if (!descriptors.length) return [];
757
+ const stored = [];
758
+ const seen = new Set();
759
+ for (const descriptor of descriptors) {
760
+ try {
761
+ const artifact = this.artifactStore?.storeArtifact
762
+ ? this.artifactStore.storeArtifact({
763
+ sessionId,
764
+ toolCallId: call.id,
765
+ toolName: call.name,
766
+ kind: descriptor.kind,
767
+ sourcePath: descriptor.path || descriptor.sourcePath,
768
+ content: descriptor.content,
769
+ mimeType: descriptor.mimeType,
770
+ bytes: descriptor.bytes,
771
+ sha256: descriptor.sha256,
772
+ metadata: descriptor.metadata || {},
773
+ })
774
+ : descriptor;
775
+ const key = artifact.artifactId || `${artifact.kind}:${artifact.path}`;
776
+ if (seen.has(key)) continue;
777
+ seen.add(key);
778
+ stored.push(artifact);
779
+ } catch {}
780
+ }
781
+ return stored;
782
+ }
783
+
512
784
  async _recordDiagnostics(sessionId, cwd, call, result) {
513
785
  const diagnostics = extractDiagnostics(result);
514
786
  for (const diagnostic of diagnostics) {
@@ -529,7 +801,7 @@ class StreamProcessor extends EventEmitter {
529
801
  }
530
802
 
531
803
  async _record(sessionId, cwd, partType, data) {
532
- const payload = {
804
+ const payload = attachProjectionFlags({
533
805
  type: 'walle_part',
534
806
  provider: 'walle',
535
807
  sessionId,
@@ -537,7 +809,7 @@ class StreamProcessor extends EventEmitter {
537
809
  timestamp: this.now(),
538
810
  partType,
539
811
  data,
540
- };
812
+ }, partType);
541
813
  if (this.transcript?.appendPart) return this.transcript.appendPart(payload);
542
814
  if (this.transcript?.append) return this.transcript.append(payload);
543
815
  return null;
@@ -561,7 +833,7 @@ class StreamProcessor extends EventEmitter {
561
833
 
562
834
  async _runtimePart(sessionId, cwd, partType, event = {}) {
563
835
  if (!this.transcript) return null;
564
- const payload = {
836
+ const payload = attachProjectionFlags({
565
837
  type: 'walle_part',
566
838
  provider: 'walle',
567
839
  sessionId,
@@ -573,7 +845,7 @@ class StreamProcessor extends EventEmitter {
573
845
  threadId: event.threadId || sessionId,
574
846
  ...event,
575
847
  },
576
- };
848
+ }, partType);
577
849
  if (partType === 'runtime_thread' && this.transcript.appendRuntimeThread) return this.transcript.appendRuntimeThread(payload.data, payload);
578
850
  if (partType === 'runtime_turn' && this.transcript.appendRuntimeTurn) return this.transcript.appendRuntimeTurn(payload.data, payload);
579
851
  if (partType === 'runtime_item' && this.transcript.appendRuntimeItem) return this.transcript.appendRuntimeItem(payload.data, payload);
@@ -604,12 +876,18 @@ function isEditTool(name) {
604
876
  return ['edit_file', 'write_file', 'apply_patch', 'multi_edit'].includes(name);
605
877
  }
606
878
 
879
+ function orderToolResultsByCalls(state, calls = []) {
880
+ if (!state?.toolResults || !Array.isArray(state.toolResults)) return;
881
+ const order = new Map((calls || []).map((call, index) => [call.id, index]));
882
+ state.toolResults.sort((a, b) => {
883
+ const ai = order.has(a.toolCallId) ? order.get(a.toolCallId) : Number.MAX_SAFE_INTEGER;
884
+ const bi = order.has(b.toolCallId) ? order.get(b.toolCallId) : Number.MAX_SAFE_INTEGER;
885
+ return ai - bi;
886
+ });
887
+ }
888
+
607
889
  function isSuccessfulTestCommand(call, result) {
608
- if (call?.name !== 'run_shell') return false;
609
- const command = String(call.input?.command || '');
610
- if (!/\b(test|spec|jest|mocha|pytest|npm\s+test|node\s+test\.js)\b/i.test(command)) return false;
611
- if (result?.error || result?.exitCode) return false;
612
- return true;
890
+ return isSuccessfulVerificationToolCall(normalizeToolCallEvidence(call, result));
613
891
  }
614
892
 
615
893
  function extractDiagnostics(result) {
@@ -639,9 +917,85 @@ function extractDiagnostics(result) {
639
917
  return diagnostics;
640
918
  }
641
919
 
920
+ function extractTypedArtifactDescriptors(result, call = {}) {
921
+ const descriptors = [];
922
+ const push = (descriptor) => {
923
+ if (!descriptor || typeof descriptor !== 'object') return;
924
+ const kind = String(descriptor.kind || descriptor.type || '').trim();
925
+ const artifactPath = descriptor.path || descriptor.file_path || descriptor.sourcePath || '';
926
+ if (!kind || (!artifactPath && descriptor.content === undefined)) return;
927
+ descriptors.push({
928
+ ...descriptor,
929
+ kind,
930
+ path: artifactPath,
931
+ mimeType: descriptor.mimeType || descriptor.mime_type || mimeTypeForKind(kind, artifactPath),
932
+ metadata: descriptor.metadata || {},
933
+ });
934
+ };
935
+ if (result && typeof result === 'object') {
936
+ if (result.artifact) push(result.artifact);
937
+ if (Array.isArray(result.artifacts)) result.artifacts.forEach(push);
938
+ if (call.name === 'browser_screenshot' && result.ok && result.path) {
939
+ push({
940
+ kind: 'screenshot',
941
+ path: result.path,
942
+ mimeType: 'image/png',
943
+ bytes: result.size || result.bytes,
944
+ metadata: {
945
+ url: result.url,
946
+ viewport: result.viewport,
947
+ width: result.width,
948
+ height: result.height,
949
+ },
950
+ });
951
+ }
952
+ if ((call.name === 'make_pdf' || call.name === 'pdf_info') && result.ok && result.path) {
953
+ push({
954
+ kind: 'pdf',
955
+ path: result.path,
956
+ mimeType: 'application/pdf',
957
+ bytes: result.bytes,
958
+ sha256: result.sha256,
959
+ metadata: { page_count: result.page_count },
960
+ });
961
+ }
962
+ if ((call.name === 'make_pdf' || call.name === 'pdf_render_pages') && Array.isArray(result.preview_paths)) {
963
+ result.preview_paths.forEach((previewPath, index) => push({
964
+ kind: 'pdf_page_preview',
965
+ path: previewPath,
966
+ mimeType: 'image/jpeg',
967
+ metadata: {
968
+ source_pdf: result.path,
969
+ page: result.pages?.start ? result.pages.start + index : index + 1,
970
+ page_count: result.page_count,
971
+ },
972
+ }));
973
+ }
974
+ }
975
+ const seen = new Set();
976
+ return descriptors.filter((descriptor) => {
977
+ const key = `${descriptor.kind}:${descriptor.path || ''}:${descriptor.sha256 || ''}`;
978
+ if (seen.has(key)) return false;
979
+ seen.add(key);
980
+ return true;
981
+ });
982
+ }
983
+
984
+ function mimeTypeForKind(kind, artifactPath) {
985
+ if (kind === 'pdf') return 'application/pdf';
986
+ if (kind === 'screenshot') return 'image/png';
987
+ if (kind === 'pdf_page_preview') return 'image/jpeg';
988
+ const text = String(artifactPath || '').toLowerCase();
989
+ if (text.endsWith('.pdf')) return 'application/pdf';
990
+ if (text.endsWith('.png')) return 'image/png';
991
+ if (text.endsWith('.jpg') || text.endsWith('.jpeg')) return 'image/jpeg';
992
+ return 'application/octet-stream';
993
+ }
994
+
642
995
  module.exports = {
643
996
  StreamProcessor,
644
997
  streamFromChat,
645
998
  isSuccessfulTestCommand,
646
999
  extractDiagnostics,
1000
+ extractTypedArtifactDescriptors,
647
1001
  };