From 9504eeab629929e5d607372af2f63a18b72163d5 Mon Sep 17 00:00:00 2001 From: Jiang Bohan Date: Mon, 2 Feb 2026 16:43:05 +0800 Subject: [PATCH] feat(cli): add /provider command to show and switch providers The /provider command shows: - Current provider and model - List of available providers (OAuth and API Key) - Status of each provider (configured/not configured) - Instructions for switching providers Co-Authored-By: Claude Opus 4.5 --- src/agent/cli/commands/chat.ts | 64 +++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/agent/cli/commands/chat.ts b/src/agent/cli/commands/chat.ts index b9eaf7d8..e50c159d 100644 --- a/src/agent/cli/commands/chat.ts +++ b/src/agent/cli/commands/chat.ts @@ -11,7 +11,13 @@ import { Agent } from "../../runner.js"; import type { AgentOptions } from "../../types.js"; import { SkillManager } from "../../skills/index.js"; import { autocompleteInput, type AutocompleteOption } from "../autocomplete.js"; -import { colors, dim, cyan, brightCyan, yellow, green, gray } from "../colors.js"; +import { colors, dim, cyan, brightCyan, yellow, green, gray, red } from "../colors.js"; +import { + getProviderList, + getCurrentProvider, + getLoginInstructions, + type ProviderInfo, +} from "../../credentials/providers.js"; type ChatOptions = { profile?: string; @@ -31,6 +37,7 @@ const COMMANDS = { session: "Show current session ID", new: "Start a new session", multiline: "Toggle multi-line input mode (end with a line containing only '.')", + provider: "Show current provider and available options", }; function printHelp() { @@ -455,6 +462,10 @@ class InteractiveCLI { } return true; + case "provider": + this.showProviderStatus(); + return true; + default: const invocation = this.skillManager.resolveCommand(input); if (invocation) { @@ -468,6 +479,57 @@ class InteractiveCLI { } } + private showProviderStatus() { + const providers = getProviderList(); + const currentProvider = this.opts.provider ?? getCurrentProvider(); + + console.log(`\n${cyan("🔌 Provider Status")}\n`); + console.log(`${dim("Current:")} ${green(currentProvider)}`); + if (this.opts.model) { + console.log(`${dim("Model:")} ${yellow(this.opts.model)}`); + } + + console.log(`\n${dim("Available Providers:")}`); + + // Group by auth method + const apiKeyProviders = providers.filter(p => p.authMethod === "api-key"); + const oauthProviders = providers.filter(p => p.authMethod === "oauth"); + + // OAuth providers first (more interesting) + for (const p of oauthProviders) { + const status = p.available ? green("✓") : red("✗"); + const current = p.id === currentProvider || (p.id === "claude-code" && currentProvider === "anthropic" && p.available) ? yellow(" (current)") : ""; + const authLabel = cyan("[OAuth]"); + const statusLabel = p.available ? green("ready") : dim("not logged in"); + console.log(` ${status} ${p.name.padEnd(20)} ${authLabel.padEnd(18)} ${statusLabel}${current}`); + } + + // API Key providers + for (const p of apiKeyProviders) { + const status = p.available ? green("✓") : red("✗"); + const current = p.id === currentProvider ? yellow(" (current)") : ""; + const authLabel = dim("[API Key]"); + const statusLabel = p.available ? green("configured") : dim("not configured"); + console.log(` ${status} ${p.name.padEnd(20)} ${authLabel.padEnd(18)} ${statusLabel}${current}`); + } + + console.log(`\n${dim("To switch provider:")}`); + console.log(` ${dim("•")} ${cyan("OAuth:")} Run login command (e.g., ${yellow("claude login")}), then restart`); + console.log(` ${dim("•")} ${cyan("API Key:")} Add to ${yellow("~/.super-multica/credentials.json5")}`); + console.log(` ${dim("•")} ${cyan("Session:")} Use ${yellow("--provider ")} flag when starting chat`); + + // If user hasn't logged into Claude Code, show instructions + const claudeCode = providers.find(p => p.id === "claude-code"); + if (claudeCode && !claudeCode.available) { + console.log(`\n${cyan("💡 Tip:")} To use Claude Code (free with Claude subscription):`); + console.log(` 1. Install Claude Code: ${yellow("npm install -g @anthropic-ai/claude-code")}`); + console.log(` 2. Login: ${yellow("claude login")}`); + console.log(` 3. Restart multica with: ${yellow("multica chat --provider claude-code")}`); + } + + console.log(""); + } + private async handleInput(input: string) { try { console.log("");