popeye-cli 1.1.0 → 1.2.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/.env.example +24 -1
- package/CONTRIBUTING.md +275 -0
- package/OPEN_SOURCE_MANIFESTO.md +172 -0
- package/README.md +340 -27
- package/dist/adapters/claude.d.ts +5 -2
- package/dist/adapters/claude.d.ts.map +1 -1
- package/dist/adapters/claude.js +239 -19
- package/dist/adapters/claude.js.map +1 -1
- package/dist/adapters/grok.d.ts +73 -0
- package/dist/adapters/grok.d.ts.map +1 -0
- package/dist/adapters/grok.js +430 -0
- package/dist/adapters/grok.js.map +1 -0
- package/dist/adapters/openai.d.ts +1 -1
- package/dist/adapters/openai.d.ts.map +1 -1
- package/dist/adapters/openai.js +6 -1
- package/dist/adapters/openai.js.map +1 -1
- package/dist/auth/grok.d.ts +73 -0
- package/dist/auth/grok.d.ts.map +1 -0
- package/dist/auth/grok.js +211 -0
- package/dist/auth/grok.js.map +1 -0
- package/dist/auth/index.d.ts +9 -6
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +23 -6
- package/dist/auth/index.js.map +1 -1
- package/dist/cli/commands/auth.d.ts +1 -1
- package/dist/cli/commands/auth.d.ts.map +1 -1
- package/dist/cli/commands/auth.js +79 -8
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/create.d.ts.map +1 -1
- package/dist/cli/commands/create.js +15 -4
- package/dist/cli/commands/create.js.map +1 -1
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +374 -35
- package/dist/cli/interactive.js.map +1 -1
- package/dist/config/defaults.d.ts +3 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +9 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +16 -3
- package/dist/config/index.js.map +1 -1
- package/dist/config/schema.d.ts +27 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +24 -3
- package/dist/config/schema.js.map +1 -1
- package/dist/generators/fullstack.d.ts +32 -0
- package/dist/generators/fullstack.d.ts.map +1 -0
- package/dist/generators/fullstack.js +497 -0
- package/dist/generators/fullstack.js.map +1 -0
- package/dist/generators/index.d.ts +4 -3
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +15 -1
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/python.d.ts +17 -1
- package/dist/generators/python.d.ts.map +1 -1
- package/dist/generators/python.js +34 -21
- package/dist/generators/python.js.map +1 -1
- package/dist/generators/templates/fullstack.d.ts +113 -0
- package/dist/generators/templates/fullstack.d.ts.map +1 -0
- package/dist/generators/templates/fullstack.js +1004 -0
- package/dist/generators/templates/fullstack.js.map +1 -0
- package/dist/generators/typescript.d.ts +19 -1
- package/dist/generators/typescript.d.ts.map +1 -1
- package/dist/generators/typescript.js +37 -21
- package/dist/generators/typescript.js.map +1 -1
- package/dist/types/cli.d.ts +4 -0
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/cli.js.map +1 -1
- package/dist/types/consensus.d.ts +119 -2
- package/dist/types/consensus.d.ts.map +1 -1
- package/dist/types/consensus.js +12 -1
- package/dist/types/consensus.js.map +1 -1
- package/dist/types/project.d.ts +76 -0
- package/dist/types/project.d.ts.map +1 -1
- package/dist/types/project.js +1 -1
- package/dist/types/project.js.map +1 -1
- package/dist/types/workflow.d.ts +162 -16
- package/dist/types/workflow.d.ts.map +1 -1
- package/dist/types/workflow.js +24 -1
- package/dist/types/workflow.js.map +1 -1
- package/dist/workflow/consensus.d.ts +29 -3
- package/dist/workflow/consensus.d.ts.map +1 -1
- package/dist/workflow/consensus.js +334 -27
- package/dist/workflow/consensus.js.map +1 -1
- package/dist/workflow/milestone-workflow.js +2 -2
- package/dist/workflow/milestone-workflow.js.map +1 -1
- package/dist/workflow/plan-mode.d.ts +66 -2
- package/dist/workflow/plan-mode.d.ts.map +1 -1
- package/dist/workflow/plan-mode.js +187 -11
- package/dist/workflow/plan-mode.js.map +1 -1
- package/dist/workflow/plan-storage.d.ts +252 -8
- package/dist/workflow/plan-storage.d.ts.map +1 -1
- package/dist/workflow/plan-storage.js +580 -33
- package/dist/workflow/plan-storage.js.map +1 -1
- package/dist/workflow/project-verification.js +1 -1
- package/dist/workflow/project-verification.js.map +1 -1
- package/dist/workflow/task-workflow.d.ts.map +1 -1
- package/dist/workflow/task-workflow.js +4 -1
- package/dist/workflow/task-workflow.js.map +1 -1
- package/dist/workflow/test-runner.d.ts +8 -0
- package/dist/workflow/test-runner.d.ts.map +1 -1
- package/dist/workflow/test-runner.js +92 -0
- package/dist/workflow/test-runner.js.map +1 -1
- package/dist/workflow/workspace-manager.d.ts +342 -0
- package/dist/workflow/workspace-manager.d.ts.map +1 -0
- package/dist/workflow/workspace-manager.js +733 -0
- package/dist/workflow/workspace-manager.js.map +1 -0
- package/package.json +1 -1
- package/src/adapters/claude.ts +263 -24
- package/src/adapters/grok.ts +492 -0
- package/src/adapters/openai.ts +8 -2
- package/src/auth/grok.ts +255 -0
- package/src/auth/index.ts +27 -9
- package/src/cli/commands/auth.ts +89 -10
- package/src/cli/commands/create.ts +13 -4
- package/src/cli/interactive.ts +424 -34
- package/src/config/defaults.ts +9 -0
- package/src/config/index.ts +17 -3
- package/src/config/schema.ts +25 -3
- package/src/generators/fullstack.ts +551 -0
- package/src/generators/index.ts +25 -1
- package/src/generators/python.ts +65 -21
- package/src/generators/templates/fullstack.ts +1047 -0
- package/src/generators/typescript.ts +69 -21
- package/src/types/cli.ts +4 -0
- package/src/types/consensus.ts +135 -3
- package/src/types/project.ts +82 -1
- package/src/types/workflow.ts +56 -2
- package/src/workflow/consensus.ts +461 -31
- package/src/workflow/milestone-workflow.ts +2 -2
- package/src/workflow/plan-mode.ts +238 -10
- package/src/workflow/plan-storage.ts +835 -35
- package/src/workflow/project-verification.ts +1 -1
- package/src/workflow/task-workflow.ts +4 -1
- package/src/workflow/test-runner.ts +110 -0
- package/src/workflow/workspace-manager.ts +912 -0
|
@@ -289,7 +289,7 @@ async function verifyRouteCompleteness(projectDir: string): Promise<Verification
|
|
|
289
289
|
|
|
290
290
|
// Check all page components
|
|
291
291
|
const pageFiles = await findFiles(path.join(frontendDir, 'src', 'pages'), /\.tsx$/);
|
|
292
|
-
|
|
292
|
+
const incompletePages: string[] = [];
|
|
293
293
|
|
|
294
294
|
for (const file of pageFiles) {
|
|
295
295
|
const content = await readFile(file);
|
|
@@ -90,7 +90,7 @@ Please provide:
|
|
|
90
90
|
Be specific and actionable. This plan will be reviewed for consensus before implementation.
|
|
91
91
|
`.trim();
|
|
92
92
|
|
|
93
|
-
const result = await claudeCreatePlan(prompt, context, onProgress);
|
|
93
|
+
const result = await claudeCreatePlan(prompt, context, state.language, onProgress);
|
|
94
94
|
|
|
95
95
|
if (!result.success) {
|
|
96
96
|
throw new Error(`Failed to create task plan: ${result.error}`);
|
|
@@ -329,6 +329,7 @@ Task: ${task.name}
|
|
|
329
329
|
taskId: task.id,
|
|
330
330
|
taskName: task.name,
|
|
331
331
|
parallelReviews: true,
|
|
332
|
+
isFullstack: state.language === 'fullstack',
|
|
332
333
|
onIteration: (iteration, result) => {
|
|
333
334
|
onProgress?.('task-consensus', `Iteration ${iteration}: ${result.score}%`);
|
|
334
335
|
},
|
|
@@ -343,6 +344,8 @@ Task: ${task.name}
|
|
|
343
344
|
{
|
|
344
345
|
projectDir,
|
|
345
346
|
config: consensusConfig,
|
|
347
|
+
isFullstack: state.language === 'fullstack',
|
|
348
|
+
language: state.language,
|
|
346
349
|
onIteration: (iteration, result) => {
|
|
347
350
|
onProgress?.('task-consensus', `Iteration ${iteration}: ${result.score}%`);
|
|
348
351
|
},
|
|
@@ -37,6 +37,7 @@ export interface TestConfig {
|
|
|
37
37
|
export const DEFAULT_TEST_COMMANDS: Record<OutputLanguage, string> = {
|
|
38
38
|
python: 'python -m pytest tests/ -v',
|
|
39
39
|
typescript: 'npm test',
|
|
40
|
+
fullstack: 'npm run test:all', // Runs both frontend and backend tests via workspace.json
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
/**
|
|
@@ -78,6 +79,12 @@ export function buildTestCommand(config: TestConfig): string {
|
|
|
78
79
|
|
|
79
80
|
return parts.join(' ');
|
|
80
81
|
}
|
|
82
|
+
|
|
83
|
+
case 'fullstack': {
|
|
84
|
+
// Fullstack projects use workspace.json commands
|
|
85
|
+
// Default to running both frontend and backend tests
|
|
86
|
+
return 'npm run test:all';
|
|
87
|
+
}
|
|
81
88
|
}
|
|
82
89
|
}
|
|
83
90
|
|
|
@@ -137,6 +144,38 @@ export function parseTestOutput(output: string, language: OutputLanguage): TestR
|
|
|
137
144
|
}
|
|
138
145
|
break;
|
|
139
146
|
}
|
|
147
|
+
|
|
148
|
+
case 'fullstack': {
|
|
149
|
+
// Fullstack combines pytest and jest output
|
|
150
|
+
// Parse both formats
|
|
151
|
+
const pytestMatch = output.match(/(\d+)\s+passed/);
|
|
152
|
+
const pytestFailedMatch = output.match(/(\d+)\s+failed/);
|
|
153
|
+
const jestMatch = output.match(/Tests:\s*(?:(\d+)\s+failed,\s*)?(\d+)\s+passed,\s*(\d+)\s+total/);
|
|
154
|
+
|
|
155
|
+
if (pytestMatch) {
|
|
156
|
+
passed += parseInt(pytestMatch[1], 10);
|
|
157
|
+
}
|
|
158
|
+
if (pytestFailedMatch) {
|
|
159
|
+
failed += parseInt(pytestFailedMatch[1], 10);
|
|
160
|
+
}
|
|
161
|
+
if (jestMatch) {
|
|
162
|
+
failed += jestMatch[1] ? parseInt(jestMatch[1], 10) : 0;
|
|
163
|
+
passed += parseInt(jestMatch[2], 10);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
total = passed + failed;
|
|
167
|
+
|
|
168
|
+
// Extract failed test names from both pytest and jest
|
|
169
|
+
const pytestFailedMatches = output.matchAll(/FAILED\s+([^\s]+)/g);
|
|
170
|
+
for (const match of pytestFailedMatches) {
|
|
171
|
+
failedTests.push(match[1]);
|
|
172
|
+
}
|
|
173
|
+
const jestFailedMatches = output.matchAll(/✕\s+(.+)/g);
|
|
174
|
+
for (const match of jestFailedMatches) {
|
|
175
|
+
failedTests.push(match[1].trim());
|
|
176
|
+
}
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
140
179
|
}
|
|
141
180
|
|
|
142
181
|
// Success if no failures - treat "no tests found" as success (not a failure)
|
|
@@ -241,6 +280,48 @@ export async function runTypeScriptTests(
|
|
|
241
280
|
}
|
|
242
281
|
}
|
|
243
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Run fullstack tests (both frontend and backend)
|
|
285
|
+
*
|
|
286
|
+
* @param cwd - Working directory
|
|
287
|
+
* @param config - Test configuration
|
|
288
|
+
* @returns Combined test result
|
|
289
|
+
*/
|
|
290
|
+
export async function runFullstackTests(
|
|
291
|
+
cwd: string,
|
|
292
|
+
config: Partial<TestConfig> = {}
|
|
293
|
+
): Promise<TestResult> {
|
|
294
|
+
const path = await import('node:path');
|
|
295
|
+
|
|
296
|
+
// Run backend tests first
|
|
297
|
+
const backendCwd = path.join(cwd, 'apps', 'backend');
|
|
298
|
+
const backendResult = await runPythonTests(backendCwd, config);
|
|
299
|
+
|
|
300
|
+
// Run frontend tests
|
|
301
|
+
const frontendCwd = path.join(cwd, 'apps', 'frontend');
|
|
302
|
+
const frontendResult = await runTypeScriptTests(frontendCwd, config);
|
|
303
|
+
|
|
304
|
+
// Combine results
|
|
305
|
+
const combinedOutput = `=== Backend Tests ===\n${backendResult.output}\n\n=== Frontend Tests ===\n${frontendResult.output}`;
|
|
306
|
+
|
|
307
|
+
return {
|
|
308
|
+
success: backendResult.success && frontendResult.success,
|
|
309
|
+
passed: backendResult.passed + frontendResult.passed,
|
|
310
|
+
failed: backendResult.failed + frontendResult.failed,
|
|
311
|
+
total: backendResult.total + frontendResult.total,
|
|
312
|
+
output: combinedOutput,
|
|
313
|
+
failedTests: [
|
|
314
|
+
...(backendResult.failedTests || []).map((t) => `[backend] ${t}`),
|
|
315
|
+
...(frontendResult.failedTests || []).map((t) => `[frontend] ${t}`),
|
|
316
|
+
].length > 0 ? [
|
|
317
|
+
...(backendResult.failedTests || []).map((t) => `[backend] ${t}`),
|
|
318
|
+
...(frontendResult.failedTests || []).map((t) => `[frontend] ${t}`),
|
|
319
|
+
] : undefined,
|
|
320
|
+
error: backendResult.error || frontendResult.error,
|
|
321
|
+
noTestsFound: backendResult.noTestsFound && frontendResult.noTestsFound,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
244
325
|
/**
|
|
245
326
|
* Run tests for a project
|
|
246
327
|
*
|
|
@@ -259,6 +340,8 @@ export async function runTests(
|
|
|
259
340
|
return runPythonTests(cwd, config);
|
|
260
341
|
case 'typescript':
|
|
261
342
|
return runTypeScriptTests(cwd, config);
|
|
343
|
+
case 'fullstack':
|
|
344
|
+
return runFullstackTests(cwd, config);
|
|
262
345
|
}
|
|
263
346
|
}
|
|
264
347
|
|
|
@@ -318,6 +401,33 @@ export async function testsExist(
|
|
|
318
401
|
}
|
|
319
402
|
}
|
|
320
403
|
}
|
|
404
|
+
|
|
405
|
+
case 'fullstack': {
|
|
406
|
+
// Check for tests in both frontend and backend
|
|
407
|
+
const backendTestsDir = path.join(cwd, 'apps', 'backend', 'tests');
|
|
408
|
+
const frontendTestsDir = path.join(cwd, 'apps', 'frontend', 'src');
|
|
409
|
+
|
|
410
|
+
let hasBackendTests = false;
|
|
411
|
+
let hasFrontendTests = false;
|
|
412
|
+
|
|
413
|
+
try {
|
|
414
|
+
await fs.access(backendTestsDir);
|
|
415
|
+
hasBackendTests = true;
|
|
416
|
+
} catch {
|
|
417
|
+
// No backend tests directory
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
const files = await fs.readdir(frontendTestsDir, { recursive: true });
|
|
422
|
+
hasFrontendTests = files.some(
|
|
423
|
+
(f) => f.toString().endsWith('.test.ts') || f.toString().endsWith('.spec.ts')
|
|
424
|
+
);
|
|
425
|
+
} catch {
|
|
426
|
+
// No frontend test files
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return hasBackendTests || hasFrontendTests;
|
|
430
|
+
}
|
|
321
431
|
}
|
|
322
432
|
} catch {
|
|
323
433
|
return false;
|