mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 07:29:42 +02:00
Merge pull request #473 from irisitymichaelgrundberg/feat/session-watching-badge
feat(approvals): let a session watching its own background work keep quiet (#468) # Conflicts: # src/config/cli-registry/stock.ts
This commit is contained in:
@@ -176,6 +176,12 @@ export function registerHookEventRoutes(
|
||||
// identity beyond the shared per-instance secret, so a prompt claimed for a
|
||||
// session that can never show one must not create an answerable item).
|
||||
let approvalId: string | undefined;
|
||||
// Set when the item opened ALREADY acknowledged, which today means the session is
|
||||
// watching work it started itself. It rides the broadcast so a live page declines to
|
||||
// arm the alert (a reloading page learns the same thing from `acknowledgedAt` when it
|
||||
// seeds from /api/approvals), and it suppresses the push: an alert nobody can answer
|
||||
// is worth even less on a phone than in a tab.
|
||||
let acknowledgedReason: string | undefined;
|
||||
const approvalKind = APPROVAL_KIND_BY_EVENT[event];
|
||||
if (session && hooksAvailableForMode(session.mode, sessionHookOptions(session))) {
|
||||
if (approvalKind) {
|
||||
@@ -194,6 +200,10 @@ export function registerHookEventRoutes(
|
||||
toolSummary: typeof toolSummary === 'string' ? toolSummary : undefined,
|
||||
message: typeof safeData.message === 'string' ? safeData.message : undefined,
|
||||
cwd: typeof safeData.cwd === 'string' ? safeData.cwd : undefined,
|
||||
// What the pane says is still running in the background. An idle prompt from a
|
||||
// session that is watching its own work opens acknowledged, so it never arms an
|
||||
// alert nobody can answer; notePrompt() carries the whole reasoning.
|
||||
watching: session.watching,
|
||||
// Visible tmux frame first (it IS the dialog); raw byte-buffer tail as
|
||||
// the fallback for direct-PTY sessions and the no-op test mux.
|
||||
capture: () => {
|
||||
@@ -203,6 +213,7 @@ export function registerHookEventRoutes(
|
||||
},
|
||||
});
|
||||
approvalId = item.id;
|
||||
acknowledgedReason = item.acknowledgedReason;
|
||||
} else if (APPROVAL_RESOLVING_EVENTS.has(event)) {
|
||||
approvalInbox.resolveForSession(sessionId, 'resolved_in_terminal');
|
||||
}
|
||||
@@ -213,6 +224,7 @@ export function registerHookEventRoutes(
|
||||
timestamp: Date.now(),
|
||||
...safeData,
|
||||
...(approvalId && { approvalId }),
|
||||
...(acknowledgedReason && { acknowledgedReason }),
|
||||
});
|
||||
// Full state ride-along, same shape as the working/idle handlers: the home
|
||||
// screens rank the blocked group on lastActivityAt, and without this a
|
||||
@@ -224,12 +236,17 @@ export function registerHookEventRoutes(
|
||||
// on approvalId, and the answer route refuses keystrokes for dsh dialogs
|
||||
// (third-party TUI, unmeasured contract) — so a dsh push stays a plain
|
||||
// notification instead of offering buttons whose answer would be refused.
|
||||
ctx.sendPushNotifications(`hook:${event}`, {
|
||||
sessionId,
|
||||
sessionName,
|
||||
...safeData,
|
||||
...(approvalId && session?.mode !== 'deepseek' && { approvalId }),
|
||||
});
|
||||
// Nothing to push for a prompt that opened acknowledged: the agent is waiting for its
|
||||
// own monitor or backgrounded shell, and a phone buzzing about it is the same false
|
||||
// alarm as the tab alert, delivered where it is hardest to ignore.
|
||||
if (!acknowledgedReason) {
|
||||
ctx.sendPushNotifications(`hook:${event}`, {
|
||||
sessionId,
|
||||
sessionName,
|
||||
...safeData,
|
||||
...(approvalId && session?.mode !== 'deepseek' && { approvalId }),
|
||||
});
|
||||
}
|
||||
|
||||
// Track in run summary. `prompt_submitted` fires on EVERY prompt of every
|
||||
// Claude pane; only the ones where the conversation actually moved (a /clear
|
||||
|
||||
Reference in New Issue
Block a user