@redplanethq/corebrain 2.6.2 → 2.6.4

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 (69) hide show
  1. package/dist/commands/coding/close.d.ts.map +1 -1
  2. package/dist/commands/coding/close.js +13 -25
  3. package/dist/commands/coding/close.js.map +1 -1
  4. package/dist/commands/coding/list.d.ts +4 -0
  5. package/dist/commands/coding/list.d.ts.map +1 -1
  6. package/dist/commands/coding/list.js +18 -38
  7. package/dist/commands/coding/list.js.map +1 -1
  8. package/dist/commands/coding/read.d.ts +1 -0
  9. package/dist/commands/coding/read.d.ts.map +1 -1
  10. package/dist/commands/coding/read.js +36 -35
  11. package/dist/commands/coding/read.js.map +1 -1
  12. package/dist/commands/coding/resume.d.ts +1 -0
  13. package/dist/commands/coding/resume.d.ts.map +1 -1
  14. package/dist/commands/coding/resume.js +37 -31
  15. package/dist/commands/coding/resume.js.map +1 -1
  16. package/dist/commands/coding/setup.d.ts.map +1 -1
  17. package/dist/commands/coding/setup.js +34 -5
  18. package/dist/commands/coding/setup.js.map +1 -1
  19. package/dist/commands/coding/start.d.ts.map +1 -1
  20. package/dist/commands/coding/start.js +7 -32
  21. package/dist/commands/coding/start.js.map +1 -1
  22. package/dist/server/gateway-client.d.ts.map +1 -1
  23. package/dist/server/gateway-client.js +4 -0
  24. package/dist/server/gateway-client.js.map +1 -1
  25. package/dist/server/tools/coding-tools.d.ts +0 -22
  26. package/dist/server/tools/coding-tools.d.ts.map +1 -1
  27. package/dist/server/tools/coding-tools.js +237 -233
  28. package/dist/server/tools/coding-tools.js.map +1 -1
  29. package/dist/tui/chat.d.ts.map +1 -1
  30. package/dist/tui/chat.js +57 -1
  31. package/dist/tui/chat.js.map +1 -1
  32. package/dist/tui/components/tool-call-item.d.ts.map +1 -1
  33. package/dist/tui/components/tool-call-item.js +16 -8
  34. package/dist/tui/components/tool-call-item.js.map +1 -1
  35. package/dist/tui/hooks/use-conversation.d.ts +2 -0
  36. package/dist/tui/hooks/use-conversation.d.ts.map +1 -1
  37. package/dist/tui/hooks/use-conversation.js +8 -1
  38. package/dist/tui/hooks/use-conversation.js.map +1 -1
  39. package/dist/tui/utils/stream.d.ts +1 -1
  40. package/dist/tui/utils/stream.d.ts.map +1 -1
  41. package/dist/tui/utils/stream.js +2 -2
  42. package/dist/tui/utils/stream.js.map +1 -1
  43. package/dist/types/config.d.ts +2 -0
  44. package/dist/types/config.d.ts.map +1 -1
  45. package/dist/utils/coding-agents/claude-code.d.ts +8 -6
  46. package/dist/utils/coding-agents/claude-code.d.ts.map +1 -1
  47. package/dist/utils/coding-agents/claude-code.js +77 -111
  48. package/dist/utils/coding-agents/claude-code.js.map +1 -1
  49. package/dist/utils/coding-agents/codex.d.ts +23 -0
  50. package/dist/utils/coding-agents/codex.d.ts.map +1 -0
  51. package/dist/utils/coding-agents/codex.js +243 -0
  52. package/dist/utils/coding-agents/codex.js.map +1 -0
  53. package/dist/utils/coding-agents/index.d.ts +12 -10
  54. package/dist/utils/coding-agents/index.d.ts.map +1 -1
  55. package/dist/utils/coding-agents/index.js +30 -23
  56. package/dist/utils/coding-agents/index.js.map +1 -1
  57. package/dist/utils/coding-agents/types.d.ts +37 -21
  58. package/dist/utils/coding-agents/types.d.ts.map +1 -1
  59. package/dist/utils/coding-agents/types.js +98 -1
  60. package/dist/utils/coding-agents/types.js.map +1 -1
  61. package/dist/utils/coding-runner.d.ts +1 -28
  62. package/dist/utils/coding-runner.d.ts.map +1 -1
  63. package/dist/utils/coding-runner.js +10 -85
  64. package/dist/utils/coding-runner.js.map +1 -1
  65. package/dist/utils/coding-sessions.d.ts +4 -57
  66. package/dist/utils/coding-sessions.d.ts.map +1 -1
  67. package/dist/utils/coding-sessions.js +9 -75
  68. package/dist/utils/coding-sessions.js.map +1 -1
  69. package/package.json +2 -2
@@ -1,143 +1,109 @@
1
- import { existsSync, statSync, createReadStream } from 'node:fs';
2
- import { join } from 'node:path';
1
+ import { existsSync, statSync, readdirSync } from 'node:fs';
2
+ import { join, basename } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
- import { createInterface } from 'node:readline';
5
- // Claude Code projects directory
4
+ import { BaseCodingAgentReader } from './types.js';
6
5
  const CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');
7
- // Max file size before limiting lines (5MB)
8
6
  const MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
9
- // Default lines to read when file is too large
10
7
  const DEFAULT_LARGE_FILE_LINES = 100;
11
8
  /**
12
- * Convert a directory path to Claude Code's folder name format
13
- * /Users/harshithmullapudi/Documents/core -> -Users-harshithmullapudi-Documents-core
9
+ * /Users/foo/bar → -Users-foo-bar
14
10
  */
15
11
  function dirToProjectFolder(dir) {
16
12
  return dir.replace(/\//g, '-');
17
13
  }
18
14
  /**
19
- * Get the Claude Code session JSONL file path
15
+ * -Users-foo-bar → /Users/foo/bar
20
16
  */
21
- function getSessionPath(dir, sessionId) {
22
- const projectFolder = dirToProjectFolder(dir);
23
- return join(CLAUDE_PROJECTS_DIR, projectFolder, `${sessionId}.jsonl`);
17
+ function projectFolderToDir(folder) {
18
+ return folder.replace(/^-/, '/').replace(/-/g, '/');
24
19
  }
25
- /**
26
- * Format bytes to human readable size
27
- */
28
- function formatBytes(bytes) {
29
- if (bytes === 0)
30
- return '0 B';
31
- const k = 1024;
32
- const sizes = ['B', 'KB', 'MB', 'GB'];
33
- const i = Math.floor(Math.log(bytes) / Math.log(k));
34
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
35
- }
36
- /**
37
- * Read JSONL file line by line (streaming)
38
- */
39
- async function readJsonlLines(filePath, options = {}) {
40
- return new Promise((resolve, reject) => {
41
- const entries = [];
42
- let lineCount = 0;
43
- const rl = createInterface({
44
- input: createReadStream(filePath),
45
- crlfDelay: Infinity,
46
- });
47
- rl.on('line', (line) => {
48
- if (!line.trim())
49
- return;
50
- lineCount++;
51
- try {
52
- const entry = JSON.parse(line);
53
- entries.push(entry);
54
- }
55
- catch {
56
- // Skip malformed lines
57
- }
58
- });
59
- rl.on('close', () => {
60
- let resultEntries;
61
- const totalLines = entries.length;
62
- if (options.tail && options.lines) {
63
- const start = Math.max(0, totalLines - options.lines);
64
- resultEntries = entries.slice(start);
65
- }
66
- else if (options.lines || options.offset) {
67
- const offset = options.offset || 0;
68
- const limit = options.lines || totalLines;
69
- resultEntries = entries.slice(offset, offset + limit);
70
- }
71
- else {
72
- resultEntries = entries;
73
- }
74
- resolve({ entries: resultEntries, totalLines });
75
- });
76
- rl.on('error', reject);
77
- });
20
+ function getSessionPath(dir, sessionId) {
21
+ return join(CLAUDE_PROJECTS_DIR, dirToProjectFolder(dir), `${sessionId}.jsonl`);
78
22
  }
79
- /**
80
- * Claude Code session reader
81
- * Reads from ~/.claude/projects/<path>/<session-id>.jsonl
82
- */
83
- export const claudeCodeReader = {
23
+ export class ClaudeCodeReader extends BaseCodingAgentReader {
24
+ agentName = 'claude-code';
84
25
  sessionExists(dir, sessionId) {
85
- const sessionPath = getSessionPath(dir, sessionId);
86
- return existsSync(sessionPath);
87
- },
26
+ return existsSync(getSessionPath(dir, sessionId));
27
+ }
88
28
  async readSessionOutput(dir, sessionId, options = {}) {
89
29
  const sessionPath = getSessionPath(dir, sessionId);
90
30
  if (!existsSync(sessionPath)) {
91
- return {
92
- entries: [],
93
- totalLines: 0,
94
- returnedLines: 0,
95
- fileExists: false,
96
- fileSizeBytes: 0,
97
- fileSizeHuman: '0 B',
98
- };
31
+ return { entries: [], totalLines: 0, returnedLines: 0, fileExists: false, fileSizeBytes: 0, fileSizeHuman: '0 B' };
99
32
  }
100
- // Get file size
101
33
  let fileSizeBytes = 0;
102
34
  try {
103
- const stats = statSync(sessionPath);
104
- fileSizeBytes = stats.size;
105
- }
106
- catch {
107
- // Ignore stat errors
35
+ fileSizeBytes = statSync(sessionPath).size;
108
36
  }
109
- const fileSizeHuman = formatBytes(fileSizeBytes);
110
- // If file is large and no explicit lines limit, auto-limit
37
+ catch { /* ignore */ }
38
+ const fileSizeHuman = this.formatBytes(fileSizeBytes);
111
39
  let readOptions = { ...options };
112
40
  if (fileSizeBytes > MAX_FILE_SIZE_BYTES && !options.lines) {
113
- readOptions = {
114
- ...options,
115
- lines: DEFAULT_LARGE_FILE_LINES,
116
- tail: true, // Get most recent entries
117
- };
41
+ readOptions = { ...options, lines: DEFAULT_LARGE_FILE_LINES, tail: true };
118
42
  }
119
43
  try {
120
- const { entries, totalLines } = await readJsonlLines(sessionPath, readOptions);
121
- return {
122
- entries,
123
- totalLines,
124
- returnedLines: entries.length,
125
- fileExists: true,
126
- fileSizeBytes,
127
- fileSizeHuman,
128
- };
44
+ const { entries, totalLines } = await this.readJsonlLines(sessionPath, readOptions);
45
+ return { entries, totalLines, returnedLines: entries.length, fileExists: true, fileSizeBytes, fileSizeHuman };
129
46
  }
130
47
  catch (err) {
131
48
  return {
132
- entries: [],
133
- totalLines: 0,
134
- returnedLines: 0,
135
- fileExists: true,
136
- fileSizeBytes,
137
- fileSizeHuman,
49
+ entries: [], totalLines: 0, returnedLines: 0, fileExists: true, fileSizeBytes, fileSizeHuman,
138
50
  error: err instanceof Error ? err.message : 'Failed to read session file',
139
51
  };
140
52
  }
141
- },
142
- };
53
+ }
54
+ async scanSessions(options = {}) {
55
+ if (!existsSync(CLAUDE_PROJECTS_DIR))
56
+ return [];
57
+ let projectFolders;
58
+ try {
59
+ projectFolders = readdirSync(CLAUDE_PROJECTS_DIR);
60
+ }
61
+ catch {
62
+ return [];
63
+ }
64
+ const results = [];
65
+ for (const folder of projectFolders) {
66
+ const dir = projectFolderToDir(folder);
67
+ if (options.dir && dir !== options.dir)
68
+ continue;
69
+ const projectPath = join(CLAUDE_PROJECTS_DIR, folder);
70
+ let files;
71
+ try {
72
+ files = readdirSync(projectPath).filter((f) => f.endsWith('.jsonl'));
73
+ }
74
+ catch {
75
+ continue;
76
+ }
77
+ for (const file of files) {
78
+ const filePath = join(projectPath, file);
79
+ let stats;
80
+ try {
81
+ stats = statSync(filePath);
82
+ }
83
+ catch {
84
+ continue;
85
+ }
86
+ if (options.since && stats.mtimeMs < options.since)
87
+ continue;
88
+ results.push({
89
+ sessionId: basename(file, '.jsonl'),
90
+ agent: this.agentName,
91
+ dir,
92
+ title: null,
93
+ filePath,
94
+ fileSizeBytes: stats.size,
95
+ createdAt: stats.birthtimeMs || stats.mtimeMs,
96
+ updatedAt: stats.mtimeMs,
97
+ });
98
+ }
99
+ }
100
+ results.sort((a, b) => b.updatedAt - a.updatedAt);
101
+ // Populate titles in parallel (before slicing — titles are cheap to read)
102
+ await Promise.all(results.map(async (s) => {
103
+ s.title = await this.extractTitle(s.filePath);
104
+ }));
105
+ return results;
106
+ }
107
+ }
108
+ export const claudeCodeReader = new ClaudeCodeReader();
143
109
  //# sourceMappingURL=claude-code.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/utils/coding-agents/claude-code.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/utils/coding-agents/claude-code.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { BaseCodingAgentReader, type AgentReadResult, type AgentReadOptions, type ScannedSession, type ScanOptions } from './types.js';
2
+ export declare class CodexReader extends BaseCodingAgentReader {
3
+ readonly agentName = "codex-cli";
4
+ /**
5
+ * For startup polling: check if codex has written anything to the captured stdout log.
6
+ * We use our internal UUID (not codex's UUID) as sessionId during a live session.
7
+ */
8
+ sessionExists(_dir: string, sessionId: string): boolean;
9
+ /**
10
+ * Read session output.
11
+ * - For live sessions (our UUID): read from captured stdout log.
12
+ * - For historical sessions (codex UUID from list/search): find in date dirs.
13
+ */
14
+ readSessionOutput(_dir: string, sessionId: string, options?: AgentReadOptions): Promise<AgentReadResult>;
15
+ /**
16
+ * Extract title from codex JSONL format.
17
+ * Codex has no `summary` type — find the first user message that isn't the environment_context.
18
+ */
19
+ protected extractTitle(filePath: string): Promise<string | null>;
20
+ scanSessions(options?: ScanOptions): Promise<ScannedSession[]>;
21
+ }
22
+ export declare const codexReader: CodexReader;
23
+ //# sourceMappingURL=codex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/utils/coding-agents/codex.ts"],"names":[],"mappings":"AAKA,OAAO,EACN,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,WAAW,EAEhB,MAAM,SAAS,CAAC;AA2GjB,qBAAa,WAAY,SAAQ,qBAAqB;IACrD,QAAQ,CAAC,SAAS,eAAe;IAEjC;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAUvD;;;;OAIG;IACG,iBAAiB,CACtB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAAC,eAAe,CAAC;IAiC3B;;;OAGG;cACa,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAwChE,YAAY,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CA4CxE;AAED,eAAO,MAAM,WAAW,aAAoB,CAAC"}
@@ -0,0 +1,243 @@
1
+ import { existsSync, statSync, readdirSync, createReadStream } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { createInterface } from 'node:readline';
5
+ import { getSessionLogPath } from '../../utils/coding-runner.js';
6
+ import { BaseCodingAgentReader, } from './types.js';
7
+ // ~/.codex/sessions/YYYY/MM/DD/rollout-<datetime>-<uuid>.jsonl
8
+ const CODEX_SESSIONS_DIR = join(homedir(), '.codex', 'sessions');
9
+ const MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
10
+ const DEFAULT_LARGE_FILE_LINES = 100;
11
+ /**
12
+ * Extract the session UUID from a codex rollout filename.
13
+ * rollout-2025-11-03T22-52-20-019a4abd-bd5b-7ab0-aee6-f2fbdcab989c.jsonl
14
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15
+ */
16
+ function extractSessionId(filename) {
17
+ const match = filename.match(/^rollout-.*?T\d{2}-\d{2}-\d{2}-(.+)\.jsonl$/);
18
+ return match?.[1] ?? null;
19
+ }
20
+ /**
21
+ * Read the first JSONL line from a file and parse it.
22
+ */
23
+ async function readFirstLine(filePath) {
24
+ return new Promise((resolve) => {
25
+ const rl = createInterface({ input: createReadStream(filePath), crlfDelay: Infinity });
26
+ let done = false;
27
+ rl.on('line', (line) => {
28
+ if (done || !line.trim())
29
+ return;
30
+ done = true;
31
+ rl.close();
32
+ try {
33
+ resolve(JSON.parse(line));
34
+ }
35
+ catch {
36
+ resolve(null);
37
+ }
38
+ });
39
+ rl.on('close', () => { if (!done)
40
+ resolve(null); });
41
+ rl.on('error', () => resolve(null));
42
+ });
43
+ }
44
+ /**
45
+ * Walk ~/.codex/sessions/YYYY/MM/DD/ and yield rollout JSONL files (newest first).
46
+ */
47
+ function* walkCodexSessions(since) {
48
+ if (!existsSync(CODEX_SESSIONS_DIR))
49
+ return;
50
+ let years;
51
+ try {
52
+ years = readdirSync(CODEX_SESSIONS_DIR).filter((y) => /^\d{4}$/.test(y));
53
+ }
54
+ catch {
55
+ return;
56
+ }
57
+ for (const year of years.sort().reverse()) {
58
+ const yearPath = join(CODEX_SESSIONS_DIR, year);
59
+ let months;
60
+ try {
61
+ months = readdirSync(yearPath).filter((m) => /^\d{2}$/.test(m));
62
+ }
63
+ catch {
64
+ continue;
65
+ }
66
+ for (const month of months.sort().reverse()) {
67
+ const monthPath = join(yearPath, month);
68
+ let days;
69
+ try {
70
+ days = readdirSync(monthPath).filter((d) => /^\d{2}$/.test(d));
71
+ }
72
+ catch {
73
+ continue;
74
+ }
75
+ for (const day of days.sort().reverse()) {
76
+ if (since) {
77
+ const dateMs = new Date(`${year}-${month}-${day}`).getTime();
78
+ if (dateMs < since - 86_400_000)
79
+ continue;
80
+ }
81
+ const dayPath = join(monthPath, day);
82
+ let files;
83
+ try {
84
+ files = readdirSync(dayPath)
85
+ .filter((f) => f.startsWith('rollout-') && f.endsWith('.jsonl'));
86
+ }
87
+ catch {
88
+ continue;
89
+ }
90
+ for (const file of files.sort().reverse()) {
91
+ const sessionId = extractSessionId(file);
92
+ if (!sessionId)
93
+ continue;
94
+ yield { filePath: join(dayPath, file), sessionId };
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Find the JSONL file path for a codex session UUID.
102
+ */
103
+ function findSessionPath(sessionId) {
104
+ for (const { filePath, sessionId: id } of walkCodexSessions()) {
105
+ if (id === sessionId)
106
+ return filePath;
107
+ }
108
+ return null;
109
+ }
110
+ export class CodexReader extends BaseCodingAgentReader {
111
+ agentName = 'codex-cli';
112
+ /**
113
+ * For startup polling: check if codex has written anything to the captured stdout log.
114
+ * We use our internal UUID (not codex's UUID) as sessionId during a live session.
115
+ */
116
+ sessionExists(_dir, sessionId) {
117
+ const logPath = getSessionLogPath(sessionId, 'stdout');
118
+ if (!existsSync(logPath))
119
+ return false;
120
+ try {
121
+ return statSync(logPath).size > 0;
122
+ }
123
+ catch {
124
+ return false;
125
+ }
126
+ }
127
+ /**
128
+ * Read session output.
129
+ * - For live sessions (our UUID): read from captured stdout log.
130
+ * - For historical sessions (codex UUID from list/search): find in date dirs.
131
+ */
132
+ async readSessionOutput(_dir, sessionId, options = {}) {
133
+ // Check stdout log first (live/recent session tracked by our UUID)
134
+ const logPath = getSessionLogPath(sessionId, 'stdout');
135
+ const sessionPath = existsSync(logPath) && statSync(logPath).size > 0
136
+ ? logPath
137
+ : findSessionPath(sessionId);
138
+ if (!sessionPath) {
139
+ return { entries: [], totalLines: 0, returnedLines: 0, fileExists: false, fileSizeBytes: 0, fileSizeHuman: '0 B' };
140
+ }
141
+ let fileSizeBytes = 0;
142
+ try {
143
+ fileSizeBytes = statSync(sessionPath).size;
144
+ }
145
+ catch { /* ignore */ }
146
+ const fileSizeHuman = this.formatBytes(fileSizeBytes);
147
+ let readOptions = { ...options };
148
+ if (fileSizeBytes > MAX_FILE_SIZE_BYTES && !options.lines) {
149
+ readOptions = { ...options, lines: DEFAULT_LARGE_FILE_LINES, tail: true };
150
+ }
151
+ try {
152
+ const { entries, totalLines } = await this.readJsonlLines(sessionPath, readOptions);
153
+ return { entries, totalLines, returnedLines: entries.length, fileExists: true, fileSizeBytes, fileSizeHuman };
154
+ }
155
+ catch (err) {
156
+ return {
157
+ entries: [], totalLines: 0, returnedLines: 0, fileExists: true, fileSizeBytes, fileSizeHuman,
158
+ error: err instanceof Error ? err.message : 'Failed to read session file',
159
+ };
160
+ }
161
+ }
162
+ /**
163
+ * Extract title from codex JSONL format.
164
+ * Codex has no `summary` type — find the first user message that isn't the environment_context.
165
+ */
166
+ async extractTitle(filePath) {
167
+ return new Promise((resolve) => {
168
+ let firstUserMessage = null;
169
+ let resolved = false;
170
+ const rl = createInterface({ input: createReadStream(filePath), crlfDelay: Infinity });
171
+ rl.on('line', (line) => {
172
+ if (resolved || !line.trim())
173
+ return;
174
+ try {
175
+ const entry = JSON.parse(line);
176
+ if (entry.type === 'response_item' &&
177
+ entry.payload?.type === 'message' &&
178
+ entry.payload?.role === 'user') {
179
+ const content = entry.payload?.content;
180
+ if (Array.isArray(content)) {
181
+ for (const part of content) {
182
+ if (part.type === 'input_text' && typeof part.text === 'string') {
183
+ const text = part.text.trim();
184
+ // Skip environment context injected by codex
185
+ if (!text.startsWith('<environment_context>')) {
186
+ firstUserMessage = text.slice(0, 120);
187
+ resolved = true;
188
+ rl.close();
189
+ return;
190
+ }
191
+ }
192
+ }
193
+ }
194
+ }
195
+ }
196
+ catch { /* skip */ }
197
+ });
198
+ rl.on('close', () => resolve(firstUserMessage));
199
+ rl.on('error', () => resolve(null));
200
+ });
201
+ }
202
+ async scanSessions(options = {}) {
203
+ const results = [];
204
+ for (const { filePath, sessionId } of walkCodexSessions(options.since)) {
205
+ let stats;
206
+ try {
207
+ stats = statSync(filePath);
208
+ }
209
+ catch {
210
+ continue;
211
+ }
212
+ if (options.since && stats.mtimeMs < options.since)
213
+ continue;
214
+ results.push({
215
+ sessionId,
216
+ agent: this.agentName,
217
+ dir: '', // populated below from session_meta
218
+ title: null,
219
+ filePath,
220
+ fileSizeBytes: stats.size,
221
+ createdAt: stats.birthtimeMs || stats.mtimeMs,
222
+ updatedAt: stats.mtimeMs,
223
+ });
224
+ }
225
+ results.sort((a, b) => b.updatedAt - a.updatedAt);
226
+ // Populate title + dir from session_meta (first line) in parallel
227
+ await Promise.all(results.map(async (s) => {
228
+ const first = await readFirstLine(s.filePath);
229
+ if (first?.type === 'session_meta') {
230
+ const payload = first.payload;
231
+ s.dir = payload?.cwd ?? '';
232
+ }
233
+ s.title = await this.extractTitle(s.filePath);
234
+ }));
235
+ // Apply dir filter after reading cwd from session_meta
236
+ if (options.dir) {
237
+ return results.filter((s) => s.dir === options.dir);
238
+ }
239
+ return results;
240
+ }
241
+ }
242
+ export const codexReader = new CodexReader();
243
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/utils/coding-agents/codex.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,17 @@
1
- import type { AgentReader, AgentReadResult, AgentReadOptions } from './types.js';
2
- export type { AgentReader, AgentReadResult, AgentReadOptions };
3
- /**
4
- * Get the reader for a specific agent
5
- */
6
- export declare function getAgentReader(agentName: string): AgentReader | null;
1
+ import { BaseCodingAgentReader, type AgentReadResult, type AgentReadOptions, type ScannedSession, type ScanOptions, type ScanResult } from './types.js';
2
+ export type { AgentReadResult, AgentReadOptions, ScannedSession, ScanOptions, ScanResult };
3
+ export { BaseCodingAgentReader };
4
+ export declare function getAgentReader(agentName: string): BaseCodingAgentReader | null;
5
+ export declare function readAgentSessionOutput(agentName: string, dir: string, sessionId: string, options?: AgentReadOptions): Promise<AgentReadResult>;
6
+ export declare function agentSessionExists(agentName: string, dir: string, sessionId: string): boolean;
7
7
  /**
8
- * Read session output using the appropriate agent reader
8
+ * Scan sessions across all registered agents, merge, sort by recency, and paginate.
9
9
  */
10
- export declare function readAgentSessionOutput(agentName: string, dir: string, sessionId: string, options?: AgentReadOptions): Promise<AgentReadResult>;
10
+ export declare function scanAllSessions(options?: ScanOptions): Promise<ScanResult>;
11
11
  /**
12
- * Check if a session exists for the given agent
12
+ * Search sessions by title across all agents.
13
13
  */
14
- export declare function agentSessionExists(agentName: string, dir: string, sessionId: string): boolean;
14
+ export declare function searchSessions(query: string, options?: Omit<ScanOptions, 'offset'> & {
15
+ limit?: number;
16
+ }): Promise<ScannedSession[]>;
15
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/coding-agents/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAG5E,YAAY,EAAC,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAC,CAAC;AAS7D;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAEpE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC3C,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CAgB1B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,GACf,OAAO,CAMT"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/coding-agents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,qBAAqB,EAAE,KAAK,eAAe,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAC,MAAM,SAAS,CAAC;AAInJ,YAAY,EAAC,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAC,CAAC;AACzF,OAAO,EAAC,qBAAqB,EAAC,CAAC;AAO/B,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,GAAG,IAAI,CAE9E;AAED,wBAAsB,sBAAsB,CAC3C,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,eAAe,CAAC,CAS1B;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAE7F;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAepF;AAED;;GAEG;AACH,wBAAsB,cAAc,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAM,GAC1D,OAAO,CAAC,cAAc,EAAE,CAAC,CAK3B"}
@@ -1,42 +1,49 @@
1
+ import { BaseCodingAgentReader } from './types.js';
1
2
  import { claudeCodeReader } from './claude-code.js';
2
- /**
3
- * Registry of agent readers
4
- */
3
+ import { codexReader } from './codex.js';
4
+ export { BaseCodingAgentReader };
5
5
  const agentReaders = {
6
6
  'claude-code': claudeCodeReader,
7
+ 'codex-cli': codexReader,
7
8
  };
8
- /**
9
- * Get the reader for a specific agent
10
- */
11
9
  export function getAgentReader(agentName) {
12
10
  return agentReaders[agentName] || null;
13
11
  }
14
- /**
15
- * Read session output using the appropriate agent reader
16
- */
17
12
  export async function readAgentSessionOutput(agentName, dir, sessionId, options) {
18
13
  const reader = getAgentReader(agentName);
19
14
  if (!reader) {
20
15
  return {
21
- entries: [],
22
- totalLines: 0,
23
- returnedLines: 0,
24
- fileExists: false,
25
- fileSizeBytes: 0,
26
- fileSizeHuman: '0 B',
27
- error: `No reader available for agent: ${agentName}`,
16
+ entries: [], totalLines: 0, returnedLines: 0, fileExists: false, fileSizeBytes: 0,
17
+ fileSizeHuman: '0 B', error: `No reader for agent: ${agentName}`,
28
18
  };
29
19
  }
30
20
  return reader.readSessionOutput(dir, sessionId, options);
31
21
  }
22
+ export function agentSessionExists(agentName, dir, sessionId) {
23
+ return getAgentReader(agentName)?.sessionExists(dir, sessionId) ?? false;
24
+ }
32
25
  /**
33
- * Check if a session exists for the given agent
26
+ * Scan sessions across all registered agents, merge, sort by recency, and paginate.
34
27
  */
35
- export function agentSessionExists(agentName, dir, sessionId) {
36
- const reader = getAgentReader(agentName);
37
- if (!reader) {
38
- return false;
39
- }
40
- return reader.sessionExists(dir, sessionId);
28
+ export async function scanAllSessions(options = {}) {
29
+ const readers = options.agent
30
+ ? Object.values(agentReaders).filter((r) => r.agentName === options.agent)
31
+ : Object.values(agentReaders);
32
+ const allResults = await Promise.all(readers.map((r) => r.scanSessions(options)));
33
+ const merged = allResults.flat().sort((a, b) => b.updatedAt - a.updatedAt);
34
+ const total = merged.length;
35
+ const offset = options.offset ?? 0;
36
+ const limit = options.limit ?? 20;
37
+ const sessions = merged.slice(offset, offset + limit);
38
+ return { sessions, total, hasMore: offset + limit < total };
39
+ }
40
+ /**
41
+ * Search sessions by title across all agents.
42
+ */
43
+ export async function searchSessions(query, options = {}) {
44
+ const { sessions: all } = await scanAllSessions({ ...options, limit: undefined });
45
+ const q = query.toLowerCase();
46
+ const matched = all.filter((s) => s.title?.toLowerCase().includes(q));
47
+ return options.limit ? matched.slice(0, options.limit) : matched;
41
48
  }
42
49
  //# sourceMappingURL=index.js.map