Add Logger for command history (#435)

This commit is contained in:
Seth Troisi
2025-05-21 07:36:22 +00:00
committed by GitHub
parent bda472f147
commit cd13c5881b
9 changed files with 1777 additions and 26 deletions

View File

@@ -20,7 +20,6 @@ import { ShellModeIndicator } from './components/ShellModeIndicator.js';
import { InputPrompt } from './components/InputPrompt.js';
import { Footer } from './components/Footer.js';
import { ThemeDialog } from './components/ThemeDialog.js';
import { type Config } from '@gemini-code/server';
import { Colors } from './colors.js';
import { Help } from './components/Help.js';
import { loadHierarchicalGeminiMemory } from '../config/config.js';
@@ -29,9 +28,10 @@ import { Tips } from './components/Tips.js';
import { ConsoleOutput } from './components/ConsolePatcher.js';
import { HistoryItemDisplay } from './components/HistoryItemDisplay.js';
import { useHistory } from './hooks/useHistoryManager.js';
import process from 'node:process'; // For performMemoryRefresh
import { MessageType } from './types.js'; // For performMemoryRefresh
import { getErrorMessage } from '@gemini-code/server'; // For performMemoryRefresh
import { useLogger } from './hooks/useLogger.js';
import process from 'node:process';
import { MessageType } from './types.js';
import { getErrorMessage, type Config } from '@gemini-code/server';
interface AppProps {
config: Config;
@@ -157,18 +157,29 @@ export const App = ({
[submitQuery],
);
const userMessages = useMemo(
() =>
history
.filter(
(item): item is HistoryItem & { type: 'user'; text: string } =>
item.type === 'user' &&
typeof item.text === 'string' &&
item.text.trim() !== '',
)
.map((item) => item.text),
[history],
);
const logger = useLogger();
const [userMessages, setUserMessages] = useState<string[]>([]);
useEffect(() => {
const fetchUserMessages = async () => {
const pastMessages = (await logger?.getPreviousUserMessages()) || [];
if (pastMessages.length > 0) {
setUserMessages(pastMessages.reverse());
} else {
setUserMessages(
history
.filter(
(item): item is HistoryItem & { type: 'user'; text: string } =>
item.type === 'user' &&
typeof item.text === 'string' &&
item.text.trim() !== '',
)
.map((item) => item.text),
);
}
};
fetchUserMessages();
}, [history, logger]);
const isInputActive = streamingState === StreamingState.Idle && !initError;

View File

@@ -18,13 +18,14 @@ import {
getErrorMessage,
isNodeError,
Config,
MessageSenderType,
ServerToolCallConfirmationDetails,
ToolCallConfirmationDetails,
ToolCallResponseInfo,
ServerToolCallConfirmationDetails,
ToolConfirmationOutcome,
ToolResultDisplay,
ToolEditConfirmationDetails,
ToolExecuteConfirmationDetails,
ToolResultDisplay,
partListUnionToString,
} from '@gemini-code/server';
import { type Chat, type PartListUnion, type Part } from '@google/genai';
@@ -42,6 +43,7 @@ import { handleAtCommand } from './atCommandProcessor.js';
import { findLastSafeSplitPoint } from '../utils/markdownUtilities.js';
import { useStateAndRef } from './useStateAndRef.js';
import { UseHistoryManagerReturn } from './useHistoryManager.js';
import { useLogger } from './useLogger.js';
enum StreamProcessingStatus {
Completed,
@@ -71,6 +73,7 @@ export const useGeminiStream = (
const [isResponding, setIsResponding] = useState<boolean>(false);
const [pendingHistoryItemRef, setPendingHistoryItem] =
useStateAndRef<HistoryItemWithoutId | null>(null);
const logger = useLogger();
const onExec = useCallback(async (done: Promise<void>) => {
setIsResponding(true);
@@ -117,6 +120,7 @@ export const useGeminiStream = (
if (typeof query === 'string') {
const trimmedQuery = query.trim();
onDebugMessage(`User query: '${trimmedQuery}'`);
await logger?.logMessage(MessageSenderType.USER, trimmedQuery);
// Handle UI-only commands first
if (handleSlashCommand(trimmedQuery)) {
@@ -616,6 +620,7 @@ export const useGeminiStream = (
onDebugMessage,
refreshStatic,
setInitError,
logger,
],
);

View File

@@ -0,0 +1,32 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { useState, useEffect } from 'react';
import { Logger } from '@gemini-code/server';
/**
* Hook to manage the logger instance.
*/
export const useLogger = () => {
const [logger, setLogger] = useState<Logger | null>(null);
useEffect(() => {
const newLogger = new Logger();
/**
* Start async initialization, no need to await. Using await slows down the
* time from launch to see the gemini-cli prompt and it's better to not save
* messages than for the cli to hanging waiting for the logger to loading.
*/
newLogger
.initialize()
.then(() => {
setLogger(newLogger);
})
.catch(() => {});
}, []);
return logger;
};