@ai-devkit/agent-manager 0.9.0 → 0.10.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.
- package/dist/AgentManager.d.ts +7 -0
- package/dist/AgentManager.d.ts.map +1 -1
- package/dist/AgentManager.js +9 -0
- package/dist/AgentManager.js.map +1 -1
- package/dist/adapters/ClaudeCodeAdapter.d.ts +2 -44
- package/dist/adapters/ClaudeCodeAdapter.d.ts.map +1 -1
- package/dist/adapters/ClaudeCodeAdapter.js +10 -285
- package/dist/adapters/ClaudeCodeAdapter.js.map +1 -1
- package/dist/terminal/TerminalFocusManager.d.ts.map +1 -1
- package/dist/terminal/TerminalFocusManager.js +38 -27
- package/dist/terminal/TerminalFocusManager.js.map +1 -1
- package/dist/utils/ClaudeSessionParser.d.ts +112 -0
- package/dist/utils/ClaudeSessionParser.d.ts.map +1 -0
- package/dist/utils/ClaudeSessionParser.js +334 -0
- package/dist/utils/ClaudeSessionParser.js.map +1 -0
- package/dist/utils/process.d.ts +3 -4
- package/dist/utils/process.d.ts.map +1 -1
- package/dist/utils/process.js +11 -15
- package/dist/utils/process.js.map +1 -1
- package/package.json +1 -1
- package/src/AgentManager.ts +11 -1
- package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +29 -29
- package/src/__tests__/utils/process.test.ts +27 -27
- package/src/adapters/ClaudeCodeAdapter.ts +17 -365
- package/src/terminal/TerminalFocusManager.ts +38 -26
- package/src/utils/ClaudeSessionParser.ts +383 -0
- package/src/utils/process.ts +21 -24
|
@@ -4,7 +4,6 @@ exports.TerminalFocusManager = exports.TerminalType = void 0;
|
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const util_1 = require("util");
|
|
6
6
|
const process_1 = require("../utils/process");
|
|
7
|
-
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
8
7
|
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
9
8
|
var TerminalType;
|
|
10
9
|
(function (TerminalType) {
|
|
@@ -13,6 +12,9 @@ var TerminalType;
|
|
|
13
12
|
TerminalType["TERMINAL_APP"] = "terminal-app";
|
|
14
13
|
TerminalType["UNKNOWN"] = "unknown";
|
|
15
14
|
})(TerminalType || (exports.TerminalType = TerminalType = {}));
|
|
15
|
+
function escapeAppleScript(text) {
|
|
16
|
+
return text.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
17
|
+
}
|
|
16
18
|
class TerminalFocusManager {
|
|
17
19
|
/**
|
|
18
20
|
* Find the terminal location (emulator info) for a given process ID
|
|
@@ -59,16 +61,15 @@ class TerminalFocusManager {
|
|
|
59
61
|
return false;
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
|
-
catch
|
|
64
|
+
catch {
|
|
63
65
|
return false;
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
async findTmuxPane(tty) {
|
|
67
69
|
try {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const { stdout } = await execAsync("tmux list-panes -a -F '#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}'");
|
|
70
|
+
const { stdout } = await execFileAsync('tmux', [
|
|
71
|
+
'list-panes', '-a', '-F', '#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}'
|
|
72
|
+
]);
|
|
72
73
|
const lines = stdout.trim().split('\n');
|
|
73
74
|
for (const line of lines) {
|
|
74
75
|
if (!line.trim())
|
|
@@ -83,7 +84,7 @@ class TerminalFocusManager {
|
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
|
-
catch
|
|
87
|
+
catch {
|
|
87
88
|
// tmux might not be installed or running
|
|
88
89
|
}
|
|
89
90
|
return null;
|
|
@@ -91,15 +92,19 @@ class TerminalFocusManager {
|
|
|
91
92
|
async findITerm2Session(tty) {
|
|
92
93
|
try {
|
|
93
94
|
// Check if iTerm2 is running first to avoid launching it
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
await execFileAsync('pgrep', ['-x', 'iTerm2']);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const escapedTty = escapeAppleScript(tty);
|
|
97
102
|
const script = `
|
|
98
103
|
tell application "iTerm"
|
|
99
104
|
repeat with w in windows
|
|
100
105
|
repeat with t in tabs of w
|
|
101
106
|
repeat with s in sessions of t
|
|
102
|
-
if tty of s is "${
|
|
107
|
+
if tty of s is "${escapedTty}" then
|
|
103
108
|
return "found"
|
|
104
109
|
end if
|
|
105
110
|
end repeat
|
|
@@ -107,7 +112,7 @@ class TerminalFocusManager {
|
|
|
107
112
|
end repeat
|
|
108
113
|
end tell
|
|
109
114
|
`;
|
|
110
|
-
const { stdout } = await
|
|
115
|
+
const { stdout } = await execFileAsync('osascript', ['-e', script]);
|
|
111
116
|
if (stdout.trim() === "found") {
|
|
112
117
|
return {
|
|
113
118
|
type: TerminalType.ITERM2,
|
|
@@ -116,29 +121,33 @@ class TerminalFocusManager {
|
|
|
116
121
|
};
|
|
117
122
|
}
|
|
118
123
|
}
|
|
119
|
-
catch
|
|
120
|
-
// iTerm2
|
|
124
|
+
catch {
|
|
125
|
+
// iTerm2 script failed
|
|
121
126
|
}
|
|
122
127
|
return null;
|
|
123
128
|
}
|
|
124
129
|
async findTerminalAppWindow(tty) {
|
|
125
130
|
try {
|
|
126
|
-
// Check if Terminal is running
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
// Check if Terminal.app is running
|
|
132
|
+
await execFileAsync('pgrep', ['-x', 'Terminal']);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const escapedTty = escapeAppleScript(tty);
|
|
130
139
|
const script = `
|
|
131
140
|
tell application "Terminal"
|
|
132
141
|
repeat with w in windows
|
|
133
142
|
repeat with t in tabs of w
|
|
134
|
-
if tty of t is "${
|
|
143
|
+
if tty of t is "${escapedTty}" then
|
|
135
144
|
return "found"
|
|
136
145
|
end if
|
|
137
146
|
end repeat
|
|
138
147
|
end repeat
|
|
139
148
|
end tell
|
|
140
149
|
`;
|
|
141
|
-
const { stdout } = await
|
|
150
|
+
const { stdout } = await execFileAsync('osascript', ['-e', script]);
|
|
142
151
|
if (stdout.trim() === "found") {
|
|
143
152
|
return {
|
|
144
153
|
type: TerminalType.TERMINAL_APP,
|
|
@@ -147,8 +156,8 @@ class TerminalFocusManager {
|
|
|
147
156
|
};
|
|
148
157
|
}
|
|
149
158
|
}
|
|
150
|
-
catch
|
|
151
|
-
// Terminal
|
|
159
|
+
catch {
|
|
160
|
+
// Terminal.app script failed
|
|
152
161
|
}
|
|
153
162
|
return null;
|
|
154
163
|
}
|
|
@@ -157,18 +166,19 @@ class TerminalFocusManager {
|
|
|
157
166
|
await execFileAsync('tmux', ['switch-client', '-t', identifier]);
|
|
158
167
|
return true;
|
|
159
168
|
}
|
|
160
|
-
catch
|
|
169
|
+
catch {
|
|
161
170
|
return false;
|
|
162
171
|
}
|
|
163
172
|
}
|
|
164
173
|
async focusITerm2Session(tty) {
|
|
174
|
+
const escapedTty = escapeAppleScript(tty);
|
|
165
175
|
const script = `
|
|
166
176
|
tell application "iTerm"
|
|
167
177
|
activate
|
|
168
178
|
repeat with w in windows
|
|
169
179
|
repeat with t in tabs of w
|
|
170
180
|
repeat with s in sessions of t
|
|
171
|
-
if tty of s is "${
|
|
181
|
+
if tty of s is "${escapedTty}" then
|
|
172
182
|
select s
|
|
173
183
|
return "true"
|
|
174
184
|
end if
|
|
@@ -177,16 +187,17 @@ class TerminalFocusManager {
|
|
|
177
187
|
end repeat
|
|
178
188
|
end tell
|
|
179
189
|
`;
|
|
180
|
-
const { stdout } = await
|
|
190
|
+
const { stdout } = await execFileAsync('osascript', ['-e', script]);
|
|
181
191
|
return stdout.trim() === "true";
|
|
182
192
|
}
|
|
183
193
|
async focusTerminalAppWindow(tty) {
|
|
194
|
+
const escapedTty = escapeAppleScript(tty);
|
|
184
195
|
const script = `
|
|
185
196
|
tell application "Terminal"
|
|
186
197
|
activate
|
|
187
198
|
repeat with w in windows
|
|
188
199
|
repeat with t in tabs of w
|
|
189
|
-
if tty of t is "${
|
|
200
|
+
if tty of t is "${escapedTty}" then
|
|
190
201
|
set index of w to 1
|
|
191
202
|
set selected tab of w to t
|
|
192
203
|
return "true"
|
|
@@ -195,7 +206,7 @@ class TerminalFocusManager {
|
|
|
195
206
|
end repeat
|
|
196
207
|
end tell
|
|
197
208
|
`;
|
|
198
|
-
const { stdout } = await
|
|
209
|
+
const { stdout } = await execFileAsync('osascript', ['-e', script]);
|
|
199
210
|
return stdout.trim() === "true";
|
|
200
211
|
}
|
|
201
212
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalFocusManager.js","sourceRoot":"","sources":["../../src/terminal/TerminalFocusManager.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"TerminalFocusManager.js","sourceRoot":"","sources":["../../src/terminal/TerminalFocusManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { ConversationMessage } from '../adapters/AgentAdapter';
|
|
2
|
+
import { AgentStatus } from '../adapters/AgentAdapter';
|
|
3
|
+
/**
|
|
4
|
+
* Content block within a Claude Code JSONL message entry.
|
|
5
|
+
* Handles text, tool_use, and tool_result block types.
|
|
6
|
+
*/
|
|
7
|
+
export interface ContentBlock {
|
|
8
|
+
type?: string;
|
|
9
|
+
text?: string;
|
|
10
|
+
content?: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
input?: Record<string, unknown>;
|
|
13
|
+
tool_use_id?: string;
|
|
14
|
+
is_error?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A single line entry in a Claude Code session JSONL file.
|
|
18
|
+
*
|
|
19
|
+
* Each line is an independent JSON object with a type discriminator:
|
|
20
|
+
* - "user" / "assistant" / "system" — conversation turns
|
|
21
|
+
* - "progress" / "thinking" — intermediate agent state
|
|
22
|
+
* - "last-prompt" / "file-history-snapshot" — metadata (not conversation state)
|
|
23
|
+
*/
|
|
24
|
+
export interface SessionEntry {
|
|
25
|
+
type?: string;
|
|
26
|
+
timestamp?: string;
|
|
27
|
+
cwd?: string;
|
|
28
|
+
message?: {
|
|
29
|
+
content?: string | ContentBlock[];
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Parsed session state extracted from a JSONL file.
|
|
34
|
+
* Aggregates data from all entries into a single summary.
|
|
35
|
+
*/
|
|
36
|
+
export interface ClaudeSession {
|
|
37
|
+
sessionId: string;
|
|
38
|
+
projectPath: string;
|
|
39
|
+
lastCwd?: string;
|
|
40
|
+
sessionStart: Date;
|
|
41
|
+
lastActive: Date;
|
|
42
|
+
lastEntryType?: string;
|
|
43
|
+
isInterrupted: boolean;
|
|
44
|
+
lastUserMessage?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Parses Claude Code session JSONL files into structured data.
|
|
48
|
+
*
|
|
49
|
+
* Session files live at ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
|
|
50
|
+
* and contain one JSON object per line, each representing a conversation
|
|
51
|
+
* event (user turn, assistant response, tool call, etc.).
|
|
52
|
+
*/
|
|
53
|
+
export declare class ClaudeSessionParser {
|
|
54
|
+
/**
|
|
55
|
+
* Parse a session JSONL file into a ClaudeSession summary.
|
|
56
|
+
*
|
|
57
|
+
* Iterates all lines to extract: session start time (from first entry),
|
|
58
|
+
* last activity timestamp, last entry type (for status), whether the
|
|
59
|
+
* session was interrupted, and the last meaningful user message.
|
|
60
|
+
*
|
|
61
|
+
* Returns null if the file is unreadable or empty.
|
|
62
|
+
*/
|
|
63
|
+
readSession(filePath: string, projectPath: string): ClaudeSession | null;
|
|
64
|
+
/**
|
|
65
|
+
* Determine agent status from parsed session state.
|
|
66
|
+
*
|
|
67
|
+
* Status mapping:
|
|
68
|
+
* - "user" + interrupted → WAITING (agent finished, awaiting new input)
|
|
69
|
+
* - "user" + not interrupted → RUNNING (agent is processing)
|
|
70
|
+
* - "progress" / "thinking" → RUNNING
|
|
71
|
+
* - "assistant" → WAITING (agent responded, awaiting user)
|
|
72
|
+
* - "system" → IDLE
|
|
73
|
+
*/
|
|
74
|
+
determineStatus(session: ClaudeSession): AgentStatus;
|
|
75
|
+
/**
|
|
76
|
+
* Read the full conversation from a session JSONL file.
|
|
77
|
+
*
|
|
78
|
+
* Default mode returns only text content from user/assistant/system messages.
|
|
79
|
+
* Verbose mode also includes tool_use and tool_result blocks.
|
|
80
|
+
*/
|
|
81
|
+
getConversation(sessionFilePath: string, options?: {
|
|
82
|
+
verbose?: boolean;
|
|
83
|
+
}): ConversationMessage[];
|
|
84
|
+
/**
|
|
85
|
+
* Parse session start time from the first JSONL line.
|
|
86
|
+
*
|
|
87
|
+
* Claude Code may emit a "file-history-snapshot" as the first entry,
|
|
88
|
+
* which stores its timestamp inside "snapshot.timestamp" rather than
|
|
89
|
+
* at the root level.
|
|
90
|
+
*/
|
|
91
|
+
private parseSessionStart;
|
|
92
|
+
/**
|
|
93
|
+
* Extract meaningful text from a user message content field.
|
|
94
|
+
*
|
|
95
|
+
* Handles multiple formats:
|
|
96
|
+
* - Plain string content
|
|
97
|
+
* - Array of content blocks (extracts first text block)
|
|
98
|
+
* - Skill slash-commands (<command-message> tags)
|
|
99
|
+
* - Expanded skill content (extracts ARGUMENTS line)
|
|
100
|
+
* - Filters noise messages (interruptions, tool loaded, session continued)
|
|
101
|
+
*/
|
|
102
|
+
private extractUserMessageText;
|
|
103
|
+
/**
|
|
104
|
+
* Parse a <command-message> string into "/command args" format.
|
|
105
|
+
*/
|
|
106
|
+
private parseCommandMessage;
|
|
107
|
+
/**
|
|
108
|
+
* Extract displayable content from a message content field for conversation output.
|
|
109
|
+
*/
|
|
110
|
+
private extractConversationContent;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=ClaudeSessionParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeSessionParser.d.ts","sourceRoot":"","sources":["../../src/utils/ClaudeSessionParser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;GAGG;AACH,MAAM,WAAW,YAAY;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAAC;KACrC,CAAC;CACL;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAKD;;;;;;GAMG;AACH,qBAAa,mBAAmB;IAC5B;;;;;;;;OAQG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IA8ExE;;;;;;;;;OASG;IACH,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW;IA6BpD;;;;;OAKG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,mBAAmB,EAAE;IAiDhG;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAiBzB;;;;;;;;;OASG;IACH,OAAO,CAAC,sBAAsB;IAwC9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B;;OAEG;IACH,OAAO,CAAC,0BAA0B;CAiCrC"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ClaudeSessionParser = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const AgentAdapter_1 = require("../adapters/AgentAdapter");
|
|
40
|
+
/** Entry types that are metadata, not conversation state. */
|
|
41
|
+
const METADATA_ENTRY_TYPES = new Set(['last-prompt', 'file-history-snapshot']);
|
|
42
|
+
/**
|
|
43
|
+
* Parses Claude Code session JSONL files into structured data.
|
|
44
|
+
*
|
|
45
|
+
* Session files live at ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
|
|
46
|
+
* and contain one JSON object per line, each representing a conversation
|
|
47
|
+
* event (user turn, assistant response, tool call, etc.).
|
|
48
|
+
*/
|
|
49
|
+
class ClaudeSessionParser {
|
|
50
|
+
/**
|
|
51
|
+
* Parse a session JSONL file into a ClaudeSession summary.
|
|
52
|
+
*
|
|
53
|
+
* Iterates all lines to extract: session start time (from first entry),
|
|
54
|
+
* last activity timestamp, last entry type (for status), whether the
|
|
55
|
+
* session was interrupted, and the last meaningful user message.
|
|
56
|
+
*
|
|
57
|
+
* Returns null if the file is unreadable or empty.
|
|
58
|
+
*/
|
|
59
|
+
readSession(filePath, projectPath) {
|
|
60
|
+
const sessionId = path.basename(filePath, '.jsonl');
|
|
61
|
+
let content;
|
|
62
|
+
try {
|
|
63
|
+
content = fs.readFileSync(filePath, 'utf-8');
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const allLines = content.trim().split('\n');
|
|
69
|
+
if (allLines.length === 0) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const sessionStart = this.parseSessionStart(allLines[0]);
|
|
73
|
+
let lastEntryType;
|
|
74
|
+
let lastActive;
|
|
75
|
+
let lastCwd;
|
|
76
|
+
let isInterrupted = false;
|
|
77
|
+
let lastUserMessage;
|
|
78
|
+
for (const line of allLines) {
|
|
79
|
+
try {
|
|
80
|
+
const entry = JSON.parse(line);
|
|
81
|
+
if (entry.timestamp) {
|
|
82
|
+
const ts = new Date(entry.timestamp);
|
|
83
|
+
if (!Number.isNaN(ts.getTime())) {
|
|
84
|
+
lastActive = ts;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (typeof entry.cwd === 'string' && entry.cwd.trim().length > 0) {
|
|
88
|
+
lastCwd = entry.cwd;
|
|
89
|
+
}
|
|
90
|
+
if (entry.type && !METADATA_ENTRY_TYPES.has(entry.type)) {
|
|
91
|
+
lastEntryType = entry.type;
|
|
92
|
+
if (entry.type === 'user') {
|
|
93
|
+
const msgContent = entry.message?.content;
|
|
94
|
+
isInterrupted =
|
|
95
|
+
Array.isArray(msgContent) &&
|
|
96
|
+
msgContent.some((c) => (c.type === 'text' &&
|
|
97
|
+
c.text?.includes('[Request interrupted')) ||
|
|
98
|
+
(c.type === 'tool_result' &&
|
|
99
|
+
c.content?.includes('[Request interrupted')));
|
|
100
|
+
const text = this.extractUserMessageText(msgContent);
|
|
101
|
+
if (text) {
|
|
102
|
+
lastUserMessage = text;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
isInterrupted = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
sessionId,
|
|
116
|
+
projectPath: projectPath || lastCwd || '',
|
|
117
|
+
lastCwd,
|
|
118
|
+
sessionStart: sessionStart || lastActive || new Date(),
|
|
119
|
+
lastActive: lastActive || new Date(),
|
|
120
|
+
lastEntryType,
|
|
121
|
+
isInterrupted,
|
|
122
|
+
lastUserMessage,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Determine agent status from parsed session state.
|
|
127
|
+
*
|
|
128
|
+
* Status mapping:
|
|
129
|
+
* - "user" + interrupted → WAITING (agent finished, awaiting new input)
|
|
130
|
+
* - "user" + not interrupted → RUNNING (agent is processing)
|
|
131
|
+
* - "progress" / "thinking" → RUNNING
|
|
132
|
+
* - "assistant" → WAITING (agent responded, awaiting user)
|
|
133
|
+
* - "system" → IDLE
|
|
134
|
+
*/
|
|
135
|
+
determineStatus(session) {
|
|
136
|
+
if (!session.lastEntryType) {
|
|
137
|
+
return AgentAdapter_1.AgentStatus.UNKNOWN;
|
|
138
|
+
}
|
|
139
|
+
if (session.lastEntryType === 'user') {
|
|
140
|
+
return session.isInterrupted
|
|
141
|
+
? AgentAdapter_1.AgentStatus.WAITING
|
|
142
|
+
: AgentAdapter_1.AgentStatus.RUNNING;
|
|
143
|
+
}
|
|
144
|
+
if (session.lastEntryType === 'progress' ||
|
|
145
|
+
session.lastEntryType === 'thinking') {
|
|
146
|
+
return AgentAdapter_1.AgentStatus.RUNNING;
|
|
147
|
+
}
|
|
148
|
+
if (session.lastEntryType === 'assistant') {
|
|
149
|
+
return AgentAdapter_1.AgentStatus.WAITING;
|
|
150
|
+
}
|
|
151
|
+
if (session.lastEntryType === 'system') {
|
|
152
|
+
return AgentAdapter_1.AgentStatus.IDLE;
|
|
153
|
+
}
|
|
154
|
+
return AgentAdapter_1.AgentStatus.UNKNOWN;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Read the full conversation from a session JSONL file.
|
|
158
|
+
*
|
|
159
|
+
* Default mode returns only text content from user/assistant/system messages.
|
|
160
|
+
* Verbose mode also includes tool_use and tool_result blocks.
|
|
161
|
+
*/
|
|
162
|
+
getConversation(sessionFilePath, options) {
|
|
163
|
+
const verbose = options?.verbose ?? false;
|
|
164
|
+
let content;
|
|
165
|
+
try {
|
|
166
|
+
content = fs.readFileSync(sessionFilePath, 'utf-8');
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
const lines = content.trim().split('\n');
|
|
172
|
+
const messages = [];
|
|
173
|
+
for (const line of lines) {
|
|
174
|
+
let entry;
|
|
175
|
+
try {
|
|
176
|
+
entry = JSON.parse(line);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const entryType = entry.type;
|
|
182
|
+
if (!entryType || METADATA_ENTRY_TYPES.has(entryType))
|
|
183
|
+
continue;
|
|
184
|
+
if (entryType === 'progress' || entryType === 'thinking')
|
|
185
|
+
continue;
|
|
186
|
+
let role;
|
|
187
|
+
if (entryType === 'user') {
|
|
188
|
+
role = 'user';
|
|
189
|
+
}
|
|
190
|
+
else if (entryType === 'assistant') {
|
|
191
|
+
role = 'assistant';
|
|
192
|
+
}
|
|
193
|
+
else if (entryType === 'system') {
|
|
194
|
+
role = 'system';
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const text = this.extractConversationContent(entry.message?.content, role, verbose);
|
|
200
|
+
if (!text)
|
|
201
|
+
continue;
|
|
202
|
+
messages.push({
|
|
203
|
+
role,
|
|
204
|
+
content: text,
|
|
205
|
+
timestamp: entry.timestamp,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return messages;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Parse session start time from the first JSONL line.
|
|
212
|
+
*
|
|
213
|
+
* Claude Code may emit a "file-history-snapshot" as the first entry,
|
|
214
|
+
* which stores its timestamp inside "snapshot.timestamp" rather than
|
|
215
|
+
* at the root level.
|
|
216
|
+
*/
|
|
217
|
+
parseSessionStart(firstLine) {
|
|
218
|
+
try {
|
|
219
|
+
const firstEntry = JSON.parse(firstLine);
|
|
220
|
+
const rawTs = firstEntry.timestamp || firstEntry.snapshot?.timestamp;
|
|
221
|
+
if (rawTs) {
|
|
222
|
+
const ts = new Date(rawTs);
|
|
223
|
+
if (!Number.isNaN(ts.getTime())) {
|
|
224
|
+
return ts;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
/* malformed first line */
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Extract meaningful text from a user message content field.
|
|
235
|
+
*
|
|
236
|
+
* Handles multiple formats:
|
|
237
|
+
* - Plain string content
|
|
238
|
+
* - Array of content blocks (extracts first text block)
|
|
239
|
+
* - Skill slash-commands (<command-message> tags)
|
|
240
|
+
* - Expanded skill content (extracts ARGUMENTS line)
|
|
241
|
+
* - Filters noise messages (interruptions, tool loaded, session continued)
|
|
242
|
+
*/
|
|
243
|
+
extractUserMessageText(content) {
|
|
244
|
+
if (!content) {
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
let raw;
|
|
248
|
+
if (typeof content === 'string') {
|
|
249
|
+
raw = content.trim();
|
|
250
|
+
}
|
|
251
|
+
else if (Array.isArray(content)) {
|
|
252
|
+
for (const block of content) {
|
|
253
|
+
if (block.type === 'text' && block.text?.trim()) {
|
|
254
|
+
raw = block.text.trim();
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (!raw) {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
if (raw.startsWith('<command-message>')) {
|
|
263
|
+
return this.parseCommandMessage(raw);
|
|
264
|
+
}
|
|
265
|
+
if (raw.startsWith('Base directory for this skill:')) {
|
|
266
|
+
const argsMatch = raw.match(/\nARGUMENTS:\s*(.+)/);
|
|
267
|
+
return argsMatch?.[1]?.trim() || undefined;
|
|
268
|
+
}
|
|
269
|
+
if (isNoiseMessage(raw)) {
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
return raw;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Parse a <command-message> string into "/command args" format.
|
|
276
|
+
*/
|
|
277
|
+
parseCommandMessage(raw) {
|
|
278
|
+
const nameMatch = raw.match(/<command-name>([^<]+)<\/command-name>/);
|
|
279
|
+
const argsMatch = raw.match(/<command-args>([^<]+)<\/command-args>/);
|
|
280
|
+
const name = nameMatch?.[1]?.trim();
|
|
281
|
+
if (!name) {
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
284
|
+
const args = argsMatch?.[1]?.trim();
|
|
285
|
+
return args ? `${name} ${args}` : name;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Extract displayable content from a message content field for conversation output.
|
|
289
|
+
*/
|
|
290
|
+
extractConversationContent(content, role, verbose) {
|
|
291
|
+
if (!content)
|
|
292
|
+
return undefined;
|
|
293
|
+
if (typeof content === 'string') {
|
|
294
|
+
const trimmed = content.trim();
|
|
295
|
+
if (role === 'user' && isNoiseMessage(trimmed))
|
|
296
|
+
return undefined;
|
|
297
|
+
return trimmed || undefined;
|
|
298
|
+
}
|
|
299
|
+
if (!Array.isArray(content))
|
|
300
|
+
return undefined;
|
|
301
|
+
const parts = [];
|
|
302
|
+
for (const block of content) {
|
|
303
|
+
if (block.type === 'text' && block.text?.trim()) {
|
|
304
|
+
if (role === 'user' && isNoiseMessage(block.text.trim()))
|
|
305
|
+
continue;
|
|
306
|
+
parts.push(block.text.trim());
|
|
307
|
+
}
|
|
308
|
+
else if (block.type === 'tool_use' && verbose) {
|
|
309
|
+
const inputSummary = block.input?.file_path || block.input?.pattern || block.input?.command || '';
|
|
310
|
+
parts.push(`[Tool: ${block.name}]${inputSummary ? ' ' + inputSummary : ''}`);
|
|
311
|
+
}
|
|
312
|
+
else if (block.type === 'tool_result' && verbose) {
|
|
313
|
+
const truncated = truncateToolResult(block.content || '');
|
|
314
|
+
const prefix = block.is_error ? '[Tool Error]' : '[Tool Result]';
|
|
315
|
+
parts.push(`${prefix} ${truncated}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return parts.length > 0 ? parts.join('\n') : undefined;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
exports.ClaudeSessionParser = ClaudeSessionParser;
|
|
322
|
+
/** Check if a message is noise (not a meaningful user intent). */
|
|
323
|
+
function isNoiseMessage(text) {
|
|
324
|
+
return (text.startsWith('[Request interrupted') ||
|
|
325
|
+
text === 'Tool loaded.' ||
|
|
326
|
+
text.startsWith('This session is being continued'));
|
|
327
|
+
}
|
|
328
|
+
function truncateToolResult(content, maxLength = 200) {
|
|
329
|
+
const firstLine = content.split('\n')[0] || '';
|
|
330
|
+
if (firstLine.length <= maxLength)
|
|
331
|
+
return firstLine;
|
|
332
|
+
return firstLine.slice(0, maxLength - 3) + '...';
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=ClaudeSessionParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeSessionParser.js","sourceRoot":"","sources":["../../src/utils/ClaudeSessionParser.ts"],"names":[],"mappings":"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"}
|