mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-03 05:59:43 +02:00
chore: version packages
Red tab alerts track the dialog, not the keyboard: typing no longer clears them, and a dialog answered in the terminal resolves itself on the next listing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,9 @@ function makeApp(): App {
|
||||
app._persistReliableNow = vi.fn();
|
||||
app._updateConnectionIndicator = vi.fn();
|
||||
app.clearPendingHooks = vi.fn();
|
||||
// _ackDelivery spends a pending IDLE alert through markIdleAlertSeen, which
|
||||
// reads this map; without it the real prototype method throws on every ACK.
|
||||
app.pendingHooks = new Map();
|
||||
app.activeSessionId = 'session-1';
|
||||
app.isOnline = true;
|
||||
app._connectionStatus = 'connected';
|
||||
|
||||
@@ -283,6 +283,48 @@ describe('approval routes', () => {
|
||||
expect(await listApprovals(harness)).toHaveLength(0);
|
||||
});
|
||||
|
||||
describe('staleness sweep on GET /api/approvals', () => {
|
||||
it('resolves an item whose dialog left the pane, and tells the other clients', async () => {
|
||||
const resolved: Array<Record<string, unknown>> = [];
|
||||
await postHook(harness, 'permission_prompt', { tool_name: 'Bash' });
|
||||
expect((await listApprovals(harness))[0].options).toHaveLength(3);
|
||||
|
||||
// Answered in the terminal: Claude Code fires no hook for that, so only
|
||||
// the pane knows. The dialog is gone from the frame the next capture sees.
|
||||
approvalInbox.onResolved = (info) => resolved.push({ ...info });
|
||||
session.terminalBuffer = 'claude> back at the composer';
|
||||
|
||||
expect(await listApprovals(harness)).toHaveLength(0);
|
||||
expect(resolved).toEqual([expect.objectContaining({ resolution: 'resolved_in_terminal' })]);
|
||||
});
|
||||
|
||||
it('keeps an item whose dialog is still on screen', async () => {
|
||||
await postHook(harness, 'permission_prompt', { tool_name: 'Bash' });
|
||||
// Pane unchanged (PERMISSION_DIALOG): the human has not answered yet.
|
||||
expect(await listApprovals(harness)).toHaveLength(1);
|
||||
expect(await listApprovals(harness)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('never drops an item that could not be read in the first place', async () => {
|
||||
// No parseable dialog at capture time, so a later "it does not parse" says
|
||||
// nothing new. Conservative by design: an unreadable pane keeps the alert.
|
||||
session.terminalBuffer = 'some output with no dialog in it';
|
||||
await postHook(harness, 'permission_prompt', { tool_name: 'Bash' });
|
||||
const [item] = await listApprovals(harness);
|
||||
expect(item.options).toBeUndefined();
|
||||
session.terminalBuffer = 'still nothing that parses';
|
||||
expect(await listApprovals(harness)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('leaves idle prompts alone (they are not dialogs)', async () => {
|
||||
session.terminalBuffer = 'claude> waiting at the composer';
|
||||
await postHook(harness, 'idle_prompt', {});
|
||||
session.terminalBuffer = 'claude> still waiting, different frame';
|
||||
const [item] = await listApprovals(harness);
|
||||
expect(item.kind).toBe('idle');
|
||||
});
|
||||
});
|
||||
|
||||
it('viewing a session acknowledges its idle prompt (item stays pending) and broadcasts it', async () => {
|
||||
session.terminalBuffer = 'claude> waiting at the composer';
|
||||
await postHook(harness, 'idle_prompt', {});
|
||||
|
||||
Reference in New Issue
Block a user