Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35
feat: Doctor report pipeline (i18n keys + actions, non-breaking)#89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
a32b3a02e739abe2d4552f335d022531c3ed4e3a646a1961bf0ee771902867cfd6d957ce1a2fe212bb530b74785349c8d7795e124File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -75,6 +75,7 @@ const { | ||
| executeTaskPlan | ||
| } = require('./lib/task-orchestrator'); | ||
| const { buildConfigHealthReport: buildConfigHealthReportCore } = require('./cli/config-health'); | ||
| const { buildDoctorReport, buildDoctorLegacyPayload, renderDoctorMarkdown } = require('./cli/doctor-core'); | ||
| const { | ||
| createAuthProfileController | ||
| } = require('./cli/auth-profiles'); | ||
| @@ -6414,6 +6415,113 @@ function cmdStatus() { | ||
| console.log(); | ||
| } | ||
| function parseDoctorCommandArgs(argv = []) { | ||
| const options = { | ||
| format: 'json', | ||
| lang: '', | ||
| range: '7d', | ||
| targetApp: 'codex', | ||
| remote: true, | ||
| includeInstall: true, | ||
| includeUsage: true, | ||
| includeTasks: true, | ||
| includeSkills: true, | ||
| output: '' | ||
| }; | ||
| let cursor = 0; | ||
| while (cursor < argv.length) { | ||
| const token = String(argv[cursor] || ''); | ||
| if (token === '--json') { | ||
| options.format = 'json'; | ||
| cursor += 1; | ||
| continue; | ||
| } | ||
| if (token === '--format') { | ||
| const value = String(argv[cursor + 1] || '').trim().toLowerCase(); | ||
| if (!value || value.startsWith('--')) { | ||
| throw new Error('错误: --format 需要一个值(json/md)'); | ||
| } | ||
| options.format = value === 'md' || value === 'markdown' ? 'md' : 'json'; | ||
| cursor += 2; | ||
| continue; | ||
| } | ||
| if (token === '--output') { | ||
| const value = String(argv[cursor + 1] || '').trim(); | ||
| if (!value || value.startsWith('--')) { | ||
| throw new Error('错误: --output 需要一个值(文件路径)'); | ||
| } | ||
| options.output = value; | ||
| cursor += 2; | ||
| continue; | ||
| } | ||
| if (token === '--lang') { | ||
| const value = String(argv[cursor + 1] || '').trim().toLowerCase(); | ||
| if (!value || value.startsWith('--')) { | ||
| throw new Error('错误: --lang 需要一个值(zh/en)'); | ||
| } | ||
| options.lang = value === 'en' ? 'en' : 'zh'; | ||
| cursor += 2; | ||
| continue; | ||
| } | ||
| if (token === '--range') { | ||
| const value = String(argv[cursor + 1] || '').trim().toLowerCase(); | ||
| if (!value || value.startsWith('--')) { | ||
| throw new Error('错误: --range 需要一个值(7d/30d/all)'); | ||
| } | ||
| options.range = value === 'all' ? 'all' : (value === '30d' ? '30d' : '7d'); | ||
| cursor += 2; | ||
| continue; | ||
| } | ||
| if (token === '--target-app') { | ||
| const value = String(argv[cursor + 1] || '').trim().toLowerCase(); | ||
| if (!value || value.startsWith('--')) { | ||
| throw new Error('错误: --target-app 需要一个值(codex/claude)'); | ||
| } | ||
| options.targetApp = value === 'claude' ? 'claude' : 'codex'; | ||
| cursor += 2; | ||
| continue; | ||
| } | ||
| if (token === '--no-remote') { | ||
| options.remote = false; | ||
| cursor += 1; | ||
| continue; | ||
| } | ||
| if (token === '--no-install') { | ||
| options.includeInstall = false; | ||
| cursor += 1; | ||
| continue; | ||
| } | ||
| cursor += 1; | ||
| } | ||
| return options; | ||
| } | ||
| async function cmdDoctor(argv = []) { | ||
| try { | ||
| const options = parseDoctorCommandArgs(argv); | ||
| const report = await buildDoctorReport(options, { | ||
| getStatusPayload: buildMcpStatusPayload, | ||
| buildInstallStatusReport, | ||
| buildConfigHealthReport, | ||
| listSessionUsage, | ||
| buildTaskOverviewPayload, | ||
| listSkills | ||
| }); | ||
| const format = options.format === 'md' ? 'md' : 'json'; | ||
| const text = format === 'md' | ||
| ? renderDoctorMarkdown(report) | ||
| : JSON.stringify(report, null, 2); | ||
| if (options.output) { | ||
| fs.writeFileSync(options.output, text); | ||
| } else { | ||
| process.stdout.write(text + '\n'); | ||
| } | ||
| } catch (e) { | ||
| console.error('错误:', e && e.message ? e.message : e); | ||
| process.exitCode = 1; | ||
| } | ||
| } | ||
| // 列出所有提供商 | ||
| function cmdList() { | ||
| const configResult = readConfigOrVirtualDefault(); | ||
| @@ -8261,6 +8369,21 @@ function createWebServer({ htmlPath, assetsDir, webDir, host, port, openBrowser | ||
| case 'config-health-check': | ||
| result = await buildConfigHealthReport(params || {}); | ||
| break; | ||
| case 'doctor': | ||
| { | ||
| const doctorParams = isPlainObject(params) ? params : {}; | ||
| const report = await buildDoctorReport(doctorParams, { | ||
| getStatusPayload: buildMcpStatusPayload, | ||
| buildInstallStatusReport, | ||
| buildConfigHealthReport, | ||
| listSessionUsage, | ||
| buildTaskOverviewPayload, | ||
| listSkills | ||
| }); | ||
| result = buildDoctorLegacyPayload(report); | ||
| result.markdown = renderDoctorMarkdown(report); | ||
| } | ||
| break; | ||
| case 'get-agents-file': | ||
| result = readAgentsFile(params || {}); | ||
| break; | ||
| @@ -13048,6 +13171,7 @@ async function main() { | ||
| console.log('\nCodex Mate - Codex 提供商管理工具'); | ||
| console.log('\n用法:'); | ||
| console.log(' codexmate status 显示当前状态'); | ||
| console.log(' codexmate doctor [--format json|md] [--lang zh|en] [--output <PATH>] 输出诊断报告'); | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doctor help text is missing supported flags. The usage line omits valid options handled by Suggested fix- console.log(' codexmate doctor [--format json|md] [--lang zh|en] [--output <PATH>] 输出诊断报告');+ console.log(' codexmate doctor [--json|--format json|md] [--lang zh|en] [--range 7d|30d|all] [--target-app codex|claude] [--no-remote] [--no-install] [--output <PATH>] 输出诊断报告');🤖 Prompt for AI Agents | ||
| console.log(' codexmate setup 交互式配置向导'); | ||
| console.log(' codexmate list 列出所有提供商'); | ||
| console.log(' codexmate models 列出所有模型'); | ||
| @@ -13109,6 +13233,7 @@ async function main() { | ||
| switch (command) { | ||
| case '__task-worker': await cmdTaskWorker(args.slice(1)); break; | ||
| case 'status': cmdStatus(); break; | ||
| case 'doctor': await cmdDoctor(args.slice(1)); break; | ||
| case 'setup': await cmdSetup(); break; | ||
| case 'list': cmdList(); break; | ||
| case 'models': await cmdModels(); break; | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fail fast on invalid doctor flags instead of silently coercing.
Unsupported values for
--format,--range, and--target-appcurrently fall back to defaults, and unknown flags are ignored. That can make typoed commands appear successful with wrong behavior.Suggested fix
function parseDoctorCommandArgs(argv = []) { @@ if (token === '--format') { const value = String(argv[cursor + 1] || '').trim().toLowerCase(); if (!value || value.startsWith('--')) { throw new Error('错误: --format 需要一个值(json/md)'); } - options.format = value === 'md' || value === 'markdown' ? 'md' : 'json';+ if (value !== 'json' && value !== 'md' && value !== 'markdown') {+ throw new Error('错误: --format 仅支持 json 或 md');+ }+ options.format = value === 'json' ? 'json' : 'md'; cursor += 2; continue; } @@ if (token === '--range') { const value = String(argv[cursor + 1] || '').trim().toLowerCase(); if (!value || value.startsWith('--')) { throw new Error('错误: --range 需要一个值(7d/30d/all)'); } - options.range = value === 'all' ? 'all' : (value === '30d' ? '30d' : '7d');+ if (value !== '7d' && value !== '30d' && value !== 'all') {+ throw new Error('错误: --range 仅支持 7d/30d/all');+ }+ options.range = value; cursor += 2; continue; } @@ if (token === '--target-app') { const value = String(argv[cursor + 1] || '').trim().toLowerCase(); if (!value || value.startsWith('--')) { throw new Error('错误: --target-app 需要一个值(codex/claude)'); } - options.targetApp = value === 'claude' ? 'claude' : 'codex';+ if (value !== 'codex' && value !== 'claude') {+ throw new Error('错误: --target-app 仅支持 codex 或 claude');+ }+ options.targetApp = value; cursor += 2; continue; } @@ - cursor += 1;+ if (token.startsWith('--')) {+ throw new Error(`错误: 未知参数 ${token}`);+ }+ cursor += 1; } return options; }📝 Committable suggestion
🤖 Prompt for AI Agents