srpllm 1.0.1 → 1.2.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/dist/cli.mjs +8 -8
- package/dist/index.d.mts +44 -5
- package/dist/index.d.ts +44 -5
- package/dist/index.mjs +4 -4
- package/dist/shared/{srpllm.gk7klSey.mjs → srpllm.p7w-TznV.mjs} +199 -47
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import { i as init, u as uninstall,
|
|
4
|
+
import { i as init, u as uninstall, O as version } from './shared/srpllm.p7w-TznV.mjs';
|
|
5
|
+
import 'node:fs';
|
|
6
|
+
import 'node:os';
|
|
5
7
|
import 'node:process';
|
|
6
8
|
import 'inquirer';
|
|
7
|
-
import 'ora';
|
|
8
|
-
import 'node:os';
|
|
9
9
|
import 'pathe';
|
|
10
|
-
import '
|
|
10
|
+
import 'ora';
|
|
11
11
|
import 'tinyexec';
|
|
12
12
|
|
|
13
13
|
function customizeHelp(sections) {
|
|
@@ -23,7 +23,7 @@ function customizeHelp(sections) {
|
|
|
23
23
|
` ${ansis.cyan("srpllm uninstall")} \u6E05\u9664\u4E2D\u8F6C\u7AD9\u914D\u7F6E`,
|
|
24
24
|
"",
|
|
25
25
|
ansis.gray(" \u9009\u9879"),
|
|
26
|
-
` ${ansis.green("--code-type, -T")} <type> \u6307\u5B9A\u5DE5\u5177 (claude-code/codex, cc/cx)`,
|
|
26
|
+
` ${ansis.green("--code-type, -T")} <type> \u6307\u5B9A\u5DE5\u5177 (claude-code/codex/chatbox, cc/cx/cb)`,
|
|
27
27
|
` ${ansis.green("--base-url, -u")} <url> \u4E2D\u8F6C\u7AD9 base_url`,
|
|
28
28
|
` ${ansis.green("--token, -k")} <token> api_token`,
|
|
29
29
|
` ${ansis.green("--model, -m")} <model> \u4E3B\u6A21\u578B (ANTHROPIC_MODEL)`,
|
|
@@ -42,13 +42,13 @@ function customizeHelp(sections) {
|
|
|
42
42
|
return sections;
|
|
43
43
|
}
|
|
44
44
|
function setupCommands(cli) {
|
|
45
|
-
cli.command("", "\u4EA4\u4E92\u5F0F\u5F15\u5BFC\u914D\u7F6E\u4E2D\u8F6C\u7AD9\uFF08\u9ED8\u8BA4\uFF09").option("--code-type, -T <type>", "\u5DE5\u5177\u7C7B\u578B (claude-code/codex, cc/cx)").option("--base-url, -u <url>", "\u4E2D\u8F6C\u7AD9 base_url").option("--token, -k <token>", "api_token").option("--model, -m <model>", "\u4E3B\u6A21\u578B (ANTHROPIC_MODEL)").option("--opus-model, -O <model>", "Opus \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_OPUS_MODEL)").option("--sonnet-model, -S <model>", "Sonnet \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_SONNET_MODEL)").option("--haiku-model, -H <model>", "Haiku \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_HAIKU_MODEL)").option("--skip-prompt, -s", "\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async (options) => {
|
|
45
|
+
cli.command("", "\u4EA4\u4E92\u5F0F\u5F15\u5BFC\u914D\u7F6E\u4E2D\u8F6C\u7AD9\uFF08\u9ED8\u8BA4\uFF09").option("--code-type, -T <type>", "\u5DE5\u5177\u7C7B\u578B (claude-code/codex/chatbox, cc/cx/cb)").option("--base-url, -u <url>", "\u4E2D\u8F6C\u7AD9 base_url").option("--token, -k <token>", "api_token").option("--model, -m <model>", "\u4E3B\u6A21\u578B (ANTHROPIC_MODEL)").option("--opus-model, -O <model>", "Opus \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_OPUS_MODEL)").option("--sonnet-model, -S <model>", "Sonnet \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_SONNET_MODEL)").option("--haiku-model, -H <model>", "Haiku \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_HAIKU_MODEL)").option("--skip-prompt, -s", "\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async (options) => {
|
|
46
46
|
await init(options);
|
|
47
47
|
});
|
|
48
|
-
cli.command("init", "\u5B89\u88C5 CLI \u5E76\u914D\u7F6E\u4E2D\u8F6C\u7AD9").option("--code-type, -T <type>", "\u5DE5\u5177\u7C7B\u578B (claude-code/codex, cc/cx)").option("--base-url, -u <url>", "\u4E2D\u8F6C\u7AD9 base_url").option("--token, -k <token>", "api_token").option("--model, -m <model>", "\u4E3B\u6A21\u578B (ANTHROPIC_MODEL)").option("--opus-model, -O <model>", "Opus \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_OPUS_MODEL)").option("--sonnet-model, -S <model>", "Sonnet \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_SONNET_MODEL)").option("--haiku-model, -H <model>", "Haiku \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_HAIKU_MODEL)").option("--skip-prompt, -s", "\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async (options) => {
|
|
48
|
+
cli.command("init", "\u5B89\u88C5 CLI \u5E76\u914D\u7F6E\u4E2D\u8F6C\u7AD9").option("--code-type, -T <type>", "\u5DE5\u5177\u7C7B\u578B (claude-code/codex/chatbox, cc/cx/cb)").option("--base-url, -u <url>", "\u4E2D\u8F6C\u7AD9 base_url").option("--token, -k <token>", "api_token").option("--model, -m <model>", "\u4E3B\u6A21\u578B (ANTHROPIC_MODEL)").option("--opus-model, -O <model>", "Opus \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_OPUS_MODEL)").option("--sonnet-model, -S <model>", "Sonnet \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_SONNET_MODEL)").option("--haiku-model, -H <model>", "Haiku \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_HAIKU_MODEL)").option("--skip-prompt, -s", "\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async (options) => {
|
|
49
49
|
await init(options);
|
|
50
50
|
});
|
|
51
|
-
cli.command("uninstall", "\u6E05\u9664\u4E2D\u8F6C\u7AD9\u914D\u7F6E").option("--code-type, -T <type>", "\u5DE5\u5177\u7C7B\u578B (claude-code/codex, cc/cx)").option("--skip-prompt, -s", "\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async (options) => {
|
|
51
|
+
cli.command("uninstall", "\u6E05\u9664\u4E2D\u8F6C\u7AD9\u914D\u7F6E").option("--code-type, -T <type>", "\u5DE5\u5177\u7C7B\u578B (claude-code/codex/chatbox, cc/cx/cb)").option("--skip-prompt, -s", "\u975E\u4EA4\u4E92\u6A21\u5F0F").action(async (options) => {
|
|
52
52
|
await uninstall(options);
|
|
53
53
|
});
|
|
54
54
|
cli.help((sections) => customizeHelp(sections));
|
package/dist/index.d.mts
CHANGED
|
@@ -58,9 +58,14 @@ declare const CODEX_AUTH_FILE: string;
|
|
|
58
58
|
declare const CODE_TOOL_TYPES: readonly ["claude-code", "codex"];
|
|
59
59
|
type CodeToolType = (typeof CODE_TOOL_TYPES)[number];
|
|
60
60
|
declare const DEFAULT_CODE_TOOL_TYPE: CodeToolType;
|
|
61
|
-
declare const
|
|
62
|
-
|
|
63
|
-
declare
|
|
61
|
+
declare const RELAY_TOOL_TYPES: readonly ["claude-code", "codex", "chatbox"];
|
|
62
|
+
type RelayToolType = (typeof RELAY_TOOL_TYPES)[number];
|
|
63
|
+
declare const CODE_TOOL_ALIASES: Record<string, RelayToolType>;
|
|
64
|
+
declare const CODE_TOOL_LABELS: Record<RelayToolType, string>;
|
|
65
|
+
declare const MODEL_PREFIX: Record<RelayToolType, string>;
|
|
66
|
+
declare function isCodeToolType(value: unknown): value is CodeToolType;
|
|
67
|
+
declare function resolveCodeToolType(value: unknown): RelayToolType;
|
|
68
|
+
declare function isCliTool(tool: RelayToolType): tool is CodeToolType;
|
|
64
69
|
declare const RELAY_PROVIDER_ID = "srpllm";
|
|
65
70
|
|
|
66
71
|
type InstallMethod = 'npm' | 'homebrew' | 'curl' | 'powershell';
|
|
@@ -70,6 +75,34 @@ declare function selectInstallMethod(tool: CodeToolType): Promise<InstallMethod>
|
|
|
70
75
|
declare function installTool(tool: CodeToolType, skipMethodSelection?: boolean): Promise<void>;
|
|
71
76
|
declare function uninstallTool(tool: CodeToolType): Promise<boolean>;
|
|
72
77
|
|
|
78
|
+
interface LocalConfig {
|
|
79
|
+
/** 上次选的工具 */
|
|
80
|
+
codeType?: 'claude-code' | 'codex' | 'chatbox';
|
|
81
|
+
/** 上次输入的中转站 base_url */
|
|
82
|
+
baseUrl?: string;
|
|
83
|
+
/** 上次输入的 api_token(明文存储,文件权限 600) */
|
|
84
|
+
token?: string;
|
|
85
|
+
/** 上次为 Claude Code 选的四档模型 */
|
|
86
|
+
claude?: {
|
|
87
|
+
model?: string;
|
|
88
|
+
opusModel?: string;
|
|
89
|
+
sonnetModel?: string;
|
|
90
|
+
haikuModel?: string;
|
|
91
|
+
};
|
|
92
|
+
/** 上次为 Codex 选的模型 */
|
|
93
|
+
codex?: {
|
|
94
|
+
model?: string;
|
|
95
|
+
};
|
|
96
|
+
/** 上次为 Chatbox 选的模型 */
|
|
97
|
+
chatbox?: {
|
|
98
|
+
model?: string;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
declare function readLocalConfig(): LocalConfig;
|
|
102
|
+
declare function writeLocalConfig(config: LocalConfig): void;
|
|
103
|
+
/** 合并更新本地记忆 */
|
|
104
|
+
declare function updateLocalConfig(patch: Partial<LocalConfig>): void;
|
|
105
|
+
|
|
73
106
|
interface RemoteModel {
|
|
74
107
|
id: string;
|
|
75
108
|
ownedBy?: string;
|
|
@@ -84,11 +117,17 @@ declare function buildModelsChoices(models: RemoteModel[]): Array<{
|
|
|
84
117
|
name: string;
|
|
85
118
|
value: string;
|
|
86
119
|
}>;
|
|
120
|
+
/**
|
|
121
|
+
* 按中转站客户端前缀过滤模型列表。
|
|
122
|
+
* claude-code → cc-,codex → cx-,chatbox → chat-
|
|
123
|
+
* 不带前缀的模型一律排除(中转站约定模型 id 必须带客户端前缀)。
|
|
124
|
+
*/
|
|
125
|
+
declare function filterByPrefix(models: RemoteModel[], prefix: string): RemoteModel[];
|
|
87
126
|
|
|
88
127
|
type Platform = 'windows' | 'macos' | 'linux';
|
|
89
128
|
declare function getPlatform(): Platform;
|
|
90
129
|
declare function isWindows(): boolean;
|
|
91
130
|
declare function commandExists(command: string): Promise<boolean>;
|
|
92
131
|
|
|
93
|
-
export { CLAUDE_DIR, CLAUDE_SETTINGS_FILE, CODEX_AUTH_FILE, CODEX_CONFIG_FILE, CODEX_DIR, CODE_TOOL_ALIASES, CODE_TOOL_LABELS, CODE_TOOL_TYPES, DEFAULT_CODE_TOOL_TYPE, RELAY_PROVIDER_ID, buildModelsChoices, clearClaudeApiConfig, clearCodexApiConfig, commandExists, detectInstalledVersion, displayClaudeConfig, displayCodexConfig, ensureClaudeDir, fetchModels, getExistingClaudeApiConfig, getExistingCodexConfig, getPlatform, init, installTool, isToolInstalled, isWindows, readClaudeSettings, resolveCodeToolType, selectInstallMethod, uninstall, uninstallTool, writeClaudeApiConfig, writeCodexApiConfig };
|
|
94
|
-
export type { ClaudeApiConfig, CodeToolType, CodexApiConfig, InstallMethod, RemoteModel };
|
|
132
|
+
export { CLAUDE_DIR, CLAUDE_SETTINGS_FILE, CODEX_AUTH_FILE, CODEX_CONFIG_FILE, CODEX_DIR, CODE_TOOL_ALIASES, CODE_TOOL_LABELS, CODE_TOOL_TYPES, DEFAULT_CODE_TOOL_TYPE, MODEL_PREFIX, RELAY_PROVIDER_ID, RELAY_TOOL_TYPES, buildModelsChoices, clearClaudeApiConfig, clearCodexApiConfig, commandExists, detectInstalledVersion, displayClaudeConfig, displayCodexConfig, ensureClaudeDir, fetchModels, filterByPrefix, getExistingClaudeApiConfig, getExistingCodexConfig, getPlatform, init, installTool, isCliTool, isCodeToolType, isToolInstalled, isWindows, readClaudeSettings, readLocalConfig, resolveCodeToolType, selectInstallMethod, uninstall, uninstallTool, updateLocalConfig, writeClaudeApiConfig, writeCodexApiConfig, writeLocalConfig };
|
|
133
|
+
export type { ClaudeApiConfig, CodeToolType, CodexApiConfig, InstallMethod, LocalConfig, RelayToolType, RemoteModel };
|
package/dist/index.d.ts
CHANGED
|
@@ -58,9 +58,14 @@ declare const CODEX_AUTH_FILE: string;
|
|
|
58
58
|
declare const CODE_TOOL_TYPES: readonly ["claude-code", "codex"];
|
|
59
59
|
type CodeToolType = (typeof CODE_TOOL_TYPES)[number];
|
|
60
60
|
declare const DEFAULT_CODE_TOOL_TYPE: CodeToolType;
|
|
61
|
-
declare const
|
|
62
|
-
|
|
63
|
-
declare
|
|
61
|
+
declare const RELAY_TOOL_TYPES: readonly ["claude-code", "codex", "chatbox"];
|
|
62
|
+
type RelayToolType = (typeof RELAY_TOOL_TYPES)[number];
|
|
63
|
+
declare const CODE_TOOL_ALIASES: Record<string, RelayToolType>;
|
|
64
|
+
declare const CODE_TOOL_LABELS: Record<RelayToolType, string>;
|
|
65
|
+
declare const MODEL_PREFIX: Record<RelayToolType, string>;
|
|
66
|
+
declare function isCodeToolType(value: unknown): value is CodeToolType;
|
|
67
|
+
declare function resolveCodeToolType(value: unknown): RelayToolType;
|
|
68
|
+
declare function isCliTool(tool: RelayToolType): tool is CodeToolType;
|
|
64
69
|
declare const RELAY_PROVIDER_ID = "srpllm";
|
|
65
70
|
|
|
66
71
|
type InstallMethod = 'npm' | 'homebrew' | 'curl' | 'powershell';
|
|
@@ -70,6 +75,34 @@ declare function selectInstallMethod(tool: CodeToolType): Promise<InstallMethod>
|
|
|
70
75
|
declare function installTool(tool: CodeToolType, skipMethodSelection?: boolean): Promise<void>;
|
|
71
76
|
declare function uninstallTool(tool: CodeToolType): Promise<boolean>;
|
|
72
77
|
|
|
78
|
+
interface LocalConfig {
|
|
79
|
+
/** 上次选的工具 */
|
|
80
|
+
codeType?: 'claude-code' | 'codex' | 'chatbox';
|
|
81
|
+
/** 上次输入的中转站 base_url */
|
|
82
|
+
baseUrl?: string;
|
|
83
|
+
/** 上次输入的 api_token(明文存储,文件权限 600) */
|
|
84
|
+
token?: string;
|
|
85
|
+
/** 上次为 Claude Code 选的四档模型 */
|
|
86
|
+
claude?: {
|
|
87
|
+
model?: string;
|
|
88
|
+
opusModel?: string;
|
|
89
|
+
sonnetModel?: string;
|
|
90
|
+
haikuModel?: string;
|
|
91
|
+
};
|
|
92
|
+
/** 上次为 Codex 选的模型 */
|
|
93
|
+
codex?: {
|
|
94
|
+
model?: string;
|
|
95
|
+
};
|
|
96
|
+
/** 上次为 Chatbox 选的模型 */
|
|
97
|
+
chatbox?: {
|
|
98
|
+
model?: string;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
declare function readLocalConfig(): LocalConfig;
|
|
102
|
+
declare function writeLocalConfig(config: LocalConfig): void;
|
|
103
|
+
/** 合并更新本地记忆 */
|
|
104
|
+
declare function updateLocalConfig(patch: Partial<LocalConfig>): void;
|
|
105
|
+
|
|
73
106
|
interface RemoteModel {
|
|
74
107
|
id: string;
|
|
75
108
|
ownedBy?: string;
|
|
@@ -84,11 +117,17 @@ declare function buildModelsChoices(models: RemoteModel[]): Array<{
|
|
|
84
117
|
name: string;
|
|
85
118
|
value: string;
|
|
86
119
|
}>;
|
|
120
|
+
/**
|
|
121
|
+
* 按中转站客户端前缀过滤模型列表。
|
|
122
|
+
* claude-code → cc-,codex → cx-,chatbox → chat-
|
|
123
|
+
* 不带前缀的模型一律排除(中转站约定模型 id 必须带客户端前缀)。
|
|
124
|
+
*/
|
|
125
|
+
declare function filterByPrefix(models: RemoteModel[], prefix: string): RemoteModel[];
|
|
87
126
|
|
|
88
127
|
type Platform = 'windows' | 'macos' | 'linux';
|
|
89
128
|
declare function getPlatform(): Platform;
|
|
90
129
|
declare function isWindows(): boolean;
|
|
91
130
|
declare function commandExists(command: string): Promise<boolean>;
|
|
92
131
|
|
|
93
|
-
export { CLAUDE_DIR, CLAUDE_SETTINGS_FILE, CODEX_AUTH_FILE, CODEX_CONFIG_FILE, CODEX_DIR, CODE_TOOL_ALIASES, CODE_TOOL_LABELS, CODE_TOOL_TYPES, DEFAULT_CODE_TOOL_TYPE, RELAY_PROVIDER_ID, buildModelsChoices, clearClaudeApiConfig, clearCodexApiConfig, commandExists, detectInstalledVersion, displayClaudeConfig, displayCodexConfig, ensureClaudeDir, fetchModels, getExistingClaudeApiConfig, getExistingCodexConfig, getPlatform, init, installTool, isToolInstalled, isWindows, readClaudeSettings, resolveCodeToolType, selectInstallMethod, uninstall, uninstallTool, writeClaudeApiConfig, writeCodexApiConfig };
|
|
94
|
-
export type { ClaudeApiConfig, CodeToolType, CodexApiConfig, InstallMethod, RemoteModel };
|
|
132
|
+
export { CLAUDE_DIR, CLAUDE_SETTINGS_FILE, CODEX_AUTH_FILE, CODEX_CONFIG_FILE, CODEX_DIR, CODE_TOOL_ALIASES, CODE_TOOL_LABELS, CODE_TOOL_TYPES, DEFAULT_CODE_TOOL_TYPE, MODEL_PREFIX, RELAY_PROVIDER_ID, RELAY_TOOL_TYPES, buildModelsChoices, clearClaudeApiConfig, clearCodexApiConfig, commandExists, detectInstalledVersion, displayClaudeConfig, displayCodexConfig, ensureClaudeDir, fetchModels, filterByPrefix, getExistingClaudeApiConfig, getExistingCodexConfig, getPlatform, init, installTool, isCliTool, isCodeToolType, isToolInstalled, isWindows, readClaudeSettings, readLocalConfig, resolveCodeToolType, selectInstallMethod, uninstall, uninstallTool, updateLocalConfig, writeClaudeApiConfig, writeCodexApiConfig, writeLocalConfig };
|
|
133
|
+
export type { ClaudeApiConfig, CodeToolType, CodexApiConfig, InstallMethod, LocalConfig, RelayToolType, RemoteModel };
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { C as CLAUDE_DIR, b as CLAUDE_SETTINGS_FILE, f as CODEX_AUTH_FILE, e as CODEX_CONFIG_FILE, d as CODEX_DIR, j as CODE_TOOL_ALIASES, k as CODE_TOOL_LABELS, h as CODE_TOOL_TYPES, D as DEFAULT_CODE_TOOL_TYPE,
|
|
1
|
+
export { C as CLAUDE_DIR, b as CLAUDE_SETTINGS_FILE, f as CODEX_AUTH_FILE, e as CODEX_CONFIG_FILE, d as CODEX_DIR, j as CODE_TOOL_ALIASES, k as CODE_TOOL_LABELS, h as CODE_TOOL_TYPES, D as DEFAULT_CODE_TOOL_TYPE, M as MODEL_PREFIX, n as RELAY_PROVIDER_ID, R as RELAY_TOOL_TYPES, L as buildModelsChoices, s as clearClaudeApiConfig, y as clearCodexApiConfig, c as commandExists, B as detectInstalledVersion, t as displayClaudeConfig, z as displayCodexConfig, o as ensureClaudeDir, K as fetchModels, N as filterByPrefix, q as getExistingClaudeApiConfig, v as getExistingCodexConfig, g as getPlatform, i as init, F as installTool, m as isCliTool, l as isCodeToolType, A as isToolInstalled, a as isWindows, p as readClaudeSettings, H as readLocalConfig, r as resolveCodeToolType, E as selectInstallMethod, u as uninstall, G as uninstallTool, J as updateLocalConfig, w as writeClaudeApiConfig, x as writeCodexApiConfig, I as writeLocalConfig } from './shared/srpllm.p7w-TznV.mjs';
|
|
2
|
+
import 'node:fs';
|
|
3
|
+
import 'node:os';
|
|
2
4
|
import 'node:process';
|
|
3
5
|
import 'ansis';
|
|
4
6
|
import 'inquirer';
|
|
5
|
-
import 'ora';
|
|
6
|
-
import 'node:os';
|
|
7
7
|
import 'pathe';
|
|
8
|
-
import '
|
|
8
|
+
import 'ora';
|
|
9
9
|
import 'tinyexec';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync, unlinkSync } from 'node:fs';
|
|
2
|
+
import { homedir, platform } from 'node:os';
|
|
1
3
|
import process from 'node:process';
|
|
2
4
|
import ansis from 'ansis';
|
|
3
5
|
import inquirer from 'inquirer';
|
|
4
|
-
import ora from 'ora';
|
|
5
|
-
import { homedir, platform } from 'node:os';
|
|
6
6
|
import { join, dirname } from 'pathe';
|
|
7
|
-
import
|
|
7
|
+
import ora from 'ora';
|
|
8
8
|
import { exec } from 'tinyexec';
|
|
9
9
|
|
|
10
10
|
const CLAUDE_DIR = join(homedir(), ".claude");
|
|
@@ -14,16 +14,27 @@ const CODEX_CONFIG_FILE = join(CODEX_DIR, "config.toml");
|
|
|
14
14
|
const CODEX_AUTH_FILE = join(CODEX_DIR, "auth.json");
|
|
15
15
|
const CODE_TOOL_TYPES = ["claude-code", "codex"];
|
|
16
16
|
const DEFAULT_CODE_TOOL_TYPE = "claude-code";
|
|
17
|
+
const RELAY_TOOL_TYPES = ["claude-code", "codex", "chatbox"];
|
|
17
18
|
const CODE_TOOL_ALIASES = {
|
|
18
19
|
cc: "claude-code",
|
|
19
|
-
cx: "codex"
|
|
20
|
+
cx: "codex",
|
|
21
|
+
cb: "chatbox"
|
|
20
22
|
};
|
|
21
23
|
const CODE_TOOL_LABELS = {
|
|
22
24
|
"claude-code": "Claude Code",
|
|
23
|
-
"codex": "Codex"
|
|
25
|
+
"codex": "Codex",
|
|
26
|
+
"chatbox": "Chatbox (OpenAI \u517C\u5BB9)"
|
|
24
27
|
};
|
|
28
|
+
const MODEL_PREFIX = {
|
|
29
|
+
"claude-code": "cc-",
|
|
30
|
+
"codex": "cx-",
|
|
31
|
+
"chatbox": "chat-"
|
|
32
|
+
};
|
|
33
|
+
function isCodeToolType(value) {
|
|
34
|
+
return CODE_TOOL_TYPES.includes(value);
|
|
35
|
+
}
|
|
25
36
|
function resolveCodeToolType(value) {
|
|
26
|
-
if (value &&
|
|
37
|
+
if (value && RELAY_TOOL_TYPES.includes(value)) {
|
|
27
38
|
return value;
|
|
28
39
|
}
|
|
29
40
|
if (typeof value === "string" && value in CODE_TOOL_ALIASES) {
|
|
@@ -31,6 +42,9 @@ function resolveCodeToolType(value) {
|
|
|
31
42
|
}
|
|
32
43
|
return DEFAULT_CODE_TOOL_TYPE;
|
|
33
44
|
}
|
|
45
|
+
function isCliTool(tool) {
|
|
46
|
+
return tool !== "chatbox";
|
|
47
|
+
}
|
|
34
48
|
const RELAY_PROVIDER_ID = "srpllm";
|
|
35
49
|
|
|
36
50
|
function exists(path) {
|
|
@@ -479,6 +493,37 @@ async function uninstallTool(tool) {
|
|
|
479
493
|
}
|
|
480
494
|
}
|
|
481
495
|
|
|
496
|
+
const SRPLLM_DIR = join(homedir(), ".srpllm");
|
|
497
|
+
const SRPLLM_CONFIG_FILE = join(SRPLLM_DIR, "config.json");
|
|
498
|
+
function readLocalConfig() {
|
|
499
|
+
return readJson(SRPLLM_CONFIG_FILE) || {};
|
|
500
|
+
}
|
|
501
|
+
function writeLocalConfig(config) {
|
|
502
|
+
ensureDir(SRPLLM_DIR);
|
|
503
|
+
writeJson(SRPLLM_CONFIG_FILE, config);
|
|
504
|
+
try {
|
|
505
|
+
chmodSync(SRPLLM_CONFIG_FILE, 384);
|
|
506
|
+
} catch {
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
function updateLocalConfig(patch) {
|
|
510
|
+
const existing = readLocalConfig();
|
|
511
|
+
writeLocalConfig({ ...existing, ...patch });
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const LITELLM_WILDCARD_IDS = /* @__PURE__ */ new Set([
|
|
515
|
+
"all-proxy-models",
|
|
516
|
+
"all-team-models",
|
|
517
|
+
"all-models",
|
|
518
|
+
"all-user-models",
|
|
519
|
+
"all-internal-models",
|
|
520
|
+
"team-models",
|
|
521
|
+
"default-team-models"
|
|
522
|
+
]);
|
|
523
|
+
function isWildcardModel(id) {
|
|
524
|
+
const lower = id.toLowerCase().trim();
|
|
525
|
+
return LITELLM_WILDCARD_IDS.has(lower);
|
|
526
|
+
}
|
|
482
527
|
async function fetchModels(baseUrl, token) {
|
|
483
528
|
const url = `${baseUrl.replace(/\/$/, "")}/v1/models`;
|
|
484
529
|
const spinner = ora(`\u6B63\u5728\u4ECE ${url} \u62C9\u53D6\u6A21\u578B\u5217\u8868...`).start();
|
|
@@ -499,9 +544,10 @@ async function fetchModels(baseUrl, token) {
|
|
|
499
544
|
const models = data.map((m) => ({
|
|
500
545
|
id: String(m.id || m.name || m.model).trim(),
|
|
501
546
|
ownedBy: m.owned_by || m.ownedBy
|
|
502
|
-
})).filter((m) => m.id);
|
|
547
|
+
})).filter((m) => m.id && !isWildcardModel(m.id));
|
|
503
548
|
if (models.length === 0) {
|
|
504
|
-
spinner.
|
|
549
|
+
spinner.warn("\u2716 \u4E2D\u8F6C\u7AD9\u8FD4\u56DE\u7684\u6A21\u578B\u5217\u8868\u4E3A\u7A7A\u6216\u4EC5\u542B\u901A\u914D\u7B26\u5360\u4F4D\u7B26\uFF08all-team-models \u7B49\uFF09");
|
|
550
|
+
console.log(ansis.yellow(" \u2139 \u8FD9\u901A\u5E38\u8868\u793A\u8BE5 key/team \u672A\u88AB\u5206\u914D\u5177\u4F53\u6A21\u578B\uFF0C\u8BF7\u8054\u7CFB\u4E2D\u8F6C\u7AD9\u7BA1\u7406\u5458\u4E3A\u8BE5 key \u663E\u5F0F\u914D\u7F6E models \u5217\u8868"));
|
|
505
551
|
throw new Error("\u6A21\u578B\u5217\u8868\u4E3A\u7A7A");
|
|
506
552
|
}
|
|
507
553
|
spinner.succeed(`\u2714 \u5DF2\u83B7\u53D6 ${models.length} \u4E2A\u53EF\u7528\u6A21\u578B`);
|
|
@@ -517,8 +563,12 @@ function buildModelsChoices(models) {
|
|
|
517
563
|
value: m.id
|
|
518
564
|
}));
|
|
519
565
|
}
|
|
566
|
+
function filterByPrefix(models, prefix) {
|
|
567
|
+
const p = prefix.toLowerCase();
|
|
568
|
+
return models.filter((m) => m.id.toLowerCase().startsWith(p));
|
|
569
|
+
}
|
|
520
570
|
|
|
521
|
-
const version = "1.0
|
|
571
|
+
const version = "1.2.0";
|
|
522
572
|
|
|
523
573
|
function displayBanner(codeTool) {
|
|
524
574
|
const tool = codeTool ? ` ${ansis.gray(`\xB7 ${CODE_TOOL_LABELS[codeTool]}`)}` : "";
|
|
@@ -526,23 +576,26 @@ function displayBanner(codeTool) {
|
|
|
526
576
|
SrP-LLM \u914D\u7F6E\u5DE5\u5177 v${version}${tool}`));
|
|
527
577
|
console.log(ansis.gray(" \u4E2D\u8F6C\u7AD9\u5BA2\u6237\u7AEF\u4E00\u952E\u914D\u7F6E\uFF1A\u5B89\u88C5 CLI \xB7 \u586B\u5199 base_url / api_token \xB7 \u9009\u62E9\u6A21\u578B\n"));
|
|
528
578
|
}
|
|
529
|
-
async function
|
|
579
|
+
async function selectTool(defaultTool) {
|
|
580
|
+
const choices = ["claude-code", "codex", "chatbox"].map((value) => ({
|
|
581
|
+
name: CODE_TOOL_LABELS[value],
|
|
582
|
+
value
|
|
583
|
+
}));
|
|
530
584
|
const { tool } = await inquirer.prompt({
|
|
531
585
|
type: "list",
|
|
532
586
|
name: "tool",
|
|
533
587
|
message: "\u8BF7\u9009\u62E9\u8981\u914D\u7F6E\u7684\u5BA2\u6237\u7AEF\u5DE5\u5177\uFF1A",
|
|
534
|
-
choices
|
|
535
|
-
|
|
536
|
-
{ name: "Codex", value: "codex" }
|
|
537
|
-
]
|
|
588
|
+
choices,
|
|
589
|
+
default: defaultTool
|
|
538
590
|
});
|
|
539
591
|
return tool;
|
|
540
592
|
}
|
|
541
|
-
async function inputBaseUrl() {
|
|
593
|
+
async function inputBaseUrl(defaultUrl) {
|
|
542
594
|
const { url } = await inquirer.prompt({
|
|
543
595
|
type: "input",
|
|
544
596
|
name: "url",
|
|
545
597
|
message: "\u8BF7\u8F93\u5165\u4E2D\u8F6C\u7AD9 base_url\uFF08\u4F8B\u5982 https://api.srpllm.com\uFF09\uFF1A",
|
|
598
|
+
default: defaultUrl,
|
|
546
599
|
validate: (value) => {
|
|
547
600
|
const v = value.trim();
|
|
548
601
|
if (!v)
|
|
@@ -556,7 +609,13 @@ async function inputBaseUrl() {
|
|
|
556
609
|
});
|
|
557
610
|
return url.trim();
|
|
558
611
|
}
|
|
559
|
-
async function inputApiToken() {
|
|
612
|
+
async function inputApiToken(existingToken) {
|
|
613
|
+
if (existingToken) {
|
|
614
|
+
console.log(ansis.gray(` \u4E0A\u6B21 token\uFF1A${maskToken(existingToken)}`));
|
|
615
|
+
const reuse = await confirm("\u662F\u5426\u590D\u7528\u4E0A\u6B21\u7684 api_token\uFF1F", true);
|
|
616
|
+
if (reuse)
|
|
617
|
+
return existingToken;
|
|
618
|
+
}
|
|
560
619
|
const { token } = await inquirer.prompt({
|
|
561
620
|
type: "password",
|
|
562
621
|
name: "token",
|
|
@@ -591,7 +650,7 @@ async function fetchModelList(baseUrl, token) {
|
|
|
591
650
|
return null;
|
|
592
651
|
}
|
|
593
652
|
}
|
|
594
|
-
async function promptModelFromList(models, message, preset, skipPrompt) {
|
|
653
|
+
async function promptModelFromList(models, message, preset, skipPrompt, defaultModel) {
|
|
595
654
|
if (preset && preset.trim())
|
|
596
655
|
return preset.trim();
|
|
597
656
|
if (!models) {
|
|
@@ -601,7 +660,8 @@ async function promptModelFromList(models, message, preset, skipPrompt) {
|
|
|
601
660
|
const { manual } = await inquirer.prompt({
|
|
602
661
|
type: "input",
|
|
603
662
|
name: "manual",
|
|
604
|
-
message
|
|
663
|
+
message,
|
|
664
|
+
default: defaultModel
|
|
605
665
|
});
|
|
606
666
|
return manual.trim() || void 0;
|
|
607
667
|
}
|
|
@@ -612,11 +672,12 @@ async function promptModelFromList(models, message, preset, skipPrompt) {
|
|
|
612
672
|
choices: [
|
|
613
673
|
...buildModelsChoices(models),
|
|
614
674
|
{ name: "\u6682\u4E0D\u8BBE\u7F6E\uFF08\u8DF3\u8FC7\uFF09", value: "__none__" }
|
|
615
|
-
]
|
|
675
|
+
],
|
|
676
|
+
default: defaultModel
|
|
616
677
|
});
|
|
617
678
|
return choice === "__none__" ? void 0 : choice;
|
|
618
679
|
}
|
|
619
|
-
async function configureClaudeCode(options, baseUrl, token) {
|
|
680
|
+
async function configureClaudeCode(options, baseUrl, token, memory) {
|
|
620
681
|
const existing = getExistingClaudeApiConfig();
|
|
621
682
|
if (existing && !options.skipPrompt) {
|
|
622
683
|
console.log(ansis.blue("\n\u2139 \u68C0\u6D4B\u5230\u5DF2\u6709 Claude Code \u914D\u7F6E\uFF1A"));
|
|
@@ -636,17 +697,20 @@ async function configureClaudeCode(options, baseUrl, token) {
|
|
|
636
697
|
return;
|
|
637
698
|
}
|
|
638
699
|
}
|
|
639
|
-
const
|
|
640
|
-
const
|
|
641
|
-
const
|
|
642
|
-
const
|
|
643
|
-
const
|
|
700
|
+
const allModels = await fetchModelList(baseUrl, token);
|
|
701
|
+
const models = allModels ? filterByPrefix(allModels, MODEL_PREFIX["claude-code"]) : allModels;
|
|
702
|
+
const m = memory.claude;
|
|
703
|
+
const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u4E3B\u6A21\u578B (ANTHROPIC_MODEL)\uFF1A", options.model, options.skipPrompt, m?.model);
|
|
704
|
+
const opusModel = await promptModelFromList(models, "\u8BF7\u9009\u62E9 Opus \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_OPUS_MODEL)\uFF1A", options.opusModel, options.skipPrompt, m?.opusModel);
|
|
705
|
+
const sonnetModel = await promptModelFromList(models, "\u8BF7\u9009\u62E9 Sonnet \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_SONNET_MODEL)\uFF1A", options.sonnetModel, options.skipPrompt, m?.sonnetModel);
|
|
706
|
+
const haikuModel = await promptModelFromList(models, "\u8BF7\u9009\u62E9 Haiku \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_HAIKU_MODEL)\uFF1A", options.haikuModel, options.skipPrompt, m?.haikuModel);
|
|
644
707
|
const config = { baseUrl, token, model, opusModel, sonnetModel, haikuModel };
|
|
645
708
|
writeClaudeApiConfig(config);
|
|
646
709
|
console.log(ansis.green("\n\u2714 Claude Code \u914D\u7F6E\u5B8C\u6210"));
|
|
647
710
|
displayClaudeConfig(config);
|
|
711
|
+
updateLocalConfig({ claude: { model, opusModel, sonnetModel, haikuModel } });
|
|
648
712
|
}
|
|
649
|
-
async function configureCodex(options, baseUrl, token) {
|
|
713
|
+
async function configureCodex(options, baseUrl, token, memory) {
|
|
650
714
|
const existing = getExistingCodexConfig();
|
|
651
715
|
if (existing && !options.skipPrompt) {
|
|
652
716
|
console.log(ansis.blue("\n\u2139 \u68C0\u6D4B\u5230\u5DF2\u6709 Codex \u914D\u7F6E\uFF1A"));
|
|
@@ -660,47 +724,95 @@ async function configureCodex(options, baseUrl, token) {
|
|
|
660
724
|
return;
|
|
661
725
|
}
|
|
662
726
|
}
|
|
663
|
-
const
|
|
664
|
-
const
|
|
727
|
+
const allModels = await fetchModelList(baseUrl, token);
|
|
728
|
+
const models = allModels ? filterByPrefix(allModels, MODEL_PREFIX.codex) : allModels;
|
|
729
|
+
const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u9ED8\u8BA4\u4F7F\u7528\u7684\u6A21\u578B\uFF1A", options.model, options.skipPrompt, memory.codex?.model);
|
|
665
730
|
const config = { baseUrl, token, model };
|
|
666
731
|
writeCodexApiConfig(config);
|
|
667
732
|
console.log(ansis.green("\n\u2714 Codex \u914D\u7F6E\u5B8C\u6210"));
|
|
668
733
|
displayCodexConfig(config);
|
|
734
|
+
updateLocalConfig({ codex: { model } });
|
|
735
|
+
}
|
|
736
|
+
function getDownloadsDir() {
|
|
737
|
+
const home = homedir();
|
|
738
|
+
const candidates = [
|
|
739
|
+
process.env.USERPROFILE ? join(process.env.USERPROFILE, "Downloads") : "",
|
|
740
|
+
join(home, "Downloads")
|
|
741
|
+
];
|
|
742
|
+
for (const c of candidates) {
|
|
743
|
+
if (c && existsSync(c))
|
|
744
|
+
return c;
|
|
745
|
+
}
|
|
746
|
+
const fallback = join(home, "Downloads");
|
|
747
|
+
ensureDir(fallback);
|
|
748
|
+
return fallback;
|
|
749
|
+
}
|
|
750
|
+
async function configureChatbox(options, baseUrl, token, memory) {
|
|
751
|
+
const allModels = await fetchModelList(baseUrl, token);
|
|
752
|
+
const models = allModels ? filterByPrefix(allModels, MODEL_PREFIX.chatbox) : allModels;
|
|
753
|
+
const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u9ED8\u8BA4\u6A21\u578B\uFF08chat- \u524D\u7F00\uFF09\uFF1A", options.model, options.skipPrompt, memory.chatbox?.model);
|
|
754
|
+
const downloads = getDownloadsDir();
|
|
755
|
+
const filePath = join(downloads, "srpllm-chatbox-config.yaml");
|
|
756
|
+
const yaml = [
|
|
757
|
+
"# SrP-LLM \u4E2D\u8F6C\u7AD9 Chatbox \u914D\u7F6E",
|
|
758
|
+
"# \u5728 Chatbox \u5BA2\u6237\u7AEF\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u670D\u52A1 \u2192 OpenAI API\u300D\u4E2D\u586B\u5165\u4EE5\u4E0B\u4FE1\u606F",
|
|
759
|
+
`base_url: ${baseUrl}`,
|
|
760
|
+
`api_key: ${token}`,
|
|
761
|
+
model ? `model: ${model}` : "# model: \uFF08\u672A\u9009\u62E9\uFF0C\u8BF7\u5728 Chatbox \u4E2D\u624B\u52A8\u6307\u5B9A\uFF09",
|
|
762
|
+
""
|
|
763
|
+
].join("\n");
|
|
764
|
+
writeFile(filePath, yaml);
|
|
765
|
+
console.log(ansis.green("\n\u2714 Chatbox \u914D\u7F6E\u5DF2\u751F\u6210"));
|
|
766
|
+
console.log(ansis.gray(` \u914D\u7F6E\u6587\u4EF6\uFF1A${filePath}`));
|
|
767
|
+
console.log(ansis.gray(` base_url\uFF1A${baseUrl}`));
|
|
768
|
+
console.log(ansis.gray(` api_key\uFF1A${maskToken(token)}`));
|
|
769
|
+
if (model)
|
|
770
|
+
console.log(ansis.gray(` model\uFF1A${model}`));
|
|
771
|
+
console.log(ansis.yellow("\n \u2139 \u8BF7\u6253\u5F00 Chatbox\uFF0C\u5728\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u670D\u52A1 \u2192 OpenAI API \u517C\u5BB9\u300D\u4E2D\u586B\u5165\u4EE5\u4E0A base_url / api_key / model"));
|
|
772
|
+
updateLocalConfig({ chatbox: { model } });
|
|
669
773
|
}
|
|
670
774
|
async function init(options = {}) {
|
|
671
775
|
try {
|
|
672
|
-
const
|
|
776
|
+
const memory = readLocalConfig();
|
|
777
|
+
const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectTool(memory.codeType);
|
|
673
778
|
displayBanner(tool);
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
779
|
+
if (isCliTool(tool)) {
|
|
780
|
+
if (options.skipPrompt) {
|
|
781
|
+
await installTool(tool, true);
|
|
782
|
+
} else {
|
|
783
|
+
const installed = await isToolInstalled(tool);
|
|
784
|
+
if (!installed) {
|
|
785
|
+
const shouldInstall = await confirm(`\u672A\u68C0\u6D4B\u5230 ${tool === "claude-code" ? "Claude Code" : "Codex"}\uFF0C\u662F\u5426\u7ACB\u5373\u5B89\u88C5\uFF1F`, true);
|
|
786
|
+
if (shouldInstall) {
|
|
787
|
+
await installTool(tool, false);
|
|
788
|
+
} else {
|
|
789
|
+
console.log(ansis.yellow("\u2139 \u5DF2\u8DF3\u8FC7 CLI \u5B89\u88C5\uFF0C\u4EC5\u5199\u5165\u914D\u7F6E\u6587\u4EF6"));
|
|
790
|
+
}
|
|
682
791
|
} else {
|
|
683
|
-
console.log(ansis.
|
|
792
|
+
console.log(ansis.green(`\u2714 ${tool === "claude-code" ? "Claude Code" : "Codex"} \u5DF2\u5B89\u88C5`));
|
|
684
793
|
}
|
|
685
|
-
} else {
|
|
686
|
-
console.log(ansis.green(`\u2714 ${tool === "claude-code" ? "Claude Code" : "Codex"} \u5DF2\u5B89\u88C5`));
|
|
687
794
|
}
|
|
795
|
+
} else {
|
|
796
|
+
console.log(ansis.gray("\u2139 Chatbox \u4E3A\u684C\u9762\u5BA2\u6237\u7AEF\uFF0C\u9700\u81EA\u884C\u5B89\u88C5\uFF1B\u672C\u5DE5\u5177\u4EC5\u751F\u6210\u914D\u7F6E\u6587\u4EF6"));
|
|
688
797
|
}
|
|
689
|
-
const baseUrl = options.baseUrl || (options.skipPrompt ? "" : await inputBaseUrl());
|
|
798
|
+
const baseUrl = options.baseUrl || (options.skipPrompt ? memory.baseUrl || "" : await inputBaseUrl(memory.baseUrl));
|
|
690
799
|
if (!baseUrl) {
|
|
691
800
|
console.error(ansis.red("\u2716 \u7F3A\u5C11 base_url\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u914D\u7F6E"));
|
|
692
801
|
process.exit(1);
|
|
693
802
|
}
|
|
694
|
-
const token = options.token || (options.skipPrompt ? "" : await inputApiToken());
|
|
803
|
+
const token = options.token || (options.skipPrompt ? memory.token || "" : await inputApiToken(memory.token));
|
|
695
804
|
if (!token) {
|
|
696
805
|
console.error(ansis.red("\u2716 \u7F3A\u5C11 api_token\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u914D\u7F6E"));
|
|
697
806
|
process.exit(1);
|
|
698
807
|
}
|
|
699
808
|
if (tool === "claude-code") {
|
|
700
|
-
await configureClaudeCode(options, baseUrl, token);
|
|
809
|
+
await configureClaudeCode(options, baseUrl, token, memory);
|
|
810
|
+
} else if (tool === "codex") {
|
|
811
|
+
await configureCodex(options, baseUrl, token, memory);
|
|
701
812
|
} else {
|
|
702
|
-
await
|
|
813
|
+
await configureChatbox(options, baseUrl, token, memory);
|
|
703
814
|
}
|
|
815
|
+
updateLocalConfig({ codeType: tool, baseUrl, token });
|
|
704
816
|
console.log(`
|
|
705
817
|
${ansis.cyan("\u{1F389} \u914D\u7F6E\u5B8C\u6210\uFF01\u73B0\u5728\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u5BF9\u5E94 CLI \u5DE5\u5177\u8FDE\u63A5 SrP-LLM \u4E2D\u8F6C\u7AD9\u3002")}`);
|
|
706
818
|
} catch (error) {
|
|
@@ -714,10 +826,41 @@ ${ansis.cyan("\u{1F389} \u914D\u7F6E\u5B8C\u6210\uFF01\u73B0\u5728\u53EF\u4EE5\u
|
|
|
714
826
|
}
|
|
715
827
|
}
|
|
716
828
|
|
|
829
|
+
function getDownloadsYamlPath() {
|
|
830
|
+
const home = homedir();
|
|
831
|
+
const candidates = [
|
|
832
|
+
process.env.USERPROFILE ? join(process.env.USERPROFILE, "Downloads") : "",
|
|
833
|
+
join(home, "Downloads")
|
|
834
|
+
];
|
|
835
|
+
for (const c of candidates) {
|
|
836
|
+
if (c)
|
|
837
|
+
return join(c, "srpllm-chatbox-config.yaml");
|
|
838
|
+
}
|
|
839
|
+
return join(home, "Downloads", "srpllm-chatbox-config.yaml");
|
|
840
|
+
}
|
|
717
841
|
async function uninstall(options = {}) {
|
|
718
842
|
try {
|
|
719
|
-
const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await
|
|
843
|
+
const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectTool();
|
|
720
844
|
displayBanner(tool);
|
|
845
|
+
if (tool === "chatbox") {
|
|
846
|
+
console.log(ansis.blue("\n\u2139 \u6B63\u5728\u6E05\u7406 Chatbox \u751F\u6210\u7684\u914D\u7F6E\u6587\u4EF6..."));
|
|
847
|
+
const yamlPath = getDownloadsYamlPath();
|
|
848
|
+
if (existsSync(yamlPath)) {
|
|
849
|
+
unlinkSync(yamlPath);
|
|
850
|
+
console.log(ansis.green(`\u2714 \u5DF2\u5220\u9664\uFF1A${yamlPath}`));
|
|
851
|
+
} else {
|
|
852
|
+
console.log(ansis.gray("\u2139 \u672A\u627E\u5230\u751F\u6210\u7684 Chatbox \u914D\u7F6E\u6587\u4EF6\uFF0C\u65E0\u9700\u6E05\u7406"));
|
|
853
|
+
}
|
|
854
|
+
const memory2 = readLocalConfig();
|
|
855
|
+
delete memory2.chatbox;
|
|
856
|
+
if (memory2.codeType === tool)
|
|
857
|
+
delete memory2.codeType;
|
|
858
|
+
writeLocalConfig(memory2);
|
|
859
|
+
console.log(ansis.gray("\u2714 \u5DF2\u6E05\u9664\u672C\u5730\u8BB0\u5FC6"));
|
|
860
|
+
console.log(`
|
|
861
|
+
${ansis.cyan("\u{1F389} \u6E05\u7406\u5B8C\u6210")}`);
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
721
864
|
const removeCli = options.skipPrompt ? false : await confirm(`\u662F\u5426\u540C\u65F6\u5378\u8F7D ${tool === "claude-code" ? "Claude Code" : "Codex"} CLI\uFF1F`, false);
|
|
722
865
|
console.log(ansis.blue(`
|
|
723
866
|
\u2139 \u6B63\u5728\u6E05\u7406 ${tool === "claude-code" ? "Claude Code" : "Codex"} \u7684\u4E2D\u8F6C\u7AD9\u914D\u7F6E...`));
|
|
@@ -727,7 +870,16 @@ async function uninstall(options = {}) {
|
|
|
727
870
|
clearCodexApiConfig();
|
|
728
871
|
}
|
|
729
872
|
console.log(ansis.green("\u2714 \u4E2D\u8F6C\u7AD9\u914D\u7F6E\u5DF2\u6E05\u9664"));
|
|
730
|
-
|
|
873
|
+
const memory = readLocalConfig();
|
|
874
|
+
if (tool === "claude-code")
|
|
875
|
+
delete memory.claude;
|
|
876
|
+
else
|
|
877
|
+
delete memory.codex;
|
|
878
|
+
if (memory.codeType === tool)
|
|
879
|
+
delete memory.codeType;
|
|
880
|
+
writeLocalConfig(memory);
|
|
881
|
+
console.log(ansis.gray("\u2714 \u5DF2\u6E05\u9664\u672C\u5730\u8BB0\u5FC6"));
|
|
882
|
+
if (removeCli && isCliTool(tool)) {
|
|
731
883
|
const ok = await uninstallTool(tool);
|
|
732
884
|
if (!ok)
|
|
733
885
|
console.log(ansis.yellow("\u2139 CLI \u5378\u8F7D\u672A\u5B8C\u5168\u6210\u529F\uFF0C\u53EF\u624B\u52A8\u5378\u8F7D"));
|
|
@@ -744,4 +896,4 @@ ${ansis.cyan("\u{1F389} \u6E05\u7406\u5B8C\u6210")}`);
|
|
|
744
896
|
}
|
|
745
897
|
}
|
|
746
898
|
|
|
747
|
-
export {
|
|
899
|
+
export { isToolInstalled as A, detectInstalledVersion as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, selectInstallMethod as E, installTool as F, uninstallTool as G, readLocalConfig as H, writeLocalConfig as I, updateLocalConfig as J, fetchModels as K, buildModelsChoices as L, MODEL_PREFIX as M, filterByPrefix as N, version as O, RELAY_TOOL_TYPES as R, isWindows as a, CLAUDE_SETTINGS_FILE as b, commandExists as c, CODEX_DIR as d, CODEX_CONFIG_FILE as e, CODEX_AUTH_FILE as f, getPlatform as g, CODE_TOOL_TYPES as h, init as i, CODE_TOOL_ALIASES as j, CODE_TOOL_LABELS as k, isCodeToolType as l, isCliTool as m, RELAY_PROVIDER_ID as n, ensureClaudeDir as o, readClaudeSettings as p, getExistingClaudeApiConfig as q, resolveCodeToolType as r, clearClaudeApiConfig as s, displayClaudeConfig as t, uninstall as u, getExistingCodexConfig as v, writeClaudeApiConfig as w, writeCodexApiConfig as x, clearCodexApiConfig as y, displayCodexConfig as z };
|