feat: improve onboarding auth prompts
This commit is contained in:
@@ -17,6 +17,9 @@
|
||||
- Onboarding/CLI: group model/auth choice by provider and label Z.AI as GLM 4.7.
|
||||
- Onboarding/Docs: add Moonshot AI (Kimi K2) auth choice + config example.
|
||||
- CLI/Onboarding: prompt to reuse detected API keys for Moonshot/MiniMax/Z.AI/Gemini/Anthropic/OpenCode.
|
||||
- CLI/Onboarding: move MiniMax to the top of the provider list.
|
||||
- CLI/Onboarding: add MiniMax M2.1 Lightning auth choice.
|
||||
- CLI/Onboarding: show key previews when reusing detected API keys.
|
||||
- Auto-reply: add compact `/model` picker (models + available providers) and show provider endpoints in `/model status`.
|
||||
- Control UI: add Config tab model presets (MiniMax M2.1, GLM 4.7, Kimi) for one-click setup.
|
||||
- Plugins: add extension loader (tools/RPC/CLI/services), discovery paths, and config schema + Control UI labels (uiHints).
|
||||
@@ -73,6 +76,7 @@
|
||||
- Auto-reply: allow inline `/status` for allowlisted senders (stripped before the model); unauthorized senders see it as plain text.
|
||||
- Auto-reply: include config-only allowlisted models in `/model` even when the catalog is partial.
|
||||
- Auto-reply: ignore inline `/status` directives unless the message is directive-only.
|
||||
- CLI/Configure: enter the selected section immediately, then return to the section picker.
|
||||
- Auto-reply: align `/think` default display with model reasoning defaults. (#751) — thanks @gabriel-trigo.
|
||||
- Auto-reply: flush block reply buffers on tool boundaries. (#750) — thanks @sebslight.
|
||||
- Auto-reply: allow sender fallback for command authorization when `SenderId` is empty (WhatsApp self-chat). (#755) — thanks @juanpablodlc.
|
||||
|
||||
@@ -262,7 +262,7 @@ export function buildProgram() {
|
||||
.option("--mode <mode>", "Wizard mode: local|remote")
|
||||
.option(
|
||||
"--auth-choice <choice>",
|
||||
"Auth: setup-token|claude-cli|token|openai-codex|openai-api-key|openrouter-api-key|moonshot-api-key|codex-cli|antigravity|gemini-api-key|zai-api-key|apiKey|minimax-api|opencode-zen|skip",
|
||||
"Auth: setup-token|claude-cli|token|openai-codex|openai-api-key|openrouter-api-key|moonshot-api-key|codex-cli|antigravity|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip",
|
||||
)
|
||||
.option(
|
||||
"--token-provider <id>",
|
||||
@@ -339,6 +339,7 @@ export function buildProgram() {
|
||||
| "apiKey"
|
||||
| "minimax-cloud"
|
||||
| "minimax-api"
|
||||
| "minimax-api-lightning"
|
||||
| "minimax"
|
||||
| "opencode-zen"
|
||||
| "skip"
|
||||
|
||||
@@ -79,6 +79,9 @@ describe("buildAuthChoiceOptions", () => {
|
||||
});
|
||||
|
||||
expect(options.some((opt) => opt.value === "minimax-api")).toBe(true);
|
||||
expect(options.some((opt) => opt.value === "minimax-api-lightning")).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it("includes Moonshot auth choice", () => {
|
||||
|
||||
@@ -47,6 +47,12 @@ const AUTH_CHOICE_GROUP_DEFS: {
|
||||
hint: "Claude CLI + API key",
|
||||
choices: ["claude-cli", "setup-token", "token", "apiKey"],
|
||||
},
|
||||
{
|
||||
value: "minimax",
|
||||
label: "MiniMax",
|
||||
hint: "M2.1 (recommended)",
|
||||
choices: ["minimax-api", "minimax-api-lightning"],
|
||||
},
|
||||
{
|
||||
value: "google",
|
||||
label: "Google",
|
||||
@@ -77,12 +83,6 @@ const AUTH_CHOICE_GROUP_DEFS: {
|
||||
hint: "API key",
|
||||
choices: ["opencode-zen"],
|
||||
},
|
||||
{
|
||||
value: "minimax",
|
||||
label: "MiniMax",
|
||||
hint: "M2.1 (recommended)",
|
||||
choices: ["minimax-api"],
|
||||
},
|
||||
];
|
||||
|
||||
function formatOAuthHint(
|
||||
@@ -181,6 +181,11 @@ export function buildAuthChoiceOptions(params: {
|
||||
hint: "Claude, GPT, Gemini via opencode.ai/zen",
|
||||
});
|
||||
options.push({ value: "minimax-api", label: "MiniMax M2.1" });
|
||||
options.push({
|
||||
value: "minimax-api-lightning",
|
||||
label: "MiniMax M2.1 Lightning",
|
||||
hint: "Faster, lower cost",
|
||||
});
|
||||
if (params.includeSkip) {
|
||||
options.push({ value: "skip", label: "Skip for now" });
|
||||
}
|
||||
|
||||
@@ -68,6 +68,27 @@ import {
|
||||
} from "./openai-codex-model-default.js";
|
||||
import { OPENCODE_ZEN_DEFAULT_MODEL } from "./opencode-zen-model-default.js";
|
||||
|
||||
const DEFAULT_KEY_PREVIEW = { head: 4, tail: 4 };
|
||||
|
||||
function formatApiKeyPreview(
|
||||
raw: string,
|
||||
opts: { head?: number; tail?: number } = {},
|
||||
): string {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) return "…";
|
||||
const head = opts.head ?? DEFAULT_KEY_PREVIEW.head;
|
||||
const tail = opts.tail ?? DEFAULT_KEY_PREVIEW.tail;
|
||||
if (trimmed.length <= head + tail) {
|
||||
const shortHead = Math.min(2, trimmed.length);
|
||||
const shortTail = Math.min(2, trimmed.length - shortHead);
|
||||
if (shortTail <= 0) {
|
||||
return `${trimmed.slice(0, shortHead)}…`;
|
||||
}
|
||||
return `${trimmed.slice(0, shortHead)}…${trimmed.slice(-shortTail)}`;
|
||||
}
|
||||
return `${trimmed.slice(0, head)}…${trimmed.slice(-tail)}`;
|
||||
}
|
||||
|
||||
export async function warnIfModelConfigLooksOff(
|
||||
config: ClawdbotConfig,
|
||||
prompter: WizardPrompter,
|
||||
@@ -339,7 +360,7 @@ export async function applyAuthChoice(params: {
|
||||
const envKey = resolveEnvApiKey("openai");
|
||||
if (envKey) {
|
||||
const useExisting = await params.prompter.confirm({
|
||||
message: `Use existing OPENAI_API_KEY (${envKey.source})?`,
|
||||
message: `Use existing OPENAI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
@@ -406,7 +427,7 @@ export async function applyAuthChoice(params: {
|
||||
const envKey = resolveEnvApiKey("openrouter");
|
||||
if (envKey) {
|
||||
const useExisting = await params.prompter.confirm({
|
||||
message: `Use existing OPENROUTER_API_KEY (${envKey.source})?`,
|
||||
message: `Use existing OPENROUTER_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
@@ -448,7 +469,7 @@ export async function applyAuthChoice(params: {
|
||||
const envKey = resolveEnvApiKey("moonshot");
|
||||
if (envKey) {
|
||||
const useExisting = await params.prompter.confirm({
|
||||
message: `Use existing MOONSHOT_API_KEY (${envKey.source})?`,
|
||||
message: `Use existing MOONSHOT_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
@@ -691,7 +712,7 @@ export async function applyAuthChoice(params: {
|
||||
const envKey = resolveEnvApiKey("google");
|
||||
if (envKey) {
|
||||
const useExisting = await params.prompter.confirm({
|
||||
message: `Use existing GEMINI_API_KEY (${envKey.source})?`,
|
||||
message: `Use existing GEMINI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
@@ -729,7 +750,7 @@ export async function applyAuthChoice(params: {
|
||||
const envKey = resolveEnvApiKey("zai");
|
||||
if (envKey) {
|
||||
const useExisting = await params.prompter.confirm({
|
||||
message: `Use existing ZAI_API_KEY (${envKey.source})?`,
|
||||
message: `Use existing ZAI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
@@ -782,7 +803,7 @@ export async function applyAuthChoice(params: {
|
||||
const envKey = process.env.ANTHROPIC_API_KEY?.trim();
|
||||
if (envKey) {
|
||||
const useExisting = await params.prompter.confirm({
|
||||
message: "Use existing ANTHROPIC_API_KEY (env)?",
|
||||
message: `Use existing ANTHROPIC_API_KEY (env, ${formatApiKeyPreview(envKey)})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
@@ -804,14 +825,18 @@ export async function applyAuthChoice(params: {
|
||||
});
|
||||
} else if (
|
||||
params.authChoice === "minimax-cloud" ||
|
||||
params.authChoice === "minimax-api"
|
||||
params.authChoice === "minimax-api" ||
|
||||
params.authChoice === "minimax-api-lightning"
|
||||
) {
|
||||
const modelId = "MiniMax-M2.1";
|
||||
const modelId =
|
||||
params.authChoice === "minimax-api-lightning"
|
||||
? "MiniMax-M2.1-lightning"
|
||||
: "MiniMax-M2.1";
|
||||
let hasCredential = false;
|
||||
const envKey = resolveEnvApiKey("minimax");
|
||||
if (envKey) {
|
||||
const useExisting = await params.prompter.confirm({
|
||||
message: `Use existing MINIMAX_API_KEY (${envKey.source})?`,
|
||||
message: `Use existing MINIMAX_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
@@ -860,7 +885,7 @@ export async function applyAuthChoice(params: {
|
||||
const envKey = resolveEnvApiKey("opencode");
|
||||
if (envKey) {
|
||||
const useExisting = await params.prompter.confirm({
|
||||
message: `Use existing OPENCODE_API_KEY (${envKey.source})?`,
|
||||
message: `Use existing OPENCODE_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
|
||||
initialValue: true,
|
||||
});
|
||||
if (useExisting) {
|
||||
@@ -923,6 +948,7 @@ export function resolvePreferredProviderForAuthChoice(
|
||||
return "google-antigravity";
|
||||
case "minimax-cloud":
|
||||
case "minimax-api":
|
||||
case "minimax-api-lightning":
|
||||
return "minimax";
|
||||
case "minimax":
|
||||
return "lmstudio";
|
||||
|
||||
@@ -305,7 +305,11 @@ export async function runNonInteractiveOnboarding(
|
||||
mode: "api_key",
|
||||
});
|
||||
nextConfig = applyMoonshotConfig(nextConfig);
|
||||
} else if (authChoice === "minimax-cloud" || authChoice === "minimax-api") {
|
||||
} else if (
|
||||
authChoice === "minimax-cloud" ||
|
||||
authChoice === "minimax-api" ||
|
||||
authChoice === "minimax-api-lightning"
|
||||
) {
|
||||
const resolved = await resolveNonInteractiveApiKey({
|
||||
provider: "minimax",
|
||||
cfg: baseConfig,
|
||||
@@ -323,7 +327,10 @@ export async function runNonInteractiveOnboarding(
|
||||
provider: "minimax",
|
||||
mode: "api_key",
|
||||
});
|
||||
const modelId = "MiniMax-M2.1";
|
||||
const modelId =
|
||||
authChoice === "minimax-api-lightning"
|
||||
? "MiniMax-M2.1-lightning"
|
||||
: "MiniMax-M2.1";
|
||||
nextConfig = applyMinimaxApiConfig(nextConfig, modelId);
|
||||
} else if (authChoice === "claude-cli") {
|
||||
const store = ensureAuthProfileStore(undefined, {
|
||||
|
||||
@@ -20,6 +20,7 @@ export type AuthChoice =
|
||||
| "minimax-cloud"
|
||||
| "minimax"
|
||||
| "minimax-api"
|
||||
| "minimax-api-lightning"
|
||||
| "opencode-zen"
|
||||
| "skip";
|
||||
export type GatewayAuthChoice = "off" | "token" | "password";
|
||||
|
||||
Reference in New Issue
Block a user