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.
- package/README.md +276 -1
- package/dist/base-BWvHbkly.js +69 -0
- package/dist/base-BWvHbkly.js.map +1 -0
- package/dist/base-BXJVsMwL.d.ts +45 -0
- package/dist/base-BXJVsMwL.d.ts.map +1 -0
- package/dist/base-DdIJJBHV.js +34 -0
- package/dist/base-DdIJJBHV.js.map +1 -0
- package/dist/base-EQ6uvBQs.d.ts +43 -0
- package/dist/base-EQ6uvBQs.d.ts.map +1 -0
- package/dist/claude-BsdlWM7z.js +31 -0
- package/dist/claude-BsdlWM7z.js.map +1 -0
- package/dist/claude-D7KdpYHQ.js +209 -0
- package/dist/claude-D7KdpYHQ.js.map +1 -0
- package/dist/claudeDefault-pd-Kyu6o.js +19 -0
- package/dist/claudeDefault-pd-Kyu6o.js.map +1 -0
- package/dist/codex-Crifr9cw.js +32 -0
- package/dist/codex-Crifr9cw.js.map +1 -0
- package/dist/codex-UJ2PYHA6.js +85 -0
- package/dist/codex-UJ2PYHA6.js.map +1 -0
- package/dist/commands/settings/get.d.ts +24 -0
- package/dist/commands/settings/get.d.ts.map +1 -0
- package/dist/commands/settings/get.js +118 -0
- package/dist/commands/settings/get.js.map +1 -0
- package/dist/commands/settings/inspect.d.ts +19 -0
- package/dist/commands/settings/inspect.d.ts.map +1 -0
- package/dist/commands/settings/inspect.js +88 -0
- package/dist/commands/settings/inspect.js.map +1 -0
- package/dist/commands/settings/list.d.ts +25 -0
- package/dist/commands/settings/list.d.ts.map +1 -0
- package/dist/commands/settings/list.js +147 -0
- package/dist/commands/settings/list.js.map +1 -0
- package/dist/commands/settings/set.d.ts +22 -0
- package/dist/commands/settings/set.d.ts.map +1 -0
- package/dist/commands/settings/set.js +83 -0
- package/dist/commands/settings/set.js.map +1 -0
- package/dist/commands/settings/switch.d.ts +27 -0
- package/dist/commands/settings/switch.d.ts.map +1 -0
- package/dist/commands/settings/switch.js +164 -0
- package/dist/commands/settings/switch.js.map +1 -0
- package/dist/commands/x/index.d.ts +25 -0
- package/dist/commands/x/index.d.ts.map +1 -0
- package/dist/commands/x/index.js +130 -0
- package/dist/commands/x/index.js.map +1 -0
- package/dist/dispatcher-BUU7wUgm.js +94 -0
- package/dist/dispatcher-BUU7wUgm.js.map +1 -0
- package/dist/dispatcher-Co94YvDc.js +76 -0
- package/dist/dispatcher-Co94YvDc.js.map +1 -0
- package/dist/domain/interfaces.d.ts +3 -0
- package/dist/domain/interfaces.js +1 -0
- package/dist/domain/types.d.ts +2 -0
- package/dist/domain/types.js +1 -0
- package/dist/domain/validators.d.ts +82 -0
- package/dist/domain/validators.d.ts.map +1 -0
- package/dist/domain/validators.js +58 -0
- package/dist/domain/validators.js.map +1 -0
- package/dist/editor-D4qoje1V.js +32 -0
- package/dist/editor-D4qoje1V.js.map +1 -0
- package/dist/errors-CAZ5k5YT.js +89 -0
- package/dist/errors-CAZ5k5YT.js.map +1 -0
- package/dist/format-Cqecj3RS.js +229 -0
- package/dist/format-Cqecj3RS.js.map +1 -0
- package/dist/fsStore-BPnFUGta.js +122 -0
- package/dist/fsStore-BPnFUGta.js.map +1 -0
- package/dist/gemini-Qo5146d_.js +52 -0
- package/dist/gemini-Qo5146d_.js.map +1 -0
- package/dist/interfaces-DRNAGN0l.d.ts +75 -0
- package/dist/interfaces-DRNAGN0l.d.ts.map +1 -0
- package/dist/run.d.ts +1 -0
- package/dist/run.js +15 -0
- package/dist/run.js.map +1 -0
- package/dist/runner-BE7zZq1g.js +89 -0
- package/dist/runner-BE7zZq1g.js.map +1 -0
- package/dist/services/launch/adapters/base.d.ts +4 -0
- package/dist/services/launch/adapters/base.js +4 -0
- package/dist/services/launch/adapters/claude.d.ts +25 -0
- package/dist/services/launch/adapters/claude.d.ts.map +1 -0
- package/dist/services/launch/adapters/claude.js +5 -0
- package/dist/services/launch/adapters/codex.d.ts +26 -0
- package/dist/services/launch/adapters/codex.d.ts.map +1 -0
- package/dist/services/launch/adapters/codex.js +5 -0
- package/dist/services/launch/dispatcher.d.ts +44 -0
- package/dist/services/launch/dispatcher.d.ts.map +1 -0
- package/dist/services/launch/dispatcher.js +8 -0
- package/dist/services/settings/adapters/base.d.ts +4 -0
- package/dist/services/settings/adapters/base.js +5 -0
- package/dist/services/settings/adapters/claude.d.ts +43 -0
- package/dist/services/settings/adapters/claude.d.ts.map +1 -0
- package/dist/services/settings/adapters/claude.js +9 -0
- package/dist/services/settings/adapters/codex.d.ts +45 -0
- package/dist/services/settings/adapters/codex.d.ts.map +1 -0
- package/dist/services/settings/adapters/codex.js +6 -0
- package/dist/services/settings/adapters/gemini.d.ts +32 -0
- package/dist/services/settings/adapters/gemini.d.ts.map +1 -0
- package/dist/services/settings/adapters/gemini.js +6 -0
- package/dist/services/settings/dispatcher.d.ts +36 -0
- package/dist/services/settings/dispatcher.d.ts.map +1 -0
- package/dist/services/settings/dispatcher.js +12 -0
- package/dist/services/settings/fsStore.d.ts +46 -0
- package/dist/services/settings/fsStore.d.ts.map +1 -0
- package/dist/services/settings/fsStore.js +4 -0
- package/dist/services/settings/templates/claudeDefault.d.ts +20 -0
- package/dist/services/settings/templates/claudeDefault.d.ts.map +1 -0
- package/dist/services/settings/templates/claudeDefault.js +3 -0
- package/dist/types--0tjriPy.d.ts +104 -0
- package/dist/types--0tjriPy.d.ts.map +1 -0
- package/dist/utils/editor.d.ts +6 -0
- package/dist/utils/editor.d.ts.map +1 -0
- package/dist/utils/editor.js +4 -0
- package/dist/utils/errors.d.ts +61 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +3 -0
- package/dist/utils/format.d.ts +20 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +3 -0
- package/dist/utils/logger.d.ts +32 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +46 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/runner.d.ts +36 -0
- package/dist/utils/runner.d.ts.map +1 -0
- package/dist/utils/runner.js +3 -0
- 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
|