aimux-cli 0.1.5 → 0.1.7

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 (160) hide show
  1. package/dist/builtin-metadata-watchers.js +1 -1
  2. package/dist/context/context-bridge.d.ts +1 -1
  3. package/dist/context/context-bridge.js +1 -1
  4. package/dist/dashboard/command-spec.d.ts +7 -0
  5. package/dist/dashboard/command-spec.js +127 -0
  6. package/dist/dashboard/command-spec.js.map +1 -0
  7. package/dist/{dashboard-feedback.js → dashboard/feedback.js} +1 -1
  8. package/dist/dashboard/feedback.js.map +1 -0
  9. package/dist/{dashboard.d.ts → dashboard/index.d.ts} +16 -5
  10. package/dist/{dashboard.js → dashboard/index.js} +7 -4
  11. package/dist/dashboard/index.js.map +1 -0
  12. package/dist/{dashboard-pending-actions.d.ts → dashboard/pending-actions.d.ts} +8 -3
  13. package/dist/dashboard/pending-actions.js +90 -0
  14. package/dist/dashboard/pending-actions.js.map +1 -0
  15. package/dist/{dashboard-session-actions.d.ts → dashboard/session-actions.d.ts} +2 -2
  16. package/dist/{dashboard-session-actions.js → dashboard/session-actions.js} +1 -1
  17. package/dist/dashboard/session-actions.js.map +1 -0
  18. package/dist/{dashboard-session-registry.d.ts → dashboard/session-registry.d.ts} +7 -7
  19. package/dist/{dashboard-session-registry.js → dashboard/session-registry.js} +2 -2
  20. package/dist/dashboard/session-registry.js.map +1 -0
  21. package/dist/{dashboard-state.d.ts → dashboard/state.d.ts} +1 -1
  22. package/dist/{dashboard-state.js → dashboard/state.js} +1 -1
  23. package/dist/dashboard/state.js.map +1 -0
  24. package/dist/{dashboard-targets.d.ts → dashboard/targets.d.ts} +1 -6
  25. package/dist/{dashboard-targets.js → dashboard/targets.js} +5 -123
  26. package/dist/dashboard/targets.js.map +1 -0
  27. package/dist/{dashboard-ui-state-store.d.ts → dashboard/ui-state-store.d.ts} +2 -2
  28. package/dist/{dashboard-ui-state-store.js → dashboard/ui-state-store.js} +2 -2
  29. package/dist/dashboard/ui-state-store.js.map +1 -0
  30. package/dist/fast-control.d.ts +1 -1
  31. package/dist/fast-control.js +1 -1
  32. package/dist/instance-directory.js +1 -1
  33. package/dist/main.js +6 -5
  34. package/dist/main.js.map +1 -1
  35. package/dist/metadata-server.d.ts +7 -0
  36. package/dist/metadata-server.js +15 -17
  37. package/dist/metadata-server.js.map +1 -1
  38. package/dist/multiplexer/agent-io-methods.d.ts +40 -0
  39. package/dist/multiplexer/agent-io-methods.js +177 -0
  40. package/dist/multiplexer/agent-io-methods.js.map +1 -0
  41. package/dist/multiplexer/archives.d.ts +15 -0
  42. package/dist/multiplexer/archives.js +270 -0
  43. package/dist/multiplexer/archives.js.map +1 -0
  44. package/dist/multiplexer/dashboard-actions-methods.d.ts +57 -0
  45. package/dist/multiplexer/dashboard-actions-methods.js +159 -0
  46. package/dist/multiplexer/dashboard-actions-methods.js.map +1 -0
  47. package/dist/multiplexer/dashboard-control.d.ts +36 -0
  48. package/dist/multiplexer/dashboard-control.js +608 -0
  49. package/dist/multiplexer/dashboard-control.js.map +1 -0
  50. package/dist/multiplexer/dashboard-interaction.d.ts +12 -0
  51. package/dist/multiplexer/dashboard-interaction.js +552 -0
  52. package/dist/multiplexer/dashboard-interaction.js.map +1 -0
  53. package/dist/multiplexer/dashboard-model.d.ts +40 -0
  54. package/dist/multiplexer/dashboard-model.js +421 -0
  55. package/dist/multiplexer/dashboard-model.js.map +1 -0
  56. package/dist/multiplexer/dashboard-ops.d.ts +35 -0
  57. package/dist/multiplexer/dashboard-ops.js +158 -0
  58. package/dist/multiplexer/dashboard-ops.js.map +1 -0
  59. package/dist/multiplexer/dashboard-state-methods.d.ts +56 -0
  60. package/dist/multiplexer/dashboard-state-methods.js +123 -0
  61. package/dist/multiplexer/dashboard-state-methods.js.map +1 -0
  62. package/dist/multiplexer/dashboard-tail-methods.d.ts +104 -0
  63. package/dist/multiplexer/dashboard-tail-methods.js +252 -0
  64. package/dist/multiplexer/dashboard-tail-methods.js.map +1 -0
  65. package/dist/multiplexer/dashboard-view-methods.d.ts +51 -0
  66. package/dist/multiplexer/dashboard-view-methods.js +159 -0
  67. package/dist/multiplexer/dashboard-view-methods.js.map +1 -0
  68. package/dist/multiplexer/index.d.ts +205 -0
  69. package/dist/multiplexer/index.js +444 -0
  70. package/dist/multiplexer/index.js.map +1 -0
  71. package/dist/multiplexer/navigation.d.ts +17 -0
  72. package/dist/multiplexer/navigation.js +203 -0
  73. package/dist/multiplexer/navigation.js.map +1 -0
  74. package/dist/multiplexer/notifications.d.ts +6 -0
  75. package/dist/multiplexer/notifications.js +75 -0
  76. package/dist/multiplexer/notifications.js.map +1 -0
  77. package/dist/multiplexer/persistence-methods.d.ts +83 -0
  78. package/dist/multiplexer/persistence-methods.js +370 -0
  79. package/dist/multiplexer/persistence-methods.js.map +1 -0
  80. package/dist/multiplexer/runtime-lifecycle-methods.d.ts +36 -0
  81. package/dist/multiplexer/runtime-lifecycle-methods.js +235 -0
  82. package/dist/multiplexer/runtime-lifecycle-methods.js.map +1 -0
  83. package/dist/multiplexer/runtime-state.d.ts +32 -0
  84. package/dist/multiplexer/runtime-state.js +439 -0
  85. package/dist/multiplexer/runtime-state.js.map +1 -0
  86. package/dist/{multiplexer-runtime-sync.d.ts → multiplexer/runtime-sync.d.ts} +2 -2
  87. package/dist/{multiplexer-runtime-sync.js → multiplexer/runtime-sync.js} +1 -1
  88. package/dist/multiplexer/runtime-sync.js.map +1 -0
  89. package/dist/multiplexer/services.d.ts +23 -0
  90. package/dist/multiplexer/services.js +187 -0
  91. package/dist/multiplexer/services.js.map +1 -0
  92. package/dist/multiplexer/session-actions.d.ts +36 -0
  93. package/dist/multiplexer/session-actions.js +108 -0
  94. package/dist/multiplexer/session-actions.js.map +1 -0
  95. package/dist/multiplexer/session-launch.d.ts +20 -0
  96. package/dist/multiplexer/session-launch.js +407 -0
  97. package/dist/multiplexer/session-launch.js.map +1 -0
  98. package/dist/multiplexer/session-runtime-core.d.ts +37 -0
  99. package/dist/multiplexer/session-runtime-core.js +402 -0
  100. package/dist/multiplexer/session-runtime-core.js.map +1 -0
  101. package/dist/multiplexer/subscreens.d.ts +30 -0
  102. package/dist/multiplexer/subscreens.js +685 -0
  103. package/dist/multiplexer/subscreens.js.map +1 -0
  104. package/dist/multiplexer/tool-picker.d.ts +8 -0
  105. package/dist/multiplexer/tool-picker.js +142 -0
  106. package/dist/multiplexer/tool-picker.js.map +1 -0
  107. package/dist/multiplexer/worktrees.d.ts +12 -0
  108. package/dist/multiplexer/worktrees.js +181 -0
  109. package/dist/multiplexer/worktrees.js.map +1 -0
  110. package/dist/project-scanner.d.ts +1 -1
  111. package/dist/project-scanner.js +1 -1
  112. package/dist/session-bootstrap.d.ts +1 -1
  113. package/dist/session-semantics.d.ts +1 -1
  114. package/dist/{tmux-doctor.d.ts → tmux/doctor.d.ts} +14 -1
  115. package/dist/{tmux-doctor.js → tmux/doctor.js} +78 -3
  116. package/dist/tmux/doctor.js.map +1 -0
  117. package/dist/{tmux-runtime-manager.d.ts → tmux/runtime-manager.d.ts} +1 -0
  118. package/dist/{tmux-runtime-manager.js → tmux/runtime-manager.js} +31 -12
  119. package/dist/tmux/runtime-manager.js.map +1 -0
  120. package/dist/{tmux-session-transport.d.ts → tmux/session-transport.d.ts} +3 -2
  121. package/dist/{tmux-session-transport.js → tmux/session-transport.js} +5 -2
  122. package/dist/tmux/session-transport.js.map +1 -0
  123. package/dist/{tmux-statusline.d.ts → tmux/statusline.d.ts} +1 -1
  124. package/dist/{tmux-statusline.js → tmux/statusline.js} +4 -4
  125. package/dist/tmux/statusline.js.map +1 -0
  126. package/dist/{tmux-switcher.js → tmux/switcher.js} +7 -7
  127. package/dist/tmux/switcher.js.map +1 -0
  128. package/dist/{tmux-window-open.d.ts → tmux/window-open.d.ts} +1 -1
  129. package/dist/{tmux-window-open.js → tmux/window-open.js} +1 -1
  130. package/dist/tmux/window-open.js.map +1 -0
  131. package/dist/tool-output-watchers.js +1 -1
  132. package/dist/tui/render/box.js +25 -6
  133. package/dist/tui/render/box.js.map +1 -1
  134. package/dist/tui/screens/dashboard-renderers.d.ts +3 -2
  135. package/dist/tui/screens/dashboard-renderers.js +17 -2
  136. package/dist/tui/screens/dashboard-renderers.js.map +1 -1
  137. package/dist/tui/screens/overlay-renderers.js +2 -2
  138. package/dist/tui/screens/overlay-renderers.js.map +1 -1
  139. package/package.json +1 -1
  140. package/dist/dashboard-feedback.js.map +0 -1
  141. package/dist/dashboard-pending-actions.js +0 -52
  142. package/dist/dashboard-pending-actions.js.map +0 -1
  143. package/dist/dashboard-session-actions.js.map +0 -1
  144. package/dist/dashboard-session-registry.js.map +0 -1
  145. package/dist/dashboard-state.js.map +0 -1
  146. package/dist/dashboard-targets.js.map +0 -1
  147. package/dist/dashboard-ui-state-store.js.map +0 -1
  148. package/dist/dashboard.js.map +0 -1
  149. package/dist/multiplexer-runtime-sync.js.map +0 -1
  150. package/dist/multiplexer.d.ts +0 -500
  151. package/dist/multiplexer.js +0 -6081
  152. package/dist/multiplexer.js.map +0 -1
  153. package/dist/tmux-doctor.js.map +0 -1
  154. package/dist/tmux-runtime-manager.js.map +0 -1
  155. package/dist/tmux-session-transport.js.map +0 -1
  156. package/dist/tmux-statusline.js.map +0 -1
  157. package/dist/tmux-switcher.js.map +0 -1
  158. package/dist/tmux-window-open.js.map +0 -1
  159. /package/dist/{dashboard-feedback.d.ts → dashboard/feedback.d.ts} +0 -0
  160. /package/dist/{tmux-switcher.d.ts → tmux/switcher.d.ts} +0 -0
@@ -0,0 +1,370 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { spawn } from "node:child_process";
3
+ import { basename, join } from "node:path";
4
+ import { debug } from "../debug.js";
5
+ import { DashboardPendingActions } from "../dashboard/pending-actions.js";
6
+ import { loadDaemonInfo } from "../daemon.js";
7
+ import { getGraveyardPath, getLocalAimuxDir, getProjectStateDir, getStatePath } from "../paths.js";
8
+ import { loadMetadataState } from "../metadata-store.js";
9
+ import { renderCurrentDashboardView as renderCurrentDashboardViewImpl } from "./runtime-state.js";
10
+ import { loadStatusline, renderTmuxStatuslineFromData } from "../tmux/statusline.js";
11
+ import { findMainRepo, listWorktrees as listAllWorktrees } from "../worktree.js";
12
+ export const persistenceMethods = {
13
+ writeSessionsFile() {
14
+ const dir = getLocalAimuxDir();
15
+ if (!existsSync(dir))
16
+ mkdirSync(dir, { recursive: true });
17
+ const localSessions = this.sessions.map((s) => ({
18
+ id: s.id,
19
+ tool: s.command,
20
+ backendSessionId: s.backendSessionId,
21
+ worktreePath: this.sessionWorktreePaths.get(s.id),
22
+ }));
23
+ const data = this.instanceDirectory.buildSessionsFileEntries(localSessions, this.instanceDirectory.getRemoteInstancesSafe(this.instanceId, process.cwd()));
24
+ writeFileSync(`${dir}/sessions.json`, JSON.stringify(data, null, 2) + "\n");
25
+ },
26
+ writeStatuslineFile() {
27
+ try {
28
+ if (this.mode !== "project-service")
29
+ return;
30
+ this.repairManagedTmuxTargets();
31
+ for (const session of this.sessions) {
32
+ this.syncTmuxWindowMetadata(session.id);
33
+ }
34
+ this.refreshDesktopStateSnapshot();
35
+ const dir = getProjectStateDir();
36
+ const filePath = join(dir, "statusline.json");
37
+ const tmpPath = `${filePath}.tmp`;
38
+ const data = this.buildStatuslineSnapshot();
39
+ const { updatedAt: _updatedAt, ...stableData } = data;
40
+ const snapshotKey = JSON.stringify(stableData);
41
+ if (snapshotKey === this.lastStatuslineSnapshotKey) {
42
+ return;
43
+ }
44
+ this.lastStatuslineSnapshotKey = snapshotKey;
45
+ writeFileSync(tmpPath, JSON.stringify(data) + "\n");
46
+ renameSync(tmpPath, filePath);
47
+ this.writePrecomputedTmuxStatuslineFiles(data);
48
+ this.tmuxRuntimeManager.refreshStatus();
49
+ }
50
+ catch { }
51
+ },
52
+ repairManagedTmuxTargets() {
53
+ const managedWindows = this.tmuxRuntimeManager.listProjectManagedWindows(process.cwd());
54
+ const liveTargets = new Map();
55
+ for (const { target, metadata } of managedWindows) {
56
+ liveTargets.set(metadata.sessionId, target);
57
+ }
58
+ for (const session of this.sessions) {
59
+ const target = liveTargets.get(session.id);
60
+ if (!target)
61
+ continue;
62
+ this.sessionTmuxTargets.set(session.id, target);
63
+ if (session.transport instanceof Object && typeof session.transport.retarget === "function") {
64
+ session.transport.retarget(target);
65
+ }
66
+ }
67
+ },
68
+ refreshProjectStatusline(_input) {
69
+ this.repairManagedTmuxTargets();
70
+ this.invalidateDesktopStateSnapshot();
71
+ this.writeStatuslineFile();
72
+ return { ok: true };
73
+ },
74
+ getTmuxStatuslineDir() {
75
+ const dir = join(getProjectStateDir(), "tmux-statusline");
76
+ mkdirSync(dir, { recursive: true });
77
+ return dir;
78
+ },
79
+ writeStatuslineTextFile(name, content) {
80
+ const dir = this.getTmuxStatuslineDir();
81
+ const filePath = join(dir, name);
82
+ const tmpPath = `${filePath}.tmp`;
83
+ writeFileSync(tmpPath, `${content}\n`);
84
+ renameSync(tmpPath, filePath);
85
+ },
86
+ writePrecomputedTmuxStatuslineFiles(data) {
87
+ const dashboardTop = renderTmuxStatuslineFromData(data, process.cwd(), "top", {
88
+ currentWindow: "dashboard",
89
+ currentPath: process.cwd(),
90
+ });
91
+ const dashboardBottom = renderTmuxStatuslineFromData(data, process.cwd(), "bottom", {
92
+ currentWindow: "dashboard",
93
+ currentPath: process.cwd(),
94
+ });
95
+ this.writeStatuslineTextFile("top-dashboard.txt", dashboardTop);
96
+ this.writeStatuslineTextFile("bottom-dashboard.txt", dashboardBottom);
97
+ for (const entry of data.sessions) {
98
+ if (!entry.tmuxWindowId)
99
+ continue;
100
+ const renderOptions = {
101
+ currentWindow: entry.windowName,
102
+ currentWindowId: entry.tmuxWindowId,
103
+ currentPath: entry.worktreePath ?? process.cwd(),
104
+ };
105
+ const top = renderTmuxStatuslineFromData(data, process.cwd(), "top", renderOptions);
106
+ const bottom = renderTmuxStatuslineFromData(data, process.cwd(), "bottom", renderOptions);
107
+ this.writeStatuslineTextFile(`top-${entry.tmuxWindowId}.txt`, top);
108
+ this.writeStatuslineTextFile(`bottom-${entry.tmuxWindowId}.txt`, bottom);
109
+ }
110
+ },
111
+ writeDashboardClientStatuslineFile() {
112
+ if (this.mode !== "dashboard")
113
+ return;
114
+ const clientSession = this.tmuxRuntimeManager.currentClientSession();
115
+ if (!clientSession)
116
+ return;
117
+ const localData = loadStatusline(process.cwd()) ?? {
118
+ project: basename(process.cwd()),
119
+ sessions: [],
120
+ metadata: {},
121
+ tasks: { pending: 0, assigned: 0 },
122
+ controlPlane: { daemonAlive: true, projectServiceAlive: false },
123
+ flash: null,
124
+ updatedAt: new Date().toISOString(),
125
+ };
126
+ const data = { ...localData, dashboardScreen: this.dashboardState.screen };
127
+ const bottom = renderTmuxStatuslineFromData(data, process.cwd(), "bottom", {
128
+ currentSession: clientSession,
129
+ currentWindow: this.tmuxRuntimeManager.displayMessage("#{window_name}") ?? "dashboard",
130
+ currentPath: process.cwd(),
131
+ });
132
+ this.writeStatuslineTextFile(`bottom-dashboard-${clientSession}.txt`, bottom);
133
+ },
134
+ buildStatuslineSnapshot() {
135
+ const desktopState = this.desktopStateSnapshot ?? this.buildDesktopStateSnapshot();
136
+ return {
137
+ project: basename(process.cwd()),
138
+ dashboardScreen: this.dashboardState.screen,
139
+ sessions: [
140
+ ...desktopState.sessions.map((session) => ({
141
+ id: session.id,
142
+ kind: "agent",
143
+ tool: session.command,
144
+ label: session.label,
145
+ tmuxWindowId: session.tmuxWindowId,
146
+ tmuxWindowIndex: session.tmuxWindowIndex,
147
+ windowName: session.command,
148
+ headline: session.headline,
149
+ status: session.status,
150
+ role: session.role,
151
+ active: session.active,
152
+ worktreePath: session.worktreePath,
153
+ semantic: session.semantic,
154
+ })),
155
+ ...desktopState.services.map((service) => ({
156
+ id: service.id,
157
+ kind: "service",
158
+ tool: service.command,
159
+ label: service.label,
160
+ tmuxWindowId: service.tmuxWindowId,
161
+ tmuxWindowIndex: service.tmuxWindowIndex,
162
+ windowName: service.command,
163
+ headline: service.previewLine,
164
+ status: service.status,
165
+ active: service.active,
166
+ worktreePath: service.worktreePath,
167
+ })),
168
+ ],
169
+ tasks: this.taskDispatcher?.getTaskCounts() ?? { pending: 0, assigned: 0 },
170
+ controlPlane: {
171
+ daemonAlive: Boolean(loadDaemonInfo()),
172
+ projectServiceAlive: true,
173
+ },
174
+ flash: this.footerFlash,
175
+ metadata: loadMetadataState().sessions,
176
+ updatedAt: new Date().toISOString(),
177
+ };
178
+ },
179
+ buildDesktopState() {
180
+ if (!this.desktopStateSnapshot) {
181
+ this.refreshDesktopStateSnapshot();
182
+ }
183
+ const desktopState = this.desktopStateSnapshot ?? this.buildDesktopStateSnapshot();
184
+ return {
185
+ sessions: desktopState.sessions,
186
+ services: desktopState.services,
187
+ statusline: this.buildStatuslineSnapshot(),
188
+ worktrees: desktopState.worktrees,
189
+ mainCheckoutInfo: desktopState.mainCheckoutInfo,
190
+ mainCheckoutPath: desktopState.mainCheckoutPath,
191
+ };
192
+ },
193
+ reapplyDashboardPendingActions() {
194
+ this.dashboardSessionsCache = this.dashboardPendingActions.applyToSessions(this.dashboardSessionsCache.map(({ pendingAction: _pendingAction, optimistic: _optimistic, ...session }) => session));
195
+ this.dashboardServicesCache = this.dashboardPendingActions.applyToServices(this.dashboardServicesCache.map(({ pendingAction: _pendingAction, optimistic: _optimistic, ...service }) => service));
196
+ this.dashboardWorktreeGroupsCache = this.dashboardPendingActions.applyToWorktrees(this.dashboardWorktreeGroupsCache.map(({ pendingAction: _pendingAction, optimistic: _optimistic, pending: _pending, removing: _removing, ...wt }) => wt));
197
+ },
198
+ listDesktopWorktrees() {
199
+ const pendingRemovals = this.pendingWorktreeRemovals;
200
+ return listAllWorktrees()
201
+ .filter((wt) => !wt.isBare)
202
+ .map((wt) => ({
203
+ ...wt,
204
+ pending: pendingRemovals?.has(wt.path) ?? false,
205
+ removing: pendingRemovals?.has(wt.path) ?? false,
206
+ }));
207
+ },
208
+ async removeDesktopWorktree(path) {
209
+ const pendingRemovals = this.pendingWorktreeRemovals;
210
+ const existingRemoval = pendingRemovals.get(path);
211
+ if (existingRemoval) {
212
+ return existingRemoval;
213
+ }
214
+ let resolveRemoval;
215
+ let rejectRemoval;
216
+ const removalPromise = new Promise((resolve, reject) => {
217
+ resolveRemoval = resolve;
218
+ rejectRemoval = reject;
219
+ });
220
+ pendingRemovals.set(path, removalPromise);
221
+ this.dashboardPendingActions.set(DashboardPendingActions.worktreeKey(path), "removing", {
222
+ timeoutMs: 180_000,
223
+ onTimeout: () => {
224
+ this.footerFlash = `Timed out removing ${path.split("/").pop() ?? path}`;
225
+ this.footerFlashTicks = 5;
226
+ this.invalidateDesktopStateSnapshot();
227
+ this.refreshLocalDashboardModel();
228
+ if (this.mode === "dashboard") {
229
+ this.renderDashboard();
230
+ }
231
+ },
232
+ });
233
+ this.invalidateDesktopStateSnapshot();
234
+ this.refreshLocalDashboardModel();
235
+ if (this.mode === "dashboard") {
236
+ this.renderDashboard();
237
+ }
238
+ void (async () => {
239
+ try {
240
+ this.syncSessionsFromState();
241
+ const mainRepo = findMainRepo();
242
+ if (path === mainRepo) {
243
+ throw new Error("Cannot remove the main checkout");
244
+ }
245
+ const matching = this.listDesktopWorktrees().find((worktree) => worktree.path === path);
246
+ if (!matching) {
247
+ if (!existsSync(path)) {
248
+ this.offlineSessions = this.offlineSessions.filter((session) => session.worktreePath !== path);
249
+ this.offlineServices = this.offlineServices.filter((service) => service.worktreePath !== path);
250
+ this.saveState();
251
+ resolveRemoval({ path, status: "removed" });
252
+ return;
253
+ }
254
+ throw new Error(`Worktree "${path}" not found`);
255
+ }
256
+ const attachedSession = this.sessions.find((session) => session.worktreePath === path && this.isSessionRuntimeLive(session));
257
+ if (attachedSession) {
258
+ throw new Error(`Cannot remove "${matching.name}" while agent "${attachedSession.label || attachedSession.id}" is attached`);
259
+ }
260
+ const attachedService = this.buildLiveServiceStates().find((service) => service.worktreePath === path);
261
+ if (attachedService) {
262
+ throw new Error(`Cannot remove "${matching.name}" while service "${attachedService.label || attachedService.id}" is attached`);
263
+ }
264
+ await new Promise((resolve, reject) => {
265
+ let stderr = "";
266
+ let child;
267
+ try {
268
+ child = spawn("git", ["worktree", "remove", path, "--force"], {
269
+ cwd: mainRepo,
270
+ stdio: ["ignore", "ignore", "pipe"],
271
+ });
272
+ }
273
+ catch (error) {
274
+ reject(error);
275
+ return;
276
+ }
277
+ child.stderr.on("data", (chunk) => {
278
+ const text = chunk.toString();
279
+ stderr += text;
280
+ if (this.worktreeRemovalJob?.path === path) {
281
+ this.worktreeRemovalJob.stderr = stderr;
282
+ if (this.mode === "dashboard") {
283
+ this.renderDashboard();
284
+ }
285
+ }
286
+ });
287
+ child.on("error", reject);
288
+ child.on("close", (code) => {
289
+ if (code === 0) {
290
+ resolve();
291
+ return;
292
+ }
293
+ const detail = stderr
294
+ .split("\n")
295
+ .map((line) => line.trim())
296
+ .filter(Boolean)
297
+ .at(-1);
298
+ reject(new Error(detail || `git worktree remove exited with code ${code ?? 1}`));
299
+ });
300
+ });
301
+ this.offlineSessions = this.offlineSessions.filter((session) => session.worktreePath !== path);
302
+ this.offlineServices = this.offlineServices.filter((service) => service.worktreePath !== path);
303
+ this.saveState();
304
+ resolveRemoval({ path, status: "removed" });
305
+ }
306
+ catch (error) {
307
+ rejectRemoval(error);
308
+ }
309
+ })();
310
+ removalPromise.finally(() => {
311
+ this.dashboardPendingActions.set(DashboardPendingActions.worktreeKey(path), null);
312
+ pendingRemovals.delete(path);
313
+ this.invalidateDesktopStateSnapshot();
314
+ this.refreshLocalDashboardModel();
315
+ if (this.mode === "dashboard") {
316
+ this.renderDashboard();
317
+ }
318
+ });
319
+ return removalPromise;
320
+ },
321
+ listGraveyardEntries() {
322
+ try {
323
+ const content = readFileSync(getGraveyardPath(), "utf-8");
324
+ return JSON.parse(content);
325
+ }
326
+ catch {
327
+ return [];
328
+ }
329
+ },
330
+ async resurrectGraveyardSession(sessionId) {
331
+ this.loadOfflineSessions();
332
+ const graveyardEntries = this.listGraveyardEntries();
333
+ const entry = graveyardEntries.find((candidate) => candidate.id === sessionId);
334
+ if (!entry) {
335
+ throw new Error(`Graveyard session "${sessionId}" not found`);
336
+ }
337
+ const nextGraveyard = graveyardEntries.filter((candidate) => candidate.id !== sessionId);
338
+ writeFileSync(getGraveyardPath(), JSON.stringify(nextGraveyard, null, 2) + "\n");
339
+ this.offlineSessions.push(entry);
340
+ const statePath = getStatePath();
341
+ try {
342
+ let state = { savedAt: new Date().toISOString(), cwd: process.cwd(), sessions: [] };
343
+ if (existsSync(statePath)) {
344
+ state = JSON.parse(readFileSync(statePath, "utf-8"));
345
+ }
346
+ state.sessions.push(entry);
347
+ writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
348
+ }
349
+ catch { }
350
+ debug(`resurrected ${entry.id} from graveyard`, "session");
351
+ return { sessionId, status: "offline" };
352
+ },
353
+ removeSessionsFile() {
354
+ try {
355
+ unlinkSync(`${getLocalAimuxDir()}/sessions.json`);
356
+ }
357
+ catch { }
358
+ },
359
+ stripAnsi(text) {
360
+ return text.replace(/\u001B\[[0-9;]*m/g, "");
361
+ },
362
+ centerInWidth(text, width) {
363
+ const pad = Math.max(0, Math.floor((width - this.stripAnsi(text).length) / 2));
364
+ return " ".repeat(pad) + text;
365
+ },
366
+ renderCurrentDashboardView() {
367
+ renderCurrentDashboardViewImpl(this);
368
+ },
369
+ };
370
+ //# sourceMappingURL=persistence-methods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence-methods.js","sourceRoot":"","sources":["../../src/multiplexer/persistence-methods.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { InstanceSessionRef } from "../instance-registry.js";
2
+ import type { SessionRuntime } from "../session-runtime.js";
3
+ import type { Multiplexer, SavedState, ServiceState, SessionState } from "./index.js";
4
+ import { getRemoteInstancesSafe as getRemoteInstancesSafeImpl } from "./runtime-state.js";
5
+ export type RuntimeLifecycleMethods = {
6
+ writeInstructionFiles(this: Multiplexer): void;
7
+ removeInstructionFiles(this: Multiplexer): void;
8
+ startStatusRefresh(this: Multiplexer): void;
9
+ stopStatusRefresh(this: Multiplexer): void;
10
+ syncSessionsFromState(this: Multiplexer, state?: SavedState | null): void;
11
+ loadOfflineSessions(this: Multiplexer, state?: SavedState | null): boolean;
12
+ loadOfflineServices(this: Multiplexer, state?: SavedState | null): boolean;
13
+ buildLiveServiceStates(this: Multiplexer): ServiceState[];
14
+ restoreTmuxSessionsFromState(this: Multiplexer, state?: SavedState | null): void;
15
+ stopSessionToOffline(this: Multiplexer, session: SessionRuntime): void;
16
+ adjustAfterRemove(this: Multiplexer, hasWorktrees: boolean): void;
17
+ graveyardSession(this: Multiplexer, sessionId: string): void;
18
+ isSessionRuntimeLive(this: Multiplexer, runtime: SessionRuntime): boolean;
19
+ evictZombieSession(this: Multiplexer, runtime: SessionRuntime): void;
20
+ resumeOfflineSession(this: Multiplexer, session: SessionState): void;
21
+ startHeartbeat(this: Multiplexer): void;
22
+ handleSessionClaimed(this: Multiplexer, sessionId: string): void;
23
+ stopHeartbeat(this: Multiplexer): void;
24
+ startProjectServiceRefresh(this: Multiplexer): void;
25
+ stopProjectServiceRefresh(this: Multiplexer): void;
26
+ getRemoteInstancesSafe(this: Multiplexer): ReturnType<typeof getRemoteInstancesSafeImpl>;
27
+ getRemoteOwnedSessionKeys(this: Multiplexer): Set<string>;
28
+ getInstanceSessionRefs(this: Multiplexer): InstanceSessionRef[];
29
+ saveState(this: Multiplexer): void;
30
+ teardown(this: Multiplexer): void;
31
+ cleanup(this: Multiplexer): void;
32
+ cleanupTerminalOnly(this: Multiplexer): void;
33
+ exitDashboardClientOrProcess(this: Multiplexer): void;
34
+ };
35
+ export declare function loadStateStatic(): SavedState | null;
36
+ export declare const runtimeLifecycleMethods: RuntimeLifecycleMethods;
@@ -0,0 +1,235 @@
1
+ import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { closeDebug, debug } from "../debug.js";
5
+ import { loadConfig } from "../config.js";
6
+ import { getStatePath } from "../paths.js";
7
+ import { adjustAfterRemove as adjustAfterRemoveImpl, buildLiveServiceStates as buildLiveServiceStatesImpl, evictZombieSession as evictZombieSessionImpl, getInstanceSessionRefs as getInstanceSessionRefsImpl, getRemoteInstancesSafe as getRemoteInstancesSafeImpl, getRemoteOwnedSessionKeys as getRemoteOwnedSessionKeysImpl, graveyardSession as graveyardSessionImpl, handleSessionClaimed as handleSessionClaimedImpl, isSessionRuntimeLive as isSessionRuntimeLiveImpl, loadOfflineServices as loadOfflineServicesImpl, loadOfflineSessions as loadOfflineSessionsImpl, restoreTmuxSessionsFromState as restoreTmuxSessionsFromStateImpl, resumeOfflineSession as resumeOfflineSessionImpl, startHeartbeat as startHeartbeatImpl, startProjectServiceRefresh as startProjectServiceRefreshImpl, startStatusRefresh as startStatusRefreshImpl, stopHeartbeat as stopHeartbeatImpl, stopProjectServiceRefresh as stopProjectServiceRefreshImpl, stopSessionToOffline as stopSessionToOfflineImpl, stopStatusRefresh as stopStatusRefreshImpl, syncSessionsFromState as syncSessionsFromStateImpl, } from "./runtime-state.js";
8
+ export function loadStateStatic() {
9
+ const statePath = getStatePath();
10
+ if (!existsSync(statePath))
11
+ return null;
12
+ try {
13
+ const raw = readFileSync(statePath, "utf-8");
14
+ const state = JSON.parse(raw);
15
+ return state;
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ export const runtimeLifecycleMethods = {
22
+ writeInstructionFiles() {
23
+ const mux = this;
24
+ const config = loadConfig();
25
+ const preamble = "# aimux Agent Instructions\n\n" +
26
+ "You are running inside aimux, an agent multiplexer. " +
27
+ "Other agents may be working on this codebase simultaneously.\n\n" +
28
+ "## Context Files\n" +
29
+ "- `.aimux/context/{session-id}/live.md` — each agent's recent conversation\n" +
30
+ "- `.aimux/context/{session-id}/summary.md` — each agent's compacted history\n" +
31
+ "- `.aimux/sessions.json` — all running agents (use to find other agents' session IDs)\n" +
32
+ "- `.aimux/history/` — full raw conversation history (JSONL)\n\n" +
33
+ "Check sessions.json to discover other agents, then read their context files.\n" +
34
+ "This file is auto-generated by aimux and will be removed when aimux exits.\n";
35
+ let fullPreamble = preamble;
36
+ for (const mdPath of [join(homedir(), "AIMUX.md"), join(process.cwd(), "AIMUX.md")]) {
37
+ if (existsSync(mdPath)) {
38
+ try {
39
+ const userContent = readFileSync(mdPath, "utf-8").trim();
40
+ if (userContent) {
41
+ fullPreamble += "\n## User Instructions\n\n" + userContent + "\n";
42
+ debug(`loaded ${mdPath} for instructions file (${userContent.length} chars)`, "preamble");
43
+ }
44
+ }
45
+ catch { }
46
+ }
47
+ }
48
+ for (const [, tool] of Object.entries(config.tools)) {
49
+ if (!tool.instructionsFile || !tool.enabled)
50
+ continue;
51
+ const filePath = join(process.cwd(), tool.instructionsFile);
52
+ if (existsSync(filePath) && !mux.writtenInstructionFiles.has(filePath)) {
53
+ debug(`skipping ${tool.instructionsFile} — already exists`, "context");
54
+ continue;
55
+ }
56
+ writeFileSync(filePath, fullPreamble);
57
+ mux.writtenInstructionFiles.add(filePath);
58
+ debug(`wrote ${tool.instructionsFile}`, "context");
59
+ }
60
+ },
61
+ removeInstructionFiles() {
62
+ const mux = this;
63
+ for (const filePath of mux.writtenInstructionFiles) {
64
+ try {
65
+ unlinkSync(filePath);
66
+ }
67
+ catch { }
68
+ }
69
+ mux.writtenInstructionFiles.clear();
70
+ },
71
+ startStatusRefresh() {
72
+ startStatusRefreshImpl(this);
73
+ },
74
+ stopStatusRefresh() {
75
+ stopStatusRefreshImpl(this);
76
+ },
77
+ syncSessionsFromState(state = loadStateStatic()) {
78
+ syncSessionsFromStateImpl(this, state);
79
+ },
80
+ loadOfflineSessions(state = loadStateStatic()) {
81
+ return loadOfflineSessionsImpl(this, state);
82
+ },
83
+ loadOfflineServices(state = loadStateStatic()) {
84
+ return loadOfflineServicesImpl(this, state);
85
+ },
86
+ buildLiveServiceStates() {
87
+ return buildLiveServiceStatesImpl(this);
88
+ },
89
+ restoreTmuxSessionsFromState(state = loadStateStatic()) {
90
+ restoreTmuxSessionsFromStateImpl(this, state);
91
+ },
92
+ stopSessionToOffline(session) {
93
+ stopSessionToOfflineImpl(this, session);
94
+ },
95
+ adjustAfterRemove(hasWorktrees) {
96
+ adjustAfterRemoveImpl(this, hasWorktrees);
97
+ },
98
+ graveyardSession(sessionId) {
99
+ graveyardSessionImpl(this, sessionId);
100
+ },
101
+ isSessionRuntimeLive(runtime) {
102
+ return isSessionRuntimeLiveImpl(this, runtime);
103
+ },
104
+ evictZombieSession(runtime) {
105
+ evictZombieSessionImpl(this, runtime);
106
+ },
107
+ resumeOfflineSession(session) {
108
+ resumeOfflineSessionImpl(this, session);
109
+ },
110
+ startHeartbeat() {
111
+ startHeartbeatImpl(this);
112
+ },
113
+ handleSessionClaimed(sessionId) {
114
+ handleSessionClaimedImpl(this, sessionId);
115
+ },
116
+ stopHeartbeat() {
117
+ stopHeartbeatImpl(this);
118
+ },
119
+ startProjectServiceRefresh() {
120
+ startProjectServiceRefreshImpl(this);
121
+ },
122
+ stopProjectServiceRefresh() {
123
+ stopProjectServiceRefreshImpl(this);
124
+ },
125
+ getRemoteInstancesSafe() {
126
+ return getRemoteInstancesSafeImpl(this);
127
+ },
128
+ getRemoteOwnedSessionKeys() {
129
+ return getRemoteOwnedSessionKeysImpl(this);
130
+ },
131
+ getInstanceSessionRefs() {
132
+ return getInstanceSessionRefsImpl(this);
133
+ },
134
+ saveState() {
135
+ const mux = this;
136
+ const liveSessions = mux.sessions.map((s) => ({
137
+ id: s.id,
138
+ tool: s.command,
139
+ toolConfigKey: mux.sessionToolKeys.get(s.id) ?? s.command,
140
+ command: s.command,
141
+ args: mux.sessionOriginalArgs.get(s.id) ?? [],
142
+ backendSessionId: s.backendSessionId,
143
+ worktreePath: mux.sessionWorktreePaths.get(s.id),
144
+ label: this.getSessionLabel(s.id),
145
+ headline: this.deriveHeadline(s.id),
146
+ tmuxTarget: mux.sessionTmuxTargets.get(s.id),
147
+ }));
148
+ const mySessions = [...mux.offlineSessions, ...liveSessions];
149
+ const liveServices = this.buildLiveServiceStates();
150
+ const myServices = [...mux.offlineServices, ...liveServices].filter((service, index, services) => services.findIndex((entry) => entry.id === service.id) === index);
151
+ if (mySessions.length === 0 && myServices.length === 0)
152
+ return;
153
+ const statePath = getStatePath();
154
+ let mergedSessions = mySessions;
155
+ let mergedServices = myServices;
156
+ if (existsSync(statePath)) {
157
+ try {
158
+ const existing = JSON.parse(readFileSync(statePath, "utf-8"));
159
+ const myBackendIds = new Set(mySessions.map((s) => s.backendSessionId).filter(Boolean));
160
+ const myIds = new Set(mySessions.map((s) => s.id));
161
+ const otherSessions = existing.sessions.filter((s) => {
162
+ if (s.backendSessionId && myBackendIds.has(s.backendSessionId))
163
+ return false;
164
+ if (myIds.has(s.id))
165
+ return false;
166
+ return true;
167
+ });
168
+ mergedSessions = [...otherSessions, ...mySessions];
169
+ const myServiceIds = new Set(myServices.map((service) => service.id));
170
+ const otherServices = (existing.services ?? []).filter((service) => !myServiceIds.has(service.id));
171
+ mergedServices = [...otherServices, ...myServices];
172
+ }
173
+ catch { }
174
+ }
175
+ const state = {
176
+ savedAt: new Date().toISOString(),
177
+ cwd: process.cwd(),
178
+ sessions: mergedSessions,
179
+ services: mergedServices,
180
+ };
181
+ writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
182
+ this.invalidateDesktopStateSnapshot();
183
+ },
184
+ teardown() {
185
+ const mux = this;
186
+ debug("teardown started", "session");
187
+ this.clearDashboardBusy();
188
+ this.stopHeartbeat();
189
+ this.stopProjectServiceRefresh();
190
+ mux.taskDispatcher = null;
191
+ mux.orchestrationDispatcher = null;
192
+ mux.instanceDirectory.unregisterInstance(mux.instanceId, process.cwd()).catch(() => { });
193
+ this.saveState();
194
+ this.stopStatusRefresh();
195
+ mux.contextWatcher.stop();
196
+ this.removeSessionsFile();
197
+ this.removeInstructionFiles();
198
+ closeDebug();
199
+ if (mux.onStdinData) {
200
+ process.stdin.removeListener("data", mux.onStdinData);
201
+ }
202
+ if (mux.onResize) {
203
+ process.stdout.removeListener("resize", mux.onResize);
204
+ }
205
+ mux.hotkeys.destroy();
206
+ mux.terminalHost.restoreTerminalState();
207
+ },
208
+ cleanup() {
209
+ const mux = this;
210
+ for (const session of mux.sessions) {
211
+ session.destroy();
212
+ }
213
+ void this.stopProjectServices().catch(() => { });
214
+ this.teardown();
215
+ },
216
+ cleanupTerminalOnly() {
217
+ const mux = this;
218
+ mux.terminalHost.restoreTerminalState();
219
+ },
220
+ exitDashboardClientOrProcess() {
221
+ const mux = this;
222
+ const insideTmux = mux.tmuxRuntimeManager.isInsideTmux();
223
+ const currentSession = insideTmux ? mux.tmuxRuntimeManager.currentClientSession() : null;
224
+ if (insideTmux && currentSession && mux.tmuxRuntimeManager.isManagedSessionName(currentSession)) {
225
+ mux.tmuxRuntimeManager.leaveManagedSession({
226
+ insideTmux: true,
227
+ sessionName: mux.tmuxRuntimeManager.getProjectSession(process.cwd()).sessionName,
228
+ });
229
+ return;
230
+ }
231
+ this.cleanup();
232
+ process.exit(0);
233
+ },
234
+ };
235
+ //# sourceMappingURL=runtime-lifecycle-methods.js.map