@google/gemini-cli-core 0.39.0-preview.2 → 0.40.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 (259) hide show
  1. package/dist/docs/changelogs/index.md +21 -0
  2. package/dist/docs/changelogs/latest.md +253 -407
  3. package/dist/docs/changelogs/preview.md +236 -247
  4. package/dist/docs/cli/auto-memory.md +143 -0
  5. package/dist/docs/cli/enterprise.md +1 -1
  6. package/dist/docs/cli/plan-mode.md +3 -1
  7. package/dist/docs/cli/settings.md +29 -25
  8. package/dist/docs/cli/system-prompt.md +6 -6
  9. package/dist/docs/cli/telemetry.md +18 -11
  10. package/dist/docs/cli/tutorials/memory-management.md +2 -0
  11. package/dist/docs/get-started/{authentication.md → authentication.mdx} +139 -93
  12. package/dist/docs/get-started/index.md +3 -2
  13. package/dist/docs/get-started/installation.mdx +201 -0
  14. package/dist/docs/index.md +2 -2
  15. package/dist/docs/reference/configuration.md +88 -12
  16. package/dist/docs/reference/policy-engine.md +18 -12
  17. package/dist/docs/reference/tools.md +22 -0
  18. package/dist/docs/sidebar.json +13 -1
  19. package/dist/docs/tools/mcp-resources.md +44 -0
  20. package/dist/docs/tools/mcp-server.md +2 -1
  21. package/dist/docs/tools/tracker.md +61 -0
  22. package/dist/src/agents/agent-tool.js +1 -0
  23. package/dist/src/agents/agent-tool.js.map +1 -1
  24. package/dist/src/agents/agentLoader.d.ts +4 -4
  25. package/dist/src/agents/generalist-agent.js +3 -2
  26. package/dist/src/agents/generalist-agent.js.map +1 -1
  27. package/dist/src/agents/local-executor.js +4 -1
  28. package/dist/src/agents/local-executor.js.map +1 -1
  29. package/dist/src/agents/registry.js +0 -8
  30. package/dist/src/agents/registry.js.map +1 -1
  31. package/dist/src/agents/skill-extraction-agent.d.ts +3 -2
  32. package/dist/src/agents/skill-extraction-agent.js +72 -67
  33. package/dist/src/agents/skill-extraction-agent.js.map +1 -1
  34. package/dist/src/agents/skill-extraction-agent.test.js +54 -0
  35. package/dist/src/agents/skill-extraction-agent.test.js.map +1 -0
  36. package/dist/src/config/config.d.ts +21 -6
  37. package/dist/src/config/config.js +103 -19
  38. package/dist/src/config/config.js.map +1 -1
  39. package/dist/src/config/config.test.js +262 -6
  40. package/dist/src/config/config.test.js.map +1 -1
  41. package/dist/src/config/constants.d.ts +1 -0
  42. package/dist/src/config/constants.js +2 -0
  43. package/dist/src/config/constants.js.map +1 -1
  44. package/dist/src/config/memory.js +1 -1
  45. package/dist/src/config/memory.js.map +1 -1
  46. package/dist/src/config/path-validation.test.js +15 -6
  47. package/dist/src/config/path-validation.test.js.map +1 -1
  48. package/dist/src/config/projectRegistry.js +113 -32
  49. package/dist/src/config/projectRegistry.js.map +1 -1
  50. package/dist/src/config/projectRegistry.test.js +51 -0
  51. package/dist/src/config/projectRegistry.test.js.map +1 -1
  52. package/dist/src/config/storage.d.ts +3 -1
  53. package/dist/src/config/storage.js +6 -0
  54. package/dist/src/config/storage.js.map +1 -1
  55. package/dist/src/config/storage.test.js +12 -0
  56. package/dist/src/config/storage.test.js.map +1 -1
  57. package/dist/src/core/contentGenerator.d.ts +8 -1
  58. package/dist/src/core/contentGenerator.js +46 -4
  59. package/dist/src/core/contentGenerator.js.map +1 -1
  60. package/dist/src/core/contentGenerator.test.js +174 -8
  61. package/dist/src/core/contentGenerator.test.js.map +1 -1
  62. package/dist/src/core/geminiChat.test.js +1 -0
  63. package/dist/src/core/geminiChat.test.js.map +1 -1
  64. package/dist/src/core/geminiChat_network_retry.test.js +42 -0
  65. package/dist/src/core/geminiChat_network_retry.test.js.map +1 -1
  66. package/dist/src/core/localLiteRtLmClient.js +2 -0
  67. package/dist/src/core/localLiteRtLmClient.js.map +1 -1
  68. package/dist/src/core/localLiteRtLmClient.test.js +7 -0
  69. package/dist/src/core/localLiteRtLmClient.test.js.map +1 -1
  70. package/dist/src/core/loggingContentGenerator.js +3 -0
  71. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  72. package/dist/src/core/loggingContentGenerator.test.js +1 -0
  73. package/dist/src/core/loggingContentGenerator.test.js.map +1 -1
  74. package/dist/src/core/prompts.d.ts +1 -1
  75. package/dist/src/core/prompts.js +2 -2
  76. package/dist/src/core/prompts.js.map +1 -1
  77. package/dist/src/core/prompts.test.js +2 -2
  78. package/dist/src/core/prompts.test.js.map +1 -1
  79. package/dist/src/generated/git-commit.d.ts +2 -2
  80. package/dist/src/generated/git-commit.js +2 -2
  81. package/dist/src/ide/ide-client.js +3 -4
  82. package/dist/src/ide/ide-client.js.map +1 -1
  83. package/dist/src/policy/policies/read-only.toml +4 -1
  84. package/dist/src/policy/policy-engine.js +4 -0
  85. package/dist/src/policy/policy-engine.js.map +1 -1
  86. package/dist/src/policy/policy-engine.test.js +25 -0
  87. package/dist/src/policy/policy-engine.test.js.map +1 -1
  88. package/dist/src/policy/toml-loader.test.js +5 -0
  89. package/dist/src/policy/toml-loader.test.js.map +1 -1
  90. package/dist/src/prompts/promptProvider.d.ts +1 -1
  91. package/dist/src/prompts/promptProvider.js +15 -7
  92. package/dist/src/prompts/promptProvider.js.map +1 -1
  93. package/dist/src/prompts/promptProvider.test.js +31 -1
  94. package/dist/src/prompts/promptProvider.test.js.map +1 -1
  95. package/dist/src/prompts/snippets-memory-v2.test.js +94 -0
  96. package/dist/src/prompts/snippets-memory-v2.test.js.map +1 -0
  97. package/dist/src/prompts/snippets.d.ts +19 -1
  98. package/dist/src/prompts/snippets.js +24 -3
  99. package/dist/src/prompts/snippets.js.map +1 -1
  100. package/dist/src/prompts/snippets.legacy.d.ts +6 -1
  101. package/dist/src/prompts/snippets.legacy.js +10 -3
  102. package/dist/src/prompts/snippets.legacy.js.map +1 -1
  103. package/dist/src/sandbox/linux/LinuxSandboxManager.js +16 -2
  104. package/dist/src/sandbox/linux/LinuxSandboxManager.js.map +1 -1
  105. package/dist/src/sandbox/linux/bwrapArgsBuilder.js +64 -36
  106. package/dist/src/sandbox/linux/bwrapArgsBuilder.js.map +1 -1
  107. package/dist/src/sandbox/linux/bwrapArgsBuilder.test.js +3 -3
  108. package/dist/src/sandbox/linux/bwrapArgsBuilder.test.js.map +1 -1
  109. package/dist/src/sandbox/macos/MacOsSandboxManager.js +13 -1
  110. package/dist/src/sandbox/macos/MacOsSandboxManager.js.map +1 -1
  111. package/dist/src/sandbox/macos/seatbeltArgsBuilder.js +61 -42
  112. package/dist/src/sandbox/macos/seatbeltArgsBuilder.js.map +1 -1
  113. package/dist/src/sandbox/windows/WindowsSandboxManager.js +12 -1
  114. package/dist/src/sandbox/windows/WindowsSandboxManager.js.map +1 -1
  115. package/dist/src/scheduler/policy.js +1 -2
  116. package/dist/src/scheduler/policy.js.map +1 -1
  117. package/dist/src/scheduler/policy.test.js +35 -2
  118. package/dist/src/scheduler/policy.test.js.map +1 -1
  119. package/dist/src/scheduler/scheduler.js +1 -0
  120. package/dist/src/scheduler/scheduler.js.map +1 -1
  121. package/dist/src/scheduler/scheduler.test.js +2 -0
  122. package/dist/src/scheduler/scheduler.test.js.map +1 -1
  123. package/dist/src/scheduler/scheduler_hooks.test.js +1 -0
  124. package/dist/src/scheduler/scheduler_hooks.test.js.map +1 -1
  125. package/dist/src/scheduler/scheduler_parallel.test.js +1 -0
  126. package/dist/src/scheduler/scheduler_parallel.test.js.map +1 -1
  127. package/dist/src/scheduler/tool-executor.js +1 -0
  128. package/dist/src/scheduler/tool-executor.js.map +1 -1
  129. package/dist/src/services/chatRecordingService.d.ts +1 -0
  130. package/dist/src/services/chatRecordingService.js +48 -19
  131. package/dist/src/services/chatRecordingService.js.map +1 -1
  132. package/dist/src/services/memoryService.d.ts +15 -1
  133. package/dist/src/services/memoryService.js +276 -57
  134. package/dist/src/services/memoryService.js.map +1 -1
  135. package/dist/src/services/memoryService.test.js +296 -2
  136. package/dist/src/services/memoryService.test.js.map +1 -1
  137. package/dist/src/services/sandboxManager.integration.test.js +204 -0
  138. package/dist/src/services/sandboxManager.integration.test.js.map +1 -1
  139. package/dist/src/services/sandboxManager.js +16 -0
  140. package/dist/src/services/sandboxManager.js.map +1 -1
  141. package/dist/src/services/sessionSummaryUtils.d.ts +1 -1
  142. package/dist/src/services/sessionSummaryUtils.js +111 -38
  143. package/dist/src/services/sessionSummaryUtils.js.map +1 -1
  144. package/dist/src/services/sessionSummaryUtils.test.js +204 -51
  145. package/dist/src/services/sessionSummaryUtils.test.js.map +1 -1
  146. package/dist/src/services/shellExecutionService.js +7 -1
  147. package/dist/src/services/shellExecutionService.js.map +1 -1
  148. package/dist/src/telemetry/config.js +3 -0
  149. package/dist/src/telemetry/config.js.map +1 -1
  150. package/dist/src/telemetry/conseca-logger.test.js +1 -0
  151. package/dist/src/telemetry/conseca-logger.test.js.map +1 -1
  152. package/dist/src/telemetry/loggers.test.js +72 -4
  153. package/dist/src/telemetry/loggers.test.js.map +1 -1
  154. package/dist/src/telemetry/memory-monitor.d.ts +1 -0
  155. package/dist/src/telemetry/memory-monitor.js +8 -1
  156. package/dist/src/telemetry/memory-monitor.js.map +1 -1
  157. package/dist/src/telemetry/memory-monitor.test.js +6 -1
  158. package/dist/src/telemetry/memory-monitor.test.js.map +1 -1
  159. package/dist/src/telemetry/trace.d.ts +1 -0
  160. package/dist/src/telemetry/trace.js +33 -13
  161. package/dist/src/telemetry/trace.js.map +1 -1
  162. package/dist/src/telemetry/trace.test.js +50 -10
  163. package/dist/src/telemetry/trace.test.js.map +1 -1
  164. package/dist/src/telemetry/types.js +11 -4
  165. package/dist/src/telemetry/types.js.map +1 -1
  166. package/dist/src/tools/definitions/base-declarations.d.ts +2 -0
  167. package/dist/src/tools/definitions/base-declarations.js +3 -0
  168. package/dist/src/tools/definitions/base-declarations.js.map +1 -1
  169. package/dist/src/tools/definitions/coreTools.d.ts +3 -1
  170. package/dist/src/tools/definitions/coreTools.js +13 -1
  171. package/dist/src/tools/definitions/coreTools.js.map +1 -1
  172. package/dist/src/tools/definitions/model-family-sets/default-legacy.js +29 -1
  173. package/dist/src/tools/definitions/model-family-sets/default-legacy.js.map +1 -1
  174. package/dist/src/tools/definitions/model-family-sets/gemini-3.js +29 -1
  175. package/dist/src/tools/definitions/model-family-sets/gemini-3.js.map +1 -1
  176. package/dist/src/tools/definitions/types.d.ts +2 -0
  177. package/dist/src/tools/get-internal-docs.js +5 -2
  178. package/dist/src/tools/get-internal-docs.js.map +1 -1
  179. package/dist/src/tools/list-mcp-resources.d.ts +24 -0
  180. package/dist/src/tools/list-mcp-resources.js +74 -0
  181. package/dist/src/tools/list-mcp-resources.js.map +1 -0
  182. package/dist/src/tools/list-mcp-resources.test.d.ts +6 -0
  183. package/dist/src/tools/list-mcp-resources.test.js +79 -0
  184. package/dist/src/tools/list-mcp-resources.test.js.map +1 -0
  185. package/dist/src/tools/mcp-client-manager.d.ts +3 -1
  186. package/dist/src/tools/mcp-client-manager.js +24 -1
  187. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  188. package/dist/src/tools/mcp-client-manager.test.js +43 -0
  189. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  190. package/dist/src/tools/memoryTool.d.ts +2 -1
  191. package/dist/src/tools/memoryTool.js +42 -13
  192. package/dist/src/tools/memoryTool.js.map +1 -1
  193. package/dist/src/tools/memoryTool.test.js +23 -3
  194. package/dist/src/tools/memoryTool.test.js.map +1 -1
  195. package/dist/src/tools/read-mcp-resource.d.ts +25 -0
  196. package/dist/src/tools/read-mcp-resource.js +120 -0
  197. package/dist/src/tools/read-mcp-resource.js.map +1 -0
  198. package/dist/src/tools/read-mcp-resource.test.d.ts +6 -0
  199. package/dist/src/tools/read-mcp-resource.test.js +110 -0
  200. package/dist/src/tools/read-mcp-resource.test.js.map +1 -0
  201. package/dist/src/tools/ripGrep.d.ts +3 -2
  202. package/dist/src/tools/ripGrep.js +25 -54
  203. package/dist/src/tools/ripGrep.js.map +1 -1
  204. package/dist/src/tools/ripGrep.test.js +73 -131
  205. package/dist/src/tools/ripGrep.test.js.map +1 -1
  206. package/dist/src/tools/shell.js +38 -12
  207. package/dist/src/tools/shell.js.map +1 -1
  208. package/dist/src/tools/shell.test.js +410 -25
  209. package/dist/src/tools/shell.test.js.map +1 -1
  210. package/dist/src/tools/tool-error.d.ts +1 -0
  211. package/dist/src/tools/tool-error.js +1 -0
  212. package/dist/src/tools/tool-error.js.map +1 -1
  213. package/dist/src/tools/tool-names.d.ts +4 -4
  214. package/dist/src/tools/tool-names.js +6 -2
  215. package/dist/src/tools/tool-names.js.map +1 -1
  216. package/dist/src/tools/tool-registry.js +8 -1
  217. package/dist/src/tools/tool-registry.js.map +1 -1
  218. package/dist/src/utils/filesearch/fileSearch.d.ts +2 -0
  219. package/dist/src/utils/filesearch/fileSearch.js +97 -6
  220. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  221. package/dist/src/utils/filesearch/fileSearch.test.js +54 -0
  222. package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
  223. package/dist/src/utils/filesearch/fileWatcher.d.ts +25 -0
  224. package/dist/src/utils/filesearch/fileWatcher.js +86 -0
  225. package/dist/src/utils/filesearch/fileWatcher.js.map +1 -0
  226. package/dist/src/utils/filesearch/fileWatcher.test.d.ts +6 -0
  227. package/dist/src/utils/filesearch/fileWatcher.test.js +142 -0
  228. package/dist/src/utils/filesearch/fileWatcher.test.js.map +1 -0
  229. package/dist/src/utils/gitIgnoreParser.js +1 -1
  230. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  231. package/dist/src/utils/ignoreFileParser.js +1 -1
  232. package/dist/src/utils/ignoreFileParser.js.map +1 -1
  233. package/dist/src/utils/memoryDiscovery.js +15 -5
  234. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  235. package/dist/src/utils/retry.js +18 -6
  236. package/dist/src/utils/retry.js.map +1 -1
  237. package/dist/src/utils/retry.test.js +30 -0
  238. package/dist/src/utils/retry.test.js.map +1 -1
  239. package/dist/src/utils/shell-utils.d.ts +1 -0
  240. package/dist/src/utils/shell-utils.js +106 -0
  241. package/dist/src/utils/shell-utils.js.map +1 -1
  242. package/dist/tsconfig.tsbuildinfo +1 -1
  243. package/package.json +5 -3
  244. package/vendor/ripgrep/rg-darwin-arm64 +0 -0
  245. package/vendor/ripgrep/rg-darwin-x64 +0 -0
  246. package/vendor/ripgrep/rg-linux-arm64 +0 -0
  247. package/vendor/ripgrep/rg-linux-x64 +0 -0
  248. package/vendor/ripgrep/rg-win32-x64.exe +0 -0
  249. package/dist/docs/get-started/installation.md +0 -181
  250. package/dist/google-gemini-cli-core-0.39.0-preview.1.tgz +0 -0
  251. package/dist/src/agents/memory-manager-agent.d.ts +0 -25
  252. package/dist/src/agents/memory-manager-agent.js +0 -138
  253. package/dist/src/agents/memory-manager-agent.js.map +0 -1
  254. package/dist/src/agents/memory-manager-agent.test.js +0 -123
  255. package/dist/src/agents/memory-manager-agent.test.js.map +0 -1
  256. package/dist/src/prompts/snippets-memory-manager.test.js +0 -31
  257. package/dist/src/prompts/snippets-memory-manager.test.js.map +0 -1
  258. /package/dist/src/agents/{memory-manager-agent.test.d.ts → skill-extraction-agent.test.d.ts} +0 -0
  259. /package/dist/src/prompts/{snippets-memory-manager.test.d.ts → snippets-memory-v2.test.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"sandboxManager.js","sourceRoot":"","sources":["../../../src/services/sandboxManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sandboxManager.js","sourceRoot":"","sources":["../../../src/services/sandboxManager.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import type { Config } from '../config/config.js';
7
7
  /**
8
- * Finds the most recently created session that needs a summary.
8
+ * Finds the most recently updated previous session that still needs a summary.
9
9
  * Returns the path if it needs a summary, null otherwise.
10
10
  */
11
11
  export declare function getPreviousSession(config: Config): Promise<string | null>;
@@ -6,18 +6,55 @@
6
6
  import { SessionSummaryService } from './sessionSummaryService.js';
7
7
  import { BaseLlmClient } from '../core/baseLlmClient.js';
8
8
  import { debugLogger } from '../utils/debugLogger.js';
9
- import { SESSION_FILE_PREFIX, } from './chatRecordingService.js';
9
+ import { SESSION_FILE_PREFIX, loadConversationRecord, } from './chatRecordingService.js';
10
10
  import fs from 'node:fs/promises';
11
11
  import path from 'node:path';
12
12
  const MIN_MESSAGES_FOR_SUMMARY = 1;
13
+ function isSupportedSessionFile(fileName) {
14
+ return (fileName.startsWith(SESSION_FILE_PREFIX) &&
15
+ (fileName.endsWith('.json') || fileName.endsWith('.jsonl')));
16
+ }
17
+ async function listSessionFileCandidates(chatsDir) {
18
+ const allFiles = await fs.readdir(chatsDir);
19
+ const candidates = [];
20
+ for (const fileName of allFiles) {
21
+ if (!isSupportedSessionFile(fileName))
22
+ continue;
23
+ const filePath = path.join(chatsDir, fileName);
24
+ try {
25
+ const stat = await fs.stat(filePath);
26
+ if (!stat.isFile())
27
+ continue;
28
+ candidates.push({ filePath, mtimeMs: stat.mtimeMs });
29
+ }
30
+ catch {
31
+ // Skip files that disappeared between readdir and stat.
32
+ }
33
+ }
34
+ candidates.sort((a, b) => {
35
+ const mtimeDelta = b.mtimeMs - a.mtimeMs;
36
+ if (mtimeDelta !== 0) {
37
+ return mtimeDelta;
38
+ }
39
+ return path.basename(b.filePath).localeCompare(path.basename(a.filePath));
40
+ });
41
+ return candidates;
42
+ }
43
+ function getSessionTimestampMs(session) {
44
+ if (!session.lastUpdated)
45
+ return 0;
46
+ const parsed = Date.parse(session.lastUpdated);
47
+ return Number.isNaN(parsed) ? 0 : parsed;
48
+ }
13
49
  /**
14
50
  * Generates and saves a summary for a session file.
15
51
  */
16
52
  async function generateAndSaveSummary(config, sessionPath) {
17
- // Read session file
18
- const content = await fs.readFile(sessionPath, 'utf-8');
19
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
20
- const conversation = JSON.parse(content);
53
+ const conversation = await loadConversationRecord(sessionPath);
54
+ if (!conversation) {
55
+ debugLogger.debug(`[SessionSummary] Could not read session ${sessionPath}`);
56
+ return;
57
+ }
21
58
  // Skip if summary already exists
22
59
  if (conversation.summary) {
23
60
  debugLogger.debug(`[SessionSummary] Summary already exists for ${sessionPath}, skipping`);
@@ -44,23 +81,37 @@ async function generateAndSaveSummary(config, sessionPath) {
44
81
  debugLogger.warn(`[SessionSummary] Failed to generate summary for ${sessionPath}`);
45
82
  return;
46
83
  }
47
- // Re-read the file before writing to handle race conditions
48
- const freshContent = await fs.readFile(sessionPath, 'utf-8');
49
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
50
- const freshConversation = JSON.parse(freshContent);
84
+ // Re-read the file before writing to handle race conditions. For JSONL we
85
+ // only need the metadata; for legacy JSON we need the full record so we can
86
+ // round-trip the messages back to disk.
87
+ const isJsonl = sessionPath.endsWith('.jsonl');
88
+ const freshConversation = await loadConversationRecord(sessionPath, {
89
+ metadataOnly: isJsonl,
90
+ });
91
+ if (!freshConversation) {
92
+ debugLogger.debug(`[SessionSummary] Could not re-read ${sessionPath}`);
93
+ return;
94
+ }
51
95
  // Check if summary was added by another process
52
96
  if (freshConversation.summary) {
53
97
  debugLogger.debug(`[SessionSummary] Summary was added by another process for ${sessionPath}`);
54
98
  return;
55
99
  }
56
- // Add summary and write back
57
- freshConversation.summary = summary;
58
- freshConversation.lastUpdated = new Date().toISOString();
59
- await fs.writeFile(sessionPath, JSON.stringify(freshConversation, null, 2));
100
+ if (isJsonl) {
101
+ await fs.appendFile(sessionPath, `${JSON.stringify({ $set: { summary } })}\n`);
102
+ }
103
+ else {
104
+ const lastUpdated = freshConversation.lastUpdated;
105
+ await fs.writeFile(sessionPath, JSON.stringify({
106
+ ...freshConversation,
107
+ summary,
108
+ lastUpdated,
109
+ }, null, 2));
110
+ }
60
111
  debugLogger.debug(`[SessionSummary] Saved summary for ${sessionPath}: "${summary}"`);
61
112
  }
62
113
  /**
63
- * Finds the most recently created session that needs a summary.
114
+ * Finds the most recently updated previous session that still needs a summary.
64
115
  * Returns the path if it needs a summary, null otherwise.
65
116
  */
66
117
  export async function getPreviousSession(config) {
@@ -74,39 +125,61 @@ export async function getPreviousSession(config) {
74
125
  debugLogger.debug('[SessionSummary] No chats directory found');
75
126
  return null;
76
127
  }
77
- // List session files
78
- const allFiles = await fs.readdir(chatsDir);
79
- const sessionFiles = allFiles.filter((f) => f.startsWith(SESSION_FILE_PREFIX) && f.endsWith('.json'));
128
+ const sessionFiles = await listSessionFileCandidates(chatsDir);
80
129
  if (sessionFiles.length === 0) {
81
130
  debugLogger.debug('[SessionSummary] No session files found');
82
131
  return null;
83
132
  }
84
- // Sort by filename descending (most recently created first)
85
- // Filename format: session-YYYY-MM-DDTHH-MM-XXXXXXXX.json
86
- sessionFiles.sort((a, b) => b.localeCompare(a));
87
- // Check the most recently created session
88
- const mostRecentFile = sessionFiles[0];
89
- const filePath = path.join(chatsDir, mostRecentFile);
90
- try {
91
- const content = await fs.readFile(filePath, 'utf-8');
92
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
93
- const conversation = JSON.parse(content);
94
- if (conversation.summary) {
95
- debugLogger.debug('[SessionSummary] Most recent session already has summary');
96
- return null;
133
+ let bestPreviousSession = null;
134
+ for (const { filePath, mtimeMs } of sessionFiles) {
135
+ const bestTimestamp = bestPreviousSession
136
+ ? getSessionTimestampMs(bestPreviousSession.conversation)
137
+ : null;
138
+ if (bestPreviousSession &&
139
+ bestTimestamp !== null &&
140
+ bestTimestamp > 0 &&
141
+ mtimeMs < bestTimestamp) {
142
+ break;
97
143
  }
98
- // Only generate summaries for sessions with more than 1 user message
99
- const userMessageCount = conversation.messages.filter((m) => m.type === 'user').length;
100
- if (userMessageCount <= MIN_MESSAGES_FOR_SUMMARY) {
101
- debugLogger.debug(`[SessionSummary] Most recent session has ${userMessageCount} user message(s), skipping (need more than ${MIN_MESSAGES_FOR_SUMMARY})`);
102
- return null;
144
+ try {
145
+ const conversation = await loadConversationRecord(filePath, {
146
+ metadataOnly: true,
147
+ });
148
+ if (!conversation)
149
+ continue;
150
+ if (conversation.sessionId === config.getSessionId())
151
+ continue;
152
+ if (conversation.summary)
153
+ continue;
154
+ // Only generate summaries for sessions with more than 1 user message.
155
+ // `loadConversationRecord` populates `userMessageCount` in metadataOnly
156
+ // mode; fall back to scanning messages for the legacy fallback path.
157
+ const userMessageCount = conversation.userMessageCount ??
158
+ conversation.messages.filter((message) => message.type === 'user')
159
+ .length;
160
+ if (userMessageCount <= MIN_MESSAGES_FOR_SUMMARY) {
161
+ continue;
162
+ }
163
+ if (!bestPreviousSession ||
164
+ getSessionTimestampMs(conversation) >
165
+ getSessionTimestampMs(bestPreviousSession.conversation) ||
166
+ (getSessionTimestampMs(conversation) ===
167
+ getSessionTimestampMs(bestPreviousSession.conversation) &&
168
+ path
169
+ .basename(filePath)
170
+ .localeCompare(path.basename(bestPreviousSession.filePath)) > 0)) {
171
+ bestPreviousSession = { filePath, conversation };
172
+ }
173
+ }
174
+ catch {
175
+ // Ignore unreadable session files
103
176
  }
104
- return filePath;
105
177
  }
106
- catch {
107
- debugLogger.debug('[SessionSummary] Could not read most recent session');
178
+ if (!bestPreviousSession) {
179
+ debugLogger.debug('[SessionSummary] No previous session needs summary generation');
108
180
  return null;
109
181
  }
182
+ return bestPreviousSession.filePath;
110
183
  }
111
184
  catch (error) {
112
185
  debugLogger.debug(`[SessionSummary] Error finding previous session: ${error instanceof Error ? error.message : String(error)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"sessionSummaryUtils.js","sourceRoot":"","sources":["../../../src/services/sessionSummaryUtils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessionSummaryUtils.js","sourceRoot":"","sources":["../../../src/services/sessionSummaryUtils.ts"],"names":[],"mappings":"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"}
@@ -5,11 +5,10 @@
5
5
  */
6
6
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
7
  import { generateSummary, getPreviousSession } from './sessionSummaryUtils.js';
8
+ import * as chatRecordingService from './chatRecordingService.js';
8
9
  import * as fs from 'node:fs/promises';
9
10
  import * as path from 'node:path';
10
- // Mock fs/promises
11
- vi.mock('node:fs/promises');
12
- const mockReaddir = fs.readdir;
11
+ import * as os from 'node:os';
13
12
  // Mock the SessionSummaryService module
14
13
  vi.mock('./sessionSummaryService.js', () => ({
15
14
  SessionSummaryService: vi.fn().mockImplementation(() => ({
@@ -20,118 +19,272 @@ vi.mock('./sessionSummaryService.js', () => ({
20
19
  vi.mock('../core/baseLlmClient.js', () => ({
21
20
  BaseLlmClient: vi.fn(),
22
21
  }));
23
- // Helper to create a session with N user messages
24
- function createSessionWithUserMessages(count, options = {}) {
22
+ vi.mock('./chatRecordingService.js', async () => {
23
+ const actual = await vi.importActual('./chatRecordingService.js');
24
+ return {
25
+ ...actual,
26
+ loadConversationRecord: vi.fn(actual.loadConversationRecord),
27
+ };
28
+ });
29
+ function buildLegacySessionJson(fixture) {
25
30
  return JSON.stringify({
26
- sessionId: options.sessionId ?? 'session-id',
27
- summary: options.summary,
28
- messages: Array.from({ length: count }, (_, i) => ({
31
+ sessionId: fixture.sessionId ?? 'session-id',
32
+ projectHash: 'abc123',
33
+ startTime: fixture.startTime ?? '2024-01-01T00:00:00Z',
34
+ lastUpdated: fixture.lastUpdated ?? '2024-01-01T00:00:00Z',
35
+ summary: fixture.summary,
36
+ messages: Array.from({ length: fixture.userMessageCount }, (_, i) => ({
29
37
  id: String(i + 1),
38
+ timestamp: '2024-01-01T00:00:00Z',
30
39
  type: 'user',
31
40
  content: [{ text: `Message ${i + 1}` }],
32
41
  })),
33
42
  });
34
43
  }
44
+ function buildJsonlSession(fixture) {
45
+ const metadata = {
46
+ sessionId: fixture.sessionId ?? 'session-id',
47
+ projectHash: 'abc123',
48
+ startTime: fixture.startTime ?? '2024-01-01T00:00:00Z',
49
+ lastUpdated: fixture.lastUpdated ?? '2024-01-01T00:00:00Z',
50
+ ...(fixture.summary !== undefined ? { summary: fixture.summary } : {}),
51
+ };
52
+ const lines = [JSON.stringify(metadata)];
53
+ for (let i = 0; i < fixture.userMessageCount; i++) {
54
+ lines.push(JSON.stringify({
55
+ id: String(i + 1),
56
+ timestamp: '2024-01-01T00:00:00Z',
57
+ type: 'user',
58
+ content: [{ text: `Message ${i + 1}` }],
59
+ }));
60
+ }
61
+ return lines.join('\n') + '\n';
62
+ }
63
+ async function writeSession(chatsDir, fileName, contents) {
64
+ const filePath = path.join(chatsDir, fileName);
65
+ await fs.writeFile(filePath, contents);
66
+ return filePath;
67
+ }
68
+ async function setSessionMtime(filePath, timestamp) {
69
+ const date = new Date(timestamp);
70
+ await fs.utimes(filePath, date, date);
71
+ }
35
72
  describe('sessionSummaryUtils', () => {
73
+ let tmpDir;
74
+ let projectTempDir;
75
+ let chatsDir;
36
76
  let mockConfig;
37
77
  let mockContentGenerator;
38
78
  let mockGenerateSummary;
39
79
  beforeEach(async () => {
40
80
  vi.clearAllMocks();
41
- // Setup mock content generator
81
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'session-summary-utils-'));
82
+ projectTempDir = path.join(tmpDir, 'project');
83
+ chatsDir = path.join(projectTempDir, 'chats');
84
+ await fs.mkdir(chatsDir, { recursive: true });
42
85
  mockContentGenerator = {};
43
- // Setup mock config
44
86
  mockConfig = {
45
87
  getContentGenerator: vi.fn().mockReturnValue(mockContentGenerator),
88
+ getSessionId: vi.fn().mockReturnValue('current-session'),
46
89
  storage: {
47
- getProjectTempDir: vi.fn().mockReturnValue('/tmp/project'),
90
+ getProjectTempDir: vi.fn().mockReturnValue(projectTempDir),
48
91
  },
49
92
  };
50
- // Setup mock generateSummary function
51
93
  mockGenerateSummary = vi.fn().mockResolvedValue('Add dark mode to the app');
52
- // Import the mocked module to access the constructor
53
94
  const { SessionSummaryService } = await import('./sessionSummaryService.js');
54
95
  SessionSummaryService.mockImplementation(() => ({
55
96
  generateSummary: mockGenerateSummary,
56
97
  }));
57
98
  });
58
- afterEach(() => {
99
+ afterEach(async () => {
59
100
  vi.restoreAllMocks();
101
+ await fs.rm(tmpDir, { recursive: true, force: true });
60
102
  });
61
103
  describe('getPreviousSession', () => {
62
104
  it('should return null if chats directory does not exist', async () => {
63
- vi.mocked(fs.access).mockRejectedValue(new Error('ENOENT'));
105
+ await fs.rm(chatsDir, { recursive: true, force: true });
64
106
  const result = await getPreviousSession(mockConfig);
65
107
  expect(result).toBeNull();
66
108
  });
67
109
  it('should return null if no session files exist', async () => {
68
- vi.mocked(fs.access).mockResolvedValue(undefined);
69
- mockReaddir.mockResolvedValue([]);
70
110
  const result = await getPreviousSession(mockConfig);
71
111
  expect(result).toBeNull();
72
112
  });
73
113
  it('should return null if most recent session already has summary', async () => {
74
- vi.mocked(fs.access).mockResolvedValue(undefined);
75
- mockReaddir.mockResolvedValue(['session-2024-01-01T10-00-abc12345.json']);
76
- vi.mocked(fs.readFile).mockResolvedValue(createSessionWithUserMessages(5, { summary: 'Existing summary' }));
114
+ await writeSession(chatsDir, 'session-2024-01-01T10-00-abc12345.json', buildLegacySessionJson({
115
+ userMessageCount: 5,
116
+ summary: 'Existing summary',
117
+ }));
77
118
  const result = await getPreviousSession(mockConfig);
78
119
  expect(result).toBeNull();
79
120
  });
80
121
  it('should return null if most recent session has 1 or fewer user messages', async () => {
81
- vi.mocked(fs.access).mockResolvedValue(undefined);
82
- mockReaddir.mockResolvedValue(['session-2024-01-01T10-00-abc12345.json']);
83
- vi.mocked(fs.readFile).mockResolvedValue(createSessionWithUserMessages(1));
122
+ await writeSession(chatsDir, 'session-2024-01-01T10-00-abc12345.json', buildLegacySessionJson({ userMessageCount: 1 }));
84
123
  const result = await getPreviousSession(mockConfig);
85
124
  expect(result).toBeNull();
86
125
  });
87
126
  it('should return path if most recent session has more than 1 user message and no summary', async () => {
88
- vi.mocked(fs.access).mockResolvedValue(undefined);
89
- mockReaddir.mockResolvedValue(['session-2024-01-01T10-00-abc12345.json']);
90
- vi.mocked(fs.readFile).mockResolvedValue(createSessionWithUserMessages(2));
127
+ const filePath = await writeSession(chatsDir, 'session-2024-01-01T10-00-abc12345.json', buildLegacySessionJson({ userMessageCount: 2 }));
91
128
  const result = await getPreviousSession(mockConfig);
92
- expect(result).toBe(path.join('/tmp/project', 'chats', 'session-2024-01-01T10-00-abc12345.json'));
129
+ expect(result).toBe(filePath);
93
130
  });
94
- it('should select most recently created session by filename', async () => {
95
- vi.mocked(fs.access).mockResolvedValue(undefined);
96
- mockReaddir.mockResolvedValue([
97
- 'session-2024-01-01T10-00-older000.json',
98
- 'session-2024-01-02T10-00-newer000.json',
99
- ]);
100
- vi.mocked(fs.readFile).mockResolvedValue(createSessionWithUserMessages(2));
131
+ it('should select most recently updated session', async () => {
132
+ await writeSession(chatsDir, 'session-2024-01-01T10-00-older000.json', buildLegacySessionJson({
133
+ userMessageCount: 2,
134
+ lastUpdated: '2024-01-01T10:00:00Z',
135
+ }));
136
+ const newerPath = await writeSession(chatsDir, 'session-2024-01-02T10-00-newer000.json', buildLegacySessionJson({
137
+ userMessageCount: 2,
138
+ lastUpdated: '2024-01-02T10:00:00Z',
139
+ }));
101
140
  const result = await getPreviousSession(mockConfig);
102
- expect(result).toBe(path.join('/tmp/project', 'chats', 'session-2024-01-02T10-00-newer000.json'));
141
+ expect(result).toBe(newerPath);
103
142
  });
104
- it('should return null if most recent session file is corrupted', async () => {
105
- vi.mocked(fs.access).mockResolvedValue(undefined);
106
- mockReaddir.mockResolvedValue(['session-2024-01-01T10-00-abc12345.json']);
107
- vi.mocked(fs.readFile).mockResolvedValue('invalid json');
143
+ it('should ignore corrupted session files', async () => {
144
+ await writeSession(chatsDir, 'session-2024-01-01T10-00-abc12345.json', 'invalid json');
108
145
  const result = await getPreviousSession(mockConfig);
109
146
  expect(result).toBeNull();
110
147
  });
148
+ it('should support JSONL sessions and sort by lastUpdated instead of filename', async () => {
149
+ await writeSession(chatsDir, 'session-2024-01-02T10-00-older000.jsonl', buildJsonlSession({
150
+ userMessageCount: 2,
151
+ lastUpdated: '2024-01-01T10:00:00Z',
152
+ sessionId: 'older-session',
153
+ }));
154
+ const newerPath = await writeSession(chatsDir, 'session-2024-01-01T10-00-newer000.jsonl', buildJsonlSession({
155
+ userMessageCount: 2,
156
+ lastUpdated: '2024-01-03T10:00:00Z',
157
+ sessionId: 'newer-session',
158
+ }));
159
+ const result = await getPreviousSession(mockConfig);
160
+ expect(result).toBe(newerPath);
161
+ });
162
+ it('should stop scanning once older mtimes cannot beat the best lastUpdated', async () => {
163
+ const loadConversationRecord = vi.mocked(chatRecordingService.loadConversationRecord);
164
+ const currentPath = await writeSession(chatsDir, 'session-2024-01-03T10-00-cur00001.jsonl', buildJsonlSession({
165
+ sessionId: 'current-session',
166
+ userMessageCount: 2,
167
+ lastUpdated: '2024-01-03T10:00:00Z',
168
+ }));
169
+ await setSessionMtime(currentPath, '2024-01-03T10:00:00Z');
170
+ const bestPath = await writeSession(chatsDir, 'session-2024-01-02T10-00-best0001.jsonl', buildJsonlSession({
171
+ sessionId: 'best-session',
172
+ userMessageCount: 2,
173
+ lastUpdated: '2024-01-02T10:00:00Z',
174
+ }));
175
+ await setSessionMtime(bestPath, '2024-01-02T10:00:00Z');
176
+ const olderPath = await writeSession(chatsDir, 'session-2024-01-01T10-00-older001.jsonl', buildJsonlSession({
177
+ sessionId: 'older-session',
178
+ userMessageCount: 2,
179
+ lastUpdated: '2024-01-01T10:00:00Z',
180
+ }));
181
+ await setSessionMtime(olderPath, '2024-01-01T10:00:00Z');
182
+ const result = await getPreviousSession(mockConfig);
183
+ expect(result).toBe(bestPath);
184
+ expect(loadConversationRecord).toHaveBeenCalledTimes(2);
185
+ expect(loadConversationRecord).not.toHaveBeenCalledWith(olderPath, {
186
+ metadataOnly: true,
187
+ });
188
+ });
111
189
  });
112
190
  describe('generateSummary', () => {
113
191
  it('should not throw if getPreviousSession returns null', async () => {
114
- vi.mocked(fs.access).mockRejectedValue(new Error('ENOENT'));
192
+ await fs.rm(chatsDir, { recursive: true, force: true });
115
193
  await expect(generateSummary(mockConfig)).resolves.not.toThrow();
116
194
  });
117
- it('should generate and save summary for session needing one', async () => {
118
- const sessionPath = path.join('/tmp/project', 'chats', 'session-2024-01-01T10-00-abc12345.json');
119
- vi.mocked(fs.access).mockResolvedValue(undefined);
120
- mockReaddir.mockResolvedValue(['session-2024-01-01T10-00-abc12345.json']);
121
- vi.mocked(fs.readFile).mockResolvedValue(createSessionWithUserMessages(2));
122
- vi.mocked(fs.writeFile).mockResolvedValue(undefined);
195
+ it('should generate and save summary for legacy JSON sessions', async () => {
196
+ const lastUpdated = '2024-01-01T10:00:00Z';
197
+ const filePath = await writeSession(chatsDir, 'session-2024-01-01T10-00-abc12345.json', buildLegacySessionJson({ userMessageCount: 2, lastUpdated }));
123
198
  await generateSummary(mockConfig);
124
199
  expect(mockGenerateSummary).toHaveBeenCalledTimes(1);
125
- expect(fs.writeFile).toHaveBeenCalledTimes(1);
126
- expect(fs.writeFile).toHaveBeenCalledWith(sessionPath, expect.stringContaining('Add dark mode to the app'));
200
+ const written = JSON.parse(await fs.readFile(filePath, 'utf-8'));
201
+ expect(written.summary).toBe('Add dark mode to the app');
202
+ expect(written.lastUpdated).toBe(lastUpdated);
127
203
  });
128
204
  it('should handle errors gracefully without throwing', async () => {
129
- vi.mocked(fs.access).mockResolvedValue(undefined);
130
- mockReaddir.mockResolvedValue(['session-2024-01-01T10-00-abc12345.json']);
131
- vi.mocked(fs.readFile).mockResolvedValue(createSessionWithUserMessages(2));
205
+ await writeSession(chatsDir, 'session-2024-01-01T10-00-abc12345.json', buildLegacySessionJson({ userMessageCount: 2 }));
132
206
  mockGenerateSummary.mockRejectedValue(new Error('API Error'));
133
207
  await expect(generateSummary(mockConfig)).resolves.not.toThrow();
134
208
  });
209
+ it('should append a metadata update when saving a summary to JSONL', async () => {
210
+ const lastUpdated = '2024-01-01T10:00:00Z';
211
+ const filePath = await writeSession(chatsDir, 'session-2024-01-01T10-00-abc12345.jsonl', buildJsonlSession({ userMessageCount: 2, lastUpdated }));
212
+ await generateSummary(mockConfig);
213
+ expect(mockGenerateSummary).toHaveBeenCalledTimes(1);
214
+ const lines = (await fs.readFile(filePath, 'utf-8'))
215
+ .split('\n')
216
+ .filter(Boolean);
217
+ const lastRecord = JSON.parse(lines[lines.length - 1]);
218
+ expect(lastRecord).toEqual({
219
+ $set: {
220
+ summary: 'Add dark mode to the app',
221
+ },
222
+ });
223
+ });
224
+ it('should preserve a newer JSONL lastUpdated written concurrently', async () => {
225
+ const initialLastUpdated = '2024-01-01T10:00:00Z';
226
+ const newerLastUpdated = '2024-01-02T12:34:56Z';
227
+ const filePath = await writeSession(chatsDir, 'session-2024-01-01T10-00-race.jsonl', buildJsonlSession({
228
+ userMessageCount: 2,
229
+ lastUpdated: initialLastUpdated,
230
+ }));
231
+ const actualChatRecordingService = await vi.importActual('./chatRecordingService.js');
232
+ let injectedConcurrentUpdate = false;
233
+ let sessionReadCount = 0;
234
+ vi.mocked(chatRecordingService.loadConversationRecord).mockImplementation(async (targetPath, options) => {
235
+ const conversation = await actualChatRecordingService.loadConversationRecord(targetPath, options);
236
+ if (targetPath === filePath) {
237
+ sessionReadCount += 1;
238
+ }
239
+ if (!injectedConcurrentUpdate &&
240
+ targetPath === filePath &&
241
+ sessionReadCount === 2) {
242
+ injectedConcurrentUpdate = true;
243
+ await fs.appendFile(filePath, `${JSON.stringify({ $set: { lastUpdated: newerLastUpdated } })}\n`);
244
+ }
245
+ return conversation;
246
+ });
247
+ await generateSummary(mockConfig);
248
+ expect(injectedConcurrentUpdate).toBe(true);
249
+ const savedConversation = await chatRecordingService.loadConversationRecord(filePath);
250
+ expect(savedConversation?.summary).toBe('Add dark mode to the app');
251
+ expect(savedConversation?.lastUpdated).toBe(newerLastUpdated);
252
+ const lines = (await fs.readFile(filePath, 'utf-8'))
253
+ .split('\n')
254
+ .filter(Boolean);
255
+ const lastRecord = JSON.parse(lines[lines.length - 1]);
256
+ expect(lastRecord).toEqual({
257
+ $set: {
258
+ summary: 'Add dark mode to the app',
259
+ },
260
+ });
261
+ });
262
+ it('should skip the active startup session and summarize the previous session', async () => {
263
+ const previousPath = await writeSession(chatsDir, 'session-2024-01-01T10-00-prev0001.jsonl', buildJsonlSession({
264
+ sessionId: 'previous-session',
265
+ userMessageCount: 2,
266
+ lastUpdated: '2024-01-01T10:00:00Z',
267
+ }));
268
+ const currentPath = await writeSession(chatsDir, 'session-2024-01-02T10-00-cur00001.jsonl', buildJsonlSession({
269
+ sessionId: 'current-session',
270
+ userMessageCount: 1,
271
+ lastUpdated: '2024-01-02T10:00:00Z',
272
+ }));
273
+ await generateSummary(mockConfig);
274
+ expect(mockGenerateSummary).toHaveBeenCalledTimes(1);
275
+ const previousLines = (await fs.readFile(previousPath, 'utf-8'))
276
+ .split('\n')
277
+ .filter(Boolean);
278
+ expect(JSON.parse(previousLines[previousLines.length - 1])).toEqual({
279
+ $set: {
280
+ summary: 'Add dark mode to the app',
281
+ },
282
+ });
283
+ const currentLines = (await fs.readFile(currentPath, 'utf-8'))
284
+ .split('\n')
285
+ .filter(Boolean);
286
+ expect(currentLines).toHaveLength(2);
287
+ });
135
288
  });
136
289
  });
137
290
  //# sourceMappingURL=sessionSummaryUtils.test.js.map