fix: /help remove flickering and respect clear shortcut (ctr+l) (#3611)
Co-authored-by: Jacob Richman <jacob314@gmail.com> Co-authored-by: Allen Hutchison <adh@google.com>
This commit is contained in:
parent
83a04c4755
commit
e506b40c27
|
@ -38,7 +38,6 @@ import { AuthInProgress } from './components/AuthInProgress.js';
|
||||||
import { EditorSettingsDialog } from './components/EditorSettingsDialog.js';
|
import { EditorSettingsDialog } from './components/EditorSettingsDialog.js';
|
||||||
import { ShellConfirmationDialog } from './components/ShellConfirmationDialog.js';
|
import { ShellConfirmationDialog } from './components/ShellConfirmationDialog.js';
|
||||||
import { Colors } from './colors.js';
|
import { Colors } from './colors.js';
|
||||||
import { Help } from './components/Help.js';
|
|
||||||
import { loadHierarchicalGeminiMemory } from '../config/config.js';
|
import { loadHierarchicalGeminiMemory } from '../config/config.js';
|
||||||
import { LoadedSettings } from '../config/settings.js';
|
import { LoadedSettings } from '../config/settings.js';
|
||||||
import { Tips } from './components/Tips.js';
|
import { Tips } from './components/Tips.js';
|
||||||
|
@ -146,7 +145,6 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||||
|
|
||||||
const [geminiMdFileCount, setGeminiMdFileCount] = useState<number>(0);
|
const [geminiMdFileCount, setGeminiMdFileCount] = useState<number>(0);
|
||||||
const [debugMessage, setDebugMessage] = useState<string>('');
|
const [debugMessage, setDebugMessage] = useState<string>('');
|
||||||
const [showHelp, setShowHelp] = useState<boolean>(false);
|
|
||||||
const [themeError, setThemeError] = useState<string | null>(null);
|
const [themeError, setThemeError] = useState<string | null>(null);
|
||||||
const [authError, setAuthError] = useState<string | null>(null);
|
const [authError, setAuthError] = useState<string | null>(null);
|
||||||
const [editorError, setEditorError] = useState<string | null>(null);
|
const [editorError, setEditorError] = useState<string | null>(null);
|
||||||
|
@ -473,7 +471,6 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||||
clearItems,
|
clearItems,
|
||||||
loadHistory,
|
loadHistory,
|
||||||
refreshStatic,
|
refreshStatic,
|
||||||
setShowHelp,
|
|
||||||
setDebugMessage,
|
setDebugMessage,
|
||||||
openThemeDialog,
|
openThemeDialog,
|
||||||
openAuthDialog,
|
openAuthDialog,
|
||||||
|
@ -495,7 +492,6 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||||
config.getGeminiClient(),
|
config.getGeminiClient(),
|
||||||
history,
|
history,
|
||||||
addItem,
|
addItem,
|
||||||
setShowHelp,
|
|
||||||
config,
|
config,
|
||||||
setDebugMessage,
|
setDebugMessage,
|
||||||
handleSlashCommand,
|
handleSlashCommand,
|
||||||
|
@ -802,6 +798,7 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||||
item={h}
|
item={h}
|
||||||
isPending={false}
|
isPending={false}
|
||||||
config={config}
|
config={config}
|
||||||
|
commands={slashCommands}
|
||||||
/>
|
/>
|
||||||
)),
|
)),
|
||||||
]}
|
]}
|
||||||
|
@ -829,8 +826,6 @@ const App = ({ config, settings, startupWarnings = [], version }: AppProps) => {
|
||||||
</Box>
|
</Box>
|
||||||
</OverflowProvider>
|
</OverflowProvider>
|
||||||
|
|
||||||
{showHelp && <Help commands={slashCommands} />}
|
|
||||||
|
|
||||||
<Box flexDirection="column" ref={mainControlsRef}>
|
<Box flexDirection="column" ref={mainControlsRef}>
|
||||||
{/* Move UpdateNotification to render update notification above input area */}
|
{/* Move UpdateNotification to render update notification above input area */}
|
||||||
{updateInfo && <UpdateNotification message={updateInfo.message} />}
|
{updateInfo && <UpdateNotification message={updateInfo.message} />}
|
||||||
|
|
|
@ -4,37 +4,49 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||||
import { helpCommand } from './helpCommand.js';
|
import { helpCommand } from './helpCommand.js';
|
||||||
import { type CommandContext } from './types.js';
|
import { type CommandContext } from './types.js';
|
||||||
|
import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
|
||||||
|
import { MessageType } from '../types.js';
|
||||||
|
import { CommandKind } from './types.js';
|
||||||
|
|
||||||
describe('helpCommand', () => {
|
describe('helpCommand', () => {
|
||||||
let mockContext: CommandContext;
|
let mockContext: CommandContext;
|
||||||
|
const originalEnv = { ...process.env };
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockContext = {} as unknown as CommandContext;
|
mockContext = createMockCommandContext({
|
||||||
|
ui: {
|
||||||
|
addItem: vi.fn(),
|
||||||
|
},
|
||||||
|
} as unknown as CommandContext);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return a dialog action and log a debug message for '/help'", () => {
|
afterEach(() => {
|
||||||
const consoleDebugSpy = vi
|
process.env = { ...originalEnv };
|
||||||
.spyOn(console, 'debug')
|
vi.clearAllMocks();
|
||||||
.mockImplementation(() => {});
|
});
|
||||||
|
|
||||||
|
it('should add a help message to the UI history', async () => {
|
||||||
if (!helpCommand.action) {
|
if (!helpCommand.action) {
|
||||||
throw new Error('Help command has no action');
|
throw new Error('Help command has no action');
|
||||||
}
|
}
|
||||||
const result = helpCommand.action(mockContext, '');
|
|
||||||
|
|
||||||
expect(result).toEqual({
|
await helpCommand.action(mockContext, '');
|
||||||
type: 'dialog',
|
|
||||||
dialog: 'help',
|
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
|
||||||
});
|
expect.objectContaining({
|
||||||
expect(consoleDebugSpy).toHaveBeenCalledWith('Opening help UI ...');
|
type: MessageType.HELP,
|
||||||
|
timestamp: expect.any(Date),
|
||||||
|
}),
|
||||||
|
expect.any(Number),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should also be triggered by its alternative name '?'", () => {
|
it('should have the correct command properties', () => {
|
||||||
// This test is more conceptual. The routing of altNames to the command
|
expect(helpCommand.name).toBe('help');
|
||||||
// is handled by the slash command processor, but we can assert the
|
expect(helpCommand.kind).toBe(CommandKind.BUILT_IN);
|
||||||
// altNames is correctly defined on the command object itself.
|
expect(helpCommand.description).toBe('for help on gemini-cli');
|
||||||
expect(helpCommand.altNames).toContain('?');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,18 +4,20 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CommandKind, OpenDialogActionReturn, SlashCommand } from './types.js';
|
import { CommandKind, SlashCommand } from './types.js';
|
||||||
|
import { MessageType, type HistoryItemHelp } from '../types.js';
|
||||||
|
|
||||||
export const helpCommand: SlashCommand = {
|
export const helpCommand: SlashCommand = {
|
||||||
name: 'help',
|
name: 'help',
|
||||||
altNames: ['?'],
|
altNames: ['?'],
|
||||||
description: 'for help on gemini-cli',
|
|
||||||
kind: CommandKind.BUILT_IN,
|
kind: CommandKind.BUILT_IN,
|
||||||
action: (_context, _args): OpenDialogActionReturn => {
|
description: 'for help on gemini-cli',
|
||||||
console.debug('Opening help UI ...');
|
action: async (context) => {
|
||||||
return {
|
const helpItem: Omit<HistoryItemHelp, 'id'> = {
|
||||||
type: 'dialog',
|
type: MessageType.HELP,
|
||||||
dialog: 'help',
|
timestamp: new Date(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
context.ui.addItem(helpItem, Date.now());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -98,7 +98,7 @@ export interface MessageActionReturn {
|
||||||
*/
|
*/
|
||||||
export interface OpenDialogActionReturn {
|
export interface OpenDialogActionReturn {
|
||||||
type: 'dialog';
|
type: 'dialog';
|
||||||
dialog: 'help' | 'auth' | 'theme' | 'editor' | 'privacy';
|
dialog: 'auth' | 'theme' | 'editor' | 'privacy';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,6 +21,8 @@ import { ModelStatsDisplay } from './ModelStatsDisplay.js';
|
||||||
import { ToolStatsDisplay } from './ToolStatsDisplay.js';
|
import { ToolStatsDisplay } from './ToolStatsDisplay.js';
|
||||||
import { SessionSummaryDisplay } from './SessionSummaryDisplay.js';
|
import { SessionSummaryDisplay } from './SessionSummaryDisplay.js';
|
||||||
import { Config } from '@google/gemini-cli-core';
|
import { Config } from '@google/gemini-cli-core';
|
||||||
|
import { Help } from './Help.js';
|
||||||
|
import { SlashCommand } from '../commands/types.js';
|
||||||
|
|
||||||
interface HistoryItemDisplayProps {
|
interface HistoryItemDisplayProps {
|
||||||
item: HistoryItem;
|
item: HistoryItem;
|
||||||
|
@ -29,6 +31,7 @@ interface HistoryItemDisplayProps {
|
||||||
isPending: boolean;
|
isPending: boolean;
|
||||||
config?: Config;
|
config?: Config;
|
||||||
isFocused?: boolean;
|
isFocused?: boolean;
|
||||||
|
commands?: readonly SlashCommand[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||||
|
@ -37,6 +40,7 @@ export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||||
terminalWidth,
|
terminalWidth,
|
||||||
isPending,
|
isPending,
|
||||||
config,
|
config,
|
||||||
|
commands,
|
||||||
isFocused = true,
|
isFocused = true,
|
||||||
}) => (
|
}) => (
|
||||||
<Box flexDirection="column" key={item.id}>
|
<Box flexDirection="column" key={item.id}>
|
||||||
|
@ -71,6 +75,7 @@ export const HistoryItemDisplay: React.FC<HistoryItemDisplayProps> = ({
|
||||||
gcpProject={item.gcpProject}
|
gcpProject={item.gcpProject}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{item.type === 'help' && commands && <Help commands={commands} />}
|
||||||
{item.type === 'stats' && <StatsDisplay duration={item.duration} />}
|
{item.type === 'stats' && <StatsDisplay duration={item.duration} />}
|
||||||
{item.type === 'model_stats' && <ModelStatsDisplay />}
|
{item.type === 'model_stats' && <ModelStatsDisplay />}
|
||||||
{item.type === 'tool_stats' && <ToolStatsDisplay />}
|
{item.type === 'tool_stats' && <ToolStatsDisplay />}
|
||||||
|
|
|
@ -90,7 +90,7 @@ describe('useSlashCommandProcessor', () => {
|
||||||
const mockAddItem = vi.fn();
|
const mockAddItem = vi.fn();
|
||||||
const mockClearItems = vi.fn();
|
const mockClearItems = vi.fn();
|
||||||
const mockLoadHistory = vi.fn();
|
const mockLoadHistory = vi.fn();
|
||||||
const mockSetShowHelp = vi.fn();
|
const mockOpenThemeDialog = vi.fn();
|
||||||
const mockOpenAuthDialog = vi.fn();
|
const mockOpenAuthDialog = vi.fn();
|
||||||
const mockSetQuittingMessages = vi.fn();
|
const mockSetQuittingMessages = vi.fn();
|
||||||
|
|
||||||
|
@ -132,9 +132,8 @@ describe('useSlashCommandProcessor', () => {
|
||||||
mockClearItems,
|
mockClearItems,
|
||||||
mockLoadHistory,
|
mockLoadHistory,
|
||||||
vi.fn(), // refreshStatic
|
vi.fn(), // refreshStatic
|
||||||
mockSetShowHelp,
|
|
||||||
vi.fn(), // onDebugMessage
|
vi.fn(), // onDebugMessage
|
||||||
vi.fn(), // openThemeDialog
|
mockOpenThemeDialog, // openThemeDialog
|
||||||
mockOpenAuthDialog,
|
mockOpenAuthDialog,
|
||||||
vi.fn(), // openEditorDialog
|
vi.fn(), // openEditorDialog
|
||||||
vi.fn(), // toggleCorgiMode
|
vi.fn(), // toggleCorgiMode
|
||||||
|
@ -334,19 +333,19 @@ describe('useSlashCommandProcessor', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Action Result Handling', () => {
|
describe('Action Result Handling', () => {
|
||||||
it('should handle "dialog: help" action', async () => {
|
it('should handle "dialog: theme" action', async () => {
|
||||||
const command = createTestCommand({
|
const command = createTestCommand({
|
||||||
name: 'helpcmd',
|
name: 'themecmd',
|
||||||
action: vi.fn().mockResolvedValue({ type: 'dialog', dialog: 'help' }),
|
action: vi.fn().mockResolvedValue({ type: 'dialog', dialog: 'theme' }),
|
||||||
});
|
});
|
||||||
const result = setupProcessorHook([command]);
|
const result = setupProcessorHook([command]);
|
||||||
await waitFor(() => expect(result.current.slashCommands).toHaveLength(1));
|
await waitFor(() => expect(result.current.slashCommands).toHaveLength(1));
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
await result.current.handleSlashCommand('/helpcmd');
|
await result.current.handleSlashCommand('/themecmd');
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(mockSetShowHelp).toHaveBeenCalledWith(true);
|
expect(mockOpenThemeDialog).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle "load_history" action', async () => {
|
it('should handle "load_history" action', async () => {
|
||||||
|
@ -819,15 +818,15 @@ describe('useSlashCommandProcessor', () => {
|
||||||
mockClearItems,
|
mockClearItems,
|
||||||
mockLoadHistory,
|
mockLoadHistory,
|
||||||
vi.fn(), // refreshStatic
|
vi.fn(), // refreshStatic
|
||||||
mockSetShowHelp,
|
|
||||||
vi.fn(), // onDebugMessage
|
vi.fn(), // onDebugMessage
|
||||||
vi.fn(), // openThemeDialog
|
vi.fn(), // openThemeDialog
|
||||||
mockOpenAuthDialog,
|
mockOpenAuthDialog,
|
||||||
vi.fn(), // openEditorDialog,
|
vi.fn(), // openEditorDialog
|
||||||
vi.fn(), // toggleCorgiMode
|
vi.fn(), // toggleCorgiMode
|
||||||
mockSetQuittingMessages,
|
mockSetQuittingMessages,
|
||||||
vi.fn(), // openPrivacyNotice
|
vi.fn(), // openPrivacyNotice
|
||||||
vi.fn(), // toggleVimEnabled
|
vi.fn().mockResolvedValue(false), // toggleVimEnabled
|
||||||
|
vi.fn(), // setIsProcessing
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@ export const useSlashCommandProcessor = (
|
||||||
clearItems: UseHistoryManagerReturn['clearItems'],
|
clearItems: UseHistoryManagerReturn['clearItems'],
|
||||||
loadHistory: UseHistoryManagerReturn['loadHistory'],
|
loadHistory: UseHistoryManagerReturn['loadHistory'],
|
||||||
refreshStatic: () => void,
|
refreshStatic: () => void,
|
||||||
setShowHelp: React.Dispatch<React.SetStateAction<boolean>>,
|
|
||||||
onDebugMessage: (message: string) => void,
|
onDebugMessage: (message: string) => void,
|
||||||
openThemeDialog: () => void,
|
openThemeDialog: () => void,
|
||||||
openAuthDialog: () => void,
|
openAuthDialog: () => void,
|
||||||
|
@ -105,6 +104,11 @@ export const useSlashCommandProcessor = (
|
||||||
selectedAuthType: message.selectedAuthType,
|
selectedAuthType: message.selectedAuthType,
|
||||||
gcpProject: message.gcpProject,
|
gcpProject: message.gcpProject,
|
||||||
};
|
};
|
||||||
|
} else if (message.type === MessageType.HELP) {
|
||||||
|
historyItemContent = {
|
||||||
|
type: 'help',
|
||||||
|
timestamp: message.timestamp,
|
||||||
|
};
|
||||||
} else if (message.type === MessageType.STATS) {
|
} else if (message.type === MessageType.STATS) {
|
||||||
historyItemContent = {
|
historyItemContent = {
|
||||||
type: 'stats',
|
type: 'stats',
|
||||||
|
@ -138,7 +142,6 @@ export const useSlashCommandProcessor = (
|
||||||
},
|
},
|
||||||
[addItem],
|
[addItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
const commandContext = useMemo(
|
const commandContext = useMemo(
|
||||||
(): CommandContext => ({
|
(): CommandContext => ({
|
||||||
services: {
|
services: {
|
||||||
|
@ -333,9 +336,6 @@ export const useSlashCommandProcessor = (
|
||||||
return { type: 'handled' };
|
return { type: 'handled' };
|
||||||
case 'dialog':
|
case 'dialog':
|
||||||
switch (result.dialog) {
|
switch (result.dialog) {
|
||||||
case 'help':
|
|
||||||
setShowHelp(true);
|
|
||||||
return { type: 'handled' };
|
|
||||||
case 'auth':
|
case 'auth':
|
||||||
openAuthDialog();
|
openAuthDialog();
|
||||||
return { type: 'handled' };
|
return { type: 'handled' };
|
||||||
|
@ -462,7 +462,6 @@ export const useSlashCommandProcessor = (
|
||||||
[
|
[
|
||||||
config,
|
config,
|
||||||
addItem,
|
addItem,
|
||||||
setShowHelp,
|
|
||||||
openAuthDialog,
|
openAuthDialog,
|
||||||
commands,
|
commands,
|
||||||
commandContext,
|
commandContext,
|
||||||
|
|
|
@ -30,7 +30,6 @@ import {
|
||||||
SlashCommandProcessorResult,
|
SlashCommandProcessorResult,
|
||||||
StreamingState,
|
StreamingState,
|
||||||
} from '../types.js';
|
} from '../types.js';
|
||||||
import { Dispatch, SetStateAction } from 'react';
|
|
||||||
import { LoadedSettings } from '../../config/settings.js';
|
import { LoadedSettings } from '../../config/settings.js';
|
||||||
|
|
||||||
// --- MOCKS ---
|
// --- MOCKS ---
|
||||||
|
@ -257,7 +256,6 @@ describe('mergePartListUnions', () => {
|
||||||
// --- Tests for useGeminiStream Hook ---
|
// --- Tests for useGeminiStream Hook ---
|
||||||
describe('useGeminiStream', () => {
|
describe('useGeminiStream', () => {
|
||||||
let mockAddItem: Mock;
|
let mockAddItem: Mock;
|
||||||
let mockSetShowHelp: Mock;
|
|
||||||
let mockConfig: Config;
|
let mockConfig: Config;
|
||||||
let mockOnDebugMessage: Mock;
|
let mockOnDebugMessage: Mock;
|
||||||
let mockHandleSlashCommand: Mock;
|
let mockHandleSlashCommand: Mock;
|
||||||
|
@ -269,7 +267,6 @@ describe('useGeminiStream', () => {
|
||||||
vi.clearAllMocks(); // Clear mocks before each test
|
vi.clearAllMocks(); // Clear mocks before each test
|
||||||
|
|
||||||
mockAddItem = vi.fn();
|
mockAddItem = vi.fn();
|
||||||
mockSetShowHelp = vi.fn();
|
|
||||||
// Define the mock for getGeminiClient
|
// Define the mock for getGeminiClient
|
||||||
const mockGetGeminiClient = vi.fn().mockImplementation(() => {
|
const mockGetGeminiClient = vi.fn().mockImplementation(() => {
|
||||||
// MockedGeminiClientClass is defined in the module scope by the previous change.
|
// MockedGeminiClientClass is defined in the module scope by the previous change.
|
||||||
|
@ -382,7 +379,6 @@ describe('useGeminiStream', () => {
|
||||||
client: any;
|
client: any;
|
||||||
history: HistoryItem[];
|
history: HistoryItem[];
|
||||||
addItem: UseHistoryManagerReturn['addItem'];
|
addItem: UseHistoryManagerReturn['addItem'];
|
||||||
setShowHelp: Dispatch<SetStateAction<boolean>>;
|
|
||||||
config: Config;
|
config: Config;
|
||||||
onDebugMessage: (message: string) => void;
|
onDebugMessage: (message: string) => void;
|
||||||
handleSlashCommand: (
|
handleSlashCommand: (
|
||||||
|
@ -400,7 +396,6 @@ describe('useGeminiStream', () => {
|
||||||
props.client,
|
props.client,
|
||||||
props.history,
|
props.history,
|
||||||
props.addItem,
|
props.addItem,
|
||||||
props.setShowHelp,
|
|
||||||
props.config,
|
props.config,
|
||||||
props.onDebugMessage,
|
props.onDebugMessage,
|
||||||
props.handleSlashCommand,
|
props.handleSlashCommand,
|
||||||
|
@ -417,7 +412,6 @@ describe('useGeminiStream', () => {
|
||||||
client,
|
client,
|
||||||
history: [],
|
history: [],
|
||||||
addItem: mockAddItem as unknown as UseHistoryManagerReturn['addItem'],
|
addItem: mockAddItem as unknown as UseHistoryManagerReturn['addItem'],
|
||||||
setShowHelp: mockSetShowHelp,
|
|
||||||
config: mockConfig,
|
config: mockConfig,
|
||||||
onDebugMessage: mockOnDebugMessage,
|
onDebugMessage: mockOnDebugMessage,
|
||||||
handleSlashCommand: mockHandleSlashCommand as unknown as (
|
handleSlashCommand: mockHandleSlashCommand as unknown as (
|
||||||
|
@ -542,7 +536,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -610,7 +603,6 @@ describe('useGeminiStream', () => {
|
||||||
client,
|
client,
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -707,7 +699,6 @@ describe('useGeminiStream', () => {
|
||||||
client,
|
client,
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -810,7 +801,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1161,7 +1151,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1213,7 +1202,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(testConfig),
|
new MockedGeminiClientClass(testConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
testConfig,
|
testConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1262,7 +1250,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1309,7 +1296,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1357,7 +1343,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1445,7 +1430,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1500,7 +1484,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1577,7 +1560,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
@ -1630,7 +1612,6 @@ describe('useGeminiStream', () => {
|
||||||
new MockedGeminiClientClass(mockConfig),
|
new MockedGeminiClientClass(mockConfig),
|
||||||
[],
|
[],
|
||||||
mockAddItem,
|
mockAddItem,
|
||||||
mockSetShowHelp,
|
|
||||||
mockConfig,
|
mockConfig,
|
||||||
mockOnDebugMessage,
|
mockOnDebugMessage,
|
||||||
mockHandleSlashCommand,
|
mockHandleSlashCommand,
|
||||||
|
|
|
@ -82,7 +82,6 @@ export const useGeminiStream = (
|
||||||
geminiClient: GeminiClient,
|
geminiClient: GeminiClient,
|
||||||
history: HistoryItem[],
|
history: HistoryItem[],
|
||||||
addItem: UseHistoryManagerReturn['addItem'],
|
addItem: UseHistoryManagerReturn['addItem'],
|
||||||
setShowHelp: React.Dispatch<React.SetStateAction<boolean>>,
|
|
||||||
config: Config,
|
config: Config,
|
||||||
onDebugMessage: (message: string) => void,
|
onDebugMessage: (message: string) => void,
|
||||||
handleSlashCommand: (
|
handleSlashCommand: (
|
||||||
|
@ -610,7 +609,6 @@ export const useGeminiStream = (
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const userMessageTimestamp = Date.now();
|
const userMessageTimestamp = Date.now();
|
||||||
setShowHelp(false);
|
|
||||||
|
|
||||||
// Reset quota error flag when starting a new query (not a continuation)
|
// Reset quota error flag when starting a new query (not a continuation)
|
||||||
if (!options?.isContinuation) {
|
if (!options?.isContinuation) {
|
||||||
|
@ -693,7 +691,6 @@ export const useGeminiStream = (
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
streamingState,
|
streamingState,
|
||||||
setShowHelp,
|
|
||||||
setModelSwitchedFromQuotaError,
|
setModelSwitchedFromQuotaError,
|
||||||
prepareQueryForGemini,
|
prepareQueryForGemini,
|
||||||
processGeminiStreamEvents,
|
processGeminiStreamEvents,
|
||||||
|
|
|
@ -97,6 +97,11 @@ export type HistoryItemAbout = HistoryItemBase & {
|
||||||
gcpProject: string;
|
gcpProject: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type HistoryItemHelp = HistoryItemBase & {
|
||||||
|
type: 'help';
|
||||||
|
timestamp: Date;
|
||||||
|
};
|
||||||
|
|
||||||
export type HistoryItemStats = HistoryItemBase & {
|
export type HistoryItemStats = HistoryItemBase & {
|
||||||
type: 'stats';
|
type: 'stats';
|
||||||
duration: string;
|
duration: string;
|
||||||
|
@ -142,6 +147,7 @@ export type HistoryItemWithoutId =
|
||||||
| HistoryItemInfo
|
| HistoryItemInfo
|
||||||
| HistoryItemError
|
| HistoryItemError
|
||||||
| HistoryItemAbout
|
| HistoryItemAbout
|
||||||
|
| HistoryItemHelp
|
||||||
| HistoryItemToolGroup
|
| HistoryItemToolGroup
|
||||||
| HistoryItemStats
|
| HistoryItemStats
|
||||||
| HistoryItemModelStats
|
| HistoryItemModelStats
|
||||||
|
@ -157,6 +163,7 @@ export enum MessageType {
|
||||||
ERROR = 'error',
|
ERROR = 'error',
|
||||||
USER = 'user',
|
USER = 'user',
|
||||||
ABOUT = 'about',
|
ABOUT = 'about',
|
||||||
|
HELP = 'help',
|
||||||
STATS = 'stats',
|
STATS = 'stats',
|
||||||
MODEL_STATS = 'model_stats',
|
MODEL_STATS = 'model_stats',
|
||||||
TOOL_STATS = 'tool_stats',
|
TOOL_STATS = 'tool_stats',
|
||||||
|
@ -183,6 +190,11 @@ export type Message =
|
||||||
gcpProject: string;
|
gcpProject: string;
|
||||||
content?: string; // Optional content, not really used for ABOUT
|
content?: string; // Optional content, not really used for ABOUT
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: MessageType.HELP;
|
||||||
|
timestamp: Date;
|
||||||
|
content?: string; // Optional content, not really used for HELP
|
||||||
|
}
|
||||||
| {
|
| {
|
||||||
type: MessageType.STATS;
|
type: MessageType.STATS;
|
||||||
timestamp: Date;
|
timestamp: Date;
|
||||||
|
|
Loading…
Reference in New Issue