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
@@ -0,0 +1,170 @@
1
+ import { basename } from "node:path";
2
+ import { getProjectId, getRepoRoot } from "../paths.js";
3
+ import { createRuntimeTopologyStore, emptyRuntimeTopology, } from "./topology-store.js";
4
+ function serviceNodeId(serviceId) {
5
+ return `service:${serviceId}`;
6
+ }
7
+ function serviceBindingId(serviceId) {
8
+ return `tmux:service:${serviceId}`;
9
+ }
10
+ function ensureRig(topology, projectRoot, now) {
11
+ const id = getProjectId();
12
+ const existing = topology.rigs.find((rig) => rig.id === id);
13
+ if (existing) {
14
+ existing.projectRoot = projectRoot;
15
+ existing.name = basename(projectRoot);
16
+ existing.updatedAt = now;
17
+ return existing.id;
18
+ }
19
+ topology.rigs.push({
20
+ id,
21
+ name: basename(projectRoot),
22
+ projectRoot,
23
+ createdAt: now,
24
+ updatedAt: now,
25
+ });
26
+ return id;
27
+ }
28
+ function upsertServiceNode(topology, service, rigId, now) {
29
+ const nodeId = serviceNodeId(service.id);
30
+ const existing = topology.nodes.find((node) => node.id === nodeId);
31
+ const next = {
32
+ id: nodeId,
33
+ rigId,
34
+ logicalId: service.id,
35
+ role: "service",
36
+ runtime: "service",
37
+ toolConfigKey: "service",
38
+ cwd: service.cwd ?? service.worktreePath,
39
+ label: service.label,
40
+ createdAt: existing?.createdAt ?? service.createdAt ?? now,
41
+ };
42
+ if (existing) {
43
+ Object.assign(existing, next);
44
+ return existing;
45
+ }
46
+ topology.nodes.push(next);
47
+ return next;
48
+ }
49
+ function serviceToTopologyService(service, rigId, nodeId, status, now) {
50
+ return {
51
+ id: service.id,
52
+ rigId,
53
+ nodeId,
54
+ status,
55
+ command: service.command,
56
+ args: service.args ?? [],
57
+ launchCommandLine: service.launchCommandLine,
58
+ worktreePath: service.worktreePath,
59
+ cwd: service.cwd,
60
+ label: service.label,
61
+ createdAt: service.createdAt ?? now,
62
+ updatedAt: now,
63
+ lastSeenAt: status === "running" || status === "starting" ? (service.lastSeenAt ?? now) : undefined,
64
+ };
65
+ }
66
+ function serviceToBinding(service, nodeId, status, now) {
67
+ if (status !== "running" && status !== "starting" && status !== "stopped")
68
+ return undefined;
69
+ const target = service.tmuxTarget;
70
+ if (!target)
71
+ return undefined;
72
+ return {
73
+ id: serviceBindingId(service.id),
74
+ nodeId,
75
+ tmuxSession: target.sessionName,
76
+ tmuxWindowId: target.windowId,
77
+ tmuxWindowIndex: target.windowIndex,
78
+ tmuxWindowName: target.windowName,
79
+ updatedAt: now,
80
+ };
81
+ }
82
+ export function topologyServiceToServiceState(service, topology) {
83
+ const node = service.nodeId ? topology.nodes.find((entry) => entry.id === service.nodeId) : undefined;
84
+ const binding = service.nodeId ? topology.bindings.find((entry) => entry.nodeId === service.nodeId) : undefined;
85
+ return {
86
+ id: service.id,
87
+ status: service.status,
88
+ command: service.command,
89
+ args: service.args ?? [],
90
+ launchCommandLine: service.launchCommandLine,
91
+ worktreePath: service.worktreePath,
92
+ cwd: service.cwd ?? node?.cwd,
93
+ label: service.label ?? node?.label,
94
+ createdAt: service.createdAt,
95
+ lastSeenAt: service.lastSeenAt,
96
+ retained: service.status === "stopped" && Boolean(binding),
97
+ tmuxTarget: binding?.tmuxSession && binding.tmuxWindowId && typeof binding.tmuxWindowIndex === "number"
98
+ ? {
99
+ sessionName: binding.tmuxSession,
100
+ windowId: binding.tmuxWindowId,
101
+ windowIndex: binding.tmuxWindowIndex,
102
+ windowName: binding.tmuxWindowName ?? service.label ?? service.id,
103
+ }
104
+ : undefined,
105
+ };
106
+ }
107
+ export function listTopologyServiceStates(input) {
108
+ const topology = (input?.store ?? createRuntimeTopologyStore()).read();
109
+ const statuses = input?.statuses ? new Set(input.statuses) : undefined;
110
+ return topology.services
111
+ .filter((service) => !statuses || statuses.has(service.status))
112
+ .map((service) => topologyServiceToServiceState(service, topology));
113
+ }
114
+ export function upsertTopologyService(service, status, input) {
115
+ const store = input?.store ?? createRuntimeTopologyStore();
116
+ const now = input?.now ?? new Date().toISOString();
117
+ const projectRoot = input?.projectRoot ?? getRepoRoot();
118
+ return store.update((current) => {
119
+ const topology = current.version ? current : emptyRuntimeTopology(now);
120
+ topology.generatedAt = now;
121
+ const rigId = ensureRig(topology, projectRoot, now);
122
+ const node = upsertServiceNode(topology, service, rigId, now);
123
+ const nextService = serviceToTopologyService(service, rigId, node.id, status, now);
124
+ topology.services = [...topology.services.filter((entry) => entry.id !== service.id), nextService];
125
+ const binding = serviceToBinding(service, node.id, status, now);
126
+ topology.bindings = binding
127
+ ? [...topology.bindings.filter((entry) => entry.id !== binding.id), binding]
128
+ : topology.bindings.filter((entry) => entry.nodeId !== node.id);
129
+ return topology;
130
+ });
131
+ }
132
+ export function removeTopologyService(serviceId, input) {
133
+ const store = input?.store ?? createRuntimeTopologyStore();
134
+ let removed;
135
+ store.update((topology) => {
136
+ const existing = topology.services.find((service) => service.id === serviceId);
137
+ if (!existing)
138
+ return topology;
139
+ removed = topologyServiceToServiceState(existing, topology);
140
+ topology.generatedAt = input?.now ?? new Date().toISOString();
141
+ topology.services = topology.services.filter((service) => service.id !== serviceId);
142
+ if (existing.nodeId) {
143
+ topology.bindings = topology.bindings.filter((binding) => binding.nodeId !== existing.nodeId);
144
+ topology.nodes = topology.nodes.filter((node) => node.id !== existing.nodeId);
145
+ }
146
+ topology.lifecycleOperations = topology.lifecycleOperations.filter((operation) => !(operation.targetKind === "service" && operation.targetId === serviceId));
147
+ return topology;
148
+ });
149
+ return removed;
150
+ }
151
+ export function removeTopologyServicesForWorktree(worktreePath, input) {
152
+ const store = input?.store ?? createRuntimeTopologyStore();
153
+ const now = input?.now ?? new Date().toISOString();
154
+ let removed = [];
155
+ store.update((topology) => {
156
+ const removing = topology.services.filter((service) => service.worktreePath === worktreePath);
157
+ if (removing.length === 0)
158
+ return topology;
159
+ const removingServiceIds = new Set(removing.map((service) => service.id));
160
+ const removingNodeIds = new Set(removing.map((service) => service.nodeId).filter(Boolean));
161
+ removed = removing.map((service) => topologyServiceToServiceState(service, topology));
162
+ topology.generatedAt = now;
163
+ topology.services = topology.services.filter((service) => !removingServiceIds.has(service.id));
164
+ topology.bindings = topology.bindings.filter((binding) => !removingNodeIds.has(binding.nodeId));
165
+ topology.nodes = topology.nodes.filter((node) => !removingNodeIds.has(node.id));
166
+ topology.lifecycleOperations = topology.lifecycleOperations.filter((operation) => !(operation.targetKind === "service" && removingServiceIds.has(operation.targetId)));
167
+ return topology;
168
+ });
169
+ return removed;
170
+ }
@@ -0,0 +1,52 @@
1
+ import { type RuntimeTopology, type RuntimeTopologySession, type RuntimeTopologySessionStatus, type RuntimeTopologyStore } from "./topology-store.js";
2
+ export type RuntimeTopologySessionState = {
3
+ id: string;
4
+ tool: string;
5
+ toolConfigKey: string;
6
+ command: string;
7
+ args: string[];
8
+ status?: RuntimeTopologySessionStatus;
9
+ lifecycle?: "live" | "offline";
10
+ createdAt?: string;
11
+ backendSessionId?: string;
12
+ team?: unknown;
13
+ worktreePath?: string;
14
+ label?: string;
15
+ headline?: string;
16
+ tmuxTarget?: {
17
+ sessionName: string;
18
+ windowId: string;
19
+ windowIndex: number;
20
+ windowName: string;
21
+ };
22
+ };
23
+ type SaveRuntimeTopologySessionsInput = {
24
+ sessions: RuntimeTopologySessionState[];
25
+ projectRoot?: string;
26
+ now?: string;
27
+ store?: RuntimeTopologyStore;
28
+ };
29
+ export declare function topologySessionToSessionState(session: RuntimeTopologySession, topology: RuntimeTopology): RuntimeTopologySessionState;
30
+ export declare function listTopologySessionStates(input?: {
31
+ statuses?: RuntimeTopologySessionStatus[];
32
+ store?: RuntimeTopologyStore;
33
+ }): RuntimeTopologySessionState[];
34
+ export declare function saveRuntimeTopologySessions(input: SaveRuntimeTopologySessionsInput): RuntimeTopology;
35
+ export declare function upsertTopologySession(session: RuntimeTopologySessionState, status: RuntimeTopologySessionStatus, input?: {
36
+ store?: RuntimeTopologyStore;
37
+ now?: string;
38
+ projectRoot?: string;
39
+ }): RuntimeTopology;
40
+ export declare function moveTopologySessionToGraveyard(sessionId: string, input?: {
41
+ store?: RuntimeTopologyStore;
42
+ now?: string;
43
+ }): RuntimeTopologySessionState | undefined;
44
+ export declare function removeTopologySessionsForWorktree(worktreePath: string, input?: {
45
+ store?: RuntimeTopologyStore;
46
+ now?: string;
47
+ }): RuntimeTopologySessionState[];
48
+ export declare function resurrectTopologySession(sessionId: string, input?: {
49
+ store?: RuntimeTopologyStore;
50
+ now?: string;
51
+ }): RuntimeTopologySessionState | undefined;
52
+ export {};
@@ -0,0 +1,238 @@
1
+ import { basename } from "node:path";
2
+ import { getProjectId, getRepoRoot } from "../paths.js";
3
+ import { createRuntimeTopologyStore, emptyRuntimeTopology, } from "./topology-store.js";
4
+ function nodeIdForSession(sessionId) {
5
+ return `agent:${sessionId}`;
6
+ }
7
+ function bindingIdForSession(sessionId) {
8
+ return `tmux:${sessionId}`;
9
+ }
10
+ function statusFromLifecycle(lifecycle) {
11
+ return lifecycle === "offline" ? "offline" : "running";
12
+ }
13
+ function lifecycleFromStatus(status) {
14
+ if (status === "offline")
15
+ return "offline";
16
+ if (status === "graveyard")
17
+ return undefined;
18
+ return "live";
19
+ }
20
+ function ensureRig(topology, projectRoot, now) {
21
+ const id = getProjectId();
22
+ const existing = topology.rigs.find((rig) => rig.id === id);
23
+ if (existing) {
24
+ existing.projectRoot = projectRoot;
25
+ existing.name = basename(projectRoot);
26
+ existing.updatedAt = now;
27
+ return existing.id;
28
+ }
29
+ topology.rigs.push({
30
+ id,
31
+ name: basename(projectRoot),
32
+ projectRoot,
33
+ createdAt: now,
34
+ updatedAt: now,
35
+ });
36
+ return id;
37
+ }
38
+ function upsertNode(topology, session, rigId, now) {
39
+ const nodeId = nodeIdForSession(session.id);
40
+ const existing = topology.nodes.find((node) => node.id === nodeId);
41
+ const next = {
42
+ id: nodeId,
43
+ rigId,
44
+ logicalId: session.id,
45
+ role: typeof session.team?.role === "string" ? session.team.role : undefined,
46
+ runtime: session.toolConfigKey ?? session.tool ?? session.command,
47
+ toolConfigKey: session.toolConfigKey ?? session.tool ?? session.command,
48
+ cwd: session.worktreePath,
49
+ label: session.label,
50
+ createdAt: existing?.createdAt ?? session.createdAt ?? now,
51
+ };
52
+ if (existing) {
53
+ Object.assign(existing, next);
54
+ return existing;
55
+ }
56
+ topology.nodes.push(next);
57
+ return next;
58
+ }
59
+ function sessionToTopologySession(session, nodeId, now) {
60
+ return {
61
+ id: session.id,
62
+ nodeId,
63
+ status: statusFromLifecycle(session.lifecycle),
64
+ tool: session.tool,
65
+ command: session.command,
66
+ args: session.args ?? [],
67
+ backendSessionId: session.backendSessionId,
68
+ worktreePath: session.worktreePath,
69
+ label: session.label,
70
+ headline: session.headline,
71
+ team: session.team,
72
+ createdAt: session.createdAt ?? now,
73
+ updatedAt: now,
74
+ lastSeenAt: session.lifecycle === "offline" ? undefined : now,
75
+ };
76
+ }
77
+ function sessionToBinding(session, nodeId, now) {
78
+ if (session.lifecycle === "offline")
79
+ return undefined;
80
+ const target = session.tmuxTarget;
81
+ if (!target)
82
+ return undefined;
83
+ return {
84
+ id: bindingIdForSession(session.id),
85
+ nodeId,
86
+ tmuxSession: target.sessionName,
87
+ tmuxWindowId: target.windowId,
88
+ tmuxWindowIndex: target.windowIndex,
89
+ tmuxWindowName: target.windowName,
90
+ updatedAt: now,
91
+ };
92
+ }
93
+ export function topologySessionToSessionState(session, topology) {
94
+ const node = topology.nodes.find((entry) => entry.id === session.nodeId);
95
+ const binding = session.status === "running" || session.status === "idle" || session.status === "starting"
96
+ ? topology.bindings.find((entry) => entry.nodeId === session.nodeId)
97
+ : undefined;
98
+ const tool = session.tool ?? node?.toolConfigKey ?? session.command ?? "unknown";
99
+ return {
100
+ id: session.id,
101
+ tool,
102
+ toolConfigKey: node?.toolConfigKey ?? tool,
103
+ command: session.command ?? tool,
104
+ args: session.args ?? [],
105
+ status: session.status,
106
+ lifecycle: lifecycleFromStatus(session.status),
107
+ createdAt: session.createdAt,
108
+ backendSessionId: session.backendSessionId,
109
+ team: session.team,
110
+ worktreePath: session.worktreePath ?? node?.cwd,
111
+ label: session.label ?? node?.label,
112
+ headline: session.headline,
113
+ tmuxTarget: binding?.tmuxSession && binding.tmuxWindowId && typeof binding.tmuxWindowIndex === "number"
114
+ ? {
115
+ sessionName: binding.tmuxSession,
116
+ windowId: binding.tmuxWindowId,
117
+ windowIndex: binding.tmuxWindowIndex,
118
+ windowName: binding.tmuxWindowName ?? session.command ?? tool,
119
+ }
120
+ : undefined,
121
+ };
122
+ }
123
+ export function listTopologySessionStates(input) {
124
+ const topology = (input?.store ?? createRuntimeTopologyStore()).read();
125
+ const statuses = input?.statuses ? new Set(input.statuses) : undefined;
126
+ return topology.sessions
127
+ .filter((session) => !statuses || statuses.has(session.status))
128
+ .map((session) => topologySessionToSessionState(session, topology));
129
+ }
130
+ export function saveRuntimeTopologySessions(input) {
131
+ const store = input.store ?? createRuntimeTopologyStore();
132
+ const now = input.now ?? new Date().toISOString();
133
+ const projectRoot = input.projectRoot ?? getRepoRoot();
134
+ return store.update((current) => {
135
+ const topology = current.version ? current : emptyRuntimeTopology(now);
136
+ topology.generatedAt = now;
137
+ const rigId = ensureRig(topology, projectRoot, now);
138
+ const nextSessionIds = new Set(input.sessions.map((session) => session.id));
139
+ const preservedGraveyard = topology.sessions.filter((session) => session.status === "graveyard" && !nextSessionIds.has(session.id));
140
+ const nextNodes = [];
141
+ const nextBindings = [];
142
+ const nextSessions = [];
143
+ for (const session of input.sessions) {
144
+ const node = upsertNode(topology, session, rigId, now);
145
+ nextNodes.push(node);
146
+ const binding = sessionToBinding(session, node.id, now);
147
+ if (binding)
148
+ nextBindings.push(binding);
149
+ nextSessions.push(sessionToTopologySession(session, node.id, now));
150
+ }
151
+ const activeNodeIds = new Set(nextNodes.map((node) => node.id));
152
+ const preservedServiceNodeIds = new Set(topology.services.map((service) => service.nodeId).filter(Boolean));
153
+ const preservedNodes = topology.nodes.filter((node) => preservedServiceNodeIds.has(node.id) || preservedGraveyard.some((session) => session.nodeId === node.id));
154
+ topology.nodes = [...preservedNodes.filter((node) => !activeNodeIds.has(node.id)), ...nextNodes];
155
+ topology.bindings = [
156
+ ...topology.bindings.filter((binding) => preservedServiceNodeIds.has(binding.nodeId)),
157
+ ...nextBindings,
158
+ ];
159
+ topology.sessions = [...preservedGraveyard, ...nextSessions];
160
+ const retainedNodeIds = new Set(topology.nodes.map((node) => node.id));
161
+ topology.edges = topology.edges.filter((edge) => retainedNodeIds.has(edge.sourceNodeId) && retainedNodeIds.has(edge.targetNodeId));
162
+ const retainedSessionIds = new Set(topology.sessions.map((session) => session.id));
163
+ topology.exchangeRefs = topology.exchangeRefs.filter((ref) => (!ref.sessionId || retainedSessionIds.has(ref.sessionId)) && (!ref.nodeId || retainedNodeIds.has(ref.nodeId)));
164
+ return topology;
165
+ });
166
+ }
167
+ export function upsertTopologySession(session, status, input) {
168
+ const store = input?.store ?? createRuntimeTopologyStore();
169
+ const now = input?.now ?? new Date().toISOString();
170
+ const projectRoot = input?.projectRoot ?? getRepoRoot();
171
+ return store.update((topology) => {
172
+ topology.generatedAt = now;
173
+ const rigId = ensureRig(topology, projectRoot, now);
174
+ const node = upsertNode(topology, session, rigId, now);
175
+ const nextSession = { ...sessionToTopologySession(session, node.id, now), status };
176
+ topology.sessions = [...topology.sessions.filter((entry) => entry.id !== session.id), nextSession];
177
+ const shouldBind = status === "running" || status === "idle" || status === "starting";
178
+ const binding = shouldBind ? sessionToBinding({ ...session, lifecycle: "live" }, node.id, now) : undefined;
179
+ topology.bindings = binding
180
+ ? [...topology.bindings.filter((entry) => entry.id !== binding.id), binding]
181
+ : topology.bindings.filter((entry) => entry.nodeId !== node.id);
182
+ return topology;
183
+ });
184
+ }
185
+ export function moveTopologySessionToGraveyard(sessionId, input) {
186
+ const store = input?.store ?? createRuntimeTopologyStore();
187
+ const now = input?.now ?? new Date().toISOString();
188
+ let moved;
189
+ store.update((topology) => {
190
+ const existing = topology.sessions.find((entry) => entry.id === sessionId);
191
+ if (existing) {
192
+ existing.status = "graveyard";
193
+ existing.updatedAt = now;
194
+ topology.bindings = topology.bindings.filter((binding) => binding.nodeId !== existing.nodeId);
195
+ moved = topologySessionToSessionState(existing, topology);
196
+ return topology;
197
+ }
198
+ return topology;
199
+ });
200
+ return moved;
201
+ }
202
+ export function removeTopologySessionsForWorktree(worktreePath, input) {
203
+ const store = input?.store ?? createRuntimeTopologyStore();
204
+ const now = input?.now ?? new Date().toISOString();
205
+ let removed = [];
206
+ store.update((topology) => {
207
+ const removing = topology.sessions.filter((session) => session.worktreePath === worktreePath);
208
+ if (removing.length === 0)
209
+ return topology;
210
+ const removingSessionIds = new Set(removing.map((session) => session.id));
211
+ const removingNodeIds = new Set(removing.map((session) => session.nodeId));
212
+ removed = removing.map((session) => topologySessionToSessionState(session, topology));
213
+ topology.generatedAt = now;
214
+ topology.sessions = topology.sessions.filter((session) => !removingSessionIds.has(session.id));
215
+ topology.bindings = topology.bindings.filter((binding) => !removingNodeIds.has(binding.nodeId));
216
+ topology.nodes = topology.nodes.filter((node) => !removingNodeIds.has(node.id));
217
+ topology.lifecycleOperations = topology.lifecycleOperations.filter((operation) => !(operation.targetKind === "session" && removingSessionIds.has(operation.targetId)));
218
+ topology.exchangeRefs = topology.exchangeRefs.filter((ref) => (!ref.sessionId || !removingSessionIds.has(ref.sessionId)) && (!ref.nodeId || !removingNodeIds.has(ref.nodeId)));
219
+ return topology;
220
+ });
221
+ return removed;
222
+ }
223
+ export function resurrectTopologySession(sessionId, input) {
224
+ const store = input?.store ?? createRuntimeTopologyStore();
225
+ const now = input?.now ?? new Date().toISOString();
226
+ let restored;
227
+ store.update((topology) => {
228
+ const session = topology.sessions.find((entry) => entry.id === sessionId && entry.status === "graveyard");
229
+ if (!session)
230
+ return topology;
231
+ session.status = "offline";
232
+ session.updatedAt = now;
233
+ topology.bindings = topology.bindings.filter((binding) => binding.nodeId !== session.nodeId);
234
+ restored = topologySessionToSessionState(session, topology);
235
+ return topology;
236
+ });
237
+ return restored;
238
+ }
@@ -0,0 +1,171 @@
1
+ export declare const RUNTIME_TOPOLOGY_VERSION = 1;
2
+ export type RuntimeTopologySessionStatus = "planned" | "starting" | "running" | "idle" | "offline" | "graveyard" | "error";
3
+ export type RuntimeTopologyServiceStatus = "planned" | "starting" | "running" | "stopped" | "offline" | "error";
4
+ export type RuntimeTopologyWorktreeStatus = "planned" | "creating" | "active" | "removing" | "graveyard" | "missing" | "error";
5
+ export type RuntimeTopologyLifecycleOperationStatus = "pending" | "running" | "succeeded" | "failed" | "cancelled";
6
+ export type RuntimeTopologyLifecycleOperationTargetKind = "session" | "service" | "worktree" | "node" | "rig";
7
+ export interface RuntimeTopologyRig {
8
+ id: string;
9
+ name: string;
10
+ projectRoot: string;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ }
14
+ export interface RuntimeTopologyNode {
15
+ id: string;
16
+ rigId: string;
17
+ logicalId: string;
18
+ role?: string;
19
+ runtime?: string;
20
+ toolConfigKey?: string;
21
+ model?: string;
22
+ cwd?: string;
23
+ label?: string;
24
+ createdAt: string;
25
+ }
26
+ export interface RuntimeTopologyEdge {
27
+ id: string;
28
+ rigId: string;
29
+ sourceNodeId: string;
30
+ targetNodeId: string;
31
+ kind: string;
32
+ createdAt: string;
33
+ }
34
+ export interface RuntimeTopologyBinding {
35
+ id: string;
36
+ nodeId: string;
37
+ tmuxSession?: string;
38
+ tmuxWindowId?: string;
39
+ tmuxWindowIndex?: number;
40
+ tmuxWindowName?: string;
41
+ tmuxPane?: string;
42
+ updatedAt: string;
43
+ }
44
+ export interface RuntimeTopologySession {
45
+ id: string;
46
+ nodeId: string;
47
+ status: RuntimeTopologySessionStatus;
48
+ tool?: string;
49
+ command?: string;
50
+ args?: string[];
51
+ backendSessionId?: string;
52
+ worktreePath?: string;
53
+ label?: string;
54
+ headline?: string;
55
+ team?: unknown;
56
+ createdAt: string;
57
+ updatedAt: string;
58
+ lastSeenAt?: string;
59
+ }
60
+ export interface RuntimeTopologyService {
61
+ id: string;
62
+ rigId: string;
63
+ nodeId?: string;
64
+ status: RuntimeTopologyServiceStatus;
65
+ command?: string;
66
+ args?: string[];
67
+ launchCommandLine?: string;
68
+ worktreePath?: string;
69
+ cwd?: string;
70
+ label?: string;
71
+ createdAt: string;
72
+ updatedAt: string;
73
+ lastSeenAt?: string;
74
+ }
75
+ export interface RuntimeTopologyWorktree {
76
+ id: string;
77
+ rigId: string;
78
+ path: string;
79
+ name: string;
80
+ status: RuntimeTopologyWorktreeStatus;
81
+ branch?: string;
82
+ head?: string;
83
+ basePath?: string;
84
+ createdAt: string;
85
+ updatedAt: string;
86
+ removedAt?: string;
87
+ operationFailure?: string;
88
+ }
89
+ export interface RuntimeTopologyWorktreeGraveyardEntry {
90
+ id: string;
91
+ rigId: string;
92
+ worktreeId?: string;
93
+ path: string;
94
+ name?: string;
95
+ branch?: string;
96
+ graveyardedAt: string;
97
+ reason?: string;
98
+ deletedAt?: string;
99
+ }
100
+ export interface RuntimeTopologyTeamRole {
101
+ id: string;
102
+ rigId: string;
103
+ nodeId?: string;
104
+ parentNodeId?: string;
105
+ role: string;
106
+ label?: string;
107
+ order?: number;
108
+ createdAt: string;
109
+ updatedAt: string;
110
+ }
111
+ export interface RuntimeTopologyRemoteClient {
112
+ id: string;
113
+ rigId: string;
114
+ userId?: string;
115
+ displayName?: string;
116
+ shareId?: string;
117
+ ownerUserId?: string;
118
+ status: "online" | "stale" | "offline";
119
+ connectedAt?: string;
120
+ lastSeenAt: string;
121
+ ownsSessionIds?: string[];
122
+ }
123
+ export interface RuntimeTopologyLifecycleOperation {
124
+ id: string;
125
+ rigId: string;
126
+ kind: string;
127
+ status: RuntimeTopologyLifecycleOperationStatus;
128
+ targetKind: RuntimeTopologyLifecycleOperationTargetKind;
129
+ targetId: string;
130
+ requestedBy?: string;
131
+ startedAt: string;
132
+ updatedAt: string;
133
+ completedAt?: string;
134
+ error?: string;
135
+ }
136
+ export interface RuntimeTopologyExchangeRef {
137
+ id: string;
138
+ rigId: string;
139
+ kind: "message" | "handoff" | "task" | "review" | "plan" | "wait" | "continuity" | "attachment";
140
+ exchangeId: string;
141
+ nodeId?: string;
142
+ sessionId?: string;
143
+ createdAt: string;
144
+ updatedAt: string;
145
+ }
146
+ export interface RuntimeTopology {
147
+ version: typeof RUNTIME_TOPOLOGY_VERSION;
148
+ generatedAt: string;
149
+ rigs: RuntimeTopologyRig[];
150
+ nodes: RuntimeTopologyNode[];
151
+ edges: RuntimeTopologyEdge[];
152
+ bindings: RuntimeTopologyBinding[];
153
+ sessions: RuntimeTopologySession[];
154
+ services: RuntimeTopologyService[];
155
+ worktrees: RuntimeTopologyWorktree[];
156
+ worktreeGraveyard: RuntimeTopologyWorktreeGraveyardEntry[];
157
+ teamRoles: RuntimeTopologyTeamRole[];
158
+ remoteClients: RuntimeTopologyRemoteClient[];
159
+ lifecycleOperations: RuntimeTopologyLifecycleOperation[];
160
+ exchangeRefs: RuntimeTopologyExchangeRef[];
161
+ }
162
+ export declare function emptyRuntimeTopology(now?: string): RuntimeTopology;
163
+ export declare class RuntimeTopologyStore {
164
+ readonly path: string;
165
+ constructor(path?: string);
166
+ read(): RuntimeTopology;
167
+ write(topology: RuntimeTopology): RuntimeTopology;
168
+ private acquireUpdateLock;
169
+ update(mutator: (topology: RuntimeTopology) => RuntimeTopology): RuntimeTopology;
170
+ }
171
+ export declare function createRuntimeTopologyStore(path?: string): RuntimeTopologyStore;