@akiojin/gwt 3.1.0 → 3.1.2
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/README.ja.md +1 -1
- package/README.md +1 -1
- package/dist/cli/ui/components/App.d.ts.map +1 -1
- package/dist/cli/ui/components/App.js +8 -8
- package/dist/cli/ui/components/App.js.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
- package/dist/cli/ui/components/screens/BranchListScreen.js +9 -5
- package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
- package/dist/cli/ui/utils/branchFormatter.js +2 -2
- package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/session/common.d.ts +100 -0
- package/dist/utils/session/common.d.ts.map +1 -0
- package/dist/utils/session/common.js +417 -0
- package/dist/utils/session/common.js.map +1 -0
- package/dist/utils/session/index.d.ts +16 -0
- package/dist/utils/session/index.d.ts.map +1 -0
- package/dist/utils/session/index.js +20 -0
- package/dist/utils/session/index.js.map +1 -0
- package/dist/utils/session/parsers/claude.d.ts +56 -0
- package/dist/utils/session/parsers/claude.d.ts.map +1 -0
- package/dist/utils/session/parsers/claude.js +178 -0
- package/dist/utils/session/parsers/claude.js.map +1 -0
- package/dist/utils/session/parsers/codex.d.ts +37 -0
- package/dist/utils/session/parsers/codex.d.ts.map +1 -0
- package/dist/utils/session/parsers/codex.js +113 -0
- package/dist/utils/session/parsers/codex.js.map +1 -0
- package/dist/utils/session/parsers/gemini.d.ts +22 -0
- package/dist/utils/session/parsers/gemini.d.ts.map +1 -0
- package/dist/utils/session/parsers/gemini.js +81 -0
- package/dist/utils/session/parsers/gemini.js.map +1 -0
- package/dist/utils/session/parsers/index.d.ts +8 -0
- package/dist/utils/session/parsers/index.d.ts.map +1 -0
- package/dist/utils/session/parsers/index.js +12 -0
- package/dist/utils/session/parsers/index.js.map +1 -0
- package/dist/utils/session/parsers/qwen.d.ts +21 -0
- package/dist/utils/session/parsers/qwen.d.ts.map +1 -0
- package/dist/utils/session/parsers/qwen.js +36 -0
- package/dist/utils/session/parsers/qwen.js.map +1 -0
- package/dist/utils/session/types.d.ts +38 -0
- package/dist/utils/session/types.d.ts.map +1 -0
- package/dist/utils/session/types.js +5 -0
- package/dist/utils/session/types.js.map +1 -0
- package/dist/utils/session.d.ts +14 -79
- package/dist/utils/session.d.ts.map +1 -1
- package/dist/utils/session.js +14 -585
- package/dist/utils/session.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +40 -1
- package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +1 -1
- package/src/cli/ui/components/App.tsx +10 -8
- package/src/cli/ui/components/screens/BranchListScreen.tsx +8 -6
- package/src/cli/ui/utils/branchFormatter.ts +2 -3
- package/src/index.ts +1 -1
- package/src/utils/session/common.ts +446 -0
- package/src/utils/session/index.ts +46 -0
- package/src/utils/session/parsers/claude.ts +233 -0
- package/src/utils/session/parsers/codex.ts +135 -0
- package/src/utils/session/parsers/gemini.ts +94 -0
- package/src/utils/session/parsers/index.ts +28 -0
- package/src/utils/session/parsers/qwen.ts +54 -0
- package/src/utils/session/types.ts +42 -0
- package/src/utils/session.ts +14 -755
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/utils/session/common.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD;;GAEG;AACH,eAAO,MAAM,UAAU,QAC0C,CAAC;AAElE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAIxD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAcnE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAuB7D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA6BpE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAChC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BxB;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAChC,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CA2BhD;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBxB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAiCpD;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,OAAO,EAClB,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAM,GAC9C,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmE/C;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GACnC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA0BxB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEvE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAOrC;AA4BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,SAAS,EAAE,MAAM,GAChB,OAAO,CAST"}
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session common utilities - shared helper functions for session parsers
|
|
3
|
+
*/
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
6
|
+
/**
|
|
7
|
+
* Regular expression for UUID matching
|
|
8
|
+
*/
|
|
9
|
+
export const UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
|
|
10
|
+
/**
|
|
11
|
+
* Validates that a string is a properly formatted UUID session ID.
|
|
12
|
+
* @param id - The string to validate
|
|
13
|
+
* @returns true if the string is a valid UUID format
|
|
14
|
+
*/
|
|
15
|
+
export function isValidUuidSessionId(id) {
|
|
16
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Extracts session ID from an object by checking common key names.
|
|
20
|
+
* Only returns valid UUIDs.
|
|
21
|
+
*/
|
|
22
|
+
export function pickSessionIdFromObject(obj) {
|
|
23
|
+
if (!obj || typeof obj !== "object")
|
|
24
|
+
return null;
|
|
25
|
+
const candidate = obj;
|
|
26
|
+
const keys = ["sessionId", "session_id", "id", "conversation_id"];
|
|
27
|
+
for (const key of keys) {
|
|
28
|
+
const value = candidate[key];
|
|
29
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
30
|
+
const trimmed = value.trim();
|
|
31
|
+
if (isValidUuidSessionId(trimmed)) {
|
|
32
|
+
return trimmed;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Extracts working directory from an object by checking common key names.
|
|
40
|
+
* Also checks nested payload object (for Codex session format).
|
|
41
|
+
*/
|
|
42
|
+
export function pickCwdFromObject(obj) {
|
|
43
|
+
if (!obj || typeof obj !== "object")
|
|
44
|
+
return null;
|
|
45
|
+
const candidate = obj;
|
|
46
|
+
const keys = [
|
|
47
|
+
"cwd",
|
|
48
|
+
"workingDirectory",
|
|
49
|
+
"workdir",
|
|
50
|
+
"directory",
|
|
51
|
+
"projectPath",
|
|
52
|
+
];
|
|
53
|
+
for (const key of keys) {
|
|
54
|
+
const value = candidate[key];
|
|
55
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Check nested payload object (for Codex session format)
|
|
60
|
+
const payload = candidate["payload"];
|
|
61
|
+
if (payload && typeof payload === "object") {
|
|
62
|
+
const nested = pickCwdFromObject(payload);
|
|
63
|
+
if (nested)
|
|
64
|
+
return nested;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Extracts session ID from text content.
|
|
70
|
+
* Tries JSON parsing first, then JSONL lines, then regex fallback.
|
|
71
|
+
*/
|
|
72
|
+
export function pickSessionIdFromText(content) {
|
|
73
|
+
// Try whole content as JSON
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(content);
|
|
76
|
+
const fromObject = pickSessionIdFromObject(parsed);
|
|
77
|
+
if (fromObject)
|
|
78
|
+
return fromObject;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// ignore
|
|
82
|
+
}
|
|
83
|
+
// Try JSONL lines
|
|
84
|
+
const lines = content.split(/\r?\n/);
|
|
85
|
+
for (const line of lines) {
|
|
86
|
+
const trimmed = line.trim();
|
|
87
|
+
if (!trimmed)
|
|
88
|
+
continue;
|
|
89
|
+
try {
|
|
90
|
+
const parsedLine = JSON.parse(trimmed);
|
|
91
|
+
const fromLine = pickSessionIdFromObject(parsedLine);
|
|
92
|
+
if (fromLine)
|
|
93
|
+
return fromLine;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// ignore
|
|
97
|
+
}
|
|
98
|
+
const match = trimmed.match(UUID_REGEX);
|
|
99
|
+
if (match)
|
|
100
|
+
return match[0];
|
|
101
|
+
}
|
|
102
|
+
// Fallback: find any UUID in the whole text
|
|
103
|
+
const match = content.match(UUID_REGEX);
|
|
104
|
+
return match ? match[0] : null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Finds the latest file in a directory matching a filter.
|
|
108
|
+
*/
|
|
109
|
+
export async function findLatestFile(dir, filter) {
|
|
110
|
+
try {
|
|
111
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
112
|
+
const files = entries.filter((e) => e.isFile()).map((e) => e.name);
|
|
113
|
+
const filtered = files.filter(filter);
|
|
114
|
+
if (!filtered.length)
|
|
115
|
+
return null;
|
|
116
|
+
const withStats = await Promise.all(filtered.map(async (name) => {
|
|
117
|
+
const fullPath = path.join(dir, name);
|
|
118
|
+
try {
|
|
119
|
+
const info = await stat(fullPath);
|
|
120
|
+
return { fullPath, mtime: info.mtimeMs };
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}));
|
|
126
|
+
const valid = withStats.filter((entry) => Boolean(entry));
|
|
127
|
+
if (!valid.length)
|
|
128
|
+
return null;
|
|
129
|
+
valid.sort((a, b) => b.mtime - a.mtime);
|
|
130
|
+
return valid[0]?.fullPath ?? null;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Collects files iteratively from a directory matching a filter.
|
|
138
|
+
* Uses queue-based iteration to avoid stack overflow on deep directory structures.
|
|
139
|
+
* @param dir - The root directory to search
|
|
140
|
+
* @param filter - Function to filter files by name
|
|
141
|
+
* @returns Array of matching files with their paths and modification times
|
|
142
|
+
*/
|
|
143
|
+
export async function collectFilesIterative(dir, filter) {
|
|
144
|
+
const results = [];
|
|
145
|
+
const queue = [dir];
|
|
146
|
+
while (queue.length > 0) {
|
|
147
|
+
const currentDir = queue.shift();
|
|
148
|
+
if (!currentDir)
|
|
149
|
+
break;
|
|
150
|
+
try {
|
|
151
|
+
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
152
|
+
for (const entry of entries) {
|
|
153
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
154
|
+
if (entry.isDirectory()) {
|
|
155
|
+
queue.push(fullPath);
|
|
156
|
+
}
|
|
157
|
+
else if (entry.isFile() && filter(entry.name)) {
|
|
158
|
+
try {
|
|
159
|
+
const info = await stat(fullPath);
|
|
160
|
+
results.push({ fullPath, mtime: info.mtimeMs });
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// ignore unreadable file
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// ignore unreadable directory
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return results;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Reads session ID from a file.
|
|
176
|
+
* Priority: filename UUID > file content > filename UUID fallback
|
|
177
|
+
*/
|
|
178
|
+
export async function readSessionIdFromFile(filePath) {
|
|
179
|
+
try {
|
|
180
|
+
// Priority 1: Use filename UUID (most reliable for Claude session files)
|
|
181
|
+
const basename = path.basename(filePath);
|
|
182
|
+
const filenameWithoutExt = basename.replace(/\.(json|jsonl)$/i, "");
|
|
183
|
+
if (isValidUuidSessionId(filenameWithoutExt)) {
|
|
184
|
+
return filenameWithoutExt;
|
|
185
|
+
}
|
|
186
|
+
// Priority 2: Extract from file content
|
|
187
|
+
const content = await readFile(filePath, "utf-8");
|
|
188
|
+
const fromContent = pickSessionIdFromText(content);
|
|
189
|
+
if (fromContent)
|
|
190
|
+
return fromContent;
|
|
191
|
+
// Priority 3: Fallback to any UUID in filename
|
|
192
|
+
const filenameMatch = basename.match(UUID_REGEX);
|
|
193
|
+
return filenameMatch ? filenameMatch[0] : null;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Reads session info (ID and cwd) from a file.
|
|
201
|
+
*/
|
|
202
|
+
export async function readSessionInfoFromFile(filePath) {
|
|
203
|
+
try {
|
|
204
|
+
const content = await readFile(filePath, "utf-8");
|
|
205
|
+
try {
|
|
206
|
+
const parsed = JSON.parse(content);
|
|
207
|
+
const id = pickSessionIdFromObject(parsed);
|
|
208
|
+
const cwd = pickCwdFromObject(parsed);
|
|
209
|
+
if (id || cwd)
|
|
210
|
+
return { id, cwd };
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
// ignore
|
|
214
|
+
}
|
|
215
|
+
const lines = content.split(/\r?\n/);
|
|
216
|
+
for (const line of lines) {
|
|
217
|
+
const trimmed = line.trim();
|
|
218
|
+
if (!trimmed)
|
|
219
|
+
continue;
|
|
220
|
+
try {
|
|
221
|
+
const parsedLine = JSON.parse(trimmed);
|
|
222
|
+
const id = pickSessionIdFromObject(parsedLine);
|
|
223
|
+
const cwd = pickCwdFromObject(parsedLine);
|
|
224
|
+
if (id || cwd)
|
|
225
|
+
return { id, cwd };
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// ignore
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Fallback: filename UUID
|
|
232
|
+
const filenameMatch = path.basename(filePath).match(UUID_REGEX);
|
|
233
|
+
if (filenameMatch)
|
|
234
|
+
return { id: filenameMatch[0], cwd: null };
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// ignore unreadable
|
|
238
|
+
}
|
|
239
|
+
return { id: null, cwd: null };
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Finds newest session ID from a directory with optional time filtering.
|
|
243
|
+
* Uses queue-based iteration to avoid stack overflow on deep directory structures.
|
|
244
|
+
* @param dir - The root directory to search
|
|
245
|
+
* @param recursive - Whether to search subdirectories
|
|
246
|
+
* @param options - Search options (since, until, preferClosestTo, windowMs)
|
|
247
|
+
* @returns Session info with ID and modification time, or null if not found
|
|
248
|
+
*/
|
|
249
|
+
export async function findNewestSessionIdFromDir(dir, recursive, options = {}) {
|
|
250
|
+
try {
|
|
251
|
+
const files = [];
|
|
252
|
+
const queue = [dir];
|
|
253
|
+
// Queue-based directory traversal
|
|
254
|
+
while (queue.length > 0) {
|
|
255
|
+
const currentDir = queue.shift();
|
|
256
|
+
if (!currentDir)
|
|
257
|
+
break;
|
|
258
|
+
try {
|
|
259
|
+
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
260
|
+
for (const entry of entries) {
|
|
261
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
262
|
+
if (entry.isDirectory()) {
|
|
263
|
+
if (recursive) {
|
|
264
|
+
queue.push(fullPath);
|
|
265
|
+
}
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
if (!entry.isFile())
|
|
269
|
+
continue;
|
|
270
|
+
if (!entry.name.endsWith(".json") && !entry.name.endsWith(".jsonl"))
|
|
271
|
+
continue;
|
|
272
|
+
try {
|
|
273
|
+
const info = await stat(fullPath);
|
|
274
|
+
files.push({ fullPath, mtime: info.mtimeMs });
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// ignore unreadable file
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
// ignore unreadable directory
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Apply since/until filters
|
|
286
|
+
const filtered = files.filter((f) => {
|
|
287
|
+
if (options.since !== undefined && f.mtime < options.since)
|
|
288
|
+
return false;
|
|
289
|
+
if (options.until !== undefined && f.mtime > options.until)
|
|
290
|
+
return false;
|
|
291
|
+
return true;
|
|
292
|
+
});
|
|
293
|
+
if (!filtered.length)
|
|
294
|
+
return null;
|
|
295
|
+
// Sort by mtime descending (newest first)
|
|
296
|
+
let pool = filtered.sort((a, b) => b.mtime - a.mtime);
|
|
297
|
+
// Apply preferClosestTo window if specified
|
|
298
|
+
const ref = options.preferClosestTo;
|
|
299
|
+
if (typeof ref === "number") {
|
|
300
|
+
const window = options.windowMs ?? 30 * 60 * 1000;
|
|
301
|
+
const withinWindow = pool.filter((f) => Math.abs(f.mtime - ref) <= window);
|
|
302
|
+
if (withinWindow.length) {
|
|
303
|
+
pool = withinWindow.sort((a, b) => b.mtime - a.mtime);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
for (const file of pool) {
|
|
307
|
+
const id = await readSessionIdFromFile(file.fullPath);
|
|
308
|
+
if (id)
|
|
309
|
+
return { id, mtime: file.mtime };
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
// ignore
|
|
314
|
+
}
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Finds the latest nested session file from subdirectories.
|
|
319
|
+
*/
|
|
320
|
+
export async function findLatestNestedSessionFile(baseDir, subPath, predicate) {
|
|
321
|
+
try {
|
|
322
|
+
const entries = await readdir(baseDir);
|
|
323
|
+
if (!entries.length)
|
|
324
|
+
return null;
|
|
325
|
+
const candidates = [];
|
|
326
|
+
for (const entry of entries) {
|
|
327
|
+
const dirPath = path.join(baseDir, entry, ...subPath);
|
|
328
|
+
const latest = await findLatestFile(dirPath, predicate);
|
|
329
|
+
if (latest) {
|
|
330
|
+
try {
|
|
331
|
+
const info = await stat(latest);
|
|
332
|
+
candidates.push({ fullPath: latest, mtime: info.mtimeMs });
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// ignore
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (!candidates.length)
|
|
340
|
+
return null;
|
|
341
|
+
candidates.sort((a, b) => b.mtime - a.mtime);
|
|
342
|
+
return candidates[0]?.fullPath ?? null;
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Reads text content from a file.
|
|
350
|
+
* Wrapper for fs.readFile to centralize fs operations for testability.
|
|
351
|
+
*/
|
|
352
|
+
export async function readFileContent(filePath) {
|
|
353
|
+
return readFile(filePath, "utf-8");
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Checks if a file exists and returns stat info.
|
|
357
|
+
* Returns null if file does not exist.
|
|
358
|
+
*/
|
|
359
|
+
export async function checkFileStat(filePath) {
|
|
360
|
+
try {
|
|
361
|
+
const info = await stat(filePath);
|
|
362
|
+
return { mtimeMs: info.mtimeMs };
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Normalizes a path for cross-platform comparison.
|
|
370
|
+
* Converts backslashes to forward slashes and resolves the path.
|
|
371
|
+
* @param p - The path to normalize
|
|
372
|
+
* @returns The normalized path string
|
|
373
|
+
*/
|
|
374
|
+
function normalizePath(p) {
|
|
375
|
+
// Normalize separators to forward slashes for consistent comparison
|
|
376
|
+
return path.normalize(p).replace(/\\/g, "/");
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Checks if one path is a proper prefix of another (with path separator boundary).
|
|
380
|
+
* Ensures that the prefix ends at a directory boundary to avoid false matches
|
|
381
|
+
* like "/home/user/proj" matching "/home/user/project".
|
|
382
|
+
* @param prefix - The potential prefix path
|
|
383
|
+
* @param full - The full path to check against
|
|
384
|
+
* @returns true if prefix is a valid path prefix of full
|
|
385
|
+
*/
|
|
386
|
+
function isPathPrefix(prefix, full) {
|
|
387
|
+
if (!full.startsWith(prefix))
|
|
388
|
+
return false;
|
|
389
|
+
if (full.length === prefix.length)
|
|
390
|
+
return true;
|
|
391
|
+
// Ensure the next character is a path separator
|
|
392
|
+
return full[prefix.length] === "/";
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Checks if a session's cwd matches the target cwd.
|
|
396
|
+
* Matching rules:
|
|
397
|
+
* - Exact match
|
|
398
|
+
* - Session cwd starts with target cwd (session is in subdirectory)
|
|
399
|
+
* - Target cwd starts with session cwd (for worktree subdirectories)
|
|
400
|
+
*
|
|
401
|
+
* Paths are normalized before comparison to handle cross-platform differences.
|
|
402
|
+
* Path prefix matching ensures boundaries at directory separators.
|
|
403
|
+
*
|
|
404
|
+
* @param sessionCwd - The cwd from the session file
|
|
405
|
+
* @param targetCwd - The target cwd to match against
|
|
406
|
+
* @returns true if the cwd matches
|
|
407
|
+
*/
|
|
408
|
+
export function matchesCwd(sessionCwd, targetCwd) {
|
|
409
|
+
if (!sessionCwd)
|
|
410
|
+
return false;
|
|
411
|
+
const normalizedSession = normalizePath(sessionCwd);
|
|
412
|
+
const normalizedTarget = normalizePath(targetCwd);
|
|
413
|
+
return (normalizedSession === normalizedTarget ||
|
|
414
|
+
isPathPrefix(normalizedTarget, normalizedSession) ||
|
|
415
|
+
isPathPrefix(normalizedSession, normalizedTarget));
|
|
416
|
+
}
|
|
417
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/utils/session/common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session module - unified session management for AI tools
|
|
3
|
+
*
|
|
4
|
+
* This module provides session detection and management for various AI CLI tools:
|
|
5
|
+
* - Claude Code
|
|
6
|
+
* - Codex CLI
|
|
7
|
+
* - Gemini CLI
|
|
8
|
+
* - Qwen CLI
|
|
9
|
+
*/
|
|
10
|
+
export type { SessionSearchOptions, SessionInfo, ClaudeSessionInfo, CodexSessionInfo, GeminiSessionInfo, } from "./types.js";
|
|
11
|
+
export { isValidUuidSessionId } from "./common.js";
|
|
12
|
+
export { encodeClaudeProjectPath, findLatestClaudeSession, findLatestClaudeSessionId, waitForClaudeSessionId, claudeSessionFileExists, } from "./parsers/claude.js";
|
|
13
|
+
export { findLatestCodexSession, findLatestCodexSessionId, waitForCodexSessionId, } from "./parsers/codex.js";
|
|
14
|
+
export { findLatestGeminiSession, findLatestGeminiSessionId, } from "./parsers/gemini.js";
|
|
15
|
+
export { findLatestQwenSessionId } from "./parsers/qwen.js";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session module - unified session management for AI tools
|
|
3
|
+
*
|
|
4
|
+
* This module provides session detection and management for various AI CLI tools:
|
|
5
|
+
* - Claude Code
|
|
6
|
+
* - Codex CLI
|
|
7
|
+
* - Gemini CLI
|
|
8
|
+
* - Qwen CLI
|
|
9
|
+
*/
|
|
10
|
+
// Common utilities
|
|
11
|
+
export { isValidUuidSessionId } from "./common.js";
|
|
12
|
+
// Claude Code parser
|
|
13
|
+
export { encodeClaudeProjectPath, findLatestClaudeSession, findLatestClaudeSessionId, waitForClaudeSessionId, claudeSessionFileExists, } from "./parsers/claude.js";
|
|
14
|
+
// Codex CLI parser
|
|
15
|
+
export { findLatestCodexSession, findLatestCodexSessionId, waitForCodexSessionId, } from "./parsers/codex.js";
|
|
16
|
+
// Gemini CLI parser
|
|
17
|
+
export { findLatestGeminiSession, findLatestGeminiSessionId, } from "./parsers/gemini.js";
|
|
18
|
+
// Qwen CLI parser
|
|
19
|
+
export { findLatestQwenSessionId } from "./parsers/qwen.js";
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/session/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,mBAAmB;AACnB,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,qBAAqB;AACrB,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,mBAAmB;AACnB,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,oBAAoB;AACpB,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,kBAAkB;AAClB,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code session parser
|
|
3
|
+
*
|
|
4
|
+
* Handles session detection and management for Claude Code CLI.
|
|
5
|
+
* Session files are stored in ~/.claude/projects/<encoded-path>/sessions/
|
|
6
|
+
*/
|
|
7
|
+
import type { ClaudeSessionInfo, SessionSearchOptions } from "../types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Encodes a project path for Claude's directory structure.
|
|
10
|
+
* Normalizes separators and replaces special characters with dashes.
|
|
11
|
+
* @param cwd - The working directory path to encode
|
|
12
|
+
* @returns The encoded path string suitable for Claude's directory naming
|
|
13
|
+
*/
|
|
14
|
+
export declare function encodeClaudeProjectPath(cwd: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Finds the latest Claude session for a given working directory.
|
|
17
|
+
*
|
|
18
|
+
* Search order:
|
|
19
|
+
* 1. ~/.claude/projects/<encoded>/sessions/ (official location)
|
|
20
|
+
* 2. ~/.claude/projects/<encoded>/ (root and subdirs)
|
|
21
|
+
* 3. ~/.claude/history.jsonl (global history fallback)
|
|
22
|
+
*
|
|
23
|
+
* @param cwd - The working directory to find sessions for
|
|
24
|
+
* @param options - Search options (since, until, preferClosestTo, windowMs)
|
|
25
|
+
* @returns Session info with ID and modification time, or null if not found
|
|
26
|
+
*/
|
|
27
|
+
export declare function findLatestClaudeSession(cwd: string, options?: Omit<SessionSearchOptions, "cwd">): Promise<ClaudeSessionInfo | null>;
|
|
28
|
+
/**
|
|
29
|
+
* Finds the latest Claude session ID for a given working directory.
|
|
30
|
+
* @param cwd - The working directory to find sessions for
|
|
31
|
+
* @param options - Search options (since, until, preferClosestTo, windowMs)
|
|
32
|
+
* @returns Session ID string or null if not found
|
|
33
|
+
*/
|
|
34
|
+
export declare function findLatestClaudeSessionId(cwd: string, options?: Omit<SessionSearchOptions, "cwd">): Promise<string | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Polls for a Claude session ID until found or timeout.
|
|
37
|
+
* @param cwd - The working directory to find sessions for
|
|
38
|
+
* @param options - Polling options including timeout, interval, and search filters
|
|
39
|
+
* @returns Session ID string or null if timeout reached
|
|
40
|
+
*/
|
|
41
|
+
export declare function waitForClaudeSessionId(cwd: string, options?: {
|
|
42
|
+
timeoutMs?: number;
|
|
43
|
+
pollIntervalMs?: number;
|
|
44
|
+
since?: number;
|
|
45
|
+
until?: number;
|
|
46
|
+
preferClosestTo?: number;
|
|
47
|
+
windowMs?: number;
|
|
48
|
+
}): Promise<string | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if a Claude session file exists for the given session ID and worktree path.
|
|
51
|
+
* @param sessionId - The session ID to check
|
|
52
|
+
* @param worktreePath - The worktree path (used to determine project encoding)
|
|
53
|
+
* @returns true if a session file exists for this ID
|
|
54
|
+
*/
|
|
55
|
+
export declare function claudeSessionFileExists(sessionId: string, worktreePath: string): Promise<boolean>;
|
|
56
|
+
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../../src/utils/session/parsers/claude.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAS3E;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI3D;AAuCD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAM,GAC9C,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAuDnC;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAM,GAC9C,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,GACL,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmBxB;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CAgClB"}
|