Noah Vogt 1 день назад
Родитель
Сommit
2c7e40274b
1 измененных файлов с 69 добавлено и 3 удалено
  1. 69 3
      local-bin/copilot-notify

+ 69 - 3
local-bin/copilot-notify

@@ -28,10 +28,43 @@ notify_task_finished() {
 start_interactive_monitor() {
     local win_addr="$1"
     local started_epoch="$2"
+    local monitor_pid="$BASHPID"
     local log_file
     local line
     local busy=0
     local ask_user_pending=0
+    local permission_pending=0
+    local permission_notified=0
+    local permission_timer_pid=""
+    local tool_calls_count=0
+
+    clear_permission_state() {
+        permission_pending=0
+        permission_notified=0
+        if [ -n "${permission_timer_pid:-}" ]; then
+            kill "$permission_timer_pid" 2>/dev/null || true
+            permission_timer_pid=""
+        fi
+    }
+
+    start_permission_timer() {
+        if [ -n "${permission_timer_pid:-}" ]; then
+            kill "$permission_timer_pid" 2>/dev/null || true
+            permission_timer_pid=""
+        fi
+        (
+            sleep 1
+            kill -USR1 "$monitor_pid" 2>/dev/null || true
+        ) &
+        permission_timer_pid=$!
+    }
+
+    trap '
+        if [ "$permission_pending" -eq 1 ] && [ "$permission_notified" -eq 0 ]; then
+            notify_action_required "$win_addr"
+            permission_notified=1
+        fi
+    ' USR1
 
     # Wait for the process log created by this copilot invocation.
     for _ in $(seq 1 60); do
@@ -44,14 +77,20 @@ start_interactive_monitor() {
 
     [ -n "${log_file:-}" ] || return 0
 
-    tail -n0 -F "$log_file" 2>/dev/null | while IFS= read -r line; do
+    while IFS= read -r line; do
         if [ "$ask_user_pending" -gt 0 ]; then
             ask_user_pending=$((ask_user_pending - 1))
         fi
 
         case "$line" in
+        *"Tool calls count: "*)
+            tool_calls_count="${line##*Tool calls count: }"
+            tool_calls_count="${tool_calls_count%%[^0-9]*}"
+            [ -n "$tool_calls_count" ] || tool_calls_count=0
+            ;;
         *"kind: assistant_turn_start"*)
             busy=1
+            clear_permission_state
             ;;
         *'"name": "ask_user"'*)
             # "ask_user" appears in tool schema on every turn; only alert if a
@@ -64,19 +103,46 @@ start_interactive_monitor() {
                 ask_user_pending=0
             fi
             ;;
+        *"Permission request (kind="*"): routing via PermissionService"*)
+            # PermissionService handles all tool calls; only notify if the
+            # request stays unresolved for a moment (likely a real prompt).
+            permission_pending=1
+            permission_notified=0
+            start_permission_timer
+            ask_user_pending=0
+            ;;
+        *"respondToPermission:"*)
+            clear_permission_state
+            ask_user_pending=0
+            ;;
+        *"kind: tool_call_executed"*)
+            # Single-tool turns that auto-approve complete quickly; suppress
+            # stale timer notifications in that common case.
+            if [ "$permission_pending" -eq 1 ] && [ "$tool_calls_count" -le 1 ]; then
+                clear_permission_state
+            fi
+            ;;
         *"kind: permission_prompt"*)
-            notify_action_required "$win_addr"
+            # Emitted when a decision is submitted; don't notify here.
+            clear_permission_state
             ask_user_pending=0
             ;;
+        *"kind: assistant_turn_end"*)
+            clear_permission_state
+            ;;
         *"kind: session_idle"*)
             if [ "$busy" -eq 1 ]; then
                 notify_task_finished "$win_addr"
                 busy=0
             fi
+            clear_permission_state
             ask_user_pending=0
             ;;
         esac
-    done
+    done < <(tail -n0 -F "$log_file" 2>/dev/null)
+
+    clear_permission_state
+    trap - USR1
 }
 
 is_prompt_run=0