xling 0.0.2 → 0.2.4
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 +229 -1
- package/dist/base-BlaKDtDu.d.ts +43 -0
- package/dist/base-BlaKDtDu.d.ts.map +1 -0
- package/dist/base-Cm9xh6sW.js +69 -0
- package/dist/base-Cm9xh6sW.js.map +1 -0
- package/dist/claude-l3zomoHg.js +209 -0
- package/dist/claude-l3zomoHg.js.map +1 -0
- package/dist/claudeDefault-Fk1-kHLE.js +19 -0
- package/dist/claudeDefault-Fk1-kHLE.js.map +1 -0
- package/dist/codex-CR8xqNrZ.js +85 -0
- package/dist/codex-CR8xqNrZ.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/dispatcher-JXm3OqRQ.js +76 -0
- package/dist/dispatcher-JXm3OqRQ.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-i-3731TM.js +122 -0
- package/dist/fsStore-i-3731TM.js.map +1 -0
- package/dist/gemini-aNNm-QGE.js +52 -0
- package/dist/gemini-aNNm-QGE.js.map +1 -0
- package/dist/interfaces-CriQW6hF.d.ts +41 -0
- package/dist/interfaces-CriQW6hF.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/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-BfNSo2rs.d.ts +71 -0
- package/dist/types-BfNSo2rs.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/package.json +66 -6
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import "../../errors-CAZ5k5YT.js";
|
|
2
|
+
import "../../editor-D4qoje1V.js";
|
|
3
|
+
import { r as formatJson } from "../../format-Cqecj3RS.js";
|
|
4
|
+
import "../../fsStore-i-3731TM.js";
|
|
5
|
+
import "../../base-Cm9xh6sW.js";
|
|
6
|
+
import "../../claudeDefault-Fk1-kHLE.js";
|
|
7
|
+
import "../../claude-l3zomoHg.js";
|
|
8
|
+
import "../../codex-CR8xqNrZ.js";
|
|
9
|
+
import "../../gemini-aNNm-QGE.js";
|
|
10
|
+
import { t as SettingsDispatcher } from "../../dispatcher-JXm3OqRQ.js";
|
|
11
|
+
import { Command, Flags } from "@oclif/core";
|
|
12
|
+
|
|
13
|
+
//#region src/commands/settings/set.ts
|
|
14
|
+
/**
|
|
15
|
+
* settings:set 命令
|
|
16
|
+
* 设置配置项的值
|
|
17
|
+
*/
|
|
18
|
+
var SettingsSet = class SettingsSet extends Command {
|
|
19
|
+
static summary = "Open settings files in your IDE (Claude only)";
|
|
20
|
+
static description = `
|
|
21
|
+
Create or open Claude settings variants in your preferred editor.
|
|
22
|
+
Provide --name to edit settings.<name>.json (default: settings.json).
|
|
23
|
+
`;
|
|
24
|
+
static examples = ["<%= config.bin %> <%= command.id %> --tool claude --scope user --name hxi", "<%= config.bin %> <%= command.id %> --tool claude --scope project --name default --ide cursor"];
|
|
25
|
+
static args = {};
|
|
26
|
+
static flags = {
|
|
27
|
+
tool: Flags.string({
|
|
28
|
+
char: "t",
|
|
29
|
+
description: "AI CLI tool to manage",
|
|
30
|
+
options: [
|
|
31
|
+
"claude",
|
|
32
|
+
"codex",
|
|
33
|
+
"gemini"
|
|
34
|
+
],
|
|
35
|
+
default: "claude"
|
|
36
|
+
}),
|
|
37
|
+
scope: Flags.string({
|
|
38
|
+
char: "s",
|
|
39
|
+
description: "Configuration scope",
|
|
40
|
+
options: [
|
|
41
|
+
"user",
|
|
42
|
+
"project",
|
|
43
|
+
"local",
|
|
44
|
+
"system"
|
|
45
|
+
],
|
|
46
|
+
default: "user"
|
|
47
|
+
}),
|
|
48
|
+
name: Flags.string({ description: "Claude variant name (e.g., hxi). Creates settings.<name>.json if missing and opens it in the IDE." }),
|
|
49
|
+
ide: Flags.string({
|
|
50
|
+
description: "Editor command or alias (default: code for VS Code)",
|
|
51
|
+
default: "code"
|
|
52
|
+
}),
|
|
53
|
+
json: Flags.boolean({
|
|
54
|
+
description: "Output JSON (default)",
|
|
55
|
+
default: true,
|
|
56
|
+
allowNo: true
|
|
57
|
+
})
|
|
58
|
+
};
|
|
59
|
+
async run() {
|
|
60
|
+
const { flags } = await this.parse(SettingsSet);
|
|
61
|
+
try {
|
|
62
|
+
if (flags.tool !== "claude") this.error("Editing settings files is currently only supported for Claude.", { exit: 1 });
|
|
63
|
+
const result = await new SettingsDispatcher().execute({
|
|
64
|
+
tool: flags.tool,
|
|
65
|
+
scope: flags.scope,
|
|
66
|
+
action: "edit",
|
|
67
|
+
name: flags.name,
|
|
68
|
+
ide: flags.ide
|
|
69
|
+
});
|
|
70
|
+
if (flags.json) this.log(formatJson(result));
|
|
71
|
+
else {
|
|
72
|
+
this.log(result.message ?? "Opened settings file");
|
|
73
|
+
if (result.filePath) this.log(`File: ${result.filePath}`);
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
this.error(error.message, { exit: 1 });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
//#endregion
|
|
82
|
+
export { SettingsSet as default };
|
|
83
|
+
//# sourceMappingURL=set.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set.js","names":[],"sources":["../../../src/commands/settings/set.ts"],"sourcesContent":["/**\n * settings:set 命令\n * 设置配置项的值\n */\n\nimport { Command, Flags } from \"@oclif/core\";\nimport { SettingsDispatcher } from \"@/services/settings/dispatcher.ts\";\nimport { formatJson } from \"@/utils/format.ts\";\nimport type { ToolId, Scope } from \"@/domain/types.ts\";\n\nexport default class SettingsSet extends Command {\n static summary = \"Open settings files in your IDE (Claude only)\";\n\n static description = `\n Create or open Claude settings variants in your preferred editor.\n Provide --name to edit settings.<name>.json (default: settings.json).\n `;\n\n static examples = [\n \"<%= config.bin %> <%= command.id %> --tool claude --scope user --name hxi\",\n \"<%= config.bin %> <%= command.id %> --tool claude --scope project --name default --ide cursor\",\n ];\n\n static args = {};\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 name: Flags.string({\n description:\n \"Claude variant name (e.g., hxi). Creates settings.<name>.json if missing and opens it in the IDE.\",\n }),\n ide: Flags.string({\n description: \"Editor command or alias (default: code for VS Code)\",\n default: \"code\",\n }),\n json: Flags.boolean({\n description: \"Output JSON (default)\",\n default: true,\n allowNo: true,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(SettingsSet);\n\n try {\n if (flags.tool !== \"claude\") {\n this.error(\n \"Editing settings files is currently only supported for Claude.\",\n {\n exit: 1,\n },\n );\n }\n\n const dispatcher = new SettingsDispatcher();\n const result = await dispatcher.execute({\n tool: flags.tool as ToolId,\n scope: flags.scope as Scope,\n action: \"edit\",\n name: flags.name,\n ide: flags.ide,\n });\n\n if (flags.json) {\n this.log(formatJson(result));\n } else {\n this.log(result.message ?? \"Opened settings file\");\n if (result.filePath) {\n this.log(`File: ${result.filePath}`);\n }\n }\n } catch (error) {\n this.error((error as Error).message, { exit: 1 });\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAUA,IAAqB,cAArB,MAAqB,oBAAoB,QAAQ;CAC/C,OAAO,UAAU;CAEjB,OAAO,cAAc;;;;CAKrB,OAAO,WAAW,CAChB,6EACA,gGACD;CAED,OAAO,OAAO,EAAE;CAEhB,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;EACF,MAAM,MAAM,OAAO,EACjB,aACE,qGACH,CAAC;EACF,KAAK,MAAM,OAAO;GAChB,aAAa;GACb,SAAS;GACV,CAAC;EACF,MAAM,MAAM,QAAQ;GAClB,aAAa;GACb,SAAS;GACT,SAAS;GACV,CAAC;EACH;CAED,MAAM,MAAqB;EACzB,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,YAAY;AAE/C,MAAI;AACF,OAAI,MAAM,SAAS,SACjB,MAAK,MACH,kEACA,EACE,MAAM,GACP,CACF;GAIH,MAAM,SAAS,MADI,IAAI,oBAAoB,CACX,QAAQ;IACtC,MAAM,MAAM;IACZ,OAAO,MAAM;IACb,QAAQ;IACR,MAAM,MAAM;IACZ,KAAK,MAAM;IACZ,CAAC;AAEF,OAAI,MAAM,KACR,MAAK,IAAI,WAAW,OAAO,CAAC;QACvB;AACL,SAAK,IAAI,OAAO,WAAW,uBAAuB;AAClD,QAAI,OAAO,SACT,MAAK,IAAI,SAAS,OAAO,WAAW;;WAGjC,OAAO;AACd,QAAK,MAAO,MAAgB,SAAS,EAAE,MAAM,GAAG,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
import * as _oclif_core_interfaces0 from "@oclif/core/interfaces";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/settings/switch.d.ts
|
|
5
|
+
|
|
6
|
+
declare class SettingsSwitch extends Command {
|
|
7
|
+
static summary: string;
|
|
8
|
+
static description: string;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static args: {
|
|
11
|
+
profile: _oclif_core_interfaces0.Arg<string, 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
|
+
json: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
17
|
+
force: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
18
|
+
backup: _oclif_core_interfaces0.BooleanFlag<boolean>;
|
|
19
|
+
};
|
|
20
|
+
run(): Promise<void>;
|
|
21
|
+
private handleClaudeSwitch;
|
|
22
|
+
private promptClaudeAction;
|
|
23
|
+
private printResult;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { SettingsSwitch as default };
|
|
27
|
+
//# sourceMappingURL=switch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch.d.ts","names":[],"sources":["../../../src/commands/settings/switch.ts"],"sourcesContent":[],"mappings":";;;;;cAYqB,cAAA,SAAuB,OAAA;;;;;;;;;IAgD7B,KAAA,oCAAA,CAAA,MAAA,wCAAA;IAhD6B,IAAA,qCAAA,CAAA,OAAA,CAAA;IAAO,KAAA,qCAAA,CAAA,OAAA,CAAA;;;SAgDpC"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import "../../errors-CAZ5k5YT.js";
|
|
2
|
+
import "../../editor-D4qoje1V.js";
|
|
3
|
+
import { r as formatJson } from "../../format-Cqecj3RS.js";
|
|
4
|
+
import "../../fsStore-i-3731TM.js";
|
|
5
|
+
import "../../base-Cm9xh6sW.js";
|
|
6
|
+
import "../../claudeDefault-Fk1-kHLE.js";
|
|
7
|
+
import "../../claude-l3zomoHg.js";
|
|
8
|
+
import "../../codex-CR8xqNrZ.js";
|
|
9
|
+
import "../../gemini-aNNm-QGE.js";
|
|
10
|
+
import { t as SettingsDispatcher } from "../../dispatcher-JXm3OqRQ.js";
|
|
11
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
12
|
+
import readline from "node:readline/promises";
|
|
13
|
+
import { stdin, stdout } from "node:process";
|
|
14
|
+
|
|
15
|
+
//#region src/commands/settings/switch.ts
|
|
16
|
+
/**
|
|
17
|
+
* settings:switch 命令
|
|
18
|
+
* 切换 profile(仅 Codex 支持)
|
|
19
|
+
*/
|
|
20
|
+
var SettingsSwitch = class SettingsSwitch extends Command {
|
|
21
|
+
static summary = "Switch Codex profiles or Claude settings variants";
|
|
22
|
+
static description = `
|
|
23
|
+
Switch to a different profile configuration for Codex
|
|
24
|
+
or activate a specific settings.<variant>.json for Claude.
|
|
25
|
+
`;
|
|
26
|
+
static examples = [
|
|
27
|
+
"<%= config.bin %> <%= command.id %> oss --tool codex",
|
|
28
|
+
"<%= config.bin %> <%= command.id %> production --tool codex",
|
|
29
|
+
"<%= config.bin %> <%= command.id %> hxi --tool claude --scope user"
|
|
30
|
+
];
|
|
31
|
+
static args = { profile: Args.string({
|
|
32
|
+
description: "Profile name to switch to",
|
|
33
|
+
required: true
|
|
34
|
+
}) };
|
|
35
|
+
static flags = {
|
|
36
|
+
tool: Flags.string({
|
|
37
|
+
char: "t",
|
|
38
|
+
description: "AI CLI tool to manage",
|
|
39
|
+
options: [
|
|
40
|
+
"claude",
|
|
41
|
+
"codex",
|
|
42
|
+
"gemini"
|
|
43
|
+
],
|
|
44
|
+
default: "claude"
|
|
45
|
+
}),
|
|
46
|
+
scope: Flags.string({
|
|
47
|
+
char: "s",
|
|
48
|
+
description: "Configuration scope",
|
|
49
|
+
options: [
|
|
50
|
+
"user",
|
|
51
|
+
"project",
|
|
52
|
+
"local",
|
|
53
|
+
"system"
|
|
54
|
+
],
|
|
55
|
+
default: "user"
|
|
56
|
+
}),
|
|
57
|
+
json: Flags.boolean({
|
|
58
|
+
description: "Output JSON instead of interactive text",
|
|
59
|
+
default: false
|
|
60
|
+
}),
|
|
61
|
+
force: Flags.boolean({
|
|
62
|
+
description: "Skip confirmation prompts (Claude only)",
|
|
63
|
+
default: false
|
|
64
|
+
}),
|
|
65
|
+
backup: Flags.boolean({
|
|
66
|
+
description: "Create a .bak backup when switching (Claude only)",
|
|
67
|
+
default: false
|
|
68
|
+
})
|
|
69
|
+
};
|
|
70
|
+
async run() {
|
|
71
|
+
const { args, flags } = await this.parse(SettingsSwitch);
|
|
72
|
+
try {
|
|
73
|
+
const dispatcher = new SettingsDispatcher();
|
|
74
|
+
const result = flags.tool === "claude" ? await this.handleClaudeSwitch(dispatcher, args.profile, flags) : await dispatcher.execute({
|
|
75
|
+
tool: flags.tool,
|
|
76
|
+
scope: flags.scope,
|
|
77
|
+
action: "switch-profile",
|
|
78
|
+
profile: args.profile
|
|
79
|
+
});
|
|
80
|
+
if (!result) return;
|
|
81
|
+
this.printResult(result, args.profile, flags);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
this.error(error.message, { exit: 1 });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async handleClaudeSwitch(dispatcher, profile, flags) {
|
|
87
|
+
if (flags.json && !flags.force) this.error("--json requires --force when switching Claude settings.", { exit: 1 });
|
|
88
|
+
const preview = await dispatcher.execute({
|
|
89
|
+
tool: "claude",
|
|
90
|
+
scope: flags.scope,
|
|
91
|
+
action: "switch-profile",
|
|
92
|
+
profile,
|
|
93
|
+
switchOptions: { preview: true }
|
|
94
|
+
});
|
|
95
|
+
if (preview.diff) this.log("Proposed changes:\n" + preview.diff);
|
|
96
|
+
else {
|
|
97
|
+
this.log("No differences detected. Current settings already match the selected variant.");
|
|
98
|
+
return preview;
|
|
99
|
+
}
|
|
100
|
+
let backup = Boolean(flags.backup);
|
|
101
|
+
if (!flags.force && !backup) {
|
|
102
|
+
const action = await this.promptClaudeAction();
|
|
103
|
+
if (action === "cancel") {
|
|
104
|
+
this.log("Switch cancelled.");
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
backup = action === "backup";
|
|
108
|
+
}
|
|
109
|
+
const result = await dispatcher.execute({
|
|
110
|
+
tool: "claude",
|
|
111
|
+
scope: flags.scope,
|
|
112
|
+
action: "switch-profile",
|
|
113
|
+
profile,
|
|
114
|
+
switchOptions: { backup }
|
|
115
|
+
});
|
|
116
|
+
result.diff = preview.diff;
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
async promptClaudeAction() {
|
|
120
|
+
const rl = readline.createInterface({
|
|
121
|
+
input: stdin,
|
|
122
|
+
output: stdout
|
|
123
|
+
});
|
|
124
|
+
try {
|
|
125
|
+
while (true) {
|
|
126
|
+
const answer = (await rl.question("Choose action ([o]verwrite/[b]ackup/[c]ancel): ")).trim().toLowerCase();
|
|
127
|
+
if ([
|
|
128
|
+
"overwrite",
|
|
129
|
+
"backup",
|
|
130
|
+
"cancel"
|
|
131
|
+
].includes(answer)) return answer;
|
|
132
|
+
if ([
|
|
133
|
+
"o",
|
|
134
|
+
"b",
|
|
135
|
+
"c"
|
|
136
|
+
].includes(answer)) return {
|
|
137
|
+
o: "overwrite",
|
|
138
|
+
b: "backup",
|
|
139
|
+
c: "cancel"
|
|
140
|
+
}[answer];
|
|
141
|
+
}
|
|
142
|
+
} finally {
|
|
143
|
+
rl.close();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
printResult(result, profile, flags) {
|
|
147
|
+
if (flags.json) {
|
|
148
|
+
this.log(formatJson(result));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (result.preview) {
|
|
152
|
+
this.log("Preview only. No changes applied.");
|
|
153
|
+
if (result.diff) this.log(result.diff);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.log(result.message ?? `✓ Switched to profile: ${profile}`);
|
|
157
|
+
if (result.filePath) this.log(` File: ${result.filePath}`);
|
|
158
|
+
if (result.diff) this.log("Applied diff:\n" + result.diff);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
//#endregion
|
|
163
|
+
export { SettingsSwitch as default };
|
|
164
|
+
//# sourceMappingURL=switch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch.js","names":[],"sources":["../../../src/commands/settings/switch.ts"],"sourcesContent":["/**\n * settings:switch 命令\n * 切换 profile(仅 Codex 支持)\n */\n\nimport { Args, Command, Flags } from \"@oclif/core\";\nimport readline from \"node:readline/promises\";\nimport { stdin as input, stdout as output } from \"node:process\";\nimport { SettingsDispatcher } from \"@/services/settings/dispatcher.ts\";\nimport { formatJson } from \"@/utils/format.ts\";\nimport type { ToolId, Scope, SettingsResult } from \"@/domain/types.ts\";\n\nexport default class SettingsSwitch extends Command {\n static summary = \"Switch Codex profiles or Claude settings variants\";\n\n static description = `\n Switch to a different profile configuration for Codex\n or activate a specific settings.<variant>.json for Claude.\n `;\n\n static examples = [\n \"<%= config.bin %> <%= command.id %> oss --tool codex\",\n \"<%= config.bin %> <%= command.id %> production --tool codex\",\n \"<%= config.bin %> <%= command.id %> hxi --tool claude --scope user\",\n ];\n\n static args = {\n profile: Args.string({\n description: \"Profile name to switch to\",\n required: true,\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 json: Flags.boolean({\n description: \"Output JSON instead of interactive text\",\n default: false,\n }),\n force: Flags.boolean({\n description: \"Skip confirmation prompts (Claude only)\",\n default: false,\n }),\n backup: Flags.boolean({\n description: \"Create a .bak backup when switching (Claude only)\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(SettingsSwitch);\n\n try {\n const dispatcher = new SettingsDispatcher();\n const result =\n flags.tool === \"claude\"\n ? await this.handleClaudeSwitch(dispatcher, args.profile, flags)\n : await dispatcher.execute({\n tool: flags.tool as ToolId,\n scope: flags.scope as Scope,\n action: \"switch-profile\",\n profile: args.profile,\n });\n\n if (!result) {\n return;\n }\n\n this.printResult(result, args.profile, flags);\n } catch (error) {\n this.error((error as Error).message, { exit: 1 });\n }\n }\n\n private async handleClaudeSwitch(\n dispatcher: SettingsDispatcher,\n profile: string,\n flags: Record<string, any>,\n ): Promise<SettingsResult | null> {\n if (flags.json && !flags.force) {\n this.error(\"--json requires --force when switching Claude settings.\", {\n exit: 1,\n });\n }\n\n const preview = await dispatcher.execute({\n tool: \"claude\",\n scope: flags.scope as Scope,\n action: \"switch-profile\",\n profile,\n switchOptions: { preview: true },\n });\n\n if (preview.diff) {\n this.log(\"Proposed changes:\\n\" + preview.diff);\n } else {\n this.log(\n \"No differences detected. Current settings already match the selected variant.\",\n );\n return preview;\n }\n\n let backup = Boolean(flags.backup);\n if (!flags.force && !backup) {\n const action = await this.promptClaudeAction();\n if (action === \"cancel\") {\n this.log(\"Switch cancelled.\");\n return null;\n }\n backup = action === \"backup\";\n }\n\n const result = await dispatcher.execute({\n tool: \"claude\",\n scope: flags.scope as Scope,\n action: \"switch-profile\",\n profile,\n switchOptions: { backup },\n });\n result.diff = preview.diff;\n return result;\n }\n\n private async promptClaudeAction(): Promise<\n \"overwrite\" | \"backup\" | \"cancel\"\n > {\n const rl = readline.createInterface({ input, output });\n try {\n while (true) {\n const answer = (\n await rl.question(\"Choose action ([o]verwrite/[b]ackup/[c]ancel): \")\n )\n .trim()\n .toLowerCase();\n if ([\"overwrite\", \"backup\", \"cancel\"].includes(answer)) {\n return answer as \"overwrite\" | \"backup\" | \"cancel\";\n }\n if ([\"o\", \"b\", \"c\"].includes(answer)) {\n return {\n o: \"overwrite\",\n b: \"backup\",\n c: \"cancel\",\n }[answer] as \"overwrite\" | \"backup\" | \"cancel\";\n }\n }\n } finally {\n rl.close();\n }\n }\n\n private printResult(\n result: SettingsResult,\n profile: string,\n flags: Record<string, any>,\n ): void {\n if (flags.json) {\n this.log(formatJson(result));\n return;\n }\n\n if (result.preview) {\n this.log(\"Preview only. No changes applied.\");\n if (result.diff) {\n this.log(result.diff);\n }\n return;\n }\n\n this.log(result.message ?? `✓ Switched to profile: ${profile}`);\n if (result.filePath) {\n this.log(` File: ${result.filePath}`);\n }\n if (result.diff) {\n this.log(\"Applied diff:\\n\" + result.diff);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { c as UnsupportedToolError } from "./errors-CAZ5k5YT.js";
|
|
2
|
+
import { t as ClaudeAdapter } from "./claude-l3zomoHg.js";
|
|
3
|
+
import { t as CodexAdapter } from "./codex-CR8xqNrZ.js";
|
|
4
|
+
import { t as GeminiAdapter } from "./gemini-aNNm-QGE.js";
|
|
5
|
+
|
|
6
|
+
//#region src/services/settings/dispatcher.ts
|
|
7
|
+
/**
|
|
8
|
+
* Settings 调度器
|
|
9
|
+
*
|
|
10
|
+
* 体现 SOLID 原则:
|
|
11
|
+
* - OCP: 新增工具只需在构造函数中注册适配器
|
|
12
|
+
* - DIP: 依赖 SettingsAdapter 接口,不依赖具体实现
|
|
13
|
+
* - SRP: 只负责调度,不处理具体逻辑
|
|
14
|
+
*/
|
|
15
|
+
var SettingsDispatcher = class {
|
|
16
|
+
adapters;
|
|
17
|
+
constructor() {
|
|
18
|
+
this.adapters = /* @__PURE__ */ new Map();
|
|
19
|
+
this.adapters.set("claude", new ClaudeAdapter());
|
|
20
|
+
this.adapters.set("codex", new CodexAdapter());
|
|
21
|
+
this.adapters.set("gemini", new GeminiAdapter());
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 执行 settings 操作
|
|
25
|
+
*/
|
|
26
|
+
async execute(payload) {
|
|
27
|
+
const adapter = this.getAdapter(payload.tool);
|
|
28
|
+
switch (payload.action) {
|
|
29
|
+
case "list": return {
|
|
30
|
+
success: true,
|
|
31
|
+
data: await adapter.list(payload.scope)
|
|
32
|
+
};
|
|
33
|
+
case "switch-profile":
|
|
34
|
+
if (!payload.profile) throw new Error("Profile is required for switch-profile action");
|
|
35
|
+
if (!adapter.switchProfile) throw new Error(`Tool ${payload.tool} does not support profile switching`);
|
|
36
|
+
return await adapter.switchProfile(payload.scope, payload.profile, payload.switchOptions);
|
|
37
|
+
case "edit":
|
|
38
|
+
if (!adapter.edit) throw new Error(`Tool ${payload.tool} does not support editing via CLI`);
|
|
39
|
+
return await adapter.edit(payload.scope, {
|
|
40
|
+
name: payload.name,
|
|
41
|
+
ide: payload.ide
|
|
42
|
+
});
|
|
43
|
+
case "inspect":
|
|
44
|
+
if (!adapter.inspect) throw new Error(`Tool ${payload.tool} does not support inspect action`);
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
data: await adapter.inspect(payload.scope)
|
|
48
|
+
};
|
|
49
|
+
default: throw new Error(`Unsupported action: ${payload.action}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 获取适配器
|
|
54
|
+
*/
|
|
55
|
+
getAdapter(tool) {
|
|
56
|
+
const adapter = this.adapters.get(tool);
|
|
57
|
+
if (!adapter) throw new UnsupportedToolError(tool);
|
|
58
|
+
return adapter;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 注册新的适配器(扩展点)
|
|
62
|
+
*/
|
|
63
|
+
registerAdapter(adapter) {
|
|
64
|
+
this.adapters.set(adapter.toolId, adapter);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 获取所有支持的工具
|
|
68
|
+
*/
|
|
69
|
+
getSupportedTools() {
|
|
70
|
+
return Array.from(this.adapters.keys());
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { SettingsDispatcher as t };
|
|
76
|
+
//# sourceMappingURL=dispatcher-JXm3OqRQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher-JXm3OqRQ.js","names":[],"sources":["../src/services/settings/dispatcher.ts"],"sourcesContent":["/**\n * Settings 调度器\n * 负责将请求路由到对应的适配器(DIP 原则)\n */\n\nimport type { SettingsAdapter } from \"@/domain/interfaces.ts\";\nimport type {\n SettingsPayload,\n SettingsResult,\n ToolId,\n} from \"@/domain/types.ts\";\nimport { ClaudeAdapter } from \"./adapters/claude.ts\";\nimport { CodexAdapter } from \"./adapters/codex.ts\";\nimport { GeminiAdapter } from \"./adapters/gemini.ts\";\nimport { UnsupportedToolError } from \"@/utils/errors.ts\";\n\n/**\n * Settings 调度器\n *\n * 体现 SOLID 原则:\n * - OCP: 新增工具只需在构造函数中注册适配器\n * - DIP: 依赖 SettingsAdapter 接口,不依赖具体实现\n * - SRP: 只负责调度,不处理具体逻辑\n */\nexport class SettingsDispatcher {\n private adapters: Map<ToolId, SettingsAdapter>;\n\n constructor() {\n // 注册所有适配器\n this.adapters = new Map<ToolId, SettingsAdapter>();\n this.adapters.set(\"claude\", new ClaudeAdapter());\n this.adapters.set(\"codex\", new CodexAdapter());\n this.adapters.set(\"gemini\", new GeminiAdapter());\n }\n\n /**\n * 执行 settings 操作\n */\n async execute(payload: SettingsPayload): Promise<SettingsResult> {\n const adapter = this.getAdapter(payload.tool);\n\n switch (payload.action) {\n case \"list\":\n return {\n success: true,\n data: await adapter.list(payload.scope),\n };\n\n case \"switch-profile\":\n if (!payload.profile) {\n throw new Error(\"Profile is required for switch-profile action\");\n }\n if (!adapter.switchProfile) {\n throw new Error(\n `Tool ${payload.tool} does not support profile switching`,\n );\n }\n return await adapter.switchProfile(\n payload.scope,\n payload.profile,\n payload.switchOptions,\n );\n\n case \"edit\":\n if (!adapter.edit) {\n throw new Error(\n `Tool ${payload.tool} does not support editing via CLI`,\n );\n }\n return await adapter.edit(payload.scope, {\n name: payload.name,\n ide: payload.ide,\n });\n\n case \"inspect\":\n if (!adapter.inspect) {\n throw new Error(\n `Tool ${payload.tool} does not support inspect action`,\n );\n }\n return {\n success: true,\n data: await adapter.inspect(payload.scope),\n };\n\n default:\n throw new Error(`Unsupported action: ${payload.action}`);\n }\n }\n\n /**\n * 获取适配器\n */\n private getAdapter(tool: ToolId): SettingsAdapter {\n const adapter = this.adapters.get(tool);\n if (!adapter) {\n throw new UnsupportedToolError(tool);\n }\n return adapter;\n }\n\n /**\n * 注册新的适配器(扩展点)\n */\n registerAdapter(adapter: SettingsAdapter): void {\n this.adapters.set(adapter.toolId, adapter);\n }\n\n /**\n * 获取所有支持的工具\n */\n getSupportedTools(): ToolId[] {\n return Array.from(this.adapters.keys());\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAwBA,IAAa,qBAAb,MAAgC;CAC9B,AAAQ;CAER,cAAc;AAEZ,OAAK,2BAAW,IAAI,KAA8B;AAClD,OAAK,SAAS,IAAI,UAAU,IAAI,eAAe,CAAC;AAChD,OAAK,SAAS,IAAI,SAAS,IAAI,cAAc,CAAC;AAC9C,OAAK,SAAS,IAAI,UAAU,IAAI,eAAe,CAAC;;;;;CAMlD,MAAM,QAAQ,SAAmD;EAC/D,MAAM,UAAU,KAAK,WAAW,QAAQ,KAAK;AAE7C,UAAQ,QAAQ,QAAhB;GACE,KAAK,OACH,QAAO;IACL,SAAS;IACT,MAAM,MAAM,QAAQ,KAAK,QAAQ,MAAM;IACxC;GAEH,KAAK;AACH,QAAI,CAAC,QAAQ,QACX,OAAM,IAAI,MAAM,gDAAgD;AAElE,QAAI,CAAC,QAAQ,cACX,OAAM,IAAI,MACR,QAAQ,QAAQ,KAAK,qCACtB;AAEH,WAAO,MAAM,QAAQ,cACnB,QAAQ,OACR,QAAQ,SACR,QAAQ,cACT;GAEH,KAAK;AACH,QAAI,CAAC,QAAQ,KACX,OAAM,IAAI,MACR,QAAQ,QAAQ,KAAK,mCACtB;AAEH,WAAO,MAAM,QAAQ,KAAK,QAAQ,OAAO;KACvC,MAAM,QAAQ;KACd,KAAK,QAAQ;KACd,CAAC;GAEJ,KAAK;AACH,QAAI,CAAC,QAAQ,QACX,OAAM,IAAI,MACR,QAAQ,QAAQ,KAAK,kCACtB;AAEH,WAAO;KACL,SAAS;KACT,MAAM,MAAM,QAAQ,QAAQ,QAAQ,MAAM;KAC3C;GAEH,QACE,OAAM,IAAI,MAAM,uBAAuB,QAAQ,SAAS;;;;;;CAO9D,AAAQ,WAAW,MAA+B;EAChD,MAAM,UAAU,KAAK,SAAS,IAAI,KAAK;AACvC,MAAI,CAAC,QACH,OAAM,IAAI,qBAAqB,KAAK;AAEtC,SAAO;;;;;CAMT,gBAAgB,SAAgC;AAC9C,OAAK,SAAS,IAAI,QAAQ,QAAQ,QAAQ;;;;;CAM5C,oBAA8B;AAC5B,SAAO,MAAM,KAAK,KAAK,SAAS,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as SettingAction, c as SettingsPayload, d as ToolId, i as Scope, l as SettingsResult, n as InspectResult, o as SettingsFileEntry, r as OutputFormat, s as SettingsListData, t as EditOptions, u as SwitchOptions } from "../types-BfNSo2rs.js";
|
|
2
|
+
export { EditOptions, InspectResult, OutputFormat, Scope, SettingAction, SettingsFileEntry, SettingsListData, SettingsPayload, SettingsResult, SwitchOptions, ToolId };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/domain/validators.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ToolId 验证 schema
|
|
7
|
+
*/
|
|
8
|
+
declare const ToolIdSchema: z.ZodEnum<{
|
|
9
|
+
claude: "claude";
|
|
10
|
+
codex: "codex";
|
|
11
|
+
gemini: "gemini";
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Scope 验证 schema
|
|
15
|
+
*/
|
|
16
|
+
declare const ScopeSchema: z.ZodEnum<{
|
|
17
|
+
user: "user";
|
|
18
|
+
project: "project";
|
|
19
|
+
local: "local";
|
|
20
|
+
system: "system";
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* SettingAction 验证 schema
|
|
24
|
+
*/
|
|
25
|
+
declare const SettingActionSchema: z.ZodEnum<{
|
|
26
|
+
list: "list";
|
|
27
|
+
edit: "edit";
|
|
28
|
+
"switch-profile": "switch-profile";
|
|
29
|
+
inspect: "inspect";
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* SettingsPayload 验证 schema
|
|
33
|
+
*/
|
|
34
|
+
declare const SettingsPayloadSchema: z.ZodObject<{
|
|
35
|
+
tool: z.ZodEnum<{
|
|
36
|
+
claude: "claude";
|
|
37
|
+
codex: "codex";
|
|
38
|
+
gemini: "gemini";
|
|
39
|
+
}>;
|
|
40
|
+
scope: z.ZodEnum<{
|
|
41
|
+
user: "user";
|
|
42
|
+
project: "project";
|
|
43
|
+
local: "local";
|
|
44
|
+
system: "system";
|
|
45
|
+
}>;
|
|
46
|
+
action: z.ZodEnum<{
|
|
47
|
+
list: "list";
|
|
48
|
+
edit: "edit";
|
|
49
|
+
"switch-profile": "switch-profile";
|
|
50
|
+
inspect: "inspect";
|
|
51
|
+
}>;
|
|
52
|
+
profile: z.ZodOptional<z.ZodString>;
|
|
53
|
+
name: z.ZodOptional<z.ZodString>;
|
|
54
|
+
ide: z.ZodOptional<z.ZodString>;
|
|
55
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
56
|
+
json: "json";
|
|
57
|
+
table: "table";
|
|
58
|
+
}>>;
|
|
59
|
+
switchOptions: z.ZodOptional<z.ZodObject<{
|
|
60
|
+
preview: z.ZodOptional<z.ZodBoolean>;
|
|
61
|
+
backup: z.ZodOptional<z.ZodBoolean>;
|
|
62
|
+
}, z.core.$strip>>;
|
|
63
|
+
}, z.core.$strip>;
|
|
64
|
+
/**
|
|
65
|
+
* 验证 SettingsPayload
|
|
66
|
+
*/
|
|
67
|
+
declare function validatePayload(payload: unknown): {
|
|
68
|
+
tool: "claude" | "codex" | "gemini";
|
|
69
|
+
scope: "user" | "project" | "local" | "system";
|
|
70
|
+
action: "list" | "edit" | "switch-profile" | "inspect";
|
|
71
|
+
profile?: string | undefined;
|
|
72
|
+
name?: string | undefined;
|
|
73
|
+
ide?: string | undefined;
|
|
74
|
+
format?: "json" | "table" | undefined;
|
|
75
|
+
switchOptions?: {
|
|
76
|
+
preview?: boolean | undefined;
|
|
77
|
+
backup?: boolean | undefined;
|
|
78
|
+
} | undefined;
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
export { ScopeSchema, SettingActionSchema, SettingsPayloadSchema, ToolIdSchema, validatePayload };
|
|
82
|
+
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.ts","names":[],"sources":["../../src/domain/validators.ts"],"sourcesContent":[],"mappings":";;;;AAcA;AAKA;AAUA;cApBa,cAAY,CAAA,CAAA;;;;;;;;cAKZ,aAAW,CAAA,CAAA;;;;;;;;;cAKX,qBAAmB,CAAA,CAAA;;EAUE,IAAA,EAAA,MAAA;EAAA,gBAAA,EAAA,gBAAA;EAmBlB,OAAA,EAAA,SAAe;;;;;cAnBlB,uBAAqB,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBlB,eAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/domain/validators.ts
|
|
4
|
+
/**
|
|
5
|
+
* 配置验证器
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* ToolId 验证 schema
|
|
9
|
+
*/
|
|
10
|
+
const ToolIdSchema = z.enum([
|
|
11
|
+
"claude",
|
|
12
|
+
"codex",
|
|
13
|
+
"gemini"
|
|
14
|
+
]);
|
|
15
|
+
/**
|
|
16
|
+
* Scope 验证 schema
|
|
17
|
+
*/
|
|
18
|
+
const ScopeSchema = z.enum([
|
|
19
|
+
"user",
|
|
20
|
+
"project",
|
|
21
|
+
"local",
|
|
22
|
+
"system"
|
|
23
|
+
]);
|
|
24
|
+
/**
|
|
25
|
+
* SettingAction 验证 schema
|
|
26
|
+
*/
|
|
27
|
+
const SettingActionSchema = z.enum([
|
|
28
|
+
"list",
|
|
29
|
+
"edit",
|
|
30
|
+
"switch-profile",
|
|
31
|
+
"inspect"
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* SettingsPayload 验证 schema
|
|
35
|
+
*/
|
|
36
|
+
const SettingsPayloadSchema = z.object({
|
|
37
|
+
tool: ToolIdSchema,
|
|
38
|
+
scope: ScopeSchema,
|
|
39
|
+
action: SettingActionSchema,
|
|
40
|
+
profile: z.string().optional(),
|
|
41
|
+
name: z.string().optional(),
|
|
42
|
+
ide: z.string().optional(),
|
|
43
|
+
format: z.enum(["json", "table"]).optional(),
|
|
44
|
+
switchOptions: z.object({
|
|
45
|
+
preview: z.boolean().optional(),
|
|
46
|
+
backup: z.boolean().optional()
|
|
47
|
+
}).optional()
|
|
48
|
+
});
|
|
49
|
+
/**
|
|
50
|
+
* 验证 SettingsPayload
|
|
51
|
+
*/
|
|
52
|
+
function validatePayload(payload) {
|
|
53
|
+
return SettingsPayloadSchema.parse(payload);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
export { ScopeSchema, SettingActionSchema, SettingsPayloadSchema, ToolIdSchema, validatePayload };
|
|
58
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.js","names":[],"sources":["../../src/domain/validators.ts"],"sourcesContent":["/**\n * 配置验证器\n */\n\nimport { z } from \"zod\";\n\n/**\n * ToolId 验证 schema\n */\nexport const ToolIdSchema = z.enum([\"claude\", \"codex\", \"gemini\"]);\n\n/**\n * Scope 验证 schema\n */\nexport const ScopeSchema = z.enum([\"user\", \"project\", \"local\", \"system\"]);\n\n/**\n * SettingAction 验证 schema\n */\nexport const SettingActionSchema = z.enum([\n \"list\",\n \"edit\",\n \"switch-profile\",\n \"inspect\",\n]);\n\n/**\n * SettingsPayload 验证 schema\n */\nexport const SettingsPayloadSchema = z.object({\n tool: ToolIdSchema,\n scope: ScopeSchema,\n action: SettingActionSchema,\n profile: z.string().optional(),\n name: z.string().optional(),\n ide: z.string().optional(),\n format: z.enum([\"json\", \"table\"]).optional(),\n switchOptions: z\n .object({\n preview: z.boolean().optional(),\n backup: z.boolean().optional(),\n })\n .optional(),\n});\n\n/**\n * 验证 SettingsPayload\n */\nexport function validatePayload(payload: unknown) {\n return SettingsPayloadSchema.parse(payload);\n}\n"],"mappings":";;;;;;;;;AASA,MAAa,eAAe,EAAE,KAAK;CAAC;CAAU;CAAS;CAAS,CAAC;;;;AAKjE,MAAa,cAAc,EAAE,KAAK;CAAC;CAAQ;CAAW;CAAS;CAAS,CAAC;;;;AAKzE,MAAa,sBAAsB,EAAE,KAAK;CACxC;CACA;CACA;CACA;CACD,CAAC;;;;AAKF,MAAa,wBAAwB,EAAE,OAAO;CAC5C,MAAM;CACN,OAAO;CACP,QAAQ;CACR,SAAS,EAAE,QAAQ,CAAC,UAAU;CAC9B,MAAM,EAAE,QAAQ,CAAC,UAAU;CAC3B,KAAK,EAAE,QAAQ,CAAC,UAAU;CAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ,QAAQ,CAAC,CAAC,UAAU;CAC5C,eAAe,EACZ,OAAO;EACN,SAAS,EAAE,SAAS,CAAC,UAAU;EAC/B,QAAQ,EAAE,SAAS,CAAC,UAAU;EAC/B,CAAC,CACD,UAAU;CACd,CAAC;;;;AAKF,SAAgB,gBAAgB,SAAkB;AAChD,QAAO,sBAAsB,MAAM,QAAQ"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { r as EditorLaunchError } from "./errors-CAZ5k5YT.js";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/editor.ts
|
|
5
|
+
const KNOWN_EDITORS = {
|
|
6
|
+
vscode: "code",
|
|
7
|
+
code: "code",
|
|
8
|
+
cursor: "cursor",
|
|
9
|
+
zed: "zed",
|
|
10
|
+
sublime: "subl",
|
|
11
|
+
subl: "subl"
|
|
12
|
+
};
|
|
13
|
+
function resolveEditorCommand(ide) {
|
|
14
|
+
if (!ide) return "code";
|
|
15
|
+
return KNOWN_EDITORS[ide.toLowerCase()] ?? ide;
|
|
16
|
+
}
|
|
17
|
+
async function openInEditor(command, filePath) {
|
|
18
|
+
await new Promise((resolve, reject) => {
|
|
19
|
+
const child = spawn(command, [filePath], { stdio: "inherit" });
|
|
20
|
+
child.on("error", (error) => {
|
|
21
|
+
reject(new EditorLaunchError(command, error.message));
|
|
22
|
+
});
|
|
23
|
+
child.on("exit", (code) => {
|
|
24
|
+
if (code === 0 || code === null) resolve();
|
|
25
|
+
else reject(new EditorLaunchError(command, `Exited with code ${code}`));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { resolveEditorCommand as n, openInEditor as t };
|
|
32
|
+
//# sourceMappingURL=editor-D4qoje1V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-D4qoje1V.js","names":["KNOWN_EDITORS: Record<string, string>"],"sources":["../src/utils/editor.ts"],"sourcesContent":["import { spawn } from \"child_process\";\nimport { EditorLaunchError } from \"./errors.ts\";\n\nconst KNOWN_EDITORS: Record<string, string> = {\n vscode: \"code\",\n code: \"code\",\n cursor: \"cursor\",\n zed: \"zed\",\n sublime: \"subl\",\n subl: \"subl\",\n};\n\nexport function resolveEditorCommand(ide?: string): string {\n if (!ide) {\n return \"code\";\n }\n const normalized = ide.toLowerCase();\n return KNOWN_EDITORS[normalized] ?? ide;\n}\n\nexport async function openInEditor(\n command: string,\n filePath: string,\n): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, [filePath], {\n stdio: \"inherit\",\n });\n\n child.on(\"error\", (error) => {\n reject(new EditorLaunchError(command, error.message));\n });\n\n child.on(\"exit\", (code) => {\n if (code === 0 || code === null) {\n resolve();\n } else {\n reject(new EditorLaunchError(command, `Exited with code ${code}`));\n }\n });\n });\n}\n"],"mappings":";;;;AAGA,MAAMA,gBAAwC;CAC5C,QAAQ;CACR,MAAM;CACN,QAAQ;CACR,KAAK;CACL,SAAS;CACT,MAAM;CACP;AAED,SAAgB,qBAAqB,KAAsB;AACzD,KAAI,CAAC,IACH,QAAO;AAGT,QAAO,cADY,IAAI,aAAa,KACA;;AAGtC,eAAsB,aACpB,SACA,UACe;AACf,OAAM,IAAI,SAAe,SAAS,WAAW;EAC3C,MAAM,QAAQ,MAAM,SAAS,CAAC,SAAS,EAAE,EACvC,OAAO,WACR,CAAC;AAEF,QAAM,GAAG,UAAU,UAAU;AAC3B,UAAO,IAAI,kBAAkB,SAAS,MAAM,QAAQ,CAAC;IACrD;AAEF,QAAM,GAAG,SAAS,SAAS;AACzB,OAAI,SAAS,KAAK,SAAS,KACzB,UAAS;OAET,QAAO,IAAI,kBAAkB,SAAS,oBAAoB,OAAO,CAAC;IAEpE;GACF"}
|