srpllm 1.1.0 → 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, J as version } from './shared/srpllm.BDtiig24.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';
@@ -72,7 +77,7 @@ declare function uninstallTool(tool: CodeToolType): Promise<boolean>;
72
77
 
73
78
  interface LocalConfig {
74
79
  /** 上次选的工具 */
75
- codeType?: 'claude-code' | 'codex';
80
+ codeType?: 'claude-code' | 'codex' | 'chatbox';
76
81
  /** 上次输入的中转站 base_url */
77
82
  baseUrl?: string;
78
83
  /** 上次输入的 api_token(明文存储,文件权限 600) */
@@ -88,6 +93,10 @@ interface LocalConfig {
88
93
  codex?: {
89
94
  model?: string;
90
95
  };
96
+ /** 上次为 Chatbox 选的模型 */
97
+ chatbox?: {
98
+ model?: string;
99
+ };
91
100
  }
92
101
  declare function readLocalConfig(): LocalConfig;
93
102
  declare function writeLocalConfig(config: LocalConfig): void;
@@ -108,11 +117,17 @@ declare function buildModelsChoices(models: RemoteModel[]): Array<{
108
117
  name: string;
109
118
  value: string;
110
119
  }>;
120
+ /**
121
+ * 按中转站客户端前缀过滤模型列表。
122
+ * claude-code → cc-,codex → cx-,chatbox → chat-
123
+ * 不带前缀的模型一律排除(中转站约定模型 id 必须带客户端前缀)。
124
+ */
125
+ declare function filterByPrefix(models: RemoteModel[], prefix: string): RemoteModel[];
111
126
 
112
127
  type Platform = 'windows' | 'macos' | 'linux';
113
128
  declare function getPlatform(): Platform;
114
129
  declare function isWindows(): boolean;
115
130
  declare function commandExists(command: string): Promise<boolean>;
116
131
 
117
- 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, readLocalConfig, resolveCodeToolType, selectInstallMethod, uninstall, uninstallTool, updateLocalConfig, writeClaudeApiConfig, writeCodexApiConfig, writeLocalConfig };
118
- export type { ClaudeApiConfig, CodeToolType, CodexApiConfig, InstallMethod, LocalConfig, 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';
@@ -72,7 +77,7 @@ declare function uninstallTool(tool: CodeToolType): Promise<boolean>;
72
77
 
73
78
  interface LocalConfig {
74
79
  /** 上次选的工具 */
75
- codeType?: 'claude-code' | 'codex';
80
+ codeType?: 'claude-code' | 'codex' | 'chatbox';
76
81
  /** 上次输入的中转站 base_url */
77
82
  baseUrl?: string;
78
83
  /** 上次输入的 api_token(明文存储,文件权限 600) */
@@ -88,6 +93,10 @@ interface LocalConfig {
88
93
  codex?: {
89
94
  model?: string;
90
95
  };
96
+ /** 上次为 Chatbox 选的模型 */
97
+ chatbox?: {
98
+ model?: string;
99
+ };
91
100
  }
92
101
  declare function readLocalConfig(): LocalConfig;
93
102
  declare function writeLocalConfig(config: LocalConfig): void;
@@ -108,11 +117,17 @@ declare function buildModelsChoices(models: RemoteModel[]): Array<{
108
117
  name: string;
109
118
  value: string;
110
119
  }>;
120
+ /**
121
+ * 按中转站客户端前缀过滤模型列表。
122
+ * claude-code → cc-,codex → cx-,chatbox → chat-
123
+ * 不带前缀的模型一律排除(中转站约定模型 id 必须带客户端前缀)。
124
+ */
125
+ declare function filterByPrefix(models: RemoteModel[], prefix: string): RemoteModel[];
111
126
 
112
127
  type Platform = 'windows' | 'macos' | 'linux';
113
128
  declare function getPlatform(): Platform;
114
129
  declare function isWindows(): boolean;
115
130
  declare function commandExists(command: string): Promise<boolean>;
116
131
 
117
- 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, readLocalConfig, resolveCodeToolType, selectInstallMethod, uninstall, uninstallTool, updateLocalConfig, writeClaudeApiConfig, writeCodexApiConfig, writeLocalConfig };
118
- export type { ClaudeApiConfig, CodeToolType, CodexApiConfig, InstallMethod, LocalConfig, 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, I as buildModelsChoices, o as clearClaudeApiConfig, t as clearCodexApiConfig, c as commandExists, y as detectInstalledVersion, p as displayClaudeConfig, v as displayCodexConfig, l as ensureClaudeDir, H 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, E as readLocalConfig, r as resolveCodeToolType, z as selectInstallMethod, u as uninstall, B as uninstallTool, G as updateLocalConfig, w as writeClaudeApiConfig, s as writeCodexApiConfig, F as writeLocalConfig } from './shared/srpllm.BDtiig24.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 { existsSync, readFileSync, writeFileSync, mkdirSync, chmodSync } 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) {
@@ -497,6 +511,19 @@ function updateLocalConfig(patch) {
497
511
  writeLocalConfig({ ...existing, ...patch });
498
512
  }
499
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
+ }
500
527
  async function fetchModels(baseUrl, token) {
501
528
  const url = `${baseUrl.replace(/\/$/, "")}/v1/models`;
502
529
  const spinner = ora(`\u6B63\u5728\u4ECE ${url} \u62C9\u53D6\u6A21\u578B\u5217\u8868...`).start();
@@ -517,9 +544,10 @@ async function fetchModels(baseUrl, token) {
517
544
  const models = data.map((m) => ({
518
545
  id: String(m.id || m.name || m.model).trim(),
519
546
  ownedBy: m.owned_by || m.ownedBy
520
- })).filter((m) => m.id);
547
+ })).filter((m) => m.id && !isWildcardModel(m.id));
521
548
  if (models.length === 0) {
522
- 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"));
523
551
  throw new Error("\u6A21\u578B\u5217\u8868\u4E3A\u7A7A");
524
552
  }
525
553
  spinner.succeed(`\u2714 \u5DF2\u83B7\u53D6 ${models.length} \u4E2A\u53EF\u7528\u6A21\u578B`);
@@ -535,8 +563,12 @@ function buildModelsChoices(models) {
535
563
  value: m.id
536
564
  }));
537
565
  }
566
+ function filterByPrefix(models, prefix) {
567
+ const p = prefix.toLowerCase();
568
+ return models.filter((m) => m.id.toLowerCase().startsWith(p));
569
+ }
538
570
 
539
- const version = "1.1.0";
571
+ const version = "1.2.0";
540
572
 
541
573
  function displayBanner(codeTool) {
542
574
  const tool = codeTool ? ` ${ansis.gray(`\xB7 ${CODE_TOOL_LABELS[codeTool]}`)}` : "";
@@ -544,11 +576,11 @@ function displayBanner(codeTool) {
544
576
  SrP-LLM \u914D\u7F6E\u5DE5\u5177 v${version}${tool}`));
545
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"));
546
578
  }
547
- async function selectCodeTool(defaultTool) {
548
- const choices = [
549
- { name: "Claude Code", value: "claude-code" },
550
- { name: "Codex", value: "codex" }
551
- ];
579
+ async function selectTool(defaultTool) {
580
+ const choices = ["claude-code", "codex", "chatbox"].map((value) => ({
581
+ name: CODE_TOOL_LABELS[value],
582
+ value
583
+ }));
552
584
  const { tool } = await inquirer.prompt({
553
585
  type: "list",
554
586
  name: "tool",
@@ -665,7 +697,8 @@ async function configureClaudeCode(options, baseUrl, token, memory) {
665
697
  return;
666
698
  }
667
699
  }
668
- const models = await fetchModelList(baseUrl, token);
700
+ const allModels = await fetchModelList(baseUrl, token);
701
+ const models = allModels ? filterByPrefix(allModels, MODEL_PREFIX["claude-code"]) : allModels;
669
702
  const m = memory.claude;
670
703
  const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u4E3B\u6A21\u578B (ANTHROPIC_MODEL)\uFF1A", options.model, options.skipPrompt, m?.model);
671
704
  const opusModel = await promptModelFromList(models, "\u8BF7\u9009\u62E9 Opus \u6863\u6A21\u578B (ANTHROPIC_DEFAULT_OPUS_MODEL)\uFF1A", options.opusModel, options.skipPrompt, m?.opusModel);
@@ -691,7 +724,8 @@ async function configureCodex(options, baseUrl, token, memory) {
691
724
  return;
692
725
  }
693
726
  }
694
- const models = await fetchModelList(baseUrl, token);
727
+ const allModels = await fetchModelList(baseUrl, token);
728
+ const models = allModels ? filterByPrefix(allModels, MODEL_PREFIX.codex) : allModels;
695
729
  const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u9ED8\u8BA4\u4F7F\u7528\u7684\u6A21\u578B\uFF1A", options.model, options.skipPrompt, memory.codex?.model);
696
730
  const config = { baseUrl, token, model };
697
731
  writeCodexApiConfig(config);
@@ -699,25 +733,67 @@ async function configureCodex(options, baseUrl, token, memory) {
699
733
  displayCodexConfig(config);
700
734
  updateLocalConfig({ codex: { model } });
701
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 } });
773
+ }
702
774
  async function init(options = {}) {
703
775
  try {
704
776
  const memory = readLocalConfig();
705
- const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectCodeTool(memory.codeType);
777
+ const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectTool(memory.codeType);
706
778
  displayBanner(tool);
707
- if (options.skipPrompt) {
708
- await installTool(tool, true);
709
- } else {
710
- const installed = await isToolInstalled(tool);
711
- if (!installed) {
712
- const shouldInstall = await confirm(`\u672A\u68C0\u6D4B\u5230 ${tool === "claude-code" ? "Claude Code" : "Codex"}\uFF0C\u662F\u5426\u7ACB\u5373\u5B89\u88C5\uFF1F`, true);
713
- if (shouldInstall) {
714
- 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
+ }
715
791
  } else {
716
- 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`));
717
793
  }
718
- } else {
719
- console.log(ansis.green(`\u2714 ${tool === "claude-code" ? "Claude Code" : "Codex"} \u5DF2\u5B89\u88C5`));
720
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"));
721
797
  }
722
798
  const baseUrl = options.baseUrl || (options.skipPrompt ? memory.baseUrl || "" : await inputBaseUrl(memory.baseUrl));
723
799
  if (!baseUrl) {
@@ -731,8 +807,10 @@ async function init(options = {}) {
731
807
  }
732
808
  if (tool === "claude-code") {
733
809
  await configureClaudeCode(options, baseUrl, token, memory);
734
- } else {
810
+ } else if (tool === "codex") {
735
811
  await configureCodex(options, baseUrl, token, memory);
812
+ } else {
813
+ await configureChatbox(options, baseUrl, token, memory);
736
814
  }
737
815
  updateLocalConfig({ codeType: tool, baseUrl, token });
738
816
  console.log(`
@@ -748,10 +826,41 @@ ${ansis.cyan("\u{1F389} \u914D\u7F6E\u5B8C\u6210\uFF01\u73B0\u5728\u53EF\u4EE5\u
748
826
  }
749
827
  }
750
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
+ }
751
841
  async function uninstall(options = {}) {
752
842
  try {
753
- 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();
754
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
+ }
755
864
  const removeCli = options.skipPrompt ? false : await confirm(`\u662F\u5426\u540C\u65F6\u5378\u8F7D ${tool === "claude-code" ? "Claude Code" : "Codex"} CLI\uFF1F`, false);
756
865
  console.log(ansis.blue(`
757
866
  \u2139 \u6B63\u5728\u6E05\u7406 ${tool === "claude-code" ? "Claude Code" : "Codex"} \u7684\u4E2D\u8F6C\u7AD9\u914D\u7F6E...`));
@@ -770,7 +879,7 @@ async function uninstall(options = {}) {
770
879
  delete memory.codeType;
771
880
  writeLocalConfig(memory);
772
881
  console.log(ansis.gray("\u2714 \u5DF2\u6E05\u9664\u672C\u5730\u8BB0\u5FC6"));
773
- if (removeCli) {
882
+ if (removeCli && isCliTool(tool)) {
774
883
  const ok = await uninstallTool(tool);
775
884
  if (!ok)
776
885
  console.log(ansis.yellow("\u2139 CLI \u5378\u8F7D\u672A\u5B8C\u5168\u6210\u529F\uFF0C\u53EF\u624B\u52A8\u5378\u8F7D"));
@@ -787,4 +896,4 @@ ${ansis.cyan("\u{1F389} \u6E05\u7406\u5B8C\u6210")}`);
787
896
  }
788
897
  }
789
898
 
790
- export { installTool as A, uninstallTool as B, CLAUDE_DIR as C, DEFAULT_CODE_TOOL_TYPE as D, readLocalConfig as E, writeLocalConfig as F, updateLocalConfig as G, fetchModels as H, buildModelsChoices as I, version as J, 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.1.0",
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": {