@google/gemini-cli-core 0.1.18 → 0.1.19-nightly.250814.514e883a
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/README.md +199 -132
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/src/code_assist/converter.d.ts +3 -2
- package/dist/src/code_assist/converter.js +2 -2
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +48 -1
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.js +1 -1
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/server.test.js +4 -1
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.js +48 -17
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/setup.test.js +105 -5
- package/dist/src/code_assist/setup.test.js.map +1 -1
- package/dist/src/config/config.d.ts +25 -6
- package/dist/src/config/config.js +47 -16
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +95 -1
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/core/client.d.ts +8 -5
- package/dist/src/core/client.js +184 -119
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +342 -37
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.js +3 -2
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +3 -2
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +21 -8
- package/dist/src/core/coreToolScheduler.js +170 -61
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +183 -41
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +7 -6
- package/dist/src/core/geminiChat.js +43 -43
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/logger.d.ts +1 -0
- package/dist/src/core/logger.js +18 -0
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +29 -0
- package/dist/src/core/logger.test.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.d.ts +29 -0
- package/dist/src/core/loggingContentGenerator.js +97 -0
- package/dist/src/core/loggingContentGenerator.js.map +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.js +20 -1
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +7 -31
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/subagent.d.ts +230 -0
- package/dist/src/core/subagent.js +447 -0
- package/dist/src/core/subagent.js.map +1 -0
- package/dist/src/core/subagent.test.d.ts +6 -0
- package/dist/src/core/subagent.test.js +515 -0
- package/dist/src/core/subagent.test.js.map +1 -0
- package/dist/src/core/turn.js +1 -0
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +4 -0
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +12 -2
- package/dist/src/ide/detect-ide.js +64 -5
- package/dist/src/ide/detect-ide.js.map +1 -1
- package/dist/src/ide/detect-ide.test.d.ts +6 -0
- package/dist/src/ide/detect-ide.test.js +65 -0
- package/dist/src/ide/detect-ide.test.js.map +1 -0
- package/dist/src/ide/ide-client.d.ts +20 -1
- package/dist/src/ide/ide-client.js +145 -19
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-installer.js +1 -26
- package/dist/src/ide/ide-installer.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +0 -4
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/ideContext.d.ts +95 -0
- package/dist/src/ide/ideContext.js +45 -0
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.js +9 -0
- package/dist/src/mcp/google-auth-provider.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.test.js +45 -10
- package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-provider.d.ts +0 -1
- package/dist/src/mcp/oauth-provider.js +0 -1
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mocks/msw.d.ts +6 -0
- package/dist/src/mocks/msw.js +8 -0
- package/dist/src/mocks/msw.js.map +1 -0
- package/dist/src/services/loopDetectionService.js +14 -11
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +191 -0
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +29 -9
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +8 -0
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +50 -7
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +236 -116
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +6 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +281 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +8 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +17 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +2 -2
- package/dist/src/telemetry/index.js +2 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +2 -1
- package/dist/src/telemetry/loggers.js +15 -0
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +7 -2
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +7 -2
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +3 -2
- package/dist/src/telemetry/metrics.js +7 -1
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +50 -0
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sdk.d.ts +1 -1
- package/dist/src/telemetry/sdk.js +13 -5
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/telemetry.test.js +2 -2
- package/dist/src/telemetry/telemetry.test.js.map +1 -1
- package/dist/src/telemetry/tool-call-decision.d.ts +13 -0
- package/dist/src/telemetry/tool-call-decision.js +29 -0
- package/dist/src/telemetry/tool-call-decision.js.map +1 -0
- package/dist/src/telemetry/types.d.ts +37 -21
- package/dist/src/telemetry/types.js +55 -44
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +4 -1
- package/dist/src/telemetry/uiTelemetry.js +3 -1
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +13 -2
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/config.d.ts +16 -0
- package/dist/src/test-utils/config.js +32 -0
- package/dist/src/test-utils/config.js.map +1 -0
- package/dist/src/test-utils/tools.d.ts +23 -0
- package/dist/src/test-utils/tools.js +41 -0
- package/dist/src/test-utils/tools.js.map +1 -0
- package/dist/src/tools/diffOptions.d.ts +2 -0
- package/dist/src/tools/diffOptions.js +28 -0
- package/dist/src/tools/diffOptions.js.map +1 -1
- package/dist/src/tools/diffOptions.test.d.ts +6 -0
- package/dist/src/tools/diffOptions.test.js +119 -0
- package/dist/src/tools/diffOptions.test.js.map +1 -0
- package/dist/src/tools/edit.d.ts +9 -33
- package/dist/src/tools/edit.js +142 -132
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +115 -51
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +3 -10
- package/dist/src/tools/glob.js +85 -89
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +22 -12
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +3 -35
- package/dist/src/tools/grep.js +111 -83
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +40 -23
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.d.ts +3 -22
- package/dist/src/tools/ls.js +81 -78
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +62 -34
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +14 -3
- package/dist/src/tools/mcp-client.js +82 -6
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +340 -5
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +6 -13
- package/dist/src/tools/mcp-tool.js +41 -31
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +53 -51
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +10 -14
- package/dist/src/tools/memoryTool.js +128 -121
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +38 -18
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.d.ts +8 -5
- package/dist/src/tools/modifiable-tool.js +4 -1
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +3 -3
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +4 -6
- package/dist/src/tools/read-file.js +92 -45
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +192 -130
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +4 -5
- package/dist/src/tools/read-many-files.js +120 -103
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +81 -47
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +4 -6
- package/dist/src/tools/shell.js +99 -101
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +43 -28
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/tool-error.d.ts +4 -0
- package/dist/src/tools/tool-error.js +4 -0
- package/dist/src/tools/tool-error.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +17 -20
- package/dist/src/tools/tool-registry.js +35 -77
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +19 -192
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +156 -54
- package/dist/src/tools/tools.js +196 -25
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/tools.test.d.ts +6 -0
- package/dist/src/tools/tools.test.js +117 -0
- package/dist/src/tools/tools.test.js.map +1 -0
- package/dist/src/tools/web-fetch.d.ts +4 -7
- package/dist/src/tools/web-fetch.js +62 -63
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +8 -4
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.js +3 -3
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +8 -3
- package/dist/src/tools/write-file.js +89 -22
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +112 -8
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +28 -56
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/editCorrector.js +8 -9
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/environmentContext.d.ts +21 -0
- package/dist/src/utils/environmentContext.js +90 -0
- package/dist/src/utils/environmentContext.js.map +1 -0
- package/dist/src/utils/environmentContext.test.d.ts +6 -0
- package/dist/src/utils/environmentContext.test.js +139 -0
- package/dist/src/utils/environmentContext.test.js.map +1 -0
- package/dist/src/utils/errorParsing.d.ts +8 -0
- package/dist/src/utils/errorParsing.js +93 -0
- package/dist/src/utils/errorParsing.js.map +1 -0
- package/dist/src/utils/errorParsing.test.d.ts +6 -0
- package/dist/src/utils/errorParsing.test.js +172 -0
- package/dist/src/utils/errorParsing.test.js.map +1 -0
- package/dist/src/utils/fileUtils.d.ts +7 -0
- package/dist/src/utils/fileUtils.js +15 -12
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +6 -5
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/crawlCache.d.ts +1 -1
- package/dist/src/utils/filesearch/crawlCache.js +4 -1
- package/dist/src/utils/filesearch/crawlCache.js.map +1 -1
- package/dist/src/utils/filesearch/crawlCache.test.js +10 -0
- package/dist/src/utils/filesearch/crawlCache.test.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.d.ts +2 -0
- package/dist/src/utils/filesearch/fileSearch.js +33 -8
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.test.js +139 -0
- package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
- package/dist/src/utils/filesearch/result-cache.d.ts +1 -2
- package/dist/src/utils/filesearch/result-cache.js +1 -3
- package/dist/src/utils/filesearch/result-cache.js.map +1 -1
- package/dist/src/utils/filesearch/result-cache.test.js +3 -4
- package/dist/src/utils/filesearch/result-cache.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.js +4 -1
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.js +1 -1
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.test.js +17 -20
- package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.js +5 -6
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +2 -2
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/quotaErrorDetection.d.ts +1 -5
- package/dist/src/utils/quotaErrorDetection.js.map +1 -1
- package/dist/src/utils/schemaValidator.d.ts +1 -8
- package/dist/src/utils/schemaValidator.js +1 -32
- package/dist/src/utils/schemaValidator.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -1
- package/dist/google-gemini-cli-core-0.1.17.tgz +0 -0
|
@@ -170,11 +170,13 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
170
170
|
getUsageStatisticsEnabled: vi.fn().mockReturnValue(true),
|
|
171
171
|
getIdeModeFeature: vi.fn().mockReturnValue(false),
|
|
172
172
|
getIdeMode: vi.fn().mockReturnValue(true),
|
|
173
|
+
getDebugMode: vi.fn().mockReturnValue(false),
|
|
173
174
|
getWorkspaceContext: vi.fn().mockReturnValue({
|
|
174
175
|
getDirectories: vi.fn().mockReturnValue(['/test/dir']),
|
|
175
176
|
}),
|
|
176
177
|
getGeminiClient: vi.fn(),
|
|
177
178
|
setFallbackMode: vi.fn(),
|
|
179
|
+
getChatCompression: vi.fn().mockReturnValue(undefined),
|
|
178
180
|
};
|
|
179
181
|
const MockedConfig = vi.mocked(Config, true);
|
|
180
182
|
MockedConfig.mockImplementation(() => mockConfigObject);
|
|
@@ -314,7 +316,7 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
314
316
|
systemInstruction: getCoreSystemPrompt(''),
|
|
315
317
|
temperature: 0,
|
|
316
318
|
topP: 1,
|
|
317
|
-
|
|
319
|
+
responseJsonSchema: schema,
|
|
318
320
|
responseMimeType: 'application/json',
|
|
319
321
|
},
|
|
320
322
|
contents,
|
|
@@ -340,7 +342,7 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
340
342
|
temperature: 0.9,
|
|
341
343
|
topP: 1, // from default
|
|
342
344
|
topK: 20,
|
|
343
|
-
|
|
345
|
+
responseJsonSchema: schema,
|
|
344
346
|
responseMimeType: 'application/json',
|
|
345
347
|
},
|
|
346
348
|
contents,
|
|
@@ -352,7 +354,6 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
352
354
|
const mockChat = {
|
|
353
355
|
addHistory: vi.fn(),
|
|
354
356
|
};
|
|
355
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
356
357
|
client['chat'] = mockChat;
|
|
357
358
|
const newContent = {
|
|
358
359
|
role: 'user',
|
|
@@ -418,13 +419,17 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
418
419
|
expect(result).toBeNull();
|
|
419
420
|
expect(newChat).toBe(initialChat);
|
|
420
421
|
});
|
|
421
|
-
it('should trigger summarization if token count is at threshold', async () => {
|
|
422
|
+
it('should trigger summarization if token count is at threshold with contextPercentageThreshold setting', async () => {
|
|
422
423
|
const MOCKED_TOKEN_LIMIT = 1000;
|
|
424
|
+
const MOCKED_CONTEXT_PERCENTAGE_THRESHOLD = 0.5;
|
|
423
425
|
vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
|
|
426
|
+
vi.spyOn(client['config'], 'getChatCompression').mockReturnValue({
|
|
427
|
+
contextPercentageThreshold: MOCKED_CONTEXT_PERCENTAGE_THRESHOLD,
|
|
428
|
+
});
|
|
424
429
|
mockGetHistory.mockReturnValue([
|
|
425
430
|
{ role: 'user', parts: [{ text: '...history...' }] },
|
|
426
431
|
]);
|
|
427
|
-
const originalTokenCount =
|
|
432
|
+
const originalTokenCount = MOCKED_TOKEN_LIMIT * MOCKED_CONTEXT_PERCENTAGE_THRESHOLD;
|
|
428
433
|
const newTokenCount = 100;
|
|
429
434
|
mockCountTokens
|
|
430
435
|
.mockResolvedValueOnce({ totalTokens: originalTokenCount }) // First call for the check
|
|
@@ -524,7 +529,7 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
524
529
|
});
|
|
525
530
|
});
|
|
526
531
|
describe('sendMessageStream', () => {
|
|
527
|
-
it('should include
|
|
532
|
+
it('should include editor context when ideMode is enabled', async () => {
|
|
528
533
|
// Arrange
|
|
529
534
|
vi.mocked(ideContext.getIdeContext).mockReturnValue({
|
|
530
535
|
workspaceState: {
|
|
@@ -547,7 +552,7 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
547
552
|
],
|
|
548
553
|
},
|
|
549
554
|
});
|
|
550
|
-
vi.spyOn(client['config'], '
|
|
555
|
+
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
|
|
551
556
|
const mockStream = (async function* () {
|
|
552
557
|
yield { type: 'content', value: 'Hello' };
|
|
553
558
|
})();
|
|
@@ -571,27 +576,35 @@ describe('Gemini Client (client.ts)', () => {
|
|
|
571
576
|
// Assert
|
|
572
577
|
expect(ideContext.getIdeContext).toHaveBeenCalled();
|
|
573
578
|
const expectedContext = `
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
579
|
+
Here is the user's editor context as a JSON object. This is for your information only.
|
|
580
|
+
\`\`\`json
|
|
581
|
+
${JSON.stringify({
|
|
582
|
+
activeFile: {
|
|
583
|
+
path: '/path/to/active/file.ts',
|
|
584
|
+
cursor: {
|
|
585
|
+
line: 5,
|
|
586
|
+
character: 10,
|
|
587
|
+
},
|
|
588
|
+
selectedText: 'hello',
|
|
589
|
+
},
|
|
590
|
+
otherOpenFiles: ['/path/to/recent/file1.ts', '/path/to/recent/file2.ts'],
|
|
591
|
+
}, null, 2)}
|
|
592
|
+
\`\`\`
|
|
583
593
|
`.trim();
|
|
584
|
-
const expectedRequest = [{ text: expectedContext }
|
|
585
|
-
expect(
|
|
594
|
+
const expectedRequest = [{ text: expectedContext }];
|
|
595
|
+
expect(mockChat.addHistory).toHaveBeenCalledWith({
|
|
596
|
+
role: 'user',
|
|
597
|
+
parts: expectedRequest,
|
|
598
|
+
});
|
|
586
599
|
});
|
|
587
|
-
it('should not add context if
|
|
600
|
+
it('should not add context if ideMode is enabled but no open files', async () => {
|
|
588
601
|
// Arrange
|
|
589
602
|
vi.mocked(ideContext.getIdeContext).mockReturnValue({
|
|
590
603
|
workspaceState: {
|
|
591
604
|
openFiles: [],
|
|
592
605
|
},
|
|
593
606
|
});
|
|
594
|
-
vi.spyOn(client['config'], '
|
|
607
|
+
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
|
|
595
608
|
const mockStream = (async function* () {
|
|
596
609
|
yield { type: 'content', value: 'Hello' };
|
|
597
610
|
})();
|
|
@@ -616,7 +629,7 @@ Here are some other files the user has open, with the most recent at the top:
|
|
|
616
629
|
expect(ideContext.getIdeContext).toHaveBeenCalled();
|
|
617
630
|
expect(mockTurnRunFn).toHaveBeenCalledWith(initialRequest, expect.any(Object));
|
|
618
631
|
});
|
|
619
|
-
it('should add context if
|
|
632
|
+
it('should add context if ideMode is enabled and there is one active file', async () => {
|
|
620
633
|
// Arrange
|
|
621
634
|
vi.mocked(ideContext.getIdeContext).mockReturnValue({
|
|
622
635
|
workspaceState: {
|
|
@@ -631,7 +644,7 @@ Here are some other files the user has open, with the most recent at the top:
|
|
|
631
644
|
],
|
|
632
645
|
},
|
|
633
646
|
});
|
|
634
|
-
vi.spyOn(client['config'], '
|
|
647
|
+
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
|
|
635
648
|
const mockStream = (async function* () {
|
|
636
649
|
yield { type: 'content', value: 'Hello' };
|
|
637
650
|
})();
|
|
@@ -655,17 +668,27 @@ Here are some other files the user has open, with the most recent at the top:
|
|
|
655
668
|
// Assert
|
|
656
669
|
expect(ideContext.getIdeContext).toHaveBeenCalled();
|
|
657
670
|
const expectedContext = `
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
671
|
+
Here is the user's editor context as a JSON object. This is for your information only.
|
|
672
|
+
\`\`\`json
|
|
673
|
+
${JSON.stringify({
|
|
674
|
+
activeFile: {
|
|
675
|
+
path: '/path/to/active/file.ts',
|
|
676
|
+
cursor: {
|
|
677
|
+
line: 5,
|
|
678
|
+
character: 10,
|
|
679
|
+
},
|
|
680
|
+
selectedText: 'hello',
|
|
681
|
+
},
|
|
682
|
+
}, null, 2)}
|
|
683
|
+
\`\`\`
|
|
664
684
|
`.trim();
|
|
665
|
-
const expectedRequest = [{ text: expectedContext }
|
|
666
|
-
expect(
|
|
685
|
+
const expectedRequest = [{ text: expectedContext }];
|
|
686
|
+
expect(mockChat.addHistory).toHaveBeenCalledWith({
|
|
687
|
+
role: 'user',
|
|
688
|
+
parts: expectedRequest,
|
|
689
|
+
});
|
|
667
690
|
});
|
|
668
|
-
it('should add context if
|
|
691
|
+
it('should add context if ideMode is enabled and there are open files but no active file', async () => {
|
|
669
692
|
// Arrange
|
|
670
693
|
vi.mocked(ideContext.getIdeContext).mockReturnValue({
|
|
671
694
|
workspaceState: {
|
|
@@ -681,7 +704,7 @@ This is the selected text in the file:
|
|
|
681
704
|
],
|
|
682
705
|
},
|
|
683
706
|
});
|
|
684
|
-
vi.spyOn(client['config'], '
|
|
707
|
+
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
|
|
685
708
|
const mockStream = (async function* () {
|
|
686
709
|
yield { type: 'content', value: 'Hello' };
|
|
687
710
|
})();
|
|
@@ -705,12 +728,18 @@ This is the selected text in the file:
|
|
|
705
728
|
// Assert
|
|
706
729
|
expect(ideContext.getIdeContext).toHaveBeenCalled();
|
|
707
730
|
const expectedContext = `
|
|
708
|
-
Here
|
|
709
|
-
|
|
710
|
-
|
|
731
|
+
Here is the user's editor context as a JSON object. This is for your information only.
|
|
732
|
+
\`\`\`json
|
|
733
|
+
${JSON.stringify({
|
|
734
|
+
otherOpenFiles: ['/path/to/recent/file1.ts', '/path/to/recent/file2.ts'],
|
|
735
|
+
}, null, 2)}
|
|
736
|
+
\`\`\`
|
|
711
737
|
`.trim();
|
|
712
|
-
const expectedRequest = [{ text: expectedContext }
|
|
713
|
-
expect(
|
|
738
|
+
const expectedRequest = [{ text: expectedContext }];
|
|
739
|
+
expect(mockChat.addHistory).toHaveBeenCalledWith({
|
|
740
|
+
role: 'user',
|
|
741
|
+
parts: expectedRequest,
|
|
742
|
+
});
|
|
714
743
|
});
|
|
715
744
|
it('should return the turn instance after the stream is complete', async () => {
|
|
716
745
|
// Arrange
|
|
@@ -913,6 +942,222 @@ Here are some files the user has open, with the most recent at the top:
|
|
|
913
942
|
console.log(`Infinite loop protection working: checkNextSpeaker called ${callCount} times, ` +
|
|
914
943
|
`${eventCount} events generated (properly bounded by MAX_TURNS)`);
|
|
915
944
|
});
|
|
945
|
+
describe('Editor context delta', () => {
|
|
946
|
+
const mockStream = (async function* () {
|
|
947
|
+
yield { type: 'content', value: 'Hello' };
|
|
948
|
+
})();
|
|
949
|
+
beforeEach(() => {
|
|
950
|
+
client['forceFullIdeContext'] = false; // Reset before each delta test
|
|
951
|
+
vi.spyOn(client, 'tryCompressChat').mockResolvedValue(null);
|
|
952
|
+
vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
|
|
953
|
+
mockTurnRunFn.mockReturnValue(mockStream);
|
|
954
|
+
const mockChat = {
|
|
955
|
+
addHistory: vi.fn(),
|
|
956
|
+
setHistory: vi.fn(),
|
|
957
|
+
sendMessage: vi.fn().mockResolvedValue({ text: 'summary' }),
|
|
958
|
+
// Assume history is not empty for delta checks
|
|
959
|
+
getHistory: vi
|
|
960
|
+
.fn()
|
|
961
|
+
.mockReturnValue([
|
|
962
|
+
{ role: 'user', parts: [{ text: 'previous message' }] },
|
|
963
|
+
]),
|
|
964
|
+
};
|
|
965
|
+
client['chat'] = mockChat;
|
|
966
|
+
const mockGenerator = {
|
|
967
|
+
countTokens: vi.fn().mockResolvedValue({ totalTokens: 0 }),
|
|
968
|
+
generateContent: mockGenerateContentFn,
|
|
969
|
+
};
|
|
970
|
+
client['contentGenerator'] = mockGenerator;
|
|
971
|
+
});
|
|
972
|
+
const testCases = [
|
|
973
|
+
{
|
|
974
|
+
description: 'sends delta when active file changes',
|
|
975
|
+
previousActiveFile: {
|
|
976
|
+
path: '/path/to/old/file.ts',
|
|
977
|
+
cursor: { line: 5, character: 10 },
|
|
978
|
+
selectedText: 'hello',
|
|
979
|
+
},
|
|
980
|
+
currentActiveFile: {
|
|
981
|
+
path: '/path/to/active/file.ts',
|
|
982
|
+
cursor: { line: 5, character: 10 },
|
|
983
|
+
selectedText: 'hello',
|
|
984
|
+
},
|
|
985
|
+
shouldSendContext: true,
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
description: 'sends delta when cursor line changes',
|
|
989
|
+
previousActiveFile: {
|
|
990
|
+
path: '/path/to/active/file.ts',
|
|
991
|
+
cursor: { line: 1, character: 10 },
|
|
992
|
+
selectedText: 'hello',
|
|
993
|
+
},
|
|
994
|
+
currentActiveFile: {
|
|
995
|
+
path: '/path/to/active/file.ts',
|
|
996
|
+
cursor: { line: 5, character: 10 },
|
|
997
|
+
selectedText: 'hello',
|
|
998
|
+
},
|
|
999
|
+
shouldSendContext: true,
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
description: 'sends delta when cursor character changes',
|
|
1003
|
+
previousActiveFile: {
|
|
1004
|
+
path: '/path/to/active/file.ts',
|
|
1005
|
+
cursor: { line: 5, character: 1 },
|
|
1006
|
+
selectedText: 'hello',
|
|
1007
|
+
},
|
|
1008
|
+
currentActiveFile: {
|
|
1009
|
+
path: '/path/to/active/file.ts',
|
|
1010
|
+
cursor: { line: 5, character: 10 },
|
|
1011
|
+
selectedText: 'hello',
|
|
1012
|
+
},
|
|
1013
|
+
shouldSendContext: true,
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
description: 'sends delta when selected text changes',
|
|
1017
|
+
previousActiveFile: {
|
|
1018
|
+
path: '/path/to/active/file.ts',
|
|
1019
|
+
cursor: { line: 5, character: 10 },
|
|
1020
|
+
selectedText: 'world',
|
|
1021
|
+
},
|
|
1022
|
+
currentActiveFile: {
|
|
1023
|
+
path: '/path/to/active/file.ts',
|
|
1024
|
+
cursor: { line: 5, character: 10 },
|
|
1025
|
+
selectedText: 'hello',
|
|
1026
|
+
},
|
|
1027
|
+
shouldSendContext: true,
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
description: 'sends delta when selected text is added',
|
|
1031
|
+
previousActiveFile: {
|
|
1032
|
+
path: '/path/to/active/file.ts',
|
|
1033
|
+
cursor: { line: 5, character: 10 },
|
|
1034
|
+
},
|
|
1035
|
+
currentActiveFile: {
|
|
1036
|
+
path: '/path/to/active/file.ts',
|
|
1037
|
+
cursor: { line: 5, character: 10 },
|
|
1038
|
+
selectedText: 'hello',
|
|
1039
|
+
},
|
|
1040
|
+
shouldSendContext: true,
|
|
1041
|
+
},
|
|
1042
|
+
{
|
|
1043
|
+
description: 'sends delta when selected text is removed',
|
|
1044
|
+
previousActiveFile: {
|
|
1045
|
+
path: '/path/to/active/file.ts',
|
|
1046
|
+
cursor: { line: 5, character: 10 },
|
|
1047
|
+
selectedText: 'hello',
|
|
1048
|
+
},
|
|
1049
|
+
currentActiveFile: {
|
|
1050
|
+
path: '/path/to/active/file.ts',
|
|
1051
|
+
cursor: { line: 5, character: 10 },
|
|
1052
|
+
},
|
|
1053
|
+
shouldSendContext: true,
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
description: 'does not send context when nothing changes',
|
|
1057
|
+
previousActiveFile: {
|
|
1058
|
+
path: '/path/to/active/file.ts',
|
|
1059
|
+
cursor: { line: 5, character: 10 },
|
|
1060
|
+
selectedText: 'hello',
|
|
1061
|
+
},
|
|
1062
|
+
currentActiveFile: {
|
|
1063
|
+
path: '/path/to/active/file.ts',
|
|
1064
|
+
cursor: { line: 5, character: 10 },
|
|
1065
|
+
selectedText: 'hello',
|
|
1066
|
+
},
|
|
1067
|
+
shouldSendContext: false,
|
|
1068
|
+
},
|
|
1069
|
+
];
|
|
1070
|
+
it.each(testCases)('$description', async ({ previousActiveFile, currentActiveFile, shouldSendContext, }) => {
|
|
1071
|
+
// Setup previous context
|
|
1072
|
+
client['lastSentIdeContext'] = {
|
|
1073
|
+
workspaceState: {
|
|
1074
|
+
openFiles: [
|
|
1075
|
+
{
|
|
1076
|
+
path: previousActiveFile.path,
|
|
1077
|
+
cursor: previousActiveFile.cursor,
|
|
1078
|
+
selectedText: previousActiveFile.selectedText,
|
|
1079
|
+
isActive: true,
|
|
1080
|
+
timestamp: Date.now() - 1000,
|
|
1081
|
+
},
|
|
1082
|
+
],
|
|
1083
|
+
},
|
|
1084
|
+
};
|
|
1085
|
+
// Setup current context
|
|
1086
|
+
vi.mocked(ideContext.getIdeContext).mockReturnValue({
|
|
1087
|
+
workspaceState: {
|
|
1088
|
+
openFiles: [
|
|
1089
|
+
{ ...currentActiveFile, isActive: true, timestamp: Date.now() },
|
|
1090
|
+
],
|
|
1091
|
+
},
|
|
1092
|
+
});
|
|
1093
|
+
const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-id-delta');
|
|
1094
|
+
for await (const _ of stream) {
|
|
1095
|
+
// consume stream
|
|
1096
|
+
}
|
|
1097
|
+
const mockChat = client['chat'];
|
|
1098
|
+
if (shouldSendContext) {
|
|
1099
|
+
expect(mockChat.addHistory).toHaveBeenCalledWith(expect.objectContaining({
|
|
1100
|
+
parts: expect.arrayContaining([
|
|
1101
|
+
expect.objectContaining({
|
|
1102
|
+
text: expect.stringContaining("Here is a summary of changes in the user's editor context"),
|
|
1103
|
+
}),
|
|
1104
|
+
]),
|
|
1105
|
+
}));
|
|
1106
|
+
}
|
|
1107
|
+
else {
|
|
1108
|
+
expect(mockChat.addHistory).not.toHaveBeenCalled();
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
it('sends full context when history is cleared, even if editor state is unchanged', async () => {
|
|
1112
|
+
const activeFile = {
|
|
1113
|
+
path: '/path/to/active/file.ts',
|
|
1114
|
+
cursor: { line: 5, character: 10 },
|
|
1115
|
+
selectedText: 'hello',
|
|
1116
|
+
};
|
|
1117
|
+
// Setup previous context
|
|
1118
|
+
client['lastSentIdeContext'] = {
|
|
1119
|
+
workspaceState: {
|
|
1120
|
+
openFiles: [
|
|
1121
|
+
{
|
|
1122
|
+
path: activeFile.path,
|
|
1123
|
+
cursor: activeFile.cursor,
|
|
1124
|
+
selectedText: activeFile.selectedText,
|
|
1125
|
+
isActive: true,
|
|
1126
|
+
timestamp: Date.now() - 1000,
|
|
1127
|
+
},
|
|
1128
|
+
],
|
|
1129
|
+
},
|
|
1130
|
+
};
|
|
1131
|
+
// Setup current context (same as previous)
|
|
1132
|
+
vi.mocked(ideContext.getIdeContext).mockReturnValue({
|
|
1133
|
+
workspaceState: {
|
|
1134
|
+
openFiles: [
|
|
1135
|
+
{ ...activeFile, isActive: true, timestamp: Date.now() },
|
|
1136
|
+
],
|
|
1137
|
+
},
|
|
1138
|
+
});
|
|
1139
|
+
// Make history empty
|
|
1140
|
+
const mockChat = client['chat'];
|
|
1141
|
+
mockChat.getHistory.mockReturnValue([]);
|
|
1142
|
+
const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-id-history-cleared');
|
|
1143
|
+
for await (const _ of stream) {
|
|
1144
|
+
// consume stream
|
|
1145
|
+
}
|
|
1146
|
+
expect(mockChat.addHistory).toHaveBeenCalledWith(expect.objectContaining({
|
|
1147
|
+
parts: expect.arrayContaining([
|
|
1148
|
+
expect.objectContaining({
|
|
1149
|
+
text: expect.stringContaining("Here is the user's editor context"),
|
|
1150
|
+
}),
|
|
1151
|
+
]),
|
|
1152
|
+
}));
|
|
1153
|
+
// Also verify it's the full context, not a delta.
|
|
1154
|
+
const call = mockChat.addHistory.mock.calls[0][0];
|
|
1155
|
+
const contextText = call.parts[0].text;
|
|
1156
|
+
const contextJson = JSON.parse(contextText.match(/```json\n(.*)\n```/s)[1]);
|
|
1157
|
+
expect(contextJson).toHaveProperty('activeFile');
|
|
1158
|
+
expect(contextJson.activeFile.path).toBe('/path/to/active/file.ts');
|
|
1159
|
+
});
|
|
1160
|
+
});
|
|
916
1161
|
});
|
|
917
1162
|
describe('generateContent', () => {
|
|
918
1163
|
it('should use current model from config for content generation', async () => {
|
|
@@ -999,5 +1244,65 @@ Here are some files the user has open, with the most recent at the top:
|
|
|
999
1244
|
expect(mockFallbackHandler).toHaveBeenCalledWith(currentModel, fallbackModel, undefined);
|
|
1000
1245
|
});
|
|
1001
1246
|
});
|
|
1247
|
+
describe('setHistory', () => {
|
|
1248
|
+
it('should strip thought signatures when stripThoughts is true', () => {
|
|
1249
|
+
const mockChat = {
|
|
1250
|
+
setHistory: vi.fn(),
|
|
1251
|
+
};
|
|
1252
|
+
client['chat'] = mockChat;
|
|
1253
|
+
const historyWithThoughts = [
|
|
1254
|
+
{
|
|
1255
|
+
role: 'user',
|
|
1256
|
+
parts: [{ text: 'hello' }],
|
|
1257
|
+
},
|
|
1258
|
+
{
|
|
1259
|
+
role: 'model',
|
|
1260
|
+
parts: [
|
|
1261
|
+
{ text: 'thinking...', thoughtSignature: 'thought-123' },
|
|
1262
|
+
{
|
|
1263
|
+
functionCall: { name: 'test', args: {} },
|
|
1264
|
+
thoughtSignature: 'thought-456',
|
|
1265
|
+
},
|
|
1266
|
+
],
|
|
1267
|
+
},
|
|
1268
|
+
];
|
|
1269
|
+
client.setHistory(historyWithThoughts, { stripThoughts: true });
|
|
1270
|
+
const expectedHistory = [
|
|
1271
|
+
{
|
|
1272
|
+
role: 'user',
|
|
1273
|
+
parts: [{ text: 'hello' }],
|
|
1274
|
+
},
|
|
1275
|
+
{
|
|
1276
|
+
role: 'model',
|
|
1277
|
+
parts: [
|
|
1278
|
+
{ text: 'thinking...' },
|
|
1279
|
+
{ functionCall: { name: 'test', args: {} } },
|
|
1280
|
+
],
|
|
1281
|
+
},
|
|
1282
|
+
];
|
|
1283
|
+
expect(mockChat.setHistory).toHaveBeenCalledWith(expectedHistory);
|
|
1284
|
+
});
|
|
1285
|
+
it('should not strip thought signatures when stripThoughts is false', () => {
|
|
1286
|
+
const mockChat = {
|
|
1287
|
+
setHistory: vi.fn(),
|
|
1288
|
+
};
|
|
1289
|
+
client['chat'] = mockChat;
|
|
1290
|
+
const historyWithThoughts = [
|
|
1291
|
+
{
|
|
1292
|
+
role: 'user',
|
|
1293
|
+
parts: [{ text: 'hello' }],
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
role: 'model',
|
|
1297
|
+
parts: [
|
|
1298
|
+
{ text: 'thinking...', thoughtSignature: 'thought-123' },
|
|
1299
|
+
{ text: 'ok', thoughtSignature: 'thought-456' },
|
|
1300
|
+
],
|
|
1301
|
+
},
|
|
1302
|
+
];
|
|
1303
|
+
client.setHistory(historyWithThoughts, { stripThoughts: false });
|
|
1304
|
+
expect(mockChat.setHistory).toHaveBeenCalledWith(historyWithThoughts);
|
|
1305
|
+
});
|
|
1306
|
+
});
|
|
1002
1307
|
});
|
|
1003
1308
|
//# sourceMappingURL=client.test.js.map
|