mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-12 16:23:18 -10:00
* fix plan mode and add test * Address review: wire plan mode, harden test script, restore friendly errors - Wire /plan into agent behavior: add PLAN_MODE_SYSTEM_PROMPT and a planMode option on runAgent; App passes isPlanMode through so the agent actually plans without editing instead of only changing UI color. - Harden test script to "bun test ./tests --timeout 15000" for deterministic discovery and a bounded runtime so it always exits. - Restore friendly provider-setup/auth/network error mapping via toFriendlyError(); debug mode still records the full error object. - Add tests/agent-loop.test.ts covering prompt selection and the tool-call -> result -> final-answer loop with a mock provider. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> --------- Co-authored-by: Kevin Codex <[email protected]> Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
import { describe, it, expect, beforeEach } from 'bun:test';
|
|
import { planTool, getCurrentPlan, clearPlan } from '../src/tools/plan';
|
|
|
|
const samplePlan = [
|
|
{ id: '1', content: 'First step', status: 'completed' as const },
|
|
{ id: '2', content: 'Second step', status: 'in_progress' as const, notes: 'halfway' },
|
|
{ id: '3', content: 'Third step', status: 'pending' as const },
|
|
];
|
|
|
|
describe('planTool', () => {
|
|
beforeEach(() => clearPlan());
|
|
|
|
it('stores the plan and reflects it via getCurrentPlan', async () => {
|
|
await planTool.execute({ plan: samplePlan });
|
|
expect(getCurrentPlan()).toEqual(samplePlan);
|
|
});
|
|
|
|
it('formats the plan with status markers and notes', async () => {
|
|
const output = await planTool.execute({ plan: samplePlan });
|
|
expect(output).toContain('1. ✓ [completed] First step');
|
|
expect(output).toContain('2. ◉ [in_progress] Second step');
|
|
expect(output).toContain('Notes: halfway');
|
|
expect(output).toContain('3. ○ [pending] Third step');
|
|
});
|
|
|
|
it('clearPlan empties the stored plan', async () => {
|
|
await planTool.execute({ plan: samplePlan });
|
|
clearPlan();
|
|
expect(getCurrentPlan()).toEqual([]);
|
|
});
|
|
|
|
it('getCurrentPlan returns a copy, not the internal reference', async () => {
|
|
await planTool.execute({ plan: samplePlan });
|
|
const snapshot = getCurrentPlan();
|
|
snapshot.push({ id: 'x', content: 'mutation', status: 'pending' });
|
|
expect(getCurrentPlan()).toHaveLength(samplePlan.length);
|
|
});
|
|
|
|
it('rejects invalid status values', async () => {
|
|
await expect(
|
|
planTool.execute({ plan: [{ id: '1', content: 'bad', status: 'nope' }] })
|
|
).rejects.toThrow();
|
|
});
|
|
});
|