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,287 @@
1
+ 'use strict';
2
+
3
+ const { EventEmitter } = require('node:events');
4
+ const { fork } = require('node:child_process');
5
+ const path = require('node:path');
6
+
7
+ const DEFAULT_START_TIMEOUT_MS = 5000;
8
+ const DEFAULT_KILL_TIMEOUT_MS = 3000;
9
+
10
+ function _durationMs(value, fallback) {
11
+ const n = Number(value);
12
+ return Number.isFinite(n) ? Math.max(0, Math.trunc(n)) : fallback;
13
+ }
14
+
15
+ class HostedPtyAdapter {
16
+ constructor(options = {}) {
17
+ if (!options.sessionId) throw new Error('HostedPtyAdapter requires sessionId');
18
+ this.sessionId = options.sessionId;
19
+ this.cmd = options.cmd;
20
+ this.args = Array.isArray(options.args) ? options.args : [];
21
+ this.cwd = options.cwd;
22
+ this.env = options.env;
23
+ this.cols = Number(options.cols || 120) || 120;
24
+ this.rows = Number(options.rows || 30) || 30;
25
+ this.pid = 0;
26
+ this.hostPid = 0;
27
+ this.started = false;
28
+ this.closed = false;
29
+ this._events = new EventEmitter();
30
+ this._manager = options.manager;
31
+ this._logger = options.logger || console;
32
+ this._workerPath = options.workerPath || path.resolve(__dirname, '..', 'workers', 'session-host-process.js');
33
+ this._startTimeoutMs = _durationMs(options.startTimeoutMs, DEFAULT_START_TIMEOUT_MS);
34
+ this._killTimeoutMs = _durationMs(options.killTimeoutMs, DEFAULT_KILL_TIMEOUT_MS);
35
+ this._child = null;
36
+ this._start();
37
+ }
38
+
39
+ _start() {
40
+ const child = fork(this._workerPath, [], {
41
+ cwd: path.resolve(__dirname, '..'),
42
+ env: {
43
+ ...process.env,
44
+ CTM_PROCESS_ROLE: 'ctm-session-host',
45
+ },
46
+ execArgv: [],
47
+ serialization: 'advanced',
48
+ stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
49
+ });
50
+ this._child = child;
51
+ this.hostPid = child.pid || 0;
52
+ this.pid = this.hostPid;
53
+
54
+ child.stdout?.on('data', (buf) => {
55
+ const text = String(buf || '').trimEnd();
56
+ if (text) this._logger.log?.(`[session-host:${this.sessionId.slice(0, 8)}] ${text}`);
57
+ });
58
+ child.stderr?.on('data', (buf) => {
59
+ const text = String(buf || '').trimEnd();
60
+ if (text) this._logger.warn?.(`[session-host:${this.sessionId.slice(0, 8)}] ${text}`);
61
+ });
62
+ child.on('message', (msg) => this._handleChildMessage(msg));
63
+ child.on('error', (err) => {
64
+ this._logger.warn?.(`[session-host:${this.sessionId.slice(0, 8)}] process error: ${err.message}`);
65
+ this._events.emit('host-error', err);
66
+ });
67
+ child.on('exit', (code, signal) => {
68
+ if (this.closed) return;
69
+ this.closed = true;
70
+ this._manager?._unregister(this.sessionId, this);
71
+ if (!this._sawPtyExit) {
72
+ this._events.emit('exit', {
73
+ exitCode: Number.isFinite(code) ? code : 1,
74
+ signal: signal || null,
75
+ });
76
+ }
77
+ });
78
+
79
+ const startTimer = setTimeout(() => {
80
+ if (this.started || this.closed) return;
81
+ this._logger.warn?.(`[session-host:${this.sessionId.slice(0, 8)}] start timed out after ${this._startTimeoutMs}ms`);
82
+ }, this._startTimeoutMs);
83
+ startTimer.unref?.();
84
+
85
+ this._post({
86
+ type: 'start',
87
+ sessionId: this.sessionId,
88
+ cmd: this.cmd,
89
+ args: this.args,
90
+ cwd: this.cwd,
91
+ env: this.env,
92
+ cols: this.cols,
93
+ rows: this.rows,
94
+ });
95
+ }
96
+
97
+ _post(message) {
98
+ if (!this._child || this.closed || !this._child.connected) return false;
99
+ try {
100
+ this._child.send(message);
101
+ return true;
102
+ } catch (err) {
103
+ this._events.emit('host-error', err);
104
+ return false;
105
+ }
106
+ }
107
+
108
+ _handleChildMessage(msg) {
109
+ if (!msg || typeof msg !== 'object') return;
110
+ switch (msg.type) {
111
+ case 'ready':
112
+ return;
113
+ case 'started':
114
+ this.started = true;
115
+ this.pid = msg.pid || this.pid || this.hostPid;
116
+ this.cols = msg.cols || this.cols;
117
+ this.rows = msg.rows || this.rows;
118
+ this._events.emit('started', msg);
119
+ return;
120
+ case 'data':
121
+ this._events.emit('data', String(msg.data || ''));
122
+ return;
123
+ case 'exit':
124
+ this._sawPtyExit = true;
125
+ this.ptyClosed = true;
126
+ this._events.emit('exit', {
127
+ exitCode: Number.isFinite(msg.exitCode) ? msg.exitCode : 0,
128
+ signal: msg.signal || null,
129
+ spawnFailed: !!msg.spawnFailed,
130
+ });
131
+ return;
132
+ case 'headless-message':
133
+ this._manager?._emitHeadlessMessage(msg.message || {});
134
+ return;
135
+ case 'host-error': {
136
+ const err = new Error(msg.message || 'session host error');
137
+ err.code = msg.code || 'SESSION_HOST_ERROR';
138
+ this._events.emit('host-error', err);
139
+ this._manager?._emitHostError(this.sessionId, err);
140
+ return;
141
+ }
142
+ }
143
+ }
144
+
145
+ onData(callback) {
146
+ this._events.on('data', callback);
147
+ return { dispose: () => this._events.off('data', callback) };
148
+ }
149
+
150
+ onExit(callback) {
151
+ this._events.on('exit', callback);
152
+ return { dispose: () => this._events.off('exit', callback) };
153
+ }
154
+
155
+ onStarted(callback) {
156
+ this._events.on('started', callback);
157
+ return { dispose: () => this._events.off('started', callback) };
158
+ }
159
+
160
+ write(data) {
161
+ this._post({ type: 'input', sessionId: this.sessionId, data: String(data || '') });
162
+ }
163
+
164
+ resize(cols, rows) {
165
+ const nextCols = Number(cols || 0);
166
+ const nextRows = Number(rows || 0);
167
+ if (nextCols > 0) this.cols = nextCols;
168
+ if (nextRows > 0) this.rows = nextRows;
169
+ this._post({ type: 'resize', sessionId: this.sessionId, cols: this.cols, rows: this.rows });
170
+ }
171
+
172
+ kill() {
173
+ if (this.closed) return;
174
+ this._post({ type: 'kill', sessionId: this.sessionId });
175
+ const child = this._child;
176
+ const timer = setTimeout(() => {
177
+ if (!this.closed && child && !child.killed) {
178
+ try { child.kill('SIGKILL'); } catch {}
179
+ }
180
+ }, this._killTimeoutMs);
181
+ timer.unref?.();
182
+ }
183
+
184
+ postHeadlessMessage(message) {
185
+ this._post({ type: 'headless', sessionId: this.sessionId, message });
186
+ }
187
+
188
+ terminate() {
189
+ if (this.closed) return;
190
+ this._post({ type: 'shutdown', sessionId: this.sessionId });
191
+ try { this._child?.kill('SIGTERM'); } catch {}
192
+ }
193
+ }
194
+
195
+ class SessionHostManager extends EventEmitter {
196
+ constructor(options = {}) {
197
+ super();
198
+ this.workerPath = options.workerPath || path.resolve(__dirname, '..', 'workers', 'session-host-process.js');
199
+ this.logger = options.logger || console;
200
+ this.hosts = new Map();
201
+ }
202
+
203
+ createPty(options = {}) {
204
+ const host = new HostedPtyAdapter({
205
+ ...options,
206
+ workerPath: this.workerPath,
207
+ manager: this,
208
+ logger: this.logger,
209
+ });
210
+ this.hosts.set(options.sessionId, host);
211
+ return host;
212
+ }
213
+
214
+ get(sessionId) {
215
+ return this.hosts.get(sessionId);
216
+ }
217
+
218
+ has(sessionId) {
219
+ return this.hosts.has(sessionId);
220
+ }
221
+
222
+ postHeadlessMessage(message) {
223
+ const host = this.get(message && message.sessionId);
224
+ if (!host) return false;
225
+ host.postHeadlessMessage(message);
226
+ return true;
227
+ }
228
+
229
+ terminateAll() {
230
+ for (const host of this.hosts.values()) host.terminate();
231
+ this.hosts.clear();
232
+ }
233
+
234
+ _unregister(sessionId, host) {
235
+ if (this.hosts.get(sessionId) === host) this.hosts.delete(sessionId);
236
+ }
237
+
238
+ _emitHeadlessMessage(message) {
239
+ this.emit('headless-message', message);
240
+ }
241
+
242
+ _emitHostError(sessionId, err) {
243
+ this.emit('host-error', { sessionId, error: err });
244
+ }
245
+ }
246
+
247
+ class HeadlessTerminalRouter extends EventEmitter {
248
+ constructor(options = {}) {
249
+ super();
250
+ if (!options.legacyWorker) throw new Error('HeadlessTerminalRouter requires legacyWorker');
251
+ if (!options.sessionHostManager) throw new Error('HeadlessTerminalRouter requires sessionHostManager');
252
+ this.legacyWorker = options.legacyWorker;
253
+ this.sessionHostManager = options.sessionHostManager;
254
+ this.legacyWorker.on('message', (msg) => this.emit('message', msg));
255
+ this.legacyWorker.on('error', (err) => this.emit('error', err));
256
+ this.sessionHostManager.on('headless-message', (msg) => this.emit('message', msg));
257
+ this.sessionHostManager.on('host-error', ({ sessionId, error }) => {
258
+ this.emit('host-error', { sessionId, error });
259
+ });
260
+ }
261
+
262
+ postMessage(message) {
263
+ if (message?.sessionId && this.sessionHostManager.postHeadlessMessage(message)) return;
264
+ this.legacyWorker.postMessage(message);
265
+ }
266
+
267
+ terminate() {
268
+ this.sessionHostManager.terminateAll();
269
+ return this.legacyWorker.terminate();
270
+ }
271
+ }
272
+
273
+ function createSessionHostManager(options = {}) {
274
+ return new SessionHostManager(options);
275
+ }
276
+
277
+ function createHeadlessTerminalRouter(options = {}) {
278
+ return new HeadlessTerminalRouter(options);
279
+ }
280
+
281
+ module.exports = {
282
+ HostedPtyAdapter,
283
+ SessionHostManager,
284
+ HeadlessTerminalRouter,
285
+ createSessionHostManager,
286
+ createHeadlessTerminalRouter,
287
+ };
@@ -0,0 +1,209 @@
1
+ 'use strict';
2
+
3
+ // Session image-ref enrichment.
4
+ //
5
+ // Background: CTM hands images to Claude/Codex via provider-native paste
6
+ // (commit 277cf940). The prompt text that survives in the JSONL transcript
7
+ // therefore carries only a compact `[Image #N]` label — the image itself lands
8
+ // as a base64 block that the conversation/review parsers deliberately strip
9
+ // (lib/jsonl-conversation-parser.js, lib/session-stream.js). On submit the
10
+ // client records a per-submission manifest mapping that prompt's images to
11
+ // their stored files under DATA_DIR/session-images/<session>/
12
+ // (db.recordSessionImageRefs).
13
+ //
14
+ // This module folds those manifests back onto the matching user messages as
15
+ // `image_refs`, which public/js/message-renderer.js already knows how to
16
+ // render. Without this the recorded manifests were write-only and thumbnails
17
+ // never came back on reload.
18
+ //
19
+ // Join key: TIMESTAMP, not label. Manifest labels are per-submission (`[Image
20
+ // #1]`, `[Image #2]`) while the surviving prompt text uses session-accumulated
21
+ // labels (`[Image #8]`), so the two never line up. But the manifest's
22
+ // submit-time and the JSONL user-entry time are the same event, observed <2s
23
+ // apart in practice — so we match each manifest to the nearest image-bearing
24
+ // user message in time (greedy, smallest-gap-first, each side consumed once).
25
+ //
26
+ // Pure (no fs/db) so the matching logic is unit-testable in isolation; db.js
27
+ // supplies the parsed manifests and server.js composes the two.
28
+
29
+ const IMAGE_TOKEN_RE = /\[Image #\d+\]/gi;
30
+ const IMAGE_TOKEN_TEST_RE = /\[Image #\d+\]/i;
31
+
32
+ // Manifests recorded much further from their prompt than this are treated as a
33
+ // non-match rather than risk attaching to an unrelated message. Real gaps are
34
+ // sub-second; the wide window only guards against clock skew / queued sends.
35
+ const DEFAULT_MATCH_TOLERANCE_MS = 5 * 60 * 1000;
36
+
37
+ function _basename(value) {
38
+ return String(value || '').replace(/[?#].*$/, '').split(/[\\/]/).filter(Boolean).pop() || '';
39
+ }
40
+
41
+ function _servedImageUrl(filename) {
42
+ const name = String(filename || '').trim();
43
+ if (!name) return '';
44
+ return '/api/images/file/' + encodeURIComponent(name);
45
+ }
46
+
47
+ // The on-disk file is content-hashed and pointed to by the manifest's relative
48
+ // `target` (e.g. ../../images/<hash>.png); `filename` is only the original
49
+ // upload name and is NOT a real file. Serve by the target basename, falling
50
+ // back to `filename` for older manifests that predate the target field.
51
+ function _manifestLinkServedName(link) {
52
+ return _basename(link && link.target) || _basename(link && link.filename);
53
+ }
54
+
55
+ function _manifestTimestampMs(manifest) {
56
+ if (!manifest || typeof manifest !== 'object') return NaN;
57
+ // Prefer `submitted_at` — the client's submit time, which is the event the
58
+ // JSONL user-entry timestamp also records. `created_at` is only the manifest
59
+ // file-write time (≈ submit in practice, but diverges for backfilled refs).
60
+ const slug = String(manifest.submitted_at || manifest.submittedAt || '');
61
+ const m = slug.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})(\d{3})Z$/);
62
+ if (m) return Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +m[6], +m[7]);
63
+ const created = manifest.created_at || manifest.createdAt;
64
+ if (created) {
65
+ const ms = new Date(created).getTime();
66
+ if (Number.isFinite(ms)) return ms;
67
+ }
68
+ return NaN;
69
+ }
70
+
71
+ // Normalize raw manifest JSON into the shape the matcher consumes: a parsed
72
+ // submit timestamp plus served image URLs. Manifests without a usable timestamp
73
+ // or any servable link are dropped. Returned sorted oldest-first.
74
+ function buildSessionImageRefs(rawManifests) {
75
+ const out = [];
76
+ for (const manifest of Array.isArray(rawManifests) ? rawManifests : []) {
77
+ if (!manifest || typeof manifest !== 'object') continue;
78
+ const submittedAtMs = _manifestTimestampMs(manifest);
79
+ if (!Number.isFinite(submittedAtMs)) continue;
80
+ const links = [];
81
+ for (const link of Array.isArray(manifest.links) ? manifest.links : []) {
82
+ if (!link || typeof link !== 'object') continue;
83
+ const servedName = _manifestLinkServedName(link);
84
+ const url = _servedImageUrl(servedName);
85
+ if (!url) continue;
86
+ links.push({
87
+ label: String(link.label || '').trim(),
88
+ filename: servedName,
89
+ url,
90
+ mediaType: link.mime_type || link.mediaType || '',
91
+ });
92
+ }
93
+ if (!links.length) continue;
94
+ out.push({ submittedAtMs, links });
95
+ }
96
+ out.sort((a, b) => a.submittedAtMs - b.submittedAtMs);
97
+ return out;
98
+ }
99
+
100
+ function _messageTimestampMs(msg) {
101
+ const raw = msg && (msg.timestamp || msg.created_at || msg.ts);
102
+ if (!raw) return NaN;
103
+ const ms = new Date(raw).getTime();
104
+ return Number.isFinite(ms) ? ms : NaN;
105
+ }
106
+
107
+ function _messageText(msg) {
108
+ if (!msg || typeof msg !== 'object') return '';
109
+ const direct = msg.text ?? msg.content ?? msg.message ?? '';
110
+ if (typeof direct === 'string') return direct;
111
+ if (Array.isArray(direct)) {
112
+ return direct.map((part) => {
113
+ if (typeof part === 'string') return part;
114
+ if (!part || typeof part !== 'object') return '';
115
+ if (typeof part.text === 'string') return part.text;
116
+ if (typeof part.content === 'string') return part.content;
117
+ if (typeof part.message === 'string') return part.message;
118
+ return '';
119
+ }).filter(Boolean).join('\n');
120
+ }
121
+ if (direct && typeof direct === 'object') {
122
+ if (typeof direct.text === 'string') return direct.text;
123
+ if (typeof direct.content === 'string') return direct.content;
124
+ if (typeof direct.message === 'string') return direct.message;
125
+ }
126
+ return '';
127
+ }
128
+
129
+ // Distinct `[Image #N]` tokens in the order they appear, used only to caption
130
+ // the thumbnails with labels that match the prompt text where possible.
131
+ function _distinctImageTokens(text) {
132
+ const tokens = [];
133
+ const seen = new Set();
134
+ for (const tok of String(text || '').match(IMAGE_TOKEN_RE) || []) {
135
+ const key = tok.toLowerCase();
136
+ if (seen.has(key)) continue;
137
+ seen.add(key);
138
+ tokens.push(tok);
139
+ }
140
+ return tokens;
141
+ }
142
+
143
+ // Re-attach `image_refs` to the user messages each manifest belongs to.
144
+ //
145
+ // `messages` must be chronological. Matching is greedy smallest-gap-first over
146
+ // (manifest, image-token-bearing user message) pairs within `toleranceMs`, with
147
+ // each manifest and each message consumed at most once. Returns a new array;
148
+ // only enriched messages are shallow-copied (cached objects stay untouched).
149
+ function attachSessionImageRefs(messages, manifests, opts = {}) {
150
+ if (!Array.isArray(messages) || !messages.length) return messages;
151
+ const refs = Array.isArray(manifests) ? manifests : [];
152
+ if (!refs.length) return messages;
153
+ const toleranceMs = Number.isFinite(opts.toleranceMs) ? opts.toleranceMs : DEFAULT_MATCH_TOLERANCE_MS;
154
+
155
+ // Candidate messages: user prompts that reference an image and carry a time.
156
+ const candidates = [];
157
+ for (let i = 0; i < messages.length; i++) {
158
+ const msg = messages[i];
159
+ if (!msg || msg.role !== 'user') continue;
160
+ const text = _messageText(msg);
161
+ if (!IMAGE_TOKEN_TEST_RE.test(text)) continue;
162
+ const ms = _messageTimestampMs(msg);
163
+ if (!Number.isFinite(ms)) continue;
164
+ candidates.push({ index: i, ms, text });
165
+ }
166
+ if (!candidates.length) return messages;
167
+
168
+ const pairs = [];
169
+ for (let m = 0; m < refs.length; m++) {
170
+ const manifest = refs[m];
171
+ for (const cand of candidates) {
172
+ const gap = Math.abs(cand.ms - manifest.submittedAtMs);
173
+ if (gap <= toleranceMs) pairs.push({ gap, manifest: m, message: cand.index });
174
+ }
175
+ }
176
+ if (!pairs.length) return messages;
177
+ pairs.sort((a, b) => a.gap - b.gap);
178
+
179
+ const usedManifest = new Set();
180
+ const assignment = new Map(); // message index -> manifest
181
+ for (const pair of pairs) {
182
+ if (usedManifest.has(pair.manifest) || assignment.has(pair.message)) continue;
183
+ usedManifest.add(pair.manifest);
184
+ assignment.set(pair.message, refs[pair.manifest]);
185
+ }
186
+ if (!assignment.size) return messages;
187
+
188
+ return messages.map((msg, i) => {
189
+ const manifest = assignment.get(i);
190
+ if (!manifest) return msg;
191
+ const tokens = _distinctImageTokens(_messageText(msg));
192
+ const image_refs = manifest.links.map((link, idx) => ({
193
+ kind: 'image',
194
+ label: tokens[idx] || link.label || '[Image #' + (idx + 1) + ']',
195
+ filename: link.filename,
196
+ url: link.url,
197
+ mediaType: link.mediaType || '',
198
+ }));
199
+ return { ...msg, image_refs };
200
+ });
201
+ }
202
+
203
+ module.exports = {
204
+ buildSessionImageRefs,
205
+ attachSessionImageRefs,
206
+ _servedImageUrl,
207
+ _manifestTimestampMs,
208
+ DEFAULT_MATCH_TOLERANCE_MS,
209
+ };