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 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, G as version } from './shared/srpllm.gk7klSey.mjs';
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 'node:fs';
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 CODE_TOOL_ALIASES: Record<string, CodeToolType>;
62
- declare const CODE_TOOL_LABELS: Record<CodeToolType, string>;
63
- declare function resolveCodeToolType(value: unknown): CodeToolType;
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 CODE_TOOL_ALIASES: Record<string, CodeToolType>;
62
- declare const CODE_TOOL_LABELS: Record<CodeToolType, string>;
63
- declare function resolveCodeToolType(value: unknown): CodeToolType;
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, R as RELAY_PROVIDER_ID, F as buildModelsChoices, o as clearClaudeApiConfig, t as clearCodexApiConfig, c as commandExists, y as detectInstalledVersion, p as displayClaudeConfig, v as displayCodexConfig, l as ensureClaudeDir, E as fetchModels, n as getExistingClaudeApiConfig, q as getExistingCodexConfig, g as getPlatform, i as init, A as installTool, x as isToolInstalled, a as isWindows, m as readClaudeSettings, r as resolveCodeToolType, z as selectInstallMethod, u as uninstall, B as uninstallTool, w as writeClaudeApiConfig, s as writeCodexApiConfig } from './shared/srpllm.gk7klSey.mjs';
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 'node:fs';
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 { writeFileSync, existsSync, readFileSync, mkdirSync } from 'node:fs';
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 && CODE_TOOL_TYPES.includes(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.fail("\u2716 \u4E2D\u8F6C\u7AD9\u8FD4\u56DE\u7684\u6A21\u578B\u5217\u8868\u4E3A\u7A7A");
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.1";
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 selectCodeTool() {
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
- { name: "Claude Code", value: "claude-code" },
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 models = await fetchModelList(baseUrl, token);
640
- const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u4E3B\u6A21\u578B (ANTHROPIC_MODEL)\uFF1A", options.model, options.skipPrompt);
641
- const opusModel = await promptModelFromList(models, "\u8BF7\u9009\u62E9 Opus \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_OPUS_MODEL)\uFF1A", options.opusModel, options.skipPrompt);
642
- const sonnetModel = await promptModelFromList(models, "\u8BF7\u9009\u62E9 Sonnet \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_SONNET_MODEL)\uFF1A", options.sonnetModel, options.skipPrompt);
643
- const haikuModel = await promptModelFromList(models, "\u8BF7\u9009\u62E9 Haiku \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_HAIKU_MODEL)\uFF1A", options.haikuModel, options.skipPrompt);
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 models = await fetchModelList(baseUrl, token);
664
- const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u9ED8\u8BA4\u4F7F\u7528\u7684\u6A21\u578B\uFF1A", options.model, options.skipPrompt);
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 tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectCodeTool();
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 (options.skipPrompt) {
675
- await installTool(tool, true);
676
- } else {
677
- const installed = await isToolInstalled(tool);
678
- if (!installed) {
679
- const shouldInstall = await confirm(`\u672A\u68C0\u6D4B\u5230 ${tool === "claude-code" ? "Claude Code" : "Codex"}\uFF0C\u662F\u5426\u7ACB\u5373\u5B89\u88C5\uFF1F`, true);
680
- if (shouldInstall) {
681
- await installTool(tool, false);
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.yellow("\u2139 \u5DF2\u8DF3\u8FC7 CLI \u5B89\u88C5\uFF0C\u4EC5\u5199\u5165\u914D\u7F6E\u6587\u4EF6"));
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 configureCodex(options, baseUrl, token);
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 selectCodeTool();
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
- if (removeCli) {
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 { installTool as A, uninstallTool as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, fetchModels as E, buildModelsChoices as F, version as G, RELAY_PROVIDER_ID 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, ensureClaudeDir as l, readClaudeSettings as m, getExistingClaudeApiConfig as n, clearClaudeApiConfig as o, displayClaudeConfig as p, getExistingCodexConfig as q, resolveCodeToolType as r, writeCodexApiConfig as s, clearCodexApiConfig as t, uninstall as u, displayCodexConfig as v, writeClaudeApiConfig as w, isToolInstalled as x, detectInstalledVersion as y, selectInstallMethod as z };
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 };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srpllm",
3
3
  "type": "module",
4
- "version": "1.0.1",
4
+ "version": "1.2.0",
5
5
  "packageManager": "pnpm@10.17.1",
6
6
  "description": "SrP-LLM 中转站客户端一键配置工具:安装 Claude Code / Codex 并引导填写 base_url、api_token 与模型",
7
7
  "author": {