summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/hooks')
-rw-r--r--packages/cli/src/ui/hooks/slashCommandProcessor.test.ts37
-rw-r--r--packages/cli/src/ui/hooks/slashCommandProcessor.ts48
-rw-r--r--packages/cli/src/ui/hooks/useGeminiStream.test.tsx13
-rw-r--r--packages/cli/src/ui/hooks/useGeminiStream.ts8
4 files changed, 44 insertions, 62 deletions
diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts
index 7466e2a6..6ec356aa 100644
--- a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts
+++ b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts
@@ -255,18 +255,19 @@ describe('useSlashCommandProcessor', () => {
describe('/stats command', () => {
it('should show detailed session statistics', async () => {
// Arrange
+ const cumulativeStats = {
+ totalTokenCount: 900,
+ promptTokenCount: 200,
+ candidatesTokenCount: 400,
+ cachedContentTokenCount: 100,
+ turnCount: 1,
+ toolUsePromptTokenCount: 50,
+ thoughtsTokenCount: 150,
+ };
mockUseSessionStats.mockReturnValue({
stats: {
sessionStartTime: new Date('2025-01-01T00:00:00.000Z'),
- cumulative: {
- totalTokenCount: 900,
- promptTokenCount: 200,
- candidatesTokenCount: 400,
- cachedContentTokenCount: 100,
- turnCount: 1,
- toolUsePromptTokenCount: 50,
- thoughtsTokenCount: 150,
- },
+ cumulative: cumulativeStats,
},
});
@@ -280,24 +281,12 @@ describe('useSlashCommandProcessor', () => {
});
// Assert
- const expectedContent = [
- ` ⎿ Total duration (wall): 1h 2m 3s`,
- ` Total Token usage:`,
- ` Turns: 1`,
- ` Total: 900`,
- ` ├─ Input: 200`,
- ` ├─ Output: 400`,
- ` ├─ Cached: 100`,
- ` └─ Overhead: 200`,
- ` ├─ Model thoughts: 150`,
- ` └─ Tool-use prompts: 50`,
- ].join('\n');
-
expect(mockAddItem).toHaveBeenNthCalledWith(
2, // Called after the user message
expect.objectContaining({
- type: MessageType.INFO,
- text: expectedContent,
+ type: MessageType.STATS,
+ stats: cumulativeStats,
+ duration: '1h 2m 3s',
}),
expect.any(Number),
);
diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts
index fa1e4016..9e82b6cf 100644
--- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts
+++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts
@@ -20,7 +20,7 @@ import { Message, MessageType, HistoryItemWithoutId } from '../types.js';
import { useSessionStats } from '../contexts/SessionContext.js';
import { createShowMemoryAction } from './useShowMemoryCommand.js';
import { GIT_COMMIT_INFO } from '../../generated/git-commit.js';
-import { formatMemoryUsage } from '../utils/formatters.js';
+import { formatDuration, formatMemoryUsage } from '../utils/formatters.js';
import { getCliVersion } from '../../utils/version.js';
export interface SlashCommandActionReturn {
@@ -69,6 +69,13 @@ export const useSlashCommandProcessor = (
sandboxEnv: message.sandboxEnv,
modelVersion: message.modelVersion,
};
+ } else if (message.type === MessageType.STATS) {
+ historyItemContent = {
+ type: 'stats',
+ stats: message.stats,
+ lastTurnStats: message.lastTurnStats,
+ duration: message.duration,
+ };
} else {
historyItemContent = {
type: message.type as
@@ -152,41 +159,14 @@ export const useSlashCommandProcessor = (
description: 'check session stats',
action: (_mainCommand, _subCommand, _args) => {
const now = new Date();
- const { sessionStartTime, cumulative } = session.stats;
-
- const duration = now.getTime() - sessionStartTime.getTime();
- const durationInSeconds = Math.floor(duration / 1000);
- const hours = Math.floor(durationInSeconds / 3600);
- const minutes = Math.floor((durationInSeconds % 3600) / 60);
- const seconds = durationInSeconds % 60;
-
- const durationString = [
- hours > 0 ? `${hours}h` : '',
- minutes > 0 ? `${minutes}m` : '',
- `${seconds}s`,
- ]
- .filter(Boolean)
- .join(' ');
-
- const overheadTotal =
- cumulative.thoughtsTokenCount + cumulative.toolUsePromptTokenCount;
-
- const statsContent = [
- ` ⎿ Total duration (wall): ${durationString}`,
- ` Total Token usage:`,
- ` Turns: ${cumulative.turnCount.toLocaleString()}`,
- ` Total: ${cumulative.totalTokenCount.toLocaleString()}`,
- ` ├─ Input: ${cumulative.promptTokenCount.toLocaleString()}`,
- ` ├─ Output: ${cumulative.candidatesTokenCount.toLocaleString()}`,
- ` ├─ Cached: ${cumulative.cachedContentTokenCount.toLocaleString()}`,
- ` └─ Overhead: ${overheadTotal.toLocaleString()}`,
- ` ├─ Model thoughts: ${cumulative.thoughtsTokenCount.toLocaleString()}`,
- ` └─ Tool-use prompts: ${cumulative.toolUsePromptTokenCount.toLocaleString()}`,
- ].join('\n');
+ const { sessionStartTime, cumulative, currentTurn } = session.stats;
+ const wallDuration = now.getTime() - sessionStartTime.getTime();
addMessage({
- type: MessageType.INFO,
- content: statsContent,
+ type: MessageType.STATS,
+ stats: cumulative,
+ lastTurnStats: currentTurn,
+ duration: formatDuration(wallDuration),
timestamp: new Date(),
});
},
diff --git a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx
index ed0f2aac..e39feb01 100644
--- a/packages/cli/src/ui/hooks/useGeminiStream.test.tsx
+++ b/packages/cli/src/ui/hooks/useGeminiStream.test.tsx
@@ -598,5 +598,18 @@ describe('useGeminiStream', () => {
expect(mockStartNewTurn).toHaveBeenCalledTimes(1);
expect(mockAddUsage).not.toHaveBeenCalled();
});
+
+ it('should not call startNewTurn for a slash command', async () => {
+ mockHandleSlashCommand.mockReturnValue(true);
+
+ const { result } = renderTestHook();
+
+ await act(async () => {
+ await result.current.submitQuery('/stats');
+ });
+
+ expect(mockStartNewTurn).not.toHaveBeenCalled();
+ expect(mockSendMessageStream).not.toHaveBeenCalled();
+ });
});
});
diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts
index bad9f78a..725d8737 100644
--- a/packages/cli/src/ui/hooks/useGeminiStream.ts
+++ b/packages/cli/src/ui/hooks/useGeminiStream.ts
@@ -432,10 +432,6 @@ export const useGeminiStream = (
const userMessageTimestamp = Date.now();
setShowHelp(false);
- if (!options?.isContinuation) {
- startNewTurn();
- }
-
abortControllerRef.current = new AbortController();
const abortSignal = abortControllerRef.current.signal;
@@ -449,6 +445,10 @@ export const useGeminiStream = (
return;
}
+ if (!options?.isContinuation) {
+ startNewTurn();
+ }
+
if (!geminiClient) {
const errorMsg = 'Gemini client is not available.';
setInitError(errorMsg);