@raolin2025/claude-code-node 2.8.24 → 2.8.25

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/core/cli.js +51 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raolin2025/claude-code-node",
3
- "version": "2.8.24",
3
+ "version": "2.8.25",
4
4
  "description": "Node.js AI Code Agent CLI - Zero dependencies, pure JavaScript, security hardened, multi-channel notifications, Telegram & QQ Bot remote programming, rich media upload, multi-account management",
5
5
  "type": "module",
6
6
  "main": "src/core/index.js",
package/src/core/cli.js CHANGED
@@ -254,6 +254,9 @@ Commands:
254
254
  /help — Show this help
255
255
  /model NAME — Switch model
256
256
  /models — List available models from current API
257
+ /api-base URL — Switch API base URL at runtime (local session only)
258
+ /api-key KEY — Switch API key at runtime (local session only)
259
+ /api — Show current API base/key/model
257
260
  /tools — List available tools
258
261
  /session — Show session info
259
262
  /sessions — List all sessions
@@ -284,6 +287,11 @@ const DETAILED_HELP = {
284
287
 
285
288
  models: "/models\n Fetch and display all available models from the current API provider.\n Shows a numbered list, then prompts you to select by number or name.\n Requires a configured API key (the one you used to start cc-node).\n Uses the endpoint: <apiBase>/models",
286
289
 
290
+ apiBase:"/api-base <url>\n Switch the LLM API base URL at runtime (session-only, not persisted).\n Takes effect immediately for the next message.\n After switching, cc-node re-probes the context window.\n Then use /model <name> or /models to pick the new provider's model.\n For local llama.cpp/Ollama (no auth) you can skip /api-key.\n\n Example: /api-base http://127.0.0.1:11434/v1",
291
+ apiKey: "/api-key <key>\n Switch the LLM API key at runtime (session-only, not persisted).\n Takes effect immediately for the next message.\n For local llama.cpp/Ollama (no auth) you can leave it unset.\n\n Example: /api-key sk-xxxxxxxx",
292
+
293
+ api: "/api\n Show the current API configuration: base URL, key (masked), and model.",
294
+
287
295
  tools: "/tools\n List all available tools that cc-node can use.\n Shows tool names with their short descriptions.\n\n Tools include: Bash, Read, Edit, Write, Glob, Grep,\n WebFetch, WebSearch, AskUserQuestion, GitTool",
288
296
 
289
297
  session: "/session\n Show current session information:\n - Session ID\n - Session title\n - Number of messages\n - Number of tool call turns",
@@ -425,7 +433,7 @@ export async function main() {
425
433
  const config = new Config()
426
434
  await config.load(process.cwd())
427
435
 
428
- const apiBase = cliArgs.apiBase || config.get('apiBase') || process.env.LLM_API_BASE || ''
436
+ let apiBase = cliArgs.apiBase || config.get('apiBase') || process.env.LLM_API_BASE || ''
429
437
  // apiBase 指向自建本地服务(Ollama / llama.cpp / vLLM 等)时允许缺省 apiKey
430
438
  const localApiBase = isLocalLlmServer(apiBase)
431
439
  let model = cliArgs.model || config.get('model') || ''
@@ -488,7 +496,7 @@ export async function main() {
488
496
  const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
489
497
  const permissionMode = cliArgs.permissionMode || config.get('permissionMode')
490
498
  const maxTurns = cliArgs.maxTurns || config.get('maxTurns')
491
- const apiKey = cliArgs.apiKey || config.get('apiKey') || ''
499
+ let apiKey = cliArgs.apiKey || config.get('apiKey') || ''
492
500
  const verbose = cliArgs.verbose || config.get('verbose')
493
501
 
494
502
  const registry = createDefaultRegistry()
@@ -749,6 +757,47 @@ const systemPrompt = cliArgs.systemPrompt || DEFAULT_SYSTEM_PROMPT
749
757
  }
750
758
  else console.log(`Model: ${engine.config.model}`)
751
759
  break
760
+ case 'api-base':
761
+ // /api-base <url> — 运行时切换 LLM 来源地址(仅本次会话生效)
762
+ if (rest[0]) {
763
+ const newBase = rest.join(' ').trim().replace(/\/+$/, '')
764
+ apiBase = newBase
765
+ engine.config.apiBase = newBase
766
+ console.log(`API Base → ${newBase}`)
767
+ // 切换来源后重新探测上下文窗口(旧来源窗口可能不同)
768
+ const manual = config.get('maxBudgetTokens') || 0
769
+ try {
770
+ const { window: win, source } = await detectContextWindow({ model, apiBase: newBase, apiKey, manualWindow: manual })
771
+ tokenBudget.setWindow(win, source)
772
+ windowSource = source
773
+ console.log(` ↳ Context window → ${formatTokens(win)} (${windowSourceLabel(source)})`)
774
+ } catch (e) {
775
+ console.log(` ⚠️ 窗口探测失败: ${e.message}`)
776
+ }
777
+ // 提示切模型:不同来源的模型名不同
778
+ const localNow = isLocalLlmServer(newBase)
779
+ if (!localNow && !apiKey) {
780
+ console.log(' ⚠️ 新来源需 API Key → 请用 /api-key <key> 设置')
781
+ }
782
+ console.log(' ℹ️ 不同模型的名称不同,请用 /model <名称> 选择新来源的模型,或用 /models 查看')
783
+ }
784
+ else console.log(`API Base: ${engine.config.apiBase}`)
785
+ break
786
+ case 'api-key':
787
+ // /api-key <key> — 运行时切换 LLM API Key(仅本次会话生效)
788
+ if (rest[0]) {
789
+ const newKey = rest.join(' ').trim()
790
+ apiKey = newKey
791
+ engine.config.apiKey = newKey
792
+ console.log(`API Key → ${newKey.slice(0, 4)}...${newKey.slice(-4)}`)
793
+ }
794
+ else console.log(`API Key: ${engine.config.apiKey ? `已设置 (${engine.config.apiKey.slice(0, 4)}...${engine.config.apiKey.slice(-4)})` : '未设置'}`)
795
+ break
796
+ case 'api':
797
+ console.log(`API Base: ${engine.config.apiBase}`)
798
+ console.log(`API Key: ${engine.config.apiKey ? `已设置 (${engine.config.apiKey.slice(0, 4)}...${engine.config.apiKey.slice(-4)})` : '未设置'}`)
799
+ console.log(`Model: ${engine.config.model}`)
800
+ break
752
801
  case 'window': {
753
802
  const arg = rest[0] ? rest.join(' ').trim() : ''
754
803
  if (!arg) {