mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-18 10:01:29 -07:00
99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
|
|
/**
|
||
|
|
* @license
|
||
|
|
* Copyright 2025 Google LLC
|
||
|
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { useInactivityTimer } from './useInactivityTimer.js';
|
||
|
|
import { useTurnActivityMonitor } from './useTurnActivityMonitor.js';
|
||
|
|
import {
|
||
|
|
SHELL_FOCUS_HINT_DELAY_MS,
|
||
|
|
SHELL_ACTION_REQUIRED_TITLE_DELAY_MS,
|
||
|
|
SHELL_SILENT_WORKING_TITLE_DELAY_MS,
|
||
|
|
} from '../constants.js';
|
||
|
|
import type { StreamingState } from '../types.js';
|
||
|
|
import { type TrackedToolCall } from './useReactToolScheduler.js';
|
||
|
|
|
||
|
|
interface ShellInactivityStatusProps {
|
||
|
|
activePtyId: number | string | null | undefined;
|
||
|
|
lastOutputTime: number;
|
||
|
|
streamingState: StreamingState;
|
||
|
|
pendingToolCalls: TrackedToolCall[];
|
||
|
|
embeddedShellFocused: boolean;
|
||
|
|
isInteractiveShellEnabled: boolean;
|
||
|
|
}
|
||
|
|
|
||
|
|
export type InactivityStatus = 'none' | 'action_required' | 'silent_working';
|
||
|
|
|
||
|
|
export interface ShellInactivityStatus {
|
||
|
|
shouldShowFocusHint: boolean;
|
||
|
|
inactivityStatus: InactivityStatus;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Consolidated hook to manage all shell-related inactivity states.
|
||
|
|
* Centralizes the timing heuristics and redirection suppression logic.
|
||
|
|
*/
|
||
|
|
export const useShellInactivityStatus = ({
|
||
|
|
activePtyId,
|
||
|
|
lastOutputTime,
|
||
|
|
streamingState,
|
||
|
|
pendingToolCalls,
|
||
|
|
embeddedShellFocused,
|
||
|
|
isInteractiveShellEnabled,
|
||
|
|
}: ShellInactivityStatusProps): ShellInactivityStatus => {
|
||
|
|
const { operationStartTime, isRedirectionActive } = useTurnActivityMonitor(
|
||
|
|
streamingState,
|
||
|
|
activePtyId,
|
||
|
|
pendingToolCalls,
|
||
|
|
);
|
||
|
|
|
||
|
|
const isAwaitingFocus =
|
||
|
|
!!activePtyId && !embeddedShellFocused && isInteractiveShellEnabled;
|
||
|
|
|
||
|
|
// Derive whether output was produced by comparing the last output time to when the operation started.
|
||
|
|
const hasProducedOutput = lastOutputTime > operationStartTime;
|
||
|
|
|
||
|
|
// 1. Focus Hint (The "press tab to focus" message in the loading indicator)
|
||
|
|
// Logic: 5s if output has been produced, 20s if silent. Suppressed if redirected.
|
||
|
|
const shouldShowFocusHint = useInactivityTimer(
|
||
|
|
isAwaitingFocus && !isRedirectionActive,
|
||
|
|
lastOutputTime,
|
||
|
|
hasProducedOutput
|
||
|
|
? SHELL_FOCUS_HINT_DELAY_MS
|
||
|
|
: SHELL_FOCUS_HINT_DELAY_MS * 4,
|
||
|
|
);
|
||
|
|
|
||
|
|
// 2. Action Required Status (The ✋ icon in the terminal window title)
|
||
|
|
// Logic: Only if output has been produced (likely a prompt).
|
||
|
|
// Triggered after 30s of silence, but SUPPRESSED if redirection is active.
|
||
|
|
const shouldShowActionRequiredTitle = useInactivityTimer(
|
||
|
|
isAwaitingFocus && !isRedirectionActive && hasProducedOutput,
|
||
|
|
lastOutputTime,
|
||
|
|
SHELL_ACTION_REQUIRED_TITLE_DELAY_MS,
|
||
|
|
);
|
||
|
|
|
||
|
|
// 3. Silent Working Status (The ⏲ icon in the terminal window title)
|
||
|
|
// Logic: If redirected OR if no output has been produced yet (e.g. sleep 600).
|
||
|
|
// Triggered after 2 mins for redirected, or 60s for non-redirected silent commands.
|
||
|
|
const shouldShowSilentWorkingTitle = useInactivityTimer(
|
||
|
|
isAwaitingFocus && (isRedirectionActive || !hasProducedOutput),
|
||
|
|
lastOutputTime,
|
||
|
|
isRedirectionActive
|
||
|
|
? SHELL_SILENT_WORKING_TITLE_DELAY_MS
|
||
|
|
: SHELL_ACTION_REQUIRED_TITLE_DELAY_MS * 2,
|
||
|
|
);
|
||
|
|
|
||
|
|
let inactivityStatus: InactivityStatus = 'none';
|
||
|
|
if (shouldShowActionRequiredTitle) {
|
||
|
|
inactivityStatus = 'action_required';
|
||
|
|
} else if (shouldShowSilentWorkingTitle) {
|
||
|
|
inactivityStatus = 'silent_working';
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
shouldShowFocusHint,
|
||
|
|
inactivityStatus,
|
||
|
|
};
|
||
|
|
};
|