Просмотр исходного кода

CLI - fix race conditions on auto-approval commands options

CLI - fix race conditions on auto-approval commands options
Catriel Müller 4 месяцев назад
Родитель
Сommit
e54a3bf535
2 измененных файлов с 26 добавлено и 9 удалено
  1. 8 4
      cli/src/state/atoms/approval.ts
  2. 18 5
      cli/src/state/hooks/useApprovalMonitor.ts

+ 8 - 4
cli/src/state/atoms/approval.ts

@@ -217,14 +217,18 @@ export const setPendingApprovalAtom = atom(null, (get, set, message: ExtensionCh
 		return
 	}
 
-	// Create a new object reference to force Jotai to re-evaluate dependent atoms
-	// This is important for streaming messages that update from partial to complete
+	// Always create a new object reference to force Jotai to re-evaluate dependent atoms
+	// This is critical for streaming messages that update from partial to complete
+	// and ensures approvalOptionsAtom recalculates when message content changes
 	const messageToSet = message ? { ...message } : null
 	set(pendingApprovalAtom, messageToSet)
 
-	// Only reset selection if this is a new message (different timestamp)
+	// Get the current pending message to check if this is a new message or an update
 	const current = get(pendingApprovalAtom)
-	if (!current || current.ts !== message?.ts) {
+	const isNewMessage = !current || current.ts !== message?.ts
+
+	// Reset selection if this is a new message (different timestamp)
+	if (isNewMessage) {
 		set(selectedIndexAtom, 0)
 	}
 })

+ 18 - 5
cli/src/state/hooks/useApprovalMonitor.ts

@@ -137,8 +137,12 @@ export function useApprovalMonitor(): void {
 		},
 	}
 
-	// Track the last message we set as pending (timestamp + partial state)
-	const lastPendingRef = useRef<{ ts: number; partial: boolean } | null>(null)
+	// Track the last message we set as pending (full message snapshot for comparison)
+	const lastPendingRef = useRef<{
+		ts: number
+		partial: boolean
+		text: string
+	} | null>(null)
 
 	// Main effect: handle approval orchestration
 	useEffect(() => {
@@ -166,16 +170,25 @@ export function useApprovalMonitor(): void {
 
 		// Set as pending if:
 		// 1. This is a new message (different timestamp), OR
-		// 2. The message transitioned from partial to complete (need to update options)
+		// 2. The message transitioned from partial to complete (need to update options), OR
+		// 3. The message text changed (for command messages, this means the command is now available)
 		const isNewMessage = !lastPendingRef.current || lastPendingRef.current.ts !== lastAskMessage.ts
 		const transitionedToComplete =
 			lastPendingRef.current &&
 			lastPendingRef.current.ts === lastAskMessage.ts &&
 			lastPendingRef.current.partial &&
 			!lastAskMessage.partial
+		const textChanged =
+			lastPendingRef.current &&
+			lastPendingRef.current.ts === lastAskMessage.ts &&
+			lastPendingRef.current.text !== (lastAskMessage.text || "")
 
-		if (isNewMessage || transitionedToComplete) {
-			lastPendingRef.current = { ts: lastAskMessage.ts, partial: lastAskMessage.partial || false }
+		if (isNewMessage || transitionedToComplete || textChanged) {
+			lastPendingRef.current = {
+				ts: lastAskMessage.ts,
+				partial: lastAskMessage.partial || false,
+				text: lastAskMessage.text || "",
+			}
 			setPendingApproval(lastAskMessage)
 		}