cc-reviewer 2.0.0 → 2.1.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.
@@ -5,7 +5,6 @@
5
5
  * Makes it easy to add new models (Ollama, Azure, etc.) without
6
6
  * changing the core orchestration logic.
7
7
  */
8
- import { ReviewOutput, PeerOutput } from '../schema.js';
9
8
  import { FocusArea, OutputType, ReasoningEffort, ServiceTier, TaskType } from '../types.js';
10
9
  export interface ReviewerCapabilities {
11
10
  /** Display name for this reviewer */
@@ -77,8 +76,7 @@ export interface PeerRequest {
77
76
  }
78
77
  export interface ReviewSuccess {
79
78
  success: true;
80
- output: ReviewOutput;
81
- rawOutput?: string;
79
+ output: string;
82
80
  executionTimeMs: number;
83
81
  }
84
82
  export interface ReviewFailure {
@@ -96,8 +94,7 @@ export interface ReviewError {
96
94
  }
97
95
  export interface PeerSuccess {
98
96
  success: true;
99
- output: PeerOutput;
100
- rawOutput?: string;
97
+ output: string;
101
98
  executionTimeMs: number;
102
99
  }
103
100
  export interface PeerFailure {
@@ -127,7 +124,7 @@ export interface ReviewerAdapter {
127
124
  * Optional: Run peer review of another model's output
128
125
  * Future capability - not currently implemented by any adapter
129
126
  */
130
- runPeerReview?(originalRequest: ReviewRequest, reviewToScore: ReviewOutput): Promise<ReviewResult>;
127
+ runPeerReview?(originalRequest: ReviewRequest, reviewToScore: string): Promise<ReviewResult>;
131
128
  }
132
129
  export declare function registerAdapter(adapter: ReviewerAdapter): void;
133
130
  export declare function getAdapter(id: string): ReviewerAdapter | undefined;
@@ -2,7 +2,8 @@
2
2
  * Codex CLI Adapter
3
3
  *
4
4
  * Implements the ReviewerAdapter interface for OpenAI's Codex CLI.
5
- * Specializes in correctness, edge cases, and performance analysis.
5
+ * Returns raw text no JSON parsing or schema enforcement.
6
+ * CC handles interpretation of the reviewer's response.
6
7
  */
7
8
  import { ReviewerAdapter, ReviewerCapabilities, ReviewRequest, ReviewResult, PeerRequest, PeerResult } from './base.js';
8
9
  export declare class CodexAdapter implements ReviewerAdapter {
@@ -10,12 +11,10 @@ export declare class CodexAdapter implements ReviewerAdapter {
10
11
  getCapabilities(): ReviewerCapabilities;
11
12
  isAvailable(): Promise<boolean>;
12
13
  runReview(request: ReviewRequest): Promise<ReviewResult>;
13
- private runWithRetry;
14
14
  runPeerRequest(request: PeerRequest): Promise<PeerResult>;
15
- private runPeerWithRetry;
16
15
  private runCli;
16
+ private handleException;
17
17
  private categorizeError;
18
18
  private getSuggestion;
19
- private parseRetryAfter;
20
19
  }
21
20
  export declare const codexAdapter: CodexAdapter;
@@ -2,27 +2,23 @@
2
2
  * Codex CLI Adapter
3
3
  *
4
4
  * Implements the ReviewerAdapter interface for OpenAI's Codex CLI.
5
- * Specializes in correctness, edge cases, and performance analysis.
5
+ * Returns raw text no JSON parsing or schema enforcement.
6
+ * CC handles interpretation of the reviewer's response.
6
7
  */
7
8
  import { spawn } from 'child_process';
8
- import { existsSync, writeFileSync, unlinkSync, mkdtempSync } from 'fs';
9
- import { tmpdir } from 'os';
10
- import { join } from 'path';
9
+ import { existsSync } from 'fs';
11
10
  import { registerAdapter, } from './base.js';
12
- import { parseReviewOutput, parseLegacyMarkdownOutput, getReviewOutputJsonSchema, getPeerOutputJsonSchema, parsePeerOutput, isSubstantiveReview } from '../schema.js';
13
11
  import { CliExecutor } from '../executor.js';
14
12
  import { CodexEventDecoder } from '../decoders/index.js';
15
13
  import { buildSimpleHandoff, buildHandoffPrompt, buildPeerPrompt, selectRole, } from '../handoff.js';
16
14
  // =============================================================================
17
15
  // CONFIGURATION
18
16
  // =============================================================================
19
- const COLD_START_TIMEOUT_MS = {
20
- high: 180_000, // 3 min — waiting for first JSONL event
21
- xhigh: 300_000, // 5 min — xhigh thinks longer before first event
17
+ const INACTIVITY_TIMEOUT_MS = {
18
+ high: 180_000, // 3 min — covers reasoning gaps between tool use bursts
19
+ xhigh: 300_000, // 5 min — xhigh has longer reasoning phases
22
20
  };
23
- const STREAMING_TIMEOUT_MS = 90_000; // 90s — if events stop mid-stream
24
21
  const MAX_TIMEOUT_MS = 3_600_000; // 60 min absolute max
25
- const MAX_RETRIES = 2;
26
22
  const MAX_BUFFER_SIZE = 1024 * 1024; // 1MB max buffer
27
23
  // =============================================================================
28
24
  // CODEX ADAPTER
@@ -36,7 +32,7 @@ export class CodexAdapter {
36
32
  strengths: ['correctness', 'performance', 'security', 'testing'],
37
33
  weaknesses: ['documentation'],
38
34
  hasFilesystemAccess: true,
39
- supportsStructuredOutput: true,
35
+ supportsStructuredOutput: false,
40
36
  maxContextTokens: 128000,
41
37
  reasoningLevels: ['high', 'xhigh'],
42
38
  };
@@ -46,175 +42,42 @@ export class CodexAdapter {
46
42
  const proc = spawn('codex', ['--version'], {
47
43
  stdio: ['ignore', 'pipe', 'pipe'],
48
44
  });
49
- proc.on('close', (code) => {
50
- resolve(code === 0);
51
- });
52
- proc.on('error', () => {
53
- resolve(false);
54
- });
55
- // Timeout after 5s
56
- setTimeout(() => {
57
- proc.kill();
58
- resolve(false);
59
- }, 5000);
45
+ proc.on('close', (code) => resolve(code === 0));
46
+ proc.on('error', () => resolve(false));
47
+ setTimeout(() => { proc.kill(); resolve(false); }, 5000);
60
48
  });
61
49
  }
62
50
  async runReview(request) {
63
51
  const startTime = Date.now();
64
- // Validate working directory
65
52
  if (!existsSync(request.workingDir)) {
66
53
  return {
67
54
  success: false,
68
- error: {
69
- type: 'cli_error',
70
- message: `Working directory does not exist: ${request.workingDir}`,
71
- },
55
+ error: { type: 'cli_error', message: `Working directory does not exist: ${request.workingDir}` },
72
56
  suggestion: 'Check that the working directory path is correct',
73
57
  executionTimeMs: Date.now() - startTime,
74
58
  };
75
59
  }
76
- return this.runWithRetry(request, 0, startTime);
77
- }
78
- async runWithRetry(request, attempt, startTime, previousError, previousOutput) {
79
60
  try {
80
- // Build the prompt using handoff protocol
81
61
  const handoff = buildSimpleHandoff(request.workingDir, request.ccOutput, request.analyzedFiles, request.focusAreas, request.customPrompt);
82
- // Select role based on focus areas
83
62
  const role = selectRole(request.focusAreas);
84
- // Build prompt with retry context if needed
85
- // Use 'schema-enforced' since Codex gets --output-schema flag (avoids redundant inline JSON template)
86
- let prompt = buildHandoffPrompt({
87
- handoff,
88
- role,
89
- outputFormat: 'schema-enforced',
90
- });
91
- // Add retry context if this is a retry attempt
92
- if (attempt > 0) {
93
- prompt += `\n\n---\n\n# RETRY ATTEMPT ${attempt + 1}\n\n` +
94
- `Previous output had issues: ${previousError}\n` +
95
- `Please fix these issues and provide valid JSON output.\n` +
96
- (previousOutput ? `\nPrevious output (for reference):\n${previousOutput.slice(0, 500)}...` : '');
97
- }
98
- // Run the CLI
99
- const result = await this.runCli(prompt, request.workingDir, request.reasoningEffort || 'high', getReviewOutputJsonSchema, request.serviceTier);
100
- // Handle CLI errors
63
+ const prompt = buildHandoffPrompt({ handoff, role });
64
+ const result = await this.runCli(prompt, request.workingDir, request.reasoningEffort || 'high', request.serviceTier);
101
65
  if (result.exitCode !== 0) {
102
66
  const error = this.categorizeError(result.stderr);
103
- return {
104
- success: false,
105
- error,
106
- suggestion: this.getSuggestion(error),
107
- rawOutput: result.stderr,
108
- executionTimeMs: Date.now() - startTime,
109
- };
67
+ return { success: false, error, suggestion: this.getSuggestion(error), executionTimeMs: Date.now() - startTime };
110
68
  }
111
- // Handle buffer truncation
112
- if (result.truncated) {
69
+ if (!result.stdout.trim()) {
113
70
  return {
114
71
  success: false,
115
- error: {
116
- type: 'cli_error',
117
- message: 'Output exceeded maximum buffer size (1MB) and was truncated',
118
- },
119
- suggestion: 'Try reviewing a smaller scope with --focus',
72
+ error: { type: 'cli_error', message: 'Codex returned empty response' },
73
+ suggestion: 'Try again or use /gemini instead',
120
74
  executionTimeMs: Date.now() - startTime,
121
75
  };
122
76
  }
123
- // Parse the output
124
- let output = parseReviewOutput(result.stdout);
125
- let usedFallback = false;
126
- // If JSON parsing fails, try legacy markdown
127
- if (!output) {
128
- output = parseLegacyMarkdownOutput(result.stdout, 'codex');
129
- usedFallback = true;
130
- }
131
- // If no valid output, retry or fail
132
- if (!output) {
133
- if (attempt < MAX_RETRIES) {
134
- return this.runWithRetry(request, attempt + 1, startTime, 'Output did not match expected JSON schema', result.stdout);
135
- }
136
- return {
137
- success: false,
138
- error: {
139
- type: 'parse_error',
140
- message: 'Failed to parse reviewer output after retries',
141
- details: { rawOutput: result.stdout.slice(0, 1000) },
142
- },
143
- suggestion: 'The model may not be following the output format. Try a different focus area.',
144
- rawOutput: result.stdout,
145
- executionTimeMs: Date.now() - startTime,
146
- };
147
- }
148
- // Check for empty/minimal output — centralized substance check
149
- if (!isSubstantiveReview(output)) {
150
- if (attempt < MAX_RETRIES) {
151
- console.error(`[codex] Received empty output, retrying...`);
152
- return this.runWithRetry(request, attempt + 1, startTime, usedFallback
153
- ? 'Received markdown output instead of JSON. Please provide valid JSON output.'
154
- : 'Output contained no substantive review content. Please provide findings or analysis.', result.stdout);
155
- }
156
- return {
157
- success: false,
158
- error: {
159
- type: 'parse_error',
160
- message: 'Reviewer returned empty output after retries',
161
- details: { rawOutput: result.stdout.slice(0, 1000) },
162
- },
163
- suggestion: 'The model returned no substantive review. Try a different focus area.',
164
- rawOutput: result.stdout,
165
- executionTimeMs: Date.now() - startTime,
166
- };
167
- }
168
- return {
169
- success: true,
170
- output,
171
- rawOutput: result.stdout,
172
- executionTimeMs: Date.now() - startTime,
173
- };
77
+ return { success: true, output: result.stdout, executionTimeMs: Date.now() - startTime };
174
78
  }
175
79
  catch (error) {
176
- const err = error;
177
- if (err.code === 'ENOENT') {
178
- return {
179
- success: false,
180
- error: {
181
- type: 'cli_not_found',
182
- message: 'Codex CLI not found',
183
- },
184
- suggestion: 'Install with: npm install -g @openai/codex',
185
- executionTimeMs: Date.now() - startTime,
186
- };
187
- }
188
- if (err.message === 'TIMEOUT') {
189
- return {
190
- success: false,
191
- error: {
192
- type: 'timeout',
193
- message: 'No output for 2 minutes - process may be hung',
194
- },
195
- suggestion: 'Try a smaller scope or use --focus',
196
- executionTimeMs: Date.now() - startTime,
197
- };
198
- }
199
- if (err.message === 'MAX_TIMEOUT') {
200
- return {
201
- success: false,
202
- error: {
203
- type: 'timeout',
204
- message: 'Task exceeded 60 minute maximum',
205
- },
206
- suggestion: 'Try a smaller scope',
207
- executionTimeMs: Date.now() - startTime,
208
- };
209
- }
210
- return {
211
- success: false,
212
- error: {
213
- type: 'cli_error',
214
- message: err.message,
215
- },
216
- executionTimeMs: Date.now() - startTime,
217
- };
80
+ return this.handleException(error, startTime);
218
81
  }
219
82
  }
220
83
  async runPeerRequest(request) {
@@ -222,20 +85,13 @@ export class CodexAdapter {
222
85
  if (!existsSync(request.workingDir)) {
223
86
  return {
224
87
  success: false,
225
- error: {
226
- type: 'cli_error',
227
- message: `Working directory does not exist: ${request.workingDir}`,
228
- },
88
+ error: { type: 'cli_error', message: `Working directory does not exist: ${request.workingDir}` },
229
89
  suggestion: 'Check that the working directory path is correct',
230
90
  executionTimeMs: Date.now() - startTime,
231
91
  };
232
92
  }
233
- return this.runPeerWithRetry(request, 0, startTime);
234
- }
235
- async runPeerWithRetry(request, attempt, startTime, previousError, previousOutput) {
236
93
  try {
237
- // Use 'schema-enforced' since Codex gets --output-schema flag (avoids redundant inline JSON template)
238
- let prompt = buildPeerPrompt({
94
+ const prompt = buildPeerPrompt({
239
95
  workingDir: request.workingDir,
240
96
  prompt: request.prompt,
241
97
  taskType: request.taskType,
@@ -243,85 +99,27 @@ export class CodexAdapter {
243
99
  context: request.context,
244
100
  focusAreas: request.focusAreas,
245
101
  customInstructions: request.customPrompt,
246
- outputFormat: 'schema-enforced',
247
102
  });
248
- if (attempt > 0) {
249
- prompt += `\n\n---\n\n# RETRY ATTEMPT ${attempt + 1}\n\n` +
250
- `Previous output had issues: ${previousError}\n` +
251
- `Please fix these issues and provide valid JSON output.\n` +
252
- (previousOutput ? `\nPrevious output (for reference):\n${previousOutput.slice(0, 500)}...` : '');
253
- }
254
- const result = await this.runCli(prompt, request.workingDir, request.reasoningEffort || 'high', getPeerOutputJsonSchema, request.serviceTier);
103
+ const result = await this.runCli(prompt, request.workingDir, request.reasoningEffort || 'high', request.serviceTier);
255
104
  if (result.exitCode !== 0) {
256
105
  const error = this.categorizeError(result.stderr);
257
- return {
258
- success: false,
259
- error,
260
- suggestion: this.getSuggestion(error),
261
- rawOutput: result.stderr,
262
- executionTimeMs: Date.now() - startTime,
263
- };
106
+ return { success: false, error, suggestion: this.getSuggestion(error), executionTimeMs: Date.now() - startTime };
264
107
  }
265
- if (result.truncated) {
108
+ if (!result.stdout.trim()) {
266
109
  return {
267
110
  success: false,
268
- error: { type: 'cli_error', message: 'Output exceeded maximum buffer size (1MB)' },
269
- suggestion: 'Try a more focused request',
111
+ error: { type: 'cli_error', message: 'Codex returned empty response' },
112
+ suggestion: 'Try again or use /ask-gemini instead',
270
113
  executionTimeMs: Date.now() - startTime,
271
114
  };
272
115
  }
273
- const output = parsePeerOutput(result.stdout);
274
- if (!output) {
275
- if (attempt < MAX_RETRIES) {
276
- return this.runPeerWithRetry(request, attempt + 1, startTime, 'Output did not match expected JSON schema', result.stdout);
277
- }
278
- return {
279
- success: false,
280
- error: { type: 'parse_error', message: 'Failed to parse peer output after retries',
281
- details: { rawOutput: result.stdout.slice(0, 1000) } },
282
- suggestion: 'The model may not be following the output format.',
283
- rawOutput: result.stdout,
284
- executionTimeMs: Date.now() - startTime,
285
- };
286
- }
287
- return {
288
- success: true,
289
- output,
290
- rawOutput: result.stdout,
291
- executionTimeMs: Date.now() - startTime,
292
- };
116
+ return { success: true, output: result.stdout, executionTimeMs: Date.now() - startTime };
293
117
  }
294
118
  catch (error) {
295
- const err = error;
296
- if (err.code === 'ENOENT') {
297
- return { success: false, error: { type: 'cli_not_found', message: 'Codex CLI not found' },
298
- suggestion: 'Install with: npm install -g @openai/codex', executionTimeMs: Date.now() - startTime };
299
- }
300
- if (err.message === 'TIMEOUT') {
301
- return { success: false, error: { type: 'timeout', message: 'No output for 2 minutes' },
302
- suggestion: 'Try a simpler request', executionTimeMs: Date.now() - startTime };
303
- }
304
- if (err.message === 'MAX_TIMEOUT') {
305
- return { success: false, error: { type: 'timeout', message: 'Task exceeded 60 minute maximum' },
306
- suggestion: 'Try a smaller scope', executionTimeMs: Date.now() - startTime };
307
- }
308
- return { success: false, error: { type: 'cli_error', message: err.message },
309
- executionTimeMs: Date.now() - startTime };
119
+ return this.handleException(error, startTime);
310
120
  }
311
121
  }
312
- async runCli(prompt, workingDir, reasoningEffort, schemaGetter, serviceTier) {
313
- // Create temp schema file for structured output
314
- let schemaFile = null;
315
- try {
316
- const tempDir = mkdtempSync(join(tmpdir(), 'codex-schema-'));
317
- schemaFile = join(tempDir, 'schema.json');
318
- const schema = schemaGetter();
319
- writeFileSync(schemaFile, JSON.stringify(schema, null, 2), 'utf-8');
320
- }
321
- catch (err) {
322
- console.error('[codex] Warning: Failed to create schema file:', err);
323
- schemaFile = null;
324
- }
122
+ async runCli(prompt, workingDir, reasoningEffort, serviceTier) {
325
123
  const args = [
326
124
  'exec',
327
125
  '--json', // JSONL streaming events
@@ -331,19 +129,15 @@ export class CodexAdapter {
331
129
  '--dangerously-bypass-approvals-and-sandbox',
332
130
  '--skip-git-repo-check',
333
131
  '-C', workingDir,
132
+ '-', // Read prompt from stdin
334
133
  ];
335
134
  if (serviceTier && serviceTier !== 'default') {
336
135
  args.push('-c', `service_tier=${serviceTier}`);
337
136
  }
338
- if (schemaFile) {
339
- args.push('--output-schema', schemaFile);
340
- }
341
- args.push('-'); // Read prompt from stdin
342
137
  const decoder = new CodexEventDecoder();
343
138
  const cliStartTime = Date.now();
344
- let firstEventReceived = false;
345
139
  const tierLabel = serviceTier && serviceTier !== 'default' ? ` [${serviceTier}]` : '';
346
- console.error(`[codex] Running review with ${reasoningEffort} reasoning${tierLabel}...`);
140
+ console.error(`[codex] Running with ${reasoningEffort} reasoning${tierLabel}...`);
347
141
  decoder.onProgress = (eventType, detail) => {
348
142
  const elapsed = Math.round((Date.now() - cliStartTime) / 1000);
349
143
  const detailStr = detail ? ` — ${detail}` : '';
@@ -354,79 +148,70 @@ export class CodexAdapter {
354
148
  args,
355
149
  cwd: workingDir,
356
150
  stdin: prompt,
357
- inactivityTimeoutMs: COLD_START_TIMEOUT_MS[reasoningEffort] || COLD_START_TIMEOUT_MS.high,
151
+ inactivityTimeoutMs: INACTIVITY_TIMEOUT_MS[reasoningEffort] || INACTIVITY_TIMEOUT_MS.high,
358
152
  maxTimeoutMs: MAX_TIMEOUT_MS,
359
153
  maxBufferSize: MAX_BUFFER_SIZE,
360
154
  onLine: (line) => {
361
155
  decoder.processLine(line);
362
- // Phase transition: tighten timeout after first event
363
- if (!firstEventReceived) {
364
- firstEventReceived = true;
365
- executor.setInactivityTimeout(STREAMING_TIMEOUT_MS);
366
- }
367
156
  },
368
157
  });
369
- try {
370
- const result = await executor.run();
371
- const elapsed = Math.round((Date.now() - cliStartTime) / 1000);
372
- console.error(`[codex] complete (${elapsed}s)`);
373
- const finalResponse = decoder.getFinalResponse();
374
- return {
375
- stdout: finalResponse || result.rawStdout,
376
- stderr: result.stderr,
377
- exitCode: result.exitCode,
378
- truncated: result.truncated,
379
- };
158
+ const result = await executor.run();
159
+ const elapsed = Math.round((Date.now() - cliStartTime) / 1000);
160
+ console.error(`[codex] complete (${elapsed}s)`);
161
+ // Check for errors captured from JSONL events
162
+ const decoderError = decoder.getError();
163
+ if (decoderError) {
164
+ return { stdout: '', stderr: decoderError, exitCode: 1, truncated: false };
380
165
  }
381
- finally {
382
- if (schemaFile) {
383
- try {
384
- unlinkSync(schemaFile);
385
- }
386
- catch { /* ignore */ }
387
- }
166
+ const finalResponse = decoder.getFinalResponse();
167
+ if (!finalResponse && decoder.hasNoOutput()) {
168
+ return { stdout: '', stderr: 'No response from Codex — possible rate limit or model rejection', exitCode: 1, truncated: false };
169
+ }
170
+ return {
171
+ stdout: finalResponse || result.rawStdout,
172
+ stderr: result.stderr,
173
+ exitCode: result.exitCode,
174
+ truncated: result.truncated,
175
+ };
176
+ }
177
+ handleException(error, startTime) {
178
+ const err = error;
179
+ if (err.code === 'ENOENT') {
180
+ return { success: false, error: { type: 'cli_not_found', message: 'Codex CLI not found' },
181
+ suggestion: 'Install with: npm install -g @openai/codex', executionTimeMs: Date.now() - startTime };
388
182
  }
183
+ if (err.message === 'TIMEOUT') {
184
+ return { success: false, error: { type: 'timeout', message: 'Codex timed out — no events received' },
185
+ suggestion: 'Try a smaller scope or use /gemini', executionTimeMs: Date.now() - startTime };
186
+ }
187
+ if (err.message === 'MAX_TIMEOUT') {
188
+ return { success: false, error: { type: 'timeout', message: 'Task exceeded 60 minute maximum' },
189
+ suggestion: 'Try a smaller scope', executionTimeMs: Date.now() - startTime };
190
+ }
191
+ return { success: false, error: { type: 'cli_error', message: err.message }, executionTimeMs: Date.now() - startTime };
389
192
  }
390
193
  categorizeError(stderr) {
391
194
  const lower = stderr.toLowerCase();
392
- if (lower.includes('rate limit')) {
393
- return {
394
- type: 'rate_limit',
395
- message: 'Rate limit exceeded',
396
- details: { retryAfterMs: this.parseRetryAfter(stderr) },
397
- };
195
+ if (lower.includes('rate limit') || lower.includes('possible rate limit') || lower.includes('no response from codex')) {
196
+ return { type: 'rate_limit', message: 'Codex rate limit — no tokens available' };
398
197
  }
399
- if (lower.includes('unauthorized') || lower.includes('authentication') ||
400
- stderr.includes('401') || stderr.includes('403')) {
401
- return {
402
- type: 'auth_error',
403
- message: 'Authentication failed',
404
- details: { stderr },
405
- };
198
+ if (lower.includes('unauthorized') || lower.includes('authentication') || stderr.includes('401') || stderr.includes('403')) {
199
+ return { type: 'auth_error', message: 'Authentication failed', details: { stderr } };
406
200
  }
407
- return {
408
- type: 'cli_error',
409
- message: stderr || 'Unknown error',
410
- };
201
+ if (lower.includes('invalid_json_schema') || lower.includes('invalid_request_error')) {
202
+ return { type: 'cli_error', message: `API error: ${stderr.slice(0, 300)}` };
203
+ }
204
+ return { type: 'cli_error', message: stderr || 'Unknown error' };
411
205
  }
412
206
  getSuggestion(error) {
413
207
  switch (error.type) {
414
- case 'rate_limit':
415
- return 'Wait and retry, or use /gemini instead';
416
- case 'auth_error':
417
- return 'Run `codex login` to authenticate';
418
- case 'cli_not_found':
419
- return 'Install with: npm install -g @openai/codex';
420
- default:
421
- return 'Check the error message and try again';
208
+ case 'rate_limit': return 'Wait and retry, or use /gemini instead';
209
+ case 'auth_error': return 'Run `codex login` to authenticate';
210
+ case 'cli_not_found': return 'Install with: npm install -g @openai/codex';
211
+ default: return 'Check the error message and try again';
422
212
  }
423
213
  }
424
- parseRetryAfter(errorMessage) {
425
- const match = errorMessage.match(/retry[- ]?after[:\s]+(\d+)/i);
426
- return match ? parseInt(match[1]) * 1000 : undefined;
427
- }
428
214
  }
429
215
  // Register the adapter
430
216
  registerAdapter(new CodexAdapter());
431
- // Export for direct use
432
217
  export const codexAdapter = new CodexAdapter();
@@ -2,7 +2,8 @@
2
2
  * Gemini CLI Adapter
3
3
  *
4
4
  * Implements the ReviewerAdapter interface for Google's Gemini CLI.
5
- * Specializes in architecture, design patterns, and large-context analysis.
5
+ * Returns raw text no JSON parsing or schema enforcement.
6
+ * CC handles interpretation of the reviewer's response.
6
7
  */
7
8
  import { ReviewerAdapter, ReviewerCapabilities, ReviewRequest, ReviewResult, PeerRequest, PeerResult } from './base.js';
8
9
  export declare class GeminiAdapter implements ReviewerAdapter {
@@ -10,12 +11,10 @@ export declare class GeminiAdapter implements ReviewerAdapter {
10
11
  getCapabilities(): ReviewerCapabilities;
11
12
  isAvailable(): Promise<boolean>;
12
13
  runReview(request: ReviewRequest): Promise<ReviewResult>;
13
- private runWithRetry;
14
14
  runPeerRequest(request: PeerRequest): Promise<PeerResult>;
15
- private runPeerWithRetry;
16
15
  private runCli;
16
+ private handleException;
17
17
  private categorizeError;
18
18
  private getSuggestion;
19
- private parseRetryAfter;
20
19
  }
21
20
  export declare const geminiAdapter: GeminiAdapter;