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
6 changes: 6 additions & 0 deletions .changeset/tui-honors-agent-file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@moonshot-ai/kimi-code": patch
"@moonshot-ai/kimi-code-sdk": minor
---

Bind the agent selected by `--agent` or `--agent-file` to the startup session of the interactive TUI, which previously started on the default agent without reporting that the flag was dropped. An `--agent-file` is registered for the whole launch while the flag itself still binds only the startup session, so a file named after a built-in agent keeps replacing that built-in for sessions created later in the same launch. A requested name absent from the workspace agent catalog is now rejected before the session is created instead of after. The SDK gains a matching `agentFiles` harness option.
5 changes: 5 additions & 0 deletions apps/kimi-code/src/cli/run-shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ export async function runShell(
homeDir: telemetryBootstrap.homeDir,
identity: createKimiCodeHostIdentity(version),
skillDirs: opts.skillsDirs,
// `--agent-file` registers the file for this launch; the harness is built
// before any session exists, and the v2 engine reads explicit agent files
// from its own bootstrap arguments, so the registration has to happen here.
// Selecting the profile it defines stays per-session (`agentProfile`).
agentFiles: opts.agentFiles,
telemetry: telemetryClient,
onOAuthRefresh: (outcome) => {
if (outcome.success) {
Expand Down
43 changes: 42 additions & 1 deletion apps/kimi-code/test/cli/run-shell.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { execSync } from 'node:child_process';
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';

import type { createKimiDeviceId as createKimiDeviceIdFn } from '@moonshot-ai/kimi-code-oauth';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
Expand Down Expand Up @@ -156,11 +159,16 @@ vi.mock('node:child_process', () => ({
}));

describe('runShell', () => {
const tempDirs: string[] = [];

beforeEach(() => {
vi.stubEnv('KIMI_CODE_LEGACY_FLAG', '1');
});

afterEach(() => {
afterEach(async () => {
for (const dir of tempDirs.splice(0)) {
await rm(dir, { recursive: true, force: true });
}
vi.clearAllMocks();
vi.unstubAllEnvs();
mocks.harnessGetConfig.mockResolvedValue({
Expand Down Expand Up @@ -398,6 +406,39 @@ describe('runShell', () => {
);
});

// `--agent-file` registers the file for the whole launch, and the v2 engine
// reads explicit agent files from the process bootstrap the harness sets up —
// so the flag has to reach the harness, not only the startup session. Runs on
// the default (v2) route, which is the one that reads the option.
it('forwards agentFiles from CLI options to the v2 harness', async () => {
stubTuiStartup();
const agentDir = await mkdtemp(join(tmpdir(), 'kimi-code-agent-'));
tempDirs.push(agentDir);
const agentFile = join(agentDir, 'reviewer.md');
await writeFile(
agentFile,
'---\nname: reviewer\ndescription: Reviews code.\n---\n\nReview the requested change.\n',
'utf-8',
);

await withEnv(
{ KIMI_CODE_LEGACY_FLAG: undefined, KIMI_CODE_EXPERIMENTAL_FLAG: undefined },
async () => {
await runShell({ ...minimalCliOptions, agentFiles: [agentFile] }, '1.2.3-test');
},
);

expect(mocks.kimiHarnessV2Constructor).toHaveBeenCalledWith(
expect.objectContaining({ agentFiles: [agentFile] }),
);
// The startup session still selects the profile that file defines.
expect(mocks.kimiTuiConstructor).toHaveBeenCalledWith(
expect.anything(),
expect.anything(),
expect.objectContaining({ agentProfile: 'reviewer' }),
);
});

it('tracks first launch when device id creation reports first launch', async () => {
mocks.loadTuiConfig.mockResolvedValue({
theme: 'dark',
Expand Down
2 changes: 1 addition & 1 deletion docs/en/reference/kimi-command.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ kimi --agent reviewer
kimi -p --agent reviewer "Review the changes on this branch"
```

`--agent-file` registers a single agent file at the highest priority for this launch only and selects it; the flag cannot be repeated, and `--agent` and `--agent-file` are mutually exclusive. Both flags only apply when starting a new session — neither can be combined with `--session`/`--continue`, because the agent is bound at session creation and resuming restores the bound agent automatically. The selection is fixed at the session's first bind and cannot be switched later; in the TUI the flags bind only the startup session, and a session created later in the same process (for example via `/new`) starts with the default agent. See [Agents and Sub-Agents](../customization/agents.md#custom-agents) for the agent file format and discovery directories.
`--agent-file` registers a single agent file at the highest priority for this launch only and selects it; the flag cannot be repeated, and `--agent` and `--agent-file` are mutually exclusive. Both flags only apply when starting a new session — neither can be combined with `--session`/`--continue`, because the agent is bound at session creation and resuming restores the bound agent automatically. The selection is fixed at the session's first bind and cannot be switched later; in the TUI the flags bind only the startup session, and a session created later in the same process (for example via `/new`) starts with the default agent. On the default `agent-core-v2` engine, the file `--agent-file` points at stays in the agent catalog for the rest of the launch: sessions created later start on the default agent, but the file's agent remains available for delegation as a sub-agent, subject to the active agent's sub-agent allowlist — and if the file is named after a built-in agent, it keeps replacing that built-in for those sessions too. The legacy engine selected with `KIMI_CODE_LEGACY_FLAG=1` registers the file for the startup session only. See [Agents and Sub-Agents](../customization/agents.md#custom-agents) for the agent file format and discovery directories.

## Non-Interactive Execution

Expand Down
2 changes: 1 addition & 1 deletion docs/zh/reference/kimi-command.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ kimi --agent reviewer
kimi -p --agent reviewer "审查这个分支上的改动"
```

`--agent-file` 以最高优先级注册单个 Agent 文件(仅本次启动)并选中它;该 flag 不可重复传入,`--agent` 与 `--agent-file` 互斥。两个 flag 都仅在新建会话时有效——都不能与 `--session`/`--continue` 组合,因为 Agent 在会话创建时绑定,恢复会话时会自动还原已绑定的 Agent。选择在会话首次绑定后即固定,之后不可切换;在 TUI 中,这些 flag 只绑定启动时的会话,之后在同一进程内新建的会话(例如通过 `/new`)使用默认 Agent。Agent 文件格式与发现目录详见 [Agent 与子 Agent](../customization/agents.md#自定义-agent)。
`--agent-file` 以最高优先级注册单个 Agent 文件(仅本次启动)并选中它;该 flag 不可重复传入,`--agent` 与 `--agent-file` 互斥。两个 flag 都仅在新建会话时有效——都不能与 `--session`/`--continue` 组合,因为 Agent 在会话创建时绑定,恢复会话时会自动还原已绑定的 Agent。选择在会话首次绑定后即固定,之后不可切换;在 TUI 中,这些 flag 只绑定启动时的会话,之后在同一进程内新建的会话(例如通过 `/new`)使用默认 Agent。在默认的 `agent-core-v2` 引擎下,`--agent-file` 指向的文件在本次启动的剩余时间内一直留在 Agent 清单中:之后新建的会话虽然以默认 Agent 启动,该文件定义的 Agent 仍可作为子 Agent 派发,但要受当前 Agent 的子 Agent 允许列表限制;如果该文件与某个内置 Agent 同名,它对这些会话也会继续替换那个内置 Agent。设置 `KIMI_CODE_LEGACY_FLAG=1` 选择旧版引擎时,该文件只为启动时的会话注册。Agent 文件格式与发现目录详见 [Agent 与子 Agent](../customization/agents.md#自定义-agent)。

## 非交互执行

Expand Down
Loading