@ai-devkit/agent-manager 0.41.0 → 0.42.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 (101) hide show
  1. package/dist/AgentManager.d.ts.map +1 -1
  2. package/dist/AgentManager.js +25 -9
  3. package/dist/AgentManager.js.map +1 -1
  4. package/dist/__tests__/fixtures.test.js.map +1 -1
  5. package/dist/__tests__/harnesses/devin/DevinAdapter.test.js.map +1 -1
  6. package/dist/__tests__/harnesses/devin/DevinSessionParser.test.js.map +1 -1
  7. package/dist/__tests__/harnesses/muse/MuseAdapter.test.js +247 -0
  8. package/dist/__tests__/harnesses/muse/MuseAdapter.test.js.map +1 -0
  9. package/dist/__tests__/harnesses/muse/MuseAgentMapper.test.js +81 -0
  10. package/dist/__tests__/harnesses/muse/MuseAgentMapper.test.js.map +1 -0
  11. package/dist/__tests__/harnesses/muse/MuseSessionLocator.test.js +185 -0
  12. package/dist/__tests__/harnesses/muse/MuseSessionLocator.test.js.map +1 -0
  13. package/dist/__tests__/harnesses/muse/MuseSessionParser.test.js +328 -0
  14. package/dist/__tests__/harnesses/muse/MuseSessionParser.test.js.map +1 -0
  15. package/dist/__tests__/harnesses/opencode/OpenCodeSessionParser.test.js.map +1 -1
  16. package/dist/__tests__/harnesses/readiness/AgentReadiness.test.js +42 -1
  17. package/dist/__tests__/harnesses/readiness/AgentReadiness.test.js.map +1 -1
  18. package/dist/__tests__/harnesses/runtimeProfiles.test.js +12 -0
  19. package/dist/__tests__/harnesses/runtimeProfiles.test.js.map +1 -1
  20. package/dist/__tests__/utils/process.test.js +71 -1
  21. package/dist/__tests__/utils/process.test.js.map +1 -1
  22. package/dist/adapters/AgentAdapter.d.ts +8 -1
  23. package/dist/adapters/AgentAdapter.d.ts.map +1 -1
  24. package/dist/adapters/AgentAdapter.js +2 -1
  25. package/dist/adapters/AgentAdapter.js.map +1 -1
  26. package/dist/fixtures/capture.d.ts.map +1 -1
  27. package/dist/fixtures/capture.js +5 -4
  28. package/dist/fixtures/capture.js.map +1 -1
  29. package/dist/harnesses/devin/DevinAdapter.d.ts.map +1 -1
  30. package/dist/harnesses/devin/DevinAdapter.js.map +1 -1
  31. package/dist/harnesses/devin/DevinAgentMapper.d.ts.map +1 -1
  32. package/dist/harnesses/devin/DevinAgentMapper.js.map +1 -1
  33. package/dist/harnesses/devin/DevinSessionParser.d.ts.map +1 -1
  34. package/dist/harnesses/devin/DevinSessionParser.js.map +1 -1
  35. package/dist/harnesses/index.d.ts.map +1 -1
  36. package/dist/harnesses/index.js +3 -1
  37. package/dist/harnesses/index.js.map +1 -1
  38. package/dist/harnesses/muse/MuseAdapter.d.ts +33 -0
  39. package/dist/harnesses/muse/MuseAdapter.d.ts.map +1 -0
  40. package/dist/harnesses/muse/MuseAdapter.js +122 -0
  41. package/dist/harnesses/muse/MuseAdapter.js.map +1 -0
  42. package/dist/harnesses/muse/MuseAgentMapper.d.ts +15 -0
  43. package/dist/harnesses/muse/MuseAgentMapper.d.ts.map +1 -0
  44. package/dist/harnesses/muse/MuseAgentMapper.js +29 -0
  45. package/dist/harnesses/muse/MuseAgentMapper.js.map +1 -0
  46. package/dist/harnesses/muse/MuseSessionLocator.d.ts +61 -0
  47. package/dist/harnesses/muse/MuseSessionLocator.d.ts.map +1 -0
  48. package/dist/harnesses/muse/MuseSessionLocator.js +233 -0
  49. package/dist/harnesses/muse/MuseSessionLocator.js.map +1 -0
  50. package/dist/harnesses/muse/MuseSessionParser.d.ts +77 -0
  51. package/dist/harnesses/muse/MuseSessionParser.d.ts.map +1 -0
  52. package/dist/harnesses/muse/MuseSessionParser.js +350 -0
  53. package/dist/harnesses/muse/MuseSessionParser.js.map +1 -0
  54. package/dist/harnesses/muse/readiness.d.ts +3 -0
  55. package/dist/harnesses/muse/readiness.d.ts.map +1 -0
  56. package/dist/harnesses/muse/readiness.js +37 -0
  57. package/dist/harnesses/muse/readiness.js.map +1 -0
  58. package/dist/harnesses/readiness/AgentReadiness.d.ts.map +1 -1
  59. package/dist/harnesses/readiness/AgentReadiness.js +3 -1
  60. package/dist/harnesses/readiness/AgentReadiness.js.map +1 -1
  61. package/dist/harnesses/readiness/types.d.ts +1 -1
  62. package/dist/harnesses/readiness/types.d.ts.map +1 -1
  63. package/dist/harnesses/runtimeProfiles.d.ts.map +1 -1
  64. package/dist/harnesses/runtimeProfiles.js +2 -1
  65. package/dist/harnesses/runtimeProfiles.js.map +1 -1
  66. package/dist/harnesses/shared.d.ts +1 -1
  67. package/dist/harnesses/shared.d.ts.map +1 -1
  68. package/dist/harnesses/shared.js +6 -5
  69. package/dist/harnesses/shared.js.map +1 -1
  70. package/dist/utils/process.d.ts +23 -1
  71. package/dist/utils/process.d.ts.map +1 -1
  72. package/dist/utils/process.js +44 -8
  73. package/dist/utils/process.js.map +1 -1
  74. package/package.json +1 -1
  75. package/src/AgentManager.ts +34 -8
  76. package/src/__tests__/fixtures.test.ts +15 -17
  77. package/src/__tests__/harnesses/devin/DevinAdapter.test.ts +1 -3
  78. package/src/__tests__/harnesses/devin/DevinSessionParser.test.ts +3 -9
  79. package/src/__tests__/harnesses/muse/MuseAdapter.test.ts +197 -0
  80. package/src/__tests__/harnesses/muse/MuseAgentMapper.test.ts +83 -0
  81. package/src/__tests__/harnesses/muse/MuseSessionLocator.test.ts +177 -0
  82. package/src/__tests__/harnesses/muse/MuseSessionParser.test.ts +279 -0
  83. package/src/__tests__/harnesses/opencode/OpenCodeSessionParser.test.ts +3 -2
  84. package/src/__tests__/harnesses/readiness/AgentReadiness.test.ts +36 -0
  85. package/src/__tests__/harnesses/runtimeProfiles.test.ts +13 -0
  86. package/src/__tests__/utils/process.test.ts +30 -0
  87. package/src/adapters/AgentAdapter.ts +9 -0
  88. package/src/fixtures/capture.ts +32 -17
  89. package/src/harnesses/devin/DevinAdapter.ts +3 -15
  90. package/src/harnesses/devin/DevinAgentMapper.ts +1 -5
  91. package/src/harnesses/devin/DevinSessionParser.ts +3 -12
  92. package/src/harnesses/index.ts +2 -0
  93. package/src/harnesses/muse/MuseAdapter.ts +157 -0
  94. package/src/harnesses/muse/MuseAgentMapper.ts +33 -0
  95. package/src/harnesses/muse/MuseSessionLocator.ts +286 -0
  96. package/src/harnesses/muse/MuseSessionParser.ts +435 -0
  97. package/src/harnesses/muse/readiness.ts +38 -0
  98. package/src/harnesses/readiness/AgentReadiness.ts +2 -0
  99. package/src/harnesses/runtimeProfiles.ts +1 -0
  100. package/src/harnesses/shared.ts +10 -5
  101. package/src/utils/process.ts +61 -9
@@ -0,0 +1,233 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { matchProcessesToSessions } from "../../utils/matching.js";
4
+ import { isDirectory, isSafePathSegment, safeReaddir, safeStat } from "../../utils/session.js";
5
+ import { homeDir } from "../shared.js";
6
+ /** Session ids are UUID-shaped; anything else is never a session dir. */ const SESSION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7
+ /** Maximum |process start − transcript birth| before a pid match is recycled. */ const PID_STALENESS_MS = 60000;
8
+ function parsePidHint(value) {
9
+ if (typeof value !== "string") return null;
10
+ const match = /^pid=(\d+)$/.exec(value.trim());
11
+ return match ? Number(match[1]) : null;
12
+ }
13
+ function parseRuntimeEntry(filePath) {
14
+ let raw;
15
+ try {
16
+ raw = fs.readFileSync(filePath, "utf-8");
17
+ } catch {
18
+ return null;
19
+ }
20
+ let parsed;
21
+ try {
22
+ parsed = JSON.parse(raw);
23
+ } catch {
24
+ return null;
25
+ }
26
+ if (!parsed || typeof parsed !== "object") return null;
27
+ const entry = parsed;
28
+ const sessionId = typeof entry.session_id === "string" ? entry.session_id : null;
29
+ const pid = parsePidHint(entry.process_generation_hint);
30
+ if (!sessionId || !SESSION_ID_PATTERN.test(sessionId) || pid === null) return null;
31
+ return {
32
+ sessionId,
33
+ pid
34
+ };
35
+ }
36
+ /** Head-read a transcript for its recorded workspace root (bounded, cheap). */ function readWorkspaceRootHead(filePath, maxBytes = 8192) {
37
+ let fd;
38
+ try {
39
+ fd = fs.openSync(filePath, "r");
40
+ } catch {
41
+ return null;
42
+ }
43
+ try {
44
+ const stat = fs.fstatSync(fd);
45
+ const buf = Buffer.alloc(Math.min(maxBytes, stat.size));
46
+ fs.readSync(fd, buf, 0, buf.length, 0);
47
+ const text = buf.toString("utf-8");
48
+ for (const line of text.split("\n")){
49
+ if (!line.includes("runtime.session.metadata")) continue;
50
+ try {
51
+ const outer = JSON.parse(line);
52
+ const inner = typeof outer.record_json === "string" ? JSON.parse(outer.record_json) : outer;
53
+ const root = inner.payload?.record?.workspace_root;
54
+ if (typeof root === "string" && root) return root;
55
+ } catch {
56
+ /* keep scanning */ }
57
+ }
58
+ return null;
59
+ } catch {
60
+ return null;
61
+ } finally{
62
+ try {
63
+ fs.closeSync(fd);
64
+ } catch {
65
+ /* best effort */ }
66
+ }
67
+ }
68
+ export class MuseSessionLocator {
69
+ home;
70
+ runtimeDir;
71
+ archiveDir;
72
+ constructor(options = {}){
73
+ this.home = options.homeDir ?? homeDir();
74
+ const store = path.join(this.home, ".local", "share", "muse");
75
+ this.runtimeDir = options.runtimeDir ?? path.join(store, "runtime", "muse", "sessions");
76
+ this.archiveDir = options.archiveDir ?? path.join(store, "sessions");
77
+ }
78
+ /**
79
+ * Pair live Muse processes with transcripts.
80
+ *
81
+ * Two staged strategies, each handing unmatched processes onward:
82
+ * 1. Runtime-file matching via `runtime/muse/sessions/<id>.json`
83
+ * (authoritative; guarded against recycled pids).
84
+ * 2. Legacy cwd+birthtime heuristic over recent transcripts.
85
+ */ matchRunningProcesses(processes) {
86
+ // Callers pass muse processes only (the adapter pre-filters via canHandle).
87
+ const { direct, fallback: noDirect } = this.tryRuntimeFileMatching(processes);
88
+ const legacySessions = this.discoverLiveSessions(noDirect);
89
+ const legacyMatches = noDirect.length > 0 && legacySessions.length > 0 ? matchProcessesToSessions(noDirect, legacySessions) : [];
90
+ const matchedPids = new Set([
91
+ ...direct.map((d)=>d.process.pid),
92
+ ...legacyMatches.map((m)=>m.process.pid)
93
+ ]);
94
+ return {
95
+ direct,
96
+ legacyMatches,
97
+ fallback: noDirect.filter((p)=>!matchedPids.has(p.pid))
98
+ };
99
+ }
100
+ tryRuntimeFileMatching(processes) {
101
+ const byPid = new Map();
102
+ for (const proc of processes){
103
+ if (!byPid.has(proc.pid)) byPid.set(proc.pid, proc);
104
+ }
105
+ const direct = [];
106
+ const usedPids = new Set();
107
+ if (!isDirectory(this.runtimeDir)) return {
108
+ direct,
109
+ fallback: processes
110
+ };
111
+ for (const name of safeReaddir(this.runtimeDir)){
112
+ if (!name.endsWith(".json")) continue;
113
+ const entry = parseRuntimeEntry(path.join(this.runtimeDir, name));
114
+ if (!entry) continue;
115
+ const proc = byPid.get(entry.pid);
116
+ if (!proc || usedPids.has(proc.pid)) continue;
117
+ const transcript = this.findTranscriptById(entry.sessionId);
118
+ if (!transcript) continue;
119
+ // Guard against pid recycling: the live process must have started
120
+ // around the transcript's creation.
121
+ const birth = safeStat(transcript)?.birthtimeMs;
122
+ const start = proc.startTime?.getTime();
123
+ if (birth === undefined || start === undefined) continue;
124
+ if (Math.abs(start - birth) > PID_STALENESS_MS) continue;
125
+ usedPids.add(proc.pid);
126
+ direct.push({
127
+ process: proc,
128
+ sessionFile: {
129
+ sessionId: entry.sessionId,
130
+ filePath: transcript,
131
+ projectDir: path.dirname(transcript),
132
+ birthtimeMs: birth,
133
+ resolvedCwd: proc.cwd ?? ""
134
+ }
135
+ });
136
+ }
137
+ return {
138
+ direct,
139
+ fallback: processes.filter((p)=>!usedPids.has(p.pid))
140
+ };
141
+ }
142
+ /** Recent transcripts for legacy cwd+birthtime matching (today-first, bounded). */ discoverLiveSessions(processes) {
143
+ const cwds = new Set(processes.map((p)=>p.cwd).filter((cwd)=>!!cwd));
144
+ if (cwds.size === 0 || !isDirectory(this.archiveDir)) return [];
145
+ const dayDirs = this.listDayDirs().slice(-2);
146
+ const sessionFiles = [];
147
+ for (const dayDir of dayDirs){
148
+ for (const name of safeReaddir(dayDir)){
149
+ if (!SESSION_ID_PATTERN.test(name)) continue;
150
+ const filePath = path.join(dayDir, name, "session.jsonl");
151
+ const stat = safeStat(filePath);
152
+ if (!stat?.isFile() || !Number.isFinite(stat.birthtimeMs) || stat.birthtimeMs <= 0) {
153
+ continue;
154
+ }
155
+ const workspaceRoot = readWorkspaceRootHead(filePath);
156
+ if (!workspaceRoot || !cwds.has(workspaceRoot)) continue;
157
+ sessionFiles.push({
158
+ sessionId: name,
159
+ filePath,
160
+ projectDir: path.dirname(filePath),
161
+ birthtimeMs: stat.birthtimeMs,
162
+ resolvedCwd: workspaceRoot
163
+ });
164
+ }
165
+ }
166
+ return sessionFiles;
167
+ }
168
+ /**
169
+ * Every archived transcript: walks `sessions/yyyy/mm/dd/<uuid>/session.jsonl`.
170
+ * Only directories matching the session-id pattern that contain a transcript
171
+ * are returned; `subagent/`, logs, and databases never match.
172
+ */ discoverHistoricalSessionFiles() {
173
+ const out = [];
174
+ for (const filePath of this.walkTranscripts()){
175
+ out.push({
176
+ filePath,
177
+ defaultCwd: ""
178
+ });
179
+ }
180
+ return out;
181
+ }
182
+ findHistoricalSessionFilesById(sessionId) {
183
+ if (!isSafePathSegment(sessionId) || !SESSION_ID_PATTERN.test(sessionId)) return [];
184
+ const filePath = this.findTranscriptById(sessionId);
185
+ return filePath ? [
186
+ {
187
+ filePath,
188
+ defaultCwd: ""
189
+ }
190
+ ] : [];
191
+ }
192
+ /** Exact transcript lookup by session id across dated dirs. */ findTranscriptById(sessionId) {
193
+ if (!isSafePathSegment(sessionId) || !SESSION_ID_PATTERN.test(sessionId)) return null;
194
+ for (const dayDir of this.listDayDirs()){
195
+ const filePath = path.join(dayDir, sessionId, "session.jsonl");
196
+ if (safeStat(filePath)?.isFile()) return filePath;
197
+ }
198
+ return null;
199
+ }
200
+ walkTranscripts() {
201
+ const out = [];
202
+ for (const dayDir of this.listDayDirs()){
203
+ for (const name of safeReaddir(dayDir)){
204
+ if (!SESSION_ID_PATTERN.test(name)) continue;
205
+ const filePath = path.join(dayDir, name, "session.jsonl");
206
+ if (safeStat(filePath)?.isFile()) out.push(filePath);
207
+ }
208
+ }
209
+ return out;
210
+ }
211
+ /** Dated directories `sessions/yyyy/mm/dd`, each level guarded by a pattern. */ listDayDirs() {
212
+ const out = [];
213
+ if (!isDirectory(this.archiveDir)) return out;
214
+ for (const yyyy of safeReaddir(this.archiveDir)){
215
+ if (!/^\d{4}$/.test(yyyy)) continue;
216
+ const yDir = path.join(this.archiveDir, yyyy);
217
+ if (!isDirectory(yDir)) continue;
218
+ for (const mm of safeReaddir(yDir)){
219
+ if (!/^\d{2}$/.test(mm)) continue;
220
+ const mDir = path.join(yDir, mm);
221
+ if (!isDirectory(mDir)) continue;
222
+ for (const dd of safeReaddir(mDir)){
223
+ if (!/^\d{2}$/.test(dd)) continue;
224
+ const dDir = path.join(mDir, dd);
225
+ if (isDirectory(dDir)) out.push(dDir);
226
+ }
227
+ }
228
+ }
229
+ return out;
230
+ }
231
+ }
232
+
233
+ //# sourceMappingURL=MuseSessionLocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/harnesses/muse/MuseSessionLocator.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\nimport type { ProcessInfo } from \"../../adapters/AgentAdapter.js\";\nimport { matchProcessesToSessions, type MatchResult } from \"../../utils/matching.js\";\nimport {\n isDirectory,\n isSafePathSegment,\n safeReaddir,\n safeStat,\n type SessionFile,\n} from \"../../utils/session.js\";\nimport { homeDir } from \"../shared.js\";\n\n/** Entry in `~/.local/share/muse/runtime/muse/sessions/<session-id>.json`. */\nexport interface MuseRuntimeEntry {\n sessionId: string;\n pid: number;\n}\n\n/** A live Muse process paired with its transcript through the runtime file. */\nexport interface MuseDirectMatch {\n process: ProcessInfo;\n sessionFile: SessionFile;\n}\n\nexport interface MuseProcessSessionMatches {\n direct: MuseDirectMatch[];\n legacyMatches: MatchResult[];\n /** Muse processes no strategy could pair (become process-only agents). */\n fallback: ProcessInfo[];\n}\n\nexport interface MuseSessionLocatorOptions {\n homeDir?: string;\n runtimeDir?: string;\n archiveDir?: string;\n}\n\n/** Session ids are UUID-shaped; anything else is never a session dir. */\nconst SESSION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/** Maximum |process start − transcript birth| before a pid match is recycled. */\nconst PID_STALENESS_MS = 60000;\n\nfunction parsePidHint(value: unknown): number | null {\n if (typeof value !== \"string\") return null;\n const match = /^pid=(\\d+)$/.exec(value.trim());\n return match ? Number(match[1]) : null;\n}\n\nfunction parseRuntimeEntry(filePath: string): MuseRuntimeEntry | null {\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== \"object\") return null;\n const entry = parsed as { session_id?: unknown; process_generation_hint?: unknown };\n const sessionId = typeof entry.session_id === \"string\" ? entry.session_id : null;\n const pid = parsePidHint(entry.process_generation_hint);\n if (!sessionId || !SESSION_ID_PATTERN.test(sessionId) || pid === null) return null;\n return { sessionId, pid };\n}\n\n/** Head-read a transcript for its recorded workspace root (bounded, cheap). */\nfunction readWorkspaceRootHead(filePath: string, maxBytes = 8192): string | null {\n let fd: number;\n try {\n fd = fs.openSync(filePath, \"r\");\n } catch {\n return null;\n }\n try {\n const stat = fs.fstatSync(fd);\n const buf = Buffer.alloc(Math.min(maxBytes, stat.size));\n fs.readSync(fd, buf, 0, buf.length, 0);\n const text = buf.toString(\"utf-8\");\n for (const line of text.split(\"\\n\")) {\n if (!line.includes(\"runtime.session.metadata\")) continue;\n try {\n const outer = JSON.parse(line) as {\n record_json?: string;\n payload?: { record?: { workspace_root?: unknown } };\n };\n const inner =\n typeof outer.record_json === \"string\"\n ? (JSON.parse(outer.record_json) as typeof outer)\n : outer;\n const root = inner.payload?.record?.workspace_root;\n if (typeof root === \"string\" && root) return root;\n } catch {\n /* keep scanning */\n }\n }\n return null;\n } catch {\n return null;\n } finally {\n try {\n fs.closeSync(fd);\n } catch {\n /* best effort */\n }\n }\n}\n\nexport class MuseSessionLocator {\n private readonly home: string;\n private readonly runtimeDir: string;\n private readonly archiveDir: string;\n\n constructor(options: MuseSessionLocatorOptions = {}) {\n this.home = options.homeDir ?? homeDir();\n const store = path.join(this.home, \".local\", \"share\", \"muse\");\n this.runtimeDir = options.runtimeDir ?? path.join(store, \"runtime\", \"muse\", \"sessions\");\n this.archiveDir = options.archiveDir ?? path.join(store, \"sessions\");\n }\n\n /**\n * Pair live Muse processes with transcripts.\n *\n * Two staged strategies, each handing unmatched processes onward:\n * 1. Runtime-file matching via `runtime/muse/sessions/<id>.json`\n * (authoritative; guarded against recycled pids).\n * 2. Legacy cwd+birthtime heuristic over recent transcripts.\n */\n matchRunningProcesses(processes: ProcessInfo[]): MuseProcessSessionMatches {\n // Callers pass muse processes only (the adapter pre-filters via canHandle).\n const { direct, fallback: noDirect } = this.tryRuntimeFileMatching(processes);\n const legacySessions = this.discoverLiveSessions(noDirect);\n const legacyMatches =\n noDirect.length > 0 && legacySessions.length > 0\n ? matchProcessesToSessions(noDirect, legacySessions)\n : [];\n const matchedPids = new Set([\n ...direct.map((d) => d.process.pid),\n ...legacyMatches.map((m) => m.process.pid),\n ]);\n return {\n direct,\n legacyMatches,\n fallback: noDirect.filter((p) => !matchedPids.has(p.pid)),\n };\n }\n\n private tryRuntimeFileMatching(processes: ProcessInfo[]): {\n direct: MuseDirectMatch[];\n fallback: ProcessInfo[];\n } {\n const byPid = new Map<number, ProcessInfo>();\n for (const proc of processes) {\n if (!byPid.has(proc.pid)) byPid.set(proc.pid, proc);\n }\n const direct: MuseDirectMatch[] = [];\n const usedPids = new Set<number>();\n if (!isDirectory(this.runtimeDir)) return { direct, fallback: processes };\n\n for (const name of safeReaddir(this.runtimeDir)) {\n if (!name.endsWith(\".json\")) continue;\n const entry = parseRuntimeEntry(path.join(this.runtimeDir, name));\n if (!entry) continue;\n const proc = byPid.get(entry.pid);\n if (!proc || usedPids.has(proc.pid)) continue;\n const transcript = this.findTranscriptById(entry.sessionId);\n if (!transcript) continue;\n // Guard against pid recycling: the live process must have started\n // around the transcript's creation.\n const birth = safeStat(transcript)?.birthtimeMs;\n const start = proc.startTime?.getTime();\n if (birth === undefined || start === undefined) continue;\n if (Math.abs(start - birth) > PID_STALENESS_MS) continue;\n usedPids.add(proc.pid);\n direct.push({\n process: proc,\n sessionFile: {\n sessionId: entry.sessionId,\n filePath: transcript,\n projectDir: path.dirname(transcript),\n birthtimeMs: birth,\n resolvedCwd: proc.cwd ?? \"\",\n },\n });\n }\n return { direct, fallback: processes.filter((p) => !usedPids.has(p.pid)) };\n }\n\n /** Recent transcripts for legacy cwd+birthtime matching (today-first, bounded). */\n discoverLiveSessions(processes: ProcessInfo[]): SessionFile[] {\n const cwds = new Set(processes.map((p) => p.cwd).filter((cwd): cwd is string => !!cwd));\n if (cwds.size === 0 || !isDirectory(this.archiveDir)) return [];\n const dayDirs = this.listDayDirs().slice(-2);\n const sessionFiles: SessionFile[] = [];\n for (const dayDir of dayDirs) {\n for (const name of safeReaddir(dayDir)) {\n if (!SESSION_ID_PATTERN.test(name)) continue;\n const filePath = path.join(dayDir, name, \"session.jsonl\");\n const stat = safeStat(filePath);\n if (!stat?.isFile() || !Number.isFinite(stat.birthtimeMs) || stat.birthtimeMs <= 0) {\n continue;\n }\n const workspaceRoot = readWorkspaceRootHead(filePath);\n if (!workspaceRoot || !cwds.has(workspaceRoot)) continue;\n sessionFiles.push({\n sessionId: name,\n filePath,\n projectDir: path.dirname(filePath),\n birthtimeMs: stat.birthtimeMs,\n resolvedCwd: workspaceRoot,\n });\n }\n }\n return sessionFiles;\n }\n\n /**\n * Every archived transcript: walks `sessions/yyyy/mm/dd/<uuid>/session.jsonl`.\n * Only directories matching the session-id pattern that contain a transcript\n * are returned; `subagent/`, logs, and databases never match.\n */\n discoverHistoricalSessionFiles(): Array<{ filePath: string; defaultCwd: string }> {\n const out: Array<{ filePath: string; defaultCwd: string }> = [];\n for (const filePath of this.walkTranscripts()) {\n out.push({ filePath, defaultCwd: \"\" });\n }\n return out;\n }\n\n findHistoricalSessionFilesById(\n sessionId: string,\n ): Array<{ filePath: string; defaultCwd: string }> {\n if (!isSafePathSegment(sessionId) || !SESSION_ID_PATTERN.test(sessionId)) return [];\n const filePath = this.findTranscriptById(sessionId);\n return filePath ? [{ filePath, defaultCwd: \"\" }] : [];\n }\n\n /** Exact transcript lookup by session id across dated dirs. */\n findTranscriptById(sessionId: string): string | null {\n if (!isSafePathSegment(sessionId) || !SESSION_ID_PATTERN.test(sessionId)) return null;\n for (const dayDir of this.listDayDirs()) {\n const filePath = path.join(dayDir, sessionId, \"session.jsonl\");\n if (safeStat(filePath)?.isFile()) return filePath;\n }\n return null;\n }\n\n private walkTranscripts(): string[] {\n const out: string[] = [];\n for (const dayDir of this.listDayDirs()) {\n for (const name of safeReaddir(dayDir)) {\n if (!SESSION_ID_PATTERN.test(name)) continue;\n const filePath = path.join(dayDir, name, \"session.jsonl\");\n if (safeStat(filePath)?.isFile()) out.push(filePath);\n }\n }\n return out;\n }\n\n /** Dated directories `sessions/yyyy/mm/dd`, each level guarded by a pattern. */\n private listDayDirs(): string[] {\n const out: string[] = [];\n if (!isDirectory(this.archiveDir)) return out;\n for (const yyyy of safeReaddir(this.archiveDir)) {\n if (!/^\\d{4}$/.test(yyyy)) continue;\n const yDir = path.join(this.archiveDir, yyyy);\n if (!isDirectory(yDir)) continue;\n for (const mm of safeReaddir(yDir)) {\n if (!/^\\d{2}$/.test(mm)) continue;\n const mDir = path.join(yDir, mm);\n if (!isDirectory(mDir)) continue;\n for (const dd of safeReaddir(mDir)) {\n if (!/^\\d{2}$/.test(dd)) continue;\n const dDir = path.join(mDir, dd);\n if (isDirectory(dDir)) out.push(dDir);\n }\n }\n }\n return out;\n }\n}\n"],"names":["fs","path","matchProcessesToSessions","isDirectory","isSafePathSegment","safeReaddir","safeStat","homeDir","SESSION_ID_PATTERN","PID_STALENESS_MS","parsePidHint","value","match","exec","trim","Number","parseRuntimeEntry","filePath","raw","readFileSync","parsed","JSON","parse","entry","sessionId","session_id","pid","process_generation_hint","test","readWorkspaceRootHead","maxBytes","fd","openSync","stat","fstatSync","buf","Buffer","alloc","Math","min","size","readSync","length","text","toString","line","split","includes","outer","inner","record_json","root","payload","record","workspace_root","closeSync","MuseSessionLocator","home","runtimeDir","archiveDir","options","store","join","matchRunningProcesses","processes","direct","fallback","noDirect","tryRuntimeFileMatching","legacySessions","discoverLiveSessions","legacyMatches","matchedPids","Set","map","d","process","m","filter","p","has","byPid","Map","proc","set","usedPids","name","endsWith","get","transcript","findTranscriptById","birth","birthtimeMs","start","startTime","getTime","undefined","abs","add","push","sessionFile","projectDir","dirname","resolvedCwd","cwd","cwds","dayDirs","listDayDirs","slice","sessionFiles","dayDir","isFile","isFinite","workspaceRoot","discoverHistoricalSessionFiles","out","walkTranscripts","defaultCwd","findHistoricalSessionFilesById","yyyy","yDir","mm","mDir","dd","dDir"],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import type { ConversationMessage, ConversationOptions } from "../../adapters/AgentAdapter.js";
2
+ import { AgentStatus } from "../../adapters/AgentAdapter.js";
3
+ /**
4
+ * A single unwrapped inner record from a Muse session frame.
5
+ *
6
+ * Each session.jsonl line is one of: a direct inner record, a
7
+ * `{ record_json: string }` envelope, or a `retained_frame` wrapper whose
8
+ * `children[]` carry `record_json` strings. Inner records dispatch on
9
+ * `payload_type`; timestamps (`recorded_at`) are microseconds.
10
+ */
11
+ export interface MuseInnerRecord {
12
+ stream?: {
13
+ kind?: string;
14
+ id?: string;
15
+ };
16
+ sequence?: number;
17
+ recorded_at?: number;
18
+ record_type?: string;
19
+ payload_type?: string;
20
+ payload?: Record<string, unknown>;
21
+ }
22
+ /** Parsed session state extracted from a Muse transcript. */
23
+ export interface MuseSession {
24
+ sessionId: string;
25
+ projectPath: string;
26
+ /** Last display name from `session.name.changed`, when present. */
27
+ displayName?: string;
28
+ modelId?: string;
29
+ sessionStart: Date;
30
+ lastActive: Date;
31
+ /** Last conversation signal: user-intent, assistant reply, approval, tool batch… */
32
+ lastSignal?: string;
33
+ lastUserMessage?: string;
34
+ /** First meaningful user prompt in the session. */
35
+ firstUserMessage?: string;
36
+ }
37
+ /** `recorded_at` microseconds → epoch ms; null when invalid. */
38
+ export declare function museTimestampToMs(value: unknown): number | null;
39
+ /** Unwrap one raw frame line into zero or more inner records. */
40
+ export declare function unwrapFrameRecords(line: string): MuseInnerRecord[];
41
+ /** Unwrap an already-parsed frame value into zero or more inner records. */
42
+ export declare function unwrapOuterRecords(outer: unknown): MuseInnerRecord[];
43
+ export declare class MuseSessionParser {
44
+ private readonly tailReader;
45
+ private readonly sessionCache;
46
+ constructor();
47
+ readSession(filePath: string, projectPath: string): MuseSession | null;
48
+ readSessionIncremental(filePath: string, projectPath: string): MuseSession | null;
49
+ pruneSessionCache(): void;
50
+ private readonly summaryReducer;
51
+ /**
52
+ * Fold one inner record into the summary. `isHead` marks the first line
53
+ * (session start only); `canBeFirst` allows the first user message from any
54
+ * line read before a bounded-skip.
55
+ */
56
+ private foldRecord;
57
+ private toSession;
58
+ /**
59
+ * Status mapping over the last conversation signal:
60
+ * - user-intent → RUNNING (agent is processing the new turn)
61
+ * - assistant → WAITING (reply committed, awaiting user)
62
+ * - approval-wait / input-requested → WAITING (blocked on the user)
63
+ * - run-terminal → IDLE; no signal → UNKNOWN.
64
+ */
65
+ determineStatus(session: MuseSession): AgentStatus;
66
+ getConversation(sessionFilePath: string, options?: ConversationOptions): ConversationMessage[];
67
+ /** One raw frame line → conversation messages (usually zero or one). */
68
+ private linesToMessages;
69
+ /**
70
+ * One raw frame line → its first conversation message, for tail reads.
71
+ * A retained frame can theoretically hold several messages; the tail
72
+ * window counts lines, so a boundary line keeps only its first message.
73
+ */
74
+ private lineToMessage;
75
+ private recordToMessage;
76
+ }
77
+ //# sourceMappingURL=MuseSessionParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MuseSessionParser.d.ts","sourceRoot":"","sources":["../../../src/harnesses/muse/MuseSessionParser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC/F,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAQ7D;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,6DAA6D;AAC7D,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC;IACjB,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA2ED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAI/D;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CAQlE;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,EAAE,CA6BpE;AA4CD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA4C;;IAMzE,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAWtE,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAKjF,iBAAiB,IAAI,IAAI;IAIzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAkB7B;IAEF;;;;OAIG;IACH,OAAO,CAAC,UAAU;IA2DlB,OAAO,CAAC,SAAS;IAejB;;;;;;OAMG;IACH,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW;IAelD,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE;IAwB9F,wEAAwE;IACxE,OAAO,CAAC,eAAe;IASvB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,eAAe;CAiCxB"}