fix: clarify Kimi Platform login copy (#274)

This commit is contained in:
qer 2026-06-01 18:43:01 +08:00 committed by GitHub
parent e2e17289fc
commit a1dfbfeb16
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 54 additions and 22 deletions

View file

@ -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.

View file

@ -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.

View file

@ -116,7 +116,13 @@ async function handleOpenPlatformLogin(
host: SlashCommandHost,
platform: OpenPlatformDefinition,
): Promise<void> {
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();

View file

@ -69,10 +69,15 @@ export function promptFeedbackInput(host: SlashCommandHost): Promise<string | un
});
}
export function promptApiKey(host: SlashCommandHost, platformName: string): Promise<string | undefined> {
export function promptApiKey(
host: SlashCommandHost,
platformName: string,
subtitleLines: readonly string[] = ['Your key will be saved to ~/.kimi-code/config.toml'],
): Promise<string | undefined> {
return new Promise((resolve) => {
const dialog = new ApiKeyInputDialogComponent(
platformName,
subtitleLines,
(result: ApiKeyInputResult) => {
host.restoreEditor();
resolve(result.kind === 'ok' ? result.value : undefined);

View file

@ -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[] = [
'',

View file

@ -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 })),
];

View file

@ -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 |

View file

@ -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.

View file

@ -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=<catalog-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 |

View file

@ -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 接口 |

View file

@ -101,8 +101,8 @@ kimi -C
`/login` 会弹出平台选择器,支持:
- **Kimi Code** — OAuth 验证码流程,在任意设备打开链接、登录并输入验证码即可授权
- **Moonshot AI Open Platform** — 直接输入 API key 登录
- **Kimi CodeOAuth** — 验证码流程,在任意设备打开链接、登录并输入验证码即可授权
- **Kimi Platform API 密钥** — 输入来自 `platform.kimi.com``platform.kimi.ai` 的 API 密钥
需要退出登录时,输入 `/logout` 即可清除当前凭证。

View file

@ -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=<catalog-url>]` | — | 从模型目录中选择并配置供应商与模型。CLI 已内置默认目录;传入 `--refresh` 可从 models.dev 拉取最新目录,传入 `--url` 可指向自定义目录地址。详见 [平台与模型 — `/connect` 与模型目录](../configuration/providers.md#connect-与模型目录)。 | 否 |
| `/model` | — | 切换当前会话使用的 LLM 模型。 | 否 |

View file

@ -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'],
},
];

View file

@ -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();