Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/kimi-code-model-alias-shorthand.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": patch
---

Allow `/model <alias>` to match managed Kimi Code models by shorthand. For example, `/model k3` now resolves to `kimi-code/k3`.
16 changes: 13 additions & 3 deletions apps/kimi-code/src/tui/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { UpdatePreferenceSelectorComponent } from '../components/dialogs/update-
import { DEFAULT_TUI_CONFIG, saveTuiConfig, type TuiConfig } from '../config';
import type { ThemeName } from '#/tui/theme';
import { currentTheme, isBuiltInTheme, lightColors, loadCustomThemeMerged } from '#/tui/theme';
import { DEFAULT_OAUTH_PROVIDER_NAME } from '#/constant/app';
import { NO_ACTIVE_SESSION_MESSAGE } from '../constant/kimi-tui';
import { formatErrorMessage } from '../utils/event-payload';
import { thinkingEffortToConfig } from '../utils/thinking-config';
Expand Down Expand Up @@ -237,14 +238,23 @@ export async function handleThemeCommand(host: SlashCommandHost, args: string):
}

export async function handleModelCommand(host: SlashCommandHost, args: string): Promise<void> {
const alias = args.trim();
const input = args.trim();
let alias = input;
await refreshModelsForPicker(host);
if (alias.length === 0) {
showModelPicker(host);
return;
}
if (host.state.appState.availableModels[alias] === undefined) {
host.showError(`Unknown model alias: ${alias}`);
const availableModels = host.state.appState.availableModels;
if (availableModels[alias] === undefined && !alias.includes('/')) {
const managedPrefix = DEFAULT_OAUTH_PROVIDER_NAME.slice('managed:'.length);
const managedAlias = `${managedPrefix}/${alias}`;
if (availableModels[managedAlias] !== undefined) {
alias = managedAlias;
}
}
if (availableModels[alias] === undefined) {
host.showError(`Unknown model alias: ${input}`);
return;
}
showModelPicker(host, alias);
Expand Down
36 changes: 36 additions & 0 deletions apps/kimi-code/test/tui/kimi-tui-message-flow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5126,6 +5126,42 @@ command = "vim"
expect(refreshProviderModels).not.toHaveBeenCalled();
});

it('resolves /model shorthand to the managed Kimi Code alias', async () => {
const session = makeSession();
const { driver } = await makeDriver(session, {
getConfig: vi.fn(async () => ({
models: {
k2: {
provider: 'managed:kimi-code',
model: 'kimi-k2',
maxContextSize: 100,
displayName: 'Kimi K2',
capabilities: ['thinking'],
},
'kimi-code/k3': {
provider: 'managed:kimi-code',
model: 'kimi-k3',
maxContextSize: 100,
displayName: 'K3',
capabilities: ['thinking'],
},
},
defaultModel: 'k2',
thinking: { enabled: false },
})),
});

driver.handleUserInput('/model k3');

await vi.waitFor(() => {
const picker = driver.state.editorContainer.children[0];
expect(picker).toBeInstanceOf(TabbedModelSelectorComponent);
const output = stripSgr((picker as TabbedModelSelectorComponent).render(120).join('\n'));
expect(output).toMatch(/❯ K3\s+Kimi Code/);
});
expect(session.setModel).not.toHaveBeenCalled();
});

it('opens /model picker after 2s when OAuth refresh is still pending', async () => {
const { driver } = await makeDriver(makeSession(), {
getConfig: vi.fn(async () => ({
Expand Down