diff --git a/.changeset/refine-api-key-login-copy.md b/.changeset/refine-api-key-login-copy.md new file mode 100644 index 000000000..9db76464a --- /dev/null +++ b/.changeset/refine-api-key-login-copy.md @@ -0,0 +1,6 @@ +--- +"@moonshot-ai/kimi-code-oauth": patch +"@moonshot-ai/kimi-code": patch +--- + +Clarify Kimi Platform API key login labels and prompt details. diff --git a/apps/kimi-code/README.md b/apps/kimi-code/README.md index 9c0bd4e27..79cd3ad91 100644 --- a/apps/kimi-code/README.md +++ b/apps/kimi-code/README.md @@ -55,7 +55,7 @@ cd your-project kimi ``` -On first launch, run `/login` inside Kimi Code CLI and choose either Kimi Code OAuth or a Moonshot AI Open Platform API key. After login, try a first task: +On first launch, run `/login` inside Kimi Code CLI and choose either Kimi Code OAuth or a Kimi Platform API key. After login, try a first task: ``` Take a look at this project and explain the main directories. diff --git a/apps/kimi-code/src/tui/commands/auth.ts b/apps/kimi-code/src/tui/commands/auth.ts index e9e8304cc..bb2622f07 100644 --- a/apps/kimi-code/src/tui/commands/auth.ts +++ b/apps/kimi-code/src/tui/commands/auth.ts @@ -116,7 +116,13 @@ async function handleOpenPlatformLogin( host: SlashCommandHost, platform: OpenPlatformDefinition, ): Promise { - const apiKey = await promptApiKey(host, platform.name); + const consoleHost = platform.consoleUrl?.replace(/^https?:\/\//, '') ?? ''; + const platformName = consoleHost.length > 0 ? `Kimi Platform (${consoleHost})` : 'Kimi Platform'; + const subtitleLines = [ + `${'base_url'.padEnd(12)}${platform.baseUrl}`, + `${'saved to'.padEnd(12)}~/.kimi-code/config.toml`, + ]; + const apiKey = await promptApiKey(host, platformName, subtitleLines); if (apiKey === undefined) return; const controller = new AbortController(); diff --git a/apps/kimi-code/src/tui/commands/prompts.ts b/apps/kimi-code/src/tui/commands/prompts.ts index dbc86a25a..a6b7a8c80 100644 --- a/apps/kimi-code/src/tui/commands/prompts.ts +++ b/apps/kimi-code/src/tui/commands/prompts.ts @@ -69,10 +69,15 @@ export function promptFeedbackInput(host: SlashCommandHost): Promise { +export function promptApiKey( + host: SlashCommandHost, + platformName: string, + subtitleLines: readonly string[] = ['Your key will be saved to ~/.kimi-code/config.toml'], +): Promise { return new Promise((resolve) => { const dialog = new ApiKeyInputDialogComponent( platformName, + subtitleLines, (result: ApiKeyInputResult) => { host.restoreEditor(); resolve(result.kind === 'ok' ? result.value : undefined); diff --git a/apps/kimi-code/src/tui/components/dialogs/api-key-input-dialog.ts b/apps/kimi-code/src/tui/components/dialogs/api-key-input-dialog.ts index 8296cb0a2..2a06a4278 100644 --- a/apps/kimi-code/src/tui/components/dialogs/api-key-input-dialog.ts +++ b/apps/kimi-code/src/tui/components/dialogs/api-key-input-dialog.ts @@ -49,12 +49,13 @@ export class ApiKeyInputDialogComponent extends Container implements Focusable { private readonly onDone: (result: ApiKeyInputResult) => void; private readonly colors: ColorPalette; private readonly title: string; - private readonly subtitle: string; + private readonly subtitleLines: readonly string[]; private done = false; private emptyHinted = false; constructor( platformName: string, + subtitleLines: readonly string[], onDone: (result: ApiKeyInputResult) => void, colors: ColorPalette, ) { @@ -62,7 +63,7 @@ export class ApiKeyInputDialogComponent extends Container implements Focusable { this.onDone = onDone; this.colors = colors; this.title = `Enter API key for ${platformName}`; - this.subtitle = 'Your key will be saved to ~/.kimi-code/config.toml'; + this.subtitleLines = subtitleLines; this.input.onSubmit = (value) => { this.submit(value); }; @@ -98,17 +99,26 @@ export class ApiKeyInputDialogComponent extends Container implements Focusable { const border = (s: string): string => chalk.hex(this.colors.primary)(s); const titleStyled = chalk.bold.hex(this.colors.textStrong)(this.title); - const subtitleText = this.emptyHinted ? 'API key cannot be empty.' : this.subtitle; - const subtitleStyled = chalk.hex(this.colors.textDim)(subtitleText); + const subtitleSource = this.emptyHinted ? ['API key cannot be empty.'] : this.subtitleLines; + const subtitleLines = subtitleSource.map((line) => + truncateToWidth(chalk.hex(this.colors.textDim)(line), innerWidth, '…'), + ); const footerStyled = chalk.hex(this.colors.textDim)(FOOTER); const titleLine = truncateToWidth(titleStyled, innerWidth, '…'); - const subtitleLine = truncateToWidth(subtitleStyled, innerWidth, '…'); const footerLine = truncateToWidth(footerStyled, innerWidth, '…'); const rawInputLine = this.input.render(innerWidth)[0] ?? '> '; const inputLine = this.input.getValue() === '' ? rawInputLine : maskInputLine(rawInputLine); - const contentLines: string[] = [titleLine, '', subtitleLine, '', inputLine, '', footerLine]; + const contentLines: string[] = [ + titleLine, + '', + ...subtitleLines, + '', + inputLine, + '', + footerLine, + ]; const lines: string[] = [ '', diff --git a/apps/kimi-code/src/tui/components/dialogs/platform-selector.ts b/apps/kimi-code/src/tui/components/dialogs/platform-selector.ts index c889b126d..c1d8a1467 100644 --- a/apps/kimi-code/src/tui/components/dialogs/platform-selector.ts +++ b/apps/kimi-code/src/tui/components/dialogs/platform-selector.ts @@ -5,7 +5,7 @@ import { ChoicePickerComponent, type ChoiceOption } from './choice-picker'; import type { ColorPalette } from '#/tui/theme/colors'; const PLATFORM_OPTIONS: readonly ChoiceOption[] = [ - { value: 'kimi-code', label: 'Kimi Code' }, + { value: 'kimi-code', label: 'Kimi Code (OAuth)' }, ...OPEN_PLATFORMS.map((platform) => ({ value: platform.id, label: platform.name })), ]; diff --git a/docs/en/configuration/providers.md b/docs/en/configuration/providers.md index 23247fa73..0da2ebf0a 100644 --- a/docs/en/configuration/providers.md +++ b/docs/en/configuration/providers.md @@ -8,7 +8,7 @@ The `type` field of each entry in the `providers` table determines which impleme | Type | Protocol | Typical platforms | | --- | --- | --- | -| `kimi` | OpenAI-compatible (chat completions style) | Kimi Code, Moonshot AI Open Platform | +| `kimi` | OpenAI-compatible (chat completions style) | Kimi Code, Kimi Platform API key | | `anthropic` | Anthropic Messages | Claude API | | `openai` | OpenAI Chat Completions | OpenAI and compatible services | | `openai_responses` | OpenAI Responses API | OpenAI's newer Responses endpoint | diff --git a/docs/en/guides/getting-started.md b/docs/en/guides/getting-started.md index 120b74e6c..f4cb8302e 100644 --- a/docs/en/guides/getting-started.md +++ b/docs/en/guides/getting-started.md @@ -101,8 +101,8 @@ On the first launch, Kimi Code CLI has no credentials yet, and you need to confi `/login` opens a platform selector supporting: -- **Kimi Code** — OAuth device code flow; open the URL on any device, sign in, and enter the code to authorize -- **Moonshot AI Open Platform** — log in directly with an API key +- **Kimi Code (OAuth)** — device code flow; open the URL on any device, sign in, and enter the code to authorize +- **Kimi Platform API key** — enter an API key from `platform.kimi.com` or `platform.kimi.ai` To sign out, enter `/logout` to clear the current credentials. diff --git a/docs/en/reference/slash-commands.md b/docs/en/reference/slash-commands.md index 26968e257..8317a4907 100644 --- a/docs/en/reference/slash-commands.md +++ b/docs/en/reference/slash-commands.md @@ -12,7 +12,7 @@ Some commands are only available in the idle state. Running them while the sessi | Command | Alias | Description | Always available | | --- | --- | --- | --- | -| `/login` | — | Pick an account or platform and sign in: Kimi Code uses the OAuth device code flow, while the Moonshot AI Open Platform signs in with an API key. | No | +| `/login` | — | Pick an account or platform and sign in: Kimi Code uses the OAuth device code flow, while Kimi Platform signs in with an API key. | No | | `/logout` | — | Clear the credentials of the currently selected account (Kimi Code OAuth credentials, or the corresponding open platform provider config). | No | | `/connect [--refresh] [--url=]` | — | Configure a provider and model from a model catalog. The default catalog is bundled with the CLI; pass `--refresh` to fetch the latest catalog from models.dev, or `--url` to read it from a custom URL. See [Providers and models — `/connect` and the model catalog](../configuration/providers.md#connect-and-the-model-catalog). | No | | `/model` | — | Switch the LLM model used by the current session. | No | diff --git a/docs/zh/configuration/providers.md b/docs/zh/configuration/providers.md index eaa037a48..22b2acf99 100644 --- a/docs/zh/configuration/providers.md +++ b/docs/zh/configuration/providers.md @@ -8,7 +8,7 @@ Kimi Code CLI 通过统一的供应商抽象对接多家 LLM 平台。每个供 | 类型 | 协议 | 典型平台 | | --- | --- | --- | -| `kimi` | OpenAI 兼容(chat completions 风格) | Kimi Code、Moonshot AI 开放平台 | +| `kimi` | OpenAI 兼容(chat completions 风格) | Kimi Code、Kimi Platform API 密钥 | | `anthropic` | Anthropic Messages | Claude API | | `openai` | OpenAI Chat Completions | OpenAI 及其兼容服务 | | `openai_responses` | OpenAI Responses API | OpenAI 较新的 Responses 接口 | diff --git a/docs/zh/guides/getting-started.md b/docs/zh/guides/getting-started.md index 36d519e22..142d942da 100644 --- a/docs/zh/guides/getting-started.md +++ b/docs/zh/guides/getting-started.md @@ -101,8 +101,8 @@ kimi -C `/login` 会弹出平台选择器,支持: -- **Kimi Code** — OAuth 验证码流程,在任意设备打开链接、登录并输入验证码即可授权 -- **Moonshot AI Open Platform** — 直接输入 API key 登录 +- **Kimi Code(OAuth)** — 验证码流程,在任意设备打开链接、登录并输入验证码即可授权 +- **Kimi Platform API 密钥** — 输入来自 `platform.kimi.com` 或 `platform.kimi.ai` 的 API 密钥 需要退出登录时,输入 `/logout` 即可清除当前凭证。 diff --git a/docs/zh/reference/slash-commands.md b/docs/zh/reference/slash-commands.md index 887128805..7cd8990b0 100644 --- a/docs/zh/reference/slash-commands.md +++ b/docs/zh/reference/slash-commands.md @@ -12,7 +12,7 @@ | 命令 | 别名 | 说明 | 随时可用 | | --- | --- | --- | --- | -| `/login` | — | 选择账号或平台并登录:Kimi Code 走 OAuth device code 流程,Moonshot AI 开放平台通过 API 密钥登录。 | 否 | +| `/login` | — | 选择账号或平台并登录:Kimi Code 走 OAuth 验证码流程,Kimi Platform 通过 API 密钥登录。 | 否 | | `/logout` | — | 清除当前所选账号的凭据(Kimi Code OAuth 凭据,或对应开放平台的供应商配置)。 | 否 | | `/connect [--refresh] [--url=]` | — | 从模型目录中选择并配置供应商与模型。CLI 已内置默认目录;传入 `--refresh` 可从 models.dev 拉取最新目录,传入 `--url` 可指向自定义目录地址。详见 [平台与模型 — `/connect` 与模型目录](../configuration/providers.md#connect-与模型目录)。 | 否 | | `/model` | — | 切换当前会话使用的 LLM 模型。 | 否 | diff --git a/packages/oauth/src/open-platform.ts b/packages/oauth/src/open-platform.ts index da15c893c..d32f931d9 100644 --- a/packages/oauth/src/open-platform.ts +++ b/packages/oauth/src/open-platform.ts @@ -11,20 +11,23 @@ export interface OpenPlatformDefinition { readonly id: string; readonly name: string; readonly baseUrl: string; + readonly consoleUrl?: string; readonly allowedPrefixes?: readonly string[] | undefined; } export const OPEN_PLATFORMS: readonly OpenPlatformDefinition[] = [ { id: 'moonshot-cn', - name: 'Moonshot AI Open Platform (moonshot.cn)', + name: 'Kimi Platform (API key · platform.kimi.com)', baseUrl: 'https://api.moonshot.cn/v1', + consoleUrl: 'https://platform.kimi.com', allowedPrefixes: ['kimi-k'], }, { id: 'moonshot-ai', - name: 'Moonshot AI Open Platform (moonshot.ai)', + name: 'Kimi Platform (API key · platform.kimi.ai)', baseUrl: 'https://api.moonshot.ai/v1', + consoleUrl: 'https://platform.kimi.ai', allowedPrefixes: ['kimi-k'], }, ]; diff --git a/packages/oauth/test/open-platform.test.ts b/packages/oauth/test/open-platform.test.ts index d179fc8f7..b127fd6b7 100644 --- a/packages/oauth/test/open-platform.test.ts +++ b/packages/oauth/test/open-platform.test.ts @@ -47,13 +47,15 @@ function makeModelsResponse(): Response { describe('OPEN_PLATFORMS', () => { it('contains moonshot.cn and moonshot.ai', () => { expect(getOpenPlatformById('moonshot-cn')).toMatchObject({ - name: 'Moonshot AI Open Platform (moonshot.cn)', + name: 'Kimi Platform (API key · platform.kimi.com)', baseUrl: 'https://api.moonshot.cn/v1', + consoleUrl: 'https://platform.kimi.com', allowedPrefixes: ['kimi-k'], }); expect(getOpenPlatformById('moonshot-ai')).toMatchObject({ - name: 'Moonshot AI Open Platform (moonshot.ai)', + name: 'Kimi Platform (API key · platform.kimi.ai)', baseUrl: 'https://api.moonshot.ai/v1', + consoleUrl: 'https://platform.kimi.ai', allowedPrefixes: ['kimi-k'], }); expect(getOpenPlatformById('unknown')).toBeUndefined();