agentbox-app 0.1.12 → 0.1.16

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 (370) hide show
  1. package/README.md +24 -9
  2. package/bin/agentbox.mjs +23 -1
  3. package/briefs/message-rules.md +36 -8
  4. package/briefs/worker.md +46 -23
  5. package/main/account-discovery.mjs +122 -30
  6. package/main/account-tooling.mjs +29 -1
  7. package/main/account-usage.mjs +46 -0
  8. package/main/acp.mjs +296 -0
  9. package/main/agent-homes.mjs +158 -0
  10. package/main/agent-sessions.mjs +311 -260
  11. package/main/agent-updates.mjs +9 -22
  12. package/main/agents.mjs +179 -466
  13. package/main/analytics.mjs +42 -2
  14. package/main/answer-modes.mjs +103 -37
  15. package/main/approval-prompt-core.mjs +197 -0
  16. package/main/approval-prompt-server.mjs +4 -138
  17. package/main/approvals.mjs +101 -297
  18. package/main/artifact-path.mjs +47 -18
  19. package/main/claude-bin.mjs +45 -311
  20. package/main/claude-input.mjs +57 -7
  21. package/main/claude-launch-env.mjs +54 -0
  22. package/main/claude-models.mjs +39 -7
  23. package/main/claude-plan.mjs +64 -16
  24. package/main/claude-session-open.mjs +28 -0
  25. package/main/claude-usage-process.mjs +40 -0
  26. package/main/claude-usage.mjs +94 -59
  27. package/main/cloud/account.mjs +179 -0
  28. package/main/cloud/aws.mjs +127 -0
  29. package/main/cloud/browser-return.mjs +58 -0
  30. package/main/cloud/clients.mjs +15 -0
  31. package/main/cloud/codex-cloud.mjs +53 -0
  32. package/main/cloud/config.mjs +107 -0
  33. package/main/cloud/docs.mjs +219 -0
  34. package/main/cloud/exec.mjs +27 -0
  35. package/main/cloud/host.mjs +165 -0
  36. package/main/cloud/kit.mjs +80 -0
  37. package/main/cloud/logins.mjs +543 -0
  38. package/main/cloud/managed.mjs +115 -0
  39. package/main/cloud/marker.mjs +104 -0
  40. package/main/cloud/org.mjs +53 -0
  41. package/main/cloud/reuse.mjs +208 -0
  42. package/main/cloud/run-cli.mjs +177 -0
  43. package/main/cloud/run.mjs +1934 -0
  44. package/main/cloud/usage.mjs +76 -0
  45. package/main/cloud-permission.mjs +51 -0
  46. package/main/codex-account.mjs +78 -0
  47. package/main/codex-app-server.mjs +276 -409
  48. package/main/codex-approvals.mjs +148 -433
  49. package/main/codex-bin.mjs +51 -249
  50. package/main/codex-models.mjs +20 -2
  51. package/main/codex-session.mjs +246 -506
  52. package/main/codex-threads-worker.mjs +12 -0
  53. package/main/codex-threads.mjs +112 -11
  54. package/main/codex-usage-file.mjs +5 -3
  55. package/main/codex-usage.mjs +56 -7
  56. package/main/codex-watch.mjs +83 -5
  57. package/main/codex.mjs +95 -363
  58. package/main/config.mjs +37 -5
  59. package/main/corner-tag.mjs +810 -0
  60. package/main/crash-report.mjs +26 -3
  61. package/main/dev-window.mjs +1 -1
  62. package/main/engine-bin.mjs +545 -0
  63. package/main/engine-setup.mjs +25 -24
  64. package/main/feedback.mjs +14 -31
  65. package/main/folder-pictures.mjs +2 -2
  66. package/main/freeze-recorder-thread.mjs +86 -0
  67. package/main/freeze-recorder.mjs +146 -0
  68. package/main/fresh-user.mjs +20 -9
  69. package/main/git-change-offthread.mjs +17 -3
  70. package/main/git-change-thread.mjs +5 -2
  71. package/main/harnesses/claude-stream.mjs +208 -0
  72. package/main/harnesses/claude.mjs +105 -0
  73. package/main/harnesses/codex.mjs +72 -0
  74. package/main/harnesses/common.mjs +78 -0
  75. package/main/harnesses/instructions-file.mjs +116 -0
  76. package/main/harnesses/opencode.mjs +234 -0
  77. package/main/harnesses.mjs +65 -0
  78. package/main/importable-threads.mjs +96 -0
  79. package/main/ipc.mjs +520 -135
  80. package/main/leftovers.mjs +117 -25
  81. package/main/liquid-glass.mjs +26 -0
  82. package/main/live-replies.mjs +10 -4
  83. package/main/local-app-frames.mjs +82 -0
  84. package/main/main-went-red.mjs +330 -0
  85. package/main/main.mjs +248 -37
  86. package/main/memory-gate-history.mjs +85 -20
  87. package/main/memory-gate-server.mjs +129 -11
  88. package/main/memory-gate.mjs +62 -8
  89. package/main/memory-log.mjs +124 -0
  90. package/main/menu.mjs +4 -2
  91. package/main/message-priority.mjs +2 -2
  92. package/main/mic.mjs +38 -0
  93. package/main/native/liquid-glass/build/liquid-glass.node +0 -0
  94. package/main/new-chats-watch.mjs +110 -0
  95. package/main/new-user-window.mjs +25 -0
  96. package/main/notify.mjs +64 -5
  97. package/main/opencode-server.mjs +271 -0
  98. package/main/opencode.mjs +287 -0
  99. package/main/phone-alerts.mjs +117 -0
  100. package/main/phone-inbox.mjs +625 -0
  101. package/main/phone-link.mjs +571 -0
  102. package/main/phone-uploads.mjs +476 -0
  103. package/main/picture-shape.mjs +114 -0
  104. package/main/quit-sequence.mjs +143 -0
  105. package/main/refresh-agent-models.mjs +15 -2
  106. package/main/relay-address.mjs +28 -0
  107. package/main/relay-client.mjs +314 -0
  108. package/main/repeats.mjs +10 -4
  109. package/main/row-label.mjs +18 -47
  110. package/main/run-change.mjs +13 -0
  111. package/main/run-ledger.mjs +135 -0
  112. package/main/runs-on.mjs +32 -35
  113. package/main/save-attachments.mjs +41 -0
  114. package/main/serve.mjs +155 -9
  115. package/main/settings.mjs +364 -50
  116. package/main/shell-path.mjs +234 -0
  117. package/main/ship-conflict-brief.mjs +119 -0
  118. package/main/ship-queue.mjs +134 -20
  119. package/main/sign-in-files.mjs +3 -7
  120. package/main/source-updater.mjs +45 -11
  121. package/main/stage-attachment.mjs +68 -0
  122. package/main/stall-watch.mjs +50 -0
  123. package/main/start-hold.mjs +73 -0
  124. package/main/store/home.mjs +87 -232
  125. package/main/store/paths.mjs +11 -0
  126. package/main/store/teammates-files.mjs +99 -0
  127. package/main/store/work-items.mjs +231 -13
  128. package/main/store.mjs +227 -53
  129. package/main/supervisor.mjs +3865 -699
  130. package/main/task-commands.mjs +13 -17
  131. package/main/task-folders-offthread.mjs +6 -1
  132. package/main/task-folders.mjs +897 -105
  133. package/main/task-terminals.mjs +147 -41
  134. package/main/team/index.mjs +114 -10
  135. package/main/team/memory-cloud.mjs +183 -1
  136. package/main/team/room-hours.mjs +48 -0
  137. package/main/team/room-setup.mjs +31 -0
  138. package/main/team/rooms-memory.mjs +454 -0
  139. package/main/team/rooms-shape.mjs +42 -0
  140. package/main/team/rooms-supabase.mjs +324 -0
  141. package/main/team/rooms.mjs +575 -0
  142. package/main/team/session.mjs +96 -26
  143. package/main/team/supabase-backend.mjs +180 -0
  144. package/main/team/sync.mjs +109 -1
  145. package/main/teammates.mjs +580 -0
  146. package/main/terminal-host.mjs +143 -0
  147. package/main/terminal-hosts.mjs +261 -0
  148. package/main/transcript-search.mjs +80 -0
  149. package/main/updater.mjs +71 -9
  150. package/main/webview-guard.mjs +45 -0
  151. package/main/worktree-include.mjs +365 -0
  152. package/mcp/core/documents.mjs +3 -1
  153. package/mcp/core/repeats.mjs +88 -0
  154. package/mcp/core/teammates.mjs +222 -0
  155. package/mcp/core/work.mjs +76 -4
  156. package/mcp/stdio.mjs +24 -11
  157. package/mcp/tools.mjs +116 -8
  158. package/package.json +30 -5
  159. package/renderer/dist/assets/abnfDiagram-YUKMZFIV-CoWB6YUK.js +1 -0
  160. package/renderer/dist/assets/arc-Ch0NrCul.js +1 -0
  161. package/renderer/dist/assets/architectureDiagram-47P4ROYG-CXz9M5tQ.js +36 -0
  162. package/renderer/dist/assets/blockDiagram-E7TT5TSB-DchGUuHH.js +140 -0
  163. package/renderer/dist/assets/c4Diagram-CRA5TL53-Cip-zNyr.js +38 -0
  164. package/renderer/dist/assets/channel-BQuQSL--.js +1 -0
  165. package/renderer/dist/assets/chunk-2Q5K7J3B-BoXid_2r.js +1 -0
  166. package/renderer/dist/assets/chunk-5VM5RSS4-Cpez1rRz.js +15 -0
  167. package/renderer/dist/assets/chunk-7TKQ45FW-DKA84YkE.js +1 -0
  168. package/renderer/dist/assets/chunk-AW2ZBBNX-Dg-SumPG.js +88 -0
  169. package/renderer/dist/assets/chunk-FVRAUYC3-06TCvPm1.js +2 -0
  170. package/renderer/dist/assets/chunk-HTAEGDNF-CMEBy1Td.js +1 -0
  171. package/renderer/dist/assets/chunk-JWPE2WC7-BJ2ObmV-.js +1 -0
  172. package/renderer/dist/assets/chunk-KQW6MTUR-CGWOYXUE.js +1 -0
  173. package/renderer/dist/assets/chunk-XXDRQBXY-CiZp07XC.js +1 -0
  174. package/renderer/dist/assets/classDiagram-v2-K4WV4PDN-DJNIX719.js +217 -0
  175. package/renderer/dist/assets/cornerTag-CPgvu-q3.js +1 -0
  176. package/renderer/dist/assets/cornerTag-oMfEjzCO.css +1 -0
  177. package/renderer/dist/assets/cose-bilkent-JH36ORCC-CbkyZOUH.js +1 -0
  178. package/renderer/dist/assets/cynefin-EF2NZ3EQ-78iOroZO.js +141 -0
  179. package/renderer/dist/assets/cynefinDiagram-3GCD6N5R-GcCopMs7.js +62 -0
  180. package/renderer/dist/assets/cytoscape.esm-C5JX3QLV.js +331 -0
  181. package/renderer/dist/assets/dagre-W4DXFKR2-DHLlXLkz.js +4 -0
  182. package/renderer/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  183. package/renderer/dist/assets/diagram-2UJZ2QOL-DuZSUHcH.js +200 -0
  184. package/renderer/dist/assets/diagram-OVF4WLC6-Ckxu3cqH.js +24 -0
  185. package/renderer/dist/assets/diagram-PFPMY2P6-CsTw9Ycn.js +30 -0
  186. package/renderer/dist/assets/diagram-UMYRVEAY-CTXd8qVg.js +24 -0
  187. package/renderer/dist/assets/diagram-YEKJPTXX-CJs1T_9m.js +41 -0
  188. package/renderer/dist/assets/diagram-ZIFT7M5P-CvjI23mf.js +3 -0
  189. package/renderer/dist/assets/ebnfDiagram-VR2GEFS7-d_IeAzOJ.js +1 -0
  190. package/renderer/dist/assets/elk-IJKZMXRS-zo9KFP3N.js +27 -0
  191. package/renderer/dist/assets/erDiagram-O2IAPWRE-DqfYf5Dt.js +99 -0
  192. package/renderer/dist/assets/flowDiagram-OXPTDLAJ-DAWsMLmo.js +213 -0
  193. package/renderer/dist/assets/ganttDiagram-R7TSEDQI-4ml_bhwR.js +292 -0
  194. package/renderer/dist/assets/gitGraphDiagram-XJZIOB7I-B_WcqSId.js +106 -0
  195. package/renderer/dist/assets/graph-DGbsTEsI.js +1 -0
  196. package/renderer/dist/assets/infoDiagram-5W2HQ5XZ-CI-jYqzc.js +2 -0
  197. package/renderer/dist/assets/init-Gi6I4Gst.js +1 -0
  198. package/renderer/dist/assets/ishikawaDiagram-K3B6WC7H-B56VWRlV.js +70 -0
  199. package/renderer/dist/assets/journeyDiagram-COXZFDF6-D1-p09Lr.js +139 -0
  200. package/renderer/dist/assets/kanban-definition-P3RFRI5V-Cv3w7JoN.js +89 -0
  201. package/renderer/dist/assets/katex-C5jXJg4s.js +257 -0
  202. package/renderer/dist/assets/linear-C35V2Spi.js +1 -0
  203. package/renderer/dist/assets/main-BcoBiGwv.css +32 -0
  204. package/renderer/dist/assets/main-CLnIOulD.js +1191 -0
  205. package/renderer/dist/assets/mermaid.core-BzGT5Vo9.js +314 -0
  206. package/renderer/dist/assets/mindmap-definition-LZFPQGKD-BZUfuymC.js +96 -0
  207. package/renderer/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  208. package/renderer/dist/assets/pegDiagram-BGZESJAR-DFh9XNGe.js +1 -0
  209. package/renderer/dist/assets/pieDiagram-CAPJLFHJ-C65tPVsy.js +39 -0
  210. package/renderer/dist/assets/product-name-CSNW6d7s.js +40 -0
  211. package/renderer/dist/assets/quadrantDiagram-GDMTTRAM-Cushj_nk.js +7 -0
  212. package/renderer/dist/assets/railroadDiagram-SM67HX2B-DZGebGx5.js +1 -0
  213. package/renderer/dist/assets/requirementDiagram-X7JNWC4A-DpAB0MNo.js +84 -0
  214. package/renderer/dist/assets/sankeyDiagram-UM26HJRW-D-29rHra.js +40 -0
  215. package/renderer/dist/assets/sequenceDiagram-ZO4K6R2Y-FfOQAZol.js +169 -0
  216. package/renderer/dist/assets/sizeCapture-INFHLROL-C_n6fDBY.js +1 -0
  217. package/renderer/dist/assets/stateDiagram-v2-TBUQTH76-BZjenzJG.js +291 -0
  218. package/renderer/dist/assets/swimlanes-N4OXWK64-DxaMU9vX.js +1 -0
  219. package/renderer/dist/assets/swimlanesDiagram-K3J5GTZL-Cb2kM6rr.js +8 -0
  220. package/renderer/dist/assets/timeline-definition-YOQAKGHF-DTg5HJKz.js +120 -0
  221. package/renderer/dist/assets/usecaseDiagram-VIAY4XPW-Bc3MZDsl.js +370 -0
  222. package/renderer/dist/assets/vennDiagram-BLWOH2XV-GIVGk9Id.js +34 -0
  223. package/renderer/dist/assets/wardleyDiagram-YMQ3BMBF-NmJnbQOg.js +78 -0
  224. package/renderer/dist/assets/xychartDiagram-TAQBALBS-p-kfGfnW.js +7 -0
  225. package/renderer/dist/corner-tag.html +13 -0
  226. package/renderer/dist/emulator/audio-rules.mjs +74 -0
  227. package/renderer/dist/emulator/data/compression/README.md +11 -0
  228. package/renderer/dist/emulator/data/compression/extract7z.js +1 -0
  229. package/renderer/dist/emulator/data/compression/extractzip.js +1 -0
  230. package/renderer/dist/emulator/data/compression/libunrar.js +519 -0
  231. package/renderer/dist/emulator/data/compression/libunrar.wasm +0 -0
  232. package/renderer/dist/emulator/data/cores/README.md +22 -0
  233. package/renderer/dist/emulator/data/cores/mgba-legacy-wasm.data +0 -0
  234. package/renderer/dist/emulator/data/cores/mgba-thread-legacy-wasm.data +0 -0
  235. package/renderer/dist/emulator/data/cores/mgba-thread-wasm.data +0 -0
  236. package/renderer/dist/emulator/data/cores/mgba-wasm.data +0 -0
  237. package/renderer/dist/emulator/data/cores/package.json +65 -0
  238. package/renderer/dist/emulator/data/cores/reports/mgba.json +1 -0
  239. package/renderer/dist/emulator/data/emulator.css +1614 -0
  240. package/renderer/dist/emulator/data/loader.js +170 -0
  241. package/renderer/dist/emulator/data/localization/README.md +63 -0
  242. package/renderer/dist/emulator/data/localization/af-FR.json +339 -0
  243. package/renderer/dist/emulator/data/localization/ar-AR.json +301 -0
  244. package/renderer/dist/emulator/data/localization/ben-BEN.json +301 -0
  245. package/renderer/dist/emulator/data/localization/de-GER.json +301 -0
  246. package/renderer/dist/emulator/data/localization/el-GR.json +301 -0
  247. package/renderer/dist/emulator/data/localization/en-US.json +339 -0
  248. package/renderer/dist/emulator/data/localization/es-ES.json +310 -0
  249. package/renderer/dist/emulator/data/localization/fa-AF.json +310 -0
  250. package/renderer/dist/emulator/data/localization/hi-HI.json +301 -0
  251. package/renderer/dist/emulator/data/localization/it-IT.json +302 -0
  252. package/renderer/dist/emulator/data/localization/ja-JA.json +301 -0
  253. package/renderer/dist/emulator/data/localization/jv-JV.json +301 -0
  254. package/renderer/dist/emulator/data/localization/ko-KO.json +336 -0
  255. package/renderer/dist/emulator/data/localization/pt-BR.json +361 -0
  256. package/renderer/dist/emulator/data/localization/retroarch.json +617 -0
  257. package/renderer/dist/emulator/data/localization/ro-RO.json +310 -0
  258. package/renderer/dist/emulator/data/localization/ru-RU.json +301 -0
  259. package/renderer/dist/emulator/data/localization/tr-TR.json +310 -0
  260. package/renderer/dist/emulator/data/localization/vi-VN.json +302 -0
  261. package/renderer/dist/emulator/data/localization/zh-CN.json +351 -0
  262. package/renderer/dist/emulator/data/src/GameManager.js +464 -0
  263. package/renderer/dist/emulator/data/src/compression.js +142 -0
  264. package/renderer/dist/emulator/data/src/emulator.js +6158 -0
  265. package/renderer/dist/emulator/data/src/gamepad.js +167 -0
  266. package/renderer/dist/emulator/data/src/nipplejs.js +1 -0
  267. package/renderer/dist/emulator/data/src/shaders.js +236 -0
  268. package/renderer/dist/emulator/data/src/socket.io.min.js +7 -0
  269. package/renderer/dist/emulator/data/src/storage.js +125 -0
  270. package/renderer/dist/emulator/data/version.json +5 -0
  271. package/renderer/dist/emulator/host.js +297 -0
  272. package/renderer/dist/emulator/index.html +28 -0
  273. package/renderer/dist/emulator/provenance.json +6 -0
  274. package/renderer/dist/index.html +16 -3
  275. package/scripts/after-install.mjs +30 -8
  276. package/scripts/approval-server.sh +24 -5
  277. package/scripts/before-publish.mjs +12 -10
  278. package/scripts/cloud-shim.pl +57 -0
  279. package/shared/account-names.d.mts +6 -0
  280. package/shared/account-names.mjs +15 -0
  281. package/shared/agent-hours.mjs +136 -0
  282. package/shared/agent-import.mjs +62 -34
  283. package/shared/agents.d.mts +1 -0
  284. package/shared/agents.mjs +126 -522
  285. package/shared/analytics-events.mjs +12 -0
  286. package/shared/approval-card.mjs +36 -0
  287. package/shared/bridge-map.mjs +45 -1
  288. package/shared/claude-code-shape.mjs +6 -0
  289. package/shared/claude-commands.generated.mjs +6 -4
  290. package/shared/claude-models.generated.mjs +6 -4
  291. package/shared/claude-usage.d.mts +1 -0
  292. package/shared/claude-usage.mjs +42 -1
  293. package/shared/cloud-hand-back.d.mts +7 -0
  294. package/shared/cloud-hand-back.mjs +20 -0
  295. package/shared/cloud-kit.d.mts +219 -0
  296. package/shared/cloud-kit.mjs +341 -0
  297. package/shared/cloud-login-name.mjs +4 -0
  298. package/shared/cloud-start.mjs +17 -0
  299. package/shared/cloud-versions.mjs +23 -0
  300. package/shared/codex-import.mjs +2 -2
  301. package/shared/codex-modes.d.mts +22 -9
  302. package/shared/codex-modes.mjs +67 -11
  303. package/shared/codex-usage.mjs +108 -2
  304. package/shared/corner-tag.d.mts +36 -0
  305. package/shared/corner-tag.mjs +396 -0
  306. package/shared/dead-run-trace.mjs +19 -2
  307. package/shared/engines.mjs +76 -300
  308. package/shared/feedback.d.mts +7 -0
  309. package/shared/feedback.mjs +25 -0
  310. package/shared/first-run-practice.mjs +17 -24
  311. package/shared/harness-definitions.mjs +111 -0
  312. package/shared/instruction-defaults.json +2 -2
  313. package/shared/key-caps.d.mts +14 -0
  314. package/shared/key-caps.mjs +68 -0
  315. package/shared/message-edits.d.mts +7 -0
  316. package/shared/message-edits.mjs +35 -0
  317. package/shared/move-thread.d.mts +24 -0
  318. package/shared/move-thread.mjs +112 -0
  319. package/shared/named-threads.mjs +72 -0
  320. package/shared/not-shipped.d.mts +22 -0
  321. package/shared/not-shipped.mjs +89 -0
  322. package/shared/notify-rules.d.mts +31 -0
  323. package/shared/notify-rules.mjs +55 -8
  324. package/shared/phone-files.mjs +28 -0
  325. package/shared/phone-settings.mjs +118 -0
  326. package/shared/phone-snapshot.d.mts +16 -0
  327. package/shared/phone-snapshot.mjs +348 -0
  328. package/shared/picture-formats.d.mts +1 -0
  329. package/shared/picture-formats.mjs +13 -0
  330. package/shared/provider-commands.mjs +10 -2
  331. package/shared/rank.d.mts +4 -1
  332. package/shared/rank.mjs +82 -19
  333. package/shared/relay-address.mjs +6 -0
  334. package/shared/relay-crypto.mjs +165 -0
  335. package/shared/repeats.d.mts +8 -0
  336. package/shared/repeats.mjs +33 -2
  337. package/shared/room-cards.mjs +167 -0
  338. package/shared/room-links.d.mts +4 -0
  339. package/shared/room-links.mjs +21 -0
  340. package/shared/runs-on.d.mts +3 -13
  341. package/shared/runs-on.mjs +31 -52
  342. package/shared/shipped-note.d.mts +4 -0
  343. package/shared/shipped-note.mjs +6 -0
  344. package/shared/shortcuts.mjs +24 -10
  345. package/shared/spawn-trouble.d.mts +4 -0
  346. package/shared/spawn-trouble.mjs +484 -30
  347. package/shared/team-rules.mjs +9 -2
  348. package/shared/teammates.d.mts +19 -0
  349. package/shared/teammates.mjs +756 -0
  350. package/shared/terminal-focus.d.mts +1 -0
  351. package/shared/terminal-focus.mjs +13 -0
  352. package/shared/terminal-input.d.mts +1 -0
  353. package/shared/terminal-input.mjs +30 -0
  354. package/shared/terminal-keys.d.mts +1 -0
  355. package/shared/terminal-keys.mjs +16 -0
  356. package/shared/terminal-size.d.mts +4 -0
  357. package/shared/terminal-size.mjs +29 -0
  358. package/shared/thread-cards.mjs +4 -1
  359. package/shared/usage.d.mts +12 -0
  360. package/shared/usage.mjs +56 -3
  361. package/shared/websites.d.mts +15 -0
  362. package/shared/websites.mjs +61 -0
  363. package/shared/where-it-runs-from.d.mts +43 -0
  364. package/shared/where-it-runs-from.mjs +155 -0
  365. package/shared/work-items.mjs +150 -29
  366. package/shared/work-lines.mjs +93 -245
  367. package/shared/xterm-invalid-range.d.mts +2 -0
  368. package/shared/xterm-invalid-range.mjs +58 -0
  369. package/renderer/dist/assets/index-ChKsQkRw.js +0 -1169
  370. package/renderer/dist/assets/index-ClBXnq3B.css +0 -32
@@ -26,19 +26,41 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
26
26
 
27
27
  const require = createRequire(import.meta.url);
28
28
 
29
- // A checkout has scripts/linux-launcher.mjs next to this file. The published
30
- // package does not, so an npm install of that package, including npx, leaves
31
- // the launcher alone. A missing file is the ordinary case, not an error.
32
- const launcherPath = path.join(path.dirname(fileURLToPath(import.meta.url)), 'linux-launcher.mjs');
33
- if (fs.existsSync(launcherPath)) {
29
+ // A checkout has scripts/linux-launcher.mjs and scripts/link-own-bin.mjs next
30
+ // to this file. The published package carries neither, so an npm install of
31
+ // that package, including npx, leaves both alone. A missing file is the
32
+ // ordinary case here, not an error.
33
+ const here = path.dirname(fileURLToPath(import.meta.url));
34
+
35
+ async function fromCheckout(file) {
36
+ const at = path.join(here, file);
37
+ if (!fs.existsSync(at)) return null;
34
38
  try {
35
- const { installLinuxLauncher } = await import(pathToFileURL(launcherPath).href);
36
- installLinuxLauncher({ env: process.env });
39
+ return await import(pathToFileURL(at).href);
37
40
  } catch {
38
41
  // Nothing here is worth stopping an install for.
42
+ return null;
39
43
  }
40
44
  }
41
45
 
46
+ const launcher = await fromCheckout('linux-launcher.mjs');
47
+ if (launcher) {
48
+ const { changed, why } = launcher.installLinuxLauncher({ env: process.env });
49
+ if (changed) console.log('agentbox: this checkout is in the app launcher.');
50
+ // A launcher that did not happen says so. Before this, a fresh clone whose
51
+ // Electron binary was not downloaded yet got no launcher and no word about
52
+ // it, and `which agentbox` answered nothing.
53
+ else if (why) console.log(`agentbox: no app launcher was written: ${why}.`);
54
+ }
55
+
56
+ // And the checkout's own command, so `npx agentbox-app` from here starts the
57
+ // browser rather than looking for `agentbox` on PATH.
58
+ const own = await fromCheckout('link-own-bin.mjs');
59
+ if (own) {
60
+ const { why } = own.linkOwnBin();
61
+ if (why) console.log(`agentbox: \`npx agentbox-app\` will not work from this checkout: ${why}.`);
62
+ }
63
+
42
64
  function prebuildsDir() {
43
65
  // Resolve the package rather than guessing at ../node-pty: npm may have
44
66
  // hoisted it, nested it, or put it in a workspace root.
@@ -67,7 +89,7 @@ try {
67
89
  fs.chmodSync(helper, 0o755);
68
90
  fixed += 1;
69
91
  }
70
- if (fixed) console.log(`agentbox: made ${fixed} node-pty spawn-helper binary${fixed === 1 ? '' : 'ies'} executable, so the terminal works.`);
92
+ if (fixed) console.log(`agentbox: made ${fixed} node-pty spawn-helper binar${fixed === 1 ? 'y' : 'ies'} executable, so the terminal works.`);
71
93
  } catch {
72
94
  // Nothing here is worth stopping an install for.
73
95
  }
@@ -39,10 +39,29 @@ case "$here" in
39
39
  exec env ELECTRON_RUN_AS_NODE=1 "$app/MacOS/$exe" "$res/app.asar/main/approval-prompt-server.mjs"
40
40
  ;;
41
41
  *)
42
- # Running from source: node is nvm-only on this machine, and MCP servers
43
- # boot from a bare login shell, so resolve it the same way the store
44
- # launcher does.
45
- export PATH="$HOME/.nvm/versions/node/$(ls "$HOME/.nvm/versions/node" 2>/dev/null | tail -1)/bin:$PATH"
46
- exec node "$(cd "$here/.." && pwd)/main/approval-prompt-server.mjs"
42
+ # RUNNING FROM SOURCE, AND THIS LINE USED TO ASSUME NVM. It prepended
43
+ # $HOME/.nvm/versions/node/<newest>/bin and exec'd node. On a Mac that
44
+ # installed node by Homebrew, Volta, asdf or not at all, that folder is
45
+ # absent, PATH is untouched, and an MCP server booting from a bare login
46
+ # shell has no node on it: the exec failed and every agent died the same
47
+ # four-second death described at the top of this file. Reported from
48
+ # source on 2026-10-07 (issue 21).
49
+ #
50
+ # So the app hands its own binary down in ZERO_APPROVALS_RUNTIME, and
51
+ # ELECTRON_RUN_AS_NODE=1 makes that binary a node, exactly as the packaged
52
+ # branch above does. Nothing on the machine is needed.
53
+ server="$(cd "$here/.." && pwd)/main/approval-prompt-server.mjs"
54
+ if [ -f "$ZERO_APPROVALS_RUNTIME" ] && [ -x "$ZERO_APPROVALS_RUNTIME" ]; then
55
+ exec env ELECTRON_RUN_AS_NODE=1 "$ZERO_APPROVALS_RUNTIME" "$server"
56
+ fi
57
+ # Nobody handed one down, so this is somebody running the script by hand.
58
+ # A node already on PATH wins; nvm's newest is the last resort, for the
59
+ # bare login shell that has never sourced nvm.
60
+ if ! command -v node >/dev/null 2>&1; then
61
+ nvm="$HOME/.nvm/versions/node"
62
+ newest="$(ls "$nvm" 2>/dev/null | tail -1)"
63
+ [ -n "$newest" ] && export PATH="$nvm/$newest/bin:$PATH"
64
+ fi
65
+ exec node "$server"
47
66
  ;;
48
67
  esac
@@ -69,17 +69,19 @@ function wouldShip(changed) {
69
69
  // If npm cannot tell us, the honest answer is the cautious one.
70
70
  return changed;
71
71
  }
72
- // THE FILES THE PUBLISH ITSELF REWRITES, which would otherwise make every
73
- // attempt poison the next one. `prepack` runs `npm run build`, and the build
74
- // reads the installed Claude Code and writes what it found into
75
- // shared/*.generated.*. So a failed publish leaves those modified, and the
76
- // next publish refuses because of dirt the last publish made. Measured
77
- // 2026-09-28: one failed attempt left claude-models.generated.mjs changed by
78
- // a version number, and that alone blocked the retry.
72
+ // THE FILES A PUBLISH USED TO REWRITE, which made every attempt poison the
73
+ // next one. `prepack` runs `npm run build`, and the build read the installed
74
+ // Claude Code and wrote what it found over shared/*.generated.*. So a failed
75
+ // publish left those modified and the next publish refused because of dirt the
76
+ // last publish had made. Measured 2026-09-28: one failed attempt left
77
+ // claude-models.generated.mjs changed by a version number, and that alone
78
+ // blocked the retry.
79
79
  //
80
- // They are safe to ignore here BECAUSE the build rewrites them anyway. What
81
- // ships is whatever the build produces on the machine publishing, every time,
82
- // committed or not, so a difference in the working tree changes nothing.
80
+ // THE BUILD NO LONGER WRITES THEM (w-6bbb709b1f): it writes
81
+ // shared/*.local.json, which is gitignored, and `npm run read:claude` is what
82
+ // updates the committed tables. This filter stays as the belt for a folder an
83
+ // OLDER build already dirtied, and because what ships is whatever the build
84
+ // produces on the machine publishing, so a difference here changes nothing.
83
85
  return changed.filter((f) => packed.has(f) && !/\.generated\./.test(f));
84
86
  }
85
87
 
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/perl
2
+ # A CLOUD RUN, AS THE SUPERVISOR SEES IT: one small process standing in for a
3
+ # run whose relay lives in the shared host (main/cloud/host.mjs). It carries
4
+ # its input, output, signals and exit code there and back. Perl, because every
5
+ # Mac has it and a stand-in in it costs a few megabytes.
6
+ #
7
+ # cloud-shim.pl <host socket> <the relay's own arguments ...>
8
+ use strict;
9
+ use warnings;
10
+ use IO::Socket::UNIX;
11
+ use IO::Select;
12
+ use MIME::Base64 qw(encode_base64 decode_base64);
13
+ use JSON::PP;
14
+ use Cwd qw(getcwd);
15
+ use POSIX qw(:sys_wait_h);
16
+
17
+ my $sockpath = shift @ARGV;
18
+ # A host just started may take a moment to listen.
19
+ my $sock;
20
+ for (1 .. 50) { $sock = IO::Socket::UNIX->new(Type => SOCK_STREAM(), Peer => $sockpath); last if $sock; select(undef, undef, undef, 0.1); }
21
+ if (!$sock) { print STDERR "agentbox cloud: the cloud host is not running ($!)\n"; exit 75; }
22
+ binmode($sock); binmode(STDIN); binmode(STDOUT); binmode(STDERR);
23
+ $sock->autoflush(1);
24
+
25
+ sub put { my ($line) = @_; local $SIG{PIPE} = 'IGNORE'; print {$sock} "$line\n"; }
26
+
27
+ put(JSON::PP->new->canonical->encode({ argv => [@ARGV], env => {%ENV}, cwd => getcwd(), pid => $$ }));
28
+ for my $sig (qw(TERM INT HUP)) { $SIG{$sig} = sub { put("k SIG$sig"); }; }
29
+
30
+ my $sel = IO::Select->new($sock, \*STDIN);
31
+ my ($buf, $code, $parent, $orphaned) = ('', undef, getppid(), 0);
32
+ while (1) {
33
+ my @ready = $sel->can_read(1);
34
+ # The app gone without a word: the run is left going, as on a quit.
35
+ if (!$orphaned && getppid() != $parent) { $orphaned = 1; put('k SIGHUP'); }
36
+ for my $fh (@ready) {
37
+ if ($fh == $sock) {
38
+ my $n = sysread($sock, my $chunk, 65536);
39
+ if (!defined $n) { next if $!{EINTR}; $n = 0; }
40
+ if (!$n) { exit(defined $code ? $code : 75); }
41
+ $buf .= $chunk;
42
+ while ((my $i = index($buf, "\n")) >= 0) {
43
+ my $line = substr($buf, 0, $i);
44
+ $buf = substr($buf, $i + 1);
45
+ my ($tag, $rest) = (substr($line, 0, 1), substr($line, 2));
46
+ if ($tag eq 'o') { my $d = decode_base64($rest); my $off = 0; while ($off < length $d) { my $w = syswrite(STDOUT, $d, length($d) - $off, $off); last unless defined $w; $off += $w; } }
47
+ elsif ($tag eq 'e') { my $d = decode_base64($rest); syswrite(STDERR, $d); }
48
+ elsif ($tag eq 'x') { $code = int($rest); }
49
+ }
50
+ } else {
51
+ my $n = sysread(STDIN, my $chunk, 65536);
52
+ if (!defined $n) { next if $!{EINTR}; $n = 0; }
53
+ if (!$n) { put('I'); $sel->remove(\*STDIN); }
54
+ else { put('i ' . encode_base64($chunk, '')); }
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,6 @@
1
+ export declare function accountName(account?: {
2
+ email?: string | null;
3
+ engine?: string;
4
+ index?: number;
5
+ total?: number;
6
+ }): string;
@@ -0,0 +1,15 @@
1
+ // WHAT ONE LOGIN IS CALLED, in the one rule both sides read: the Settings
2
+ // page, which has named accounts by their email since it had rows, and the
3
+ // sentence a thread gets when a login runs out, which had no name for one at
4
+ // all until w-e1a42f6b21.
5
+
6
+ /**
7
+ * @param {{ email?: string | null, engine?: string, index?: number, total?: number }} account
8
+ * `index` is its place among that engine's accounts, `total` how many there
9
+ * are: one account is not counted, because the number would mean nothing.
10
+ */
11
+ export function accountName({ email = null, engine = 'claude', index = 0, total = 1 } = {}) {
12
+ if (email) return email;
13
+ const word = engine === 'codex' ? 'Codex' : 'Claude';
14
+ return `${word} account${total > 1 ? ` ${index + 1}` : ''}`;
15
+ }
@@ -0,0 +1,136 @@
1
+ // AGENT HOURS: the level, the week, the streak (w-3d0fa23ffb).
2
+ //
3
+ // Pure. A run is `{key, at, start, item, product, engine, seconds, failed,
4
+ // began}`: `at` is when it ended, and a run is counted on the local day it
5
+ // ended. Every run whose agent actually began counts its wall time, failed or
6
+ // not, and overlapping runs each count.
7
+
8
+ export const MASTERY_HOURS = 10_000;
9
+ const MAX_RUN_SECONDS = 24 * 3600;
10
+ const DAY_MS = 86_400_000;
11
+
12
+ // Up to 99, hours grow as level^2.5: level 2 in minutes, 99 at MASTERY_HOURS.
13
+ // Not RuneScape's curve, which spends half its hours on the last seven levels
14
+ // and so reads 82 after one heavy month. Past 99 there is no ceiling and each
15
+ // level costs 5% more than the last, starting from the curve's pace at 99 so
16
+ // no level ever costs less than the one before.
17
+ const RISE = 2.5;
18
+ const PAST = Math.log(1.05);
19
+ const PACE_AT_99 = (MASTERY_HOURS * RISE) / 98;
20
+ // A level starts at its exact hours, not one float step later.
21
+ const EPS = 1e-10;
22
+
23
+ export function hoursForLevel(level) {
24
+ const L = Number(level);
25
+ if (!(L > 1)) return 0;
26
+ if (L <= 99) return MASTERY_HOURS * ((L - 1) / 98) ** RISE;
27
+ return MASTERY_HOURS + (PACE_AT_99 * Math.expm1((L - 99) * PAST)) / PAST;
28
+ }
29
+
30
+ export function levelFor(hours) {
31
+ const h = Number(hours);
32
+ if (!Number.isFinite(h) || h <= 0) return 1;
33
+ if (h < MASTERY_HOURS) return 1 + Math.floor(98 * (h / MASTERY_HOURS) ** (1 / RISE) + EPS);
34
+ return 99 + Math.floor(Math.log1p(((h - MASTERY_HOURS) * PAST) / PACE_AT_99) / PAST + EPS);
35
+ }
36
+
37
+ const pad = (n) => String(n).padStart(2, '0');
38
+ export const localDate = (ms) => { const d = new Date(ms); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; };
39
+ const localMonth = (ms) => localDate(ms).slice(0, 7);
40
+
41
+ function mondayOf(ms) {
42
+ const d = new Date(ms);
43
+ d.setHours(0, 0, 0, 0);
44
+ d.setDate(d.getDate() - ((d.getDay() + 6) % 7));
45
+ return d.getTime();
46
+ }
47
+
48
+ function startOfDay(ms) {
49
+ const d = new Date(ms);
50
+ d.setHours(0, 0, 0, 0);
51
+ return d.getTime();
52
+ }
53
+
54
+ const counts = (r) => r && r.began !== false && Number.isFinite(r.at) && Number(r.seconds) > 0;
55
+
56
+ // One line per key. The line written when the run ended beats one read back
57
+ // from its log, which may have been read while the run was still going.
58
+ export function dedupeRuns(runs) {
59
+ const seen = new Map();
60
+ for (const r of runs ?? []) {
61
+ if (!r || typeof r !== 'object' || typeof r.key !== 'string' || !r.key) continue;
62
+ if (!Number.isFinite(r.at) || !(Number(r.seconds) > 0)) continue;
63
+ const had = seen.get(r.key);
64
+ if (!had || (had.backfilled && !r.backfilled)) seen.set(r.key, r);
65
+ }
66
+ return [...seen.values()];
67
+ }
68
+
69
+ // Days in a row with a run, counted back from today, or from yesterday when
70
+ // today has none yet. `dates` are local YYYY-MM-DD strings, from any number of
71
+ // Macs.
72
+ export function streakOf(dates, now = Date.now()) {
73
+ const have = new Set(dates);
74
+ let cursor = startOfDay(now);
75
+ if (!have.has(localDate(cursor))) cursor -= DAY_MS / 2;
76
+ let n = 0;
77
+ while (have.has(localDate(cursor))) {
78
+ n += 1;
79
+ // Half a day back and then to the start of that day survives a DST change.
80
+ cursor = startOfDay(startOfDay(cursor) - DAY_MS / 2);
81
+ }
82
+ return n;
83
+ }
84
+
85
+ export function summarizeRuns(runs, { now = Date.now() } = {}) {
86
+ const weekStartMs = mondayOf(now);
87
+ const dayStartMs = startOfDay(now);
88
+ let total = 0;
89
+ let week = 0;
90
+ let today = 0;
91
+ const active = new Set();
92
+ const months = new Map();
93
+ const first = new Date(now);
94
+ first.setDate(1);
95
+ for (let i = 11; i >= 0; i -= 1) {
96
+ const d = new Date(first.getFullYear(), first.getMonth() - i, 1);
97
+ months.set(`${d.getFullYear()}-${pad(d.getMonth() + 1)}`, 0);
98
+ }
99
+ for (const r of dedupeRuns(runs)) {
100
+ if (!counts(r) || r.at > now) continue;
101
+ const h = Math.min(Number(r.seconds), MAX_RUN_SECONDS) / 3600;
102
+ total += h;
103
+ if (r.at >= weekStartMs) week += h;
104
+ if (r.at >= dayStartMs) today += h;
105
+ active.add(localDate(r.at));
106
+ const m = localMonth(r.at);
107
+ if (months.has(m)) months.set(m, months.get(m) + h);
108
+ }
109
+ const activeDays = [...active].sort().slice(-60);
110
+ return {
111
+ total,
112
+ week,
113
+ weekStart: localDate(weekStartMs),
114
+ today,
115
+ day: localDate(dayStartMs),
116
+ streak: streakOf(activeDays, now),
117
+ activeDays,
118
+ byMonth: [...months].map(([month, hours]) => ({ month, hours })),
119
+ level: levelFor(total),
120
+ };
121
+ }
122
+
123
+ // One run read back from its trace log, `sessions/<item>/<startedAtMs>.log`:
124
+ // the start is the file's name, the end the `# exited (code) <ISO>` footer,
125
+ // else the file's last write.
126
+ export function runFromTrace({ name, text = '', mtimeMs, item, product }) {
127
+ const m = /^(\d{12,14})\.log$/.exec(String(name ?? ''));
128
+ if (!m) return null;
129
+ const start = Number(m[1]);
130
+ const footer = /# exited \((-?\d+|null)\) (\S+)(?: · [^\n]*)?\s*$/m.exec(String(text));
131
+ const end = footer ? Date.parse(footer[2]) : Number(mtimeMs);
132
+ if (!Number.isFinite(end) || end <= start) return null;
133
+ const seconds = Math.round((end - start) / 1000);
134
+ if (seconds > MAX_RUN_SECONDS) return null;
135
+ return { key: `${item}:${start}`, at: end, start, item, product, engine: null, seconds, failed: footer ? footer[1] !== '0' : null };
136
+ }
@@ -18,7 +18,7 @@
18
18
  /**
19
19
  * The label every one of these rows carries, so a second walk through the
20
20
  * first run can tell which agents already have a row and file nothing twice. */
21
- import { NAME, Name } from '../shared/product-name.mjs';
21
+ import { NAME } from '../shared/product-name.mjs';
22
22
  export const IMPORT_LABEL = 'agent-import';
23
23
 
24
24
  /**
@@ -107,11 +107,11 @@ export function agentsNeedingRows(chosen, existingItems = []) {
107
107
  }
108
108
 
109
109
  /* --------------------------- AND THE THREADS ----------------------------- */
110
- // Of the three things a picked thread could do, this is the plainest one. It
111
- // does NOT resume the conversation, and that is the half these words have to
112
- // carry, because a row named after an earlier conversation is a row anybody
113
- // would assume was carrying it on. So the body says, in plain words, that this
114
- // starts fresh.
110
+ // A picked thread becomes a row that carries the conversation on. It first
111
+ // did not: the body said the reply started fresh, and somebody importing a
112
+ // hundred half-finished sessions was asked to restate every one of them
113
+ // (GitHub #44). The row is still only a row here; the resume happens on the
114
+ // first reply, in `Supervisor#importedThreadFor`.
115
115
  //
116
116
  // Everything else is the agent import's shape, for the same reasons: one row per
117
117
  // thing the user ticked, a label so a second press files nothing twice, and a
@@ -125,6 +125,53 @@ export const THREAD_LABEL = 'thread-import';
125
125
  * which is stable across renames and is what the transcript is filed under. */
126
126
  export const threadLabel = (id) => `thread:${String(id ?? '').trim()}`;
127
127
 
128
+ /**
129
+ * WHETHER A CHAT ENDED WAITING ON YOU, read off the agent's last reply.
130
+ *
131
+ * Waiting means the reply's last line is a question, or a question followed by
132
+ * the choices it offers. `ask` is that question, cut from the front when it is
133
+ * long, because the question is at the end of the line. */
134
+ const ASK_CHARS = 140;
135
+ const SHORT_ASK = 40;
136
+ const CHOICE = /^(\d+[.)]|[-*+]|[a-z][.)])\s+/i;
137
+ const NOT_WAITING = Object.freeze({ waiting: false, ask: '' });
138
+
139
+ function plainLine(line) {
140
+ return String(line)
141
+ .replace(/^(>\s*)+/, '')
142
+ .replace(/^#{1,6}\s+/, '')
143
+ .replace(/[*`]+/g, '')
144
+ // An underscore between two letters is part of a name (account_id).
145
+ .replace(/(?<![A-Za-z0-9])_+|_+(?![A-Za-z0-9])/g, '')
146
+ .replace(/^[("'“‘\s]+/, '')
147
+ .replace(/[)"'”’\s]+$/, '')
148
+ .trim();
149
+ }
150
+
151
+ function shortAsk(line) {
152
+ if (line.length <= ASK_CHARS) return line;
153
+ const sentences = line.split(/(?<=[.!?])\s+/);
154
+ let last = sentences.pop();
155
+ // "Shall I do that?" says nothing without the sentence it follows.
156
+ while (last.length < SHORT_ASK && sentences.length && sentences.at(-1).length + 1 + last.length <= ASK_CHARS) {
157
+ last = `${sentences.pop()} ${last}`;
158
+ }
159
+ if (last.length <= ASK_CHARS) return last;
160
+ const tail = line.slice(-(ASK_CHARS - 1));
161
+ const sp = tail.indexOf(' ');
162
+ return `…${sp > 0 && sp < 40 ? tail.slice(sp + 1) : tail}`;
163
+ }
164
+
165
+ export function howTheChatEnded(said) {
166
+ const lines = String(said ?? '').replace(/\r/g, '').split('\n').map((l) => l.trim()).filter(Boolean);
167
+ let i = lines.length - 1;
168
+ while (i >= 0 && CHOICE.test(lines[i])) i -= 1;
169
+ if (i < 0) return { ...NOT_WAITING };
170
+ const line = plainLine(lines[i].replace(CHOICE, ''));
171
+ if (!line.endsWith('?')) return { ...NOT_WAITING };
172
+ return { waiting: true, ask: shortAsk(line) };
173
+ }
174
+
128
175
  /**
129
176
  * WHEN SHE HAD IT, in the words a person uses about this week.
130
177
  *
@@ -148,41 +195,22 @@ export function whenWords(when, now = Date.now()) {
148
195
  /** Where she was when she started it, in the two places she named. */
149
196
  export function startedIn(source) {
150
197
  if (source === 'codex') return 'in Codex';
198
+ // VS Code, Cursor or Windsurf: the extension says which family, not which one.
199
+ if (source === 'editor') return 'in your code editor';
151
200
  return source === 'desktop' ? 'in the Claude Code desktop app' : 'in a terminal';
152
201
  }
153
202
 
154
203
  /**
155
- * ONE IMPORTED THREAD'S WORDS.
156
- *
157
- * The title is the thread's own, which is the first thing the user typed into
158
- * it, so the row in the inbox is called what they would call it. Ours is not
159
- * added in front of it: a list of rows all opening with the same three words is
160
- * a list that has to be read past to find which is which.
161
- *
162
- * The last paragraph is the honest one. Agentbox read the top of the transcript
163
- * to find this name and nothing else, and the reply starts a fresh session. A
164
- * row that let her believe otherwise would be the same empty promise the agent
165
- * import had before 08-23, in a new place. */
166
- export function threadImportRow(thread, { projectName = null, now = Date.now() } = {}) {
204
+ * ONE IMPORTED THREAD'S WORDS, the chat as it was: the title Claude Code gave
205
+ * it, your first message as the body and the agent's last reply as the
206
+ * result, so the thread opens on the question it ended with. The reply
207
+ * carries the conversation on (`Supervisor#importedThreadFor`). */
208
+ export function threadImportRow(thread) {
167
209
  const title = String(thread?.title || '').trim();
168
- const where = String(thread?.short || thread?.folder || '').trim();
169
- const when = whenWords(thread?.when, now);
170
- const started = [
171
- 'You started this',
172
- startedIn(thread?.source),
173
- when,
174
- where ? `in ${where}` : '',
175
- ].filter(Boolean).join(' ');
176
- const inProject = projectName ? ` here in ${projectName}` : '';
177
- const body = [
178
- '**Say what you want done next in this thread.**',
179
- `${started}.`,
180
- `Reply with the job and ${NAME} runs it${inProject}, answering you here.`,
181
- `${Name} has not read the conversation, only the line above that names it, and replying starts a fresh session rather than carrying the old one on. So say what you need in the reply.`,
182
- ].join('\n\n');
183
210
  return {
184
211
  title,
185
- body,
212
+ body: String(thread?.firstSaid || '').trim() || title,
213
+ result: String(thread?.lastSaid || '').trim(),
186
214
  kind: 'question',
187
215
  priority: 3,
188
216
  labels: [THREAD_LABEL, threadLabel(thread?.id)],
@@ -110,6 +110,7 @@ export interface AgentTurnLike {
110
110
  // ONE THING THE AGENT RAN, between two messages. Shape B.
111
111
  export interface AgentWorkLike {
112
112
  kind: 'work';
113
+ standalone?: true;
113
114
  at: number;
114
115
  verb: string;
115
116
  subject: string;