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
@@ -0,0 +1,109 @@
1
+ 'use strict';
2
+
3
+ const BLOCKING_STATUSES = new Set(['running', 'busy']);
4
+
5
+ function normalizeStatus(value) {
6
+ const text = String(value || '').trim().toLowerCase().replace(/[-\s]+/g, '_');
7
+ if (!text) return '';
8
+ if (text === 'waiting' || text === 'waiting_for_input' || text === 'waiting_input') return 'waiting_input';
9
+ if (text === 'busy') return 'running';
10
+ return text;
11
+ }
12
+
13
+ function sessionLabel(session) {
14
+ return String(
15
+ session?.label ||
16
+ session?.title ||
17
+ session?.name ||
18
+ session?.id ||
19
+ ''
20
+ ).trim();
21
+ }
22
+
23
+ function sessionId(session) {
24
+ return String(session?.id || session?.sessionId || session?.ctmSessionId || '').trim();
25
+ }
26
+
27
+ function restartSessionSummary(session, status, waitingForInput, waitingReason) {
28
+ const normalized = waitingForInput ? 'waiting_input' : normalizeStatus(status);
29
+ const summary = {
30
+ id: sessionId(session),
31
+ label: sessionLabel(session),
32
+ status: normalized || 'idle',
33
+ };
34
+ if (waitingReason) summary.waitingReason = waitingReason;
35
+ return summary;
36
+ }
37
+
38
+ function normalizeWaitingReason(value) {
39
+ return String(value || '').trim().toLowerCase().replace(/[-\s]+/g, '_');
40
+ }
41
+
42
+ function defaultWaitingReasonForSession(session) {
43
+ return normalizeWaitingReason(
44
+ session?.waitingReason ||
45
+ session?.waiting_reason ||
46
+ session?.reason ||
47
+ session?._waitingForInputReason ||
48
+ ''
49
+ );
50
+ }
51
+
52
+ function isBlockingWaitingReason(reason) {
53
+ const text = normalizeWaitingReason(reason);
54
+ return text === 'approval' || text === 'choice';
55
+ }
56
+
57
+ function isBlockingWaitingSession(session, summary, waitingForInput, waitingReason, options) {
58
+ if (typeof options.isBlockingWaitingForInput === 'function') {
59
+ return !!options.isBlockingWaitingForInput(session);
60
+ }
61
+ if (isBlockingWaitingReason(waitingReason)) return true;
62
+ // Older callers did not provide waiting reasons. Preserve the conservative
63
+ // behavior for unknown waiting_input rows instead of silently restarting over
64
+ // a possible approval prompt.
65
+ return summary.status === 'waiting_input' && !waitingReason;
66
+ }
67
+
68
+ function summarizeRestartGuard(sessions = [], options = {}) {
69
+ const items = Array.from(sessions || []).filter(Boolean);
70
+ const blockers = [];
71
+ const restorable = [];
72
+
73
+ for (const session of items) {
74
+ const rawStatus = typeof options.statusForSession === 'function'
75
+ ? options.statusForSession(session)
76
+ : (session.standupStatus || session.liveStatus || session.serverState || session.status || '');
77
+ const waitingForInput = typeof options.isWaitingForInput === 'function'
78
+ ? !!options.isWaitingForInput(session)
79
+ : !!session.waitingForInput;
80
+ const waitingReason = typeof options.waitingReasonForSession === 'function'
81
+ ? normalizeWaitingReason(options.waitingReasonForSession(session))
82
+ : defaultWaitingReasonForSession(session);
83
+ const summary = restartSessionSummary(session, rawStatus, waitingForInput, waitingReason);
84
+ if (
85
+ BLOCKING_STATUSES.has(summary.status) ||
86
+ (summary.status === 'waiting_input' &&
87
+ isBlockingWaitingSession(session, summary, waitingForInput, waitingReason, options))
88
+ ) blockers.push(summary);
89
+ else restorable.push(summary);
90
+ }
91
+
92
+ return {
93
+ totalCount: items.length,
94
+ blockingCount: blockers.length,
95
+ restorableCount: restorable.length,
96
+ blockers,
97
+ restorable,
98
+ };
99
+ }
100
+
101
+ module.exports = {
102
+ summarizeRestartGuard,
103
+ _private: {
104
+ normalizeStatus,
105
+ normalizeWaitingReason,
106
+ isBlockingWaitingReason,
107
+ restartSessionSummary,
108
+ },
109
+ };
@@ -0,0 +1,439 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const DEFAULT_TAIL_BYTES = 2 * 1024 * 1024;
7
+ const MAX_PARSED_LINES = 400;
8
+
9
+ function _asString(value) {
10
+ return String(value || '').trim();
11
+ }
12
+
13
+ function _safeJson(value) {
14
+ try { return JSON.parse(value); } catch { return null; }
15
+ }
16
+
17
+ function _readJsonlTail(filePath, opts = {}) {
18
+ const target = _asString(filePath);
19
+ if (!target) return { entries: [], error: 'missing_path' };
20
+ try {
21
+ const stat = fs.statSync(target);
22
+ if (!stat.isFile() || stat.size <= 0) return { entries: [], error: 'empty_file' };
23
+ const tailBytes = Math.max(64 * 1024, Number(opts.tailBytes) || DEFAULT_TAIL_BYTES);
24
+ const start = Math.max(0, stat.size - tailBytes);
25
+ const fd = fs.openSync(target, 'r');
26
+ try {
27
+ const len = stat.size - start;
28
+ const buf = Buffer.allocUnsafe(len);
29
+ fs.readSync(fd, buf, 0, len, start);
30
+ let raw = buf.toString('utf8');
31
+ if (start > 0) {
32
+ const nl = raw.indexOf('\n');
33
+ raw = nl >= 0 ? raw.slice(nl + 1) : '';
34
+ }
35
+ const lines = raw.split('\n').filter(Boolean).slice(-MAX_PARSED_LINES);
36
+ const entries = [];
37
+ for (const line of lines) {
38
+ const parsed = _safeJson(line);
39
+ if (parsed && typeof parsed === 'object') entries.push(parsed);
40
+ }
41
+ return { entries, size: stat.size, mtimeMs: stat.mtimeMs || 0 };
42
+ } finally {
43
+ try { fs.closeSync(fd); } catch {}
44
+ }
45
+ } catch (e) {
46
+ return { entries: [], error: e.message || 'read_failed' };
47
+ }
48
+ }
49
+
50
+ function _entryText(entry) {
51
+ const content = entry?.message?.content ?? entry?.content;
52
+ if (typeof content === 'string') return content;
53
+ if (Array.isArray(content)) {
54
+ return content.map((block) => {
55
+ if (!block || typeof block !== 'object') return '';
56
+ if (typeof block.text === 'string') return block.text;
57
+ if (typeof block.content === 'string') return block.content;
58
+ if (block.type === 'tool_result') return `[tool_result:${block.tool_use_id || block.name || ''}]`;
59
+ if (block.type === 'tool_use') return `[tool_use:${block.name || ''}]`;
60
+ return '';
61
+ }).filter(Boolean).join('\n');
62
+ }
63
+ if (typeof entry?.text === 'string') return entry.text;
64
+ if (typeof entry?.summary === 'string') return entry.summary;
65
+ if (typeof entry?.content === 'string') return entry.content;
66
+ return '';
67
+ }
68
+
69
+ function _codexContentText(content, wantedTypes) {
70
+ if (typeof content === 'string') return content;
71
+ if (!Array.isArray(content)) return '';
72
+ const types = new Set(Array.isArray(wantedTypes) ? wantedTypes : []);
73
+ return content.map((block) => {
74
+ if (!block || typeof block !== 'object') return '';
75
+ if (types.size && !types.has(block.type)) return '';
76
+ if (typeof block.text === 'string') return block.text;
77
+ if (typeof block.content === 'string') return block.content;
78
+ return '';
79
+ }).filter(Boolean).join('\n').trim();
80
+ }
81
+
82
+ function _codexUserText(entry) {
83
+ const payload = entry?.payload || {};
84
+ if (payload.type === 'user_message') return _asString(payload.message);
85
+ if (payload.type === 'message' && payload.role === 'user') {
86
+ return _codexContentText(payload.content, ['input_text', 'text']);
87
+ }
88
+ return '';
89
+ }
90
+
91
+ function _isCodexProviderContextUserText(text) {
92
+ const cleaned = _asString(text);
93
+ if (!cleaned) return true;
94
+ return /^<environment_context>/i.test(cleaned) ||
95
+ /^<permissions instructions>/i.test(cleaned) ||
96
+ /^<collaboration_mode>/i.test(cleaned) ||
97
+ /^<skills_instructions>/i.test(cleaned) ||
98
+ /^<plugins_instructions>/i.test(cleaned) ||
99
+ /^<skill>\s*<name>/i.test(cleaned) ||
100
+ /^# AGENTS\.md instructions for\b/i.test(cleaned);
101
+ }
102
+
103
+ function _isCodexTurnAbortedText(text) {
104
+ return /^<turn_aborted>\s*[\s\S]*?<\/turn_aborted>\s*$/i.test(_asString(text));
105
+ }
106
+
107
+ function _codexToolPreview(payload) {
108
+ if (!payload || typeof payload !== 'object') return '';
109
+ if (payload.name) return `[tool:${payload.name}]`;
110
+ if (payload.call_id) return `[tool:${payload.call_id}]`;
111
+ return '';
112
+ }
113
+
114
+ function _contentBlocks(entry) {
115
+ const content = entry?.message?.content ?? entry?.content;
116
+ return Array.isArray(content) ? content : [];
117
+ }
118
+
119
+ function _hasToolResult(entry) {
120
+ if (!entry || typeof entry !== 'object') return false;
121
+ if (entry.type === 'tool_result') return true;
122
+ return _contentBlocks(entry).some((block) => block && block.type === 'tool_result');
123
+ }
124
+
125
+ function _hasToolUse(entry) {
126
+ if (!entry || typeof entry !== 'object') return false;
127
+ if (entry.type === 'tool_use') return true;
128
+ return _contentBlocks(entry).some((block) => block && block.type === 'tool_use');
129
+ }
130
+
131
+ function _isMetadataNoise(entry) {
132
+ const type = _asString(entry?.type).toLowerCase();
133
+ return !type ||
134
+ type === 'summary' ||
135
+ type === 'metadata' ||
136
+ type === 'last-prompt' ||
137
+ type === 'ai-title' ||
138
+ type === 'title' ||
139
+ type === 'message-stat' ||
140
+ type === 'session-meta' ||
141
+ type === 'model';
142
+ }
143
+
144
+ function _semanticEvent(entry) {
145
+ const type = _asString(entry?.type).toLowerCase();
146
+ const timestamp = _asString(entry?.timestamp);
147
+ const payload = entry?.payload || {};
148
+ const payloadType = _asString(payload?.type).toLowerCase();
149
+
150
+ if (type === 'event_msg') {
151
+ if (payloadType === 'user_message') {
152
+ const text = _codexUserText(entry);
153
+ if (!text || _isCodexProviderContextUserText(text)) return null;
154
+ if (_isCodexTurnAbortedText(text)) return { kind: 'codex_turn_aborted', timestamp, text };
155
+ return { kind: 'user', timestamp, text };
156
+ }
157
+ if (payloadType === 'agent_message') {
158
+ const text = _asString(payload.message);
159
+ const phase = _asString(payload.phase).toLowerCase();
160
+ if (!text) return null;
161
+ return {
162
+ kind: phase === 'commentary' ? 'codex_assistant_commentary' : 'assistant',
163
+ timestamp,
164
+ text,
165
+ phase,
166
+ };
167
+ }
168
+ if (payloadType === 'task_complete') {
169
+ const text = _asString(payload.last_agent_message);
170
+ return { kind: 'assistant', timestamp, text, phase: 'task_complete' };
171
+ }
172
+ if (payloadType === 'turn_aborted') {
173
+ return { kind: 'codex_turn_aborted', timestamp, text: payload.reason || payload.message || 'turn_aborted' };
174
+ }
175
+ if (payloadType === 'patch_apply_end') {
176
+ return { kind: 'tool_result', timestamp, text: payload.stdout || payload.stderr || 'patch_apply_end' };
177
+ }
178
+ }
179
+
180
+ if (type === 'response_item') {
181
+ if (payloadType === 'message' && payload.role === 'user') {
182
+ const text = _codexUserText(entry);
183
+ if (!text || _isCodexProviderContextUserText(text)) return null;
184
+ if (_isCodexTurnAbortedText(text)) return { kind: 'codex_turn_aborted', timestamp, text };
185
+ return { kind: 'user', timestamp, text };
186
+ }
187
+ if (payloadType === 'message' && payload.role === 'assistant') {
188
+ const text = _codexContentText(payload.content, ['output_text', 'text']);
189
+ if (!text) return null;
190
+ const phase = _asString(payload.phase).toLowerCase();
191
+ return {
192
+ kind: phase === 'commentary' ? 'codex_assistant_commentary' : 'assistant',
193
+ timestamp,
194
+ text,
195
+ phase,
196
+ };
197
+ }
198
+ if (payloadType === 'function_call' || payloadType === 'custom_tool_call') {
199
+ return { kind: 'assistant_tool_use', timestamp, text: _codexToolPreview(payload), stopReason: 'tool_use' };
200
+ }
201
+ if (payloadType === 'function_call_output' || payloadType === 'custom_tool_call_output') {
202
+ return { kind: 'tool_result', timestamp, text: payload.output || _codexToolPreview(payload) };
203
+ }
204
+ }
205
+
206
+ if (type === 'assistant' || entry?.message?.role === 'assistant') {
207
+ const stopReason = _asString(entry?.message?.stop_reason || entry?.stop_reason).toLowerCase();
208
+ return {
209
+ kind: _hasToolUse(entry) || stopReason === 'tool_use' ? 'assistant_tool_use' : 'assistant',
210
+ timestamp,
211
+ stopReason,
212
+ text: _entryText(entry),
213
+ };
214
+ }
215
+ if (type === 'user' || entry?.message?.role === 'user') {
216
+ if (_hasToolResult(entry)) {
217
+ return { kind: 'tool_result', timestamp, text: _entryText(entry) };
218
+ }
219
+ const text = _entryText(entry);
220
+ if (!text) return null;
221
+ return { kind: 'user', timestamp, text };
222
+ }
223
+ if (type === 'tool_result') {
224
+ return { kind: 'tool_result', timestamp, text: _entryText(entry) };
225
+ }
226
+ if (type === 'queue-operation') {
227
+ const operation = _asString(entry.operation).toLowerCase();
228
+ const content = _entryText(entry);
229
+ if (operation === 'enqueue' && /<status>\s*completed\s*<\/status>|completed/i.test(content)) {
230
+ return { kind: 'background_task_completed', timestamp, text: content };
231
+ }
232
+ return null;
233
+ }
234
+ if (_isMetadataNoise(entry)) return null;
235
+ return null;
236
+ }
237
+
238
+ function _lastSemanticEvent(entries) {
239
+ for (let i = entries.length - 1; i >= 0; i--) {
240
+ const semantic = _semanticEvent(entries[i]);
241
+ if (semantic) return semantic;
242
+ }
243
+ return null;
244
+ }
245
+
246
+ function _reasonForSemantic(semantic) {
247
+ if (!semantic) return null;
248
+ if (semantic.kind === 'tool_result') {
249
+ return {
250
+ interrupted: true,
251
+ reason: 'tool_result_without_assistant_continuation',
252
+ label: 'Interrupted after a tool result',
253
+ detail: 'The last transcript event is a tool result, but no assistant message followed it.',
254
+ };
255
+ }
256
+ if (semantic.kind === 'background_task_completed') {
257
+ return {
258
+ interrupted: true,
259
+ reason: 'background_task_completed_without_assistant_continuation',
260
+ label: 'Interrupted after background work completed',
261
+ detail: 'A background task completion notification was written, but the assistant never processed it.',
262
+ };
263
+ }
264
+ if (semantic.kind === 'assistant_tool_use') {
265
+ return {
266
+ interrupted: true,
267
+ reason: 'assistant_tool_use_without_result',
268
+ label: 'Interrupted while a tool was pending',
269
+ detail: 'The assistant requested a tool and CTM restored before a later continuation was recorded.',
270
+ };
271
+ }
272
+ if (semantic.kind === 'codex_assistant_commentary') {
273
+ return {
274
+ interrupted: true,
275
+ reason: 'codex_commentary_without_final_response',
276
+ label: 'Interrupted after a progress update',
277
+ detail: 'Codex recorded an assistant commentary/progress message, but no final answer or task completion followed it.',
278
+ };
279
+ }
280
+ if (semantic.kind === 'codex_turn_aborted') {
281
+ return {
282
+ interrupted: true,
283
+ reason: 'codex_turn_aborted',
284
+ label: 'Interrupted by Codex turn abort',
285
+ detail: 'Codex recorded a turn-aborted control event before CTM restored the session.',
286
+ };
287
+ }
288
+ if (semantic.kind === 'user') {
289
+ return {
290
+ interrupted: true,
291
+ reason: 'user_prompt_without_assistant_response',
292
+ label: 'Interrupted before the assistant responded',
293
+ detail: 'The last transcript event is a user prompt with no later assistant response.',
294
+ };
295
+ }
296
+ return null;
297
+ }
298
+
299
+ function detectRestoreInterruptionFromEntries(entries, opts = {}) {
300
+ const semantic = _lastSemanticEvent(Array.isArray(entries) ? entries : []);
301
+ const reason = _reasonForSemantic(semantic);
302
+ if (!reason) {
303
+ return {
304
+ interrupted: false,
305
+ lastEventKind: semantic?.kind || '',
306
+ lastEventTimestamp: semantic?.timestamp || '',
307
+ };
308
+ }
309
+ const observedAt = Date.parse(semantic.timestamp || '') || Number(opts.now) || Date.now();
310
+ return {
311
+ ...reason,
312
+ lastEventKind: semantic.kind,
313
+ lastEventTimestamp: semantic.timestamp || '',
314
+ observedAt,
315
+ preview: _asString(semantic.text).replace(/\s+/g, ' ').slice(0, 240),
316
+ };
317
+ }
318
+
319
+ function _selectAgentRow(db, ctmSessionId, provider) {
320
+ if (!db || !ctmSessionId) return null;
321
+ try {
322
+ const rows = db.prepare(`
323
+ SELECT *
324
+ FROM agent_sessions
325
+ WHERE ctm_session_id = ?
326
+ ORDER BY COALESCE(NULLIF(modified_at, ''), updated_at, created_at) DESC,
327
+ updated_at DESC,
328
+ created_at DESC
329
+ `).all(ctmSessionId);
330
+ const wanted = _asString(provider).toLowerCase();
331
+ return rows.find((row) => {
332
+ if (!row?.jsonl_path) return false;
333
+ if (!wanted) return true;
334
+ const rowProvider = _asString(row.provider).toLowerCase();
335
+ return !rowProvider || rowProvider === wanted;
336
+ }) || rows.find((row) => row?.jsonl_path) || null;
337
+ } catch {
338
+ return null;
339
+ }
340
+ }
341
+
342
+ function _normalizeArgs(value) {
343
+ if (Array.isArray(value)) return value.map((item) => String(item || ''));
344
+ if (typeof value === 'string') {
345
+ const parsed = _safeJson(value);
346
+ if (Array.isArray(parsed)) return parsed.map((item) => String(item || ''));
347
+ }
348
+ return [];
349
+ }
350
+
351
+ function _resumeIdFromArgs(args) {
352
+ const list = _normalizeArgs(args);
353
+ for (let i = 0; i < list.length; i++) {
354
+ const arg = list[i];
355
+ if ((arg === '--resume' || arg === '-r' || arg === '--session' || arg === '--session-id') && list[i + 1]) {
356
+ return _asString(list[i + 1]);
357
+ }
358
+ const eq = arg.match(/^--(?:resume|session|session-id)=(.+)$/);
359
+ if (eq) return _asString(eq[1]);
360
+ }
361
+ return '';
362
+ }
363
+
364
+ function _encodeProjectEntry(cwd) {
365
+ return String(cwd || '').replace(/\/\./g, '/-').replace(/\//g, '-');
366
+ }
367
+
368
+ function _canonicalClaudeCwd(cwd) {
369
+ const resolved = path.resolve(cwd || process.env.HOME || '.');
370
+ try { return fs.realpathSync(resolved); } catch { return resolved; }
371
+ }
372
+
373
+ function _existingTranscriptPath(basePath) {
374
+ if (!basePath) return '';
375
+ try {
376
+ if (fs.existsSync(basePath)) return basePath;
377
+ const bakPath = `${basePath}.bak`;
378
+ if (fs.existsSync(bakPath)) return bakPath;
379
+ } catch {}
380
+ return '';
381
+ }
382
+
383
+ function _fallbackTranscriptPathFromTask(task, provider, opts = {}) {
384
+ if (!task || typeof task !== 'object') return '';
385
+ const agentId =
386
+ _asString(task.agent_session_id) ||
387
+ _asString(task.claude_session_id) ||
388
+ _asString(task.resume_session_id) ||
389
+ _resumeIdFromArgs(task.args);
390
+ if (!agentId) return '';
391
+
392
+ const explicitProjectDir = _asString(task.agent_project_dir || task.claude_project_dir || task.project_dir);
393
+ if (explicitProjectDir) {
394
+ const explicit = _existingTranscriptPath(path.resolve(explicitProjectDir, `${agentId}.jsonl`));
395
+ if (explicit) return explicit;
396
+ }
397
+
398
+ if (provider === 'claude') {
399
+ const cwd = _asString(task.worktree_path || task.cwd);
400
+ if (!cwd) return '';
401
+ const homeDir = path.resolve(opts.homeDir || process.env.HOME || '');
402
+ if (!homeDir) return '';
403
+ const projectEntry = _encodeProjectEntry(_canonicalClaudeCwd(cwd));
404
+ return _existingTranscriptPath(path.join(homeDir, '.claude', 'projects', projectEntry, `${agentId}.jsonl`));
405
+ }
406
+
407
+ return '';
408
+ }
409
+
410
+ function detectRestoreInterruption({ db, task, agentType, jsonlPath, now, homeDir } = {}) {
411
+ const provider = _asString(agentType || task?.type || task?.cmd).toLowerCase();
412
+ if (!['claude', 'codex'].includes(provider)) {
413
+ return { interrupted: false, reason: 'unsupported_provider' };
414
+ }
415
+ const ctmSessionId = _asString(task?.ctm_session_id || task?.session_id);
416
+ const row = jsonlPath ? null : _selectAgentRow(db, ctmSessionId, provider);
417
+ const filePath = _asString(jsonlPath || row?.jsonl_path || _fallbackTranscriptPathFromTask(task, provider, { homeDir }));
418
+ if (!filePath) return { interrupted: false, reason: 'missing_transcript_path' };
419
+ const tail = _readJsonlTail(path.resolve(filePath));
420
+ if (tail.error) return { interrupted: false, reason: tail.error, jsonlPath: filePath };
421
+ const result = detectRestoreInterruptionFromEntries(tail.entries, { now });
422
+ return {
423
+ ...result,
424
+ jsonlPath: filePath,
425
+ fileSize: tail.size || 0,
426
+ fileMtimeMs: tail.mtimeMs || 0,
427
+ agentSessionId: row?.agent_session_id || '',
428
+ };
429
+ }
430
+
431
+ module.exports = {
432
+ detectRestoreInterruption,
433
+ detectRestoreInterruptionFromEntries,
434
+ _private: {
435
+ _readJsonlTail,
436
+ _semanticEvent,
437
+ _lastSemanticEvent,
438
+ },
439
+ };
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ function shouldDeferStartupTaskRestore(task, restoredOrdinal, fastSessionCount) {
4
+ if (task?.type === 'walle') return false;
5
+ const ordinal = Number(restoredOrdinal) || 0;
6
+ const fastCount = Number(fastSessionCount) || 0;
7
+ if (ordinal <= fastCount) return false;
8
+ return true;
9
+ }
10
+
11
+ module.exports = {
12
+ shouldDeferStartupTaskRestore,
13
+ };
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ // Background auto-resume drain, extracted from server.js _autoResumeDeferredSessions
4
+ // so the batch + coalesced-broadcast invariant is unit-testable without booting the
5
+ // whole server.
6
+ //
7
+ // Drains an ordered list of deferred-session ids in batches of `batchSize`. For each
8
+ // id it re-checks `canResume` (so a tab the user clicked mid-pass is skipped, not
9
+ // double-started) and, if resumable, awaits `startSession`. After each batch it emits
10
+ // EXACTLY ONE coalesced `broadcast()` — but only when >=1 session actually resumed in
11
+ // that batch (an all-skipped batch broadcasts nothing). A `scheduleGap(fn)` callback
12
+ // schedules the next tick after the inter-batch gap; `onComplete` fires once drained.
13
+ //
14
+ // batchSize=1 reproduces the legacy serial cadence (1 resume -> 1 broadcast -> gap):
15
+ // every resumed session is its own batch, so broadcasts == resumes.
16
+ //
17
+ // All effects are injected (no module state), so a test can drive it synchronously
18
+ // with spies + a `scheduleGap` that calls its fn immediately.
19
+ //
20
+ // deps:
21
+ // ids string[] ordered deferred ids (snapshotted once)
22
+ // batchSize number >=1; ids drained per tick
23
+ // getSession (id) => session|undefined
24
+ // canResume (session) => boolean re-checked per id
25
+ // startSession async (session) => any resumes one session
26
+ // onError (id, err) => void non-fatal per-session resume error (optional)
27
+ // broadcast () => void one coalesced list refresh per non-empty batch
28
+ // scheduleGap (fn) => void schedule next tick after the inter-batch gap
29
+ // onComplete () => void all ids drained (optional)
30
+ function drainDeferredInBatches(deps) {
31
+ const {
32
+ ids,
33
+ batchSize,
34
+ getSession,
35
+ canResume,
36
+ startSession,
37
+ onError,
38
+ broadcast,
39
+ scheduleGap,
40
+ onComplete,
41
+ } = deps || {};
42
+ const list = Array.isArray(ids) ? ids : [];
43
+ const size = Math.max(1, Math.floor(Number(batchSize)) || 1);
44
+ let i = 0;
45
+
46
+ async function tick() {
47
+ if (i >= list.length) {
48
+ if (typeof onComplete === 'function') onComplete();
49
+ return;
50
+ }
51
+ let resumedInBatch = 0;
52
+ for (let b = 0; b < size && i < list.length; b++) {
53
+ const id = list[i++];
54
+ const s = getSession(id);
55
+ if (canResume(s)) {
56
+ try {
57
+ await startSession(s);
58
+ resumedInBatch++;
59
+ } catch (e) {
60
+ if (typeof onError === 'function') onError(id, e);
61
+ }
62
+ }
63
+ }
64
+ // One session-list refresh for the whole batch; an all-skipped batch is silent.
65
+ if (resumedInBatch > 0 && typeof broadcast === 'function') broadcast();
66
+ scheduleGap(tick);
67
+ }
68
+
69
+ // First tick is scheduled through the same gap (the original kicked off with
70
+ // setTimeout(resumeNext, gap) after the identity-cache prebuild settled).
71
+ scheduleGap(tick);
72
+ }
73
+
74
+ module.exports = { drainDeferredInBatches };