@google/gemini-cli-core 0.18.0-nightly.20251120.2231497b1 → 0.18.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/src/agents/executor.js +12 -21
  2. package/dist/src/agents/executor.js.map +1 -1
  3. package/dist/src/agents/executor.test.js +53 -57
  4. package/dist/src/agents/executor.test.js.map +1 -1
  5. package/dist/src/agents/registry.d.ts +4 -0
  6. package/dist/src/agents/registry.js +23 -0
  7. package/dist/src/agents/registry.js.map +1 -1
  8. package/dist/src/agents/registry.test.js +30 -16
  9. package/dist/src/agents/registry.test.js.map +1 -1
  10. package/dist/src/code_assist/oauth-credential-storage.test.js +1 -0
  11. package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
  12. package/dist/src/code_assist/oauth2.test.js +5 -4
  13. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  14. package/dist/src/config/config.d.ts +5 -0
  15. package/dist/src/config/config.js +10 -0
  16. package/dist/src/config/config.js.map +1 -1
  17. package/dist/src/config/config.test.js +1 -0
  18. package/dist/src/config/config.test.js.map +1 -1
  19. package/dist/src/config/defaultModelConfigs.js +31 -4
  20. package/dist/src/config/defaultModelConfigs.js.map +1 -1
  21. package/dist/src/core/client.d.ts +1 -2
  22. package/dist/src/core/client.js +11 -23
  23. package/dist/src/core/client.js.map +1 -1
  24. package/dist/src/core/client.test.js +14 -38
  25. package/dist/src/core/client.test.js.map +1 -1
  26. package/dist/src/core/coreToolScheduler.d.ts +0 -2
  27. package/dist/src/core/coreToolScheduler.js +1 -3
  28. package/dist/src/core/coreToolScheduler.js.map +1 -1
  29. package/dist/src/core/coreToolScheduler.test.js +1 -17
  30. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  31. package/dist/src/core/geminiChat.d.ts +10 -5
  32. package/dist/src/core/geminiChat.js +37 -20
  33. package/dist/src/core/geminiChat.js.map +1 -1
  34. package/dist/src/core/geminiChat.test.js +96 -54
  35. package/dist/src/core/geminiChat.test.js.map +1 -1
  36. package/dist/src/core/logger.test.js +12 -11
  37. package/dist/src/core/logger.test.js.map +1 -1
  38. package/dist/src/core/nonInteractiveToolExecutor.js +6 -2
  39. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
  40. package/dist/src/core/prompts.test.js +4 -1
  41. package/dist/src/core/prompts.test.js.map +1 -1
  42. package/dist/src/core/turn.d.ts +2 -1
  43. package/dist/src/core/turn.js +2 -7
  44. package/dist/src/core/turn.js.map +1 -1
  45. package/dist/src/core/turn.test.js +18 -21
  46. package/dist/src/core/turn.test.js.map +1 -1
  47. package/dist/src/generated/git-commit.d.ts +2 -2
  48. package/dist/src/generated/git-commit.js +2 -2
  49. package/dist/src/generated/git-commit.js.map +1 -1
  50. package/dist/src/index.d.ts +1 -0
  51. package/dist/src/index.js +1 -0
  52. package/dist/src/index.js.map +1 -1
  53. package/dist/src/mcp/oauth-provider.test.js +1 -0
  54. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  55. package/dist/src/routing/modelRouterService.js +1 -1
  56. package/dist/src/routing/modelRouterService.js.map +1 -1
  57. package/dist/src/routing/strategies/classifierStrategy.test.js +4 -3
  58. package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
  59. package/dist/src/services/chatCompressionService.d.ts +1 -1
  60. package/dist/src/services/chatCompressionService.js +1 -1
  61. package/dist/src/services/modelConfig.integration.test.js +34 -0
  62. package/dist/src/services/modelConfig.integration.test.js.map +1 -1
  63. package/dist/src/services/modelConfigService.d.ts +2 -0
  64. package/dist/src/services/modelConfigService.js +7 -2
  65. package/dist/src/services/modelConfigService.js.map +1 -1
  66. package/dist/src/services/modelConfigService.test.js +22 -0
  67. package/dist/src/services/modelConfigService.test.js.map +1 -1
  68. package/dist/src/services/test-data/resolved-aliases.golden.json +37 -4
  69. package/dist/src/telemetry/activity-monitor.test.js +4 -1
  70. package/dist/src/telemetry/activity-monitor.test.js.map +1 -1
  71. package/dist/src/tools/mcp-client.test.js +1 -0
  72. package/dist/src/tools/mcp-client.test.js.map +1 -1
  73. package/dist/src/tools/modifiable-tool.d.ts +1 -1
  74. package/dist/src/tools/modifiable-tool.js +2 -2
  75. package/dist/src/tools/modifiable-tool.js.map +1 -1
  76. package/dist/src/tools/modifiable-tool.test.js +12 -11
  77. package/dist/src/tools/modifiable-tool.test.js.map +1 -1
  78. package/dist/src/utils/debugLogger.test.js +27 -25
  79. package/dist/src/utils/debugLogger.test.js.map +1 -1
  80. package/dist/src/utils/editor.d.ts +1 -1
  81. package/dist/src/utils/editor.js +3 -2
  82. package/dist/src/utils/editor.js.map +1 -1
  83. package/dist/src/utils/editor.test.js +7 -46
  84. package/dist/src/utils/editor.test.js.map +1 -1
  85. package/dist/src/utils/events.d.ts +33 -3
  86. package/dist/src/utils/events.js +35 -15
  87. package/dist/src/utils/events.js.map +1 -1
  88. package/dist/src/utils/events.test.js +86 -5
  89. package/dist/src/utils/events.test.js.map +1 -1
  90. package/dist/src/utils/installationManager.test.js +2 -1
  91. package/dist/src/utils/installationManager.test.js.map +1 -1
  92. package/dist/src/utils/llm-edit-fixer.test.js +2 -1
  93. package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
  94. package/dist/src/utils/memoryDiscovery.test.js +3 -2
  95. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  96. package/dist/src/utils/memoryImportProcessor.js +1 -1
  97. package/dist/src/utils/memoryImportProcessor.js.map +1 -1
  98. package/dist/src/utils/memoryImportProcessor.test.js +8 -14
  99. package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
  100. package/dist/src/utils/nextSpeakerChecker.test.js +3 -1
  101. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  102. package/dist/src/utils/systemEncoding.test.js +2 -1
  103. package/dist/src/utils/systemEncoding.test.js.map +1 -1
  104. package/dist/src/utils/userAccountManager.test.js +7 -6
  105. package/dist/src/utils/userAccountManager.test.js.map +1 -1
  106. package/dist/src/utils/workspaceContext.test.js +5 -4
  107. package/dist/src/utils/workspaceContext.test.js.map +1 -1
  108. package/dist/tsconfig.tsbuildinfo +1 -1
  109. package/package.json +1 -1
  110. package/dist/google-gemini-cli-core-0.18.0-nightly.20251118.86828bb56.tgz +0 -0
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
- import { ApiError } from '@google/genai';
7
+ import { ApiError, ThinkingLevel } from '@google/genai';
8
8
  import { GeminiChat, InvalidStreamError, StreamEventType, SYNTHETIC_THOUGHT_SIGNATURE, } from './geminiChat.js';
9
9
  import { setSimulate429 } from '../utils/testUtils.js';
10
10
  import { DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_MODEL, PREVIEW_GEMINI_MODEL, } from '../config/models.js';
@@ -65,7 +65,6 @@ describe('GeminiChat', () => {
65
65
  let mockContentGenerator;
66
66
  let chat;
67
67
  let mockConfig;
68
- const config = {};
69
68
  beforeEach(() => {
70
69
  vi.clearAllMocks();
71
70
  vi.mocked(uiTelemetryService.setLastPromptTokenCount).mockClear();
@@ -104,6 +103,17 @@ describe('GeminiChat', () => {
104
103
  }),
105
104
  getContentGenerator: vi.fn().mockReturnValue(mockContentGenerator),
106
105
  getRetryFetchErrors: vi.fn().mockReturnValue(false),
106
+ modelConfigService: {
107
+ getResolvedConfig: vi.fn().mockImplementation((modelConfigKey) => ({
108
+ model: modelConfigKey.model,
109
+ generateContentConfig: {
110
+ temperature: 0,
111
+ thinkingConfig: {
112
+ thinkingBudget: 1000,
113
+ },
114
+ },
115
+ })),
116
+ },
107
117
  isPreviewModelBypassMode: vi.fn().mockReturnValue(false),
108
118
  setPreviewModelBypassMode: vi.fn(),
109
119
  isPreviewModelFallbackMode: vi.fn().mockReturnValue(false),
@@ -113,7 +123,7 @@ describe('GeminiChat', () => {
113
123
  // Disable 429 simulation for tests
114
124
  setSimulate429(false);
115
125
  // Reset history for each test by creating a new instance
116
- chat = new GeminiChat(mockConfig, config, []);
126
+ chat = new GeminiChat(mockConfig);
117
127
  });
118
128
  afterEach(() => {
119
129
  vi.restoreAllMocks();
@@ -125,12 +135,12 @@ describe('GeminiChat', () => {
125
135
  { role: 'user', parts: [{ text: 'Hello' }] },
126
136
  { role: 'model', parts: [{ text: 'Hi there' }] },
127
137
  ];
128
- const chatWithHistory = new GeminiChat(mockConfig, config, history);
138
+ const chatWithHistory = new GeminiChat(mockConfig, '', [], history);
129
139
  const estimatedTokens = Math.ceil(JSON.stringify(history).length / 4);
130
140
  expect(chatWithHistory.getLastPromptTokenCount()).toBe(estimatedTokens);
131
141
  });
132
142
  it('should initialize lastPromptTokenCount for empty history', () => {
133
- const chatEmpty = new GeminiChat(mockConfig, config, []);
143
+ const chatEmpty = new GeminiChat(mockConfig);
134
144
  expect(chatEmpty.getLastPromptTokenCount()).toBe(Math.ceil(JSON.stringify([]).length / 4));
135
145
  });
136
146
  });
@@ -163,7 +173,7 @@ describe('GeminiChat', () => {
163
173
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithToolCall);
164
174
  // 2. Action & Assert: The stream processing should complete without throwing an error
165
175
  // because the presence of a tool call makes the empty final chunk acceptable.
166
- const stream = await chat.sendMessageStream('test-model', { message: 'test message' }, 'prompt-id-tool-call-empty-end');
176
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-tool-call-empty-end', new AbortController().signal);
167
177
  await expect((async () => {
168
178
  for await (const _ of stream) {
169
179
  /* consume stream */
@@ -203,7 +213,7 @@ describe('GeminiChat', () => {
203
213
  })();
204
214
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithNoFinish);
205
215
  // 2. Action & Assert: The stream should fail because there's no finish reason.
206
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test message' }, 'prompt-id-no-finish-empty-end');
216
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test message', 'prompt-id-no-finish-empty-end', new AbortController().signal);
207
217
  await expect((async () => {
208
218
  for await (const _ of stream) {
209
219
  /* consume stream */
@@ -238,7 +248,7 @@ describe('GeminiChat', () => {
238
248
  })();
239
249
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithInvalidEnd);
240
250
  // 2. Action & Assert: The stream should complete without throwing an error.
241
- const stream = await chat.sendMessageStream('test-model', { message: 'test message' }, 'prompt-id-valid-then-invalid-end');
251
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-valid-then-invalid-end', new AbortController().signal);
242
252
  await expect((async () => {
243
253
  for await (const _ of stream) {
244
254
  /* consume stream */
@@ -273,7 +283,7 @@ describe('GeminiChat', () => {
273
283
  })();
274
284
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(multiChunkStream);
275
285
  // 2. Action: Send a message and consume the stream.
276
- const stream = await chat.sendMessageStream('test-model', { message: 'test message' }, 'prompt-id-empty-chunk-consolidation');
286
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-empty-chunk-consolidation', new AbortController().signal);
277
287
  for await (const _ of stream) {
278
288
  // Consume the stream
279
289
  }
@@ -321,7 +331,7 @@ describe('GeminiChat', () => {
321
331
  })();
322
332
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(multiChunkStream);
323
333
  // 2. Action: Send a message and consume the stream.
324
- const stream = await chat.sendMessageStream('test-model', { message: 'test message' }, 'prompt-id-multi-chunk');
334
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-multi-chunk', new AbortController().signal);
325
335
  for await (const _ of stream) {
326
336
  // Consume the stream to trigger history recording.
327
337
  }
@@ -357,7 +367,7 @@ describe('GeminiChat', () => {
357
367
  })();
358
368
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(mixedContentStream);
359
369
  // 2. Action: Send a message and fully consume the stream to trigger history recording.
360
- const stream = await chat.sendMessageStream('test-model', { message: 'test message' }, 'prompt-id-mixed-chunk');
370
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-mixed-chunk', new AbortController().signal);
361
371
  for await (const _ of stream) {
362
372
  // This loop consumes the stream.
363
373
  }
@@ -385,7 +395,7 @@ describe('GeminiChat', () => {
385
395
  ],
386
396
  };
387
397
  })());
388
- const stream = await chat.sendMessageStream(PREVIEW_GEMINI_MODEL, { message: 'test' }, 'prompt-id-fast-retry');
398
+ const stream = await chat.sendMessageStream({ model: PREVIEW_GEMINI_MODEL }, 'test', 'prompt-id-fast-retry', new AbortController().signal);
389
399
  for await (const _ of stream) {
390
400
  // consume stream
391
401
  }
@@ -405,7 +415,7 @@ describe('GeminiChat', () => {
405
415
  ],
406
416
  };
407
417
  })());
408
- const stream = await chat.sendMessageStream(DEFAULT_GEMINI_FLASH_MODEL, { message: 'test' }, 'prompt-id-normal-retry');
418
+ const stream = await chat.sendMessageStream({ model: DEFAULT_GEMINI_FLASH_MODEL }, 'test', 'prompt-id-normal-retry', new AbortController().signal);
409
419
  for await (const _ of stream) {
410
420
  // consume stream
411
421
  }
@@ -437,7 +447,7 @@ describe('GeminiChat', () => {
437
447
  }));
438
448
  // ACT
439
449
  const consumeStream = async () => {
440
- const stream = await chat.sendMessageStream(PREVIEW_GEMINI_MODEL, { message: 'test' }, 'prompt-id-bypass');
450
+ const stream = await chat.sendMessageStream({ model: PREVIEW_GEMINI_MODEL }, 'test', 'prompt-id-bypass', new AbortController().signal);
441
451
  // Consume the stream to trigger execution
442
452
  for await (const _ of stream) {
443
453
  // do nothing
@@ -484,14 +494,12 @@ describe('GeminiChat', () => {
484
494
  })();
485
495
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(emptyStreamResponse);
486
496
  // 3. Action: Send the function response back to the model and consume the stream.
487
- const stream = await chat.sendMessageStream('gemini-2.0-flash', {
488
- message: {
489
- functionResponse: {
490
- name: 'find_restaurant',
491
- response: { name: 'Vesuvio' },
492
- },
497
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, {
498
+ functionResponse: {
499
+ name: 'find_restaurant',
500
+ response: { name: 'Vesuvio' },
493
501
  },
494
- }, 'prompt-id-stream-1');
502
+ }, 'prompt-id-stream-1', new AbortController().signal);
495
503
  // 4. Assert: The stream processing should throw an InvalidStreamError.
496
504
  await expect((async () => {
497
505
  for await (const _ of stream) {
@@ -522,7 +530,7 @@ describe('GeminiChat', () => {
522
530
  };
523
531
  })();
524
532
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithToolCall);
525
- const stream = await chat.sendMessageStream('test-model', { message: 'test' }, 'prompt-id-1');
533
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-1', new AbortController().signal);
526
534
  // Should not throw an error
527
535
  await expect((async () => {
528
536
  for await (const _ of stream) {
@@ -546,7 +554,7 @@ describe('GeminiChat', () => {
546
554
  };
547
555
  })();
548
556
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithoutFinishReason);
549
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-1');
557
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test message', 'prompt-id-1', new AbortController().signal);
550
558
  await expect((async () => {
551
559
  for await (const _ of stream) {
552
560
  // consume stream
@@ -569,7 +577,7 @@ describe('GeminiChat', () => {
569
577
  };
570
578
  })();
571
579
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithEmptyResponse);
572
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-1');
580
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test message', 'prompt-id-1', new AbortController().signal);
573
581
  await expect((async () => {
574
582
  for await (const _ of stream) {
575
583
  // consume stream
@@ -592,7 +600,7 @@ describe('GeminiChat', () => {
592
600
  };
593
601
  })();
594
602
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(validStream);
595
- const stream = await chat.sendMessageStream('test-model', { message: 'test' }, 'prompt-id-1');
603
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-1', new AbortController().signal);
596
604
  // Should not throw an error
597
605
  await expect((async () => {
598
606
  for await (const _ of stream) {
@@ -616,7 +624,7 @@ describe('GeminiChat', () => {
616
624
  };
617
625
  })();
618
626
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(streamWithMalformedFunctionCall);
619
- const stream = await chat.sendMessageStream('gemini-2.5-pro', { message: 'test' }, 'prompt-id-malformed');
627
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.5-pro' }, 'test', 'prompt-id-malformed', new AbortController().signal);
620
628
  // Should throw an error
621
629
  await expect((async () => {
622
630
  for await (const _ of stream) {
@@ -650,7 +658,7 @@ describe('GeminiChat', () => {
650
658
  };
651
659
  })());
652
660
  // 2. Send a message
653
- const stream = await chat.sendMessageStream('gemini-2.5-pro', { message: 'test retry' }, 'prompt-id-retry-malformed');
661
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.5-pro' }, 'test retry', 'prompt-id-retry-malformed', new AbortController().signal);
654
662
  const events = [];
655
663
  for await (const event of stream) {
656
664
  events.push(event);
@@ -688,7 +696,7 @@ describe('GeminiChat', () => {
688
696
  };
689
697
  })();
690
698
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(response);
691
- const stream = await chat.sendMessageStream('test-model', { message: 'hello' }, 'prompt-id-1');
699
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'hello', 'prompt-id-1', new AbortController().signal);
692
700
  for await (const _ of stream) {
693
701
  // consume stream
694
702
  }
@@ -700,9 +708,43 @@ describe('GeminiChat', () => {
700
708
  parts: [{ text: 'hello' }],
701
709
  },
702
710
  ],
703
- config: {},
711
+ config: {
712
+ systemInstruction: '',
713
+ tools: [],
714
+ temperature: 0,
715
+ thinkingConfig: {
716
+ thinkingBudget: 1000,
717
+ },
718
+ abortSignal: expect.any(AbortSignal),
719
+ },
704
720
  }, 'prompt-id-1');
705
721
  });
722
+ it('should use thinkingLevel and remove thinkingBudget for gemini-3 models', async () => {
723
+ const response = (async function* () {
724
+ yield {
725
+ candidates: [
726
+ {
727
+ content: { parts: [{ text: 'response' }], role: 'model' },
728
+ finishReason: 'STOP',
729
+ },
730
+ ],
731
+ };
732
+ })();
733
+ vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(response);
734
+ const stream = await chat.sendMessageStream({ model: 'gemini-3-test-only-model-string-for-testing' }, 'hello', 'prompt-id-thinking-level', new AbortController().signal);
735
+ for await (const _ of stream) {
736
+ // consume stream
737
+ }
738
+ expect(mockContentGenerator.generateContentStream).toHaveBeenCalledWith(expect.objectContaining({
739
+ model: 'gemini-3-test-only-model-string-for-testing',
740
+ config: expect.objectContaining({
741
+ thinkingConfig: {
742
+ thinkingBudget: undefined,
743
+ thinkingLevel: ThinkingLevel.HIGH,
744
+ },
745
+ }),
746
+ }), 'prompt-id-thinking-level');
747
+ });
706
748
  });
707
749
  describe('addHistory', () => {
708
750
  it('should add a new content item to the history', () => {
@@ -740,7 +782,7 @@ describe('GeminiChat', () => {
740
782
  candidates: [{ content: { parts: [{ text: '' }] } }],
741
783
  };
742
784
  })());
743
- const stream = await chat.sendMessageStream('gemini-1.5-pro', { message: 'test' }, 'prompt-id-no-retry');
785
+ const stream = await chat.sendMessageStream({ model: 'gemini-1.5-pro' }, 'test', 'prompt-id-no-retry', new AbortController().signal);
744
786
  await expect((async () => {
745
787
  for await (const _ of stream) {
746
788
  // Must loop to trigger the internal logic that throws.
@@ -773,7 +815,7 @@ describe('GeminiChat', () => {
773
815
  };
774
816
  })());
775
817
  // ACT: Send a message and collect all events from the stream.
776
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-yield-retry');
818
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test message', 'prompt-id-yield-retry', new AbortController().signal);
777
819
  const events = [];
778
820
  for await (const event of stream) {
779
821
  events.push(event);
@@ -805,7 +847,7 @@ describe('GeminiChat', () => {
805
847
  ],
806
848
  };
807
849
  })());
808
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-retry-success');
850
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test', 'prompt-id-retry-success', new AbortController().signal);
809
851
  const chunks = [];
810
852
  for await (const chunk of stream) {
811
853
  chunks.push(chunk);
@@ -856,7 +898,7 @@ describe('GeminiChat', () => {
856
898
  ],
857
899
  };
858
900
  })());
859
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test', config: { temperature: 0.5 } }, 'prompt-id-retry-temperature');
901
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test message', 'prompt-id-retry-temperature', new AbortController().signal);
860
902
  for await (const _ of stream) {
861
903
  // consume stream
862
904
  }
@@ -864,7 +906,7 @@ describe('GeminiChat', () => {
864
906
  // First call should have original temperature
865
907
  expect(mockContentGenerator.generateContentStream).toHaveBeenNthCalledWith(1, expect.objectContaining({
866
908
  config: expect.objectContaining({
867
- temperature: 0.5,
909
+ temperature: 0,
868
910
  }),
869
911
  }), 'prompt-id-retry-temperature');
870
912
  // Second call (retry) should have temperature 1
@@ -887,7 +929,7 @@ describe('GeminiChat', () => {
887
929
  ],
888
930
  };
889
931
  })());
890
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-retry-fail');
932
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test', 'prompt-id-retry-fail', new AbortController().signal);
891
933
  await expect(async () => {
892
934
  for await (const _ of stream) {
893
935
  // Must loop to trigger the internal logic that throws.
@@ -936,7 +978,7 @@ describe('GeminiChat', () => {
936
978
  it('should not retry on 400 Bad Request errors', async () => {
937
979
  const error400 = new ApiError({ message: 'Bad Request', status: 400 });
938
980
  vi.mocked(mockContentGenerator.generateContentStream).mockRejectedValue(error400);
939
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-400');
981
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test message', 'prompt-id-400', new AbortController().signal);
940
982
  await expect((async () => {
941
983
  for await (const _ of stream) {
942
984
  /* consume stream */
@@ -959,7 +1001,7 @@ describe('GeminiChat', () => {
959
1001
  ],
960
1002
  };
961
1003
  })());
962
- const stream = await chat.sendMessageStream('test-model', { message: 'test' }, 'prompt-id-429-retry');
1004
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-429-retry', new AbortController().signal);
963
1005
  const events = [];
964
1006
  for await (const event of stream) {
965
1007
  events.push(event);
@@ -988,7 +1030,7 @@ describe('GeminiChat', () => {
988
1030
  ],
989
1031
  };
990
1032
  })());
991
- const stream = await chat.sendMessageStream('test-model', { message: 'test' }, 'prompt-id-500-retry');
1033
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-500-retry', new AbortController().signal);
992
1034
  const events = [];
993
1035
  for await (const event of stream) {
994
1036
  events.push(event);
@@ -1024,7 +1066,7 @@ describe('GeminiChat', () => {
1024
1066
  throw error;
1025
1067
  }
1026
1068
  });
1027
- const stream = await chat.sendMessageStream('test-model', { message: 'test' }, 'prompt-id-fetch-error-retry');
1069
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-fetch-error-retry', new AbortController().signal);
1028
1070
  const events = [];
1029
1071
  for await (const event of stream) {
1030
1072
  events.push(event);
@@ -1067,7 +1109,7 @@ describe('GeminiChat', () => {
1067
1109
  };
1068
1110
  })());
1069
1111
  // 3. Send a new message
1070
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'Second question' }, 'prompt-id-retry-existing');
1112
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'Second question', 'prompt-id-retry-existing', new AbortController().signal);
1071
1113
  for await (const _ of stream) {
1072
1114
  // consume stream
1073
1115
  }
@@ -1119,7 +1161,7 @@ describe('GeminiChat', () => {
1119
1161
  };
1120
1162
  })());
1121
1163
  // 2. Call the method and consume the stream.
1122
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test empty stream' }, 'prompt-id-empty-stream');
1164
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test empty stream', 'prompt-id-empty-stream', new AbortController().signal);
1123
1165
  const chunks = [];
1124
1166
  for await (const chunk of stream) {
1125
1167
  chunks.push(chunk);
@@ -1180,11 +1222,11 @@ describe('GeminiChat', () => {
1180
1222
  .mockResolvedValueOnce(firstStreamGenerator)
1181
1223
  .mockResolvedValueOnce(secondStreamGenerator);
1182
1224
  // 3. Start the first stream and consume only the first chunk to pause it
1183
- const firstStream = await chat.sendMessageStream('test-model', { message: 'first' }, 'prompt-1');
1225
+ const firstStream = await chat.sendMessageStream({ model: 'test-model' }, 'first', 'prompt-1', new AbortController().signal);
1184
1226
  const firstStreamIterator = firstStream[Symbol.asyncIterator]();
1185
1227
  await firstStreamIterator.next();
1186
1228
  // 4. While the first stream is paused, start the second call. It will block.
1187
- const secondStreamPromise = chat.sendMessageStream('test-model', { message: 'second' }, 'prompt-2');
1229
+ const secondStreamPromise = chat.sendMessageStream({ model: 'test-model' }, 'second', 'prompt-2', new AbortController().signal);
1188
1230
  // 5. Assert that only one API call has been made so far.
1189
1231
  expect(mockContentGenerator.generateContentStream).toHaveBeenCalledTimes(1);
1190
1232
  // 6. Unblock and fully consume the first stream to completion.
@@ -1224,7 +1266,7 @@ describe('GeminiChat', () => {
1224
1266
  vi.mocked(mockContentGenerator.generateContentStream).mockImplementation(async () => (async function* () {
1225
1267
  yield mockResponse;
1226
1268
  })());
1227
- const stream = await chat.sendMessageStream('test-model', { message: 'test' }, 'prompt-id-res3');
1269
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'test message', 'prompt-id-res3', new AbortController().signal);
1228
1270
  for await (const _ of stream) {
1229
1271
  // consume stream
1230
1272
  }
@@ -1287,7 +1329,7 @@ describe('GeminiChat', () => {
1287
1329
  isInFallbackModeSpy.mockReturnValue(true);
1288
1330
  return true; // Signal retry
1289
1331
  });
1290
- const stream = await chat.sendMessageStream('test-model', { message: 'trigger 429' }, 'prompt-id-fb1');
1332
+ const stream = await chat.sendMessageStream({ model: 'test-model' }, 'trigger 429', 'prompt-id-fb1', new AbortController().signal);
1291
1333
  // Consume stream to trigger logic
1292
1334
  for await (const _ of stream) {
1293
1335
  // no-op
@@ -1303,7 +1345,7 @@ describe('GeminiChat', () => {
1303
1345
  vi.mocked(mockConfig.getModel).mockReturnValue('gemini-pro');
1304
1346
  vi.mocked(mockContentGenerator.generateContentStream).mockRejectedValue(error429);
1305
1347
  mockHandleFallback.mockResolvedValue(false);
1306
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test stop' }, 'prompt-id-fb2');
1348
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test stop', 'prompt-id-fb2', new AbortController().signal);
1307
1349
  await expect((async () => {
1308
1350
  for await (const _ of stream) {
1309
1351
  /* consume stream */
@@ -1347,7 +1389,7 @@ describe('GeminiChat', () => {
1347
1389
  };
1348
1390
  })());
1349
1391
  // Send a message and consume the stream
1350
- const stream = await chat.sendMessageStream('gemini-2.0-flash', { message: 'test' }, 'prompt-id-discard-test');
1392
+ const stream = await chat.sendMessageStream({ model: 'gemini-2.0-flash' }, 'test message', 'prompt-id-discard-test', new AbortController().signal);
1351
1393
  const events = [];
1352
1394
  for await (const event of stream) {
1353
1395
  events.push(event);
@@ -1411,7 +1453,7 @@ describe('GeminiChat', () => {
1411
1453
  };
1412
1454
  })();
1413
1455
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
1414
- await chat.sendMessageStream('test-model', { message: 'test' }, 'prompt-id-preview-model-reset');
1456
+ await chat.sendMessageStream({ model: 'test-model' }, 'test', 'prompt-id-preview-model-reset', new AbortController().signal);
1415
1457
  expect(mockConfig.setPreviewModelBypassMode).toHaveBeenCalledWith(false);
1416
1458
  });
1417
1459
  it('should reset previewModelFallbackMode to false upon successful Preview Model usage', async () => {
@@ -1426,7 +1468,7 @@ describe('GeminiChat', () => {
1426
1468
  };
1427
1469
  })();
1428
1470
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
1429
- const resultStream = await chat.sendMessageStream(PREVIEW_GEMINI_MODEL, { message: 'test' }, 'prompt-id-preview-model-healing');
1471
+ const resultStream = await chat.sendMessageStream({ model: PREVIEW_GEMINI_MODEL }, 'test', 'prompt-id-preview-model-healing', new AbortController().signal);
1430
1472
  for await (const _ of resultStream) {
1431
1473
  // consume stream
1432
1474
  }
@@ -1446,7 +1488,7 @@ describe('GeminiChat', () => {
1446
1488
  vi.mocked(mockContentGenerator.generateContentStream).mockResolvedValue(stream);
1447
1489
  // Simulate bypass mode being active (downgrade happened)
1448
1490
  vi.mocked(mockConfig.isPreviewModelBypassMode).mockReturnValue(true);
1449
- const resultStream = await chat.sendMessageStream(PREVIEW_GEMINI_MODEL, { message: 'test' }, 'prompt-id-bypass-no-healing');
1491
+ const resultStream = await chat.sendMessageStream({ model: PREVIEW_GEMINI_MODEL }, 'test', 'prompt-id-bypass-no-healing', new AbortController().signal);
1450
1492
  for await (const _ of resultStream) {
1451
1493
  // consume stream
1452
1494
  }
@@ -1455,7 +1497,7 @@ describe('GeminiChat', () => {
1455
1497
  });
1456
1498
  describe('ensureActiveLoopHasThoughtSignatures', () => {
1457
1499
  it('should add thoughtSignature to the first functionCall in each model turn of the active loop', () => {
1458
- const chat = new GeminiChat(mockConfig, {}, []);
1500
+ const chat = new GeminiChat(mockConfig, '', [], []);
1459
1501
  const history = [
1460
1502
  { role: 'user', parts: [{ text: 'Old message' }] },
1461
1503
  {
@@ -1504,7 +1546,7 @@ describe('GeminiChat', () => {
1504
1546
  expect(newContents[5]?.parts?.[1]).not.toHaveProperty('thoughtSignature');
1505
1547
  });
1506
1548
  it('should not modify contents if there is no user text message', () => {
1507
- const chat = new GeminiChat(mockConfig, {}, []);
1549
+ const chat = new GeminiChat(mockConfig, '', [], []);
1508
1550
  const history = [
1509
1551
  {
1510
1552
  role: 'user',
@@ -1520,13 +1562,13 @@ describe('GeminiChat', () => {
1520
1562
  expect(newContents[1]?.parts?.[0]).not.toHaveProperty('thoughtSignature');
1521
1563
  });
1522
1564
  it('should handle an empty history', () => {
1523
- const chat = new GeminiChat(mockConfig, {}, []);
1565
+ const chat = new GeminiChat(mockConfig, '', []);
1524
1566
  const history = [];
1525
1567
  const newContents = chat.ensureActiveLoopHasThoughtSignatures(history);
1526
1568
  expect(newContents).toEqual([]);
1527
1569
  });
1528
1570
  it('should handle history with only a user message', () => {
1529
- const chat = new GeminiChat(mockConfig, {}, []);
1571
+ const chat = new GeminiChat(mockConfig, '', []);
1530
1572
  const history = [{ role: 'user', parts: [{ text: 'Hello' }] }];
1531
1573
  const newContents = chat.ensureActiveLoopHasThoughtSignatures(history);
1532
1574
  expect(newContents).toEqual(history);