mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 14:25:51 +00:00
Merge pull request #156 from amDosion/feat/ultraplan-enablement
feat: enable /ultraplan and harden GrowthBook fallback chain
This commit is contained in:
@@ -27,7 +27,9 @@ function hasSummarySinceLastUserTurn(messages: readonly Message[]): boolean {
|
||||
* blurred for 5 minutes. Fires only when (a) 5min since blur, (b) no turn in
|
||||
* progress, and (c) no existing away_summary since the last user message.
|
||||
*
|
||||
* Focus state 'unknown' (terminal doesn't support DECSET 1004) is a no-op.
|
||||
* For terminals that don't support DECSET 1004 focus events (CMD, PowerShell),
|
||||
* falls back to idle-based detection: starts an idle timer after each turn
|
||||
* ends, resets it when the user starts a new turn.
|
||||
*/
|
||||
export function useAwaySummary(
|
||||
messages: readonly Message[],
|
||||
@@ -91,7 +93,10 @@ export function useAwaySummary(
|
||||
|
||||
function onFocusChange(): void {
|
||||
const state = getTerminalFocusState()
|
||||
if (state === 'blurred') {
|
||||
if (state === 'blurred' || state === 'unknown') {
|
||||
// For 'unknown' terminals (CMD, PowerShell), treat mount as
|
||||
// potentially away — start idle timer. The isLoading effect
|
||||
// below resets the timer on each turn transition.
|
||||
clearTimer()
|
||||
timerRef.current = setTimeout(onBlurTimerFire, BLUR_DELAY_MS)
|
||||
} else if (state === 'focused') {
|
||||
@@ -99,7 +104,6 @@ export function useAwaySummary(
|
||||
abortInFlight()
|
||||
pendingRef.current = false
|
||||
}
|
||||
// 'unknown' → no-op
|
||||
}
|
||||
|
||||
const unsubscribe = subscribeTerminalFocus(onFocusChange)
|
||||
@@ -115,11 +119,45 @@ export function useAwaySummary(
|
||||
}
|
||||
}, [gbEnabled, setMessages])
|
||||
|
||||
// Timer fired mid-turn → fire when turn ends (if still blurred)
|
||||
// Timer fired mid-turn → fire when turn ends (if still away)
|
||||
useEffect(() => {
|
||||
if (isLoading) return
|
||||
if (!pendingRef.current) return
|
||||
if (getTerminalFocusState() !== 'blurred') return
|
||||
const state = getTerminalFocusState()
|
||||
if (state !== 'blurred' && state !== 'unknown') return
|
||||
void generateRef.current?.()
|
||||
}, [isLoading])
|
||||
|
||||
// For 'unknown' terminals: use isLoading transitions as presence signal.
|
||||
// User starts a turn → they're present, cancel idle timer.
|
||||
// Turn ends → restart idle timer.
|
||||
useEffect(() => {
|
||||
if (getTerminalFocusState() !== 'unknown') return
|
||||
if (!feature('AWAY_SUMMARY')) return
|
||||
if (!gbEnabled) return
|
||||
|
||||
if (isLoading) {
|
||||
// User is actively using — cancel idle timer
|
||||
if (timerRef.current !== null) {
|
||||
clearTimeout(timerRef.current)
|
||||
timerRef.current = null
|
||||
}
|
||||
abortRef.current?.abort()
|
||||
abortRef.current = null
|
||||
pendingRef.current = false
|
||||
} else {
|
||||
// Turn ended — restart idle timer
|
||||
if (timerRef.current !== null) {
|
||||
clearTimeout(timerRef.current)
|
||||
}
|
||||
timerRef.current = setTimeout(() => {
|
||||
timerRef.current = null
|
||||
if (isLoadingRef.current) {
|
||||
pendingRef.current = true
|
||||
return
|
||||
}
|
||||
void generateRef.current?.()
|
||||
}, BLUR_DELAY_MS)
|
||||
}
|
||||
}, [isLoading, gbEnabled])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user