@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.
- package/dist/docs/changelogs/index.md +21 -0
- package/dist/docs/changelogs/latest.md +253 -407
- package/dist/docs/changelogs/preview.md +236 -247
- package/dist/docs/cli/auto-memory.md +143 -0
- package/dist/docs/cli/enterprise.md +1 -1
- package/dist/docs/cli/plan-mode.md +3 -1
- package/dist/docs/cli/settings.md +29 -25
- package/dist/docs/cli/system-prompt.md +6 -6
- package/dist/docs/cli/telemetry.md +18 -11
- package/dist/docs/cli/tutorials/memory-management.md +2 -0
- package/dist/docs/get-started/{authentication.md → authentication.mdx} +139 -93
- package/dist/docs/get-started/index.md +3 -2
- package/dist/docs/get-started/installation.mdx +201 -0
- package/dist/docs/index.md +2 -2
- package/dist/docs/reference/configuration.md +88 -12
- package/dist/docs/reference/policy-engine.md +18 -12
- package/dist/docs/reference/tools.md +22 -0
- package/dist/docs/sidebar.json +13 -1
- package/dist/docs/tools/mcp-resources.md +44 -0
- package/dist/docs/tools/mcp-server.md +2 -1
- package/dist/docs/tools/tracker.md +61 -0
- package/dist/src/agents/agent-tool.js +1 -0
- package/dist/src/agents/agent-tool.js.map +1 -1
- package/dist/src/agents/agentLoader.d.ts +4 -4
- package/dist/src/agents/generalist-agent.js +3 -2
- package/dist/src/agents/generalist-agent.js.map +1 -1
- package/dist/src/agents/local-executor.js +4 -1
- package/dist/src/agents/local-executor.js.map +1 -1
- package/dist/src/agents/registry.js +0 -8
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/skill-extraction-agent.d.ts +3 -2
- package/dist/src/agents/skill-extraction-agent.js +72 -67
- package/dist/src/agents/skill-extraction-agent.js.map +1 -1
- package/dist/src/agents/skill-extraction-agent.test.js +54 -0
- package/dist/src/agents/skill-extraction-agent.test.js.map +1 -0
- package/dist/src/config/config.d.ts +21 -6
- package/dist/src/config/config.js +103 -19
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +262 -6
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/constants.d.ts +1 -0
- package/dist/src/config/constants.js +2 -0
- package/dist/src/config/constants.js.map +1 -1
- package/dist/src/config/memory.js +1 -1
- package/dist/src/config/memory.js.map +1 -1
- package/dist/src/config/path-validation.test.js +15 -6
- package/dist/src/config/path-validation.test.js.map +1 -1
- package/dist/src/config/projectRegistry.js +113 -32
- package/dist/src/config/projectRegistry.js.map +1 -1
- package/dist/src/config/projectRegistry.test.js +51 -0
- package/dist/src/config/projectRegistry.test.js.map +1 -1
- package/dist/src/config/storage.d.ts +3 -1
- package/dist/src/config/storage.js +6 -0
- package/dist/src/config/storage.js.map +1 -1
- package/dist/src/config/storage.test.js +12 -0
- package/dist/src/config/storage.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +8 -1
- package/dist/src/core/contentGenerator.js +46 -4
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +174 -8
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +1 -0
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/geminiChat_network_retry.test.js +42 -0
- package/dist/src/core/geminiChat_network_retry.test.js.map +1 -1
- package/dist/src/core/localLiteRtLmClient.js +2 -0
- package/dist/src/core/localLiteRtLmClient.js.map +1 -1
- package/dist/src/core/localLiteRtLmClient.test.js +7 -0
- package/dist/src/core/localLiteRtLmClient.test.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.js +3 -0
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.test.js +1 -0
- package/dist/src/core/loggingContentGenerator.test.js.map +1 -1
- package/dist/src/core/prompts.d.ts +1 -1
- package/dist/src/core/prompts.js +2 -2
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +2 -2
- package/dist/src/core/prompts.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/ide/ide-client.js +3 -4
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/policy/policies/read-only.toml +4 -1
- package/dist/src/policy/policy-engine.js +4 -0
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +25 -0
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/toml-loader.test.js +5 -0
- package/dist/src/policy/toml-loader.test.js.map +1 -1
- package/dist/src/prompts/promptProvider.d.ts +1 -1
- package/dist/src/prompts/promptProvider.js +15 -7
- package/dist/src/prompts/promptProvider.js.map +1 -1
- package/dist/src/prompts/promptProvider.test.js +31 -1
- package/dist/src/prompts/promptProvider.test.js.map +1 -1
- package/dist/src/prompts/snippets-memory-v2.test.js +94 -0
- package/dist/src/prompts/snippets-memory-v2.test.js.map +1 -0
- package/dist/src/prompts/snippets.d.ts +19 -1
- package/dist/src/prompts/snippets.js +24 -3
- package/dist/src/prompts/snippets.js.map +1 -1
- package/dist/src/prompts/snippets.legacy.d.ts +6 -1
- package/dist/src/prompts/snippets.legacy.js +10 -3
- package/dist/src/prompts/snippets.legacy.js.map +1 -1
- package/dist/src/sandbox/linux/LinuxSandboxManager.js +16 -2
- package/dist/src/sandbox/linux/LinuxSandboxManager.js.map +1 -1
- package/dist/src/sandbox/linux/bwrapArgsBuilder.js +64 -36
- package/dist/src/sandbox/linux/bwrapArgsBuilder.js.map +1 -1
- package/dist/src/sandbox/linux/bwrapArgsBuilder.test.js +3 -3
- package/dist/src/sandbox/linux/bwrapArgsBuilder.test.js.map +1 -1
- package/dist/src/sandbox/macos/MacOsSandboxManager.js +13 -1
- package/dist/src/sandbox/macos/MacOsSandboxManager.js.map +1 -1
- package/dist/src/sandbox/macos/seatbeltArgsBuilder.js +61 -42
- package/dist/src/sandbox/macos/seatbeltArgsBuilder.js.map +1 -1
- package/dist/src/sandbox/windows/WindowsSandboxManager.js +12 -1
- package/dist/src/sandbox/windows/WindowsSandboxManager.js.map +1 -1
- package/dist/src/scheduler/policy.js +1 -2
- package/dist/src/scheduler/policy.js.map +1 -1
- package/dist/src/scheduler/policy.test.js +35 -2
- package/dist/src/scheduler/policy.test.js.map +1 -1
- package/dist/src/scheduler/scheduler.js +1 -0
- package/dist/src/scheduler/scheduler.js.map +1 -1
- package/dist/src/scheduler/scheduler.test.js +2 -0
- package/dist/src/scheduler/scheduler.test.js.map +1 -1
- package/dist/src/scheduler/scheduler_hooks.test.js +1 -0
- package/dist/src/scheduler/scheduler_hooks.test.js.map +1 -1
- package/dist/src/scheduler/scheduler_parallel.test.js +1 -0
- package/dist/src/scheduler/scheduler_parallel.test.js.map +1 -1
- package/dist/src/scheduler/tool-executor.js +1 -0
- package/dist/src/scheduler/tool-executor.js.map +1 -1
- package/dist/src/services/chatRecordingService.d.ts +1 -0
- package/dist/src/services/chatRecordingService.js +48 -19
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/memoryService.d.ts +15 -1
- package/dist/src/services/memoryService.js +276 -57
- package/dist/src/services/memoryService.js.map +1 -1
- package/dist/src/services/memoryService.test.js +296 -2
- package/dist/src/services/memoryService.test.js.map +1 -1
- package/dist/src/services/sandboxManager.integration.test.js +204 -0
- package/dist/src/services/sandboxManager.integration.test.js.map +1 -1
- package/dist/src/services/sandboxManager.js +16 -0
- package/dist/src/services/sandboxManager.js.map +1 -1
- package/dist/src/services/sessionSummaryUtils.d.ts +1 -1
- package/dist/src/services/sessionSummaryUtils.js +111 -38
- package/dist/src/services/sessionSummaryUtils.js.map +1 -1
- package/dist/src/services/sessionSummaryUtils.test.js +204 -51
- package/dist/src/services/sessionSummaryUtils.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +7 -1
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/telemetry/config.js +3 -0
- package/dist/src/telemetry/config.js.map +1 -1
- package/dist/src/telemetry/conseca-logger.test.js +1 -0
- package/dist/src/telemetry/conseca-logger.test.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +72 -4
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/memory-monitor.d.ts +1 -0
- package/dist/src/telemetry/memory-monitor.js +8 -1
- package/dist/src/telemetry/memory-monitor.js.map +1 -1
- package/dist/src/telemetry/memory-monitor.test.js +6 -1
- package/dist/src/telemetry/memory-monitor.test.js.map +1 -1
- package/dist/src/telemetry/trace.d.ts +1 -0
- package/dist/src/telemetry/trace.js +33 -13
- package/dist/src/telemetry/trace.js.map +1 -1
- package/dist/src/telemetry/trace.test.js +50 -10
- package/dist/src/telemetry/trace.test.js.map +1 -1
- package/dist/src/telemetry/types.js +11 -4
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/tools/definitions/base-declarations.d.ts +2 -0
- package/dist/src/tools/definitions/base-declarations.js +3 -0
- package/dist/src/tools/definitions/base-declarations.js.map +1 -1
- package/dist/src/tools/definitions/coreTools.d.ts +3 -1
- package/dist/src/tools/definitions/coreTools.js +13 -1
- package/dist/src/tools/definitions/coreTools.js.map +1 -1
- package/dist/src/tools/definitions/model-family-sets/default-legacy.js +29 -1
- package/dist/src/tools/definitions/model-family-sets/default-legacy.js.map +1 -1
- package/dist/src/tools/definitions/model-family-sets/gemini-3.js +29 -1
- package/dist/src/tools/definitions/model-family-sets/gemini-3.js.map +1 -1
- package/dist/src/tools/definitions/types.d.ts +2 -0
- package/dist/src/tools/get-internal-docs.js +5 -2
- package/dist/src/tools/get-internal-docs.js.map +1 -1
- package/dist/src/tools/list-mcp-resources.d.ts +24 -0
- package/dist/src/tools/list-mcp-resources.js +74 -0
- package/dist/src/tools/list-mcp-resources.js.map +1 -0
- package/dist/src/tools/list-mcp-resources.test.d.ts +6 -0
- package/dist/src/tools/list-mcp-resources.test.js +79 -0
- package/dist/src/tools/list-mcp-resources.test.js.map +1 -0
- package/dist/src/tools/mcp-client-manager.d.ts +3 -1
- package/dist/src/tools/mcp-client-manager.js +24 -1
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +43 -0
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +2 -1
- package/dist/src/tools/memoryTool.js +42 -13
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +23 -3
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/read-mcp-resource.d.ts +25 -0
- package/dist/src/tools/read-mcp-resource.js +120 -0
- package/dist/src/tools/read-mcp-resource.js.map +1 -0
- package/dist/src/tools/read-mcp-resource.test.d.ts +6 -0
- package/dist/src/tools/read-mcp-resource.test.js +110 -0
- package/dist/src/tools/read-mcp-resource.test.js.map +1 -0
- package/dist/src/tools/ripGrep.d.ts +3 -2
- package/dist/src/tools/ripGrep.js +25 -54
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +73 -131
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.js +38 -12
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +410 -25
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/tool-error.d.ts +1 -0
- package/dist/src/tools/tool-error.js +1 -0
- package/dist/src/tools/tool-error.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +4 -4
- package/dist/src/tools/tool-names.js +6 -2
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tool-registry.js +8 -1
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.d.ts +2 -0
- package/dist/src/utils/filesearch/fileSearch.js +97 -6
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.test.js +54 -0
- package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
- package/dist/src/utils/filesearch/fileWatcher.d.ts +25 -0
- package/dist/src/utils/filesearch/fileWatcher.js +86 -0
- package/dist/src/utils/filesearch/fileWatcher.js.map +1 -0
- package/dist/src/utils/filesearch/fileWatcher.test.d.ts +6 -0
- package/dist/src/utils/filesearch/fileWatcher.test.js +142 -0
- package/dist/src/utils/filesearch/fileWatcher.test.js.map +1 -0
- package/dist/src/utils/gitIgnoreParser.js +1 -1
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/ignoreFileParser.js +1 -1
- package/dist/src/utils/ignoreFileParser.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.js +15 -5
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/retry.js +18 -6
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +30 -0
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/shell-utils.d.ts +1 -0
- package/dist/src/utils/shell-utils.js +106 -0
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -3
- package/vendor/ripgrep/rg-darwin-arm64 +0 -0
- package/vendor/ripgrep/rg-darwin-x64 +0 -0
- package/vendor/ripgrep/rg-linux-arm64 +0 -0
- package/vendor/ripgrep/rg-linux-x64 +0 -0
- package/vendor/ripgrep/rg-win32-x64.exe +0 -0
- package/dist/docs/get-started/installation.md +0 -181
- package/dist/google-gemini-cli-core-0.39.0-preview.1.tgz +0 -0
- package/dist/src/agents/memory-manager-agent.d.ts +0 -25
- package/dist/src/agents/memory-manager-agent.js +0 -138
- package/dist/src/agents/memory-manager-agent.js.map +0 -1
- package/dist/src/agents/memory-manager-agent.test.js +0 -123
- package/dist/src/agents/memory-manager-agent.test.js.map +0 -1
- package/dist/src/prompts/snippets-memory-manager.test.js +0 -31
- package/dist/src/prompts/snippets-memory-manager.test.js.map +0 -1
- /package/dist/src/agents/{memory-manager-agent.test.d.ts → skill-extraction-agent.test.d.ts} +0 -0
- /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
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
49
|
-
//
|
|
50
|
-
const
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
107
|
-
debugLogger.debug('[SessionSummary]
|
|
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":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACL,mBAAmB,
|
|
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
|
-
|
|
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
|
-
|
|
24
|
-
|
|
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:
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
129
|
+
expect(result).toBe(filePath);
|
|
93
130
|
});
|
|
94
|
-
it('should select most recently
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
'
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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(
|
|
141
|
+
expect(result).toBe(newerPath);
|
|
103
142
|
});
|
|
104
|
-
it('should
|
|
105
|
-
|
|
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
|
-
|
|
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
|
|
118
|
-
const
|
|
119
|
-
|
|
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
|
-
|
|
126
|
-
expect(
|
|
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
|
-
|
|
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
|