aimux-cli 0.1.0

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 (207) hide show
  1. package/README.md +743 -0
  2. package/bin/aimux +2 -0
  3. package/dist/agent-events.d.ts +20 -0
  4. package/dist/agent-events.js +2 -0
  5. package/dist/agent-events.js.map +1 -0
  6. package/dist/agent-message-parts.d.ts +17 -0
  7. package/dist/agent-message-parts.js +31 -0
  8. package/dist/agent-message-parts.js.map +1 -0
  9. package/dist/agent-output-parser.d.ts +16 -0
  10. package/dist/agent-output-parser.js +229 -0
  11. package/dist/agent-output-parser.js.map +1 -0
  12. package/dist/agent-tracker.d.ts +9 -0
  13. package/dist/agent-tracker.js +144 -0
  14. package/dist/agent-tracker.js.map +1 -0
  15. package/dist/agent-watcher.d.ts +15 -0
  16. package/dist/agent-watcher.js +2 -0
  17. package/dist/agent-watcher.js.map +1 -0
  18. package/dist/attachment-store.d.ts +35 -0
  19. package/dist/attachment-store.js +129 -0
  20. package/dist/attachment-store.js.map +1 -0
  21. package/dist/builtin-metadata-watchers.d.ts +2 -0
  22. package/dist/builtin-metadata-watchers.js +275 -0
  23. package/dist/builtin-metadata-watchers.js.map +1 -0
  24. package/dist/claude-hooks.d.ts +29 -0
  25. package/dist/claude-hooks.js +106 -0
  26. package/dist/claude-hooks.js.map +1 -0
  27. package/dist/config.d.ts +78 -0
  28. package/dist/config.js +172 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/context/compactor.d.ts +20 -0
  31. package/dist/context/compactor.js +212 -0
  32. package/dist/context/compactor.js.map +1 -0
  33. package/dist/context/context-bridge.d.ts +67 -0
  34. package/dist/context/context-bridge.js +471 -0
  35. package/dist/context/context-bridge.js.map +1 -0
  36. package/dist/context/context-file.d.ts +11 -0
  37. package/dist/context/context-file.js +93 -0
  38. package/dist/context/context-file.js.map +1 -0
  39. package/dist/context/history.d.ts +40 -0
  40. package/dist/context/history.js +108 -0
  41. package/dist/context/history.js.map +1 -0
  42. package/dist/daemon.d.ts +39 -0
  43. package/dist/daemon.js +344 -0
  44. package/dist/daemon.js.map +1 -0
  45. package/dist/dashboard-session-registry.d.ts +47 -0
  46. package/dist/dashboard-session-registry.js +161 -0
  47. package/dist/dashboard-session-registry.js.map +1 -0
  48. package/dist/dashboard-state.d.ts +18 -0
  49. package/dist/dashboard-state.js +26 -0
  50. package/dist/dashboard-state.js.map +1 -0
  51. package/dist/dashboard.d.ts +118 -0
  52. package/dist/dashboard.js +91 -0
  53. package/dist/dashboard.js.map +1 -0
  54. package/dist/debug.d.ts +7 -0
  55. package/dist/debug.js +41 -0
  56. package/dist/debug.js.map +1 -0
  57. package/dist/fast-control.d.ts +45 -0
  58. package/dist/fast-control.js +174 -0
  59. package/dist/fast-control.js.map +1 -0
  60. package/dist/hotkeys.d.ts +44 -0
  61. package/dist/hotkeys.js +118 -0
  62. package/dist/hotkeys.js.map +1 -0
  63. package/dist/http-client.d.ts +10 -0
  64. package/dist/http-client.js +54 -0
  65. package/dist/http-client.js.map +1 -0
  66. package/dist/instance-directory.d.ts +32 -0
  67. package/dist/instance-directory.js +82 -0
  68. package/dist/instance-directory.js.map +1 -0
  69. package/dist/instance-registry.d.ts +38 -0
  70. package/dist/instance-registry.js +208 -0
  71. package/dist/instance-registry.js.map +1 -0
  72. package/dist/key-parser.d.ts +30 -0
  73. package/dist/key-parser.js +272 -0
  74. package/dist/key-parser.js.map +1 -0
  75. package/dist/last-used.d.ts +31 -0
  76. package/dist/last-used.js +93 -0
  77. package/dist/last-used.js.map +1 -0
  78. package/dist/main.d.ts +1 -0
  79. package/dist/main.js +2483 -0
  80. package/dist/main.js.map +1 -0
  81. package/dist/metadata-server.d.ts +268 -0
  82. package/dist/metadata-server.js +1379 -0
  83. package/dist/metadata-server.js.map +1 -0
  84. package/dist/metadata-store.d.ts +80 -0
  85. package/dist/metadata-store.js +87 -0
  86. package/dist/metadata-store.js.map +1 -0
  87. package/dist/multiplexer.d.ts +471 -0
  88. package/dist/multiplexer.js +5714 -0
  89. package/dist/multiplexer.js.map +1 -0
  90. package/dist/notification-context.d.ts +18 -0
  91. package/dist/notification-context.js +68 -0
  92. package/dist/notification-context.js.map +1 -0
  93. package/dist/notifications.d.ts +38 -0
  94. package/dist/notifications.js +111 -0
  95. package/dist/notifications.js.map +1 -0
  96. package/dist/notify.d.ts +10 -0
  97. package/dist/notify.js +62 -0
  98. package/dist/notify.js.map +1 -0
  99. package/dist/orchestration-actions.d.ts +76 -0
  100. package/dist/orchestration-actions.js +310 -0
  101. package/dist/orchestration-actions.js.map +1 -0
  102. package/dist/orchestration-dispatcher.d.ts +22 -0
  103. package/dist/orchestration-dispatcher.js +49 -0
  104. package/dist/orchestration-dispatcher.js.map +1 -0
  105. package/dist/orchestration-routing.d.ts +20 -0
  106. package/dist/orchestration-routing.js +78 -0
  107. package/dist/orchestration-routing.js.map +1 -0
  108. package/dist/orchestration.d.ts +26 -0
  109. package/dist/orchestration.js +110 -0
  110. package/dist/orchestration.js.map +1 -0
  111. package/dist/osc-notifications.d.ts +15 -0
  112. package/dist/osc-notifications.js +180 -0
  113. package/dist/osc-notifications.js.map +1 -0
  114. package/dist/paths.d.ts +55 -0
  115. package/dist/paths.js +259 -0
  116. package/dist/paths.js.map +1 -0
  117. package/dist/plugin-runtime.d.ts +46 -0
  118. package/dist/plugin-runtime.js +180 -0
  119. package/dist/plugin-runtime.js.map +1 -0
  120. package/dist/project-events.d.ts +36 -0
  121. package/dist/project-events.js +63 -0
  122. package/dist/project-events.js.map +1 -0
  123. package/dist/project-scanner.d.ts +38 -0
  124. package/dist/project-scanner.js +243 -0
  125. package/dist/project-scanner.js.map +1 -0
  126. package/dist/project-service-manifest.d.ts +18 -0
  127. package/dist/project-service-manifest.js +56 -0
  128. package/dist/project-service-manifest.js.map +1 -0
  129. package/dist/recency.d.ts +2 -0
  130. package/dist/recency.js +34 -0
  131. package/dist/recency.js.map +1 -0
  132. package/dist/recorder.d.ts +14 -0
  133. package/dist/recorder.js +130 -0
  134. package/dist/recorder.js.map +1 -0
  135. package/dist/session-bootstrap.d.ts +45 -0
  136. package/dist/session-bootstrap.js +436 -0
  137. package/dist/session-bootstrap.js.map +1 -0
  138. package/dist/session-message-history.d.ts +27 -0
  139. package/dist/session-message-history.js +105 -0
  140. package/dist/session-message-history.js.map +1 -0
  141. package/dist/session-runtime.d.ts +44 -0
  142. package/dist/session-runtime.js +56 -0
  143. package/dist/session-runtime.js.map +1 -0
  144. package/dist/session-semantics.d.ts +35 -0
  145. package/dist/session-semantics.js +110 -0
  146. package/dist/session-semantics.js.map +1 -0
  147. package/dist/status-detector.d.ts +17 -0
  148. package/dist/status-detector.js +67 -0
  149. package/dist/status-detector.js.map +1 -0
  150. package/dist/statusline-model.d.ts +103 -0
  151. package/dist/statusline-model.js +177 -0
  152. package/dist/statusline-model.js.map +1 -0
  153. package/dist/task-dispatcher.d.ts +63 -0
  154. package/dist/task-dispatcher.js +210 -0
  155. package/dist/task-dispatcher.js.map +1 -0
  156. package/dist/task-workflow.d.ts +13 -0
  157. package/dist/task-workflow.js +153 -0
  158. package/dist/task-workflow.js.map +1 -0
  159. package/dist/tasks.d.ts +60 -0
  160. package/dist/tasks.js +120 -0
  161. package/dist/tasks.js.map +1 -0
  162. package/dist/team.d.ts +28 -0
  163. package/dist/team.js +91 -0
  164. package/dist/team.js.map +1 -0
  165. package/dist/terminal-host.d.ts +10 -0
  166. package/dist/terminal-host.js +52 -0
  167. package/dist/terminal-host.js.map +1 -0
  168. package/dist/threads.d.ts +61 -0
  169. package/dist/threads.js +200 -0
  170. package/dist/threads.js.map +1 -0
  171. package/dist/tmux-doctor.d.ts +47 -0
  172. package/dist/tmux-doctor.js +112 -0
  173. package/dist/tmux-doctor.js.map +1 -0
  174. package/dist/tmux-runtime-manager.d.ts +164 -0
  175. package/dist/tmux-runtime-manager.js +794 -0
  176. package/dist/tmux-runtime-manager.js.map +1 -0
  177. package/dist/tmux-session-transport.d.ts +31 -0
  178. package/dist/tmux-session-transport.js +115 -0
  179. package/dist/tmux-session-transport.js.map +1 -0
  180. package/dist/tmux-statusline.d.ts +17 -0
  181. package/dist/tmux-statusline.js +166 -0
  182. package/dist/tmux-statusline.js.map +1 -0
  183. package/dist/tool-output-watchers.d.ts +10 -0
  184. package/dist/tool-output-watchers.js +190 -0
  185. package/dist/tool-output-watchers.js.map +1 -0
  186. package/dist/tui/render/box.d.ts +1 -0
  187. package/dist/tui/render/box.js +20 -0
  188. package/dist/tui/render/box.js.map +1 -0
  189. package/dist/tui/render/text.d.ts +8 -0
  190. package/dist/tui/render/text.js +92 -0
  191. package/dist/tui/render/text.js.map +1 -0
  192. package/dist/tui/screens/dashboard-renderers.d.ts +23 -0
  193. package/dist/tui/screens/dashboard-renderers.js +411 -0
  194. package/dist/tui/screens/dashboard-renderers.js.map +1 -0
  195. package/dist/tui/screens/overlay-renderers.d.ts +10 -0
  196. package/dist/tui/screens/overlay-renderers.js +274 -0
  197. package/dist/tui/screens/overlay-renderers.js.map +1 -0
  198. package/dist/tui/screens/subscreen-renderers.d.ts +9 -0
  199. package/dist/tui/screens/subscreen-renderers.js +327 -0
  200. package/dist/tui/screens/subscreen-renderers.js.map +1 -0
  201. package/dist/workflow.d.ts +19 -0
  202. package/dist/workflow.js +111 -0
  203. package/dist/workflow.js.map +1 -0
  204. package/dist/worktree.d.ts +23 -0
  205. package/dist/worktree.js +101 -0
  206. package/dist/worktree.js.map +1 -0
  207. package/package.json +70 -0
@@ -0,0 +1,243 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { join, basename } from "node:path";
3
+ import { homedir, tmpdir } from "node:os";
4
+ import { getAimuxDirFor, getProjectStateDirById, listProjects } from "./paths.js";
5
+ import { TmuxRuntimeManager } from "./tmux-runtime-manager.js";
6
+ /**
7
+ * Discover local projects with aimux state.
8
+ * Uses the global projects registry plus filesystem scanning as fallback.
9
+ */
10
+ export function discoverProjects() {
11
+ const found = new Set();
12
+ // Primary: projects registry
13
+ for (const entry of listProjects()) {
14
+ if (existsSync(entry.repoRoot)) {
15
+ found.add(entry.repoRoot);
16
+ }
17
+ }
18
+ // Fallback: scan common dev directories for old-style in-repo .aimux/
19
+ const home = homedir();
20
+ const scanDirs = [
21
+ join(home, "cs"),
22
+ join(home, "projects"),
23
+ join(home, "dev"),
24
+ join(home, "src"),
25
+ join(home, "code"),
26
+ join(home, "work"),
27
+ ];
28
+ for (const scanDir of scanDirs) {
29
+ try {
30
+ const entries = readdirSync(scanDir);
31
+ for (const entry of entries) {
32
+ const projectPath = join(scanDir, entry);
33
+ try {
34
+ if (!statSync(projectPath).isDirectory())
35
+ continue;
36
+ const aimuxDir = join(projectPath, ".aimux");
37
+ if (existsSync(join(aimuxDir, "instances.json")) || existsSync(join(aimuxDir, "state.json"))) {
38
+ found.add(projectPath);
39
+ }
40
+ }
41
+ catch { }
42
+ }
43
+ }
44
+ catch { }
45
+ }
46
+ return [...found];
47
+ }
48
+ /**
49
+ * Scan a single project for all sessions (running + offline).
50
+ */
51
+ export function scanProject(projectPath) {
52
+ const sessions = [];
53
+ const seenIds = new Set();
54
+ const registryEntry = listProjects().find((entry) => entry.repoRoot === projectPath);
55
+ const sessionById = new Map();
56
+ // Check both global state dir and in-repo .aimux/ for instances
57
+ const instancesPaths = [join(getAimuxDirFor(projectPath), "instances.json")];
58
+ const statusDirs = [join(getAimuxDirFor(projectPath), "status")];
59
+ // Also check global project state dirs for registered projects
60
+ if (registryEntry) {
61
+ const projectStateDir = getProjectStateDirById(registryEntry.id);
62
+ const globalInstances = join(projectStateDir, "instances.json");
63
+ if (!instancesPaths.includes(globalInstances)) {
64
+ instancesPaths.unshift(globalInstances);
65
+ }
66
+ statusDirs.unshift(join(projectStateDir, "status"));
67
+ }
68
+ for (const instancesPath of instancesPaths) {
69
+ if (!existsSync(instancesPath))
70
+ continue;
71
+ try {
72
+ const instances = JSON.parse(readFileSync(instancesPath, "utf-8"));
73
+ for (const inst of instances) {
74
+ // Check PID alive
75
+ try {
76
+ process.kill(inst.pid, 0);
77
+ }
78
+ catch {
79
+ continue;
80
+ }
81
+ for (const s of inst.sessions) {
82
+ if (seenIds.has(s.id))
83
+ continue;
84
+ seenIds.add(s.id);
85
+ let headline;
86
+ for (const statusDir of statusDirs) {
87
+ try {
88
+ const statusPath = join(statusDir, `${s.id}.md`);
89
+ if (existsSync(statusPath)) {
90
+ const content = readFileSync(statusPath, "utf-8").trim();
91
+ if (content) {
92
+ headline = content.split("\n")[0].slice(0, 80);
93
+ break;
94
+ }
95
+ }
96
+ }
97
+ catch {
98
+ // Try the next candidate directory.
99
+ }
100
+ }
101
+ sessions.push({
102
+ id: s.id,
103
+ tool: s.tool,
104
+ status: "running",
105
+ headline,
106
+ worktreePath: s.worktreePath,
107
+ ownerPid: inst.pid,
108
+ });
109
+ sessionById.set(s.id, sessions[sessions.length - 1]);
110
+ }
111
+ }
112
+ }
113
+ catch { }
114
+ }
115
+ // Enrich live sessions with statusline.json when available.
116
+ const statuslinePaths = [join(getAimuxDirFor(projectPath), "statusline.json")];
117
+ if (registryEntry) {
118
+ const globalStatusline = join(getProjectStateDirById(registryEntry.id), "statusline.json");
119
+ if (!statuslinePaths.includes(globalStatusline)) {
120
+ statuslinePaths.unshift(globalStatusline);
121
+ }
122
+ }
123
+ for (const statuslinePath of statuslinePaths) {
124
+ if (!existsSync(statuslinePath))
125
+ continue;
126
+ try {
127
+ const stat = statSync(statuslinePath);
128
+ if (Date.now() - stat.mtimeMs > 10_000)
129
+ continue;
130
+ const statusline = JSON.parse(readFileSync(statuslinePath, "utf-8"));
131
+ for (const s of statusline.sessions ?? []) {
132
+ const existing = sessionById.get(s.id);
133
+ if (existing) {
134
+ existing.tool = s.tool ?? existing.tool;
135
+ existing.label = s.label ?? existing.label;
136
+ existing.headline = s.headline ?? existing.headline;
137
+ existing.status = s.status ?? existing.status;
138
+ existing.role = s.role ?? existing.role;
139
+ continue;
140
+ }
141
+ const session = {
142
+ id: s.id,
143
+ tool: s.tool ?? "unknown",
144
+ label: s.label,
145
+ headline: s.headline,
146
+ status: s.status ?? "idle",
147
+ role: s.role,
148
+ };
149
+ sessions.push(session);
150
+ sessionById.set(s.id, session);
151
+ seenIds.add(s.id);
152
+ }
153
+ break;
154
+ }
155
+ catch { }
156
+ }
157
+ // Offline sessions — check both global state and in-repo
158
+ const statePaths = [join(getAimuxDirFor(projectPath), "state.json")];
159
+ if (registryEntry) {
160
+ const globalState = join(getProjectStateDirById(registryEntry.id), "state.json");
161
+ if (!statePaths.includes(globalState)) {
162
+ statePaths.unshift(globalState);
163
+ }
164
+ }
165
+ for (const statePath of statePaths) {
166
+ if (!existsSync(statePath))
167
+ continue;
168
+ try {
169
+ const state = JSON.parse(readFileSync(statePath, "utf-8"));
170
+ for (const s of state.sessions) {
171
+ if (seenIds.has(s.id))
172
+ continue;
173
+ seenIds.add(s.id);
174
+ sessions.push({
175
+ id: s.id,
176
+ tool: s.command ?? s.tool ?? "unknown",
177
+ status: "offline",
178
+ label: s.label,
179
+ headline: s.headline,
180
+ worktreePath: s.worktreePath,
181
+ });
182
+ }
183
+ }
184
+ catch { }
185
+ }
186
+ return {
187
+ name: basename(projectPath),
188
+ path: projectPath,
189
+ sessions,
190
+ };
191
+ }
192
+ /**
193
+ * Scan all discovered projects and return global state.
194
+ */
195
+ export function scanAllProjects() {
196
+ const projectPaths = discoverProjects();
197
+ return projectPaths
198
+ .map(scanProject)
199
+ .filter((p) => p.sessions.length > 0)
200
+ .sort((a, b) => a.name.localeCompare(b.name));
201
+ }
202
+ export function listDesktopProjects(tmux = new TmuxRuntimeManager()) {
203
+ const scannedByPath = new Map(scanAllProjects().map((project) => [project.path, project]));
204
+ const projects = new Map();
205
+ const osTmpDir = tmpdir();
206
+ function shouldHideDesktopProject(projectPath) {
207
+ const name = basename(projectPath);
208
+ if (!projectPath.startsWith(osTmpDir)) {
209
+ return false;
210
+ }
211
+ return name.startsWith("aimux-metadata-server-") || name.startsWith("aimux-test-");
212
+ }
213
+ for (const entry of listProjects()) {
214
+ if (shouldHideDesktopProject(entry.repoRoot))
215
+ continue;
216
+ const scanned = scannedByPath.get(entry.repoRoot);
217
+ const tmuxSession = tmux.getProjectSession(entry.repoRoot);
218
+ projects.set(entry.repoRoot, {
219
+ id: entry.id,
220
+ name: entry.name,
221
+ path: entry.repoRoot,
222
+ lastSeen: entry.lastSeen,
223
+ dashboardSessionName: tmuxSession.sessionName,
224
+ sessions: scanned?.sessions ?? [],
225
+ });
226
+ }
227
+ for (const scanned of scannedByPath.values()) {
228
+ if (shouldHideDesktopProject(scanned.path))
229
+ continue;
230
+ if (projects.has(scanned.path))
231
+ continue;
232
+ const tmuxSession = tmux.getProjectSession(scanned.path);
233
+ projects.set(scanned.path, {
234
+ id: `unregistered-${tmuxSession.sessionName}`,
235
+ name: scanned.name,
236
+ path: scanned.path,
237
+ dashboardSessionName: tmuxSession.sessionName,
238
+ sessions: scanned.sessions,
239
+ });
240
+ }
241
+ return [...projects.values()].sort((a, b) => a.name.localeCompare(b.name) || a.path.localeCompare(b.path));
242
+ }
243
+ //# sourceMappingURL=project-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-scanner.js","sourceRoot":"","sources":["../src/project-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export declare const PROJECT_SERVICE_API_VERSION = 4;
2
+ export declare const PROJECT_SERVICE_CAPABILITIES: {
3
+ readonly structuredAgentInput: true;
4
+ readonly parsedAgentOutput: true;
5
+ readonly attachments: true;
6
+ readonly agentHistory: true;
7
+ readonly chatEventStream: true;
8
+ };
9
+ export interface ProjectServiceManifest {
10
+ apiVersion: number;
11
+ capabilities: Record<string, boolean>;
12
+ buildStamp: string;
13
+ }
14
+ export declare const PROJECT_SERVICE_BUILD_STAMP: string;
15
+ export declare function getProjectServiceManifest(): ProjectServiceManifest;
16
+ export declare function computeCurrentProjectServiceManifest(): ProjectServiceManifest;
17
+ export declare function hasProjectServiceBuildDrift(): boolean;
18
+ export declare function manifestsMatch(expected: ProjectServiceManifest, actual: Partial<ProjectServiceManifest> | null | undefined): boolean;
@@ -0,0 +1,56 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync, readFileSync, statSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ export const PROJECT_SERVICE_API_VERSION = 4;
5
+ export const PROJECT_SERVICE_CAPABILITIES = {
6
+ structuredAgentInput: true,
7
+ parsedAgentOutput: true,
8
+ attachments: true,
9
+ agentHistory: true,
10
+ chatEventStream: true,
11
+ };
12
+ function computeBuildStamp() {
13
+ const candidateUrls = [new URL("./main.js", import.meta.url), new URL("./main.ts", import.meta.url)];
14
+ const entryPath = candidateUrls.map((url) => fileURLToPath(url)).find((candidate) => existsSync(candidate));
15
+ if (!entryPath) {
16
+ throw new Error("unable to locate project service entrypoint for build stamp");
17
+ }
18
+ const stat = statSync(entryPath);
19
+ const content = readFileSync(entryPath);
20
+ const hash = createHash("sha1").update(content).digest("hex").slice(0, 12);
21
+ return `${Math.trunc(stat.mtimeMs)}-${hash}`;
22
+ }
23
+ export const PROJECT_SERVICE_BUILD_STAMP = computeBuildStamp();
24
+ export function getProjectServiceManifest() {
25
+ return {
26
+ apiVersion: PROJECT_SERVICE_API_VERSION,
27
+ capabilities: { ...PROJECT_SERVICE_CAPABILITIES },
28
+ buildStamp: PROJECT_SERVICE_BUILD_STAMP,
29
+ };
30
+ }
31
+ export function computeCurrentProjectServiceManifest() {
32
+ return {
33
+ apiVersion: PROJECT_SERVICE_API_VERSION,
34
+ capabilities: { ...PROJECT_SERVICE_CAPABILITIES },
35
+ buildStamp: computeBuildStamp(),
36
+ };
37
+ }
38
+ export function hasProjectServiceBuildDrift() {
39
+ try {
40
+ return computeCurrentProjectServiceManifest().buildStamp !== PROJECT_SERVICE_BUILD_STAMP;
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ }
46
+ export function manifestsMatch(expected, actual) {
47
+ if (!actual)
48
+ return false;
49
+ if (Number(actual.apiVersion || 0) !== expected.apiVersion)
50
+ return false;
51
+ if (String(actual.buildStamp || "") !== expected.buildStamp)
52
+ return false;
53
+ const actualCapabilities = actual.capabilities || {};
54
+ return Object.entries(expected.capabilities).every(([key, value]) => actualCapabilities[key] === value);
55
+ }
56
+ //# sourceMappingURL=project-service-manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-service-manifest.js","sourceRoot":"","sources":["../src/project-service-manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function parseRecencyTimestamp(value?: string | null): number | null;
2
+ export declare function formatRelativeRecency(value?: string | null, now?: number): string | null;
@@ -0,0 +1,34 @@
1
+ export function parseRecencyTimestamp(value) {
2
+ if (!value)
3
+ return null;
4
+ const parsed = Date.parse(value);
5
+ return Number.isFinite(parsed) ? parsed : null;
6
+ }
7
+ export function formatRelativeRecency(value, now = Date.now()) {
8
+ const timestamp = parseRecencyTimestamp(value);
9
+ if (timestamp == null)
10
+ return null;
11
+ const deltaSeconds = Math.max(0, Math.floor((now - timestamp) / 1000));
12
+ if (deltaSeconds < 15)
13
+ return "just now";
14
+ if (deltaSeconds < 60)
15
+ return `${deltaSeconds}s ago`;
16
+ const minutes = Math.floor(deltaSeconds / 60);
17
+ if (minutes < 60)
18
+ return `${minutes}m ago`;
19
+ const hours = Math.floor(minutes / 60);
20
+ if (hours < 24)
21
+ return `${hours}h ago`;
22
+ const days = Math.floor(hours / 24);
23
+ if (days < 7)
24
+ return `${days}d ago`;
25
+ const weeks = Math.floor(days / 7);
26
+ if (weeks < 5)
27
+ return `${weeks}w ago`;
28
+ const months = Math.floor(days / 30);
29
+ if (months < 12)
30
+ return `${months}mo ago`;
31
+ const years = Math.floor(days / 365);
32
+ return `${years}y ago`;
33
+ }
34
+ //# sourceMappingURL=recency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recency.js","sourceRoot":"","sources":["../src/recency.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB,CAAC,KAAqB;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAqB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAC3E,MAAM,SAAS,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,SAAS,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACvE,IAAI,YAAY,GAAG,EAAE;QAAE,OAAO,UAAU,CAAC;IACzC,IAAI,YAAY,GAAG,EAAE;QAAE,OAAO,GAAG,YAAY,OAAO,CAAC;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IAC9C,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,GAAG,OAAO,OAAO,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACvC,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO,GAAG,KAAK,OAAO,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,GAAG,IAAI,OAAO,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACnC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,GAAG,KAAK,OAAO,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACrC,IAAI,MAAM,GAAG,EAAE;QAAE,OAAO,GAAG,MAAM,QAAQ,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;IACrC,OAAO,GAAG,KAAK,OAAO,CAAC;AACzB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare class Recorder {
2
+ private rawStream;
3
+ private txtStream;
4
+ private _rawPath;
5
+ private _txtPath;
6
+ constructor(sessionId: string);
7
+ get rawPath(): string;
8
+ get txtPath(): string;
9
+ /**
10
+ * Record PTY output data. Writes raw (with ANSI) and stripped (plaintext).
11
+ */
12
+ write(data: string): void;
13
+ close(): void;
14
+ }
@@ -0,0 +1,130 @@
1
+ import { existsSync, mkdirSync, createWriteStream } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { getRecordingsDir } from "./paths.js";
4
+ /**
5
+ * Strip all terminal escape sequences from PTY output, not just colors.
6
+ * Handles: SGR (colors), cursor movement, cursor position, erase,
7
+ * scroll, OSC (title), and other CSI/SS3/DCS sequences.
8
+ * Also converts cursor-right (\x1b[nC) to spaces for readable output.
9
+ */
10
+ function stripTerminal(data) {
11
+ let result = "";
12
+ let i = 0;
13
+ while (i < data.length) {
14
+ const ch = data[i];
15
+ if (ch === "\x1b") {
16
+ const next = data[i + 1];
17
+ if (next === "[") {
18
+ // CSI sequence: \x1b[ ... <final byte>
19
+ let j = i + 2;
20
+ // Parse parameter bytes (0x30-0x3f) and intermediate bytes (0x20-0x2f)
21
+ while (j < data.length && data.charCodeAt(j) >= 0x20 && data.charCodeAt(j) <= 0x3f)
22
+ j++;
23
+ while (j < data.length && data.charCodeAt(j) >= 0x20 && data.charCodeAt(j) <= 0x2f)
24
+ j++;
25
+ // Final byte
26
+ if (j < data.length) {
27
+ const finalByte = data[j];
28
+ // Cursor right: convert to spaces for readable text
29
+ if (finalByte === "C") {
30
+ const params = data.slice(i + 2, j);
31
+ const n = parseInt(params) || 1;
32
+ result += " ".repeat(n);
33
+ }
34
+ // All other CSI sequences (cursor move, erase, scroll, SGR) → skip
35
+ j++;
36
+ }
37
+ i = j;
38
+ continue;
39
+ }
40
+ if (next === "]") {
41
+ // OSC sequence: \x1b] ... (terminated by BEL \x07 or ST \x1b\\)
42
+ let j = i + 2;
43
+ while (j < data.length) {
44
+ if (data[j] === "\x07") {
45
+ j++;
46
+ break;
47
+ }
48
+ if (data[j] === "\x1b" && data[j + 1] === "\\") {
49
+ j += 2;
50
+ break;
51
+ }
52
+ j++;
53
+ }
54
+ i = j;
55
+ continue;
56
+ }
57
+ if (next === "(" || next === ")" || next === "*" || next === "+") {
58
+ // Character set designation: \x1b( <char> — skip 3 bytes
59
+ i += 3;
60
+ continue;
61
+ }
62
+ if (next === "P") {
63
+ // DCS sequence: \x1bP ... ST
64
+ let j = i + 2;
65
+ while (j < data.length) {
66
+ if (data[j] === "\x1b" && data[j + 1] === "\\") {
67
+ j += 2;
68
+ break;
69
+ }
70
+ j++;
71
+ }
72
+ i = j;
73
+ continue;
74
+ }
75
+ // Single-char escape (save/restore cursor, etc.): \x1b <char>
76
+ i += 2;
77
+ continue;
78
+ }
79
+ // Strip other control chars except newline, carriage return, tab
80
+ const code = ch.charCodeAt(0);
81
+ if (code < 0x20 && code !== 0x0a && code !== 0x0d && code !== 0x09) {
82
+ i++;
83
+ continue;
84
+ }
85
+ result += ch;
86
+ i++;
87
+ }
88
+ // Clean up carriage returns: keep only content after last \r per line
89
+ return result
90
+ .split("\n")
91
+ .map((line) => {
92
+ const lastCr = line.lastIndexOf("\r");
93
+ return lastCr >= 0 ? line.slice(lastCr + 1) : line;
94
+ })
95
+ .join("\n");
96
+ }
97
+ export class Recorder {
98
+ rawStream;
99
+ txtStream;
100
+ _rawPath;
101
+ _txtPath;
102
+ constructor(sessionId) {
103
+ const recordingsDir = getRecordingsDir();
104
+ if (!existsSync(recordingsDir)) {
105
+ mkdirSync(recordingsDir, { recursive: true });
106
+ }
107
+ this._rawPath = join(recordingsDir, `${sessionId}.log`);
108
+ this._txtPath = join(recordingsDir, `${sessionId}.txt`);
109
+ this.rawStream = createWriteStream(this._rawPath, { flags: "a" });
110
+ this.txtStream = createWriteStream(this._txtPath, { flags: "a" });
111
+ }
112
+ get rawPath() {
113
+ return this._rawPath;
114
+ }
115
+ get txtPath() {
116
+ return this._txtPath;
117
+ }
118
+ /**
119
+ * Record PTY output data. Writes raw (with ANSI) and stripped (plaintext).
120
+ */
121
+ write(data) {
122
+ this.rawStream.write(data);
123
+ this.txtStream.write(stripTerminal(data));
124
+ }
125
+ close() {
126
+ this.rawStream.end();
127
+ this.txtStream.end();
128
+ }
129
+ }
130
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../src/recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { type ToolConfig } from "./config.js";
2
+ import { type TmuxRuntimeManager, type TmuxTarget } from "./tmux-runtime-manager.js";
3
+ export interface ForkSourceSnapshot {
4
+ historyText?: string;
5
+ liveText?: string;
6
+ planText?: string;
7
+ statusText?: string;
8
+ }
9
+ interface SessionBootstrapDependencies {
10
+ tmuxRuntimeManager: TmuxRuntimeManager;
11
+ getSessionLabel(sessionId: string): string | undefined;
12
+ getSessionRole(sessionId: string): string | undefined;
13
+ getSessionWorktreePath(sessionId: string): string | undefined;
14
+ getSessionTmuxTarget(sessionId: string): TmuxTarget | undefined;
15
+ }
16
+ export declare class SessionBootstrapService {
17
+ private readonly deps;
18
+ constructor(deps: SessionBootstrapDependencies);
19
+ buildSessionPreamble(opts: {
20
+ sessionId: string;
21
+ command: string;
22
+ worktreePath?: string;
23
+ extraPreamble?: string;
24
+ }): string;
25
+ ensurePlanFile(sessionId: string, command: string, worktreePath?: string): void;
26
+ composeToolArgs(toolCfg: {
27
+ args: string[];
28
+ }, actionArgs: string[], savedArgs?: string[]): string[];
29
+ canResumeWithBackendSessionId(toolCfg: {
30
+ resumeArgs?: string[];
31
+ resumeByBackendSessionId?: boolean;
32
+ } | undefined, backendSessionId: string | undefined): boolean;
33
+ readForkSourceSnapshot(sourceSessionId: string): ForkSourceSnapshot;
34
+ summarizeForkSourceActivity(snapshot: ForkSourceSnapshot): string | undefined;
35
+ buildForkPreamble(sourceSessionId: string, targetSessionId: string): string;
36
+ buildForkKickoffPrompt(sourceSessionId: string, targetSessionId: string, snapshot: ForkSourceSnapshot, instruction?: string): string;
37
+ seedForkArtifacts(sourceSessionId: string, targetSessionId: string, targetToolConfigKey: string): void;
38
+ waitForCodexKickoffSubmit(targetSessionId: string, target: TmuxTarget, kickoff: string): Promise<boolean>;
39
+ finalizePreamble(command: string, preamble: string): void;
40
+ private isDefaultPlanContent;
41
+ private paneStillContainsDraft;
42
+ private capturePaneFingerprint;
43
+ }
44
+ export declare function getToolResumeArgs(toolCfg: ToolConfig | undefined, backendSessionId: string | undefined): string[] | undefined;
45
+ export {};