xling 0.0.2 → 0.3.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 (122) hide show
  1. package/README.md +276 -1
  2. package/dist/base-BWvHbkly.js +69 -0
  3. package/dist/base-BWvHbkly.js.map +1 -0
  4. package/dist/base-BXJVsMwL.d.ts +45 -0
  5. package/dist/base-BXJVsMwL.d.ts.map +1 -0
  6. package/dist/base-DdIJJBHV.js +34 -0
  7. package/dist/base-DdIJJBHV.js.map +1 -0
  8. package/dist/base-EQ6uvBQs.d.ts +43 -0
  9. package/dist/base-EQ6uvBQs.d.ts.map +1 -0
  10. package/dist/claude-BsdlWM7z.js +31 -0
  11. package/dist/claude-BsdlWM7z.js.map +1 -0
  12. package/dist/claude-D7KdpYHQ.js +209 -0
  13. package/dist/claude-D7KdpYHQ.js.map +1 -0
  14. package/dist/claudeDefault-pd-Kyu6o.js +19 -0
  15. package/dist/claudeDefault-pd-Kyu6o.js.map +1 -0
  16. package/dist/codex-Crifr9cw.js +32 -0
  17. package/dist/codex-Crifr9cw.js.map +1 -0
  18. package/dist/codex-UJ2PYHA6.js +85 -0
  19. package/dist/codex-UJ2PYHA6.js.map +1 -0
  20. package/dist/commands/settings/get.d.ts +24 -0
  21. package/dist/commands/settings/get.d.ts.map +1 -0
  22. package/dist/commands/settings/get.js +118 -0
  23. package/dist/commands/settings/get.js.map +1 -0
  24. package/dist/commands/settings/inspect.d.ts +19 -0
  25. package/dist/commands/settings/inspect.d.ts.map +1 -0
  26. package/dist/commands/settings/inspect.js +88 -0
  27. package/dist/commands/settings/inspect.js.map +1 -0
  28. package/dist/commands/settings/list.d.ts +25 -0
  29. package/dist/commands/settings/list.d.ts.map +1 -0
  30. package/dist/commands/settings/list.js +147 -0
  31. package/dist/commands/settings/list.js.map +1 -0
  32. package/dist/commands/settings/set.d.ts +22 -0
  33. package/dist/commands/settings/set.d.ts.map +1 -0
  34. package/dist/commands/settings/set.js +83 -0
  35. package/dist/commands/settings/set.js.map +1 -0
  36. package/dist/commands/settings/switch.d.ts +27 -0
  37. package/dist/commands/settings/switch.d.ts.map +1 -0
  38. package/dist/commands/settings/switch.js +164 -0
  39. package/dist/commands/settings/switch.js.map +1 -0
  40. package/dist/commands/x/index.d.ts +25 -0
  41. package/dist/commands/x/index.d.ts.map +1 -0
  42. package/dist/commands/x/index.js +130 -0
  43. package/dist/commands/x/index.js.map +1 -0
  44. package/dist/dispatcher-BUU7wUgm.js +94 -0
  45. package/dist/dispatcher-BUU7wUgm.js.map +1 -0
  46. package/dist/dispatcher-Co94YvDc.js +76 -0
  47. package/dist/dispatcher-Co94YvDc.js.map +1 -0
  48. package/dist/domain/interfaces.d.ts +3 -0
  49. package/dist/domain/interfaces.js +1 -0
  50. package/dist/domain/types.d.ts +2 -0
  51. package/dist/domain/types.js +1 -0
  52. package/dist/domain/validators.d.ts +82 -0
  53. package/dist/domain/validators.d.ts.map +1 -0
  54. package/dist/domain/validators.js +58 -0
  55. package/dist/domain/validators.js.map +1 -0
  56. package/dist/editor-D4qoje1V.js +32 -0
  57. package/dist/editor-D4qoje1V.js.map +1 -0
  58. package/dist/errors-CAZ5k5YT.js +89 -0
  59. package/dist/errors-CAZ5k5YT.js.map +1 -0
  60. package/dist/format-Cqecj3RS.js +229 -0
  61. package/dist/format-Cqecj3RS.js.map +1 -0
  62. package/dist/fsStore-BPnFUGta.js +122 -0
  63. package/dist/fsStore-BPnFUGta.js.map +1 -0
  64. package/dist/gemini-Qo5146d_.js +52 -0
  65. package/dist/gemini-Qo5146d_.js.map +1 -0
  66. package/dist/interfaces-DRNAGN0l.d.ts +75 -0
  67. package/dist/interfaces-DRNAGN0l.d.ts.map +1 -0
  68. package/dist/run.d.ts +1 -0
  69. package/dist/run.js +15 -0
  70. package/dist/run.js.map +1 -0
  71. package/dist/runner-BE7zZq1g.js +89 -0
  72. package/dist/runner-BE7zZq1g.js.map +1 -0
  73. package/dist/services/launch/adapters/base.d.ts +4 -0
  74. package/dist/services/launch/adapters/base.js +4 -0
  75. package/dist/services/launch/adapters/claude.d.ts +25 -0
  76. package/dist/services/launch/adapters/claude.d.ts.map +1 -0
  77. package/dist/services/launch/adapters/claude.js +5 -0
  78. package/dist/services/launch/adapters/codex.d.ts +26 -0
  79. package/dist/services/launch/adapters/codex.d.ts.map +1 -0
  80. package/dist/services/launch/adapters/codex.js +5 -0
  81. package/dist/services/launch/dispatcher.d.ts +44 -0
  82. package/dist/services/launch/dispatcher.d.ts.map +1 -0
  83. package/dist/services/launch/dispatcher.js +8 -0
  84. package/dist/services/settings/adapters/base.d.ts +4 -0
  85. package/dist/services/settings/adapters/base.js +5 -0
  86. package/dist/services/settings/adapters/claude.d.ts +43 -0
  87. package/dist/services/settings/adapters/claude.d.ts.map +1 -0
  88. package/dist/services/settings/adapters/claude.js +9 -0
  89. package/dist/services/settings/adapters/codex.d.ts +45 -0
  90. package/dist/services/settings/adapters/codex.d.ts.map +1 -0
  91. package/dist/services/settings/adapters/codex.js +6 -0
  92. package/dist/services/settings/adapters/gemini.d.ts +32 -0
  93. package/dist/services/settings/adapters/gemini.d.ts.map +1 -0
  94. package/dist/services/settings/adapters/gemini.js +6 -0
  95. package/dist/services/settings/dispatcher.d.ts +36 -0
  96. package/dist/services/settings/dispatcher.d.ts.map +1 -0
  97. package/dist/services/settings/dispatcher.js +12 -0
  98. package/dist/services/settings/fsStore.d.ts +46 -0
  99. package/dist/services/settings/fsStore.d.ts.map +1 -0
  100. package/dist/services/settings/fsStore.js +4 -0
  101. package/dist/services/settings/templates/claudeDefault.d.ts +20 -0
  102. package/dist/services/settings/templates/claudeDefault.d.ts.map +1 -0
  103. package/dist/services/settings/templates/claudeDefault.js +3 -0
  104. package/dist/types--0tjriPy.d.ts +104 -0
  105. package/dist/types--0tjriPy.d.ts.map +1 -0
  106. package/dist/utils/editor.d.ts +6 -0
  107. package/dist/utils/editor.d.ts.map +1 -0
  108. package/dist/utils/editor.js +4 -0
  109. package/dist/utils/errors.d.ts +61 -0
  110. package/dist/utils/errors.d.ts.map +1 -0
  111. package/dist/utils/errors.js +3 -0
  112. package/dist/utils/format.d.ts +20 -0
  113. package/dist/utils/format.d.ts.map +1 -0
  114. package/dist/utils/format.js +3 -0
  115. package/dist/utils/logger.d.ts +32 -0
  116. package/dist/utils/logger.d.ts.map +1 -0
  117. package/dist/utils/logger.js +46 -0
  118. package/dist/utils/logger.js.map +1 -0
  119. package/dist/utils/runner.d.ts +36 -0
  120. package/dist/utils/runner.d.ts.map +1 -0
  121. package/dist/utils/runner.js +3 -0
  122. package/package.json +66 -6
@@ -0,0 +1,209 @@
1
+ import { a as InvalidScopeError, s as SettingsVariantNotFoundError } from "./errors-CAZ5k5YT.js";
2
+ import { n as resolveEditorCommand, t as openInEditor } from "./editor-D4qoje1V.js";
3
+ import { t as formatDiff } from "./format-Cqecj3RS.js";
4
+ import { c as writeJSON, i as getFileInfo, n as ensureDir, s as resolveHome } from "./fsStore-BPnFUGta.js";
5
+ import { t as BaseAdapter } from "./base-BWvHbkly.js";
6
+ import { t as CLAUDE_SETTINGS_TEMPLATE } from "./claudeDefault-pd-Kyu6o.js";
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+
10
+ //#region src/services/settings/adapters/claude.ts
11
+ /**
12
+ * Claude Code 适配器
13
+ */
14
+ /**
15
+ * Claude Code 配置适配器
16
+ *
17
+ * 配置文件路径:
18
+ * - user: ~/.claude/settings.json
19
+ * - project: <cwd>/.claude/settings.json
20
+ * - local: <cwd>/.claude/settings.local.json
21
+ */
22
+ var ClaudeAdapter = class extends BaseAdapter {
23
+ toolId = "claude";
24
+ /**
25
+ * 列出所有 settings.*.json 文件
26
+ */
27
+ async list(scope) {
28
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
29
+ const activePath = resolveHome(this.resolvePath(scope));
30
+ const directory = path.dirname(activePath);
31
+ const activeFilename = path.basename(activePath);
32
+ const files = [this.buildEntry(activePath, scope, true)];
33
+ if (fs.existsSync(directory)) {
34
+ const entries = fs.readdirSync(directory, { withFileTypes: true });
35
+ for (const entry of entries) {
36
+ if (!entry.isFile()) continue;
37
+ if (entry.name === activeFilename) continue;
38
+ if (!this.isSettingsFile(entry.name)) continue;
39
+ const entryPath = path.join(directory, entry.name);
40
+ files.push(this.buildEntry(entryPath, scope, false));
41
+ }
42
+ }
43
+ return {
44
+ type: "files",
45
+ files: this.sortFiles(files)
46
+ };
47
+ }
48
+ /**
49
+ * 解析配置文件路径
50
+ */
51
+ resolvePath(scope) {
52
+ switch (scope) {
53
+ case "user": return "~/.claude/settings.json";
54
+ case "project": return ".claude/settings.json";
55
+ case "local": return ".claude/settings.local.json";
56
+ default: throw new Error(`Unsupported scope for Claude: ${scope}`);
57
+ }
58
+ }
59
+ /**
60
+ * 验证 scope 是否有效
61
+ */
62
+ validateScope(scope) {
63
+ return [
64
+ "user",
65
+ "project",
66
+ "local"
67
+ ].includes(scope);
68
+ }
69
+ /**
70
+ * 切换 settings.<variant>.json 到活动文件
71
+ */
72
+ async switchProfile(scope, profile, options) {
73
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
74
+ const variant = profile.trim();
75
+ if (!variant) throw new Error("Variant name cannot be empty");
76
+ const targetPath = resolveHome(this.resolvePath(scope));
77
+ const directory = path.dirname(targetPath);
78
+ const sourcePath = this.findVariantPath(directory, variant, targetPath);
79
+ if (!sourcePath) throw new SettingsVariantNotFoundError(variant);
80
+ const nextConfig = this.readConfig(sourcePath);
81
+ let currentConfig = {};
82
+ try {
83
+ currentConfig = this.readConfig(targetPath);
84
+ } catch {
85
+ currentConfig = {};
86
+ }
87
+ const diff = formatDiff(currentConfig, nextConfig);
88
+ if (options?.preview) return {
89
+ success: true,
90
+ preview: true,
91
+ filePath: targetPath,
92
+ diff: diff ?? void 0,
93
+ data: {
94
+ from: sourcePath,
95
+ to: targetPath,
96
+ hasChanges: Boolean(diff)
97
+ },
98
+ message: diff ? "Preview generated. Review diff before applying." : "Current settings already match the selected variant."
99
+ };
100
+ if (!diff) return {
101
+ success: true,
102
+ message: "Current settings already match the selected variant.",
103
+ filePath: targetPath
104
+ };
105
+ const shouldBackup = options?.backup ?? false;
106
+ this.writeConfig(targetPath, nextConfig, shouldBackup);
107
+ return {
108
+ success: true,
109
+ message: `Switched to ${path.basename(sourcePath)}`,
110
+ filePath: targetPath,
111
+ data: {
112
+ from: sourcePath,
113
+ to: targetPath
114
+ }
115
+ };
116
+ }
117
+ async edit(scope, options) {
118
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
119
+ const basePath = resolveHome(this.resolvePath(scope));
120
+ const directory = path.dirname(basePath);
121
+ const variantName = options.name?.trim();
122
+ const resolvedEditor = resolveEditorCommand(options.ide);
123
+ ensureDir(directory);
124
+ let targetPath = basePath;
125
+ let label = "default";
126
+ if (variantName && variantName !== "" && variantName !== "default") {
127
+ const existingPath = this.findVariantPath(directory, variantName, basePath);
128
+ if (existingPath) targetPath = existingPath;
129
+ else {
130
+ targetPath = path.join(directory, `settings.${variantName}.json`);
131
+ if (!fs.existsSync(targetPath)) {
132
+ const seed = this.buildSeedConfig(basePath);
133
+ writeJSON(targetPath, seed, false);
134
+ }
135
+ }
136
+ label = variantName;
137
+ } else if (!fs.existsSync(targetPath)) {
138
+ const seed = this.buildSeedConfig(basePath);
139
+ writeJSON(targetPath, seed, false);
140
+ }
141
+ await openInEditor(resolvedEditor, targetPath);
142
+ return {
143
+ success: true,
144
+ message: `Opened ${label} settings in ${resolvedEditor}`,
145
+ filePath: targetPath,
146
+ data: {
147
+ variant: label,
148
+ ide: resolvedEditor
149
+ }
150
+ };
151
+ }
152
+ buildEntry(filePath, scope, active) {
153
+ const info = getFileInfo(filePath);
154
+ return {
155
+ filename: path.basename(filePath),
156
+ variant: this.extractVariant(filePath),
157
+ path: filePath,
158
+ scope,
159
+ active,
160
+ exists: Boolean(info),
161
+ size: info?.size,
162
+ lastModified: info?.lastModified
163
+ };
164
+ }
165
+ extractVariant(filePath) {
166
+ const filename = path.basename(filePath);
167
+ const match = filename.match(/^settings(?:[._-](.+))?\.json$/);
168
+ if (!match) return filename.replace(/\.json$/, "");
169
+ return match[1] ?? "default";
170
+ }
171
+ buildSeedConfig(basePath) {
172
+ try {
173
+ if (fs.existsSync(basePath)) {
174
+ const content = fs.readFileSync(basePath, "utf-8");
175
+ return JSON.parse(content);
176
+ }
177
+ } catch {}
178
+ return { ...CLAUDE_SETTINGS_TEMPLATE };
179
+ }
180
+ isSettingsFile(filename) {
181
+ return /^settings[._-].+\.json$/.test(filename);
182
+ }
183
+ sortFiles(files) {
184
+ return files.sort((a, b) => {
185
+ if (a.active && !b.active) return -1;
186
+ if (!a.active && b.active) return 1;
187
+ return a.variant.localeCompare(b.variant);
188
+ });
189
+ }
190
+ findVariantPath(directory, profile, defaultPath) {
191
+ const candidates = [];
192
+ const pushCandidate = (value) => {
193
+ if (!candidates.includes(value)) candidates.push(value);
194
+ };
195
+ if (profile === "default") pushCandidate(defaultPath);
196
+ if (profile.endsWith(".json")) pushCandidate(path.isAbsolute(profile) ? profile : path.join(directory, profile));
197
+ else {
198
+ pushCandidate(path.join(directory, `settings.${profile}.json`));
199
+ pushCandidate(path.join(directory, `settings-${profile}.json`));
200
+ pushCandidate(path.join(directory, `settings_${profile}.json`));
201
+ }
202
+ for (const candidate of candidates) if (fs.existsSync(candidate)) return candidate;
203
+ return null;
204
+ }
205
+ };
206
+
207
+ //#endregion
208
+ export { ClaudeAdapter as t };
209
+ //# sourceMappingURL=claude-D7KdpYHQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-D7KdpYHQ.js","names":["fsStore.resolveHome","files: SettingsFileEntry[]","currentConfig: Record<string, unknown>","fsStore.getFileInfo","candidates: string[]"],"sources":["../src/services/settings/adapters/claude.ts"],"sourcesContent":["/**\n * Claude Code 适配器\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type {\n Scope,\n SettingsListData,\n SettingsFileEntry,\n SettingsResult,\n EditOptions,\n SwitchOptions,\n} from \"@/domain/types.ts\";\nimport { BaseAdapter } from \"./base.ts\";\nimport * as fsStore from \"@/services/settings/fsStore.ts\";\nimport {\n InvalidScopeError,\n SettingsVariantNotFoundError,\n} from \"@/utils/errors.ts\";\nimport { CLAUDE_SETTINGS_TEMPLATE } from \"@/services/settings/templates/claudeDefault.ts\";\nimport { openInEditor, resolveEditorCommand } from \"@/utils/editor.ts\";\nimport { formatDiff } from \"@/utils/format.ts\";\n\n/**\n * Claude Code 配置适配器\n *\n * 配置文件路径:\n * - user: ~/.claude/settings.json\n * - project: <cwd>/.claude/settings.json\n * - local: <cwd>/.claude/settings.local.json\n */\nexport class ClaudeAdapter extends BaseAdapter {\n readonly toolId = \"claude\" as const;\n\n /**\n * 列出所有 settings.*.json 文件\n */\n override async list(scope: Scope): Promise<SettingsListData> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const activePath = fsStore.resolveHome(this.resolvePath(scope));\n const directory = path.dirname(activePath);\n const activeFilename = path.basename(activePath);\n\n const files: SettingsFileEntry[] = [\n this.buildEntry(activePath, scope, true),\n ];\n\n if (fs.existsSync(directory)) {\n const entries = fs.readdirSync(directory, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n if (entry.name === activeFilename) continue;\n if (!this.isSettingsFile(entry.name)) continue;\n\n const entryPath = path.join(directory, entry.name);\n files.push(this.buildEntry(entryPath, scope, false));\n }\n }\n\n return {\n type: \"files\",\n files: this.sortFiles(files),\n };\n }\n\n /**\n * 解析配置文件路径\n */\n resolvePath(scope: Scope): string {\n switch (scope) {\n case \"user\":\n return \"~/.claude/settings.json\";\n case \"project\":\n return \".claude/settings.json\";\n case \"local\":\n return \".claude/settings.local.json\";\n default:\n throw new Error(`Unsupported scope for Claude: ${scope}`);\n }\n }\n\n /**\n * 验证 scope 是否有效\n */\n validateScope(scope: Scope): boolean {\n return [\"user\", \"project\", \"local\"].includes(scope);\n }\n\n /**\n * 切换 settings.<variant>.json 到活动文件\n */\n override async switchProfile(\n scope: Scope,\n profile: string,\n options?: SwitchOptions,\n ): Promise<SettingsResult> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const variant = profile.trim();\n if (!variant) {\n throw new Error(\"Variant name cannot be empty\");\n }\n\n const targetPath = fsStore.resolveHome(this.resolvePath(scope));\n const directory = path.dirname(targetPath);\n const sourcePath = this.findVariantPath(directory, variant, targetPath);\n\n if (!sourcePath) {\n throw new SettingsVariantNotFoundError(variant);\n }\n\n const nextConfig = this.readConfig(sourcePath);\n\n let currentConfig: Record<string, unknown> = {};\n try {\n currentConfig = this.readConfig(targetPath);\n } catch {\n currentConfig = {};\n }\n\n const diff = formatDiff(currentConfig, nextConfig);\n\n if (options?.preview) {\n return {\n success: true,\n preview: true,\n filePath: targetPath,\n diff: diff ?? undefined,\n data: {\n from: sourcePath,\n to: targetPath,\n hasChanges: Boolean(diff),\n },\n message: diff\n ? \"Preview generated. Review diff before applying.\"\n : \"Current settings already match the selected variant.\",\n };\n }\n\n if (!diff) {\n return {\n success: true,\n message: \"Current settings already match the selected variant.\",\n filePath: targetPath,\n };\n }\n\n const shouldBackup = options?.backup ?? false;\n this.writeConfig(targetPath, nextConfig, shouldBackup);\n\n return {\n success: true,\n message: `Switched to ${path.basename(sourcePath)}`,\n filePath: targetPath,\n data: {\n from: sourcePath,\n to: targetPath,\n },\n };\n }\n\n override async edit(\n scope: Scope,\n options: EditOptions,\n ): Promise<SettingsResult> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const basePath = fsStore.resolveHome(this.resolvePath(scope));\n const directory = path.dirname(basePath);\n const variantName = options.name?.trim();\n const resolvedEditor = resolveEditorCommand(options.ide);\n\n fsStore.ensureDir(directory);\n\n let targetPath = basePath;\n let label = \"default\";\n\n if (variantName && variantName !== \"\" && variantName !== \"default\") {\n const existingPath = this.findVariantPath(\n directory,\n variantName,\n basePath,\n );\n if (existingPath) {\n targetPath = existingPath;\n } else {\n targetPath = path.join(directory, `settings.${variantName}.json`);\n if (!fs.existsSync(targetPath)) {\n const seed = this.buildSeedConfig(basePath);\n fsStore.writeJSON(targetPath, seed, false);\n }\n }\n label = variantName;\n } else if (!fs.existsSync(targetPath)) {\n const seed = this.buildSeedConfig(basePath);\n fsStore.writeJSON(targetPath, seed, false);\n }\n\n await openInEditor(resolvedEditor, targetPath);\n\n return {\n success: true,\n message: `Opened ${label} settings in ${resolvedEditor}`,\n filePath: targetPath,\n data: {\n variant: label,\n ide: resolvedEditor,\n },\n };\n }\n\n private buildEntry(\n filePath: string,\n scope: Scope,\n active: boolean,\n ): SettingsFileEntry {\n const info = fsStore.getFileInfo(filePath);\n\n return {\n filename: path.basename(filePath),\n variant: this.extractVariant(filePath),\n path: filePath,\n scope,\n active,\n exists: Boolean(info),\n size: info?.size,\n lastModified: info?.lastModified,\n };\n }\n\n private extractVariant(filePath: string): string {\n const filename = path.basename(filePath);\n const match = filename.match(/^settings(?:[._-](.+))?\\.json$/);\n if (!match) {\n return filename.replace(/\\.json$/, \"\");\n }\n return match[1] ?? \"default\";\n }\n\n private buildSeedConfig(basePath: string): Record<string, unknown> {\n try {\n if (fs.existsSync(basePath)) {\n const content = fs.readFileSync(basePath, \"utf-8\");\n return JSON.parse(content);\n }\n } catch {\n // ignore, fallback to template\n }\n return { ...CLAUDE_SETTINGS_TEMPLATE };\n }\n\n private isSettingsFile(filename: string): boolean {\n return /^settings[._-].+\\.json$/.test(filename);\n }\n\n private sortFiles(files: SettingsFileEntry[]): SettingsFileEntry[] {\n return files.sort((a, b) => {\n if (a.active && !b.active) return -1;\n if (!a.active && b.active) return 1;\n return a.variant.localeCompare(b.variant);\n });\n }\n\n private findVariantPath(\n directory: string,\n profile: string,\n defaultPath: string,\n ): string | null {\n const candidates: string[] = [];\n const pushCandidate = (value: string) => {\n if (!candidates.includes(value)) {\n candidates.push(value);\n }\n };\n\n if (profile === \"default\") {\n pushCandidate(defaultPath);\n }\n\n if (profile.endsWith(\".json\")) {\n pushCandidate(\n path.isAbsolute(profile) ? profile : path.join(directory, profile),\n );\n } else {\n pushCandidate(path.join(directory, `settings.${profile}.json`));\n pushCandidate(path.join(directory, `settings-${profile}.json`));\n pushCandidate(path.join(directory, `settings_${profile}.json`));\n }\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n }\n\n return null;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ //#region src/services/settings/templates/claudeDefault.ts
2
+ const CLAUDE_SETTINGS_TEMPLATE = {
3
+ env: {
4
+ ANTHROPIC_AUTH_TOKEN: "",
5
+ ANTHROPIC_BASE_URL: "https://api.anthropic.com",
6
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
7
+ ANTHROPIC_MODEL: "claude-sonnet-4-5-20250929",
8
+ ANTHROPIC_SMALL_FAST_MODEL: "claude-haiku-4-5-20251001"
9
+ },
10
+ permissions: {
11
+ allow: [],
12
+ deny: []
13
+ },
14
+ enabledPlugins: { "example-skills@anthropic-agent-skills": false }
15
+ };
16
+
17
+ //#endregion
18
+ export { CLAUDE_SETTINGS_TEMPLATE as t };
19
+ //# sourceMappingURL=claudeDefault-pd-Kyu6o.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeDefault-pd-Kyu6o.js","names":[],"sources":["../src/services/settings/templates/claudeDefault.ts"],"sourcesContent":["export const CLAUDE_SETTINGS_TEMPLATE = {\n env: {\n ANTHROPIC_AUTH_TOKEN: \"\",\n ANTHROPIC_BASE_URL: \"https://api.anthropic.com\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n ANTHROPIC_MODEL: \"claude-sonnet-4-5-20250929\",\n ANTHROPIC_SMALL_FAST_MODEL: \"claude-haiku-4-5-20251001\",\n },\n permissions: {\n allow: [],\n deny: [],\n },\n enabledPlugins: {\n \"example-skills@anthropic-agent-skills\": false,\n },\n} satisfies Record<string, unknown>;\n"],"mappings":";AAAA,MAAa,2BAA2B;CACtC,KAAK;EACH,sBAAsB;EACtB,oBAAoB;EACpB,0CAA0C;EAC1C,iBAAiB;EACjB,4BAA4B;EAC7B;CACD,aAAa;EACX,OAAO,EAAE;EACT,MAAM,EAAE;EACT;CACD,gBAAgB,EACd,yCAAyC,OAC1C;CACF"}
@@ -0,0 +1,32 @@
1
+ import { t as BaseLaunchAdapter } from "./base-DdIJJBHV.js";
2
+
3
+ //#region src/services/launch/adapters/codex.ts
4
+ /**
5
+ * Codex Launch 适配器
6
+ */
7
+ /**
8
+ * Codex 启动适配器
9
+ *
10
+ * Yolo 模式: --dangerously-bypass-approvals-and-sandbox
11
+ * Resume 模式: resume (显示会话列表选择)
12
+ * Continue 模式: resume --last (继续最后一个会话)
13
+ * 启动交互式会话: codex --dangerously-bypass-approvals-and-sandbox
14
+ */
15
+ var CodexLaunchAdapter = class extends BaseLaunchAdapter {
16
+ toolId = "codex";
17
+ executable = "codex";
18
+ buildCommandSpec(payload) {
19
+ const baseArgs = [];
20
+ if (payload.continue) baseArgs.push("resume", "--last");
21
+ else if (payload.resume) baseArgs.push("resume");
22
+ return {
23
+ executable: this.executable,
24
+ baseArgs,
25
+ yoloArgs: payload.yolo ? ["--dangerously-bypass-approvals-and-sandbox"] : void 0
26
+ };
27
+ }
28
+ };
29
+
30
+ //#endregion
31
+ export { CodexLaunchAdapter as t };
32
+ //# sourceMappingURL=codex-Crifr9cw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-Crifr9cw.js","names":["baseArgs: string[]"],"sources":["../src/services/launch/adapters/codex.ts"],"sourcesContent":["/**\n * Codex Launch 适配器\n */\n\nimport { BaseLaunchAdapter } from \"./base.ts\";\nimport type { LaunchCommandSpec } from \"@/domain/types.ts\";\n\n/**\n * Codex 启动适配器\n *\n * Yolo 模式: --dangerously-bypass-approvals-and-sandbox\n * Resume 模式: resume (显示会话列表选择)\n * Continue 模式: resume --last (继续最后一个会话)\n * 启动交互式会话: codex --dangerously-bypass-approvals-and-sandbox\n */\nexport class CodexLaunchAdapter extends BaseLaunchAdapter {\n readonly toolId = \"codex\" as const;\n readonly executable = \"codex\";\n\n buildCommandSpec(payload: {\n yolo?: boolean;\n resume?: boolean;\n continue?: boolean;\n }): LaunchCommandSpec {\n const baseArgs: string[] = [];\n\n // Resume 和 Continue 是互斥的\n if (payload.continue) {\n // codex resume --last\n baseArgs.push(\"resume\", \"--last\");\n } else if (payload.resume) {\n // codex resume\n baseArgs.push(\"resume\");\n }\n // 否则直接启动交互式会话,baseArgs 为空\n\n return {\n executable: this.executable,\n baseArgs,\n yoloArgs: payload.yolo\n ? [\"--dangerously-bypass-approvals-and-sandbox\"]\n : undefined,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,IAAa,qBAAb,cAAwC,kBAAkB;CACxD,AAAS,SAAS;CAClB,AAAS,aAAa;CAEtB,iBAAiB,SAIK;EACpB,MAAMA,WAAqB,EAAE;AAG7B,MAAI,QAAQ,SAEV,UAAS,KAAK,UAAU,SAAS;WACxB,QAAQ,OAEjB,UAAS,KAAK,SAAS;AAIzB,SAAO;GACL,YAAY,KAAK;GACjB;GACA,UAAU,QAAQ,OACd,CAAC,6CAA6C,GAC9C;GACL"}
@@ -0,0 +1,85 @@
1
+ import { a as InvalidScopeError, o as ProfileNotFoundError } from "./errors-CAZ5k5YT.js";
2
+ import { l as writeTOML, o as readTOML } from "./fsStore-BPnFUGta.js";
3
+ import { t as BaseAdapter } from "./base-BWvHbkly.js";
4
+
5
+ //#region src/services/settings/adapters/codex.ts
6
+ /**
7
+ * Codex 配置适配器
8
+ *
9
+ * 配置文件路径:
10
+ * - user: ~/.codex/config.toml
11
+ *
12
+ * 支持 profile 切换
13
+ */
14
+ var CodexAdapter = class extends BaseAdapter {
15
+ toolId = "codex";
16
+ /**
17
+ * 自定义 list:聚焦 model_providers
18
+ */
19
+ async list(scope) {
20
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
21
+ const path = this.resolvePath(scope);
22
+ const config = this.readConfig(path);
23
+ return {
24
+ type: "entries",
25
+ entries: this.extractProviders(config),
26
+ filePath: path
27
+ };
28
+ }
29
+ /**
30
+ * 解析配置文件路径
31
+ */
32
+ resolvePath(scope) {
33
+ switch (scope) {
34
+ case "user": return "~/.codex/config.toml";
35
+ default: throw new Error(`Unsupported scope for Codex: ${scope}`);
36
+ }
37
+ }
38
+ /**
39
+ * 验证 scope 是否有效
40
+ */
41
+ validateScope(scope) {
42
+ return scope === "user";
43
+ }
44
+ /**
45
+ * 切换 profile
46
+ */
47
+ async switchProfile(scope, profile, _options) {
48
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
49
+ const path = this.resolvePath(scope);
50
+ const config = this.readConfig(path);
51
+ const profiles = config.profiles;
52
+ if (!profiles || !(profile in profiles)) throw new ProfileNotFoundError(profile);
53
+ const profileConfig = profiles[profile];
54
+ const newConfig = { ...config };
55
+ for (const [key, value] of Object.entries(profileConfig)) newConfig[key] = value;
56
+ newConfig.current_profile = profile;
57
+ this.writeConfig(path, newConfig);
58
+ return {
59
+ success: true,
60
+ message: `Switched to profile: ${profile}`,
61
+ filePath: path
62
+ };
63
+ }
64
+ /**
65
+ * 读取 TOML 配置文件
66
+ */
67
+ readConfig(path) {
68
+ return readTOML(path);
69
+ }
70
+ /**
71
+ * 写入 TOML 配置文件
72
+ */
73
+ writeConfig(path, data) {
74
+ writeTOML(path, data);
75
+ }
76
+ extractProviders(config) {
77
+ const providers = config.model_providers;
78
+ if (typeof providers === "object" && providers !== null && !Array.isArray(providers)) return providers;
79
+ return {};
80
+ }
81
+ };
82
+
83
+ //#endregion
84
+ export { CodexAdapter as t };
85
+ //# sourceMappingURL=codex-UJ2PYHA6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-UJ2PYHA6.js","names":["fsStore.readTOML"],"sources":["../src/services/settings/adapters/codex.ts"],"sourcesContent":["/**\n * Codex 适配器\n */\n\nimport type {\n Scope,\n SettingsResult,\n SettingsListData,\n SwitchOptions,\n} from \"@/domain/types.ts\";\nimport { BaseAdapter } from \"./base.ts\";\nimport { InvalidScopeError, ProfileNotFoundError } from \"@/utils/errors.ts\";\nimport * as fsStore from \"@/services/settings/fsStore.ts\";\n\n/**\n * Codex 配置适配器\n *\n * 配置文件路径:\n * - user: ~/.codex/config.toml\n *\n * 支持 profile 切换\n */\nexport class CodexAdapter extends BaseAdapter {\n readonly toolId = \"codex\" as const;\n\n /**\n * 自定义 list:聚焦 model_providers\n */\n override async list(scope: Scope): Promise<SettingsListData> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const path = this.resolvePath(scope);\n const config = this.readConfig(path);\n const providers = this.extractProviders(config);\n\n return {\n type: \"entries\",\n entries: providers,\n filePath: path,\n };\n }\n\n /**\n * 解析配置文件路径\n */\n resolvePath(scope: Scope): string {\n switch (scope) {\n case \"user\":\n return \"~/.codex/config.toml\";\n default:\n throw new Error(`Unsupported scope for Codex: ${scope}`);\n }\n }\n\n /**\n * 验证 scope 是否有效\n */\n validateScope(scope: Scope): boolean {\n return scope === \"user\";\n }\n\n /**\n * 切换 profile\n */\n async switchProfile(\n scope: Scope,\n profile: string,\n _options?: SwitchOptions,\n ): Promise<SettingsResult> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const path = this.resolvePath(scope);\n const config = this.readConfig(path);\n\n // 检查 profile 是否存在\n const profiles = config.profiles as Record<string, unknown> | undefined;\n if (!profiles || !(profile in profiles)) {\n throw new ProfileNotFoundError(profile);\n }\n\n // 获取 profile 配置\n const profileConfig = profiles[profile] as Record<string, unknown>;\n\n // 将 profile 配置合并到根配置\n const newConfig = { ...config };\n for (const [key, value] of Object.entries(profileConfig)) {\n newConfig[key] = value;\n }\n\n // 设置当前 profile\n newConfig.current_profile = profile;\n\n // 写入配置\n this.writeConfig(path, newConfig);\n\n return {\n success: true,\n message: `Switched to profile: ${profile}`,\n filePath: path,\n };\n }\n\n /**\n * 读取 TOML 配置文件\n */\n protected readConfig(path: string): Record<string, unknown> {\n return fsStore.readTOML(path);\n }\n\n /**\n * 写入 TOML 配置文件\n */\n protected writeConfig(path: string, data: Record<string, unknown>): void {\n fsStore.writeTOML(path, data);\n }\n\n private extractProviders(\n config: Record<string, unknown>,\n ): Record<string, unknown> {\n const providers = config.model_providers;\n if (\n typeof providers === \"object\" &&\n providers !== null &&\n !Array.isArray(providers)\n ) {\n return providers as Record<string, unknown>;\n }\n return {};\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAsBA,IAAa,eAAb,cAAkC,YAAY;CAC5C,AAAS,SAAS;;;;CAKlB,MAAe,KAAK,OAAyC;AAC3D,MAAI,CAAC,KAAK,cAAc,MAAM,CAC5B,OAAM,IAAI,kBAAkB,MAAM;EAGpC,MAAM,OAAO,KAAK,YAAY,MAAM;EACpC,MAAM,SAAS,KAAK,WAAW,KAAK;AAGpC,SAAO;GACL,MAAM;GACN,SAJgB,KAAK,iBAAiB,OAAO;GAK7C,UAAU;GACX;;;;;CAMH,YAAY,OAAsB;AAChC,UAAQ,OAAR;GACE,KAAK,OACH,QAAO;GACT,QACE,OAAM,IAAI,MAAM,gCAAgC,QAAQ;;;;;;CAO9D,cAAc,OAAuB;AACnC,SAAO,UAAU;;;;;CAMnB,MAAM,cACJ,OACA,SACA,UACyB;AACzB,MAAI,CAAC,KAAK,cAAc,MAAM,CAC5B,OAAM,IAAI,kBAAkB,MAAM;EAGpC,MAAM,OAAO,KAAK,YAAY,MAAM;EACpC,MAAM,SAAS,KAAK,WAAW,KAAK;EAGpC,MAAM,WAAW,OAAO;AACxB,MAAI,CAAC,YAAY,EAAE,WAAW,UAC5B,OAAM,IAAI,qBAAqB,QAAQ;EAIzC,MAAM,gBAAgB,SAAS;EAG/B,MAAM,YAAY,EAAE,GAAG,QAAQ;AAC/B,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,cAAc,CACtD,WAAU,OAAO;AAInB,YAAU,kBAAkB;AAG5B,OAAK,YAAY,MAAM,UAAU;AAEjC,SAAO;GACL,SAAS;GACT,SAAS,wBAAwB;GACjC,UAAU;GACX;;;;;CAMH,AAAU,WAAW,MAAuC;AAC1D,SAAOA,SAAiB,KAAK;;;;;CAM/B,AAAU,YAAY,MAAc,MAAqC;AACvE,YAAkB,MAAM,KAAK;;CAG/B,AAAQ,iBACN,QACyB;EACzB,MAAM,YAAY,OAAO;AACzB,MACE,OAAO,cAAc,YACrB,cAAc,QACd,CAAC,MAAM,QAAQ,UAAU,CAEzB,QAAO;AAET,SAAO,EAAE"}
@@ -0,0 +1,24 @@
1
+ import { Command } from "@oclif/core";
2
+ import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
3
+
4
+ //#region src/commands/settings/get.d.ts
5
+
6
+ declare class SettingsGet extends Command {
7
+ static summary: string;
8
+ static description: string;
9
+ static examples: string[];
10
+ static args: {
11
+ name: _oclif_core_interfaces0.Arg<string | undefined, Record<string, unknown>>;
12
+ };
13
+ static flags: {
14
+ tool: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
15
+ scope: _oclif_core_interfaces0.OptionFlag<string, _oclif_core_interfaces0.CustomOptions>;
16
+ };
17
+ run(): Promise<void>;
18
+ private inspectViaDispatcher;
19
+ private inspectClaudeVariant;
20
+ private findVariantPath;
21
+ }
22
+ //#endregion
23
+ export { SettingsGet as default };
24
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","names":[],"sources":["../../../src/commands/settings/get.ts"],"sourcesContent":[],"mappings":";;;;;cAcqB,WAAA,SAAoB,OAAA;;;;;;EAmC1B,CAAA;EAnC0B,OAAA,KAAA,EAAA;IAAO,IAAA,oCAAA,CAAA,MAAA,wCAAA;;;SAmCjC"}
@@ -0,0 +1,118 @@
1
+ import "../../errors-CAZ5k5YT.js";
2
+ import "../../editor-D4qoje1V.js";
3
+ import { r as formatJson } from "../../format-Cqecj3RS.js";
4
+ import { s as resolveHome } from "../../fsStore-BPnFUGta.js";
5
+ import "../../base-BWvHbkly.js";
6
+ import "../../claudeDefault-pd-Kyu6o.js";
7
+ import { t as ClaudeAdapter } from "../../claude-D7KdpYHQ.js";
8
+ import "../../codex-UJ2PYHA6.js";
9
+ import "../../gemini-Qo5146d_.js";
10
+ import { t as SettingsDispatcher } from "../../dispatcher-Co94YvDc.js";
11
+ import { Args, Command, Flags } from "@oclif/core";
12
+ import fs from "node:fs";
13
+ import path from "node:path";
14
+
15
+ //#region src/commands/settings/get.ts
16
+ /**
17
+ * settings:get 命令
18
+ * 获取指定配置项的值
19
+ */
20
+ var SettingsGet = class SettingsGet extends Command {
21
+ static summary = "View the full configuration file";
22
+ static description = `
23
+ Print the entire configuration file for the selected tool/scope.
24
+ Use --json for structured output or --no-json for plain text.
25
+ `;
26
+ static examples = ["<%= config.bin %> <%= command.id %> --tool claude --scope user", "<%= config.bin %> <%= command.id %> --tool codex --no-json"];
27
+ static args = { name: Args.string({
28
+ description: "Claude variant name (optional). Example: settings:get hxi",
29
+ required: false
30
+ }) };
31
+ static flags = {
32
+ tool: Flags.string({
33
+ char: "t",
34
+ description: "AI CLI tool to manage",
35
+ options: [
36
+ "claude",
37
+ "codex",
38
+ "gemini"
39
+ ],
40
+ default: "claude"
41
+ }),
42
+ scope: Flags.string({
43
+ char: "s",
44
+ description: "Configuration scope",
45
+ options: [
46
+ "user",
47
+ "project",
48
+ "local",
49
+ "system"
50
+ ],
51
+ default: "user"
52
+ })
53
+ };
54
+ async run() {
55
+ const { args, flags } = await this.parse(SettingsGet);
56
+ try {
57
+ const tool = flags.tool;
58
+ const scope = flags.scope;
59
+ const data = tool === "claude" && args.name ? await this.inspectClaudeVariant(scope, args.name) : await this.inspectViaDispatcher(tool, scope);
60
+ if (flags.json) {
61
+ this.log(formatJson({
62
+ success: true,
63
+ data
64
+ }));
65
+ return;
66
+ }
67
+ if (!data.exists) {
68
+ this.warn(`Config file not found: ${data.path}`);
69
+ return;
70
+ }
71
+ if (data.content) this.log(data.content);
72
+ else this.log("File is empty.");
73
+ } catch (error) {
74
+ this.error(error.message, { exit: 1 });
75
+ }
76
+ }
77
+ async inspectViaDispatcher(tool, scope) {
78
+ return (await new SettingsDispatcher().execute({
79
+ tool,
80
+ scope,
81
+ action: "inspect"
82
+ })).data;
83
+ }
84
+ async inspectClaudeVariant(scope, name) {
85
+ const adapter = new ClaudeAdapter();
86
+ if (!adapter.validateScope(scope)) throw new Error(`Invalid scope for Claude: ${scope}`);
87
+ const normalized = name.trim();
88
+ if (!normalized || normalized === "default") return this.inspectViaDispatcher("claude", scope);
89
+ const basePath = adapter.resolvePath(scope);
90
+ const resolvedBase = resolveHome(basePath);
91
+ const directory = path.dirname(resolvedBase);
92
+ const variantPath = this.findVariantPath(directory, normalized) ?? path.join(directory, `settings.${normalized}.json`);
93
+ if (!fs.existsSync(variantPath)) return {
94
+ path: variantPath,
95
+ exists: false
96
+ };
97
+ const stats = fs.statSync(variantPath);
98
+ return {
99
+ path: variantPath,
100
+ exists: true,
101
+ content: fs.readFileSync(variantPath, "utf-8"),
102
+ size: stats.size,
103
+ lastModified: stats.mtime
104
+ };
105
+ }
106
+ findVariantPath(directory, name) {
107
+ const candidates = [`settings.${name}.json`, `settings-${name}.json`];
108
+ for (const candidate of candidates) {
109
+ const fullPath = path.join(directory, candidate);
110
+ if (fs.existsSync(fullPath)) return fullPath;
111
+ }
112
+ return null;
113
+ }
114
+ };
115
+
116
+ //#endregion
117
+ export { SettingsGet as default };
118
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","names":["fsStore.resolveHome"],"sources":["../../../src/commands/settings/get.ts"],"sourcesContent":["/**\n * settings:get 命令\n * 获取指定配置项的值\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Args, Command, Flags } from \"@oclif/core\";\nimport { SettingsDispatcher } from \"@/services/settings/dispatcher.ts\";\nimport { formatJson } from \"@/utils/format.ts\";\nimport * as fsStore from \"@/services/settings/fsStore.ts\";\nimport { ClaudeAdapter } from \"@/services/settings/adapters/claude.ts\";\nimport type { ToolId, Scope, InspectResult } from \"@/domain/types.ts\";\n\nexport default class SettingsGet extends Command {\n static summary = \"View the full configuration file\";\n\n static description = `\n Print the entire configuration file for the selected tool/scope.\n Use --json for structured output or --no-json for plain text.\n `;\n\n static examples = [\n \"<%= config.bin %> <%= command.id %> --tool claude --scope user\",\n \"<%= config.bin %> <%= command.id %> --tool codex --no-json\",\n ];\n\n static args = {\n name: Args.string({\n description: \"Claude variant name (optional). Example: settings:get hxi\",\n required: false,\n }),\n };\n\n static flags = {\n tool: Flags.string({\n char: \"t\",\n description: \"AI CLI tool to manage\",\n options: [\"claude\", \"codex\", \"gemini\"],\n default: \"claude\",\n }),\n scope: Flags.string({\n char: \"s\",\n description: \"Configuration scope\",\n options: [\"user\", \"project\", \"local\", \"system\"],\n default: \"user\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(SettingsGet);\n\n try {\n const tool = flags.tool as ToolId;\n const scope = flags.scope as Scope;\n const data =\n tool === \"claude\" && args.name\n ? await this.inspectClaudeVariant(scope, args.name)\n : await this.inspectViaDispatcher(tool, scope);\n\n if (flags.json) {\n this.log(formatJson({ success: true, data }));\n return;\n }\n\n if (!data.exists) {\n this.warn(`Config file not found: ${data.path}`);\n return;\n }\n\n if (data.content) {\n this.log(data.content);\n } else {\n this.log(\"File is empty.\");\n }\n } catch (error) {\n this.error((error as Error).message, { exit: 1 });\n }\n }\n\n private async inspectViaDispatcher(tool: ToolId, scope: Scope) {\n const dispatcher = new SettingsDispatcher();\n const result = await dispatcher.execute({\n tool,\n scope,\n action: \"inspect\",\n });\n return result.data as InspectResult;\n }\n\n private async inspectClaudeVariant(\n scope: Scope,\n name: string,\n ): Promise<InspectResult> {\n const adapter = new ClaudeAdapter();\n if (!adapter.validateScope(scope)) {\n throw new Error(`Invalid scope for Claude: ${scope}`);\n }\n\n const normalized = name.trim();\n if (!normalized || normalized === \"default\") {\n return this.inspectViaDispatcher(\"claude\", scope);\n }\n\n const basePath = adapter.resolvePath(scope);\n const resolvedBase = fsStore.resolveHome(basePath);\n const directory = path.dirname(resolvedBase);\n const variantPath =\n this.findVariantPath(directory, normalized) ??\n path.join(directory, `settings.${normalized}.json`);\n\n if (!fs.existsSync(variantPath)) {\n return {\n path: variantPath,\n exists: false,\n };\n }\n\n const stats = fs.statSync(variantPath);\n return {\n path: variantPath,\n exists: true,\n content: fs.readFileSync(variantPath, \"utf-8\"),\n size: stats.size,\n lastModified: stats.mtime,\n };\n }\n\n private findVariantPath(directory: string, name: string): string | null {\n const candidates = [`settings.${name}.json`, `settings-${name}.json`];\n\n for (const candidate of candidates) {\n const fullPath = path.join(directory, candidate);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAcA,IAAqB,cAArB,MAAqB,oBAAoB,QAAQ;CAC/C,OAAO,UAAU;CAEjB,OAAO,cAAc;;;;CAKrB,OAAO,WAAW,CAChB,kEACA,6DACD;CAED,OAAO,OAAO,EACZ,MAAM,KAAK,OAAO;EAChB,aAAa;EACb,UAAU;EACX,CAAC,EACH;CAED,OAAO,QAAQ;EACb,MAAM,MAAM,OAAO;GACjB,MAAM;GACN,aAAa;GACb,SAAS;IAAC;IAAU;IAAS;IAAS;GACtC,SAAS;GACV,CAAC;EACF,OAAO,MAAM,OAAO;GAClB,MAAM;GACN,aAAa;GACb,SAAS;IAAC;IAAQ;IAAW;IAAS;IAAS;GAC/C,SAAS;GACV,CAAC;EACH;CAED,MAAM,MAAqB;EACzB,MAAM,EAAE,MAAM,UAAU,MAAM,KAAK,MAAM,YAAY;AAErD,MAAI;GACF,MAAM,OAAO,MAAM;GACnB,MAAM,QAAQ,MAAM;GACpB,MAAM,OACJ,SAAS,YAAY,KAAK,OACtB,MAAM,KAAK,qBAAqB,OAAO,KAAK,KAAK,GACjD,MAAM,KAAK,qBAAqB,MAAM,MAAM;AAElD,OAAI,MAAM,MAAM;AACd,SAAK,IAAI,WAAW;KAAE,SAAS;KAAM;KAAM,CAAC,CAAC;AAC7C;;AAGF,OAAI,CAAC,KAAK,QAAQ;AAChB,SAAK,KAAK,0BAA0B,KAAK,OAAO;AAChD;;AAGF,OAAI,KAAK,QACP,MAAK,IAAI,KAAK,QAAQ;OAEtB,MAAK,IAAI,iBAAiB;WAErB,OAAO;AACd,QAAK,MAAO,MAAgB,SAAS,EAAE,MAAM,GAAG,CAAC;;;CAIrD,MAAc,qBAAqB,MAAc,OAAc;AAO7D,UALe,MADI,IAAI,oBAAoB,CACX,QAAQ;GACtC;GACA;GACA,QAAQ;GACT,CAAC,EACY;;CAGhB,MAAc,qBACZ,OACA,MACwB;EACxB,MAAM,UAAU,IAAI,eAAe;AACnC,MAAI,CAAC,QAAQ,cAAc,MAAM,CAC/B,OAAM,IAAI,MAAM,6BAA6B,QAAQ;EAGvD,MAAM,aAAa,KAAK,MAAM;AAC9B,MAAI,CAAC,cAAc,eAAe,UAChC,QAAO,KAAK,qBAAqB,UAAU,MAAM;EAGnD,MAAM,WAAW,QAAQ,YAAY,MAAM;EAC3C,MAAM,eAAeA,YAAoB,SAAS;EAClD,MAAM,YAAY,KAAK,QAAQ,aAAa;EAC5C,MAAM,cACJ,KAAK,gBAAgB,WAAW,WAAW,IAC3C,KAAK,KAAK,WAAW,YAAY,WAAW,OAAO;AAErD,MAAI,CAAC,GAAG,WAAW,YAAY,CAC7B,QAAO;GACL,MAAM;GACN,QAAQ;GACT;EAGH,MAAM,QAAQ,GAAG,SAAS,YAAY;AACtC,SAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS,GAAG,aAAa,aAAa,QAAQ;GAC9C,MAAM,MAAM;GACZ,cAAc,MAAM;GACrB;;CAGH,AAAQ,gBAAgB,WAAmB,MAA6B;EACtE,MAAM,aAAa,CAAC,YAAY,KAAK,QAAQ,YAAY,KAAK,OAAO;AAErE,OAAK,MAAM,aAAa,YAAY;GAClC,MAAM,WAAW,KAAK,KAAK,WAAW,UAAU;AAChD,OAAI,GAAG,WAAW,SAAS,CACzB,QAAO;;AAGX,SAAO"}
@@ -0,0 +1,19 @@
1
+ import { Command } from "@oclif/core";
2
+ import * as _oclif_core_interfaces4 from "@oclif/core/interfaces";
3
+
4
+ //#region src/commands/settings/inspect.d.ts
5
+
6
+ declare class SettingsInspect extends Command {
7
+ static summary: string;
8
+ static description: string;
9
+ static examples: string[];
10
+ static flags: {
11
+ tool: _oclif_core_interfaces4.OptionFlag<string, _oclif_core_interfaces4.CustomOptions>;
12
+ scope: _oclif_core_interfaces4.OptionFlag<string, _oclif_core_interfaces4.CustomOptions>;
13
+ json: _oclif_core_interfaces4.BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
17
+ //#endregion
18
+ export { SettingsInspect as default };
19
+ //# sourceMappingURL=inspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.d.ts","names":[],"sources":["../../../src/commands/settings/inspect.ts"],"sourcesContent":[],"mappings":";;;;;AAUqC,cAAhB,eAAA,SAAwB,OAAA,CAAR;;;;;IAqCtB,IAAA,oCAAA,CAAA,MAAA,EArCsB,uBAAA,CAAA,aAAA,CAqCtB;IArC8B,KAAA,oCAAA,CAAA,MAAA,wCAAA;IAAO,IAAA,qCAAA,CAAA,OAAA,CAAA;;SAqCrC"}
@@ -0,0 +1,88 @@
1
+ import "../../errors-CAZ5k5YT.js";
2
+ import "../../editor-D4qoje1V.js";
3
+ import { r as formatJson } from "../../format-Cqecj3RS.js";
4
+ import "../../fsStore-BPnFUGta.js";
5
+ import "../../base-BWvHbkly.js";
6
+ import "../../claudeDefault-pd-Kyu6o.js";
7
+ import "../../claude-D7KdpYHQ.js";
8
+ import "../../codex-UJ2PYHA6.js";
9
+ import "../../gemini-Qo5146d_.js";
10
+ import { t as SettingsDispatcher } from "../../dispatcher-Co94YvDc.js";
11
+ import { Command, Flags } from "@oclif/core";
12
+
13
+ //#region src/commands/settings/inspect.ts
14
+ /**
15
+ * settings:inspect 命令
16
+ * 检查配置文件状态
17
+ */
18
+ var SettingsInspect = class SettingsInspect extends Command {
19
+ static summary = "Inspect configuration file status";
20
+ static description = `
21
+ Display information about the configuration file, including:
22
+ - File path
23
+ - Existence status
24
+ - File size
25
+ - Last modified date
26
+ - File contents (if exists)
27
+ `;
28
+ static examples = ["<%= config.bin %> <%= command.id %> --tool claude --scope user", "<%= config.bin %> <%= command.id %> --tool codex --json"];
29
+ static flags = {
30
+ tool: Flags.string({
31
+ char: "t",
32
+ description: "AI CLI tool to manage",
33
+ options: [
34
+ "claude",
35
+ "codex",
36
+ "gemini"
37
+ ],
38
+ default: "claude"
39
+ }),
40
+ scope: Flags.string({
41
+ char: "s",
42
+ description: "Configuration scope",
43
+ options: [
44
+ "user",
45
+ "project",
46
+ "local",
47
+ "system"
48
+ ],
49
+ default: "user"
50
+ }),
51
+ json: Flags.boolean({
52
+ description: "Output JSON (default)",
53
+ default: true,
54
+ allowNo: true
55
+ })
56
+ };
57
+ async run() {
58
+ const { flags } = await this.parse(SettingsInspect);
59
+ try {
60
+ const result = await new SettingsDispatcher().execute({
61
+ tool: flags.tool,
62
+ scope: flags.scope,
63
+ action: "inspect"
64
+ });
65
+ if (flags.json) {
66
+ this.log(formatJson(result));
67
+ return;
68
+ }
69
+ const data = result.data;
70
+ this.log(`Path: ${data.path}`);
71
+ this.log(`Exists: ${data.exists ? "Yes" : "No"}`);
72
+ if (data.exists) {
73
+ if (data.size !== void 0) this.log(`Size: ${data.size} bytes`);
74
+ if (data.lastModified) this.log(`Last Modified: ${data.lastModified.toISOString()}`);
75
+ if (data.content) {
76
+ this.log("\nContents:");
77
+ this.log(data.content);
78
+ }
79
+ }
80
+ } catch (error) {
81
+ this.error(error.message, { exit: 1 });
82
+ }
83
+ }
84
+ };
85
+
86
+ //#endregion
87
+ export { SettingsInspect as default };
88
+ //# sourceMappingURL=inspect.js.map