@trishchuk/codex-mcp-tool 1.2.0 → 1.4.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/README.md +84 -170
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +14 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/tools/ask-codex.tool.d.ts.map +1 -1
- package/dist/tools/ask-codex.tool.js +82 -54
- package/dist/tools/ask-codex.tool.js.map +1 -1
- package/dist/tools/batch-codex.tool.js +1 -1
- package/dist/tools/batch-codex.tool.js.map +1 -1
- package/dist/tools/health.tool.d.ts +3 -0
- package/dist/tools/health.tool.d.ts.map +1 -0
- package/dist/tools/health.tool.js +189 -0
- package/dist/tools/health.tool.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/list-sessions.tool.d.ts +3 -0
- package/dist/tools/list-sessions.tool.d.ts.map +1 -0
- package/dist/tools/list-sessions.tool.js +71 -0
- package/dist/tools/list-sessions.tool.js.map +1 -0
- package/dist/utils/codexCommandBuilder.d.ts +87 -0
- package/dist/utils/codexCommandBuilder.d.ts.map +1 -0
- package/dist/utils/codexCommandBuilder.js +285 -0
- package/dist/utils/codexCommandBuilder.js.map +1 -0
- package/dist/utils/codexExecutor.d.ts +12 -1
- package/dist/utils/codexExecutor.d.ts.map +1 -1
- package/dist/utils/codexExecutor.js +18 -181
- package/dist/utils/codexExecutor.js.map +1 -1
- package/dist/utils/commandExecutor.js +3 -3
- package/dist/utils/commandExecutor.js.map +1 -1
- package/dist/utils/errorTypes.d.ts +74 -0
- package/dist/utils/errorTypes.d.ts.map +1 -0
- package/dist/utils/errorTypes.js +268 -0
- package/dist/utils/errorTypes.js.map +1 -0
- package/dist/utils/modelDetection.d.ts +45 -0
- package/dist/utils/modelDetection.d.ts.map +1 -0
- package/dist/utils/modelDetection.js +148 -0
- package/dist/utils/modelDetection.js.map +1 -0
- package/dist/utils/sessionStorage.d.ts +79 -0
- package/dist/utils/sessionStorage.d.ts.map +1 -0
- package/dist/utils/sessionStorage.js +276 -0
- package/dist/utils/sessionStorage.js.map +1 -0
- package/dist/utils/versionDetection.d.ts +123 -0
- package/dist/utils/versionDetection.d.ts.map +1 -0
- package/dist/utils/versionDetection.js +188 -0
- package/dist/utils/versionDetection.js.map +1 -0
- package/dist/utils/workingDirResolver.d.ts +13 -8
- package/dist/utils/workingDirResolver.d.ts.map +1 -1
- package/dist/utils/workingDirResolver.js +44 -26
- package/dist/utils/workingDirResolver.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionStorage.d.ts","sourceRoot":"","sources":["../../src/utils/sessionStorage.ts"],"names":[],"mappings":"AAoBA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAiDD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAO9D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C;AAoCD;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAsB3F;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAehE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAc7E;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CAiCtF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAStF;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG5E;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,WAAW,EAAE,CAG5C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAMxD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAgBA;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe3E"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { existsSync, readFileSync } from 'fs';
|
|
3
|
+
import { join, basename, dirname } from 'path';
|
|
4
|
+
import { Logger } from './logger.js';
|
|
5
|
+
/**
|
|
6
|
+
* Session Storage for Codex MCP Tool
|
|
7
|
+
* Provides workspace-isolated session management with native Codex resume support
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Workspace isolation via MD5 hash (repo:head:path)
|
|
11
|
+
* - Native Codex conversation ID storage for resume
|
|
12
|
+
* - Configurable TTL via CODEX_SESSION_TTL_MS
|
|
13
|
+
* - Aggressive cleanup (max 50 sessions)
|
|
14
|
+
*/
|
|
15
|
+
// Configuration from environment
|
|
16
|
+
const SESSION_TTL_MS = parseInt(process.env.CODEX_SESSION_TTL_MS || '', 10) || 24 * 60 * 60 * 1000; // 24 hours default
|
|
17
|
+
const MAX_SESSIONS = parseInt(process.env.CODEX_MAX_SESSIONS || '', 10) || 50;
|
|
18
|
+
/**
|
|
19
|
+
* In-memory session storage
|
|
20
|
+
*/
|
|
21
|
+
const sessionStore = new Map();
|
|
22
|
+
/**
|
|
23
|
+
* Find git root directory by walking up the tree
|
|
24
|
+
*/
|
|
25
|
+
function findGitRoot(startPath) {
|
|
26
|
+
let currentPath = startPath;
|
|
27
|
+
// Limit search depth to prevent infinite loops
|
|
28
|
+
for (let i = 0; i < 20; i++) {
|
|
29
|
+
const gitPath = join(currentPath, '.git');
|
|
30
|
+
if (existsSync(gitPath)) {
|
|
31
|
+
return currentPath;
|
|
32
|
+
}
|
|
33
|
+
const parentPath = dirname(currentPath);
|
|
34
|
+
if (parentPath === currentPath) {
|
|
35
|
+
// Reached filesystem root
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
currentPath = parentPath;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read git HEAD content for workspace identification
|
|
44
|
+
*/
|
|
45
|
+
function readGitHead(gitRoot) {
|
|
46
|
+
if (!gitRoot)
|
|
47
|
+
return '';
|
|
48
|
+
try {
|
|
49
|
+
const headPath = join(gitRoot, '.git', 'HEAD');
|
|
50
|
+
if (existsSync(headPath)) {
|
|
51
|
+
return readFileSync(headPath, 'utf8').trim();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
Logger.debug('Failed to read git HEAD:', error);
|
|
56
|
+
}
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Generate workspace ID using MD5 hash
|
|
61
|
+
* Format: repo:head:path -> 12-char hex
|
|
62
|
+
*/
|
|
63
|
+
export function generateWorkspaceId(workingDir) {
|
|
64
|
+
const gitRoot = findGitRoot(workingDir);
|
|
65
|
+
const repoName = basename(gitRoot || workingDir);
|
|
66
|
+
const headContent = readGitHead(gitRoot);
|
|
67
|
+
const hashInput = `${repoName}:${headContent}:${workingDir}`;
|
|
68
|
+
return createHash('md5').update(hashInput).digest('hex').substring(0, 12);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Generate unique session ID
|
|
72
|
+
*/
|
|
73
|
+
export function generateSessionId() {
|
|
74
|
+
const timestamp = Date.now().toString(36);
|
|
75
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
76
|
+
return `ses_${timestamp}_${random}`;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Clean up expired sessions and enforce max limit
|
|
80
|
+
*/
|
|
81
|
+
function cleanupSessions() {
|
|
82
|
+
const now = Date.now();
|
|
83
|
+
const expiredIds = [];
|
|
84
|
+
// Find expired sessions
|
|
85
|
+
for (const [id, session] of sessionStore.entries()) {
|
|
86
|
+
if (now - session.updatedAt > SESSION_TTL_MS) {
|
|
87
|
+
expiredIds.push(id);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Remove expired
|
|
91
|
+
for (const id of expiredIds) {
|
|
92
|
+
sessionStore.delete(id);
|
|
93
|
+
Logger.debug(`Cleaned up expired session: ${id}`);
|
|
94
|
+
}
|
|
95
|
+
// Enforce max limit - remove oldest if over limit
|
|
96
|
+
if (sessionStore.size > MAX_SESSIONS) {
|
|
97
|
+
const sessions = Array.from(sessionStore.entries()).sort(([, a], [, b]) => a.updatedAt - b.updatedAt);
|
|
98
|
+
const toRemove = sessions.slice(0, sessionStore.size - MAX_SESSIONS);
|
|
99
|
+
for (const [id] of toRemove) {
|
|
100
|
+
sessionStore.delete(id);
|
|
101
|
+
Logger.debug(`Cleaned up oldest session (over limit): ${id}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Save or update a session
|
|
107
|
+
*/
|
|
108
|
+
export function saveSession(data) {
|
|
109
|
+
cleanupSessions();
|
|
110
|
+
const existing = sessionStore.get(data.sessionId);
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
const session = {
|
|
113
|
+
sessionId: data.sessionId,
|
|
114
|
+
workspaceId: data.workspaceId || existing?.workspaceId || '',
|
|
115
|
+
codexConversationId: data.codexConversationId || existing?.codexConversationId,
|
|
116
|
+
lastPrompt: data.lastPrompt || existing?.lastPrompt || '',
|
|
117
|
+
lastResponse: data.lastResponse || existing?.lastResponse || '',
|
|
118
|
+
model: data.model || existing?.model,
|
|
119
|
+
workingDir: data.workingDir || existing?.workingDir,
|
|
120
|
+
createdAt: existing?.createdAt || now,
|
|
121
|
+
updatedAt: now,
|
|
122
|
+
};
|
|
123
|
+
sessionStore.set(data.sessionId, session);
|
|
124
|
+
Logger.debug(`Saved session: ${data.sessionId} (workspace: ${session.workspaceId})`);
|
|
125
|
+
return session;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get session by ID
|
|
129
|
+
*/
|
|
130
|
+
export function getSession(sessionId) {
|
|
131
|
+
const session = sessionStore.get(sessionId);
|
|
132
|
+
if (!session) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
// Check if expired
|
|
136
|
+
if (Date.now() - session.updatedAt > SESSION_TTL_MS) {
|
|
137
|
+
sessionStore.delete(sessionId);
|
|
138
|
+
Logger.debug(`Session expired: ${sessionId}`);
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
return session;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get session by workspace ID (returns most recent)
|
|
145
|
+
*/
|
|
146
|
+
export function getSessionByWorkspace(workspaceId) {
|
|
147
|
+
cleanupSessions();
|
|
148
|
+
let mostRecent = null;
|
|
149
|
+
for (const session of sessionStore.values()) {
|
|
150
|
+
if (session.workspaceId === workspaceId) {
|
|
151
|
+
if (!mostRecent || session.updatedAt > mostRecent.updatedAt) {
|
|
152
|
+
mostRecent = session;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return mostRecent;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get or create session for a workspace
|
|
160
|
+
*
|
|
161
|
+
* When sessionId is provided: returns existing session or creates new with that ID
|
|
162
|
+
* When sessionId is NOT provided: returns workspace session or creates new with generated ID
|
|
163
|
+
*/
|
|
164
|
+
export function getOrCreateSession(workingDir, sessionId) {
|
|
165
|
+
const workspaceId = generateWorkspaceId(workingDir);
|
|
166
|
+
// If sessionId provided explicitly - honor it
|
|
167
|
+
if (sessionId) {
|
|
168
|
+
const existing = getSession(sessionId);
|
|
169
|
+
if (existing) {
|
|
170
|
+
return existing;
|
|
171
|
+
}
|
|
172
|
+
// Create NEW session with requested ID (don't fall back to workspace!)
|
|
173
|
+
return saveSession({
|
|
174
|
+
sessionId,
|
|
175
|
+
workspaceId,
|
|
176
|
+
workingDir,
|
|
177
|
+
lastPrompt: '',
|
|
178
|
+
lastResponse: '',
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
// No sessionId provided - try workspace fallback
|
|
182
|
+
const workspaceSession = getSessionByWorkspace(workspaceId);
|
|
183
|
+
if (workspaceSession) {
|
|
184
|
+
return workspaceSession;
|
|
185
|
+
}
|
|
186
|
+
// Generate new session ID
|
|
187
|
+
return saveSession({
|
|
188
|
+
sessionId: generateSessionId(),
|
|
189
|
+
workspaceId,
|
|
190
|
+
workingDir,
|
|
191
|
+
lastPrompt: '',
|
|
192
|
+
lastResponse: '',
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Update session with Codex conversation ID (for native resume)
|
|
197
|
+
*/
|
|
198
|
+
export function setCodexConversationId(sessionId, conversationId) {
|
|
199
|
+
const session = getSession(sessionId);
|
|
200
|
+
if (session) {
|
|
201
|
+
saveSession({
|
|
202
|
+
...session,
|
|
203
|
+
codexConversationId: conversationId,
|
|
204
|
+
});
|
|
205
|
+
Logger.debug(`Set Codex conversation ID for session ${sessionId}: ${conversationId}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get Codex conversation ID for resume
|
|
210
|
+
*/
|
|
211
|
+
export function getCodexConversationId(sessionId) {
|
|
212
|
+
const session = getSession(sessionId);
|
|
213
|
+
return session?.codexConversationId;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* List all active sessions
|
|
217
|
+
*/
|
|
218
|
+
export function listSessions() {
|
|
219
|
+
cleanupSessions();
|
|
220
|
+
return Array.from(sessionStore.values()).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Delete a session
|
|
224
|
+
*/
|
|
225
|
+
export function deleteSession(sessionId) {
|
|
226
|
+
const deleted = sessionStore.delete(sessionId);
|
|
227
|
+
if (deleted) {
|
|
228
|
+
Logger.debug(`Deleted session: ${sessionId}`);
|
|
229
|
+
}
|
|
230
|
+
return deleted;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Clear all sessions
|
|
234
|
+
*/
|
|
235
|
+
export function clearAllSessions() {
|
|
236
|
+
const count = sessionStore.size;
|
|
237
|
+
sessionStore.clear();
|
|
238
|
+
Logger.debug(`Cleared all ${count} sessions`);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get session statistics
|
|
242
|
+
*/
|
|
243
|
+
export function getSessionStats() {
|
|
244
|
+
cleanupSessions();
|
|
245
|
+
let withConversationId = 0;
|
|
246
|
+
for (const session of sessionStore.values()) {
|
|
247
|
+
if (session.codexConversationId) {
|
|
248
|
+
withConversationId++;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
total: sessionStore.size,
|
|
253
|
+
withConversationId,
|
|
254
|
+
maxSessions: MAX_SESSIONS,
|
|
255
|
+
ttlMs: SESSION_TTL_MS,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Parse Codex conversation ID from stderr output
|
|
260
|
+
* Pattern: "conversation id: abc123" or "Conversation ID: abc-123-def"
|
|
261
|
+
*/
|
|
262
|
+
export function parseConversationIdFromOutput(output) {
|
|
263
|
+
const patterns = [
|
|
264
|
+
/conversation\s*id\s*:\s*([a-zA-Z0-9-]+)/i,
|
|
265
|
+
/conv(?:ersation)?[-_]?id\s*[=:]\s*([a-zA-Z0-9-]+)/i,
|
|
266
|
+
/session\s*id\s*:\s*([a-zA-Z0-9-]+)/i,
|
|
267
|
+
];
|
|
268
|
+
for (const pattern of patterns) {
|
|
269
|
+
const match = output.match(pattern);
|
|
270
|
+
if (match && match[1]) {
|
|
271
|
+
return match[1];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=sessionStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionStorage.js","sourceRoot":"","sources":["../../src/utils/sessionStorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI version detection and feature compatibility checks
|
|
3
|
+
* Ensures correct CLI flags are used based on installed version
|
|
4
|
+
*/
|
|
5
|
+
export interface CodexVersion {
|
|
6
|
+
major: number;
|
|
7
|
+
minor: number;
|
|
8
|
+
patch: number;
|
|
9
|
+
raw: string;
|
|
10
|
+
isValid: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Feature availability by version
|
|
14
|
+
*/
|
|
15
|
+
export declare const FEATURE_VERSIONS: {
|
|
16
|
+
readonly NATIVE_SEARCH: {
|
|
17
|
+
readonly major: 0;
|
|
18
|
+
readonly minor: 52;
|
|
19
|
+
readonly patch: 0;
|
|
20
|
+
};
|
|
21
|
+
readonly TOOL_TOKEN_LIMIT: {
|
|
22
|
+
readonly major: 0;
|
|
23
|
+
readonly minor: 59;
|
|
24
|
+
readonly patch: 0;
|
|
25
|
+
};
|
|
26
|
+
readonly ADD_DIR: {
|
|
27
|
+
readonly major: 0;
|
|
28
|
+
readonly minor: 59;
|
|
29
|
+
readonly patch: 0;
|
|
30
|
+
};
|
|
31
|
+
readonly WINDOWS_AGENT: {
|
|
32
|
+
readonly major: 0;
|
|
33
|
+
readonly minor: 59;
|
|
34
|
+
readonly patch: 0;
|
|
35
|
+
};
|
|
36
|
+
readonly GPT5_1_MODELS: {
|
|
37
|
+
readonly major: 0;
|
|
38
|
+
readonly minor: 56;
|
|
39
|
+
readonly patch: 0;
|
|
40
|
+
};
|
|
41
|
+
readonly RESUME: {
|
|
42
|
+
readonly major: 0;
|
|
43
|
+
readonly minor: 36;
|
|
44
|
+
readonly patch: 0;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Parse version string into structured format
|
|
49
|
+
* @param versionString Raw version string (e.g., "0.59.0", "v0.52.1")
|
|
50
|
+
* @returns CodexVersion object
|
|
51
|
+
*/
|
|
52
|
+
export declare function parseVersion(versionString: string): CodexVersion;
|
|
53
|
+
/**
|
|
54
|
+
* Compare two versions
|
|
55
|
+
* @returns number Negative if v1 < v2, 0 if equal, positive if v1 > v2
|
|
56
|
+
*/
|
|
57
|
+
export declare function compareVersions(v1: CodexVersion, v2: {
|
|
58
|
+
major: number;
|
|
59
|
+
minor: number;
|
|
60
|
+
patch: number;
|
|
61
|
+
}): number;
|
|
62
|
+
/**
|
|
63
|
+
* Check if version meets minimum requirement
|
|
64
|
+
* @param version Current version
|
|
65
|
+
* @param minVersion Minimum required version
|
|
66
|
+
* @returns boolean True if version >= minVersion
|
|
67
|
+
*/
|
|
68
|
+
export declare function meetsMinVersion(version: CodexVersion, minVersion: {
|
|
69
|
+
major: number;
|
|
70
|
+
minor: number;
|
|
71
|
+
patch: number;
|
|
72
|
+
}): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Get installed Codex CLI version (with caching)
|
|
75
|
+
* @param bypassCache If true, forces fresh version check
|
|
76
|
+
* @returns Promise<CodexVersion> Version information
|
|
77
|
+
*/
|
|
78
|
+
export declare function getCodexVersion(bypassCache?: boolean): Promise<CodexVersion>;
|
|
79
|
+
/**
|
|
80
|
+
* Check if specific feature is available in installed version
|
|
81
|
+
* @param featureName Name of feature from FEATURE_VERSIONS
|
|
82
|
+
* @returns Promise<boolean> True if feature is available
|
|
83
|
+
*/
|
|
84
|
+
export declare function isFeatureAvailable(featureName: keyof typeof FEATURE_VERSIONS): Promise<boolean>;
|
|
85
|
+
/**
|
|
86
|
+
* Check if native --search flag is available
|
|
87
|
+
* @returns Promise<boolean> True if --search flag is supported
|
|
88
|
+
*/
|
|
89
|
+
export declare function supportsNativeSearch(): Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Check if --add-dir flag is available
|
|
92
|
+
* @returns Promise<boolean> True if --add-dir flag is supported
|
|
93
|
+
*/
|
|
94
|
+
export declare function supportsAddDir(): Promise<boolean>;
|
|
95
|
+
/**
|
|
96
|
+
* Check if tool_output_token_limit config is available
|
|
97
|
+
* @returns Promise<boolean> True if token limit config is supported
|
|
98
|
+
*/
|
|
99
|
+
export declare function supportsToolTokenLimit(): Promise<boolean>;
|
|
100
|
+
/**
|
|
101
|
+
* Check if GPT-5.1 models are available
|
|
102
|
+
* @returns Promise<boolean> True if GPT-5.1 models are supported
|
|
103
|
+
*/
|
|
104
|
+
export declare function supportsGPT51Models(): Promise<boolean>;
|
|
105
|
+
/**
|
|
106
|
+
* Check if native resume command is available
|
|
107
|
+
* @returns Promise<boolean> True if 'codex resume' is supported
|
|
108
|
+
*/
|
|
109
|
+
export declare function supportsResume(): Promise<boolean>;
|
|
110
|
+
/**
|
|
111
|
+
* Clear version cache (useful for testing)
|
|
112
|
+
*/
|
|
113
|
+
export declare function clearVersionCache(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Get all supported features for current version
|
|
116
|
+
* @returns Promise<Record<string, boolean>> Map of feature names to availability
|
|
117
|
+
*/
|
|
118
|
+
export declare function getSupportedFeatures(): Promise<Record<string, boolean>>;
|
|
119
|
+
/**
|
|
120
|
+
* Log version and feature support information
|
|
121
|
+
*/
|
|
122
|
+
export declare function logVersionInfo(): Promise<void>;
|
|
123
|
+
//# sourceMappingURL=versionDetection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versionDetection.d.ts","sourceRoot":"","sources":["../../src/utils/versionDetection.ts"],"names":[],"mappings":"AAGA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOnB,CAAC;AAOX;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,CAwBhE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,YAAY,EAChB,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClD,MAAM,CAIR;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1D,OAAO,CAOT;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,WAAW,GAAE,OAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CA2CzF;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,OAAO,gBAAgB,GACzC,OAAO,CAAC,OAAO,CAAC,CAKlB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE7D;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAEvD;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE/D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE5D;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAEvD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAS7E;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CASpD"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { Logger } from './logger.js';
|
|
2
|
+
import { executeCommand } from './commandExecutor.js';
|
|
3
|
+
/**
|
|
4
|
+
* Feature availability by version
|
|
5
|
+
*/
|
|
6
|
+
export const FEATURE_VERSIONS = {
|
|
7
|
+
NATIVE_SEARCH: { major: 0, minor: 52, patch: 0 }, // --search flag
|
|
8
|
+
TOOL_TOKEN_LIMIT: { major: 0, minor: 59, patch: 0 }, // tool_output_token_limit
|
|
9
|
+
ADD_DIR: { major: 0, minor: 59, patch: 0 }, // --add-dir flag
|
|
10
|
+
WINDOWS_AGENT: { major: 0, minor: 59, patch: 0 }, // Windows agent mode
|
|
11
|
+
GPT5_1_MODELS: { major: 0, minor: 56, patch: 0 }, // GPT-5.1 model family
|
|
12
|
+
RESUME: { major: 0, minor: 36, patch: 0 }, // codex resume command (v1.4.0+)
|
|
13
|
+
};
|
|
14
|
+
// Version cache for performance optimization
|
|
15
|
+
let cachedVersion = null;
|
|
16
|
+
let cacheTimestamp = 0;
|
|
17
|
+
const VERSION_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
18
|
+
/**
|
|
19
|
+
* Parse version string into structured format
|
|
20
|
+
* @param versionString Raw version string (e.g., "0.59.0", "v0.52.1")
|
|
21
|
+
* @returns CodexVersion object
|
|
22
|
+
*/
|
|
23
|
+
export function parseVersion(versionString) {
|
|
24
|
+
// Remove 'v' prefix if present
|
|
25
|
+
const cleanVersion = versionString.replace(/^v/, '').trim();
|
|
26
|
+
// Match semantic version pattern
|
|
27
|
+
const match = cleanVersion.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
28
|
+
if (!match) {
|
|
29
|
+
return {
|
|
30
|
+
major: 0,
|
|
31
|
+
minor: 0,
|
|
32
|
+
patch: 0,
|
|
33
|
+
raw: versionString,
|
|
34
|
+
isValid: false,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
major: parseInt(match[1], 10),
|
|
39
|
+
minor: parseInt(match[2], 10),
|
|
40
|
+
patch: parseInt(match[3], 10),
|
|
41
|
+
raw: versionString,
|
|
42
|
+
isValid: true,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Compare two versions
|
|
47
|
+
* @returns number Negative if v1 < v2, 0 if equal, positive if v1 > v2
|
|
48
|
+
*/
|
|
49
|
+
export function compareVersions(v1, v2) {
|
|
50
|
+
if (v1.major !== v2.major)
|
|
51
|
+
return v1.major - v2.major;
|
|
52
|
+
if (v1.minor !== v2.minor)
|
|
53
|
+
return v1.minor - v2.minor;
|
|
54
|
+
return v1.patch - v2.patch;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check if version meets minimum requirement
|
|
58
|
+
* @param version Current version
|
|
59
|
+
* @param minVersion Minimum required version
|
|
60
|
+
* @returns boolean True if version >= minVersion
|
|
61
|
+
*/
|
|
62
|
+
export function meetsMinVersion(version, minVersion) {
|
|
63
|
+
if (!version.isValid) {
|
|
64
|
+
Logger.warn('Invalid version format, assuming feature not available');
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return compareVersions(version, minVersion) >= 0;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get installed Codex CLI version (with caching)
|
|
71
|
+
* @param bypassCache If true, forces fresh version check
|
|
72
|
+
* @returns Promise<CodexVersion> Version information
|
|
73
|
+
*/
|
|
74
|
+
export async function getCodexVersion(bypassCache = false) {
|
|
75
|
+
// Return cached version if valid
|
|
76
|
+
if (!bypassCache && cachedVersion && Date.now() - cacheTimestamp < VERSION_CACHE_TTL) {
|
|
77
|
+
Logger.debug(`Using cached Codex version: ${cachedVersion.raw}`);
|
|
78
|
+
return cachedVersion;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const versionOutput = await executeCommand('codex', ['--version'], undefined, 5000);
|
|
82
|
+
// Parse version from output (format: "codex 0.59.0" or just "0.59.0")
|
|
83
|
+
const versionMatch = versionOutput.match(/codex\s+v?(\d+\.\d+\.\d+)/) || versionOutput.match(/v?(\d+\.\d+\.\d+)/);
|
|
84
|
+
if (!versionMatch) {
|
|
85
|
+
Logger.warn('Could not parse Codex version from output:', versionOutput);
|
|
86
|
+
return {
|
|
87
|
+
major: 0,
|
|
88
|
+
minor: 0,
|
|
89
|
+
patch: 0,
|
|
90
|
+
raw: versionOutput,
|
|
91
|
+
isValid: false,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const version = parseVersion(versionMatch[1]);
|
|
95
|
+
Logger.log(`Detected Codex CLI version: ${version.major}.${version.minor}.${version.patch}`);
|
|
96
|
+
// Cache the version
|
|
97
|
+
cachedVersion = version;
|
|
98
|
+
cacheTimestamp = Date.now();
|
|
99
|
+
return version;
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
Logger.error('Failed to get Codex CLI version:', error);
|
|
103
|
+
return {
|
|
104
|
+
major: 0,
|
|
105
|
+
minor: 0,
|
|
106
|
+
patch: 0,
|
|
107
|
+
raw: 'unknown',
|
|
108
|
+
isValid: false,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if specific feature is available in installed version
|
|
114
|
+
* @param featureName Name of feature from FEATURE_VERSIONS
|
|
115
|
+
* @returns Promise<boolean> True if feature is available
|
|
116
|
+
*/
|
|
117
|
+
export async function isFeatureAvailable(featureName) {
|
|
118
|
+
const version = await getCodexVersion();
|
|
119
|
+
const minVersion = FEATURE_VERSIONS[featureName];
|
|
120
|
+
return meetsMinVersion(version, minVersion);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if native --search flag is available
|
|
124
|
+
* @returns Promise<boolean> True if --search flag is supported
|
|
125
|
+
*/
|
|
126
|
+
export async function supportsNativeSearch() {
|
|
127
|
+
return await isFeatureAvailable('NATIVE_SEARCH');
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check if --add-dir flag is available
|
|
131
|
+
* @returns Promise<boolean> True if --add-dir flag is supported
|
|
132
|
+
*/
|
|
133
|
+
export async function supportsAddDir() {
|
|
134
|
+
return await isFeatureAvailable('ADD_DIR');
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if tool_output_token_limit config is available
|
|
138
|
+
* @returns Promise<boolean> True if token limit config is supported
|
|
139
|
+
*/
|
|
140
|
+
export async function supportsToolTokenLimit() {
|
|
141
|
+
return await isFeatureAvailable('TOOL_TOKEN_LIMIT');
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check if GPT-5.1 models are available
|
|
145
|
+
* @returns Promise<boolean> True if GPT-5.1 models are supported
|
|
146
|
+
*/
|
|
147
|
+
export async function supportsGPT51Models() {
|
|
148
|
+
return await isFeatureAvailable('GPT5_1_MODELS');
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check if native resume command is available
|
|
152
|
+
* @returns Promise<boolean> True if 'codex resume' is supported
|
|
153
|
+
*/
|
|
154
|
+
export async function supportsResume() {
|
|
155
|
+
return await isFeatureAvailable('RESUME');
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Clear version cache (useful for testing)
|
|
159
|
+
*/
|
|
160
|
+
export function clearVersionCache() {
|
|
161
|
+
cachedVersion = null;
|
|
162
|
+
cacheTimestamp = 0;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get all supported features for current version
|
|
166
|
+
* @returns Promise<Record<string, boolean>> Map of feature names to availability
|
|
167
|
+
*/
|
|
168
|
+
export async function getSupportedFeatures() {
|
|
169
|
+
const version = await getCodexVersion();
|
|
170
|
+
const features = {};
|
|
171
|
+
for (const [featureName, minVersion] of Object.entries(FEATURE_VERSIONS)) {
|
|
172
|
+
features[featureName] = meetsMinVersion(version, minVersion);
|
|
173
|
+
}
|
|
174
|
+
return features;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Log version and feature support information
|
|
178
|
+
*/
|
|
179
|
+
export async function logVersionInfo() {
|
|
180
|
+
const version = await getCodexVersion();
|
|
181
|
+
const features = await getSupportedFeatures();
|
|
182
|
+
Logger.log(`Codex CLI Version: ${version.raw}`);
|
|
183
|
+
Logger.log('Supported Features:');
|
|
184
|
+
for (const [feature, supported] of Object.entries(features)) {
|
|
185
|
+
Logger.log(` ${feature}: ${supported ? '✓' : '✗'}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=versionDetection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versionDetection.js","sourceRoot":"","sources":["../../src/utils/versionDetection.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,24 +10,29 @@ export declare function findProjectRoot(startPath: string): string;
|
|
|
10
10
|
* Ensures that the provided path points to a directory.
|
|
11
11
|
* If the path is a file, returns its parent directory.
|
|
12
12
|
* If the path doesn't exist or is invalid, returns undefined.
|
|
13
|
+
* Supports both absolute and relative paths.
|
|
13
14
|
*
|
|
14
|
-
* @param path - The file or directory path
|
|
15
|
+
* @param path - The file or directory path (absolute or relative)
|
|
16
|
+
* @param baseDir - Base directory for resolving relative paths (default: process.cwd())
|
|
15
17
|
* @returns The directory path, or undefined if invalid
|
|
16
18
|
*/
|
|
17
|
-
export declare function ensureDirectory(path?: string): string | undefined;
|
|
19
|
+
export declare function ensureDirectory(path?: string, baseDir?: string): string | undefined;
|
|
18
20
|
/**
|
|
19
|
-
* Extract
|
|
20
|
-
* Supports both quoted and unquoted paths.
|
|
21
|
+
* Extract file paths from @path syntax in the prompt.
|
|
22
|
+
* Supports both quoted and unquoted paths, absolute and relative.
|
|
21
23
|
*
|
|
22
24
|
* Examples:
|
|
23
|
-
* - @/absolute/path/to/file.ts
|
|
24
|
-
* -
|
|
25
|
-
* - @
|
|
25
|
+
* - @/absolute/path/to/file.ts (absolute)
|
|
26
|
+
* - @./relative/path/to/file.ts (relative)
|
|
27
|
+
* - @src/file.ts (relative)
|
|
28
|
+
* - @"path with spaces/file.ts" (quoted, can be absolute or relative)
|
|
29
|
+
* - @'path with spaces/file.ts' (quoted, can be absolute or relative)
|
|
26
30
|
*
|
|
27
31
|
* @param prompt - The user prompt that may contain @path references
|
|
32
|
+
* @param baseDir - Base directory for resolving relative paths (default: process.cwd())
|
|
28
33
|
* @returns Array of absolute paths found in the prompt
|
|
29
34
|
*/
|
|
30
|
-
export declare function extractPathFromAtSyntax(prompt: string): string[];
|
|
35
|
+
export declare function extractPathFromAtSyntax(prompt: string, baseDir?: string): string[];
|
|
31
36
|
/**
|
|
32
37
|
* Resolve the working directory using a fallback chain with multiple strategies.
|
|
33
38
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workingDirResolver.d.ts","sourceRoot":"","sources":["../../src/utils/workingDirResolver.ts"],"names":[],"mappings":"AAuBA;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA2CzD;AAED
|
|
1
|
+
{"version":3,"file":"workingDirResolver.d.ts","sourceRoot":"","sources":["../../src/utils/workingDirResolver.ts"],"names":[],"mappings":"AAuBA;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA2CzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,GAAE,MAAsB,GAC9B,MAAM,GAAG,SAAS,CAsCpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,MAAsB,GAAG,MAAM,EAAE,CAoCjG;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,GAAG,SAAS,CAqDrB"}
|