aimux-cli 0.1.16 → 0.1.19

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 (357) hide show
  1. package/README.md +184 -67
  2. package/bin/aimux-dev +10 -0
  3. package/dist/agent-events.js +0 -1
  4. package/dist/agent-output-parser.js +0 -1
  5. package/dist/agent-prompt-delivery.js +0 -1
  6. package/dist/agent-tracker.js +0 -1
  7. package/dist/agent-watcher.js +0 -1
  8. package/dist/alert-display.d.ts +21 -0
  9. package/dist/alert-display.js +85 -0
  10. package/dist/atomic-write.js +0 -1
  11. package/dist/attachment-store.d.ts +0 -7
  12. package/dist/attachment-store.js +2 -87
  13. package/dist/builtin-metadata-watchers.js +4 -5
  14. package/dist/claude-hooks.d.ts +1 -0
  15. package/dist/claude-hooks.js +25 -1
  16. package/dist/config.d.ts +19 -13
  17. package/dist/config.js +28 -15
  18. package/dist/connection-targets.d.ts +8 -0
  19. package/dist/connection-targets.js +27 -0
  20. package/dist/context/compactor.js +0 -1
  21. package/dist/context/context-bridge.js +0 -1
  22. package/dist/context/context-file.js +0 -1
  23. package/dist/context/history.js +0 -1
  24. package/dist/credentials.d.ts +12 -0
  25. package/dist/credentials.js +48 -0
  26. package/dist/daemon.d.ts +23 -0
  27. package/dist/daemon.js +391 -67
  28. package/dist/dashboard/command-spec.js +0 -1
  29. package/dist/dashboard/feedback.js +0 -1
  30. package/dist/dashboard/index.d.ts +13 -10
  31. package/dist/dashboard/index.js +3 -27
  32. package/dist/dashboard/operation-failures.js +0 -1
  33. package/dist/dashboard/order.d.ts +22 -0
  34. package/dist/dashboard/order.js +54 -0
  35. package/dist/dashboard/pending-actions.d.ts +39 -10
  36. package/dist/dashboard/pending-actions.js +166 -37
  37. package/dist/dashboard/quick-jump.d.ts +2 -1
  38. package/dist/dashboard/quick-jump.js +7 -5
  39. package/dist/dashboard/runtime-evidence.js +0 -1
  40. package/dist/dashboard/session-actions.d.ts +4 -4
  41. package/dist/dashboard/session-actions.js +1 -2
  42. package/dist/dashboard/session-registry.d.ts +4 -3
  43. package/dist/dashboard/session-registry.js +16 -51
  44. package/dist/dashboard/sort.js +0 -1
  45. package/dist/dashboard/state.d.ts +1 -1
  46. package/dist/dashboard/state.js +0 -1
  47. package/dist/dashboard/targets.js +0 -1
  48. package/dist/dashboard/ui-state-store.d.ts +16 -1
  49. package/dist/dashboard/ui-state-store.js +73 -3
  50. package/dist/debug-state.d.ts +97 -0
  51. package/dist/debug-state.js +540 -0
  52. package/dist/debug.d.ts +38 -0
  53. package/dist/debug.js +219 -16
  54. package/dist/default-plugins/gh-pr-context.d.ts +2 -1
  55. package/dist/default-plugins/gh-pr-context.js +17 -12
  56. package/dist/default-plugins/transcript-length.js +15 -3
  57. package/dist/fast-control.js +37 -20
  58. package/dist/hotkeys.js +0 -1
  59. package/dist/http-client.js +31 -3
  60. package/dist/key-parser.js +0 -1
  61. package/dist/last-used.js +0 -1
  62. package/dist/local-ui-server.d.ts +22 -0
  63. package/dist/local-ui-server.js +185 -0
  64. package/dist/login-flow.d.ts +7 -0
  65. package/dist/login-flow.js +119 -0
  66. package/dist/main.js +821 -152
  67. package/dist/managed-launch-env.js +14 -1
  68. package/dist/metadata-server.d.ts +36 -36
  69. package/dist/metadata-server.js +638 -138
  70. package/dist/metadata-store.d.ts +4 -1
  71. package/dist/metadata-store.js +30 -3
  72. package/dist/multiplexer/agent-io-methods.d.ts +2 -10
  73. package/dist/multiplexer/agent-io-methods.js +12 -44
  74. package/dist/multiplexer/archives.js +8 -10
  75. package/dist/multiplexer/dashboard-actions-methods.js +0 -1
  76. package/dist/multiplexer/dashboard-control.js +45 -14
  77. package/dist/multiplexer/dashboard-interaction.d.ts +8 -2
  78. package/dist/multiplexer/dashboard-interaction.js +187 -29
  79. package/dist/multiplexer/dashboard-model.d.ts +10 -3
  80. package/dist/multiplexer/dashboard-model.js +417 -36
  81. package/dist/multiplexer/dashboard-ops.d.ts +9 -7
  82. package/dist/multiplexer/dashboard-ops.js +178 -69
  83. package/dist/multiplexer/dashboard-state-methods.d.ts +2 -1
  84. package/dist/multiplexer/dashboard-state-methods.js +3 -3
  85. package/dist/multiplexer/dashboard-tail-methods.d.ts +22 -10
  86. package/dist/multiplexer/dashboard-tail-methods.js +164 -48
  87. package/dist/multiplexer/dashboard-view-methods.d.ts +1 -1
  88. package/dist/multiplexer/dashboard-view-methods.js +23 -9
  89. package/dist/multiplexer/graveyard-view-model.d.ts +9 -1
  90. package/dist/multiplexer/graveyard-view-model.js +39 -1
  91. package/dist/multiplexer/index.d.ts +15 -12
  92. package/dist/multiplexer/index.js +64 -44
  93. package/dist/multiplexer/navigation.js +0 -1
  94. package/dist/multiplexer/notifications.js +107 -25
  95. package/dist/multiplexer/persistence-methods.d.ts +31 -4
  96. package/dist/multiplexer/persistence-methods.js +304 -309
  97. package/dist/multiplexer/runtime-lifecycle-methods.d.ts +8 -10
  98. package/dist/multiplexer/runtime-lifecycle-methods.js +104 -87
  99. package/dist/multiplexer/runtime-state.d.ts +8 -10
  100. package/dist/multiplexer/runtime-state.js +82 -146
  101. package/dist/multiplexer/runtime-sync.d.ts +2 -10
  102. package/dist/multiplexer/runtime-sync.js +3 -19
  103. package/dist/multiplexer/service-state-snapshot.d.ts +2 -4
  104. package/dist/multiplexer/service-state-snapshot.js +4 -52
  105. package/dist/multiplexer/services.d.ts +1 -0
  106. package/dist/multiplexer/services.js +55 -6
  107. package/dist/multiplexer/session-capture.d.ts +1 -0
  108. package/dist/multiplexer/session-capture.js +23 -0
  109. package/dist/multiplexer/session-launch.d.ts +4 -1
  110. package/dist/multiplexer/session-launch.js +152 -64
  111. package/dist/multiplexer/session-runtime-core.d.ts +8 -20
  112. package/dist/multiplexer/session-runtime-core.js +40 -136
  113. package/dist/multiplexer/subscreens.js +10 -4
  114. package/dist/multiplexer/tool-picker.js +0 -1
  115. package/dist/multiplexer/worktree-graveyard.d.ts +0 -1
  116. package/dist/multiplexer/worktree-graveyard.js +15 -17
  117. package/dist/multiplexer/worktrees.js +96 -41
  118. package/dist/notification-context.js +8 -5
  119. package/dist/notifications.js +163 -102
  120. package/dist/notify.d.ts +4 -0
  121. package/dist/notify.js +14 -1
  122. package/dist/orchestration-actions.js +0 -1
  123. package/dist/orchestration-routing.js +0 -1
  124. package/dist/orchestration.js +0 -1
  125. package/dist/osc-notifications.js +0 -1
  126. package/dist/paths.d.ts +32 -7
  127. package/dist/paths.js +82 -59
  128. package/dist/pending-actions.d.ts +5 -0
  129. package/dist/pending-actions.js +13 -0
  130. package/dist/plugin-runtime.js +9 -3
  131. package/dist/project-events.d.ts +1 -10
  132. package/dist/project-events.js +0 -11
  133. package/dist/project-scanner.d.ts +2 -3
  134. package/dist/project-scanner.js +58 -130
  135. package/dist/project-service-manifest.d.ts +1 -3
  136. package/dist/project-service-manifest.js +1 -4
  137. package/dist/recency.js +0 -1
  138. package/dist/recorder.js +0 -1
  139. package/dist/relay-client.d.ts +30 -0
  140. package/dist/relay-client.js +190 -0
  141. package/dist/remote-access.d.ts +16 -0
  142. package/dist/remote-access.js +90 -0
  143. package/dist/runtime-core/exchange-derived.d.ts +2 -0
  144. package/dist/runtime-core/exchange-derived.js +153 -0
  145. package/dist/runtime-core/exchange-import.d.ts +24 -0
  146. package/dist/runtime-core/exchange-import.js +317 -0
  147. package/dist/runtime-core/exchange-store.d.ts +157 -0
  148. package/dist/runtime-core/exchange-store.js +452 -0
  149. package/dist/runtime-core/topology-services.d.ts +38 -0
  150. package/dist/runtime-core/topology-services.js +170 -0
  151. package/dist/runtime-core/topology-sessions.d.ts +52 -0
  152. package/dist/runtime-core/topology-sessions.js +238 -0
  153. package/dist/runtime-core/topology-store.d.ts +171 -0
  154. package/dist/runtime-core/topology-store.js +419 -0
  155. package/dist/runtime-core/topology-worktrees.d.ts +60 -0
  156. package/dist/runtime-core/topology-worktrees.js +199 -0
  157. package/dist/runtime-migration.d.ts +69 -0
  158. package/dist/runtime-migration.js +398 -0
  159. package/dist/session-bootstrap.d.ts +8 -6
  160. package/dist/session-bootstrap.js +51 -159
  161. package/dist/session-runtime.d.ts +2 -0
  162. package/dist/session-runtime.js +1 -1
  163. package/dist/session-semantics.d.ts +12 -4
  164. package/dist/session-semantics.js +14 -1
  165. package/dist/shell-args.js +0 -1
  166. package/dist/shell-hooks.js +32 -11
  167. package/dist/shell-state.d.ts +2 -0
  168. package/dist/shell-state.js +26 -2
  169. package/dist/status-detector.js +0 -1
  170. package/dist/statusline-model.d.ts +10 -2
  171. package/dist/statusline-model.js +106 -31
  172. package/dist/task-workflow.d.ts +6 -9
  173. package/dist/task-workflow.js +37 -85
  174. package/dist/tasks.d.ts +6 -33
  175. package/dist/tasks.js +46 -89
  176. package/dist/team.d.ts +29 -0
  177. package/dist/team.js +40 -1
  178. package/dist/terminal-host.js +0 -1
  179. package/dist/threads.d.ts +6 -35
  180. package/dist/threads.js +89 -99
  181. package/dist/tmux/doctor.js +0 -1
  182. package/dist/tmux/inbox-popup.js +37 -16
  183. package/dist/tmux/runtime-manager.d.ts +3 -0
  184. package/dist/tmux/runtime-manager.js +21 -5
  185. package/dist/tmux/session-transport.js +0 -1
  186. package/dist/tmux/statusline-cache.js +0 -1
  187. package/dist/tmux/statusline.js +49 -10
  188. package/dist/tmux/switcher.js +0 -1
  189. package/dist/tmux/window-open.js +1 -3
  190. package/dist/tool-output-watchers.d.ts +0 -18
  191. package/dist/tool-output-watchers.js +0 -323
  192. package/dist/tui/render/box.js +0 -1
  193. package/dist/tui/render/text.js +0 -1
  194. package/dist/tui/screens/dashboard-renderers.js +37 -26
  195. package/dist/tui/screens/overlay-renderers.d.ts +2 -0
  196. package/dist/tui/screens/overlay-renderers.js +37 -2
  197. package/dist/tui/screens/subscreen-renderers.js +7 -1
  198. package/dist/workflow.js +0 -1
  199. package/dist/worktree.js +17 -1
  200. package/dist-ui/_expo/static/css/web-30453ede1678c16acb08b97e83e8646d.css +1 -0
  201. package/dist-ui/_expo/static/js/web/entry-477c745b2adc79367a4380ecf07d9ff6.js +14620 -0
  202. package/dist-ui/assets/assets/images/icon.a5413dcd2e811c9f2317d01a28118d8a.png +0 -0
  203. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/back-icon-mask.0a328cd9c1afd0afe8e3b1ec5165b1b4.png +0 -0
  204. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/back-icon.35ba0eaec5a4f5ed12ca16fabeae451d.png +0 -0
  205. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55.png +0 -0
  206. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@2x.png +0 -0
  207. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@3x.png +0 -0
  208. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/clear-icon.c94f6478e7ae0cdd9f15de1fcb9e5e55@4x.png +0 -0
  209. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7.png +0 -0
  210. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@2x.png +0 -0
  211. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@3x.png +0 -0
  212. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/close-icon.808e1b1b9b53114ec2838071a7e6daa7@4x.png +0 -0
  213. package/dist-ui/assets/node_modules/@react-navigation/elements/lib/module/assets/search-icon.286d67d3f74808a60a78d3ebf1a5fb57.png +0 -0
  214. package/dist-ui/assets/node_modules/expo-router/assets/arrow_down.017bc6ba3fc25503e5eb5e53826d48a8.png +0 -0
  215. package/dist-ui/assets/node_modules/expo-router/assets/error.d1ea1496f9057eb392d5bbf3732a61b7.png +0 -0
  216. package/dist-ui/assets/node_modules/expo-router/assets/file.19eeb73b9593a38f8e9f418337fc7d10.png +0 -0
  217. package/dist-ui/assets/node_modules/expo-router/assets/forward.d8b800c443b8972542883e0b9de2bdc6.png +0 -0
  218. package/dist-ui/assets/node_modules/expo-router/assets/pkg.ab19f4cbc543357183a20571f68380a3.png +0 -0
  219. package/dist-ui/assets/node_modules/expo-router/assets/sitemap.412dd9275b6b48ad28f5e3d81bb1f626.png +0 -0
  220. package/dist-ui/assets/node_modules/expo-router/assets/unmatched.20e71bdf79e3a97bf55fd9e164041578.png +0 -0
  221. package/dist-ui/favicon.ico +0 -0
  222. package/dist-ui/index.html +38 -0
  223. package/dist-ui/metadata.json +1 -0
  224. package/package.json +29 -12
  225. package/dist/agent-events.js.map +0 -1
  226. package/dist/agent-message-parts.d.ts +0 -17
  227. package/dist/agent-message-parts.js +0 -31
  228. package/dist/agent-message-parts.js.map +0 -1
  229. package/dist/agent-output-parser.js.map +0 -1
  230. package/dist/agent-prompt-delivery.js.map +0 -1
  231. package/dist/agent-tracker.js.map +0 -1
  232. package/dist/agent-watcher.js.map +0 -1
  233. package/dist/atomic-write.js.map +0 -1
  234. package/dist/attachment-store.js.map +0 -1
  235. package/dist/builtin-metadata-watchers.js.map +0 -1
  236. package/dist/claude-hooks.js.map +0 -1
  237. package/dist/config.js.map +0 -1
  238. package/dist/context/compactor.js.map +0 -1
  239. package/dist/context/context-bridge.js.map +0 -1
  240. package/dist/context/context-file.js.map +0 -1
  241. package/dist/context/history.js.map +0 -1
  242. package/dist/daemon.js.map +0 -1
  243. package/dist/dashboard/command-spec.js.map +0 -1
  244. package/dist/dashboard/feedback.js.map +0 -1
  245. package/dist/dashboard/index.js.map +0 -1
  246. package/dist/dashboard/operation-failures.js.map +0 -1
  247. package/dist/dashboard/pending-actions.js.map +0 -1
  248. package/dist/dashboard/quick-jump.js.map +0 -1
  249. package/dist/dashboard/runtime-evidence.js.map +0 -1
  250. package/dist/dashboard/session-actions.js.map +0 -1
  251. package/dist/dashboard/session-registry.js.map +0 -1
  252. package/dist/dashboard/sort.js.map +0 -1
  253. package/dist/dashboard/state.js.map +0 -1
  254. package/dist/dashboard/targets.js.map +0 -1
  255. package/dist/dashboard/ui-state-store.js.map +0 -1
  256. package/dist/debug.js.map +0 -1
  257. package/dist/default-plugins/gh-pr-context.js.map +0 -1
  258. package/dist/default-plugins/transcript-length.js.map +0 -1
  259. package/dist/fast-control.js.map +0 -1
  260. package/dist/hotkeys.js.map +0 -1
  261. package/dist/http-client.js.map +0 -1
  262. package/dist/instance-directory.d.ts +0 -32
  263. package/dist/instance-directory.js +0 -82
  264. package/dist/instance-directory.js.map +0 -1
  265. package/dist/instance-registry.d.ts +0 -39
  266. package/dist/instance-registry.js +0 -208
  267. package/dist/instance-registry.js.map +0 -1
  268. package/dist/key-parser.js.map +0 -1
  269. package/dist/last-used.js.map +0 -1
  270. package/dist/main.js.map +0 -1
  271. package/dist/managed-launch-env.js.map +0 -1
  272. package/dist/metadata-server.js.map +0 -1
  273. package/dist/metadata-store.js.map +0 -1
  274. package/dist/multiplexer/agent-io-methods.js.map +0 -1
  275. package/dist/multiplexer/archives.js.map +0 -1
  276. package/dist/multiplexer/dashboard-actions-methods.js.map +0 -1
  277. package/dist/multiplexer/dashboard-control.js.map +0 -1
  278. package/dist/multiplexer/dashboard-interaction.js.map +0 -1
  279. package/dist/multiplexer/dashboard-model.js.map +0 -1
  280. package/dist/multiplexer/dashboard-ops.js.map +0 -1
  281. package/dist/multiplexer/dashboard-state-methods.js.map +0 -1
  282. package/dist/multiplexer/dashboard-tail-methods.js.map +0 -1
  283. package/dist/multiplexer/dashboard-view-methods.js.map +0 -1
  284. package/dist/multiplexer/graveyard-view-model.js.map +0 -1
  285. package/dist/multiplexer/index.js.map +0 -1
  286. package/dist/multiplexer/navigation.js.map +0 -1
  287. package/dist/multiplexer/notifications.js.map +0 -1
  288. package/dist/multiplexer/persistence-methods.js.map +0 -1
  289. package/dist/multiplexer/runtime-lifecycle-methods.js.map +0 -1
  290. package/dist/multiplexer/runtime-state.js.map +0 -1
  291. package/dist/multiplexer/runtime-sync.js.map +0 -1
  292. package/dist/multiplexer/service-state-snapshot.js.map +0 -1
  293. package/dist/multiplexer/services.js.map +0 -1
  294. package/dist/multiplexer/session-actions.d.ts +0 -40
  295. package/dist/multiplexer/session-actions.js +0 -110
  296. package/dist/multiplexer/session-actions.js.map +0 -1
  297. package/dist/multiplexer/session-launch.js.map +0 -1
  298. package/dist/multiplexer/session-runtime-core.js.map +0 -1
  299. package/dist/multiplexer/subscreens.js.map +0 -1
  300. package/dist/multiplexer/tool-picker.js.map +0 -1
  301. package/dist/multiplexer/worktree-graveyard.js.map +0 -1
  302. package/dist/multiplexer/worktrees.js.map +0 -1
  303. package/dist/notification-context.js.map +0 -1
  304. package/dist/notifications.js.map +0 -1
  305. package/dist/notify.js.map +0 -1
  306. package/dist/orchestration-actions.js.map +0 -1
  307. package/dist/orchestration-dispatcher.d.ts +0 -25
  308. package/dist/orchestration-dispatcher.js +0 -59
  309. package/dist/orchestration-dispatcher.js.map +0 -1
  310. package/dist/orchestration-routing.js.map +0 -1
  311. package/dist/orchestration.js.map +0 -1
  312. package/dist/osc-notifications.js.map +0 -1
  313. package/dist/paths.js.map +0 -1
  314. package/dist/plugin-runtime.js.map +0 -1
  315. package/dist/project-events.js.map +0 -1
  316. package/dist/project-scanner.js.map +0 -1
  317. package/dist/project-service-manifest.js.map +0 -1
  318. package/dist/recency.js.map +0 -1
  319. package/dist/recorder.js.map +0 -1
  320. package/dist/session-bootstrap.js.map +0 -1
  321. package/dist/session-input-operations.d.ts +0 -19
  322. package/dist/session-input-operations.js +0 -46
  323. package/dist/session-input-operations.js.map +0 -1
  324. package/dist/session-message-history.d.ts +0 -27
  325. package/dist/session-message-history.js +0 -105
  326. package/dist/session-message-history.js.map +0 -1
  327. package/dist/session-runtime.js.map +0 -1
  328. package/dist/session-semantics.js.map +0 -1
  329. package/dist/shell-args.js.map +0 -1
  330. package/dist/shell-hooks.js.map +0 -1
  331. package/dist/shell-state.js.map +0 -1
  332. package/dist/status-detector.js.map +0 -1
  333. package/dist/statusline-model.js.map +0 -1
  334. package/dist/task-dispatcher.d.ts +0 -64
  335. package/dist/task-dispatcher.js +0 -213
  336. package/dist/task-dispatcher.js.map +0 -1
  337. package/dist/task-workflow.js.map +0 -1
  338. package/dist/tasks.js.map +0 -1
  339. package/dist/team.js.map +0 -1
  340. package/dist/terminal-host.js.map +0 -1
  341. package/dist/threads.js.map +0 -1
  342. package/dist/tmux/doctor.js.map +0 -1
  343. package/dist/tmux/inbox-popup.js.map +0 -1
  344. package/dist/tmux/runtime-manager.js.map +0 -1
  345. package/dist/tmux/session-transport.js.map +0 -1
  346. package/dist/tmux/statusline-cache.js.map +0 -1
  347. package/dist/tmux/statusline.js.map +0 -1
  348. package/dist/tmux/switcher.js.map +0 -1
  349. package/dist/tmux/window-open.js.map +0 -1
  350. package/dist/tool-output-watchers.js.map +0 -1
  351. package/dist/tui/render/box.js.map +0 -1
  352. package/dist/tui/render/text.js.map +0 -1
  353. package/dist/tui/screens/dashboard-renderers.js.map +0 -1
  354. package/dist/tui/screens/overlay-renderers.js.map +0 -1
  355. package/dist/tui/screens/subscreen-renderers.js.map +0 -1
  356. package/dist/workflow.js.map +0 -1
  357. package/dist/worktree.js.map +0 -1
@@ -1,5 +1,6 @@
1
1
  import { basename } from "node:path";
2
2
  import { sessionSemanticCompactHint } from "./session-semantics.js";
3
+ import { compareTeammateSessions, isTeammateSession } from "./team.js";
3
4
  function isAutogeneratedSessionLabel(session) {
4
5
  const label = session.label?.trim().toLowerCase();
5
6
  const tool = session.tool?.trim().toLowerCase();
@@ -8,6 +9,11 @@ function isAutogeneratedSessionLabel(session) {
8
9
  return label === tool || label.startsWith(`${tool}-`);
9
10
  }
10
11
  export function compactSessionTitle(session) {
12
+ if (session.kind === "service") {
13
+ const command = session.launchCommandLine?.trim();
14
+ if (command)
15
+ return command;
16
+ }
11
17
  const base = session.kind === "service"
12
18
  ? session.label?.trim() || session.tool || "service"
13
19
  : !isAutogeneratedSessionLabel(session) && session.label?.trim()
@@ -42,12 +48,27 @@ function isWithinPath(path, root) {
42
48
  }
43
49
  function resolveScopedWorktreePath(data, projectRoot, currentPath) {
44
50
  const normalizedCurrentPath = normalizePath(currentPath, projectRoot);
45
- const candidates = (data.sessions ?? [])
51
+ const candidates = [...(data.sessions ?? []), ...(data.teammates ?? [])]
46
52
  .map((session) => normalizePath(session.worktreePath, projectRoot))
47
53
  .filter((worktreePath) => isWithinPath(normalizedCurrentPath, worktreePath))
48
54
  .sort((left, right) => right.length - left.length);
49
55
  return candidates[0] ?? normalizedCurrentPath;
50
56
  }
57
+ function allStatuslineSessions(data) {
58
+ return [...(data.sessions ?? []), ...(data.teammates ?? [])];
59
+ }
60
+ export function findStatuslineSession(data, sessionId) {
61
+ if (!sessionId)
62
+ return undefined;
63
+ return allStatuslineSessions(data).find((session) => session.id === sessionId);
64
+ }
65
+ function sessionsMatchingScopedWindow(sessions, scopedWorktreePath, currentWindow, projectRoot) {
66
+ return sessions.filter((session) => {
67
+ if (normalizePath(session.worktreePath, projectRoot) !== scopedWorktreePath)
68
+ return false;
69
+ return session.windowName === currentWindow || session.label === currentWindow || session.tool === currentWindow;
70
+ });
71
+ }
51
72
  export function sessionIdentity(session) {
52
73
  return compactSessionTitle(session);
53
74
  }
@@ -87,7 +108,7 @@ export function currentPathContext(currentPath) {
87
108
  };
88
109
  }
89
110
  export function resolveCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot) {
90
- const sessions = data.sessions ?? [];
111
+ const sessions = allStatuslineSessions(data);
91
112
  if (currentWindowId) {
92
113
  const byWindow = sessions.find((session) => session.tmuxWindowId === currentWindowId);
93
114
  if (byWindow?.id)
@@ -95,18 +116,17 @@ export function resolveCurrentSessionId(data, currentSession, currentWindow, cur
95
116
  }
96
117
  if (currentWindow && projectRoot) {
97
118
  const scopedWorktreePath = resolveScopedWorktreePath(data, projectRoot, currentPath);
98
- const byScopedWindow = sessions.find((session) => {
99
- if (normalizePath(session.worktreePath, projectRoot) !== scopedWorktreePath)
100
- return false;
101
- return session.windowName === currentWindow || session.label === currentWindow || session.tool === currentWindow;
102
- });
103
- if (byScopedWindow?.id)
104
- return byScopedWindow.id;
119
+ const visibleMatch = sessionsMatchingScopedWindow(data.sessions ?? [], scopedWorktreePath, currentWindow, projectRoot)[0];
120
+ if (visibleMatch?.id)
121
+ return visibleMatch.id;
122
+ const teammateMatch = sessionsMatchingScopedWindow(data.teammates ?? [], scopedWorktreePath, currentWindow, projectRoot)[0];
123
+ if (teammateMatch?.id)
124
+ return teammateMatch.id;
105
125
  }
106
126
  return data.sessions?.find((session) => session.active)?.id;
107
127
  }
108
128
  export function resolveExactCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot) {
109
- const sessions = data.sessions ?? [];
129
+ const sessions = allStatuslineSessions(data);
110
130
  if (currentWindowId) {
111
131
  const byWindow = sessions.find((session) => session.tmuxWindowId === currentWindowId);
112
132
  if (byWindow?.id)
@@ -114,33 +134,29 @@ export function resolveExactCurrentSessionId(data, currentSession, currentWindow
114
134
  }
115
135
  if (currentWindow && projectRoot) {
116
136
  const scopedWorktreePath = resolveScopedWorktreePath(data, projectRoot, currentPath);
117
- const matches = sessions.filter((session) => {
118
- if (normalizePath(session.worktreePath, projectRoot) !== scopedWorktreePath)
119
- return false;
120
- return session.windowName === currentWindow || session.label === currentWindow || session.tool === currentWindow;
121
- });
122
- if (matches.length === 1) {
123
- return matches[0]?.id;
137
+ const visibleMatches = sessionsMatchingScopedWindow(data.sessions ?? [], scopedWorktreePath, currentWindow, projectRoot);
138
+ if (visibleMatches.length === 1) {
139
+ return visibleMatches[0]?.id;
140
+ }
141
+ if (visibleMatches.length > 1) {
142
+ return undefined;
143
+ }
144
+ const teammateMatches = sessionsMatchingScopedWindow(data.teammates ?? [], scopedWorktreePath, currentWindow, projectRoot);
145
+ if (teammateMatches.length === 1) {
146
+ return teammateMatches[0]?.id;
124
147
  }
125
148
  }
126
149
  return undefined;
127
150
  }
128
151
  export function resolveScopedSessions(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
129
152
  const scopedWorktreePath = resolveScopedWorktreePath(data, projectRoot, currentPath);
130
- return (data.sessions ?? [])
153
+ const scopedSessions = (data.sessions ?? [])
131
154
  .filter((session) => session.status !== "offline" && session.status !== "exited")
132
- .filter((session) => normalizePath(session.worktreePath, projectRoot) === scopedWorktreePath)
133
- .sort((left, right) => {
134
- const leftKind = left.kind === "service" ? 1 : 0;
135
- const rightKind = right.kind === "service" ? 1 : 0;
136
- if (leftKind !== rightKind)
137
- return leftKind - rightKind;
138
- const leftIndex = left.tmuxWindowIndex ?? Number.MAX_SAFE_INTEGER;
139
- const rightIndex = right.tmuxWindowIndex ?? Number.MAX_SAFE_INTEGER;
140
- if (leftIndex !== rightIndex)
141
- return leftIndex - rightIndex;
142
- return compactSessionTitle(left).localeCompare(compactSessionTitle(right));
143
- })
155
+ .filter((session) => normalizePath(session.worktreePath, projectRoot) === scopedWorktreePath);
156
+ return [
157
+ ...scopedSessions.filter((session) => session.kind !== "service"),
158
+ ...scopedSessions.filter((session) => session.kind === "service"),
159
+ ]
144
160
  .slice(0, 5)
145
161
  .map((session) => {
146
162
  const resolvedMetadata = data.metadata?.[session.id];
@@ -153,6 +169,66 @@ export function resolveScopedSessions(data, projectRoot, currentSession, current
153
169
  };
154
170
  });
155
171
  }
172
+ export function resolveFocusedTeammate(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
173
+ const exactCurrentSessionId = resolveExactCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot);
174
+ if (!exactCurrentSessionId)
175
+ return null;
176
+ const teammate = (data.teammates ?? []).find((session) => session.id === exactCurrentSessionId);
177
+ if (!teammate || teammate.status === "offline" || teammate.status === "exited")
178
+ return null;
179
+ const resolvedMetadata = data.metadata?.[teammate.id];
180
+ return {
181
+ ...teammate,
182
+ derived: resolvedMetadata?.derived,
183
+ semantic: teammate.semantic,
184
+ metadata: resolvedMetadata,
185
+ isCurrent: true,
186
+ };
187
+ }
188
+ export function resolveFocusedTeammateGroup(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
189
+ const focusedTeammate = resolveFocusedTeammate(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath);
190
+ const parentSessionId = focusedTeammate?.team?.parentSessionId;
191
+ if (!focusedTeammate || !parentSessionId)
192
+ return [];
193
+ return (data.teammates ?? [])
194
+ .filter((session) => session.team?.parentSessionId === parentSessionId)
195
+ .filter((session) => session.status !== "offline" && session.status !== "exited")
196
+ .sort(compareTeammateSessions)
197
+ .slice(0, 5)
198
+ .map((session) => {
199
+ const resolvedMetadata = data.metadata?.[session.id];
200
+ return {
201
+ ...session,
202
+ derived: resolvedMetadata?.derived,
203
+ semantic: session.semantic,
204
+ metadata: resolvedMetadata,
205
+ isCurrent: session.id === focusedTeammate.id,
206
+ };
207
+ });
208
+ }
209
+ export function resolveCurrentTeammates(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
210
+ const parentSessionId = resolveExactCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot);
211
+ if (!parentSessionId)
212
+ return [];
213
+ const parentSession = (data.sessions ?? []).find((session) => session.id === parentSessionId);
214
+ if (!parentSession || isTeammateSession(parentSession))
215
+ return [];
216
+ return (data.teammates ?? [])
217
+ .filter((session) => session.team?.parentSessionId === parentSessionId)
218
+ .filter((session) => session.status !== "offline" && session.status !== "exited")
219
+ .sort(compareTeammateSessions)
220
+ .slice(0, 5)
221
+ .map((session) => {
222
+ const resolvedMetadata = data.metadata?.[session.id];
223
+ return {
224
+ ...session,
225
+ derived: resolvedMetadata?.derived,
226
+ semantic: session.semantic,
227
+ metadata: resolvedMetadata,
228
+ isCurrent: false,
229
+ };
230
+ });
231
+ }
156
232
  export function resolveSessionMetadata(data, projectRoot, currentSession, currentWindow, currentWindowId, currentPath) {
157
233
  const activeSessionId = resolveCurrentSessionId(data, currentSession, currentWindow, currentWindowId, currentPath, projectRoot);
158
234
  if (!activeSessionId)
@@ -165,4 +241,3 @@ export function resolveExactSessionMetadata(data, projectRoot, currentSession, c
165
241
  return undefined;
166
242
  return data.metadata?.[activeSessionId];
167
243
  }
168
- //# sourceMappingURL=statusline-model.js.map
@@ -1,15 +1,12 @@
1
1
  import { type Task } from "./tasks.js";
2
- import type { TaskEvent } from "./task-dispatcher.js";
3
- interface DispatchSession {
4
- id: string;
5
- write(data: string): void;
2
+ export interface TaskEvent {
3
+ type: "assigned" | "completed" | "failed" | "review_created" | "review_approved" | "changes_requested";
4
+ taskId: string;
5
+ sessionId: string;
6
+ description: string;
6
7
  }
7
8
  export declare class TaskWorkflow {
8
- private readonly deliverPrompt;
9
- constructor(deliverPrompt?: (session: DispatchSession, prompt: string) => void);
10
- injectIntoSession(session: DispatchSession, task: Task): TaskEvent;
11
- notifyAssigner(session: DispatchSession, task: Task): void;
12
9
  handleCompletion(task: Task): TaskEvent[];
13
10
  private handleReviewCompletion;
14
11
  }
15
- export {};
12
+ export declare function requestReview(agentSessionId: string, agentRole: string, diff: string | undefined, summary: string): Promise<Task | null>;
@@ -1,87 +1,6 @@
1
1
  import { normalizeReviewStatus, writeTask } from "./tasks.js";
2
2
  import { loadTeamConfig } from "./team.js";
3
- import { markMessageDelivered, openTaskThread, updateThread } from "./threads.js";
4
- import { sendThreadMessage } from "./orchestration.js";
5
3
  export class TaskWorkflow {
6
- deliverPrompt;
7
- constructor(deliverPrompt = defaultDeliverPrompt) {
8
- this.deliverPrompt = deliverPrompt;
9
- }
10
- injectIntoSession(session, task) {
11
- const thread = openTaskThread(task.id, {
12
- title: `${task.type === "review" ? "Review" : "Task"}: ${task.description}`,
13
- createdBy: task.assignedBy,
14
- participants: [task.assignedBy, session.id],
15
- kind: task.type === "review" ? "review" : "task",
16
- });
17
- task.threadId = thread.id;
18
- const initialMessage = sendThreadMessage({
19
- threadId: thread.id,
20
- from: task.assignedBy,
21
- to: [session.id],
22
- kind: "request",
23
- body: task.description,
24
- metadata: { taskId: task.id },
25
- });
26
- markMessageDelivered(thread.id, initialMessage.message.id, session.id);
27
- const prefix = task.type === "review"
28
- ? `[AIMUX REVIEW ${task.id} from ${task.assignedBy}]`
29
- : `[AIMUX TASK ${task.id} from ${task.assignedBy}]`;
30
- let prompt = `${prefix} ${task.description}\n\n`;
31
- if (task.type === "review" && task.diff) {
32
- prompt += `Diff to review:\n${task.diff.slice(0, 3000)}\n\n`;
33
- }
34
- prompt +=
35
- `Run:\n` +
36
- ` aimux task show ${task.id}\n` +
37
- ` aimux thread show ${thread.id}\n\n` +
38
- `Acknowledge with:\n` +
39
- ` aimux task accept ${task.id} --from ${session.id}\n\n` +
40
- `When done, complete with:\n` +
41
- ` aimux task complete ${task.id} --from ${session.id} --body "<summary>"`;
42
- if (task.type === "review") {
43
- prompt +=
44
- `\n\nFor review verdicts use:\n` +
45
- ` aimux review approve ${task.id} --from ${session.id} --body "<notes>"\n` +
46
- ` aimux review request-changes ${task.id} --from ${session.id} --body "<requested changes>"`;
47
- }
48
- else {
49
- prompt += `\n\nIf blocked, use:\n aimux task block ${task.id} --from ${session.id} --body "<reason>"`;
50
- }
51
- this.deliverPrompt(session, prompt);
52
- task.status = "assigned";
53
- task.assignedTo = session.id;
54
- writeTask(task);
55
- return {
56
- type: "assigned",
57
- taskId: task.id,
58
- sessionId: session.id,
59
- description: task.description,
60
- };
61
- }
62
- notifyAssigner(session, task) {
63
- if (task.threadId) {
64
- sendThreadMessage({
65
- threadId: task.threadId,
66
- from: task.assignedTo ?? task.assignedBy,
67
- to: [task.assignedBy],
68
- kind: task.status === "done" ? "status" : "reply",
69
- body: task.status === "done"
70
- ? `Completed: ${task.description}${task.result ? `\n\n${task.result}` : ""}`
71
- : `Failed: ${task.description}${task.error ? `\n\n${task.error}` : ""}`,
72
- metadata: { taskId: task.id, status: task.status },
73
- });
74
- updateThread(task.threadId, (current) => ({
75
- ...current,
76
- status: task.status === "done" ? "done" : "blocked",
77
- owner: task.assignedBy,
78
- waitingOn: [],
79
- }));
80
- }
81
- this.deliverPrompt(session, `[AIMUX TASK COMPLETE ${task.id}] Agent ${task.assignedTo} finished: ${task.result ?? task.error ?? "no details"}`);
82
- task.notifiedAt = new Date().toISOString();
83
- writeTask(task);
84
- }
85
4
  handleCompletion(task) {
86
5
  if (task.type === "review") {
87
6
  return this.handleReviewCompletion(task);
@@ -164,8 +83,41 @@ export class TaskWorkflow {
164
83
  ];
165
84
  }
166
85
  }
167
- function defaultDeliverPrompt(session, prompt) {
168
- // Production multiplexer wiring overrides this with writeAgentInput(..., submit: true).
169
- session.write(prompt + "\r");
86
+ export async function requestReview(agentSessionId, agentRole, diff, summary) {
87
+ const config = loadTeamConfig();
88
+ const roleConfig = config.roles[agentRole];
89
+ let reviewerRole = roleConfig?.reviewedBy;
90
+ if (!reviewerRole) {
91
+ const roles = Object.entries(config.roles).filter(([roleKey]) => roleKey !== agentRole);
92
+ const fallback = roles.find(([, role]) => role.description.toLowerCase().includes("review")) ??
93
+ roles.find(([, role]) => role.canEdit);
94
+ if (!fallback)
95
+ return null;
96
+ reviewerRole = fallback[0];
97
+ }
98
+ if (reviewerRole === agentRole) {
99
+ const roles = Object.entries(config.roles).filter(([roleKey]) => roleKey !== agentRole);
100
+ const fallback = roles.find(([, role]) => role.description.toLowerCase().includes("review")) ??
101
+ roles.find(([, role]) => role.canEdit);
102
+ if (!fallback)
103
+ return null;
104
+ reviewerRole = fallback[0];
105
+ }
106
+ const reviewTask = {
107
+ id: `review-manual-${Date.now().toString(36)}`,
108
+ status: "pending",
109
+ assignedBy: agentSessionId,
110
+ description: `Review: ${summary.slice(0, 100)}`,
111
+ prompt: summary,
112
+ createdAt: new Date().toISOString(),
113
+ updatedAt: new Date().toISOString(),
114
+ assignee: reviewerRole,
115
+ assigner: agentRole,
116
+ type: "review",
117
+ reviewStatus: "pending",
118
+ diff,
119
+ iteration: 1,
120
+ };
121
+ await writeTask(reviewTask);
122
+ return reviewTask;
170
123
  }
171
- //# sourceMappingURL=task-workflow.js.map
package/dist/tasks.d.ts CHANGED
@@ -1,36 +1,9 @@
1
- export type TaskStatus = "pending" | "assigned" | "in_progress" | "blocked" | "done" | "failed";
1
+ import { type RuntimeExchangeTask } from "./runtime-core/exchange-store.js";
2
+ export type TaskStatus = RuntimeExchangeTask["status"];
2
3
  export type ReviewStatus = "pending" | "approved" | "changes_requested";
3
4
  export type ReviewStatusInput = ReviewStatus | "approve" | "request-changes" | "request_changes" | "changes-requested" | "changes requested";
4
- export interface Task {
5
- id: string;
6
- status: TaskStatus;
7
- assignedBy: string;
8
- assignedTo?: string;
9
- threadId?: string;
10
- tool?: string;
11
- description: string;
12
- prompt: string;
13
- result?: string;
14
- error?: string;
15
- createdAt: string;
16
- updatedAt: string;
17
- notifiedAt?: string;
18
- /** Role name of the intended assignee (e.g. "coder", "reviewer") */
19
- assignee?: string;
20
- /** Role name of the task creator */
21
- assigner?: string;
22
- /** Task type: regular task or code review */
23
- type?: "task" | "review";
24
- /** Review verdict */
5
+ export interface Task extends Omit<RuntimeExchangeTask, "reviewStatus"> {
25
6
  reviewStatus?: ReviewStatusInput;
26
- /** Reviewer feedback text */
27
- reviewFeedback?: string;
28
- /** Git diff associated with the task */
29
- diff?: string;
30
- /** Revision iteration count (incremented on each review round-trip) */
31
- iteration?: number;
32
- /** ID of the task this review refers to */
33
- reviewOf?: string;
34
7
  }
35
8
  export declare function normalizeReviewStatus(status: unknown): ReviewStatus | undefined;
36
9
  /**
@@ -38,13 +11,13 @@ export declare function normalizeReviewStatus(status: unknown): ReviewStatus | u
38
11
  */
39
12
  export declare function readTask(id: string): Task | undefined;
40
13
  /**
41
- * Read all tasks from the tasks directory.
14
+ * Read all tasks from the runtime exchange.
42
15
  */
43
16
  export declare function readAllTasks(): Task[];
44
17
  /**
45
- * Write a task to disk with file locking.
18
+ * Write a task to the runtime exchange.
46
19
  */
47
- export declare function writeTask(task: Task): Promise<void>;
20
+ export declare function writeTask(task: Task): void;
48
21
  /**
49
22
  * Returns true if the session has an active (assigned) task.
50
23
  */
package/dist/tasks.js CHANGED
@@ -1,7 +1,5 @@
1
- import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync } from "node:fs";
2
- import { join } from "node:path";
3
- import * as lockfile from "proper-lockfile";
4
- import { getTasksDir } from "./paths.js";
1
+ import { deriveRuntimeExchangeIndexes } from "./runtime-core/exchange-derived.js";
2
+ import { createRuntimeExchangeStore } from "./runtime-core/exchange-store.js";
5
3
  export function normalizeReviewStatus(status) {
6
4
  if (!status)
7
5
  return undefined;
@@ -17,122 +15,81 @@ export function normalizeReviewStatus(status) {
17
15
  return "changes_requested";
18
16
  return undefined;
19
17
  }
20
- const LOCK_RETRIES = { retries: 5, minTimeout: 50 };
21
- /**
22
- * Get the tasks directory path, creating it if needed.
23
- */
24
- function ensureTasksDir() {
25
- const dir = getTasksDir();
26
- if (!existsSync(dir)) {
27
- mkdirSync(dir, { recursive: true });
28
- }
29
- return dir;
18
+ function nowIso() {
19
+ return new Date().toISOString();
20
+ }
21
+ function toExchangeTask(task, updatedAt) {
22
+ return {
23
+ ...task,
24
+ updatedAt,
25
+ reviewStatus: normalizeReviewStatus(task.reviewStatus),
26
+ };
27
+ }
28
+ function fromExchangeTask(task) {
29
+ return { ...task };
30
30
  }
31
31
  /**
32
32
  * Read a single task by ID.
33
33
  */
34
34
  export function readTask(id) {
35
- const filePath = join(ensureTasksDir(), `${id}.json`);
36
- if (!existsSync(filePath))
37
- return undefined;
38
- try {
39
- return JSON.parse(readFileSync(filePath, "utf-8"));
40
- }
41
- catch {
42
- return undefined;
43
- }
35
+ const task = createRuntimeExchangeStore()
36
+ .read()
37
+ .tasks.find((entry) => entry.id === id);
38
+ return task ? fromExchangeTask(task) : undefined;
44
39
  }
45
40
  /**
46
- * Read all tasks from the tasks directory.
41
+ * Read all tasks from the runtime exchange.
47
42
  */
48
43
  export function readAllTasks() {
49
- const dir = ensureTasksDir();
50
- const tasks = [];
51
- let files;
52
- try {
53
- files = readdirSync(dir).filter((f) => f.endsWith(".json"));
54
- }
55
- catch {
56
- return tasks;
57
- }
58
- for (const file of files) {
59
- try {
60
- const data = readFileSync(join(dir, file), "utf-8");
61
- tasks.push(JSON.parse(data));
62
- }
63
- catch {
64
- // skip corrupt files
65
- }
66
- }
67
- return tasks;
44
+ return createRuntimeExchangeStore().read().tasks.map(fromExchangeTask);
68
45
  }
69
46
  /**
70
- * Write a task to disk with file locking.
47
+ * Write a task to the runtime exchange.
71
48
  */
72
- export async function writeTask(task) {
73
- const dir = ensureTasksDir();
74
- const filePath = join(dir, `${task.id}.json`);
75
- // Ensure the file exists for proper-lockfile (it locks existing files)
76
- if (!existsSync(filePath)) {
77
- writeFileSync(filePath, "{}");
78
- }
79
- let release;
80
- try {
81
- release = await lockfile.lock(filePath, { retries: LOCK_RETRIES });
82
- task.updatedAt = new Date().toISOString();
83
- writeFileSync(filePath, JSON.stringify(task, null, 2) + "\n");
84
- }
85
- finally {
86
- if (release)
87
- await release();
88
- }
49
+ export function writeTask(task) {
50
+ const updatedAt = nowIso();
51
+ createRuntimeExchangeStore().update((exchange) => deriveRuntimeExchangeIndexes({
52
+ ...exchange,
53
+ generatedAt: updatedAt,
54
+ tasks: [...exchange.tasks.filter((existing) => existing.id !== task.id), toExchangeTask(task, updatedAt)],
55
+ }));
56
+ task.updatedAt = updatedAt;
57
+ task.reviewStatus = normalizeReviewStatus(task.reviewStatus);
89
58
  }
90
59
  /**
91
60
  * Returns true if the session has an active (assigned) task.
92
61
  */
93
62
  export function hasActiveTask(sessionId) {
94
- const all = readAllTasks();
95
- return all.some((t) => ["assigned", "in_progress", "blocked"].includes(t.status) && t.assignedTo === sessionId);
63
+ return readAllTasks().some((task) => ["assigned", "in_progress", "blocked"].includes(task.status) && task.assignedTo === sessionId);
96
64
  }
97
65
  /**
98
66
  * Remove done/failed tasks older than maxAgeMs.
99
67
  */
100
68
  export function cleanupTasks(maxAgeMs) {
101
- const dir = ensureTasksDir();
102
69
  const now = Date.now();
103
- let files;
104
- try {
105
- files = readdirSync(dir).filter((f) => f.endsWith(".json"));
106
- }
107
- catch {
108
- return;
109
- }
110
- for (const file of files) {
111
- try {
112
- const data = readFileSync(join(dir, file), "utf-8");
113
- const task = JSON.parse(data);
114
- if ((task.status === "done" || task.status === "failed") && now - new Date(task.updatedAt).getTime() > maxAgeMs) {
115
- unlinkSync(join(dir, file));
116
- }
117
- }
118
- catch {
119
- // skip
120
- }
121
- }
70
+ const generatedAt = nowIso();
71
+ createRuntimeExchangeStore().update((exchange) => deriveRuntimeExchangeIndexes({
72
+ ...exchange,
73
+ generatedAt,
74
+ tasks: exchange.tasks.filter((task) => {
75
+ if (task.status !== "done" && task.status !== "failed")
76
+ return true;
77
+ return now - new Date(task.updatedAt).getTime() <= maxAgeMs;
78
+ }),
79
+ }));
122
80
  }
123
81
  /**
124
82
  * List pending review tasks assigned to a given role.
125
83
  */
126
84
  export function listPendingReviews(role) {
127
- return readAllTasks().filter((t) => t.type === "review" &&
128
- t.assignee === role &&
129
- t.status === "pending" &&
130
- normalizeReviewStatus(t.reviewStatus) === "pending");
85
+ return readAllTasks().filter((task) => task.type === "review" &&
86
+ task.assignee === role &&
87
+ task.status === "pending" &&
88
+ normalizeReviewStatus(task.reviewStatus) === "pending");
131
89
  }
132
90
  /**
133
91
  * List active tasks assigned to a given role (pending or assigned, not done/failed).
134
92
  */
135
93
  export function listTasksForRole(role) {
136
- return readAllTasks().filter((t) => t.assignee === role && t.status !== "done" && t.status !== "failed");
94
+ return readAllTasks().filter((task) => task.assignee === role && task.status !== "done" && task.status !== "failed");
137
95
  }
138
- //# sourceMappingURL=tasks.js.map
package/dist/team.d.ts CHANGED
@@ -9,6 +9,35 @@ export interface TeamConfig {
9
9
  roles: Record<string, RoleConfig>;
10
10
  defaultRole: string;
11
11
  }
12
+ export interface SessionTeamMetadata {
13
+ teamId: string;
14
+ parentSessionId: string;
15
+ role?: string;
16
+ label?: string;
17
+ order?: number;
18
+ }
19
+ export declare function isTeammateSession(session: {
20
+ team?: SessionTeamMetadata;
21
+ } | undefined): boolean;
22
+ export declare function compareTeammateSessions(left: {
23
+ id: string;
24
+ createdAt?: string;
25
+ team?: SessionTeamMetadata;
26
+ }, right: {
27
+ id: string;
28
+ createdAt?: string;
29
+ team?: SessionTeamMetadata;
30
+ }): number;
31
+ export declare function selectDirectTeammates<T extends {
32
+ id: string;
33
+ createdAt?: string;
34
+ team?: SessionTeamMetadata;
35
+ }>(sessions: T[], parentSessionId: string): T[];
36
+ export declare function selectOrphanTeammates<T extends {
37
+ id: string;
38
+ createdAt?: string;
39
+ team?: SessionTeamMetadata;
40
+ }>(sessions: T[], knownParentIds: Iterable<string>): T[];
12
41
  export declare function getDefaultTeamConfig(): TeamConfig;
13
42
  /**
14
43
  * Load team config: project .aimux/team.json → global ~/.aimux/team.json → built-in defaults.