mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-21 06:35:50 +00:00
* feat(kimi-code): show live background agent activity in the /tasks panel Background agents (run_in_background or Ctrl+B) showed no run details: the /tasks panel only had static metadata, and its output view stays "[no output captured]" until completion because agent tasks capture output only once at the end. Tee child-agent events into a bounded in-memory per-agent activity store segmented by the engine's own turn.step.started events (recent 10 steps, bounded text/output tails). The /tasks preview pane now shows a live activity preview for agent tasks, and Enter/O opens a full-screen detail view rendering step-grouped Markdown text and per-tool results through the main transcript's renderers, with Ctrl+O to expand. Agent tasks without an in-memory record (e.g. lost after resume) fall back to the captured-output view. * feat(kimi-code): retain 20 recent steps in the background agent activity view * fix(kimi-code): cap the streaming-args buffer in the subagent activity store * chore(kimi-code): simplify the background agent activity changeset * fix(kimi-code): drop activity records of foreground-only subagents at terminal state * fix(kimi-code): cap retained tool argument strings in the subagent activity store * test(acp-server): retry temp-dir cleanup to deflake ENOTEMPTY on CI * fix(kimi-code): tighten subagent activity store lifecycle edges - drop delta-only arg buffers when their step is evicted - keep records of spawn-time background agents even when the task sync lags - mark records terminal on background.task.terminated for stopped agents that never emit subagent.failed * fix(kimi-code): release leftover arg buffers when an activity record turns terminal * fix(kimi-code): prune foreground-only activity records when the main turn ends
64 lines
2.1 KiB
TypeScript
64 lines
2.1 KiB
TypeScript
import { mkdtemp, rm } from 'node:fs/promises';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
|
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
|
|
import { createTestClient, type TestClient } from './_helpers/acpClient';
|
|
|
|
describe('acp-server session/close', () => {
|
|
let homeDir: string | undefined;
|
|
let client: TestClient | undefined;
|
|
|
|
afterEach(async () => {
|
|
if (client !== undefined) {
|
|
await client.close();
|
|
client = undefined;
|
|
}
|
|
if (homeDir !== undefined) {
|
|
await rm(homeDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
homeDir = undefined;
|
|
}
|
|
});
|
|
|
|
async function boot(): Promise<TestClient> {
|
|
homeDir = await mkdtemp(join(tmpdir(), 'acp-close-'));
|
|
client = await createTestClient({ homeDir });
|
|
await client.send('initialize', { protocolVersion: 1, clientCapabilities: {} });
|
|
return client;
|
|
}
|
|
|
|
it(
|
|
'advertises the close capability and closes a live session',
|
|
async () => {
|
|
const c = await boot();
|
|
const init = (await c.send('initialize', { protocolVersion: 1, clientCapabilities: {} })) as {
|
|
agentCapabilities?: { sessionCapabilities?: { close?: unknown } };
|
|
};
|
|
expect(init.agentCapabilities?.sessionCapabilities?.close).toBeDefined();
|
|
|
|
const created = (await c.send('session/new', { cwd: homeDir, mcpServers: [] })) as {
|
|
sessionId: string;
|
|
};
|
|
await c.send('session/close', { sessionId: created.sessionId });
|
|
|
|
// After close the server no longer routes the session — a follow-up
|
|
// prompt must surface invalid_params for the now-unknown sessionId.
|
|
await expect(
|
|
c.send('session/prompt', { sessionId: created.sessionId, prompt: [] }),
|
|
).rejects.toThrow();
|
|
await c.close();
|
|
await expect(c.close()).resolves.toBeUndefined();
|
|
},
|
|
30_000,
|
|
);
|
|
|
|
it(
|
|
'closing an unknown sessionId is a best-effort no-op',
|
|
async () => {
|
|
const c = await boot();
|
|
await expect(c.send('session/close', { sessionId: 'does-not-exist' })).resolves.toEqual({});
|
|
},
|
|
30_000,
|
|
);
|
|
});
|