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.
Files changed (117) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/CONTRIBUTING.md +23 -2
  3. package/README.md +47 -18
  4. package/dist/adapters/gemini.js +3 -3
  5. package/dist/adapters/openai.js +2 -2
  6. package/dist/adapters/openai.js.map +1 -1
  7. package/dist/auth/gemini.js +1 -1
  8. package/dist/cli/commands/create.d.ts.map +1 -1
  9. package/dist/cli/commands/create.js +11 -5
  10. package/dist/cli/commands/create.js.map +1 -1
  11. package/dist/cli/commands/resume.d.ts.map +1 -1
  12. package/dist/cli/commands/resume.js +9 -1
  13. package/dist/cli/commands/resume.js.map +1 -1
  14. package/dist/cli/interactive.d.ts.map +1 -1
  15. package/dist/cli/interactive.js +29 -3
  16. package/dist/cli/interactive.js.map +1 -1
  17. package/dist/config/defaults.d.ts.map +1 -1
  18. package/dist/config/defaults.js +7 -2
  19. package/dist/config/defaults.js.map +1 -1
  20. package/dist/config/index.d.ts +1 -7
  21. package/dist/config/index.d.ts.map +1 -1
  22. package/dist/config/popeye-md.d.ts +32 -0
  23. package/dist/config/popeye-md.d.ts.map +1 -0
  24. package/dist/config/popeye-md.js +111 -0
  25. package/dist/config/popeye-md.js.map +1 -0
  26. package/dist/config/schema.d.ts +3 -21
  27. package/dist/config/schema.d.ts.map +1 -1
  28. package/dist/config/schema.js +21 -8
  29. package/dist/config/schema.js.map +1 -1
  30. package/dist/pipeline/bridges/review-bridge.d.ts +70 -0
  31. package/dist/pipeline/bridges/review-bridge.d.ts.map +1 -0
  32. package/dist/pipeline/bridges/review-bridge.js +266 -0
  33. package/dist/pipeline/bridges/review-bridge.js.map +1 -0
  34. package/dist/pipeline/consensus/consensus-runner.js +3 -3
  35. package/dist/pipeline/consensus/consensus-runner.js.map +1 -1
  36. package/dist/pipeline/orchestrator.d.ts +2 -0
  37. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  38. package/dist/pipeline/orchestrator.js +5 -1
  39. package/dist/pipeline/orchestrator.js.map +1 -1
  40. package/dist/pipeline/phases/implementation.d.ts.map +1 -1
  41. package/dist/pipeline/phases/implementation.js +5 -2
  42. package/dist/pipeline/phases/implementation.js.map +1 -1
  43. package/dist/pipeline/phases/intake.d.ts.map +1 -1
  44. package/dist/pipeline/phases/intake.js +13 -4
  45. package/dist/pipeline/phases/intake.js.map +1 -1
  46. package/dist/pipeline/phases/recovery-loop.d.ts.map +1 -1
  47. package/dist/pipeline/phases/recovery-loop.js +2 -0
  48. package/dist/pipeline/phases/recovery-loop.js.map +1 -1
  49. package/dist/pipeline/type-defs/artifacts.d.ts +5 -0
  50. package/dist/pipeline/type-defs/artifacts.d.ts.map +1 -1
  51. package/dist/pipeline/type-defs/artifacts.js +1 -0
  52. package/dist/pipeline/type-defs/artifacts.js.map +1 -1
  53. package/dist/pipeline/type-defs/audit.d.ts +3 -0
  54. package/dist/pipeline/type-defs/audit.d.ts.map +1 -1
  55. package/dist/pipeline/type-defs/checks.d.ts +1 -0
  56. package/dist/pipeline/type-defs/checks.d.ts.map +1 -1
  57. package/dist/pipeline/type-defs/packets.d.ts +15 -0
  58. package/dist/pipeline/type-defs/packets.d.ts.map +1 -1
  59. package/dist/pipeline/type-defs/state.d.ts +6 -0
  60. package/dist/pipeline/type-defs/state.d.ts.map +1 -1
  61. package/dist/pipeline/type-defs/state.js +2 -0
  62. package/dist/pipeline/type-defs/state.js.map +1 -1
  63. package/dist/types/consensus.d.ts +5 -1
  64. package/dist/types/consensus.d.ts.map +1 -1
  65. package/dist/types/consensus.js +15 -4
  66. package/dist/types/consensus.js.map +1 -1
  67. package/dist/types/index.d.ts +1 -1
  68. package/dist/types/index.d.ts.map +1 -1
  69. package/dist/types/index.js +1 -1
  70. package/dist/types/index.js.map +1 -1
  71. package/dist/types/project.d.ts +1 -1
  72. package/dist/types/project.d.ts.map +1 -1
  73. package/dist/types/project.js +39 -10
  74. package/dist/types/project.js.map +1 -1
  75. package/dist/types/workflow.d.ts +1 -7
  76. package/dist/types/workflow.d.ts.map +1 -1
  77. package/dist/types/workflow.js +1 -1
  78. package/dist/types/workflow.js.map +1 -1
  79. package/dist/upgrade/handlers.js +5 -5
  80. package/dist/upgrade/handlers.js.map +1 -1
  81. package/dist/workflow/index.d.ts.map +1 -1
  82. package/dist/workflow/index.js +18 -14
  83. package/dist/workflow/index.js.map +1 -1
  84. package/dist/workflow/website-strategy.js +1 -1
  85. package/dist/workflow/website-strategy.js.map +1 -1
  86. package/package.json +1 -1
  87. package/src/adapters/gemini.ts +3 -3
  88. package/src/adapters/openai.ts +2 -2
  89. package/src/auth/gemini.ts +1 -1
  90. package/src/cli/commands/create.ts +12 -6
  91. package/src/cli/commands/resume.ts +9 -1
  92. package/src/cli/interactive.ts +32 -3
  93. package/src/config/defaults.ts +7 -2
  94. package/src/config/popeye-md.ts +139 -0
  95. package/src/config/schema.ts +21 -8
  96. package/src/pipeline/bridges/review-bridge.ts +371 -0
  97. package/src/pipeline/consensus/consensus-runner.ts +3 -3
  98. package/src/pipeline/orchestrator.ts +8 -0
  99. package/src/pipeline/phases/implementation.ts +6 -2
  100. package/src/pipeline/phases/intake.ts +18 -4
  101. package/src/pipeline/phases/recovery-loop.ts +2 -0
  102. package/src/pipeline/type-defs/artifacts.ts +1 -0
  103. package/src/pipeline/type-defs/state.ts +2 -0
  104. package/src/types/consensus.ts +16 -4
  105. package/src/types/index.ts +1 -0
  106. package/src/types/project.ts +39 -10
  107. package/src/types/workflow.ts +1 -1
  108. package/src/upgrade/handlers.ts +5 -5
  109. package/src/workflow/index.ts +18 -14
  110. package/src/workflow/website-strategy.ts +1 -1
  111. package/tests/cli/model-command.test.ts +19 -9
  112. package/tests/config/config.test.ts +3 -3
  113. package/tests/config/popeye-md.test.ts +168 -0
  114. package/tests/pipeline/bridges/review-bridge.test.ts +243 -0
  115. package/tests/pipeline/session-guidance.test.ts +205 -0
  116. package/tests/types/consensus.test.ts +1 -1
  117. package/tests/workflow/pipeline-bootstrap.test.ts +162 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "popeye-cli",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Fully autonomous code generation tool powered by Claude CLI and OpenAI consensus",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {
@@ -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.0-flash' as GeminiModel,
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.0-flash' });
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.0-flash' });
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 {
@@ -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-4o',
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-4o',
363
+ model: 'gpt-4.1',
364
364
  messages: [{ role: 'user', content: prompt }],
365
365
  temperature: 0.3,
366
366
  max_tokens: 2048,
@@ -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.0-flash' });
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-4o, gpt-4o-mini, o1-preview)',
45
- 'gpt-4o'
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
- const validModels = ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview', 'o1-mini'];
97
- if (!validModels.includes(model)) {
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) => {
@@ -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: ['grok-3', 'grok-3-mini', 'grok-2'],
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.0-flash',
3008
+ geminiModel: 'gemini-2.5-flash',
2980
3009
  grokModel: config.apis.grok.model,
2981
3010
  claudeAuth: false,
2982
3011
  openaiAuth: false,
@@ -19,10 +19,15 @@ export const DEFAULT_CONFIG: Config = {
19
19
  },
20
20
  apis: {
21
21
  openai: {
22
- model: 'gpt-4o',
22
+ model: 'gpt-4.1',
23
23
  temperature: 0.3,
24
24
  max_tokens: 4096,
25
- available_models: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview', 'o1-mini'],
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
+ }
@@ -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(['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview', 'o1-mini']),
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-4o',
61
+ model: 'gpt-4.1',
59
62
  temperature: 0.3,
60
63
  max_tokens: 4096,
61
- available_models: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview', 'o1-mini'],
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-4o',
150
+ model: 'gpt-4.1',
143
151
  temperature: 0.3,
144
152
  max_tokens: 4096,
145
- available_models: ['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview', 'o1-mini'],
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',