srpllm 1.1.0 → 1.2.1

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.BfKOtWGn.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.BfKOtWGn.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,12 +544,13 @@ 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
- spinner.succeed(`\u2714 \u5DF2\u83B7\u53D6 ${models.length} \u4E2A\u53EF\u7528\u6A21\u578B`);
553
+ spinner.succeed("\u2714 \u5DF2\u83B7\u53D6\u6A21\u578B\u5217\u8868");
526
554
  return models;
527
555
  } catch (error) {
528
556
  spinner.fail(`\u2716 \u62C9\u53D6\u6A21\u578B\u5217\u8868\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`);
@@ -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.1";
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",
@@ -562,7 +594,7 @@ async function inputBaseUrl(defaultUrl) {
562
594
  const { url } = await inquirer.prompt({
563
595
  type: "input",
564
596
  name: "url",
565
- message: "\u8BF7\u8F93\u5165\u4E2D\u8F6C\u7AD9 base_url\uFF08\u4F8B\u5982 https://api.srpllm.com\uFF09\uFF1A",
597
+ message: "\u8BF7\u8F93\u5165\u4E2D\u8F6C\u7AD9 base_url\uFF1A",
566
598
  default: defaultUrl,
567
599
  validate: (value) => {
568
600
  const v = value.trim();
@@ -618,6 +650,18 @@ async function fetchModelList(baseUrl, token) {
618
650
  return null;
619
651
  }
620
652
  }
653
+ async function fetchFilteredModels(baseUrl, token, prefix) {
654
+ const allModels = await fetchModelList(baseUrl, token);
655
+ if (!allModels)
656
+ return null;
657
+ const filtered = filterByPrefix(allModels, prefix);
658
+ if (filtered.length === 0) {
659
+ console.log(ansis.yellow(`\u2139 \u5DF2\u83B7\u53D6 ${allModels.length} \u4E2A\u6A21\u578B\uFF0C\u4F46\u65E0 ${prefix}* \u524D\u7F00\u7684\u6A21\u578B\uFF0C\u53EF\u624B\u52A8\u8F93\u5165`));
660
+ return null;
661
+ }
662
+ console.log(ansis.gray(`\u2139 \u5DF2\u83B7\u53D6 ${allModels.length} \u4E2A\u6A21\u578B\uFF0C\u8FC7\u6EE4\u540E\u5269\u4F59 ${filtered.length} \u4E2A ${prefix}* \u6A21\u578B`));
663
+ return filtered;
664
+ }
621
665
  async function promptModelFromList(models, message, preset, skipPrompt, defaultModel) {
622
666
  if (preset && preset.trim())
623
667
  return preset.trim();
@@ -665,7 +709,7 @@ async function configureClaudeCode(options, baseUrl, token, memory) {
665
709
  return;
666
710
  }
667
711
  }
668
- const models = await fetchModelList(baseUrl, token);
712
+ const models = await fetchFilteredModels(baseUrl, token, MODEL_PREFIX["claude-code"]);
669
713
  const m = memory.claude;
670
714
  const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u4E3B\u6A21\u578B (ANTHROPIC_MODEL)\uFF1A", options.model, options.skipPrompt, m?.model);
671
715
  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 +735,7 @@ async function configureCodex(options, baseUrl, token, memory) {
691
735
  return;
692
736
  }
693
737
  }
694
- const models = await fetchModelList(baseUrl, token);
738
+ const models = await fetchFilteredModels(baseUrl, token, MODEL_PREFIX.codex);
695
739
  const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u9ED8\u8BA4\u4F7F\u7528\u7684\u6A21\u578B\uFF1A", options.model, options.skipPrompt, memory.codex?.model);
696
740
  const config = { baseUrl, token, model };
697
741
  writeCodexApiConfig(config);
@@ -699,25 +743,66 @@ async function configureCodex(options, baseUrl, token, memory) {
699
743
  displayCodexConfig(config);
700
744
  updateLocalConfig({ codex: { model } });
701
745
  }
746
+ function getDownloadsDir() {
747
+ const home = homedir();
748
+ const candidates = [
749
+ process.env.USERPROFILE ? join(process.env.USERPROFILE, "Downloads") : "",
750
+ join(home, "Downloads")
751
+ ];
752
+ for (const c of candidates) {
753
+ if (c && existsSync(c))
754
+ return c;
755
+ }
756
+ const fallback = join(home, "Downloads");
757
+ ensureDir(fallback);
758
+ return fallback;
759
+ }
760
+ async function configureChatbox(options, baseUrl, token, memory) {
761
+ const models = await fetchFilteredModels(baseUrl, token, MODEL_PREFIX.chatbox);
762
+ const model = await promptModelFromList(models, "\u8BF7\u9009\u62E9\u9ED8\u8BA4\u6A21\u578B\uFF08chat- \u524D\u7F00\uFF09\uFF1A", options.model, options.skipPrompt, memory.chatbox?.model);
763
+ const downloads = getDownloadsDir();
764
+ const filePath = join(downloads, "srpllm-chatbox-config.yaml");
765
+ const yaml = [
766
+ "# SrP-LLM \u4E2D\u8F6C\u7AD9 Chatbox \u914D\u7F6E",
767
+ "# \u5728 Chatbox \u5BA2\u6237\u7AEF\u300C\u8BBE\u7F6E \u2192 \u6A21\u578B\u670D\u52A1 \u2192 OpenAI API\u300D\u4E2D\u586B\u5165\u4EE5\u4E0B\u4FE1\u606F",
768
+ `base_url: ${baseUrl}`,
769
+ `api_key: ${token}`,
770
+ model ? `model: ${model}` : "# model: \uFF08\u672A\u9009\u62E9\uFF0C\u8BF7\u5728 Chatbox \u4E2D\u624B\u52A8\u6307\u5B9A\uFF09",
771
+ ""
772
+ ].join("\n");
773
+ writeFile(filePath, yaml);
774
+ console.log(ansis.green("\n\u2714 Chatbox \u914D\u7F6E\u5DF2\u751F\u6210"));
775
+ console.log(ansis.gray(` \u914D\u7F6E\u6587\u4EF6\uFF1A${filePath}`));
776
+ console.log(ansis.gray(` base_url\uFF1A${baseUrl}`));
777
+ console.log(ansis.gray(` api_key\uFF1A${maskToken(token)}`));
778
+ if (model)
779
+ console.log(ansis.gray(` model\uFF1A${model}`));
780
+ 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"));
781
+ updateLocalConfig({ chatbox: { model } });
782
+ }
702
783
  async function init(options = {}) {
703
784
  try {
704
785
  const memory = readLocalConfig();
705
- const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectCodeTool(memory.codeType);
786
+ const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectTool(memory.codeType);
706
787
  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);
788
+ if (isCliTool(tool)) {
789
+ if (options.skipPrompt) {
790
+ await installTool(tool, true);
791
+ } else {
792
+ const installed = await isToolInstalled(tool);
793
+ if (!installed) {
794
+ const shouldInstall = await confirm(`\u672A\u68C0\u6D4B\u5230 ${tool === "claude-code" ? "Claude Code" : "Codex"}\uFF0C\u662F\u5426\u7ACB\u5373\u5B89\u88C5\uFF1F`, true);
795
+ if (shouldInstall) {
796
+ await installTool(tool, false);
797
+ } else {
798
+ console.log(ansis.yellow("\u2139 \u5DF2\u8DF3\u8FC7 CLI \u5B89\u88C5\uFF0C\u4EC5\u5199\u5165\u914D\u7F6E\u6587\u4EF6"));
799
+ }
715
800
  } else {
716
- console.log(ansis.yellow("\u2139 \u5DF2\u8DF3\u8FC7 CLI \u5B89\u88C5\uFF0C\u4EC5\u5199\u5165\u914D\u7F6E\u6587\u4EF6"));
801
+ console.log(ansis.green(`\u2714 ${tool === "claude-code" ? "Claude Code" : "Codex"} \u5DF2\u5B89\u88C5`));
717
802
  }
718
- } else {
719
- console.log(ansis.green(`\u2714 ${tool === "claude-code" ? "Claude Code" : "Codex"} \u5DF2\u5B89\u88C5`));
720
803
  }
804
+ } else {
805
+ 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
806
  }
722
807
  const baseUrl = options.baseUrl || (options.skipPrompt ? memory.baseUrl || "" : await inputBaseUrl(memory.baseUrl));
723
808
  if (!baseUrl) {
@@ -731,8 +816,10 @@ async function init(options = {}) {
731
816
  }
732
817
  if (tool === "claude-code") {
733
818
  await configureClaudeCode(options, baseUrl, token, memory);
734
- } else {
819
+ } else if (tool === "codex") {
735
820
  await configureCodex(options, baseUrl, token, memory);
821
+ } else {
822
+ await configureChatbox(options, baseUrl, token, memory);
736
823
  }
737
824
  updateLocalConfig({ codeType: tool, baseUrl, token });
738
825
  console.log(`
@@ -748,10 +835,41 @@ ${ansis.cyan("\u{1F389} \u914D\u7F6E\u5B8C\u6210\uFF01\u73B0\u5728\u53EF\u4EE5\u
748
835
  }
749
836
  }
750
837
 
838
+ function getDownloadsYamlPath() {
839
+ const home = homedir();
840
+ const candidates = [
841
+ process.env.USERPROFILE ? join(process.env.USERPROFILE, "Downloads") : "",
842
+ join(home, "Downloads")
843
+ ];
844
+ for (const c of candidates) {
845
+ if (c)
846
+ return join(c, "srpllm-chatbox-config.yaml");
847
+ }
848
+ return join(home, "Downloads", "srpllm-chatbox-config.yaml");
849
+ }
751
850
  async function uninstall(options = {}) {
752
851
  try {
753
- const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectCodeTool();
852
+ const tool = options.codeType ? resolveCodeToolType(options.codeType) : options.skipPrompt ? "claude-code" : await selectTool();
754
853
  displayBanner(tool);
854
+ if (tool === "chatbox") {
855
+ console.log(ansis.blue("\n\u2139 \u6B63\u5728\u6E05\u7406 Chatbox \u751F\u6210\u7684\u914D\u7F6E\u6587\u4EF6..."));
856
+ const yamlPath = getDownloadsYamlPath();
857
+ if (existsSync(yamlPath)) {
858
+ unlinkSync(yamlPath);
859
+ console.log(ansis.green(`\u2714 \u5DF2\u5220\u9664\uFF1A${yamlPath}`));
860
+ } else {
861
+ console.log(ansis.gray("\u2139 \u672A\u627E\u5230\u751F\u6210\u7684 Chatbox \u914D\u7F6E\u6587\u4EF6\uFF0C\u65E0\u9700\u6E05\u7406"));
862
+ }
863
+ const memory2 = readLocalConfig();
864
+ delete memory2.chatbox;
865
+ if (memory2.codeType === tool)
866
+ delete memory2.codeType;
867
+ writeLocalConfig(memory2);
868
+ console.log(ansis.gray("\u2714 \u5DF2\u6E05\u9664\u672C\u5730\u8BB0\u5FC6"));
869
+ console.log(`
870
+ ${ansis.cyan("\u{1F389} \u6E05\u7406\u5B8C\u6210")}`);
871
+ return;
872
+ }
755
873
  const removeCli = options.skipPrompt ? false : await confirm(`\u662F\u5426\u540C\u65F6\u5378\u8F7D ${tool === "claude-code" ? "Claude Code" : "Codex"} CLI\uFF1F`, false);
756
874
  console.log(ansis.blue(`
757
875
  \u2139 \u6B63\u5728\u6E05\u7406 ${tool === "claude-code" ? "Claude Code" : "Codex"} \u7684\u4E2D\u8F6C\u7AD9\u914D\u7F6E...`));
@@ -770,7 +888,7 @@ async function uninstall(options = {}) {
770
888
  delete memory.codeType;
771
889
  writeLocalConfig(memory);
772
890
  console.log(ansis.gray("\u2714 \u5DF2\u6E05\u9664\u672C\u5730\u8BB0\u5FC6"));
773
- if (removeCli) {
891
+ if (removeCli && isCliTool(tool)) {
774
892
  const ok = await uninstallTool(tool);
775
893
  if (!ok)
776
894
  console.log(ansis.yellow("\u2139 CLI \u5378\u8F7D\u672A\u5B8C\u5168\u6210\u529F\uFF0C\u53EF\u624B\u52A8\u5378\u8F7D"));
@@ -787,4 +905,4 @@ ${ansis.cyan("\u{1F389} \u6E05\u7406\u5B8C\u6210")}`);
787
905
  }
788
906
  }
789
907
 
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 };
908
+ 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.1",
5
5
  "packageManager": "pnpm@10.17.1",
6
6
  "description": "SrP-LLM 中转站客户端一键配置工具:安装 Claude Code / Codex 并引导填写 base_url、api_token 与模型",
7
7
  "author": {