mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-14 13:22:37 +00:00
fix(server): mark Claude terminals as needing input when Claude goes idle (#6022)
Claude Code reports the kind of notification in `notification_type`, but the hook parser only read `matcher` and `reason`, which Claude never sends in Notification input. Every idle_prompt notification resolved to nothing, so a Claude terminal waiting for the user never showed as needing input. Closes #5845 Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -51,7 +51,7 @@ Claude hook mapping:
|
||||
|
||||
- `UserPromptSubmit` → `running`
|
||||
- `Stop`, `StopFailure`, `SessionEnd` → `idle`
|
||||
- `Notification` with `reason` or `matcher` equal to `idle_prompt` → `needs-input`
|
||||
- `Notification` with `notification_type` equal to `idle_prompt` → `needs-input`
|
||||
|
||||
Claude does not run `Stop` when the user interrupts a turn. A standalone Ctrl-C or Escape input
|
||||
while terminal activity is working clears the activity without finished attention. The same
|
||||
|
||||
@@ -17,6 +17,15 @@ function inputFrom(value: string) {
|
||||
};
|
||||
}
|
||||
|
||||
function claudeNotification(notificationType: string) {
|
||||
return JSON.stringify({
|
||||
session_id: "session-1",
|
||||
hook_event_name: "Notification",
|
||||
message: "Claude is waiting for your input",
|
||||
notification_type: notificationType,
|
||||
});
|
||||
}
|
||||
|
||||
function ttyInput() {
|
||||
return {
|
||||
isTTY: true,
|
||||
@@ -123,7 +132,7 @@ describe("runHooksCommand", () => {
|
||||
const send = await runHook(
|
||||
claudeProvider.id,
|
||||
claudeProvider.events[4].event,
|
||||
inputFrom('{"reason":"idle_prompt"}'),
|
||||
inputFrom(claudeNotification("idle_prompt")),
|
||||
);
|
||||
|
||||
expectPostedState(send, "needs-input");
|
||||
@@ -131,11 +140,11 @@ describe("runHooksCommand", () => {
|
||||
|
||||
it.each(["permission_prompt", "elicitation_prompt", "elicitation_response", "auth_success"])(
|
||||
"ignores Claude %s notifications",
|
||||
async (reason) => {
|
||||
async (notificationType) => {
|
||||
const send = await runHook(
|
||||
claudeProvider.id,
|
||||
claudeProvider.events[4].event,
|
||||
inputFrom(JSON.stringify({ reason })),
|
||||
inputFrom(claudeNotification(notificationType)),
|
||||
);
|
||||
|
||||
expect(send.calls).toEqual([]);
|
||||
|
||||
@@ -40,8 +40,8 @@ function isIdlePrompt(raw: string | null): boolean {
|
||||
try {
|
||||
const notification = JSON.parse(raw) as unknown;
|
||||
if (!notification || typeof notification !== "object") return false;
|
||||
const payload = notification as { matcher?: unknown; reason?: unknown };
|
||||
return payload.matcher === "idle_prompt" || payload.reason === "idle_prompt";
|
||||
const payload = notification as { notification_type?: unknown };
|
||||
return payload.notification_type === "idle_prompt";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user