@qqq123456789/codex-doctor 0.9.0 → 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/README.en.md CHANGED
@@ -14,6 +14,8 @@ English | [中文](README.md)
14
14
  [![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux%20%7C%20WSL-lightgrey)](docs/06-sandbox-windows.md)
15
15
 
16
16
  > 📖 **Read online**:<https://qlw088697-ui.github.io/codex-troubleshooting/> (docsify site with full-text search, kept in sync with this repo)
17
+ >
18
+ > 📄 Prefer offline? Every release attaches a merged **PDF handbook** (`node scripts/build-pdf.mjs` regenerates it) — see [Releases](https://github.com/qlw088697-ui/codex-troubleshooting/releases).
17
19
 
18
20
  ## Quick start: run the environment self-check first
19
21
 
package/README.md CHANGED
@@ -45,6 +45,8 @@ curl -fsSL https://raw.githubusercontent.com/qlw088697-ui/codex-troubleshooting/
45
45
 
46
46
  (也可以下载 `scripts/` 目录里的脚本本地运行。脚本只读环境信息,不会修改任何配置。)
47
47
 
48
+ > 📄 喜欢离线阅读?每次发版都会在 [Releases](https://github.com/qlw088697-ui/codex-troubleshooting/releases) 附上合并排版的 PDF 手册(`node scripts/build-pdf.mjs` 可自行生成)。
49
+
48
50
  ## 🛠️ 配套工具:codex-doctor CLI
49
51
 
50
52
  把本手册的检查与维护做成了一条条命令(零依赖,Node 18.15+):
@@ -31,6 +31,7 @@ node codex-troubleshooting/tool/cli.mjs --help
31
31
  | `archive list` | List archive folders with sizes | read-only |
32
32
  | `archive delete <name\|--all>` | Delete archives (interactive confirm by default, `--yes` to skip) | medium (deletes, requires confirm) |
33
33
  | `versions [-n 10]` | List the latest openai/codex releases (prerelease flagged) | read-only |
34
+ | `config` | Read-only summary: model / provider / approval & sandbox / profiles / relays / MCP / auth mode (secrets masked) | read-only |
34
35
  | `sessions [-n 10] [--dir keyword]` | Browse past sessions: time, workdir, source, first-prompt preview; `--dir` filters by directory — find "that conversation" | read-only |
35
36
  | `sessions --search keyword [--deep]` | Search sessions by keyword (first 256KB of each file by default, `--deep` scans fully) | read-only |
36
37
  | `sessions --show [--search keyword] [--pick N] [--full]` | Print a session's full transcript (latest by default; messages truncated to 400 chars unless `--full`) | read-only |
@@ -31,6 +31,7 @@ node codex-troubleshooting/tool/cli.mjs --help
31
31
  | `archive list` | 查看归档目录与体积 | 只读 |
32
32
  | `archive delete <名称\|--all>` | 删除归档(默认需交互确认,`--yes` 跳过) | 中(删除,需确认) |
33
33
  | `versions [-n 10]` | 查看 openai/codex 最近 N 个版本(含预发布标记) | 只读 |
34
+ | `config` | 只读摘要:模型 / provider / 审批沙箱 / profiles / 中转 / MCP / 认证方式(敏感值脱敏) | 只读 |
34
35
  | `sessions [-n 10] [--dir 关键字]` | 浏览历史会话:时间、工作目录、来源、首条提问预览;`--dir` 按目录过滤,找回「上次那个对话」 | 只读 |
35
36
  | `sessions --search 关键词 [--deep]` | 按关键词搜索会话(默认搜每个文件开头 256KB,`--deep` 全文扫描) | 只读 |
36
37
  | `sessions --show [--search 关键词] [--pick N] [--full]` | 查看会话完整对话(默认最近一次;默认单条截断 400 字) | 只读 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qqq123456789/codex-doctor",
3
- "version": "0.9.0",
3
+ "version": "1.0.0",
4
4
  "scripts": {
5
5
  "test": "bash scripts/test-codex-doctor.sh",
6
6
  "check:links": "bash scripts/check-links.sh",
package/tool/cli.mjs CHANGED
@@ -4,10 +4,11 @@ import { collectChecks, summarize, renderHuman } from './checks.mjs';
4
4
  import { cleanTarget } from './clean.mjs';
5
5
  import { backupConfig, restoreBackup, resetAuth, listVersions, listArchives, deleteArchive, checkUpdate } from './ops.mjs';
6
6
  import { listSessions, searchSessions, readTranscript, exportTranscriptMarkdown } from './sessions.mjs';
7
+ import { configSummary } from './config.mjs';
7
8
  import { CODEX_DIR } from './util.mjs';
8
9
  import path from 'node:path';
9
10
 
10
- const VERSION = '0.9.0';
11
+ const VERSION = '1.0.0';
11
12
 
12
13
  const HELP = `codex-doctor v${VERSION} — Codex CLI 维护与排障工具(零依赖)
13
14
 
@@ -27,6 +28,7 @@ const HELP = `codex-doctor v${VERSION} — Codex CLI 维护与排障工具(零
27
28
  archive list 查看归档目录与体积
28
29
  archive delete <名称|--all> 删除归档(需 --yes 或交互确认)
29
30
  versions [-n N] 查看 openai/codex 最近 N 个版本(默认 10)
31
+ config 只读摘要:模型 / provider / 审批沙箱 / profiles / 中转 / MCP / 认证方式
30
32
  sessions [-n N] [--dir 关键字] 浏览历史会话:时间、目录、来源、首条提问预览
31
33
  [--search 关键词] [--deep] 按关键词搜索会话(--deep 全文扫描)
32
34
  --show [--search 关键词] [--pick N] [--full] 查看会话完整对话
@@ -209,6 +211,10 @@ async function main() {
209
211
  console.log(`\n会话文件位于 ${path.join(CODEX_DIR, 'sessions')}(-n 条数 / --dir 按目录关键字过滤)`);
210
212
  break;
211
213
  }
214
+ case 'config': {
215
+ for (const l of configSummary()) console.log(l);
216
+ break;
217
+ }
212
218
  case 'update': {
213
219
  const r = await checkUpdate(VERSION);
214
220
  print(r.lines);
@@ -0,0 +1,82 @@
1
+ // config:只读摘要——一条命令看懂 codex 当前有效配置(敏感信息脱敏)
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { CODEX_DIR, exists } from './util.mjs';
5
+
6
+ function host(u) {
7
+ try {
8
+ return new URL(u).host;
9
+ } catch {
10
+ return '(无效 URL)';
11
+ }
12
+ }
13
+
14
+ export function configSummary() {
15
+ const lines = [];
16
+ const cfg = path.join(CODEX_DIR, 'config.toml');
17
+ if (!exists(cfg)) {
18
+ lines.push('config.toml 不存在(全部使用默认配置)');
19
+ return lines;
20
+ }
21
+ const content = fs.readFileSync(cfg, 'utf8');
22
+
23
+ // 极简 TOML 分段解析:根级键 + 各表的 key=value(仅取本工具关心的键)
24
+ const root = {};
25
+ const tables = [];
26
+ let cur = null;
27
+ for (const raw of content.split(/\r?\n/)) {
28
+ const l = raw.trim();
29
+ if (!l || l.startsWith('#')) continue;
30
+ const tm = l.match(/^\[([^\]]+)\]$/);
31
+ if (tm) {
32
+ cur = tm[1].trim();
33
+ tables.push({ name: cur, kv: {} });
34
+ continue;
35
+ }
36
+ const kv = l.match(/^([A-Za-z0-9_-]+)\s*=\s*(.+)$/);
37
+ if (kv) {
38
+ const key = kv[1];
39
+ const val = kv[2].trim().replace(/^["']|["']$/g, '');
40
+ if (cur) tables[tables.length - 1].kv[key] = val;
41
+ else root[key] = val;
42
+ }
43
+ }
44
+
45
+ lines.push(`模型: ${root.model || '(默认)'}`);
46
+ lines.push(`provider: ${root.model_provider || 'openai(官方)'}`);
47
+ lines.push(`审批策略: ${root.approval_policy || '(默认)'}`);
48
+ lines.push(`沙箱模式: ${root.sandbox_mode || '(默认)'}`);
49
+
50
+ // 只显示「两段式」表名;更深的嵌套表(如 mcp_servers.x.env)是子配置,不是实体
51
+ const seg = (t) => t.name.split('.').length;
52
+ const profiles = tables.filter((t) => t.name.startsWith('profiles.') && seg(t) === 2);
53
+ if (profiles.length > 0) {
54
+ lines.push(`profiles: ${profiles.map((t) => t.name.replace('profiles.', '')).join(', ')}`);
55
+ }
56
+
57
+ const providers = tables.filter((t) => t.name.startsWith('model_providers.') && seg(t) === 2);
58
+ for (const p of providers) {
59
+ const id = p.name.replace('model_providers.', '');
60
+ const bu = p.kv.base_url ? host(p.kv.base_url) : '(未配置 base_url)';
61
+ const ek = p.kv.env_key ? `(Key 在环境变量 ${p.kv.env_key},不显示)` : '';
62
+ lines.push(`中转 ${id}: ${bu}${ek}`);
63
+ }
64
+
65
+ const mcp = tables.filter((t) => t.name.startsWith('mcp_servers.') && seg(t) === 2);
66
+ if (mcp.length > 0) {
67
+ lines.push(`MCP servers: ${mcp.map((t) => t.name.replace('mcp_servers.', '')).join(', ')}`);
68
+ }
69
+
70
+ // 认证方式(不看内容,只看结构)
71
+ const auth = path.join(CODEX_DIR, 'auth.json');
72
+ if (exists(auth)) {
73
+ try {
74
+ const j = JSON.parse(fs.readFileSync(auth, 'utf8'));
75
+ if (j.tokens) lines.push('认证: ChatGPT 账号登录');
76
+ else if (j.OPENAI_API_KEY) lines.push('认证: API Key(已脱敏)');
77
+ } catch {
78
+ lines.push('auth.json 无法解析——可运行 codex-doctor auth reset 重置');
79
+ }
80
+ }
81
+ return lines;
82
+ }