mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-07 07:59:42 +02:00
feat: Approvals Inbox, one cross-session queue for prompts waiting on a human
Permission dialogs, AskUserQuestion questions and idle prompts from every session now land in a server-side inbox (web/approval-inbox.ts, one item per session, claude-mode only) and are answerable in place: a header bell + drawer on desktop, inline answer strips on the phone overview's NEEDS YOU rows, and working push Approve/Deny buttons (previously dead ends, now answered straight from sw.js with no tab open). Pending alerts survive reloads because the frontend seeds from GET /api/approvals on init. Answering sends the digit / Esc / prompt text through the existing tmux input path; option digits are accepted only when they match options parsed from the captured pane frame, and the answer path re-captures the pane first so a dialog that already left the screen refuses with 409 instead of typing into the composer. New elicitation_complete / elicitation_response hook matchers resolve question items the moment they are answered in the terminal; refreshStaleCodemanHooks heals existing cases. Verified end-to-end against a live claude session: a real AskUserQuestion dialog parsed into 5 option buttons and was answered from the drawer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,7 +28,7 @@ describe('generateHooksConfig', () => {
|
||||
it('should have Notification hooks array', () => {
|
||||
const config = generateHooksConfig();
|
||||
expect(config.hooks.Notification).toBeInstanceOf(Array);
|
||||
expect(config.hooks.Notification).toHaveLength(3);
|
||||
expect(config.hooks.Notification).toHaveLength(5);
|
||||
});
|
||||
|
||||
it('should have Stop hooks array', () => {
|
||||
@@ -194,7 +194,7 @@ describe('writeHooksConfig', () => {
|
||||
const settingsPath = join(testDir, '.claude', 'settings.local.json');
|
||||
const parsed = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
||||
expect(parsed.hooks).toBeDefined();
|
||||
expect(parsed.hooks.Notification).toHaveLength(3);
|
||||
expect(parsed.hooks.Notification).toHaveLength(5);
|
||||
expect(parsed.hooks.Stop).toHaveLength(1);
|
||||
});
|
||||
|
||||
@@ -1085,7 +1085,7 @@ describe('Hook Config Generation - Extended', () => {
|
||||
it('should generate valid JSON structure', () => {
|
||||
const config = generateHooksConfig();
|
||||
expect(config.hooks).toBeDefined();
|
||||
expect(config.hooks.Notification).toHaveLength(3);
|
||||
expect(config.hooks.Notification).toHaveLength(5);
|
||||
expect(config.hooks.Stop).toHaveLength(1);
|
||||
});
|
||||
|
||||
@@ -1096,6 +1096,9 @@ describe('Hook Config Generation - Extended', () => {
|
||||
expect(matchers).toContain('idle_prompt');
|
||||
expect(matchers).toContain('permission_prompt');
|
||||
expect(matchers).toContain('elicitation_dialog');
|
||||
// Approvals Inbox resolution signals (dialog answered in the terminal).
|
||||
expect(matchers).toContain('elicitation_complete');
|
||||
expect(matchers).toContain('elicitation_response');
|
||||
});
|
||||
|
||||
it('should use environment variable placeholders', () => {
|
||||
|
||||
Reference in New Issue
Block a user