(
input: {
readonly active?: boolean | undefined;
readonly plan?: string | null | undefined;
readonly path?: string | undefined;
readonly planFilePath?: string | null | undefined;
readonly emit?: ((event: unknown) => void) | undefined;
} = {},
)
| 14 | const signal = new AbortController().signal; |
| 15 | |
| 16 | function makeAgent( |
| 17 | input: { |
| 18 | readonly active?: boolean | undefined; |
| 19 | readonly plan?: string | null | undefined; |
| 20 | readonly path?: string | undefined; |
| 21 | readonly planFilePath?: string | null | undefined; |
| 22 | readonly emit?: ((event: unknown) => void) | undefined; |
| 23 | } = {}, |
| 24 | ): { agent: Agent; requestApproval: ReturnType<typeof vi.fn>; emit: ReturnType<typeof vi.fn> } { |
| 25 | let active = input.active ?? true; |
| 26 | const requestApproval = vi.fn(async () => ({ decision: 'approved' })); |
| 27 | const emit = vi.fn((event: unknown) => { |
| 28 | input.emit?.(event); |
| 29 | if ((event as { type?: string }).type === 'plan_mode.exit') active = false; |
| 30 | }); |
| 31 | const agent = { |
| 32 | planMode: { |
| 33 | get isActive() { |
| 34 | return active; |
| 35 | }, |
| 36 | get planFilePath() { |
| 37 | return input.planFilePath ?? null; |
| 38 | }, |
| 39 | data: vi.fn(async () => { |
| 40 | if (input.plan === null) return null; |
| 41 | return { |
| 42 | content: input.plan ?? 'Step 1: read files\nStep 2: fix bug', |
| 43 | path: input.path ?? '/tmp/kimi-plan.md', |
| 44 | }; |
| 45 | }), |
| 46 | exit: () => { |
| 47 | emit({ type: 'plan_mode.exit' }); |
| 48 | }, |
| 49 | }, |
| 50 | rpc: { requestApproval }, |
| 51 | telemetry: { track: vi.fn() }, |
| 52 | emit, |
| 53 | } as unknown as Agent; |
| 54 | return { agent, requestApproval, emit }; |
| 55 | } |
| 56 | |
| 57 | describe('ExitPlanModeTool', () => { |
| 58 | it('has name, description, and parameters from the current schema', () => { |
no test coverage detected