cc-reviewer 1.0.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/dist/cli/check.d.ts +20 -0
- package/dist/cli/check.js +75 -0
- package/dist/cli/codex.d.ts +11 -0
- package/dist/cli/codex.js +236 -0
- package/dist/cli/gemini.d.ts +12 -0
- package/dist/cli/gemini.js +229 -0
- package/dist/errors.d.ts +46 -0
- package/dist/errors.js +188 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +77 -0
- package/dist/prompt.d.ts +24 -0
- package/dist/prompt.js +134 -0
- package/dist/tools/feedback.d.ts +185 -0
- package/dist/tools/feedback.js +360 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.js +26 -0
- package/package.json +43 -0
package/dist/errors.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Handling for AI Reviewer MCP Server
|
|
3
|
+
*/
|
|
4
|
+
// CLI installation commands
|
|
5
|
+
// Codex: https://developers.openai.com/codex/cli/
|
|
6
|
+
// Gemini: https://github.com/google-gemini/gemini-cli
|
|
7
|
+
const INSTALL_COMMANDS = {
|
|
8
|
+
codex: 'npm install -g @openai/codex-cli',
|
|
9
|
+
gemini: 'npm install -g @google/gemini-cli'
|
|
10
|
+
};
|
|
11
|
+
// Environment variables for API keys
|
|
12
|
+
const ENV_VARS = {
|
|
13
|
+
codex: 'OPENAI_API_KEY',
|
|
14
|
+
gemini: 'GEMINI_API_KEY'
|
|
15
|
+
};
|
|
16
|
+
// Authentication commands
|
|
17
|
+
const AUTH_COMMANDS = {
|
|
18
|
+
codex: 'codex login',
|
|
19
|
+
gemini: 'gemini (follow prompts)'
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Create a CLI not found error
|
|
23
|
+
*/
|
|
24
|
+
export function createCliNotFoundError(cli) {
|
|
25
|
+
return {
|
|
26
|
+
type: 'cli_not_found',
|
|
27
|
+
cli,
|
|
28
|
+
installCmd: INSTALL_COMMANDS[cli]
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Create a timeout error
|
|
33
|
+
*/
|
|
34
|
+
export function createTimeoutError(cli, durationMs) {
|
|
35
|
+
return {
|
|
36
|
+
type: 'timeout',
|
|
37
|
+
cli,
|
|
38
|
+
durationMs
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a rate limit error
|
|
43
|
+
*/
|
|
44
|
+
export function createRateLimitError(cli, retryAfterMs) {
|
|
45
|
+
return {
|
|
46
|
+
type: 'rate_limit',
|
|
47
|
+
cli,
|
|
48
|
+
retryAfterMs
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create an auth error
|
|
53
|
+
*/
|
|
54
|
+
export function createAuthError(cli, message) {
|
|
55
|
+
return {
|
|
56
|
+
type: 'auth_error',
|
|
57
|
+
cli,
|
|
58
|
+
message
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create an invalid response error
|
|
63
|
+
*/
|
|
64
|
+
export function createInvalidResponseError(cli, rawOutput) {
|
|
65
|
+
return {
|
|
66
|
+
type: 'invalid_response',
|
|
67
|
+
cli,
|
|
68
|
+
rawOutput
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a CLI crash error
|
|
73
|
+
*/
|
|
74
|
+
export function createCliError(cli, exitCode, stderr) {
|
|
75
|
+
return {
|
|
76
|
+
type: 'cli_error',
|
|
77
|
+
cli,
|
|
78
|
+
exitCode,
|
|
79
|
+
stderr
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Format an error for user display
|
|
84
|
+
*/
|
|
85
|
+
export function formatErrorForUser(error) {
|
|
86
|
+
const otherCli = error.cli === 'codex' ? 'gemini' : 'codex';
|
|
87
|
+
switch (error.type) {
|
|
88
|
+
case 'cli_not_found':
|
|
89
|
+
return `❌ ${error.cli} CLI not found.
|
|
90
|
+
|
|
91
|
+
Install with: ${error.installCmd}
|
|
92
|
+
|
|
93
|
+
Alternative: Use /${otherCli}-review instead`;
|
|
94
|
+
case 'timeout':
|
|
95
|
+
return `⏱️ ${error.cli} timed out after ${Math.round(error.durationMs / 1000)}s.
|
|
96
|
+
|
|
97
|
+
This might happen with complex reviews. Try:
|
|
98
|
+
• Reviewing a smaller scope
|
|
99
|
+
• Using --focus to narrow the review`;
|
|
100
|
+
case 'rate_limit':
|
|
101
|
+
const retryMsg = error.retryAfterMs
|
|
102
|
+
? `Try again in ${Math.ceil(error.retryAfterMs / 1000)}s`
|
|
103
|
+
: 'Wait a moment and try again';
|
|
104
|
+
return `🚫 ${error.cli} rate limit hit.
|
|
105
|
+
|
|
106
|
+
${retryMsg}
|
|
107
|
+
|
|
108
|
+
Alternative: Use /${otherCli}-review instead`;
|
|
109
|
+
case 'auth_error':
|
|
110
|
+
return `🔐 ${error.cli} authentication failed.
|
|
111
|
+
|
|
112
|
+
${error.message}
|
|
113
|
+
|
|
114
|
+
Check your API key: ${ENV_VARS[error.cli]}
|
|
115
|
+
Run: ${AUTH_COMMANDS[error.cli]}`;
|
|
116
|
+
case 'invalid_response':
|
|
117
|
+
return `⚠️ ${error.cli} returned an unusable response.
|
|
118
|
+
|
|
119
|
+
The output couldn't be parsed as valid feedback.
|
|
120
|
+
Raw output (truncated): ${error.rawOutput.slice(0, 200)}...`;
|
|
121
|
+
case 'cli_error':
|
|
122
|
+
return `❌ ${error.cli} crashed (exit code ${error.exitCode}).
|
|
123
|
+
|
|
124
|
+
${error.stderr}`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Detect error type from CLI output and error messages
|
|
129
|
+
*/
|
|
130
|
+
export function detectErrorType(cli, error, stdout, stderr, exitCode) {
|
|
131
|
+
// CLI not found
|
|
132
|
+
if (error.code === 'ENOENT') {
|
|
133
|
+
return createCliNotFoundError(cli);
|
|
134
|
+
}
|
|
135
|
+
// Rate limit
|
|
136
|
+
if (stderr.toLowerCase().includes('rate limit') ||
|
|
137
|
+
stdout.toLowerCase().includes('rate limit')) {
|
|
138
|
+
const retryAfterMatch = stderr.match(/retry after (\d+)/i);
|
|
139
|
+
const retryAfterMs = retryAfterMatch ? parseInt(retryAfterMatch[1]) * 1000 : undefined;
|
|
140
|
+
return createRateLimitError(cli, retryAfterMs);
|
|
141
|
+
}
|
|
142
|
+
// Auth error
|
|
143
|
+
if (stderr.toLowerCase().includes('unauthorized') ||
|
|
144
|
+
stderr.toLowerCase().includes('authentication') ||
|
|
145
|
+
stderr.toLowerCase().includes('401') ||
|
|
146
|
+
stderr.toLowerCase().includes('403')) {
|
|
147
|
+
return createAuthError(cli, stderr);
|
|
148
|
+
}
|
|
149
|
+
// Generic CLI error
|
|
150
|
+
if (exitCode !== null && exitCode !== 0) {
|
|
151
|
+
return createCliError(cli, exitCode, stderr);
|
|
152
|
+
}
|
|
153
|
+
// Invalid response (fallback)
|
|
154
|
+
return createInvalidResponseError(cli, stdout);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Parse retry-after from error response
|
|
158
|
+
*/
|
|
159
|
+
export function parseRetryAfter(errorMessage) {
|
|
160
|
+
const match = errorMessage.match(/retry[- ]?after[:\s]+(\d+)/i);
|
|
161
|
+
if (match) {
|
|
162
|
+
return parseInt(match[1]) * 1000; // Convert to ms
|
|
163
|
+
}
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Generate suggestion based on error type
|
|
168
|
+
*/
|
|
169
|
+
export function getSuggestion(error) {
|
|
170
|
+
switch (error.type) {
|
|
171
|
+
case 'cli_not_found':
|
|
172
|
+
return `Install ${error.cli} CLI or use the other model`;
|
|
173
|
+
case 'timeout':
|
|
174
|
+
return 'Try reviewing a smaller scope or using --focus';
|
|
175
|
+
case 'rate_limit':
|
|
176
|
+
return error.retryAfterMs
|
|
177
|
+
? `Wait ${Math.ceil(error.retryAfterMs / 1000)}s and retry`
|
|
178
|
+
: 'Wait a moment and retry';
|
|
179
|
+
case 'auth_error':
|
|
180
|
+
return `Check your ${ENV_VARS[error.cli]} environment variable`;
|
|
181
|
+
case 'invalid_response':
|
|
182
|
+
return 'Retry with a more specific focus area';
|
|
183
|
+
case 'cli_error':
|
|
184
|
+
return 'Check the CLI documentation for troubleshooting';
|
|
185
|
+
default:
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* AI Reviewer MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Provides tools for getting second-opinion feedback from external AI CLIs
|
|
6
|
+
* (Codex and Gemini) on Claude Code's work.
|
|
7
|
+
*/
|
|
8
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
9
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
10
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
11
|
+
import { handleCodexFeedback, handleGeminiFeedback, handleMultiFeedback, FeedbackInputSchema, TOOL_DEFINITIONS } from './tools/feedback.js';
|
|
12
|
+
import { logCliStatus } from './cli/check.js';
|
|
13
|
+
// Create the MCP server
|
|
14
|
+
const server = new Server({
|
|
15
|
+
name: 'ai-reviewer',
|
|
16
|
+
version: '1.0.0',
|
|
17
|
+
}, {
|
|
18
|
+
capabilities: {
|
|
19
|
+
tools: {},
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
// Handle tool listing
|
|
23
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
24
|
+
return {
|
|
25
|
+
tools: [
|
|
26
|
+
TOOL_DEFINITIONS.codex_feedback,
|
|
27
|
+
TOOL_DEFINITIONS.gemini_feedback,
|
|
28
|
+
TOOL_DEFINITIONS.multi_feedback,
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
// Handle tool calls
|
|
33
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
34
|
+
const { name, arguments: args } = request.params;
|
|
35
|
+
try {
|
|
36
|
+
// Validate input
|
|
37
|
+
const input = FeedbackInputSchema.parse(args);
|
|
38
|
+
switch (name) {
|
|
39
|
+
case 'codex_feedback':
|
|
40
|
+
return await handleCodexFeedback(input);
|
|
41
|
+
case 'gemini_feedback':
|
|
42
|
+
return await handleGeminiFeedback(input);
|
|
43
|
+
case 'multi_feedback':
|
|
44
|
+
return await handleMultiFeedback(input);
|
|
45
|
+
default:
|
|
46
|
+
return {
|
|
47
|
+
content: [{
|
|
48
|
+
type: 'text',
|
|
49
|
+
text: `Unknown tool: ${name}`
|
|
50
|
+
}],
|
|
51
|
+
isError: true
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
57
|
+
return {
|
|
58
|
+
content: [{
|
|
59
|
+
type: 'text',
|
|
60
|
+
text: `Error: ${errorMessage}`
|
|
61
|
+
}],
|
|
62
|
+
isError: true
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
// Start the server
|
|
67
|
+
async function main() {
|
|
68
|
+
// Log CLI availability status on startup
|
|
69
|
+
await logCliStatus();
|
|
70
|
+
const transport = new StdioServerTransport();
|
|
71
|
+
await server.connect(transport);
|
|
72
|
+
console.error('AI Reviewer MCP Server running on stdio');
|
|
73
|
+
}
|
|
74
|
+
main().catch((error) => {
|
|
75
|
+
console.error('Fatal error:', error);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
});
|
package/dist/prompt.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 7-Section Prompt Builder for External CLI Delegation
|
|
3
|
+
*/
|
|
4
|
+
import { FeedbackRequest, CliType } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Build the 7-section delegation prompt for external CLIs
|
|
7
|
+
*/
|
|
8
|
+
export declare function build7SectionPrompt(request: FeedbackRequest): string;
|
|
9
|
+
/**
|
|
10
|
+
* Build the developer instructions (persona) for a specific CLI
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildDeveloperInstructions(cli: CliType): string;
|
|
13
|
+
/**
|
|
14
|
+
* Build a retry prompt that includes previous attempt information
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildRetryPrompt(request: FeedbackRequest, attemptNumber: number, previousError: string, previousOutput: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Detect output type from CC's output content
|
|
19
|
+
*/
|
|
20
|
+
export declare function detectOutputType(ccOutput: string): 'findings' | 'plan' | 'proposal' | 'analysis';
|
|
21
|
+
/**
|
|
22
|
+
* Validate that external CLI output follows expected structure
|
|
23
|
+
*/
|
|
24
|
+
export declare function isValidFeedbackOutput(output: string): boolean;
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 7-Section Prompt Builder for External CLI Delegation
|
|
3
|
+
*/
|
|
4
|
+
import { REVIEWER_PERSONAS, FOCUS_AREA_DESCRIPTIONS } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Build the 7-section delegation prompt for external CLIs
|
|
7
|
+
*/
|
|
8
|
+
export function build7SectionPrompt(request) {
|
|
9
|
+
const { workingDir, ccOutput, outputType, analyzedFiles = [], focusAreas = [], customPrompt } = request;
|
|
10
|
+
const focusDescription = focusAreas.length > 0
|
|
11
|
+
? focusAreas.map(f => `${f} (${FOCUS_AREA_DESCRIPTIONS[f]})`).join(', ')
|
|
12
|
+
: 'General review';
|
|
13
|
+
const filesAnalyzed = analyzedFiles.length > 0
|
|
14
|
+
? analyzedFiles.join(', ')
|
|
15
|
+
: 'Not specified';
|
|
16
|
+
const customInstructions = customPrompt
|
|
17
|
+
? `\n Special Instructions: ${customPrompt}`
|
|
18
|
+
: '';
|
|
19
|
+
return `TASK: Review CC's ${outputType} and provide structured feedback.
|
|
20
|
+
|
|
21
|
+
EXPECTED OUTCOME: Identify agreements, disagreements, additions, and alternatives.
|
|
22
|
+
|
|
23
|
+
CONTEXT:
|
|
24
|
+
Working Directory: ${workingDir}
|
|
25
|
+
Output Type: ${outputType}
|
|
26
|
+
Files Analyzed: ${filesAnalyzed}
|
|
27
|
+
CC's Output:
|
|
28
|
+
${indent(ccOutput, 4)}
|
|
29
|
+
|
|
30
|
+
CONSTRAINTS:
|
|
31
|
+
Focus Areas: ${focusDescription}
|
|
32
|
+
Advisory mode only (no file changes)
|
|
33
|
+
You have filesystem access${customInstructions}
|
|
34
|
+
|
|
35
|
+
MUST DO:
|
|
36
|
+
• Review CC's findings critically
|
|
37
|
+
• Verify claims by reading files yourself
|
|
38
|
+
• Reference specific file:line when relevant
|
|
39
|
+
• Follow OUTPUT FORMAT exactly
|
|
40
|
+
|
|
41
|
+
MUST NOT DO:
|
|
42
|
+
• Make any file changes
|
|
43
|
+
• Hallucinate file paths
|
|
44
|
+
• Return unstructured text
|
|
45
|
+
|
|
46
|
+
OUTPUT FORMAT:
|
|
47
|
+
## Agreements
|
|
48
|
+
- [Finding]: [Why correct]
|
|
49
|
+
|
|
50
|
+
## Disagreements
|
|
51
|
+
- [Finding]: [Why wrong] - [Correct assessment]
|
|
52
|
+
|
|
53
|
+
## Additions
|
|
54
|
+
- [New finding]: [File:line] - [Impact]
|
|
55
|
+
|
|
56
|
+
## Alternatives
|
|
57
|
+
- [Topic]: [Alternative] - [Tradeoffs]
|
|
58
|
+
|
|
59
|
+
## Risk Assessment
|
|
60
|
+
[Low/Medium/High] - [Reason]`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build the developer instructions (persona) for a specific CLI
|
|
64
|
+
*/
|
|
65
|
+
export function buildDeveloperInstructions(cli) {
|
|
66
|
+
const persona = REVIEWER_PERSONAS[cli];
|
|
67
|
+
return `You are a ${persona.name} code review expert.
|
|
68
|
+
|
|
69
|
+
Focus on: ${persona.focus}
|
|
70
|
+
|
|
71
|
+
Style: ${persona.style}
|
|
72
|
+
|
|
73
|
+
You are reviewing another AI assistant's (Claude Code) work on a codebase.
|
|
74
|
+
Your job is to provide a second opinion - validate their findings, challenge
|
|
75
|
+
incorrect assessments, and add anything they missed.
|
|
76
|
+
|
|
77
|
+
Be specific. Reference file paths and line numbers when relevant.
|
|
78
|
+
Use the structured OUTPUT FORMAT provided in the prompt.`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Build a retry prompt that includes previous attempt information
|
|
82
|
+
*/
|
|
83
|
+
export function buildRetryPrompt(request, attemptNumber, previousError, previousOutput) {
|
|
84
|
+
const basePrompt = build7SectionPrompt(request);
|
|
85
|
+
return `TASK: Review CC's ${request.outputType} (RETRY - attempt ${attemptNumber}/3)
|
|
86
|
+
|
|
87
|
+
PREVIOUS ATTEMPT FAILED:
|
|
88
|
+
Error: ${previousError}
|
|
89
|
+
Raw output (truncated): ${previousOutput.slice(0, 300)}...
|
|
90
|
+
|
|
91
|
+
ADDITIONAL INSTRUCTION: Follow the OUTPUT FORMAT exactly. Each section header
|
|
92
|
+
must start with "## " and contain structured content.
|
|
93
|
+
|
|
94
|
+
${basePrompt.split('\n').slice(1).join('\n')}`;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Helper to indent text
|
|
98
|
+
*/
|
|
99
|
+
function indent(text, spaces) {
|
|
100
|
+
const padding = ' '.repeat(spaces);
|
|
101
|
+
return text.split('\n').map(line => padding + line).join('\n');
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Detect output type from CC's output content
|
|
105
|
+
*/
|
|
106
|
+
export function detectOutputType(ccOutput) {
|
|
107
|
+
if (/\b(vulnerab|injection|XSS|CSRF|SSRF|auth.*issue|security)/i.test(ccOutput)) {
|
|
108
|
+
return 'findings';
|
|
109
|
+
}
|
|
110
|
+
if (/\b(fix|bug|issue|error|proposed fix|solution|patch)/i.test(ccOutput)) {
|
|
111
|
+
return 'proposal';
|
|
112
|
+
}
|
|
113
|
+
if (/\b(architect|design|plan|implement|phase|step \d|structure)/i.test(ccOutput)) {
|
|
114
|
+
return 'plan';
|
|
115
|
+
}
|
|
116
|
+
return 'analysis';
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Validate that external CLI output follows expected structure
|
|
120
|
+
*/
|
|
121
|
+
export function isValidFeedbackOutput(output) {
|
|
122
|
+
const requiredSections = [
|
|
123
|
+
/^## Agreements$/m,
|
|
124
|
+
/^## Disagreements$/m,
|
|
125
|
+
/^## Additions$/m,
|
|
126
|
+
/^## Alternatives$/m,
|
|
127
|
+
/^## Risk Assessment$/m
|
|
128
|
+
];
|
|
129
|
+
// Must have all required sections: Agreements, Disagreements, Additions, Alternatives, Risk Assessment
|
|
130
|
+
const hasRequiredSections = requiredSections.every(regex => regex.test(output));
|
|
131
|
+
// Must not be empty or too short
|
|
132
|
+
const hasContent = output.length > 100;
|
|
133
|
+
return hasRequiredSections && hasContent;
|
|
134
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Implementations for AI Reviewer
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
export declare const FeedbackInputSchema: z.ZodObject<{
|
|
6
|
+
workingDir: z.ZodString;
|
|
7
|
+
ccOutput: z.ZodString;
|
|
8
|
+
outputType: z.ZodEnum<["plan", "findings", "analysis", "proposal"]>;
|
|
9
|
+
analyzedFiles: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
10
|
+
focusAreas: z.ZodOptional<z.ZodArray<z.ZodEnum<["security", "performance", "architecture", "correctness", "maintainability", "scalability", "testing", "documentation"]>, "many">>;
|
|
11
|
+
customPrompt: z.ZodOptional<z.ZodString>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
workingDir: string;
|
|
14
|
+
ccOutput: string;
|
|
15
|
+
outputType: "plan" | "findings" | "analysis" | "proposal";
|
|
16
|
+
analyzedFiles?: string[] | undefined;
|
|
17
|
+
focusAreas?: ("security" | "performance" | "architecture" | "correctness" | "maintainability" | "scalability" | "testing" | "documentation")[] | undefined;
|
|
18
|
+
customPrompt?: string | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
workingDir: string;
|
|
21
|
+
ccOutput: string;
|
|
22
|
+
outputType: "plan" | "findings" | "analysis" | "proposal";
|
|
23
|
+
analyzedFiles?: string[] | undefined;
|
|
24
|
+
focusAreas?: ("security" | "performance" | "architecture" | "correctness" | "maintainability" | "scalability" | "testing" | "documentation")[] | undefined;
|
|
25
|
+
customPrompt?: string | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
export type FeedbackInput = z.infer<typeof FeedbackInputSchema>;
|
|
28
|
+
/**
|
|
29
|
+
* Codex feedback tool handler
|
|
30
|
+
*/
|
|
31
|
+
export declare function handleCodexFeedback(input: FeedbackInput): Promise<{
|
|
32
|
+
content: Array<{
|
|
33
|
+
type: 'text';
|
|
34
|
+
text: string;
|
|
35
|
+
}>;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Gemini feedback tool handler
|
|
39
|
+
*/
|
|
40
|
+
export declare function handleGeminiFeedback(input: FeedbackInput): Promise<{
|
|
41
|
+
content: Array<{
|
|
42
|
+
type: 'text';
|
|
43
|
+
text: string;
|
|
44
|
+
}>;
|
|
45
|
+
}>;
|
|
46
|
+
/**
|
|
47
|
+
* Multi-model feedback tool handler (parallel execution)
|
|
48
|
+
*/
|
|
49
|
+
export declare function handleMultiFeedback(input: FeedbackInput): Promise<{
|
|
50
|
+
content: Array<{
|
|
51
|
+
type: 'text';
|
|
52
|
+
text: string;
|
|
53
|
+
}>;
|
|
54
|
+
}>;
|
|
55
|
+
/**
|
|
56
|
+
* Tool definitions for MCP registration
|
|
57
|
+
*/
|
|
58
|
+
export declare const TOOL_DEFINITIONS: {
|
|
59
|
+
codex_feedback: {
|
|
60
|
+
name: string;
|
|
61
|
+
description: string;
|
|
62
|
+
inputSchema: {
|
|
63
|
+
type: string;
|
|
64
|
+
properties: {
|
|
65
|
+
workingDir: {
|
|
66
|
+
type: string;
|
|
67
|
+
description: string;
|
|
68
|
+
};
|
|
69
|
+
ccOutput: {
|
|
70
|
+
type: string;
|
|
71
|
+
description: string;
|
|
72
|
+
};
|
|
73
|
+
outputType: {
|
|
74
|
+
type: string;
|
|
75
|
+
enum: string[];
|
|
76
|
+
description: string;
|
|
77
|
+
};
|
|
78
|
+
analyzedFiles: {
|
|
79
|
+
type: string;
|
|
80
|
+
items: {
|
|
81
|
+
type: string;
|
|
82
|
+
};
|
|
83
|
+
description: string;
|
|
84
|
+
};
|
|
85
|
+
focusAreas: {
|
|
86
|
+
type: string;
|
|
87
|
+
items: {
|
|
88
|
+
type: string;
|
|
89
|
+
enum: string[];
|
|
90
|
+
};
|
|
91
|
+
description: string;
|
|
92
|
+
};
|
|
93
|
+
customPrompt: {
|
|
94
|
+
type: string;
|
|
95
|
+
description: string;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
required: string[];
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
gemini_feedback: {
|
|
102
|
+
name: string;
|
|
103
|
+
description: string;
|
|
104
|
+
inputSchema: {
|
|
105
|
+
type: string;
|
|
106
|
+
properties: {
|
|
107
|
+
workingDir: {
|
|
108
|
+
type: string;
|
|
109
|
+
description: string;
|
|
110
|
+
};
|
|
111
|
+
ccOutput: {
|
|
112
|
+
type: string;
|
|
113
|
+
description: string;
|
|
114
|
+
};
|
|
115
|
+
outputType: {
|
|
116
|
+
type: string;
|
|
117
|
+
enum: string[];
|
|
118
|
+
description: string;
|
|
119
|
+
};
|
|
120
|
+
analyzedFiles: {
|
|
121
|
+
type: string;
|
|
122
|
+
items: {
|
|
123
|
+
type: string;
|
|
124
|
+
};
|
|
125
|
+
description: string;
|
|
126
|
+
};
|
|
127
|
+
focusAreas: {
|
|
128
|
+
type: string;
|
|
129
|
+
items: {
|
|
130
|
+
type: string;
|
|
131
|
+
enum: string[];
|
|
132
|
+
};
|
|
133
|
+
description: string;
|
|
134
|
+
};
|
|
135
|
+
customPrompt: {
|
|
136
|
+
type: string;
|
|
137
|
+
description: string;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
required: string[];
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
multi_feedback: {
|
|
144
|
+
name: string;
|
|
145
|
+
description: string;
|
|
146
|
+
inputSchema: {
|
|
147
|
+
type: string;
|
|
148
|
+
properties: {
|
|
149
|
+
workingDir: {
|
|
150
|
+
type: string;
|
|
151
|
+
description: string;
|
|
152
|
+
};
|
|
153
|
+
ccOutput: {
|
|
154
|
+
type: string;
|
|
155
|
+
description: string;
|
|
156
|
+
};
|
|
157
|
+
outputType: {
|
|
158
|
+
type: string;
|
|
159
|
+
enum: string[];
|
|
160
|
+
description: string;
|
|
161
|
+
};
|
|
162
|
+
analyzedFiles: {
|
|
163
|
+
type: string;
|
|
164
|
+
items: {
|
|
165
|
+
type: string;
|
|
166
|
+
};
|
|
167
|
+
description: string;
|
|
168
|
+
};
|
|
169
|
+
focusAreas: {
|
|
170
|
+
type: string;
|
|
171
|
+
items: {
|
|
172
|
+
type: string;
|
|
173
|
+
enum: string[];
|
|
174
|
+
};
|
|
175
|
+
description: string;
|
|
176
|
+
};
|
|
177
|
+
customPrompt: {
|
|
178
|
+
type: string;
|
|
179
|
+
description: string;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
required: string[];
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
};
|