feat(v0.3): H3 — remote approve/reject (no typing)
- types/protocol: ClientMessage approve/reject; ServerMessage status.pending
- server: POST /hook/permission HELD until the client decides; approve/reject
ws messages resolve it with {hookSpecificOutput.decision.behavior allow|deny};
5-min timeout + release-on-disconnect fall back to Claude's own prompt
- manager.handleHookEvent threads pending flag
- setup-hooks: PermissionRequest uses the held curl (writes decision to stdout);
status events stay fire-and-forget
- FE: terminal-session approve()/reject() + pending state; tabs approval banner
(Approve/Reject) for the active tab's held request
- Tests: protocol approve/reject; integration ⑧ held→approve→allow. 207 green.
- Browser-verified: banner 'Claude wants to use Bash' → Approve → resolves allow.
This commit is contained in:
@@ -130,14 +130,22 @@ export function createSessionManager(cfg: Config): SessionManager {
|
||||
* H2: a Claude Code hook reported activity for `sessionId`. Record it and push
|
||||
* a `status` frame to the attached ws (no-op if the session is gone/detached).
|
||||
*/
|
||||
function handleHookEvent(sessionId: string, status: ClaudeStatus, detail?: string): void {
|
||||
function handleHookEvent(
|
||||
sessionId: string,
|
||||
status: ClaudeStatus,
|
||||
detail?: string,
|
||||
pending?: boolean,
|
||||
): void {
|
||||
const session = sessions.get(sessionId);
|
||||
if (session === undefined) return;
|
||||
session.claudeStatus = status;
|
||||
sendIfOpen(
|
||||
session.attachedWs,
|
||||
detail !== undefined ? { type: 'status', status, detail } : { type: 'status', status },
|
||||
);
|
||||
const msg: { type: 'status'; status: ClaudeStatus; detail?: string; pending?: boolean } = {
|
||||
type: 'status',
|
||||
status,
|
||||
};
|
||||
if (detail !== undefined) msg.detail = detail;
|
||||
if (pending) msg.pending = true;
|
||||
sendIfOpen(session.attachedWs, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user