Multi-agent audit + aggressive cleanup across server/web/coder/booterm, delivered behind a DEFER discipline so none of the in-flight files were touched. Removes dead code/deps/columns, dedups server + coder helpers, and splits the oversized modules (tools.ts, opencode-server.ts, sentinel-summaries, turn.ts, TerminalPane.tsx) behind stable contracts. Adds 78 parity/unit tests (server 587, coder 323); fixes two latent bugs (ChatPane queue keys, FileViewerOverlay blank-line parity). Intended tag: v2.7.12-audit-cleanup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
75 lines
3.5 KiB
TypeScript
75 lines
3.5 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest';
|
|
import type { RequestPermissionRequest, CreateElicitationRequest, SessionNotification } from '@agentclientprotocol/sdk';
|
|
import { buildAcpClient, type AcpTurnContext } from '../acp-client.js';
|
|
|
|
/**
|
|
* buildAcpClient (v2.7 audit reshape): the shared ACP `Client` closures. These
|
|
* tests cover the pure routing decisions that don't require the permission-waiter
|
|
* broker machinery — the auto-select/decline fallbacks and the between-turns drop.
|
|
*/
|
|
|
|
describe('buildAcpClient — sessionUpdate', () => {
|
|
it('drops the update when no turn is active (resolveTurn → null)', async () => {
|
|
const client = buildAcpClient('/wt', () => null);
|
|
// Must resolve without throwing and without an onSessionUpdate to call.
|
|
await expect(client.sessionUpdate({ sessionId: 's', update: {} } as unknown as SessionNotification)).resolves.toBeUndefined();
|
|
});
|
|
|
|
it('forwards the update to the active turn', async () => {
|
|
const onSessionUpdate = vi.fn();
|
|
const turn: AcpTurnContext = { taskId: 't', sessionId: 's', modeId: undefined, agent: 'goose', onSessionUpdate };
|
|
const client = buildAcpClient('/wt', () => turn);
|
|
const note = { sessionId: 's', update: {} } as unknown as SessionNotification;
|
|
await client.sessionUpdate(note);
|
|
expect(onSessionUpdate).toHaveBeenCalledWith(note);
|
|
});
|
|
});
|
|
|
|
describe('buildAcpClient — requestPermission fallback (no UI routing)', () => {
|
|
function req(options: Array<{ optionId: string }>): RequestPermissionRequest {
|
|
return { options } as unknown as RequestPermissionRequest;
|
|
}
|
|
|
|
it('auto-selects the first option when there is no turn', async () => {
|
|
const client = buildAcpClient('/wt', () => null);
|
|
const res = await client.requestPermission(req([{ optionId: 'allow' }, { optionId: 'deny' }]));
|
|
expect(res).toEqual({ outcome: { outcome: 'selected', optionId: 'allow' } });
|
|
});
|
|
|
|
it('cancels when there is no turn and no options', async () => {
|
|
const client = buildAcpClient('/wt', () => null);
|
|
const res = await client.requestPermission(req([]));
|
|
expect(res).toEqual({ outcome: { outcome: 'cancelled' } });
|
|
});
|
|
|
|
it('auto-selects when the turn has no taskId (UI routing gated off)', async () => {
|
|
const turn: AcpTurnContext = { taskId: undefined, sessionId: 's', modeId: undefined, agent: 'goose', onSessionUpdate: () => {} };
|
|
const client = buildAcpClient('/wt', () => turn);
|
|
const res = await client.requestPermission(req([{ optionId: 'ok' }]));
|
|
expect(res).toEqual({ outcome: { outcome: 'selected', optionId: 'ok' } });
|
|
});
|
|
});
|
|
|
|
describe('buildAcpClient — elicitation fallback', () => {
|
|
it('declines when there is no turn', async () => {
|
|
const client = buildAcpClient('/wt', () => null);
|
|
const res = await client.unstable_createElicitation!({} as CreateElicitationRequest);
|
|
expect(res).toEqual({ action: 'decline' });
|
|
});
|
|
|
|
it('declines when the turn has no taskId', async () => {
|
|
const turn: AcpTurnContext = { taskId: undefined, sessionId: 's', modeId: undefined, agent: 'goose', onSessionUpdate: () => {} };
|
|
const client = buildAcpClient('/wt', () => turn);
|
|
const res = await client.unstable_createElicitation!({} as CreateElicitationRequest);
|
|
expect(res).toEqual({ action: 'decline' });
|
|
});
|
|
});
|
|
|
|
describe('buildAcpClient — createTerminal', () => {
|
|
it('returns the noop terminal id', async () => {
|
|
const client = buildAcpClient('/wt', () => null);
|
|
const res = await client.createTerminal!({} as never);
|
|
expect(res).toEqual({ terminalId: 'noop' });
|
|
});
|
|
});
|