@google/gemini-cli 0.15.0-nightly.20251110.c0b766ad → 0.15.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.
Files changed (176) hide show
  1. package/dist/package.json +3 -3
  2. package/dist/src/config/config.d.ts +3 -0
  3. package/dist/src/config/config.js +31 -0
  4. package/dist/src/config/config.js.map +1 -1
  5. package/dist/src/config/config.test.js +20 -0
  6. package/dist/src/config/config.test.js.map +1 -1
  7. package/dist/src/config/extension-manager.js +13 -1
  8. package/dist/src/config/extension-manager.js.map +1 -1
  9. package/dist/src/config/extension.test.js +65 -0
  10. package/dist/src/config/extension.test.js.map +1 -1
  11. package/dist/src/config/settingsSchema.d.ts +10 -1
  12. package/dist/src/config/settingsSchema.js +10 -1
  13. package/dist/src/config/settingsSchema.js.map +1 -1
  14. package/dist/src/gemini.d.ts +2 -2
  15. package/dist/src/gemini.js +40 -4
  16. package/dist/src/gemini.js.map +1 -1
  17. package/dist/src/gemini.test.js +14 -7
  18. package/dist/src/gemini.test.js.map +1 -1
  19. package/dist/src/generated/git-commit.d.ts +2 -2
  20. package/dist/src/generated/git-commit.js +2 -2
  21. package/dist/src/generated/git-commit.js.map +1 -1
  22. package/dist/src/nonInteractiveCli.d.ts +3 -2
  23. package/dist/src/nonInteractiveCli.js +6 -1
  24. package/dist/src/nonInteractiveCli.js.map +1 -1
  25. package/dist/src/nonInteractiveCli.test.js +1 -0
  26. package/dist/src/nonInteractiveCli.test.js.map +1 -1
  27. package/dist/src/test-utils/render.d.ts +2 -1
  28. package/dist/src/test-utils/render.js +13 -3
  29. package/dist/src/test-utils/render.js.map +1 -1
  30. package/dist/src/ui/App.js +9 -1
  31. package/dist/src/ui/App.js.map +1 -1
  32. package/dist/src/ui/App.test.js +25 -1
  33. package/dist/src/ui/App.test.js.map +1 -1
  34. package/dist/src/ui/AppContainer.d.ts +2 -3
  35. package/dist/src/ui/AppContainer.js +22 -7
  36. package/dist/src/ui/AppContainer.js.map +1 -1
  37. package/dist/src/ui/AppContainer.test.js +354 -46
  38. package/dist/src/ui/AppContainer.test.js.map +1 -1
  39. package/dist/src/ui/commands/toolsCommand.js +4 -1
  40. package/dist/src/ui/commands/toolsCommand.js.map +1 -1
  41. package/dist/src/ui/components/AlternateBufferQuittingDisplay.d.ts +6 -0
  42. package/dist/src/ui/components/AlternateBufferQuittingDisplay.js +24 -0
  43. package/dist/src/ui/components/AlternateBufferQuittingDisplay.js.map +1 -0
  44. package/dist/src/ui/components/AlternateBufferQuittingDisplay.test.d.ts +6 -0
  45. package/dist/src/ui/components/AlternateBufferQuittingDisplay.test.js +101 -0
  46. package/dist/src/ui/components/AlternateBufferQuittingDisplay.test.js.map +1 -0
  47. package/dist/src/ui/components/Composer.js +11 -4
  48. package/dist/src/ui/components/Composer.js.map +1 -1
  49. package/dist/src/ui/components/CopyModeWarning.d.ts +7 -0
  50. package/dist/src/ui/components/CopyModeWarning.js +12 -0
  51. package/dist/src/ui/components/CopyModeWarning.js.map +1 -0
  52. package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
  53. package/dist/src/ui/components/Header.js +11 -1
  54. package/dist/src/ui/components/Header.js.map +1 -1
  55. package/dist/src/ui/components/Header.test.js +69 -14
  56. package/dist/src/ui/components/Header.test.js.map +1 -1
  57. package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
  58. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  59. package/dist/src/ui/components/HistoryItemDisplay.test.js +43 -41
  60. package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -1
  61. package/dist/src/ui/components/InputPrompt.d.ts +2 -0
  62. package/dist/src/ui/components/InputPrompt.js +14 -8
  63. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  64. package/dist/src/ui/components/MainContent.js +52 -15
  65. package/dist/src/ui/components/MainContent.js.map +1 -1
  66. package/dist/src/ui/components/ModelDialog.test.js +3 -0
  67. package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
  68. package/dist/src/ui/components/StickyHeader.d.ts +11 -0
  69. package/dist/src/ui/components/StickyHeader.js +5 -0
  70. package/dist/src/ui/components/StickyHeader.js.map +1 -0
  71. package/dist/src/ui/components/StickyHeader.test.d.ts +6 -0
  72. package/dist/src/ui/components/StickyHeader.test.js +17 -0
  73. package/dist/src/ui/components/StickyHeader.test.js.map +1 -0
  74. package/dist/src/ui/components/ThemeDialog.js +11 -3
  75. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  76. package/dist/src/ui/components/messages/DiffRenderer.js +129 -89
  77. package/dist/src/ui/components/messages/DiffRenderer.js.map +1 -1
  78. package/dist/src/ui/components/messages/DiffRenderer.test.js +107 -115
  79. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
  80. package/dist/src/ui/components/messages/GeminiMessage.js +3 -1
  81. package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
  82. package/dist/src/ui/components/messages/GeminiMessageContent.js +3 -1
  83. package/dist/src/ui/components/messages/GeminiMessageContent.js.map +1 -1
  84. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +152 -121
  85. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  86. package/dist/src/ui/components/messages/ToolGroupMessage.js +5 -7
  87. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  88. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +1 -5
  89. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
  90. package/dist/src/ui/components/messages/ToolMessage.js +39 -16
  91. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  92. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js +33 -4
  93. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js.map +1 -1
  94. package/dist/src/ui/components/messages/UserMessage.d.ts +1 -0
  95. package/dist/src/ui/components/messages/UserMessage.js +2 -2
  96. package/dist/src/ui/components/messages/UserMessage.js.map +1 -1
  97. package/dist/src/ui/components/shared/ScrollableList.test.js +61 -24
  98. package/dist/src/ui/components/shared/ScrollableList.test.js.map +1 -1
  99. package/dist/src/ui/components/shared/VirtualizedList.js +1 -1
  100. package/dist/src/ui/components/shared/VirtualizedList.js.map +1 -1
  101. package/dist/src/ui/components/shared/text-buffer.d.ts +2 -8
  102. package/dist/src/ui/components/shared/text-buffer.js +1 -1
  103. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  104. package/dist/src/ui/components/shared/text-buffer.test.js +35 -0
  105. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
  106. package/dist/src/ui/constants.d.ts +1 -0
  107. package/dist/src/ui/constants.js +5 -0
  108. package/dist/src/ui/constants.js.map +1 -1
  109. package/dist/src/ui/contexts/KeypressContext.d.ts +1 -0
  110. package/dist/src/ui/contexts/KeypressContext.js +10 -0
  111. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  112. package/dist/src/ui/contexts/UIStateContext.d.ts +1 -0
  113. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  114. package/dist/src/ui/hooks/atCommandProcessor.test.js +1 -1
  115. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
  116. package/dist/src/ui/hooks/useAlternateBuffer.d.ts +6 -0
  117. package/dist/src/ui/hooks/useAlternateBuffer.js +11 -0
  118. package/dist/src/ui/hooks/useAlternateBuffer.js.map +1 -0
  119. package/dist/src/ui/hooks/useGeminiStream.test.js +4 -0
  120. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
  121. package/dist/src/ui/hooks/useKeypress.test.js +3 -1
  122. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
  123. package/dist/src/ui/hooks/usePromptCompletion.js +2 -9
  124. package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
  125. package/dist/src/ui/hooks/useSelectionList.test.js +3 -0
  126. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  127. package/dist/src/ui/hooks/useSessionBrowser.d.ts +18 -0
  128. package/dist/src/ui/hooks/useSessionBrowser.js +152 -0
  129. package/dist/src/ui/hooks/useSessionBrowser.js.map +1 -0
  130. package/dist/src/ui/hooks/useSessionBrowser.test.d.ts +6 -0
  131. package/dist/src/ui/hooks/useSessionBrowser.test.js +544 -0
  132. package/dist/src/ui/hooks/useSessionBrowser.test.js.map +1 -0
  133. package/dist/src/ui/hooks/useSessionResume.d.ts +30 -0
  134. package/dist/src/ui/hooks/useSessionResume.js +56 -0
  135. package/dist/src/ui/hooks/useSessionResume.js.map +1 -0
  136. package/dist/src/ui/hooks/useSessionResume.test.d.ts +6 -0
  137. package/dist/src/ui/hooks/useSessionResume.test.js +325 -0
  138. package/dist/src/ui/hooks/useSessionResume.test.js.map +1 -0
  139. package/dist/src/ui/hooks/useToolScheduler.test.js +1 -0
  140. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  141. package/dist/src/ui/hooks/vim.js +1 -0
  142. package/dist/src/ui/hooks/vim.js.map +1 -1
  143. package/dist/src/ui/hooks/vim.test.js +1 -0
  144. package/dist/src/ui/hooks/vim.test.js.map +1 -1
  145. package/dist/src/ui/keyMatchers.test.js +1 -0
  146. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  147. package/dist/src/ui/layouts/DefaultAppLayout.js +9 -3
  148. package/dist/src/ui/layouts/DefaultAppLayout.js.map +1 -1
  149. package/dist/src/ui/utils/CodeColorizer.d.ts +11 -3
  150. package/dist/src/ui/utils/CodeColorizer.js +18 -9
  151. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  152. package/dist/src/ui/utils/MarkdownDisplay.js +32 -6
  153. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  154. package/dist/src/ui/utils/textUtils.d.ts +1 -0
  155. package/dist/src/ui/utils/textUtils.js +3 -2
  156. package/dist/src/ui/utils/textUtils.js.map +1 -1
  157. package/dist/src/ui/utils/textUtils.test.js +7 -1
  158. package/dist/src/ui/utils/textUtils.test.js.map +1 -1
  159. package/dist/src/ui/utils/ui-sizing.js +9 -3
  160. package/dist/src/ui/utils/ui-sizing.js.map +1 -1
  161. package/dist/src/utils/cleanup.test.js +1 -1
  162. package/dist/src/utils/cleanup.test.js.map +1 -1
  163. package/dist/src/utils/sessionCleanup.test.js +76 -0
  164. package/dist/src/utils/sessionCleanup.test.js.map +1 -1
  165. package/dist/src/utils/sessionUtils.d.ts +54 -0
  166. package/dist/src/utils/sessionUtils.js +141 -1
  167. package/dist/src/utils/sessionUtils.js.map +1 -1
  168. package/dist/src/utils/sessionUtils.test.d.ts +6 -0
  169. package/dist/src/utils/sessionUtils.test.js +260 -0
  170. package/dist/src/utils/sessionUtils.test.js.map +1 -0
  171. package/dist/src/utils/sessions.d.ts +8 -0
  172. package/dist/src/utils/sessions.js +64 -0
  173. package/dist/src/utils/sessions.js.map +1 -0
  174. package/dist/tsconfig.tsbuildinfo +1 -1
  175. package/package.json +4 -4
  176. package/dist/google-gemini-cli-0.15.0-nightly.20251107.b8eeb553.tgz +0 -0
@@ -3,18 +3,27 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
+ import type { Config, ConversationRecord, MessageRecord } from '@google/gemini-cli-core';
6
7
  /**
7
8
  * Session information for display and selection purposes.
8
9
  */
9
10
  export interface SessionInfo {
10
11
  /** Unique session identifier (filename without .json) */
11
12
  id: string;
13
+ /** Filename without extension */
14
+ file: string;
12
15
  /** Full filename including .json extension */
13
16
  fileName: string;
17
+ /** ISO timestamp when session started */
18
+ startTime: string;
14
19
  /** ISO timestamp when session was last updated */
15
20
  lastUpdated: string;
21
+ /** Cleaned first user message content */
22
+ firstUserMessage: string;
16
23
  /** Whether this is the currently active session */
17
24
  isCurrentSession: boolean;
25
+ /** Display index in the list */
26
+ index: number;
18
27
  }
19
28
  /**
20
29
  * Represents a session file, which may be valid or corrupted.
@@ -25,6 +34,21 @@ export interface SessionFileEntry {
25
34
  /** Parsed session info if valid, null if corrupted */
26
35
  sessionInfo: SessionInfo | null;
27
36
  }
37
+ /**
38
+ * Result of resolving a session selection argument.
39
+ */
40
+ export interface SessionSelectionResult {
41
+ sessionPath: string;
42
+ sessionData: ConversationRecord;
43
+ }
44
+ /**
45
+ * Extracts the first meaningful user message from conversation messages.
46
+ */
47
+ export declare const extractFirstUserMessage: (messages: MessageRecord[]) => string;
48
+ /**
49
+ * Formats a timestamp as relative time (e.g., "2 hours ago", "3 days ago").
50
+ */
51
+ export declare const formatRelativeTime: (timestamp: string) => string;
28
52
  /**
29
53
  * Loads all session files (including corrupted ones) from the chats directory.
30
54
  * @returns Array of session file entries, with sessionInfo null for corrupted files
@@ -35,3 +59,33 @@ export declare const getAllSessionFiles: (chatsDir: string, currentSessionId?: s
35
59
  * Corrupted files are automatically filtered out.
36
60
  */
37
61
  export declare const getSessionFiles: (chatsDir: string, currentSessionId?: string) => Promise<SessionInfo[]>;
62
+ /**
63
+ * Utility class for session discovery and selection.
64
+ */
65
+ export declare class SessionSelector {
66
+ private config;
67
+ constructor(config: Config);
68
+ /**
69
+ * Lists all available sessions for the current project.
70
+ */
71
+ listSessions(): Promise<SessionInfo[]>;
72
+ /**
73
+ * Finds a session by identifier (UUID or numeric index).
74
+ *
75
+ * @param identifier - Can be a full UUID or an index number (1-based)
76
+ * @returns Promise resolving to the found SessionInfo
77
+ * @throws Error if the session is not found or identifier is invalid
78
+ */
79
+ findSession(identifier: string): Promise<SessionInfo>;
80
+ /**
81
+ * Resolves a resume argument to a specific session.
82
+ *
83
+ * @param resumeArg - Can be "latest", a full UUID, or an index number (1-based)
84
+ * @returns Promise resolving to session selection result
85
+ */
86
+ resolveSession(resumeArg: string): Promise<SessionSelectionResult>;
87
+ /**
88
+ * Loads session data for a selected session.
89
+ */
90
+ private selectSession;
91
+ }
@@ -3,9 +3,48 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { SESSION_FILE_PREFIX, } from '@google/gemini-cli-core';
6
+ import { SESSION_FILE_PREFIX, partListUnionToString, } from '@google/gemini-cli-core';
7
7
  import * as fs from 'node:fs/promises';
8
8
  import path from 'node:path';
9
+ /**
10
+ * Extracts the first meaningful user message from conversation messages.
11
+ */
12
+ export const extractFirstUserMessage = (messages) => {
13
+ const userMessage = messages.find((msg) => {
14
+ const content = partListUnionToString(msg.content);
15
+ return msg.type === 'user' && content?.trim() && content !== '/resume';
16
+ });
17
+ if (!userMessage) {
18
+ return 'Empty conversation';
19
+ }
20
+ // Truncate long messages for display
21
+ const content = partListUnionToString(userMessage.content).trim();
22
+ return content.length > 100 ? content.slice(0, 97) + '...' : content;
23
+ };
24
+ /**
25
+ * Formats a timestamp as relative time (e.g., "2 hours ago", "3 days ago").
26
+ */
27
+ export const formatRelativeTime = (timestamp) => {
28
+ const now = new Date();
29
+ const time = new Date(timestamp);
30
+ const diffMs = now.getTime() - time.getTime();
31
+ const diffSeconds = Math.floor(diffMs / 1000);
32
+ const diffMinutes = Math.floor(diffSeconds / 60);
33
+ const diffHours = Math.floor(diffMinutes / 60);
34
+ const diffDays = Math.floor(diffHours / 24);
35
+ if (diffDays > 0) {
36
+ return `${diffDays} day${diffDays === 1 ? '' : 's'} ago`;
37
+ }
38
+ else if (diffHours > 0) {
39
+ return `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`;
40
+ }
41
+ else if (diffMinutes > 0) {
42
+ return `${diffMinutes} minute${diffMinutes === 1 ? '' : 's'} ago`;
43
+ }
44
+ else {
45
+ return 'Just now';
46
+ }
47
+ };
9
48
  /**
10
49
  * Loads all session files (including corrupted ones) from the chats directory.
11
50
  * @returns Array of session file entries, with sessionInfo null for corrupted files
@@ -29,14 +68,19 @@ export const getAllSessionFiles = async (chatsDir, currentSessionId) => {
29
68
  // Missing required fields - treat as corrupted
30
69
  return { fileName: file, sessionInfo: null };
31
70
  }
71
+ const firstUserMessage = extractFirstUserMessage(content.messages);
32
72
  const isCurrentSession = currentSessionId
33
73
  ? file.includes(currentSessionId.slice(0, 8))
34
74
  : false;
35
75
  const sessionInfo = {
36
76
  id: content.sessionId,
77
+ file: file.replace('.json', ''),
37
78
  fileName: file,
79
+ startTime: content.startTime,
38
80
  lastUpdated: content.lastUpdated,
81
+ firstUserMessage,
39
82
  isCurrentSession,
83
+ index: 0, // Will be set after sorting valid sessions
40
84
  };
41
85
  return { fileName: file, sessionInfo };
42
86
  }
@@ -66,6 +110,102 @@ export const getSessionFiles = async (chatsDir, currentSessionId) => {
66
110
  const validSessions = allFiles
67
111
  .filter((entry) => entry.sessionInfo !== null)
68
112
  .map((entry) => entry.sessionInfo);
113
+ // Sort by startTime (oldest first) for stable session numbering
114
+ validSessions.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
115
+ // Set the correct 1-based indexes after sorting
116
+ validSessions.forEach((session, index) => {
117
+ session.index = index + 1;
118
+ });
69
119
  return validSessions;
70
120
  };
121
+ /**
122
+ * Utility class for session discovery and selection.
123
+ */
124
+ export class SessionSelector {
125
+ config;
126
+ constructor(config) {
127
+ this.config = config;
128
+ }
129
+ /**
130
+ * Lists all available sessions for the current project.
131
+ */
132
+ async listSessions() {
133
+ const chatsDir = path.join(this.config.storage.getProjectTempDir(), 'chats');
134
+ return getSessionFiles(chatsDir, this.config.getSessionId());
135
+ }
136
+ /**
137
+ * Finds a session by identifier (UUID or numeric index).
138
+ *
139
+ * @param identifier - Can be a full UUID or an index number (1-based)
140
+ * @returns Promise resolving to the found SessionInfo
141
+ * @throws Error if the session is not found or identifier is invalid
142
+ */
143
+ async findSession(identifier) {
144
+ const sessions = await this.listSessions();
145
+ if (sessions.length === 0) {
146
+ throw new Error('No previous sessions found for this project.');
147
+ }
148
+ // Sort by startTime (oldest first, so newest sessions get highest numbers)
149
+ const sortedSessions = sessions.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
150
+ // Try to find by UUID first
151
+ const sessionByUuid = sortedSessions.find((session) => session.id === identifier);
152
+ if (sessionByUuid) {
153
+ return sessionByUuid;
154
+ }
155
+ // Parse as index number (1-based) - only allow numeric indexes
156
+ const index = parseInt(identifier, 10);
157
+ if (!isNaN(index) &&
158
+ index.toString() === identifier &&
159
+ index > 0 &&
160
+ index <= sortedSessions.length) {
161
+ return sortedSessions[index - 1];
162
+ }
163
+ throw new Error(`Invalid session identifier "${identifier}". Use --list-sessions to see available sessions.`);
164
+ }
165
+ /**
166
+ * Resolves a resume argument to a specific session.
167
+ *
168
+ * @param resumeArg - Can be "latest", a full UUID, or an index number (1-based)
169
+ * @returns Promise resolving to session selection result
170
+ */
171
+ async resolveSession(resumeArg) {
172
+ let selectedSession;
173
+ if (resumeArg === 'latest') {
174
+ const sessions = await this.listSessions();
175
+ if (sessions.length === 0) {
176
+ throw new Error('No previous sessions found for this project.');
177
+ }
178
+ // Sort by startTime (oldest first, so newest sessions get highest numbers)
179
+ sessions.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
180
+ selectedSession = sessions[sessions.length - 1];
181
+ }
182
+ else {
183
+ try {
184
+ selectedSession = await this.findSession(resumeArg);
185
+ }
186
+ catch (error) {
187
+ // Re-throw with more detailed message for resume command
188
+ throw new Error(`Invalid session identifier "${resumeArg}". Use --list-sessions to see available sessions, then use --resume {number}, --resume {uuid}, or --resume latest. Error: ${error}`);
189
+ }
190
+ }
191
+ return this.selectSession(selectedSession);
192
+ }
193
+ /**
194
+ * Loads session data for a selected session.
195
+ */
196
+ async selectSession(sessionInfo) {
197
+ const chatsDir = path.join(this.config.storage.getProjectTempDir(), 'chats');
198
+ const sessionPath = path.join(chatsDir, sessionInfo.fileName);
199
+ try {
200
+ const sessionData = JSON.parse(await fs.readFile(sessionPath, 'utf8'));
201
+ return {
202
+ sessionPath,
203
+ sessionData,
204
+ };
205
+ }
206
+ catch (error) {
207
+ throw new Error(`Failed to load session ${sessionInfo.id}: ${error instanceof Error ? error.message : 'Unknown error'}`);
208
+ }
209
+ }
210
+ }
71
211
  //# sourceMappingURL=sessionUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessionUtils.js","sourceRoot":"","sources":["../../../src/utils/sessionUtils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessionUtils.js","sourceRoot":"","sources":["../../../src/utils/sessionUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,260 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
+ import { SessionSelector, extractFirstUserMessage, formatRelativeTime, } from './sessionUtils.js';
8
+ import { SESSION_FILE_PREFIX } from '@google/gemini-cli-core';
9
+ import * as fs from 'node:fs/promises';
10
+ import path from 'node:path';
11
+ import { randomUUID } from 'node:crypto';
12
+ describe('SessionSelector', () => {
13
+ let tmpDir;
14
+ let config;
15
+ beforeEach(async () => {
16
+ // Create a temporary directory for testing
17
+ tmpDir = path.join(process.cwd(), '.tmp-test-sessions');
18
+ await fs.mkdir(tmpDir, { recursive: true });
19
+ // Mock config
20
+ config = {
21
+ storage: {
22
+ getProjectTempDir: () => tmpDir,
23
+ },
24
+ getSessionId: () => 'current-session-id',
25
+ };
26
+ });
27
+ afterEach(async () => {
28
+ // Clean up test files
29
+ try {
30
+ await fs.rm(tmpDir, { recursive: true, force: true });
31
+ }
32
+ catch (_error) {
33
+ // Ignore cleanup errors
34
+ }
35
+ });
36
+ it('should resolve session by UUID', async () => {
37
+ const sessionId1 = randomUUID();
38
+ const sessionId2 = randomUUID();
39
+ // Create test session files
40
+ const chatsDir = path.join(tmpDir, 'chats');
41
+ await fs.mkdir(chatsDir, { recursive: true });
42
+ const session1 = {
43
+ sessionId: sessionId1,
44
+ projectHash: 'test-hash',
45
+ startTime: '2024-01-01T10:00:00.000Z',
46
+ lastUpdated: '2024-01-01T10:30:00.000Z',
47
+ messages: [
48
+ {
49
+ type: 'user',
50
+ content: 'Test message 1',
51
+ id: 'msg1',
52
+ timestamp: '2024-01-01T10:00:00.000Z',
53
+ },
54
+ ],
55
+ };
56
+ const session2 = {
57
+ sessionId: sessionId2,
58
+ projectHash: 'test-hash',
59
+ startTime: '2024-01-01T11:00:00.000Z',
60
+ lastUpdated: '2024-01-01T11:30:00.000Z',
61
+ messages: [
62
+ {
63
+ type: 'user',
64
+ content: 'Test message 2',
65
+ id: 'msg2',
66
+ timestamp: '2024-01-01T11:00:00.000Z',
67
+ },
68
+ ],
69
+ };
70
+ await fs.writeFile(path.join(chatsDir, `${SESSION_FILE_PREFIX}2024-01-01T10-00-${sessionId1.slice(0, 8)}.json`), JSON.stringify(session1, null, 2));
71
+ await fs.writeFile(path.join(chatsDir, `${SESSION_FILE_PREFIX}2024-01-01T11-00-${sessionId2.slice(0, 8)}.json`), JSON.stringify(session2, null, 2));
72
+ const sessionSelector = new SessionSelector(config);
73
+ // Test resolving by UUID
74
+ const result1 = await sessionSelector.resolveSession(sessionId1);
75
+ expect(result1.sessionData.sessionId).toBe(sessionId1);
76
+ expect(result1.sessionData.messages[0].content).toBe('Test message 1');
77
+ const result2 = await sessionSelector.resolveSession(sessionId2);
78
+ expect(result2.sessionData.sessionId).toBe(sessionId2);
79
+ expect(result2.sessionData.messages[0].content).toBe('Test message 2');
80
+ });
81
+ it('should resolve session by index', async () => {
82
+ const sessionId1 = randomUUID();
83
+ const sessionId2 = randomUUID();
84
+ // Create test session files
85
+ const chatsDir = path.join(tmpDir, 'chats');
86
+ await fs.mkdir(chatsDir, { recursive: true });
87
+ const session1 = {
88
+ sessionId: sessionId1,
89
+ projectHash: 'test-hash',
90
+ startTime: '2024-01-01T10:00:00.000Z',
91
+ lastUpdated: '2024-01-01T10:30:00.000Z',
92
+ messages: [
93
+ {
94
+ type: 'user',
95
+ content: 'First session',
96
+ id: 'msg1',
97
+ timestamp: '2024-01-01T10:00:00.000Z',
98
+ },
99
+ ],
100
+ };
101
+ const session2 = {
102
+ sessionId: sessionId2,
103
+ projectHash: 'test-hash',
104
+ startTime: '2024-01-01T11:00:00.000Z',
105
+ lastUpdated: '2024-01-01T11:30:00.000Z',
106
+ messages: [
107
+ {
108
+ type: 'user',
109
+ content: 'Second session',
110
+ id: 'msg2',
111
+ timestamp: '2024-01-01T11:00:00.000Z',
112
+ },
113
+ ],
114
+ };
115
+ await fs.writeFile(path.join(chatsDir, `${SESSION_FILE_PREFIX}2024-01-01T10-00-${sessionId1.slice(0, 8)}.json`), JSON.stringify(session1, null, 2));
116
+ await fs.writeFile(path.join(chatsDir, `${SESSION_FILE_PREFIX}2024-01-01T11-00-${sessionId2.slice(0, 8)}.json`), JSON.stringify(session2, null, 2));
117
+ const sessionSelector = new SessionSelector(config);
118
+ // Test resolving by index (1-based)
119
+ const result1 = await sessionSelector.resolveSession('1');
120
+ expect(result1.sessionData.messages[0].content).toBe('First session');
121
+ const result2 = await sessionSelector.resolveSession('2');
122
+ expect(result2.sessionData.messages[0].content).toBe('Second session');
123
+ });
124
+ it('should resolve latest session', async () => {
125
+ const sessionId1 = randomUUID();
126
+ const sessionId2 = randomUUID();
127
+ // Create test session files
128
+ const chatsDir = path.join(tmpDir, 'chats');
129
+ await fs.mkdir(chatsDir, { recursive: true });
130
+ const session1 = {
131
+ sessionId: sessionId1,
132
+ projectHash: 'test-hash',
133
+ startTime: '2024-01-01T10:00:00.000Z',
134
+ lastUpdated: '2024-01-01T10:30:00.000Z',
135
+ messages: [
136
+ {
137
+ type: 'user',
138
+ content: 'First session',
139
+ id: 'msg1',
140
+ timestamp: '2024-01-01T10:00:00.000Z',
141
+ },
142
+ ],
143
+ };
144
+ const session2 = {
145
+ sessionId: sessionId2,
146
+ projectHash: 'test-hash',
147
+ startTime: '2024-01-01T11:00:00.000Z',
148
+ lastUpdated: '2024-01-01T11:30:00.000Z',
149
+ messages: [
150
+ {
151
+ type: 'user',
152
+ content: 'Latest session',
153
+ id: 'msg2',
154
+ timestamp: '2024-01-01T11:00:00.000Z',
155
+ },
156
+ ],
157
+ };
158
+ await fs.writeFile(path.join(chatsDir, `${SESSION_FILE_PREFIX}2024-01-01T10-00-${sessionId1.slice(0, 8)}.json`), JSON.stringify(session1, null, 2));
159
+ await fs.writeFile(path.join(chatsDir, `${SESSION_FILE_PREFIX}2024-01-01T11-00-${sessionId2.slice(0, 8)}.json`), JSON.stringify(session2, null, 2));
160
+ const sessionSelector = new SessionSelector(config);
161
+ // Test resolving latest
162
+ const result = await sessionSelector.resolveSession('latest');
163
+ expect(result.sessionData.messages[0].content).toBe('Latest session');
164
+ });
165
+ it('should throw error for invalid session identifier', async () => {
166
+ const sessionId1 = randomUUID();
167
+ // Create test session files
168
+ const chatsDir = path.join(tmpDir, 'chats');
169
+ await fs.mkdir(chatsDir, { recursive: true });
170
+ const session1 = {
171
+ sessionId: sessionId1,
172
+ projectHash: 'test-hash',
173
+ startTime: '2024-01-01T10:00:00.000Z',
174
+ lastUpdated: '2024-01-01T10:30:00.000Z',
175
+ messages: [
176
+ {
177
+ type: 'user',
178
+ content: 'Test message 1',
179
+ id: 'msg1',
180
+ timestamp: '2024-01-01T10:00:00.000Z',
181
+ },
182
+ ],
183
+ };
184
+ await fs.writeFile(path.join(chatsDir, `${SESSION_FILE_PREFIX}2024-01-01T10-00-${sessionId1.slice(0, 8)}.json`), JSON.stringify(session1, null, 2));
185
+ const sessionSelector = new SessionSelector(config);
186
+ await expect(sessionSelector.resolveSession('invalid-uuid')).rejects.toThrow('Invalid session identifier "invalid-uuid"');
187
+ await expect(sessionSelector.resolveSession('999')).rejects.toThrow('Invalid session identifier "999"');
188
+ });
189
+ });
190
+ describe('extractFirstUserMessage', () => {
191
+ it('should extract first non-resume user message', () => {
192
+ const messages = [
193
+ {
194
+ type: 'user',
195
+ content: '/resume',
196
+ id: 'msg1',
197
+ timestamp: '2024-01-01T10:00:00.000Z',
198
+ },
199
+ {
200
+ type: 'user',
201
+ content: 'Hello world',
202
+ id: 'msg2',
203
+ timestamp: '2024-01-01T10:01:00.000Z',
204
+ },
205
+ ];
206
+ expect(extractFirstUserMessage(messages)).toBe('Hello world');
207
+ });
208
+ it('should truncate long messages', () => {
209
+ const longMessage = 'a'.repeat(150);
210
+ const messages = [
211
+ {
212
+ type: 'user',
213
+ content: longMessage,
214
+ id: 'msg1',
215
+ timestamp: '2024-01-01T10:00:00.000Z',
216
+ },
217
+ ];
218
+ const result = extractFirstUserMessage(messages);
219
+ expect(result).toBe('a'.repeat(97) + '...');
220
+ expect(result.length).toBe(100);
221
+ });
222
+ it('should return "Empty conversation" for no user messages', () => {
223
+ const messages = [
224
+ {
225
+ type: 'gemini',
226
+ content: 'Hello',
227
+ id: 'msg1',
228
+ timestamp: '2024-01-01T10:00:00.000Z',
229
+ },
230
+ ];
231
+ expect(extractFirstUserMessage(messages)).toBe('Empty conversation');
232
+ });
233
+ });
234
+ describe('formatRelativeTime', () => {
235
+ it('should format time correctly', () => {
236
+ const now = new Date();
237
+ // 5 minutes ago
238
+ const fiveMinutesAgo = new Date(now.getTime() - 5 * 60 * 1000);
239
+ expect(formatRelativeTime(fiveMinutesAgo.toISOString())).toBe('5 minutes ago');
240
+ // 1 minute ago
241
+ const oneMinuteAgo = new Date(now.getTime() - 1 * 60 * 1000);
242
+ expect(formatRelativeTime(oneMinuteAgo.toISOString())).toBe('1 minute ago');
243
+ // 2 hours ago
244
+ const twoHoursAgo = new Date(now.getTime() - 2 * 60 * 60 * 1000);
245
+ expect(formatRelativeTime(twoHoursAgo.toISOString())).toBe('2 hours ago');
246
+ // 1 hour ago
247
+ const oneHourAgo = new Date(now.getTime() - 1 * 60 * 60 * 1000);
248
+ expect(formatRelativeTime(oneHourAgo.toISOString())).toBe('1 hour ago');
249
+ // 3 days ago
250
+ const threeDaysAgo = new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000);
251
+ expect(formatRelativeTime(threeDaysAgo.toISOString())).toBe('3 days ago');
252
+ // 1 day ago
253
+ const oneDayAgo = new Date(now.getTime() - 1 * 24 * 60 * 60 * 1000);
254
+ expect(formatRelativeTime(oneDayAgo.toISOString())).toBe('1 day ago');
255
+ // Just now (within 60 seconds)
256
+ const thirtySecondsAgo = new Date(now.getTime() - 30 * 1000);
257
+ expect(formatRelativeTime(thirtySecondsAgo.toISOString())).toBe('Just now');
258
+ });
259
+ });
260
+ //# sourceMappingURL=sessionUtils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionUtils.test.js","sourceRoot":"","sources":["../../../src/utils/sessionUtils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type Config } from '@google/gemini-cli-core';
7
+ export declare function listSessions(config: Config): Promise<void>;
8
+ export declare function deleteSession(config: Config, sessionIndex: string): Promise<void>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ChatRecordingService } from '@google/gemini-cli-core';
7
+ import { formatRelativeTime, SessionSelector, } from './sessionUtils.js';
8
+ export async function listSessions(config) {
9
+ const sessionSelector = new SessionSelector(config);
10
+ const sessions = await sessionSelector.listSessions();
11
+ if (sessions.length === 0) {
12
+ console.log('No previous sessions found for this project.');
13
+ return;
14
+ }
15
+ console.log(`\nAvailable sessions for this project (${sessions.length}):\n`);
16
+ sessions
17
+ .sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime())
18
+ .forEach((session, index) => {
19
+ const current = session.isCurrentSession ? ', current' : '';
20
+ const time = formatRelativeTime(session.lastUpdated);
21
+ console.log(` ${index + 1}. ${session.firstUserMessage} (${time}${current}) [${session.id}]`);
22
+ });
23
+ }
24
+ export async function deleteSession(config, sessionIndex) {
25
+ const sessionSelector = new SessionSelector(config);
26
+ const sessions = await sessionSelector.listSessions();
27
+ if (sessions.length === 0) {
28
+ console.error('No sessions found for this project.');
29
+ return;
30
+ }
31
+ // Sort sessions by start time to match list-sessions ordering
32
+ const sortedSessions = sessions.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
33
+ let sessionToDelete;
34
+ // Try to find by UUID first
35
+ const sessionByUuid = sortedSessions.find((session) => session.id === sessionIndex);
36
+ if (sessionByUuid) {
37
+ sessionToDelete = sessionByUuid;
38
+ }
39
+ else {
40
+ // Parse session index
41
+ const index = parseInt(sessionIndex, 10);
42
+ if (isNaN(index) || index < 1 || index > sessions.length) {
43
+ console.error(`Invalid session identifier "${sessionIndex}". Use --list-sessions to see available sessions.`);
44
+ return;
45
+ }
46
+ sessionToDelete = sortedSessions[index - 1];
47
+ }
48
+ // Prevent deleting the current session
49
+ if (sessionToDelete.isCurrentSession) {
50
+ console.error('Cannot delete the current active session.');
51
+ return;
52
+ }
53
+ try {
54
+ // Use ChatRecordingService to delete the session
55
+ const chatRecordingService = new ChatRecordingService(config);
56
+ chatRecordingService.deleteSession(sessionToDelete.file);
57
+ const time = formatRelativeTime(sessionToDelete.lastUpdated);
58
+ console.log(`Deleted session ${sessionToDelete.index}: ${sessionToDelete.firstUserMessage} (${time})`);
59
+ }
60
+ catch (error) {
61
+ console.error(`Failed to delete session: ${error instanceof Error ? error.message : 'Unknown error'}`);
62
+ }
63
+ }
64
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/utils/sessions.ts"],"names":[],"mappings":"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"}