@google/gemini-cli 0.18.0-nightly.20251118.7cc5234b9 → 0.18.0-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +1 -0
- package/dist/package.json +4 -4
- package/dist/src/commands/extensions/disable.test.js +19 -13
- package/dist/src/commands/extensions/disable.test.js.map +1 -1
- package/dist/src/commands/extensions/enable.test.js +16 -9
- package/dist/src/commands/extensions/enable.test.js.map +1 -1
- package/dist/src/commands/extensions/link.test.js +18 -11
- package/dist/src/commands/extensions/link.test.js.map +1 -1
- package/dist/src/commands/extensions/list.test.js +20 -13
- package/dist/src/commands/extensions/list.test.js.map +1 -1
- package/dist/src/commands/extensions/uninstall.test.js +26 -18
- package/dist/src/commands/extensions/uninstall.test.js.map +1 -1
- package/dist/src/commands/extensions/update.test.js +20 -13
- package/dist/src/commands/extensions/update.test.js.map +1 -1
- package/dist/src/commands/mcp/add.test.js +8 -3
- package/dist/src/commands/mcp/add.test.js.map +1 -1
- package/dist/src/commands/mcp/list.test.js +1 -6
- package/dist/src/commands/mcp/list.test.js.map +1 -1
- package/dist/src/commands/mcp/remove.test.js +23 -12
- package/dist/src/commands/mcp/remove.test.js.map +1 -1
- package/dist/src/config/config.d.ts +2 -1
- package/dist/src/config/config.js +38 -14
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +64 -10
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/extension.test.js +131 -125
- package/dist/src/config/extension.test.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +2 -2
- package/dist/src/config/settingsSchema.js +3 -3
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.js +1 -1
- package/dist/src/config/settingsSchema.test.js.map +1 -1
- package/dist/src/gemini.js +65 -7
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +55 -15
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/nonInteractiveCli.js +4 -1
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.js +2 -2
- package/dist/src/nonInteractiveCli.test.js.map +1 -1
- package/dist/src/services/CommandService.test.js +3 -2
- package/dist/src/services/CommandService.test.js.map +1 -1
- package/dist/src/services/McpPromptLoader.js +5 -3
- package/dist/src/services/McpPromptLoader.js.map +1 -1
- package/dist/src/services/McpPromptLoader.test.js +29 -1
- package/dist/src/services/McpPromptLoader.test.js.map +1 -1
- package/dist/src/test-utils/render.d.ts +26 -2
- package/dist/src/test-utils/render.js +76 -3
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/ui/AppContainer.js +57 -32
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +169 -102
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/auth/AuthDialog.test.js +2 -2
- package/dist/src/ui/auth/AuthDialog.test.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.js +8 -1
- package/dist/src/ui/commands/aboutCommand.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.test.js +4 -0
- package/dist/src/ui/commands/aboutCommand.test.js.map +1 -1
- package/dist/src/ui/commands/clearCommand.js +12 -0
- package/dist/src/ui/commands/clearCommand.js.map +1 -1
- package/dist/src/ui/commands/clearCommand.test.js +5 -0
- package/dist/src/ui/commands/clearCommand.test.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.js +1 -0
- package/dist/src/ui/commands/memoryCommand.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.test.js +3 -0
- package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
- package/dist/src/ui/commands/setupGithubCommand.d.ts +1 -0
- package/dist/src/ui/commands/setupGithubCommand.js +82 -45
- package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
- package/dist/src/ui/commands/setupGithubCommand.test.js +35 -5
- package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -1
- package/dist/src/ui/components/AboutBox.d.ts +1 -0
- package/dist/src/ui/components/AboutBox.js +1 -1
- package/dist/src/ui/components/AboutBox.js.map +1 -1
- package/dist/src/ui/components/AppHeader.js +3 -8
- package/dist/src/ui/components/AppHeader.js.map +1 -1
- package/dist/src/ui/components/Banner.d.ts +4 -2
- package/dist/src/ui/components/Banner.js +18 -4
- package/dist/src/ui/components/Banner.js.map +1 -1
- package/dist/src/ui/components/DebugProfiler.d.ts +1 -0
- package/dist/src/ui/components/DebugProfiler.js +23 -34
- package/dist/src/ui/components/DebugProfiler.js.map +1 -1
- package/dist/src/ui/components/DebugProfiler.test.js +1 -0
- package/dist/src/ui/components/DebugProfiler.test.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +1 -1
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/GradientRegression.test.js +22 -1
- package/dist/src/ui/components/GradientRegression.test.js.map +1 -1
- package/dist/src/ui/components/Header.test.js +27 -2
- package/dist/src/ui/components/Header.test.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +16 -24
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.js +84 -24
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.js +2 -2
- package/dist/src/ui/components/ModelDialog.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.d.ts +3 -1
- package/dist/src/ui/components/SettingsDialog.js +4 -1
- package/dist/src/ui/components/SettingsDialog.js.map +1 -1
- package/dist/src/ui/components/ThemedGradient.js +2 -1
- package/dist/src/ui/components/ThemedGradient.js.map +1 -1
- package/dist/src/ui/components/messages/ShellToolMessage.d.ts +14 -0
- package/dist/src/ui/components/messages/ShellToolMessage.js +76 -0
- package/dist/src/ui/components/messages/ShellToolMessage.js.map +1 -0
- package/dist/src/ui/components/messages/ShellToolMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ShellToolMessage.test.js +123 -0
- package/dist/src/ui/components/messages/ShellToolMessage.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolGroupMessage.js +19 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.d.ts +3 -6
- package/dist/src/ui/components/messages/ToolMessage.js +5 -121
- package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.test.js +13 -5
- package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolResultDisplay.d.ts +13 -0
- package/dist/src/ui/components/messages/ToolResultDisplay.js +54 -0
- package/dist/src/ui/components/messages/ToolResultDisplay.js.map +1 -0
- package/dist/src/ui/components/messages/ToolShared.d.ts +23 -0
- package/dist/src/ui/components/messages/ToolShared.js +40 -0
- package/dist/src/ui/components/messages/ToolShared.js.map +1 -0
- package/dist/src/ui/components/shared/text-buffer.js +4 -1
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.js +21 -11
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +29 -10
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/UIActionsContext.d.ts +1 -0
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.js +8 -4
- package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.js +4 -3
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.d.ts +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js +5 -3
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/useBracketedPaste.js +3 -2
- package/dist/src/ui/hooks/useBracketedPaste.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.js +5 -5
- package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useConsoleMessages.d.ts +0 -1
- package/dist/src/ui/hooks/useConsoleMessages.js +26 -1
- package/dist/src/ui/hooks/useConsoleMessages.js.map +1 -1
- package/dist/src/ui/hooks/useConsoleMessages.test.js +37 -5
- package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
- package/dist/src/ui/hooks/useEditorSettings.d.ts +2 -2
- package/dist/src/ui/hooks/useEditorSettings.js.map +1 -1
- package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.d.ts +1 -1
- package/dist/src/ui/hooks/useGeminiStream.js +48 -10
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.js +20 -21
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
- package/dist/src/ui/hooks/useHistoryManager.d.ts +5 -2
- package/dist/src/ui/hooks/useHistoryManager.js +39 -3
- package/dist/src/ui/hooks/useHistoryManager.js.map +1 -1
- package/dist/src/ui/hooks/useIncludeDirsTrust.js +0 -1
- package/dist/src/ui/hooks/useIncludeDirsTrust.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js +4 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
- package/dist/src/ui/hooks/useKittyKeyboardProtocol.d.ts +0 -1
- package/dist/src/ui/hooks/useKittyKeyboardProtocol.js +1 -2
- package/dist/src/ui/hooks/useKittyKeyboardProtocol.js.map +1 -1
- package/dist/src/ui/hooks/useMouseClick.d.ts +12 -0
- package/dist/src/ui/hooks/useMouseClick.js +28 -0
- package/dist/src/ui/hooks/useMouseClick.js.map +1 -0
- package/dist/src/ui/hooks/useMouseClick.test.d.ts +6 -0
- package/dist/src/ui/hooks/useMouseClick.test.js +59 -0
- package/dist/src/ui/hooks/useMouseClick.test.js.map +1 -0
- package/dist/src/ui/hooks/useReactToolScheduler.d.ts +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.js +1 -8
- package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.test.js +1 -8
- package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -1
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +18 -12
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useSessionBrowser.js +13 -4
- package/dist/src/ui/hooks/useSessionBrowser.js.map +1 -1
- package/dist/src/ui/hooks/useSessionBrowser.test.js +37 -0
- package/dist/src/ui/hooks/useSessionBrowser.test.js.map +1 -1
- package/dist/src/ui/hooks/useSessionResume.js +1 -1
- package/dist/src/ui/hooks/useSessionResume.js.map +1 -1
- package/dist/src/ui/hooks/useSessionResume.test.js +4 -4
- package/dist/src/ui/hooks/useSessionResume.test.js.map +1 -1
- package/dist/src/ui/hooks/useThemeCommand.d.ts +2 -2
- package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +2 -2
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/themes/theme-manager.test.js +2 -1
- package/dist/src/ui/themes/theme-manager.test.js.map +1 -1
- package/dist/src/ui/types.d.ts +2 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/ConsolePatcher.js +6 -9
- package/dist/src/ui/utils/ConsolePatcher.js.map +1 -1
- package/dist/src/ui/utils/kittyProtocolDetector.d.ts +6 -2
- package/dist/src/ui/utils/kittyProtocolDetector.js +48 -43
- package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
- package/dist/src/ui/utils/mouse.js +3 -3
- package/dist/src/ui/utils/mouse.js.map +1 -1
- package/dist/src/utils/cleanup.d.ts +2 -0
- package/dist/src/utils/cleanup.js +16 -0
- package/dist/src/utils/cleanup.js.map +1 -1
- package/dist/src/utils/errors.js +10 -0
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/events.d.ts +0 -2
- package/dist/src/utils/events.js +0 -1
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/installationInfo.test.js +8 -9
- package/dist/src/utils/installationInfo.test.js.map +1 -1
- package/dist/src/utils/sessionCleanup.test.js +4 -2
- package/dist/src/utils/sessionCleanup.test.js.map +1 -1
- package/dist/src/utils/sessionUtils.d.ts +5 -0
- package/dist/src/utils/sessionUtils.js +6 -1
- package/dist/src/utils/sessionUtils.js.map +1 -1
- package/dist/src/utils/sessions.test.d.ts +6 -0
- package/dist/src/utils/sessions.test.js +516 -0
- package/dist/src/utils/sessions.test.js.map +1 -0
- package/dist/src/utils/stdio.d.ts +32 -0
- package/dist/src/utils/stdio.js +85 -0
- package/dist/src/utils/stdio.js.map +1 -0
- package/dist/src/utils/stdio.test.d.ts +6 -0
- package/dist/src/utils/stdio.test.js +47 -0
- package/dist/src/utils/stdio.test.js.map +1 -0
- package/dist/src/validateNonInterActiveAuth.js +2 -0
- package/dist/src/validateNonInterActiveAuth.js.map +1 -1
- package/dist/src/validateNonInterActiveAuth.test.js +10 -6
- package/dist/src/validateNonInterActiveAuth.test.js.map +1 -1
- package/dist/src/zed-integration/schema.d.ts +30 -30
- package/dist/src/zed-integration/zedIntegration.d.ts +0 -7
- package/dist/src/zed-integration/zedIntegration.js +9 -21
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/dist/google-gemini-cli-0.18.0-nightly.20251118.86828bb56.tgz +0 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { ChatRecordingService } from '@google/gemini-cli-core';
|
|
8
|
+
import { listSessions, deleteSession } from './sessions.js';
|
|
9
|
+
import { SessionSelector } from './sessionUtils.js';
|
|
10
|
+
// Mock the SessionSelector and ChatRecordingService
|
|
11
|
+
vi.mock('./sessionUtils.js', () => ({
|
|
12
|
+
SessionSelector: vi.fn(),
|
|
13
|
+
formatRelativeTime: vi.fn(() => 'some time ago'),
|
|
14
|
+
}));
|
|
15
|
+
vi.mock('@google/gemini-cli-core', async () => {
|
|
16
|
+
const actual = await vi.importActual('@google/gemini-cli-core');
|
|
17
|
+
return {
|
|
18
|
+
...actual,
|
|
19
|
+
ChatRecordingService: vi.fn(),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
describe('listSessions', () => {
|
|
23
|
+
let mockConfig;
|
|
24
|
+
let mockListSessions;
|
|
25
|
+
let consoleLogSpy;
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
// Create mock config
|
|
28
|
+
mockConfig = {
|
|
29
|
+
storage: {
|
|
30
|
+
getProjectTempDir: vi.fn().mockReturnValue('/tmp/test-project'),
|
|
31
|
+
},
|
|
32
|
+
getSessionId: vi.fn().mockReturnValue('current-session-id'),
|
|
33
|
+
};
|
|
34
|
+
// Create mock listSessions method
|
|
35
|
+
mockListSessions = vi.fn();
|
|
36
|
+
// Mock SessionSelector constructor to return object with listSessions method
|
|
37
|
+
vi.mocked(SessionSelector).mockImplementation(() => ({
|
|
38
|
+
listSessions: mockListSessions,
|
|
39
|
+
}));
|
|
40
|
+
// Spy on console.log
|
|
41
|
+
consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
42
|
+
});
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
vi.clearAllMocks();
|
|
45
|
+
consoleLogSpy.mockRestore();
|
|
46
|
+
});
|
|
47
|
+
it('should display message when no previous sessions were found', async () => {
|
|
48
|
+
// Arrange: Return empty array from listSessions
|
|
49
|
+
mockListSessions.mockResolvedValue([]);
|
|
50
|
+
// Act
|
|
51
|
+
await listSessions(mockConfig);
|
|
52
|
+
// Assert
|
|
53
|
+
expect(mockListSessions).toHaveBeenCalledOnce();
|
|
54
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('No previous sessions found for this project.');
|
|
55
|
+
});
|
|
56
|
+
it('should list sessions when sessions are found', async () => {
|
|
57
|
+
// Arrange: Create test sessions
|
|
58
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
59
|
+
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
|
|
60
|
+
const twoDaysAgo = new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000);
|
|
61
|
+
const mockSessions = [
|
|
62
|
+
{
|
|
63
|
+
id: 'session-1',
|
|
64
|
+
file: 'session-2025-01-18T12-00-00-session-1',
|
|
65
|
+
fileName: 'session-2025-01-18T12-00-00-session-1.json',
|
|
66
|
+
startTime: twoDaysAgo.toISOString(),
|
|
67
|
+
lastUpdated: twoDaysAgo.toISOString(),
|
|
68
|
+
firstUserMessage: 'First user message',
|
|
69
|
+
isCurrentSession: false,
|
|
70
|
+
index: 1,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 'session-2',
|
|
74
|
+
file: 'session-2025-01-20T11-00-00-session-2',
|
|
75
|
+
fileName: 'session-2025-01-20T11-00-00-session-2.json',
|
|
76
|
+
startTime: oneHourAgo.toISOString(),
|
|
77
|
+
lastUpdated: oneHourAgo.toISOString(),
|
|
78
|
+
firstUserMessage: 'Second user message',
|
|
79
|
+
isCurrentSession: false,
|
|
80
|
+
index: 2,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 'current-session-id',
|
|
84
|
+
file: 'session-2025-01-20T12-00-00-current-s',
|
|
85
|
+
fileName: 'session-2025-01-20T12-00-00-current-s.json',
|
|
86
|
+
startTime: now.toISOString(),
|
|
87
|
+
lastUpdated: now.toISOString(),
|
|
88
|
+
firstUserMessage: 'Current session',
|
|
89
|
+
isCurrentSession: true,
|
|
90
|
+
index: 3,
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
94
|
+
// Act
|
|
95
|
+
await listSessions(mockConfig);
|
|
96
|
+
// Assert
|
|
97
|
+
expect(mockListSessions).toHaveBeenCalledOnce();
|
|
98
|
+
// Check that the header was displayed
|
|
99
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('\nAvailable sessions for this project (3):\n');
|
|
100
|
+
// Check that each session was logged
|
|
101
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('1. First user message'));
|
|
102
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('[session-1]'));
|
|
103
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('2. Second user message'));
|
|
104
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('[session-2]'));
|
|
105
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('3. Current session'));
|
|
106
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining(', current)'));
|
|
107
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('[current-session-id]'));
|
|
108
|
+
});
|
|
109
|
+
it('should sort sessions by start time (oldest first)', async () => {
|
|
110
|
+
// Arrange: Create sessions in non-chronological order
|
|
111
|
+
const session1Time = new Date('2025-01-18T12:00:00.000Z');
|
|
112
|
+
const session2Time = new Date('2025-01-19T12:00:00.000Z');
|
|
113
|
+
const session3Time = new Date('2025-01-20T12:00:00.000Z');
|
|
114
|
+
const mockSessions = [
|
|
115
|
+
{
|
|
116
|
+
id: 'session-2',
|
|
117
|
+
file: 'session-2',
|
|
118
|
+
fileName: 'session-2.json',
|
|
119
|
+
startTime: session2Time.toISOString(), // Middle
|
|
120
|
+
lastUpdated: session2Time.toISOString(),
|
|
121
|
+
firstUserMessage: 'Middle session',
|
|
122
|
+
isCurrentSession: false,
|
|
123
|
+
index: 2,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'session-1',
|
|
127
|
+
file: 'session-1',
|
|
128
|
+
fileName: 'session-1.json',
|
|
129
|
+
startTime: session1Time.toISOString(), // Oldest
|
|
130
|
+
lastUpdated: session1Time.toISOString(),
|
|
131
|
+
firstUserMessage: 'Oldest session',
|
|
132
|
+
isCurrentSession: false,
|
|
133
|
+
index: 1,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: 'session-3',
|
|
137
|
+
file: 'session-3',
|
|
138
|
+
fileName: 'session-3.json',
|
|
139
|
+
startTime: session3Time.toISOString(), // Newest
|
|
140
|
+
lastUpdated: session3Time.toISOString(),
|
|
141
|
+
firstUserMessage: 'Newest session',
|
|
142
|
+
isCurrentSession: false,
|
|
143
|
+
index: 3,
|
|
144
|
+
},
|
|
145
|
+
];
|
|
146
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
147
|
+
// Act
|
|
148
|
+
await listSessions(mockConfig);
|
|
149
|
+
// Assert
|
|
150
|
+
// Get all the session log calls (skip the header)
|
|
151
|
+
const sessionCalls = consoleLogSpy.mock.calls.filter((call) => typeof call[0] === 'string' &&
|
|
152
|
+
call[0].includes('[session-') &&
|
|
153
|
+
!call[0].includes('Available sessions'));
|
|
154
|
+
// Verify they are sorted by start time (oldest first)
|
|
155
|
+
expect(sessionCalls[0][0]).toContain('1. Oldest session');
|
|
156
|
+
expect(sessionCalls[1][0]).toContain('2. Middle session');
|
|
157
|
+
expect(sessionCalls[2][0]).toContain('3. Newest session');
|
|
158
|
+
});
|
|
159
|
+
it('should format session output with relative time and session ID', async () => {
|
|
160
|
+
// Arrange
|
|
161
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
162
|
+
const mockSessions = [
|
|
163
|
+
{
|
|
164
|
+
id: 'abc123def456',
|
|
165
|
+
file: 'session-file',
|
|
166
|
+
fileName: 'session-file.json',
|
|
167
|
+
startTime: now.toISOString(),
|
|
168
|
+
lastUpdated: now.toISOString(),
|
|
169
|
+
firstUserMessage: 'Test message',
|
|
170
|
+
isCurrentSession: false,
|
|
171
|
+
index: 1,
|
|
172
|
+
},
|
|
173
|
+
];
|
|
174
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
175
|
+
// Act
|
|
176
|
+
await listSessions(mockConfig);
|
|
177
|
+
// Assert
|
|
178
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('1. Test message'));
|
|
179
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('some time ago'));
|
|
180
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('[abc123def456]'));
|
|
181
|
+
});
|
|
182
|
+
it('should handle single session', async () => {
|
|
183
|
+
// Arrange
|
|
184
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
185
|
+
const mockSessions = [
|
|
186
|
+
{
|
|
187
|
+
id: 'single-session',
|
|
188
|
+
file: 'session-file',
|
|
189
|
+
fileName: 'session-file.json',
|
|
190
|
+
startTime: now.toISOString(),
|
|
191
|
+
lastUpdated: now.toISOString(),
|
|
192
|
+
firstUserMessage: 'Only session',
|
|
193
|
+
isCurrentSession: true,
|
|
194
|
+
index: 1,
|
|
195
|
+
},
|
|
196
|
+
];
|
|
197
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
198
|
+
// Act
|
|
199
|
+
await listSessions(mockConfig);
|
|
200
|
+
// Assert
|
|
201
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('\nAvailable sessions for this project (1):\n');
|
|
202
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('1. Only session'));
|
|
203
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining(', current)'));
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
describe('deleteSession', () => {
|
|
207
|
+
let mockConfig;
|
|
208
|
+
let mockListSessions;
|
|
209
|
+
let mockDeleteSession;
|
|
210
|
+
let consoleLogSpy;
|
|
211
|
+
let consoleErrorSpy;
|
|
212
|
+
beforeEach(() => {
|
|
213
|
+
// Create mock config
|
|
214
|
+
mockConfig = {
|
|
215
|
+
storage: {
|
|
216
|
+
getProjectTempDir: vi.fn().mockReturnValue('/tmp/test-project'),
|
|
217
|
+
},
|
|
218
|
+
getSessionId: vi.fn().mockReturnValue('current-session-id'),
|
|
219
|
+
};
|
|
220
|
+
// Create mock methods
|
|
221
|
+
mockListSessions = vi.fn();
|
|
222
|
+
mockDeleteSession = vi.fn();
|
|
223
|
+
// Mock SessionSelector constructor
|
|
224
|
+
vi.mocked(SessionSelector).mockImplementation(() => ({
|
|
225
|
+
listSessions: mockListSessions,
|
|
226
|
+
}));
|
|
227
|
+
// Mock ChatRecordingService
|
|
228
|
+
vi.mocked(ChatRecordingService).mockImplementation(() => ({
|
|
229
|
+
deleteSession: mockDeleteSession,
|
|
230
|
+
}));
|
|
231
|
+
// Spy on console methods
|
|
232
|
+
consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
233
|
+
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
234
|
+
});
|
|
235
|
+
afterEach(() => {
|
|
236
|
+
vi.clearAllMocks();
|
|
237
|
+
consoleLogSpy.mockRestore();
|
|
238
|
+
consoleErrorSpy.mockRestore();
|
|
239
|
+
});
|
|
240
|
+
it('should display error when no sessions are found', async () => {
|
|
241
|
+
// Arrange
|
|
242
|
+
mockListSessions.mockResolvedValue([]);
|
|
243
|
+
// Act
|
|
244
|
+
await deleteSession(mockConfig, '1');
|
|
245
|
+
// Assert
|
|
246
|
+
expect(mockListSessions).toHaveBeenCalledOnce();
|
|
247
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('No sessions found for this project.');
|
|
248
|
+
expect(mockDeleteSession).not.toHaveBeenCalled();
|
|
249
|
+
});
|
|
250
|
+
it('should delete session by UUID', async () => {
|
|
251
|
+
// Arrange
|
|
252
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
253
|
+
const mockSessions = [
|
|
254
|
+
{
|
|
255
|
+
id: 'session-uuid-123',
|
|
256
|
+
file: 'session-file-123',
|
|
257
|
+
fileName: 'session-file-123.json',
|
|
258
|
+
startTime: now.toISOString(),
|
|
259
|
+
lastUpdated: now.toISOString(),
|
|
260
|
+
firstUserMessage: 'Test session',
|
|
261
|
+
isCurrentSession: false,
|
|
262
|
+
index: 1,
|
|
263
|
+
},
|
|
264
|
+
];
|
|
265
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
266
|
+
mockDeleteSession.mockImplementation(() => { });
|
|
267
|
+
// Act
|
|
268
|
+
await deleteSession(mockConfig, 'session-uuid-123');
|
|
269
|
+
// Assert
|
|
270
|
+
expect(mockListSessions).toHaveBeenCalledOnce();
|
|
271
|
+
expect(mockDeleteSession).toHaveBeenCalledWith('session-file-123');
|
|
272
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Deleted session 1: Test session (some time ago)');
|
|
273
|
+
expect(consoleErrorSpy).not.toHaveBeenCalled();
|
|
274
|
+
});
|
|
275
|
+
it('should delete session by index', async () => {
|
|
276
|
+
// Arrange
|
|
277
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
278
|
+
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
|
|
279
|
+
const mockSessions = [
|
|
280
|
+
{
|
|
281
|
+
id: 'session-1',
|
|
282
|
+
file: 'session-file-1',
|
|
283
|
+
fileName: 'session-file-1.json',
|
|
284
|
+
startTime: oneHourAgo.toISOString(),
|
|
285
|
+
lastUpdated: oneHourAgo.toISOString(),
|
|
286
|
+
firstUserMessage: 'First session',
|
|
287
|
+
isCurrentSession: false,
|
|
288
|
+
index: 1,
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
id: 'session-2',
|
|
292
|
+
file: 'session-file-2',
|
|
293
|
+
fileName: 'session-file-2.json',
|
|
294
|
+
startTime: now.toISOString(),
|
|
295
|
+
lastUpdated: now.toISOString(),
|
|
296
|
+
firstUserMessage: 'Second session',
|
|
297
|
+
isCurrentSession: false,
|
|
298
|
+
index: 2,
|
|
299
|
+
},
|
|
300
|
+
];
|
|
301
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
302
|
+
mockDeleteSession.mockImplementation(() => { });
|
|
303
|
+
// Act
|
|
304
|
+
await deleteSession(mockConfig, '2');
|
|
305
|
+
// Assert
|
|
306
|
+
expect(mockListSessions).toHaveBeenCalledOnce();
|
|
307
|
+
expect(mockDeleteSession).toHaveBeenCalledWith('session-file-2');
|
|
308
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Deleted session 2: Second session (some time ago)');
|
|
309
|
+
});
|
|
310
|
+
it('should display error for invalid session identifier (non-numeric)', async () => {
|
|
311
|
+
// Arrange
|
|
312
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
313
|
+
const mockSessions = [
|
|
314
|
+
{
|
|
315
|
+
id: 'session-1',
|
|
316
|
+
file: 'session-file-1',
|
|
317
|
+
fileName: 'session-file-1.json',
|
|
318
|
+
startTime: now.toISOString(),
|
|
319
|
+
lastUpdated: now.toISOString(),
|
|
320
|
+
firstUserMessage: 'Test session',
|
|
321
|
+
isCurrentSession: false,
|
|
322
|
+
index: 1,
|
|
323
|
+
},
|
|
324
|
+
];
|
|
325
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
326
|
+
// Act
|
|
327
|
+
await deleteSession(mockConfig, 'invalid-id');
|
|
328
|
+
// Assert
|
|
329
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Invalid session identifier "invalid-id". Use --list-sessions to see available sessions.');
|
|
330
|
+
expect(mockDeleteSession).not.toHaveBeenCalled();
|
|
331
|
+
});
|
|
332
|
+
it('should display error for invalid session identifier (out of range)', async () => {
|
|
333
|
+
// Arrange
|
|
334
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
335
|
+
const mockSessions = [
|
|
336
|
+
{
|
|
337
|
+
id: 'session-1',
|
|
338
|
+
file: 'session-file-1',
|
|
339
|
+
fileName: 'session-file-1.json',
|
|
340
|
+
startTime: now.toISOString(),
|
|
341
|
+
lastUpdated: now.toISOString(),
|
|
342
|
+
firstUserMessage: 'Test session',
|
|
343
|
+
isCurrentSession: false,
|
|
344
|
+
index: 1,
|
|
345
|
+
},
|
|
346
|
+
];
|
|
347
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
348
|
+
// Act
|
|
349
|
+
await deleteSession(mockConfig, '999');
|
|
350
|
+
// Assert
|
|
351
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Invalid session identifier "999". Use --list-sessions to see available sessions.');
|
|
352
|
+
expect(mockDeleteSession).not.toHaveBeenCalled();
|
|
353
|
+
});
|
|
354
|
+
it('should display error for invalid session identifier (zero)', async () => {
|
|
355
|
+
// Arrange
|
|
356
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
357
|
+
const mockSessions = [
|
|
358
|
+
{
|
|
359
|
+
id: 'session-1',
|
|
360
|
+
file: 'session-file-1',
|
|
361
|
+
fileName: 'session-file-1.json',
|
|
362
|
+
startTime: now.toISOString(),
|
|
363
|
+
lastUpdated: now.toISOString(),
|
|
364
|
+
firstUserMessage: 'Test session',
|
|
365
|
+
isCurrentSession: false,
|
|
366
|
+
index: 1,
|
|
367
|
+
},
|
|
368
|
+
];
|
|
369
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
370
|
+
// Act
|
|
371
|
+
await deleteSession(mockConfig, '0');
|
|
372
|
+
// Assert
|
|
373
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Invalid session identifier "0". Use --list-sessions to see available sessions.');
|
|
374
|
+
expect(mockDeleteSession).not.toHaveBeenCalled();
|
|
375
|
+
});
|
|
376
|
+
it('should prevent deletion of current session', async () => {
|
|
377
|
+
// Arrange
|
|
378
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
379
|
+
const mockSessions = [
|
|
380
|
+
{
|
|
381
|
+
id: 'current-session-id',
|
|
382
|
+
file: 'current-session-file',
|
|
383
|
+
fileName: 'current-session-file.json',
|
|
384
|
+
startTime: now.toISOString(),
|
|
385
|
+
lastUpdated: now.toISOString(),
|
|
386
|
+
firstUserMessage: 'Current session',
|
|
387
|
+
isCurrentSession: true,
|
|
388
|
+
index: 1,
|
|
389
|
+
},
|
|
390
|
+
];
|
|
391
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
392
|
+
// Act - try to delete by index
|
|
393
|
+
await deleteSession(mockConfig, '1');
|
|
394
|
+
// Assert
|
|
395
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Cannot delete the current active session.');
|
|
396
|
+
expect(mockDeleteSession).not.toHaveBeenCalled();
|
|
397
|
+
});
|
|
398
|
+
it('should prevent deletion of current session by UUID', async () => {
|
|
399
|
+
// Arrange
|
|
400
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
401
|
+
const mockSessions = [
|
|
402
|
+
{
|
|
403
|
+
id: 'current-session-id',
|
|
404
|
+
file: 'current-session-file',
|
|
405
|
+
fileName: 'current-session-file.json',
|
|
406
|
+
startTime: now.toISOString(),
|
|
407
|
+
lastUpdated: now.toISOString(),
|
|
408
|
+
firstUserMessage: 'Current session',
|
|
409
|
+
isCurrentSession: true,
|
|
410
|
+
index: 1,
|
|
411
|
+
},
|
|
412
|
+
];
|
|
413
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
414
|
+
// Act - try to delete by UUID
|
|
415
|
+
await deleteSession(mockConfig, 'current-session-id');
|
|
416
|
+
// Assert
|
|
417
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Cannot delete the current active session.');
|
|
418
|
+
expect(mockDeleteSession).not.toHaveBeenCalled();
|
|
419
|
+
});
|
|
420
|
+
it('should handle deletion errors gracefully', async () => {
|
|
421
|
+
// Arrange
|
|
422
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
423
|
+
const mockSessions = [
|
|
424
|
+
{
|
|
425
|
+
id: 'session-1',
|
|
426
|
+
file: 'session-file-1',
|
|
427
|
+
fileName: 'session-file-1.json',
|
|
428
|
+
startTime: now.toISOString(),
|
|
429
|
+
lastUpdated: now.toISOString(),
|
|
430
|
+
firstUserMessage: 'Test session',
|
|
431
|
+
isCurrentSession: false,
|
|
432
|
+
index: 1,
|
|
433
|
+
},
|
|
434
|
+
];
|
|
435
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
436
|
+
mockDeleteSession.mockImplementation(() => {
|
|
437
|
+
throw new Error('File deletion failed');
|
|
438
|
+
});
|
|
439
|
+
// Act
|
|
440
|
+
await deleteSession(mockConfig, '1');
|
|
441
|
+
// Assert
|
|
442
|
+
expect(mockDeleteSession).toHaveBeenCalledWith('session-file-1');
|
|
443
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to delete session: File deletion failed');
|
|
444
|
+
});
|
|
445
|
+
it('should handle non-Error deletion failures', async () => {
|
|
446
|
+
// Arrange
|
|
447
|
+
const now = new Date('2025-01-20T12:00:00.000Z');
|
|
448
|
+
const mockSessions = [
|
|
449
|
+
{
|
|
450
|
+
id: 'session-1',
|
|
451
|
+
file: 'session-file-1',
|
|
452
|
+
fileName: 'session-file-1.json',
|
|
453
|
+
startTime: now.toISOString(),
|
|
454
|
+
lastUpdated: now.toISOString(),
|
|
455
|
+
firstUserMessage: 'Test session',
|
|
456
|
+
isCurrentSession: false,
|
|
457
|
+
index: 1,
|
|
458
|
+
},
|
|
459
|
+
];
|
|
460
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
461
|
+
mockDeleteSession.mockImplementation(() => {
|
|
462
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
463
|
+
throw 'Unknown error type';
|
|
464
|
+
});
|
|
465
|
+
// Act
|
|
466
|
+
await deleteSession(mockConfig, '1');
|
|
467
|
+
// Assert
|
|
468
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to delete session: Unknown error');
|
|
469
|
+
});
|
|
470
|
+
it('should sort sessions before finding by index', async () => {
|
|
471
|
+
// Arrange: Create sessions in non-chronological order
|
|
472
|
+
const session1Time = new Date('2025-01-18T12:00:00.000Z');
|
|
473
|
+
const session2Time = new Date('2025-01-19T12:00:00.000Z');
|
|
474
|
+
const session3Time = new Date('2025-01-20T12:00:00.000Z');
|
|
475
|
+
const mockSessions = [
|
|
476
|
+
{
|
|
477
|
+
id: 'session-3',
|
|
478
|
+
file: 'session-file-3',
|
|
479
|
+
fileName: 'session-file-3.json',
|
|
480
|
+
startTime: session3Time.toISOString(), // Newest
|
|
481
|
+
lastUpdated: session3Time.toISOString(),
|
|
482
|
+
firstUserMessage: 'Newest session',
|
|
483
|
+
isCurrentSession: false,
|
|
484
|
+
index: 3,
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
id: 'session-1',
|
|
488
|
+
file: 'session-file-1',
|
|
489
|
+
fileName: 'session-file-1.json',
|
|
490
|
+
startTime: session1Time.toISOString(), // Oldest
|
|
491
|
+
lastUpdated: session1Time.toISOString(),
|
|
492
|
+
firstUserMessage: 'Oldest session',
|
|
493
|
+
isCurrentSession: false,
|
|
494
|
+
index: 1,
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
id: 'session-2',
|
|
498
|
+
file: 'session-file-2',
|
|
499
|
+
fileName: 'session-file-2.json',
|
|
500
|
+
startTime: session2Time.toISOString(), // Middle
|
|
501
|
+
lastUpdated: session2Time.toISOString(),
|
|
502
|
+
firstUserMessage: 'Middle session',
|
|
503
|
+
isCurrentSession: false,
|
|
504
|
+
index: 2,
|
|
505
|
+
},
|
|
506
|
+
];
|
|
507
|
+
mockListSessions.mockResolvedValue(mockSessions);
|
|
508
|
+
mockDeleteSession.mockImplementation(() => { });
|
|
509
|
+
// Act - delete index 1 (should be oldest session after sorting)
|
|
510
|
+
await deleteSession(mockConfig, '1');
|
|
511
|
+
// Assert
|
|
512
|
+
expect(mockDeleteSession).toHaveBeenCalledWith('session-file-1');
|
|
513
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('Oldest session'));
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
//# sourceMappingURL=sessions.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.test.js","sourceRoot":"","sources":["../../../src/utils/sessions.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Writes to the real stdout, bypassing any monkey patching on process.stdout.write.
|
|
8
|
+
*/
|
|
9
|
+
export declare function writeToStdout(...args: Parameters<typeof process.stdout.write>): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Writes to the real stderr, bypassing any monkey patching on process.stderr.write.
|
|
12
|
+
*/
|
|
13
|
+
export declare function writeToStderr(...args: Parameters<typeof process.stderr.write>): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Monkey patches process.stdout.write and process.stderr.write to redirect output to the provided logger.
|
|
16
|
+
* This prevents stray output from libraries (or the app itself) from corrupting the UI.
|
|
17
|
+
* Returns a cleanup function that restores the original write methods.
|
|
18
|
+
*/
|
|
19
|
+
export declare function patchStdio(): () => void;
|
|
20
|
+
/**
|
|
21
|
+
* Creates proxies for process.stdout and process.stderr that use the real write methods
|
|
22
|
+
* (writeToStdout and writeToStderr) bypassing any monkey patching.
|
|
23
|
+
* This is used by Ink to render to the real output.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createInkStdio(): {
|
|
26
|
+
stdout: NodeJS.WriteStream & {
|
|
27
|
+
fd: 1;
|
|
28
|
+
};
|
|
29
|
+
stderr: NodeJS.WriteStream & {
|
|
30
|
+
fd: 2;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { coreEvents } from '@google/gemini-cli-core';
|
|
7
|
+
// Capture the original stdout and stderr write methods before any monkey patching occurs.
|
|
8
|
+
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
9
|
+
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
10
|
+
/**
|
|
11
|
+
* Writes to the real stdout, bypassing any monkey patching on process.stdout.write.
|
|
12
|
+
*/
|
|
13
|
+
export function writeToStdout(...args) {
|
|
14
|
+
return originalStdoutWrite(...args);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Writes to the real stderr, bypassing any monkey patching on process.stderr.write.
|
|
18
|
+
*/
|
|
19
|
+
export function writeToStderr(...args) {
|
|
20
|
+
return originalStderrWrite(...args);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Monkey patches process.stdout.write and process.stderr.write to redirect output to the provided logger.
|
|
24
|
+
* This prevents stray output from libraries (or the app itself) from corrupting the UI.
|
|
25
|
+
* Returns a cleanup function that restores the original write methods.
|
|
26
|
+
*/
|
|
27
|
+
export function patchStdio() {
|
|
28
|
+
const previousStdoutWrite = process.stdout.write;
|
|
29
|
+
const previousStderrWrite = process.stderr.write;
|
|
30
|
+
process.stdout.write = (chunk, encodingOrCb, cb) => {
|
|
31
|
+
const encoding = typeof encodingOrCb === 'string' ? encodingOrCb : undefined;
|
|
32
|
+
coreEvents.emitOutput(false, chunk, encoding);
|
|
33
|
+
const callback = typeof encodingOrCb === 'function' ? encodingOrCb : cb;
|
|
34
|
+
if (callback) {
|
|
35
|
+
callback();
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
};
|
|
39
|
+
process.stderr.write = (chunk, encodingOrCb, cb) => {
|
|
40
|
+
const encoding = typeof encodingOrCb === 'string' ? encodingOrCb : undefined;
|
|
41
|
+
coreEvents.emitOutput(true, chunk, encoding);
|
|
42
|
+
const callback = typeof encodingOrCb === 'function' ? encodingOrCb : cb;
|
|
43
|
+
if (callback) {
|
|
44
|
+
callback();
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
};
|
|
48
|
+
return () => {
|
|
49
|
+
process.stdout.write = previousStdoutWrite;
|
|
50
|
+
process.stderr.write = previousStderrWrite;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Creates proxies for process.stdout and process.stderr that use the real write methods
|
|
55
|
+
* (writeToStdout and writeToStderr) bypassing any monkey patching.
|
|
56
|
+
* This is used by Ink to render to the real output.
|
|
57
|
+
*/
|
|
58
|
+
export function createInkStdio() {
|
|
59
|
+
const inkStdout = new Proxy(process.stdout, {
|
|
60
|
+
get(target, prop, receiver) {
|
|
61
|
+
if (prop === 'write') {
|
|
62
|
+
return writeToStdout;
|
|
63
|
+
}
|
|
64
|
+
const value = Reflect.get(target, prop, receiver);
|
|
65
|
+
if (typeof value === 'function') {
|
|
66
|
+
return value.bind(target);
|
|
67
|
+
}
|
|
68
|
+
return value;
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
const inkStderr = new Proxy(process.stderr, {
|
|
72
|
+
get(target, prop, receiver) {
|
|
73
|
+
if (prop === 'write') {
|
|
74
|
+
return writeToStderr;
|
|
75
|
+
}
|
|
76
|
+
const value = Reflect.get(target, prop, receiver);
|
|
77
|
+
if (typeof value === 'function') {
|
|
78
|
+
return value.bind(target);
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
return { stdout: inkStdout, stderr: inkStderr };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/utils/stdio.ts"],"names":[],"mappings":"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"}
|