popeye-cli 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.
- package/CHANGELOG.md +55 -0
- package/CONTRIBUTING.md +23 -2
- package/README.md +47 -18
- package/dist/adapters/gemini.js +3 -3
- package/dist/adapters/openai.js +2 -2
- package/dist/adapters/openai.js.map +1 -1
- package/dist/auth/gemini.js +1 -1
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +11 -5
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/commands/resume.d.ts.map +1 -1
- package/dist/cli/commands/resume.js +9 -1
- package/dist/cli/commands/resume.js.map +1 -1
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +29 -3
- package/dist/cli/interactive.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +7 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/index.d.ts +1 -7
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/popeye-md.d.ts +32 -0
- package/dist/config/popeye-md.d.ts.map +1 -0
- package/dist/config/popeye-md.js +111 -0
- package/dist/config/popeye-md.js.map +1 -0
- package/dist/config/schema.d.ts +3 -21
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +21 -8
- package/dist/config/schema.js.map +1 -1
- package/dist/pipeline/bridges/review-bridge.d.ts +70 -0
- package/dist/pipeline/bridges/review-bridge.d.ts.map +1 -0
- package/dist/pipeline/bridges/review-bridge.js +266 -0
- package/dist/pipeline/bridges/review-bridge.js.map +1 -0
- package/dist/pipeline/consensus/consensus-runner.js +3 -3
- package/dist/pipeline/consensus/consensus-runner.js.map +1 -1
- package/dist/pipeline/orchestrator.d.ts +2 -0
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +5 -1
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/phases/implementation.d.ts.map +1 -1
- package/dist/pipeline/phases/implementation.js +5 -2
- package/dist/pipeline/phases/implementation.js.map +1 -1
- package/dist/pipeline/phases/intake.d.ts.map +1 -1
- package/dist/pipeline/phases/intake.js +13 -4
- package/dist/pipeline/phases/intake.js.map +1 -1
- package/dist/pipeline/phases/recovery-loop.d.ts.map +1 -1
- package/dist/pipeline/phases/recovery-loop.js +2 -0
- package/dist/pipeline/phases/recovery-loop.js.map +1 -1
- package/dist/pipeline/type-defs/artifacts.d.ts +5 -0
- package/dist/pipeline/type-defs/artifacts.d.ts.map +1 -1
- package/dist/pipeline/type-defs/artifacts.js +1 -0
- package/dist/pipeline/type-defs/artifacts.js.map +1 -1
- package/dist/pipeline/type-defs/audit.d.ts +3 -0
- package/dist/pipeline/type-defs/audit.d.ts.map +1 -1
- package/dist/pipeline/type-defs/checks.d.ts +1 -0
- package/dist/pipeline/type-defs/checks.d.ts.map +1 -1
- package/dist/pipeline/type-defs/packets.d.ts +15 -0
- package/dist/pipeline/type-defs/packets.d.ts.map +1 -1
- package/dist/pipeline/type-defs/state.d.ts +6 -0
- package/dist/pipeline/type-defs/state.d.ts.map +1 -1
- package/dist/pipeline/type-defs/state.js +2 -0
- package/dist/pipeline/type-defs/state.js.map +1 -1
- package/dist/types/consensus.d.ts +5 -1
- package/dist/types/consensus.d.ts.map +1 -1
- package/dist/types/consensus.js +15 -4
- package/dist/types/consensus.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/project.d.ts +1 -1
- package/dist/types/project.d.ts.map +1 -1
- package/dist/types/project.js +39 -10
- package/dist/types/project.js.map +1 -1
- package/dist/types/workflow.d.ts +1 -7
- package/dist/types/workflow.d.ts.map +1 -1
- package/dist/types/workflow.js +1 -1
- package/dist/types/workflow.js.map +1 -1
- package/dist/upgrade/handlers.js +5 -5
- package/dist/upgrade/handlers.js.map +1 -1
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +18 -14
- package/dist/workflow/index.js.map +1 -1
- package/dist/workflow/website-strategy.js +1 -1
- package/dist/workflow/website-strategy.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/gemini.ts +3 -3
- package/src/adapters/openai.ts +2 -2
- package/src/auth/gemini.ts +1 -1
- package/src/cli/commands/create.ts +12 -6
- package/src/cli/commands/resume.ts +9 -1
- package/src/cli/interactive.ts +32 -3
- package/src/config/defaults.ts +7 -2
- package/src/config/popeye-md.ts +139 -0
- package/src/config/schema.ts +21 -8
- package/src/pipeline/bridges/review-bridge.ts +371 -0
- package/src/pipeline/consensus/consensus-runner.ts +3 -3
- package/src/pipeline/orchestrator.ts +8 -0
- package/src/pipeline/phases/implementation.ts +6 -2
- package/src/pipeline/phases/intake.ts +18 -4
- package/src/pipeline/phases/recovery-loop.ts +2 -0
- package/src/pipeline/type-defs/artifacts.ts +1 -0
- package/src/pipeline/type-defs/state.ts +2 -0
- package/src/types/consensus.ts +16 -4
- package/src/types/index.ts +1 -0
- package/src/types/project.ts +39 -10
- package/src/types/workflow.ts +1 -1
- package/src/upgrade/handlers.ts +5 -5
- package/src/workflow/index.ts +18 -14
- package/src/workflow/website-strategy.ts +1 -1
- package/tests/cli/model-command.test.ts +19 -9
- package/tests/config/config.test.ts +3 -3
- package/tests/config/popeye-md.test.ts +168 -0
- package/tests/pipeline/bridges/review-bridge.test.ts +243 -0
- package/tests/pipeline/session-guidance.test.ts +205 -0
- package/tests/types/consensus.test.ts +1 -1
- package/tests/workflow/pipeline-bootstrap.test.ts +162 -0
package/package.json
CHANGED
package/src/adapters/gemini.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type GeminiModel = string;
|
|
|
16
16
|
* Default Gemini configuration
|
|
17
17
|
*/
|
|
18
18
|
export const DEFAULT_GEMINI_CONFIG = {
|
|
19
|
-
model: 'gemini-2.
|
|
19
|
+
model: 'gemini-2.5-flash' as GeminiModel,
|
|
20
20
|
temperature: 0.3,
|
|
21
21
|
maxTokens: 4096,
|
|
22
22
|
};
|
|
@@ -94,7 +94,7 @@ export async function requestArbitration(
|
|
|
94
94
|
scores: number[]
|
|
95
95
|
): Promise<ArbitrationResult> {
|
|
96
96
|
const client = await createClient();
|
|
97
|
-
const generativeModel = client.getGenerativeModel({ model: 'gemini-2.
|
|
97
|
+
const generativeModel = client.getGenerativeModel({ model: 'gemini-2.5-flash' });
|
|
98
98
|
|
|
99
99
|
const prompt = buildArbitrationPrompt(plan, reviewerFeedback, claudeFeedback, iterations, scores);
|
|
100
100
|
|
|
@@ -370,7 +370,7 @@ function parseList(text: string): string[] {
|
|
|
370
370
|
export async function validateApiKey(): Promise<boolean> {
|
|
371
371
|
try {
|
|
372
372
|
const client = await createClient();
|
|
373
|
-
const model = client.getGenerativeModel({ model: 'gemini-2.
|
|
373
|
+
const model = client.getGenerativeModel({ model: 'gemini-2.5-flash' });
|
|
374
374
|
await model.generateContent('Say "OK" if you can hear me.');
|
|
375
375
|
return true;
|
|
376
376
|
} catch {
|
package/src/adapters/openai.ts
CHANGED
|
@@ -322,7 +322,7 @@ Be specific and actionable. The specification should be detailed enough that a d
|
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
const completion = await client.chat.completions.create({
|
|
325
|
-
model: 'gpt-
|
|
325
|
+
model: 'gpt-4.1',
|
|
326
326
|
messages: [{ role: 'user', content: prompt }],
|
|
327
327
|
temperature: 0.7,
|
|
328
328
|
max_tokens: 4096,
|
|
@@ -360,7 +360,7 @@ Provide:
|
|
|
360
360
|
Format your score as: CONSENSUS: [X]%`;
|
|
361
361
|
|
|
362
362
|
const completion = await client.chat.completions.create({
|
|
363
|
-
model: 'gpt-
|
|
363
|
+
model: 'gpt-4.1',
|
|
364
364
|
messages: [{ role: 'user', content: prompt }],
|
|
365
365
|
temperature: 0.3,
|
|
366
366
|
max_tokens: 2048,
|
package/src/auth/gemini.ts
CHANGED
|
@@ -30,7 +30,7 @@ export interface GeminiAuthStatus {
|
|
|
30
30
|
export async function validateGeminiToken(apiKey: string): Promise<boolean> {
|
|
31
31
|
try {
|
|
32
32
|
const client = new GoogleGenerativeAI(apiKey);
|
|
33
|
-
const model = client.getGenerativeModel({ model: 'gemini-2.
|
|
33
|
+
const model = client.getGenerativeModel({ model: 'gemini-2.5-flash' });
|
|
34
34
|
// Test the key by making a simple request
|
|
35
35
|
await model.generateContent('Say "OK"');
|
|
36
36
|
return true;
|
|
@@ -10,6 +10,7 @@ import { ProjectSpecSchema, type OutputLanguage, type OpenAIModel } from '../../
|
|
|
10
10
|
import { requireAuth } from '../../auth/index.js';
|
|
11
11
|
import { runWorkflow } from '../../workflow/index.js';
|
|
12
12
|
import { generateProject, projectDirExists, cleanupProject } from '../../generators/index.js';
|
|
13
|
+
import { readPopeyeMdConfig } from '../../config/popeye-md.js';
|
|
13
14
|
import {
|
|
14
15
|
printHeader,
|
|
15
16
|
printSection,
|
|
@@ -41,8 +42,8 @@ export function createCreateCommand(): Command {
|
|
|
41
42
|
)
|
|
42
43
|
.option(
|
|
43
44
|
'-m, --model <model>',
|
|
44
|
-
'OpenAI model for consensus (gpt-
|
|
45
|
-
'gpt-
|
|
45
|
+
'OpenAI model for consensus (gpt-4.1, gpt-4o, o3, o4-mini)',
|
|
46
|
+
'gpt-4.1'
|
|
46
47
|
)
|
|
47
48
|
.option(
|
|
48
49
|
'-o, --output <dir>',
|
|
@@ -93,9 +94,8 @@ export function createCreateCommand(): Command {
|
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
const model = options.model as OpenAIModel;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
printError(`Invalid model: ${model}. Use one of: ${validModels.join(', ')}`);
|
|
97
|
+
if (!model || model.trim().length === 0) {
|
|
98
|
+
printError('Model name must not be empty.');
|
|
99
99
|
process.exit(1);
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -173,15 +173,21 @@ export function createCreateCommand(): Command {
|
|
|
173
173
|
succeedSpinner(`Created ${scaffoldResult.filesCreated.length} files`);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
// Run the workflow
|
|
176
|
+
// Run the workflow — merge CLI flags with popeye.md config
|
|
177
177
|
printSection('Workflow Execution');
|
|
178
178
|
|
|
179
|
+
const popeyeConfig = await readPopeyeMdConfig(projectDir);
|
|
179
180
|
const workflowResult = await runWorkflow(spec, {
|
|
180
181
|
projectDir,
|
|
181
182
|
consensusConfig: {
|
|
182
183
|
threshold,
|
|
183
184
|
maxIterations,
|
|
184
185
|
openaiModel: model,
|
|
186
|
+
reviewer: popeyeConfig?.reviewer ?? 'openai',
|
|
187
|
+
arbitrator: popeyeConfig?.arbitrator,
|
|
188
|
+
enableArbitration: popeyeConfig?.enableArbitration ?? false,
|
|
189
|
+
geminiModel: popeyeConfig?.geminiModel,
|
|
190
|
+
grokModel: popeyeConfig?.grokModel,
|
|
185
191
|
},
|
|
186
192
|
onProgress: (phase, message) => {
|
|
187
193
|
handleProgressUpdate(phase, message);
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
resetWorkflow,
|
|
13
13
|
cancelWorkflow,
|
|
14
14
|
} from '../../workflow/index.js';
|
|
15
|
+
import { readPopeyeMdConfig } from '../../config/popeye-md.js';
|
|
15
16
|
import type { WorkflowPhase } from '../../types/workflow.js';
|
|
16
17
|
import {
|
|
17
18
|
printHeader,
|
|
@@ -94,13 +95,20 @@ export function createResumeCommand(): Command {
|
|
|
94
95
|
process.exit(1);
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
// Resume workflow
|
|
98
|
+
// Resume workflow — merge CLI flags with popeye.md config
|
|
98
99
|
printSection('Resuming Workflow');
|
|
99
100
|
|
|
101
|
+
const popeyeConfig = await readPopeyeMdConfig(projectDir);
|
|
100
102
|
const result = await resumeWorkflow(projectDir, {
|
|
101
103
|
consensusConfig: {
|
|
102
104
|
threshold,
|
|
103
105
|
maxIterations,
|
|
106
|
+
reviewer: popeyeConfig?.reviewer ?? 'openai',
|
|
107
|
+
arbitrator: popeyeConfig?.arbitrator,
|
|
108
|
+
enableArbitration: popeyeConfig?.enableArbitration ?? false,
|
|
109
|
+
openaiModel: popeyeConfig?.openaiModel,
|
|
110
|
+
geminiModel: popeyeConfig?.geminiModel,
|
|
111
|
+
grokModel: popeyeConfig?.grokModel,
|
|
104
112
|
},
|
|
105
113
|
maxRetries,
|
|
106
114
|
onProgress: (phase, message) => {
|
package/src/cli/interactive.ts
CHANGED
|
@@ -46,7 +46,7 @@ import { upgradeProject } from '../upgrade/index.js';
|
|
|
46
46
|
import { buildUpgradeContext } from '../upgrade/context.js';
|
|
47
47
|
import { OutputLanguageSchema, KNOWN_OPENAI_MODELS } from '../types/project.js';
|
|
48
48
|
import type { ProjectSpec, OutputLanguage, OpenAIModel } from '../types/project.js';
|
|
49
|
-
import { GeminiModelSchema, KNOWN_GEMINI_MODELS } from '../types/consensus.js';
|
|
49
|
+
import { GeminiModelSchema, KNOWN_GEMINI_MODELS, KNOWN_GROK_MODELS } from '../types/consensus.js';
|
|
50
50
|
import { OpenAIModelSchema } from '../types/project.js';
|
|
51
51
|
import type { AIProvider, GeminiModel, GrokModel } from '../types/consensus.js';
|
|
52
52
|
import {
|
|
@@ -1205,6 +1205,35 @@ async function handleReviewSlashCommand(state: SessionState, args: string[] = []
|
|
|
1205
1205
|
}
|
|
1206
1206
|
|
|
1207
1207
|
try {
|
|
1208
|
+
// Check if project is pipeline-managed — route through bridge
|
|
1209
|
+
const { loadProject } = await import('../state/index.js');
|
|
1210
|
+
const projectState = await loadProject(state.projectDir);
|
|
1211
|
+
const { isPipelineManaged, runReviewBridge } = await import('../pipeline/bridges/review-bridge.js');
|
|
1212
|
+
|
|
1213
|
+
if (isPipelineManaged(projectState)) {
|
|
1214
|
+
printInfo('Pipeline-managed project detected — routing through pipeline bridge');
|
|
1215
|
+
console.log();
|
|
1216
|
+
|
|
1217
|
+
const bridgeResult = await runReviewBridge({
|
|
1218
|
+
projectDir: state.projectDir,
|
|
1219
|
+
depth: options.depth,
|
|
1220
|
+
strict: options.strict,
|
|
1221
|
+
onProgress: (_stage, msg) => printInfo(msg),
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
if (bridgeResult.success) {
|
|
1225
|
+
printSuccess(`Audit score: ${bridgeResult.overallScore}% — ${bridgeResult.recommendation}`);
|
|
1226
|
+
printInfo(`${bridgeResult.findingsCount} finding(s), ${bridgeResult.changeRequestCount} CR(s) created, ${bridgeResult.artifactsCreated} artifact(s) stored`);
|
|
1227
|
+
if (bridgeResult.changeRequestCount > 0) {
|
|
1228
|
+
printInfo('Change Requests filed — run /resume to let the pipeline process them');
|
|
1229
|
+
}
|
|
1230
|
+
} else {
|
|
1231
|
+
printError(bridgeResult.error ?? 'Review bridge failed');
|
|
1232
|
+
}
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
// Non-pipeline project — use legacy audit-mode
|
|
1208
1237
|
const { runReview } = await import('./commands/review.js');
|
|
1209
1238
|
|
|
1210
1239
|
console.log();
|
|
@@ -1484,7 +1513,7 @@ function handleLanguage(args: string[], state: SessionState): void {
|
|
|
1484
1513
|
const KNOWN_MODELS: Record<string, readonly string[]> = {
|
|
1485
1514
|
openai: KNOWN_OPENAI_MODELS,
|
|
1486
1515
|
gemini: KNOWN_GEMINI_MODELS,
|
|
1487
|
-
grok:
|
|
1516
|
+
grok: KNOWN_GROK_MODELS,
|
|
1488
1517
|
};
|
|
1489
1518
|
|
|
1490
1519
|
/**
|
|
@@ -2976,7 +3005,7 @@ export async function startInteractiveMode(): Promise<void> {
|
|
|
2976
3005
|
projectDir: process.cwd(),
|
|
2977
3006
|
language: config.project.default_language,
|
|
2978
3007
|
openaiModel: config.apis.openai.model,
|
|
2979
|
-
geminiModel: 'gemini-2.
|
|
3008
|
+
geminiModel: 'gemini-2.5-flash',
|
|
2980
3009
|
grokModel: config.apis.grok.model,
|
|
2981
3010
|
claudeAuth: false,
|
|
2982
3011
|
openaiAuth: false,
|
package/src/config/defaults.ts
CHANGED
|
@@ -19,10 +19,15 @@ export const DEFAULT_CONFIG: Config = {
|
|
|
19
19
|
},
|
|
20
20
|
apis: {
|
|
21
21
|
openai: {
|
|
22
|
-
model: 'gpt-
|
|
22
|
+
model: 'gpt-4.1',
|
|
23
23
|
temperature: 0.3,
|
|
24
24
|
max_tokens: 4096,
|
|
25
|
-
available_models: [
|
|
25
|
+
available_models: [
|
|
26
|
+
'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano',
|
|
27
|
+
'o3', 'o3-mini', 'o4-mini',
|
|
28
|
+
'gpt-4o', 'gpt-4o-mini',
|
|
29
|
+
'gpt-4-turbo', 'o1-preview', 'o1-mini',
|
|
30
|
+
],
|
|
26
31
|
},
|
|
27
32
|
claude: {
|
|
28
33
|
model: 'claude-sonnet-4-20250514',
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared popeye.md configuration reader.
|
|
3
|
+
* Reads project-local config from the YAML frontmatter in popeye.md.
|
|
4
|
+
* Used by both interactive mode and CLI commands.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { promises as fs } from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { OutputLanguageSchema, type OutputLanguage } from '../types/project.js';
|
|
10
|
+
import type { AIProvider, GeminiModel, GrokModel } from '../types/consensus.js';
|
|
11
|
+
import type { OpenAIModel } from '../types/project.js';
|
|
12
|
+
|
|
13
|
+
// ─── Types ───────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
/** Project-local configuration stored in popeye.md */
|
|
16
|
+
export interface PopeyeMdConfig {
|
|
17
|
+
language: OutputLanguage;
|
|
18
|
+
reviewer: AIProvider;
|
|
19
|
+
arbitrator: AIProvider;
|
|
20
|
+
enableArbitration: boolean;
|
|
21
|
+
created: string;
|
|
22
|
+
lastRun: string;
|
|
23
|
+
projectName?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
notes?: string;
|
|
26
|
+
openaiModel?: OpenAIModel;
|
|
27
|
+
geminiModel?: GeminiModel;
|
|
28
|
+
grokModel?: GrokModel;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ─── Reader ──────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Read popeye.md from a project directory.
|
|
35
|
+
* Parses YAML frontmatter for project configuration.
|
|
36
|
+
*
|
|
37
|
+
* @param projectDir - Absolute path to the project root
|
|
38
|
+
* @returns Parsed config or null if file doesn't exist or is invalid
|
|
39
|
+
*/
|
|
40
|
+
export async function readPopeyeMdConfig(projectDir: string): Promise<PopeyeMdConfig | null> {
|
|
41
|
+
const configPath = path.join(projectDir, 'popeye.md');
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
45
|
+
|
|
46
|
+
// Parse YAML frontmatter
|
|
47
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
48
|
+
if (!frontmatterMatch) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const frontmatter = frontmatterMatch[1];
|
|
53
|
+
const config: Partial<PopeyeMdConfig> = {};
|
|
54
|
+
|
|
55
|
+
// Parse each line of YAML
|
|
56
|
+
for (const line of frontmatter.split('\n')) {
|
|
57
|
+
const match = line.match(/^(\w+):\s*(.+)$/);
|
|
58
|
+
if (match) {
|
|
59
|
+
const [, key, value] = match;
|
|
60
|
+
const cleanValue = value.trim();
|
|
61
|
+
|
|
62
|
+
switch (key) {
|
|
63
|
+
case 'language':
|
|
64
|
+
if (OutputLanguageSchema.safeParse(cleanValue).success) {
|
|
65
|
+
config.language = cleanValue as OutputLanguage;
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
case 'reviewer':
|
|
69
|
+
if (['openai', 'gemini', 'grok'].includes(cleanValue)) {
|
|
70
|
+
config.reviewer = cleanValue as AIProvider;
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
case 'arbitrator':
|
|
74
|
+
if (['openai', 'gemini', 'grok', 'off'].includes(cleanValue)) {
|
|
75
|
+
if (cleanValue === 'off') {
|
|
76
|
+
config.enableArbitration = false;
|
|
77
|
+
} else {
|
|
78
|
+
config.arbitrator = cleanValue as AIProvider;
|
|
79
|
+
config.enableArbitration = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
case 'created':
|
|
84
|
+
config.created = cleanValue;
|
|
85
|
+
break;
|
|
86
|
+
case 'lastRun':
|
|
87
|
+
config.lastRun = cleanValue;
|
|
88
|
+
break;
|
|
89
|
+
case 'projectName':
|
|
90
|
+
config.projectName = cleanValue;
|
|
91
|
+
break;
|
|
92
|
+
case 'openaiModel':
|
|
93
|
+
if (cleanValue.length > 0) {
|
|
94
|
+
config.openaiModel = cleanValue;
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
case 'geminiModel':
|
|
98
|
+
if (cleanValue.length > 0) {
|
|
99
|
+
config.geminiModel = cleanValue;
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
case 'grokModel':
|
|
103
|
+
if (cleanValue.length > 0) {
|
|
104
|
+
config.grokModel = cleanValue;
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Extract notes section if present
|
|
112
|
+
const notesMatch = content.match(/## Notes\n([\s\S]*?)(?=\n## |$)/);
|
|
113
|
+
if (notesMatch) {
|
|
114
|
+
config.notes = notesMatch[1].trim();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Return config only if we have the essential fields
|
|
118
|
+
if (config.language && config.reviewer) {
|
|
119
|
+
return {
|
|
120
|
+
language: config.language,
|
|
121
|
+
reviewer: config.reviewer,
|
|
122
|
+
arbitrator: config.arbitrator || 'gemini',
|
|
123
|
+
enableArbitration: config.enableArbitration ?? true,
|
|
124
|
+
created: config.created || new Date().toISOString(),
|
|
125
|
+
lastRun: config.lastRun || new Date().toISOString(),
|
|
126
|
+
projectName: config.projectName,
|
|
127
|
+
description: config.description,
|
|
128
|
+
notes: config.notes,
|
|
129
|
+
openaiModel: config.openaiModel,
|
|
130
|
+
geminiModel: config.geminiModel,
|
|
131
|
+
grokModel: config.grokModel,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return null;
|
|
136
|
+
} catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
package/src/config/schema.ts
CHANGED
|
@@ -23,14 +23,17 @@ export const ConsensusSettingsSchema = z.object({
|
|
|
23
23
|
* OpenAI API settings schema
|
|
24
24
|
*/
|
|
25
25
|
export const OpenAISettingsSchema = z.object({
|
|
26
|
-
model: z
|
|
27
|
-
.enum(['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview', 'o1-mini'])
|
|
28
|
-
.default('gpt-4o'),
|
|
26
|
+
model: z.string().min(1).default('gpt-4.1'),
|
|
29
27
|
temperature: z.number().min(0).max(2).default(0.3),
|
|
30
28
|
max_tokens: z.number().min(100).max(32000).default(4096),
|
|
31
29
|
available_models: z
|
|
32
30
|
.array(z.string())
|
|
33
|
-
.default([
|
|
31
|
+
.default([
|
|
32
|
+
'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano',
|
|
33
|
+
'o3', 'o3-mini', 'o4-mini',
|
|
34
|
+
'gpt-4o', 'gpt-4o-mini',
|
|
35
|
+
'gpt-4-turbo', 'o1-preview', 'o1-mini',
|
|
36
|
+
]),
|
|
34
37
|
});
|
|
35
38
|
|
|
36
39
|
/**
|
|
@@ -55,10 +58,15 @@ export const GrokSettingsSchema = z.object({
|
|
|
55
58
|
*/
|
|
56
59
|
export const APISettingsSchema = z.object({
|
|
57
60
|
openai: OpenAISettingsSchema.default({
|
|
58
|
-
model: 'gpt-
|
|
61
|
+
model: 'gpt-4.1',
|
|
59
62
|
temperature: 0.3,
|
|
60
63
|
max_tokens: 4096,
|
|
61
|
-
available_models: [
|
|
64
|
+
available_models: [
|
|
65
|
+
'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano',
|
|
66
|
+
'o3', 'o3-mini', 'o4-mini',
|
|
67
|
+
'gpt-4o', 'gpt-4o-mini',
|
|
68
|
+
'gpt-4-turbo', 'o1-preview', 'o1-mini',
|
|
69
|
+
],
|
|
62
70
|
}),
|
|
63
71
|
claude: ClaudeSettingsSchema.default({
|
|
64
72
|
model: 'claude-sonnet-4-20250514',
|
|
@@ -139,10 +147,15 @@ export const ConfigSchema = z.object({
|
|
|
139
147
|
}),
|
|
140
148
|
apis: APISettingsSchema.default({
|
|
141
149
|
openai: {
|
|
142
|
-
model: 'gpt-
|
|
150
|
+
model: 'gpt-4.1',
|
|
143
151
|
temperature: 0.3,
|
|
144
152
|
max_tokens: 4096,
|
|
145
|
-
available_models: [
|
|
153
|
+
available_models: [
|
|
154
|
+
'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano',
|
|
155
|
+
'o3', 'o3-mini', 'o4-mini',
|
|
156
|
+
'gpt-4o', 'gpt-4o-mini',
|
|
157
|
+
'gpt-4-turbo', 'o1-preview', 'o1-mini',
|
|
158
|
+
],
|
|
146
159
|
},
|
|
147
160
|
claude: {
|
|
148
161
|
model: 'claude-sonnet-4-20250514',
|