@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.
Files changed (65) hide show
  1. package/README.ja.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/cli/ui/components/App.d.ts.map +1 -1
  4. package/dist/cli/ui/components/App.js +8 -8
  5. package/dist/cli/ui/components/App.js.map +1 -1
  6. package/dist/cli/ui/components/screens/BranchListScreen.d.ts.map +1 -1
  7. package/dist/cli/ui/components/screens/BranchListScreen.js +9 -5
  8. package/dist/cli/ui/components/screens/BranchListScreen.js.map +1 -1
  9. package/dist/cli/ui/utils/branchFormatter.d.ts.map +1 -1
  10. package/dist/cli/ui/utils/branchFormatter.js +2 -2
  11. package/dist/cli/ui/utils/branchFormatter.js.map +1 -1
  12. package/dist/index.js +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/utils/session/common.d.ts +100 -0
  15. package/dist/utils/session/common.d.ts.map +1 -0
  16. package/dist/utils/session/common.js +417 -0
  17. package/dist/utils/session/common.js.map +1 -0
  18. package/dist/utils/session/index.d.ts +16 -0
  19. package/dist/utils/session/index.d.ts.map +1 -0
  20. package/dist/utils/session/index.js +20 -0
  21. package/dist/utils/session/index.js.map +1 -0
  22. package/dist/utils/session/parsers/claude.d.ts +56 -0
  23. package/dist/utils/session/parsers/claude.d.ts.map +1 -0
  24. package/dist/utils/session/parsers/claude.js +178 -0
  25. package/dist/utils/session/parsers/claude.js.map +1 -0
  26. package/dist/utils/session/parsers/codex.d.ts +37 -0
  27. package/dist/utils/session/parsers/codex.d.ts.map +1 -0
  28. package/dist/utils/session/parsers/codex.js +113 -0
  29. package/dist/utils/session/parsers/codex.js.map +1 -0
  30. package/dist/utils/session/parsers/gemini.d.ts +22 -0
  31. package/dist/utils/session/parsers/gemini.d.ts.map +1 -0
  32. package/dist/utils/session/parsers/gemini.js +81 -0
  33. package/dist/utils/session/parsers/gemini.js.map +1 -0
  34. package/dist/utils/session/parsers/index.d.ts +8 -0
  35. package/dist/utils/session/parsers/index.d.ts.map +1 -0
  36. package/dist/utils/session/parsers/index.js +12 -0
  37. package/dist/utils/session/parsers/index.js.map +1 -0
  38. package/dist/utils/session/parsers/qwen.d.ts +21 -0
  39. package/dist/utils/session/parsers/qwen.d.ts.map +1 -0
  40. package/dist/utils/session/parsers/qwen.js +36 -0
  41. package/dist/utils/session/parsers/qwen.js.map +1 -0
  42. package/dist/utils/session/types.d.ts +38 -0
  43. package/dist/utils/session/types.d.ts.map +1 -0
  44. package/dist/utils/session/types.js +5 -0
  45. package/dist/utils/session/types.js.map +1 -0
  46. package/dist/utils/session.d.ts +14 -79
  47. package/dist/utils/session.d.ts.map +1 -1
  48. package/dist/utils/session.js +14 -585
  49. package/dist/utils/session.js.map +1 -1
  50. package/package.json +1 -1
  51. package/src/cli/ui/__tests__/components/screens/BranchListScreen.test.tsx +40 -1
  52. package/src/cli/ui/__tests__/utils/branchFormatter.test.ts +1 -1
  53. package/src/cli/ui/components/App.tsx +10 -8
  54. package/src/cli/ui/components/screens/BranchListScreen.tsx +8 -6
  55. package/src/cli/ui/utils/branchFormatter.ts +2 -3
  56. package/src/index.ts +1 -1
  57. package/src/utils/session/common.ts +446 -0
  58. package/src/utils/session/index.ts +46 -0
  59. package/src/utils/session/parsers/claude.ts +233 -0
  60. package/src/utils/session/parsers/codex.ts +135 -0
  61. package/src/utils/session/parsers/gemini.ts +94 -0
  62. package/src/utils/session/parsers/index.ts +28 -0
  63. package/src/utils/session/parsers/qwen.ts +54 -0
  64. package/src/utils/session/types.ts +42 -0
  65. package/src/utils/session.ts +14 -755
@@ -0,0 +1,178 @@
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 path from "node:path";
8
+ import { homedir } from "node:os";
9
+ import { isValidUuidSessionId, findNewestSessionIdFromDir, matchesCwd, readFileContent, checkFileStat, } from "../common.js";
10
+ /**
11
+ * Encodes a project path for Claude's directory structure.
12
+ * Normalizes separators and replaces special characters with dashes.
13
+ * @param cwd - The working directory path to encode
14
+ * @returns The encoded path string suitable for Claude's directory naming
15
+ */
16
+ export function encodeClaudeProjectPath(cwd) {
17
+ // Normalize to forward slashes, drop drive colon, replace / and _ with -
18
+ const normalized = cwd.replace(/\\/g, "/").replace(/:/g, "");
19
+ return normalized.replace(/_/g, "-").replace(/\//g, "-");
20
+ }
21
+ /**
22
+ * Generates candidate paths for Claude project directory.
23
+ * Handles various encoding patterns used by different Claude versions.
24
+ * @param cwd - The working directory path to encode
25
+ * @returns Array of possible encoded directory names
26
+ */
27
+ function generateClaudeProjectPathCandidates(cwd) {
28
+ const base = encodeClaudeProjectPath(cwd);
29
+ const dotToDash = cwd
30
+ .replace(/\\/g, "/")
31
+ .replace(/:/g, "")
32
+ .replace(/\./g, "-")
33
+ .replace(/_/g, "-")
34
+ .replace(/\//g, "-");
35
+ const collapsed = dotToDash.replace(/-+/g, "-");
36
+ const candidates = [base, dotToDash, collapsed];
37
+ return Array.from(new Set(candidates));
38
+ }
39
+ /**
40
+ * Returns the list of possible Claude root directories.
41
+ * Checks CLAUDE_CONFIG_DIR environment variable first, then falls back to
42
+ * standard locations (~/.claude and ~/.config/claude).
43
+ * @returns Array of possible Claude root directory paths
44
+ */
45
+ function getClaudeRootCandidates() {
46
+ const roots = [];
47
+ if (process.env.CLAUDE_CONFIG_DIR) {
48
+ roots.push(process.env.CLAUDE_CONFIG_DIR);
49
+ }
50
+ roots.push(path.join(homedir(), ".claude"), path.join(homedir(), ".config", "claude"));
51
+ return roots;
52
+ }
53
+ /**
54
+ * Finds the latest Claude session for a given working directory.
55
+ *
56
+ * Search order:
57
+ * 1. ~/.claude/projects/<encoded>/sessions/ (official location)
58
+ * 2. ~/.claude/projects/<encoded>/ (root and subdirs)
59
+ * 3. ~/.claude/history.jsonl (global history fallback)
60
+ *
61
+ * @param cwd - The working directory to find sessions for
62
+ * @param options - Search options (since, until, preferClosestTo, windowMs)
63
+ * @returns Session info with ID and modification time, or null if not found
64
+ */
65
+ export async function findLatestClaudeSession(cwd, options = {}) {
66
+ const rootCandidates = getClaudeRootCandidates();
67
+ const encodedPaths = generateClaudeProjectPathCandidates(cwd);
68
+ for (const claudeRoot of rootCandidates) {
69
+ for (const encoded of encodedPaths) {
70
+ const projectDir = path.join(claudeRoot, "projects", encoded);
71
+ const sessionsDir = path.join(projectDir, "sessions");
72
+ // 1) Look under sessions/ (official location)
73
+ const session = await findNewestSessionIdFromDir(sessionsDir, false, options);
74
+ if (session)
75
+ return session;
76
+ // 2) Look directly under project dir and subdirs
77
+ const rootSession = await findNewestSessionIdFromDir(projectDir, true, options);
78
+ if (rootSession)
79
+ return rootSession;
80
+ }
81
+ }
82
+ // Fallback: parse ~/.claude/history.jsonl
83
+ try {
84
+ const historyPath = path.join(homedir(), ".claude", "history.jsonl");
85
+ const historyStat = await checkFileStat(historyPath);
86
+ if (!historyStat)
87
+ return null;
88
+ const content = await readFileContent(historyPath);
89
+ const lines = content.split(/\r?\n/).filter(Boolean);
90
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
91
+ try {
92
+ const line = lines[i] ?? "";
93
+ const parsed = JSON.parse(line);
94
+ const project = typeof parsed.project === "string" ? parsed.project : null;
95
+ const sessionId = typeof parsed.sessionId === "string" ? parsed.sessionId : null;
96
+ if (project && sessionId && matchesCwd(project, cwd)) {
97
+ return { id: sessionId, mtime: historyStat.mtimeMs };
98
+ }
99
+ }
100
+ catch {
101
+ // ignore malformed lines
102
+ }
103
+ }
104
+ }
105
+ catch {
106
+ // ignore if history not present
107
+ }
108
+ return null;
109
+ }
110
+ /**
111
+ * Finds the latest Claude session ID for a given working directory.
112
+ * @param cwd - The working directory to find sessions for
113
+ * @param options - Search options (since, until, preferClosestTo, windowMs)
114
+ * @returns Session ID string or null if not found
115
+ */
116
+ export async function findLatestClaudeSessionId(cwd, options = {}) {
117
+ const found = await findLatestClaudeSession(cwd, options);
118
+ return found?.id ?? null;
119
+ }
120
+ /**
121
+ * Polls for a Claude session ID until found or timeout.
122
+ * @param cwd - The working directory to find sessions for
123
+ * @param options - Polling options including timeout, interval, and search filters
124
+ * @returns Session ID string or null if timeout reached
125
+ */
126
+ export async function waitForClaudeSessionId(cwd, options = {}) {
127
+ const timeoutMs = options.timeoutMs ?? 120_000;
128
+ const pollIntervalMs = options.pollIntervalMs ?? 2_000;
129
+ const deadline = Date.now() + timeoutMs;
130
+ // Build search options once outside the loop
131
+ const searchOptions = {};
132
+ if (options.since !== undefined)
133
+ searchOptions.since = options.since;
134
+ if (options.until !== undefined)
135
+ searchOptions.until = options.until;
136
+ if (options.preferClosestTo !== undefined)
137
+ searchOptions.preferClosestTo = options.preferClosestTo;
138
+ if (options.windowMs !== undefined)
139
+ searchOptions.windowMs = options.windowMs;
140
+ while (Date.now() < deadline) {
141
+ const found = await findLatestClaudeSession(cwd, searchOptions);
142
+ if (found?.id)
143
+ return found.id;
144
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
145
+ }
146
+ return null;
147
+ }
148
+ /**
149
+ * Checks if a Claude session file exists for the given session ID and worktree path.
150
+ * @param sessionId - The session ID to check
151
+ * @param worktreePath - The worktree path (used to determine project encoding)
152
+ * @returns true if a session file exists for this ID
153
+ */
154
+ export async function claudeSessionFileExists(sessionId, worktreePath) {
155
+ if (!isValidUuidSessionId(sessionId)) {
156
+ return false;
157
+ }
158
+ const encodedPaths = generateClaudeProjectPathCandidates(worktreePath);
159
+ const roots = getClaudeRootCandidates();
160
+ for (const root of roots) {
161
+ for (const enc of encodedPaths) {
162
+ // Check official sessions/ location first
163
+ const sessionsCandidate = path.join(root, "projects", enc, "sessions", `${sessionId}.jsonl`);
164
+ const sessionsInfo = await checkFileStat(sessionsCandidate);
165
+ if (sessionsInfo) {
166
+ return true;
167
+ }
168
+ // Then check project root
169
+ const candidate = path.join(root, "projects", enc, `${sessionId}.jsonl`);
170
+ const info = await checkFileStat(candidate);
171
+ if (info) {
172
+ return true;
173
+ }
174
+ }
175
+ }
176
+ return false;
177
+ }
178
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../../src/utils/session/parsers/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Codex CLI session parser
3
+ *
4
+ * Handles session detection and management for Codex CLI.
5
+ * Session files are stored in ~/.codex/sessions/ (or CODEX_HOME/sessions/).
6
+ * Filename pattern: rollout-YYYY-MM-DDTHH-MM-SS-{uuid}.jsonl
7
+ */
8
+ import type { CodexSessionInfo, SessionSearchOptions } from "../types.js";
9
+ /**
10
+ * Finds the latest Codex session with optional time filtering and cwd matching.
11
+ *
12
+ * Session ID is extracted from:
13
+ * 1. Filename (rollout-...-{uuid}.jsonl) - most reliable
14
+ * 2. File content (payload.id or sessionId fields)
15
+ *
16
+ * @param options - Search options including time filters and cwd matching
17
+ * @returns Session info with ID and modification time, or null if not found
18
+ */
19
+ export declare function findLatestCodexSession(options?: SessionSearchOptions): Promise<CodexSessionInfo | null>;
20
+ /**
21
+ * Finds the latest Codex session ID.
22
+ * @param options - Search options including time filters and cwd matching
23
+ * @returns Session ID string or null if not found
24
+ */
25
+ export declare function findLatestCodexSessionId(options?: SessionSearchOptions): Promise<string | null>;
26
+ /**
27
+ * Polls for a Codex session ID until found or timeout.
28
+ * @param options - Polling options including startedAt time, timeout, and cwd filter
29
+ * @returns Session ID string or null if timeout reached
30
+ */
31
+ export declare function waitForCodexSessionId(options: {
32
+ startedAt: number;
33
+ timeoutMs?: number;
34
+ pollIntervalMs?: number;
35
+ cwd?: string | null;
36
+ }): Promise<string | null>;
37
+ //# sourceMappingURL=codex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../../src/utils/session/parsers/codex.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAQ1E;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA+DlC;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBzB"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Codex CLI session parser
3
+ *
4
+ * Handles session detection and management for Codex CLI.
5
+ * Session files are stored in ~/.codex/sessions/ (or CODEX_HOME/sessions/).
6
+ * Filename pattern: rollout-YYYY-MM-DDTHH-MM-SS-{uuid}.jsonl
7
+ */
8
+ import path from "node:path";
9
+ import { homedir } from "node:os";
10
+ import { UUID_REGEX, collectFilesIterative, matchesCwd, readSessionInfoFromFile, } from "../common.js";
11
+ /**
12
+ * Finds the latest Codex session with optional time filtering and cwd matching.
13
+ *
14
+ * Session ID is extracted from:
15
+ * 1. Filename (rollout-...-{uuid}.jsonl) - most reliable
16
+ * 2. File content (payload.id or sessionId fields)
17
+ *
18
+ * @param options - Search options including time filters and cwd matching
19
+ * @returns Session info with ID and modification time, or null if not found
20
+ */
21
+ export async function findLatestCodexSession(options = {}) {
22
+ // Codex CLI respects CODEX_HOME. Default is ~/.codex.
23
+ const codexHome = process.env.CODEX_HOME ?? path.join(homedir(), ".codex");
24
+ const baseDir = path.join(codexHome, "sessions");
25
+ const candidates = await collectFilesIterative(baseDir, (name) => name.endsWith(".json") || name.endsWith(".jsonl"));
26
+ if (!candidates.length)
27
+ return null;
28
+ // Apply time filters
29
+ let pool = candidates;
30
+ const sinceVal = options.since;
31
+ const untilVal = options.until;
32
+ if (sinceVal !== undefined) {
33
+ pool = pool.filter((c) => c.mtime >= sinceVal);
34
+ }
35
+ if (untilVal !== undefined) {
36
+ pool = pool.filter((c) => c.mtime <= untilVal);
37
+ }
38
+ if (!pool.length)
39
+ return null;
40
+ const ref = options.preferClosestTo;
41
+ const window = options.windowMs ?? 30 * 60 * 1000; // 30 minutes default
42
+ const ordered = [...pool].sort((a, b) => {
43
+ if (typeof ref === "number") {
44
+ const da = Math.abs(a.mtime - ref);
45
+ const db = Math.abs(b.mtime - ref);
46
+ if (da === db)
47
+ return b.mtime - a.mtime;
48
+ if (da <= window || db <= window)
49
+ return da - db;
50
+ }
51
+ return b.mtime - a.mtime;
52
+ });
53
+ for (const file of ordered) {
54
+ // Priority 1: Extract session ID from filename (most reliable for Codex)
55
+ const filenameMatch = path.basename(file.fullPath).match(UUID_REGEX);
56
+ if (filenameMatch) {
57
+ const sessionId = filenameMatch[0];
58
+ // If cwd filtering is needed, read file content to check cwd
59
+ if (options.cwd) {
60
+ const info = await readSessionInfoFromFile(file.fullPath);
61
+ if (matchesCwd(info.cwd, options.cwd)) {
62
+ return { id: sessionId, mtime: file.mtime };
63
+ }
64
+ continue; // cwd doesn't match, try next file
65
+ }
66
+ return { id: sessionId, mtime: file.mtime };
67
+ }
68
+ // Priority 2: Fallback to reading file content if filename lacks UUID
69
+ const info = await readSessionInfoFromFile(file.fullPath);
70
+ if (!info.id)
71
+ continue;
72
+ if (options.cwd) {
73
+ if (matchesCwd(info.cwd, options.cwd)) {
74
+ return { id: info.id, mtime: file.mtime };
75
+ }
76
+ continue;
77
+ }
78
+ return { id: info.id, mtime: file.mtime };
79
+ }
80
+ return null;
81
+ }
82
+ /**
83
+ * Finds the latest Codex session ID.
84
+ * @param options - Search options including time filters and cwd matching
85
+ * @returns Session ID string or null if not found
86
+ */
87
+ export async function findLatestCodexSessionId(options = {}) {
88
+ const found = await findLatestCodexSession(options);
89
+ return found?.id ?? null;
90
+ }
91
+ /**
92
+ * Polls for a Codex session ID until found or timeout.
93
+ * @param options - Polling options including startedAt time, timeout, and cwd filter
94
+ * @returns Session ID string or null if timeout reached
95
+ */
96
+ export async function waitForCodexSessionId(options) {
97
+ const timeoutMs = options.timeoutMs ?? 120_000;
98
+ const pollIntervalMs = options.pollIntervalMs ?? 2_000;
99
+ const deadline = Date.now() + timeoutMs;
100
+ while (Date.now() < deadline) {
101
+ const found = await findLatestCodexSession({
102
+ since: options.startedAt,
103
+ preferClosestTo: options.startedAt,
104
+ windowMs: 10 * 60 * 1000,
105
+ cwd: options.cwd ?? null,
106
+ });
107
+ if (found?.id)
108
+ return found.id;
109
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
110
+ }
111
+ return null;
112
+ }
113
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../../src/utils/session/parsers/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Gemini CLI session parser
3
+ *
4
+ * Handles session detection for Gemini CLI.
5
+ * Session files are stored in ~/.gemini/tmp/<project_hash>/
6
+ */
7
+ import type { GeminiSessionInfo, SessionSearchOptions } from "../types.js";
8
+ /**
9
+ * Finds the latest Gemini session with optional time filtering and cwd matching.
10
+ *
11
+ * @param options - Search options including time filters and cwd matching
12
+ * @returns Session info with ID and modification time, or null if not found
13
+ */
14
+ export declare function findLatestGeminiSession(options?: SessionSearchOptions): Promise<GeminiSessionInfo | null>;
15
+ /**
16
+ * Finds the latest Gemini session ID.
17
+ * @param cwd - The working directory to find sessions for (used as fallback if options.cwd not set)
18
+ * @param options - Search options including time filters and cwd matching
19
+ * @returns Session ID string or null if not found
20
+ */
21
+ export declare function findLatestGeminiSessionId(cwd: string, options?: SessionSearchOptions): Promise<string | null>;
22
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../../src/utils/session/parsers/gemini.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAO3E;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CA+CnC;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAUxB"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Gemini CLI session parser
3
+ *
4
+ * Handles session detection for Gemini CLI.
5
+ * Session files are stored in ~/.gemini/tmp/<project_hash>/
6
+ */
7
+ import path from "node:path";
8
+ import { homedir } from "node:os";
9
+ import { collectFilesIterative, matchesCwd, readSessionInfoFromFile, } from "../common.js";
10
+ /**
11
+ * Finds the latest Gemini session with optional time filtering and cwd matching.
12
+ *
13
+ * @param options - Search options including time filters and cwd matching
14
+ * @returns Session info with ID and modification time, or null if not found
15
+ */
16
+ export async function findLatestGeminiSession(options = {}) {
17
+ // Gemini stores sessions/logs under ~/.gemini/tmp/<project_hash>/
18
+ const baseDir = path.join(homedir(), ".gemini", "tmp");
19
+ const files = await collectFilesIterative(baseDir, (name) => name.endsWith(".json") || name.endsWith(".jsonl"));
20
+ if (!files.length)
21
+ return null;
22
+ // Apply time filters
23
+ let pool = files;
24
+ const sinceVal = options.since;
25
+ if (sinceVal !== undefined) {
26
+ pool = pool.filter((f) => f.mtime >= sinceVal);
27
+ }
28
+ const untilVal = options.until;
29
+ if (untilVal !== undefined) {
30
+ pool = pool.filter((f) => f.mtime <= untilVal);
31
+ }
32
+ if (!pool.length)
33
+ return null;
34
+ // Sort by preference or mtime
35
+ const ref = options.preferClosestTo;
36
+ const window = options.windowMs ?? 30 * 60 * 1000;
37
+ pool = pool.slice().sort((a, b) => {
38
+ if (typeof ref === "number") {
39
+ const da = Math.abs(a.mtime - ref);
40
+ const db = Math.abs(b.mtime - ref);
41
+ if (da === db)
42
+ return b.mtime - a.mtime;
43
+ if (da <= window || db <= window)
44
+ return da - db;
45
+ }
46
+ return b.mtime - a.mtime;
47
+ });
48
+ for (const file of pool) {
49
+ const info = await readSessionInfoFromFile(file.fullPath);
50
+ if (!info.id)
51
+ continue;
52
+ if (options.cwd) {
53
+ if (matchesCwd(info.cwd, options.cwd)) {
54
+ return { id: info.id, mtime: file.mtime };
55
+ }
56
+ continue;
57
+ }
58
+ return { id: info.id, mtime: file.mtime };
59
+ }
60
+ return null;
61
+ }
62
+ /**
63
+ * Finds the latest Gemini session ID.
64
+ * @param cwd - The working directory to find sessions for (used as fallback if options.cwd not set)
65
+ * @param options - Search options including time filters and cwd matching
66
+ * @returns Session ID string or null if not found
67
+ */
68
+ export async function findLatestGeminiSessionId(cwd, options = {}) {
69
+ const searchOptions = { cwd: options.cwd ?? cwd };
70
+ if (options.since !== undefined)
71
+ searchOptions.since = options.since;
72
+ if (options.until !== undefined)
73
+ searchOptions.until = options.until;
74
+ if (options.preferClosestTo !== undefined)
75
+ searchOptions.preferClosestTo = options.preferClosestTo;
76
+ if (options.windowMs !== undefined)
77
+ searchOptions.windowMs = options.windowMs;
78
+ const found = await findLatestGeminiSession(searchOptions);
79
+ return found?.id ?? null;
80
+ }
81
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../../src/utils/session/parsers/gemini.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Session parsers - re-exports all tool-specific parsers
3
+ */
4
+ export { encodeClaudeProjectPath, findLatestClaudeSession, findLatestClaudeSessionId, waitForClaudeSessionId, claudeSessionFileExists, } from "./claude.js";
5
+ export { findLatestCodexSession, findLatestCodexSessionId, waitForCodexSessionId, } from "./codex.js";
6
+ export { findLatestGeminiSession, findLatestGeminiSessionId, } from "./gemini.js";
7
+ export { findLatestQwenSessionId } from "./qwen.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/session/parsers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Session parsers - re-exports all tool-specific parsers
3
+ */
4
+ // Claude Code
5
+ export { encodeClaudeProjectPath, findLatestClaudeSession, findLatestClaudeSessionId, waitForClaudeSessionId, claudeSessionFileExists, } from "./claude.js";
6
+ // Codex CLI
7
+ export { findLatestCodexSession, findLatestCodexSessionId, waitForCodexSessionId, } from "./codex.js";
8
+ // Gemini CLI
9
+ export { findLatestGeminiSession, findLatestGeminiSessionId, } from "./gemini.js";
10
+ // Qwen CLI
11
+ export { findLatestQwenSessionId } from "./qwen.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/utils/session/parsers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc;AACd,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB,YAAY;AACZ,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAEpB,aAAa;AACb,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AAErB,WAAW;AACX,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Qwen CLI session parser
3
+ *
4
+ * Handles session detection for Qwen CLI.
5
+ * Session files are stored in ~/.qwen/tmp/<project_hash>/
6
+ * and checkpoints in ~/.qwen/tmp/<project_hash>/checkpoints/
7
+ */
8
+ /**
9
+ * Finds the latest Qwen session ID.
10
+ *
11
+ * Search order:
12
+ * 1. ~/.qwen/tmp/<hash>/*.json or *.jsonl
13
+ * 2. ~/.qwen/tmp/<hash>/checkpoints/*.json or *.ckpt
14
+ *
15
+ * Falls back to filename (without extension) if no session ID is found in content.
16
+ *
17
+ * @param _cwd - Working directory (currently unused, reserved for future per-project filtering)
18
+ * @returns Session ID string or null if not found
19
+ */
20
+ export declare function findLatestQwenSessionId(_cwd: string): Promise<string | null>;
21
+ //# sourceMappingURL=qwen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qwen.d.ts","sourceRoot":"","sources":["../../../../src/utils/session/parsers/qwen.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuBxB"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Qwen CLI session parser
3
+ *
4
+ * Handles session detection for Qwen CLI.
5
+ * Session files are stored in ~/.qwen/tmp/<project_hash>/
6
+ * and checkpoints in ~/.qwen/tmp/<project_hash>/checkpoints/
7
+ */
8
+ import path from "node:path";
9
+ import { homedir } from "node:os";
10
+ import { findLatestNestedSessionFile, readSessionIdFromFile, } from "../common.js";
11
+ /**
12
+ * Finds the latest Qwen session ID.
13
+ *
14
+ * Search order:
15
+ * 1. ~/.qwen/tmp/<hash>/*.json or *.jsonl
16
+ * 2. ~/.qwen/tmp/<hash>/checkpoints/*.json or *.ckpt
17
+ *
18
+ * Falls back to filename (without extension) if no session ID is found in content.
19
+ *
20
+ * @param _cwd - Working directory (currently unused, reserved for future per-project filtering)
21
+ * @returns Session ID string or null if not found
22
+ */
23
+ export async function findLatestQwenSessionId(_cwd) {
24
+ const baseDir = path.join(homedir(), ".qwen", "tmp");
25
+ // Try root level first, then checkpoints subdirectory
26
+ const latest = (await findLatestNestedSessionFile(baseDir, [], (name) => name.endsWith(".json") || name.endsWith(".jsonl"))) ??
27
+ (await findLatestNestedSessionFile(baseDir, ["checkpoints"], (name) => name.endsWith(".json") || name.endsWith(".ckpt")));
28
+ if (!latest)
29
+ return null;
30
+ const fromContent = await readSessionIdFromFile(latest);
31
+ if (fromContent)
32
+ return fromContent;
33
+ // Fallback: use filename (without extension) as tag
34
+ return path.basename(latest).replace(/\.[^.]+$/, "");
35
+ }
36
+ //# sourceMappingURL=qwen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qwen.js","sourceRoot":"","sources":["../../../../src/utils/session/parsers/qwen.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,GACtB,MAAM,cAAc,CAAC;AAEtB;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,IAAY;IAEZ,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAErD,sDAAsD;IACtD,MAAM,MAAM,GACV,CAAC,MAAM,2BAA2B,CAChC,OAAO,EACP,EAAE,EACF,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAC5D,CAAC;QACF,CAAC,MAAM,2BAA2B,CAChC,OAAO,EACP,CAAC,aAAa,CAAC,EACf,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAC3D,CAAC,CAAC;IAEL,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,WAAW,GAAG,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACxD,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC;IAEpC,oDAAoD;IACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Session types - common type definitions for session parsers
3
+ */
4
+ /**
5
+ * Options for session search operations
6
+ */
7
+ export interface SessionSearchOptions {
8
+ /** Minimum mtime (ms since epoch) */
9
+ since?: number;
10
+ /** Maximum mtime (ms since epoch) */
11
+ until?: number;
12
+ /** Reference time for preferring closest match */
13
+ preferClosestTo?: number;
14
+ /** Time window for closest match (default: 30 minutes) */
15
+ windowMs?: number;
16
+ /** Working directory filter */
17
+ cwd?: string | null;
18
+ }
19
+ /**
20
+ * Base session info with ID and modification time
21
+ */
22
+ export interface SessionInfo {
23
+ id: string;
24
+ mtime: number;
25
+ }
26
+ /**
27
+ * Claude Code session info
28
+ */
29
+ export type ClaudeSessionInfo = SessionInfo;
30
+ /**
31
+ * Codex CLI session info
32
+ */
33
+ export type CodexSessionInfo = SessionInfo;
34
+ /**
35
+ * Gemini CLI session info
36
+ */
37
+ export type GeminiSessionInfo = SessionInfo;
38
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/session/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE5C;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAE3C;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,WAAW,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Session types - common type definitions for session parsers
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/session/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}