@google/gemini-cli-a2a-server 0.22.0-preview.0 → 0.22.0-preview.2

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.
@@ -311099,28 +311099,6 @@ var ApiResponseEvent = class {
311099
311099
  return logRecord;
311100
311100
  }
311101
311101
  };
311102
- var EVENT_FLASH_FALLBACK = "gemini_cli.flash_fallback";
311103
- var FlashFallbackEvent = class {
311104
- "event.name";
311105
- "event.timestamp";
311106
- auth_type;
311107
- constructor(auth_type) {
311108
- this["event.name"] = "flash_fallback";
311109
- this["event.timestamp"] = (/* @__PURE__ */ new Date()).toISOString();
311110
- this.auth_type = auth_type;
311111
- }
311112
- toOpenTelemetryAttributes(config3) {
311113
- return {
311114
- ...getCommonAttributes(config3),
311115
- "event.name": EVENT_FLASH_FALLBACK,
311116
- "event.timestamp": this["event.timestamp"],
311117
- auth_type: this.auth_type
311118
- };
311119
- }
311120
- toLogBody() {
311121
- return `Switching to flash as Fallback.`;
311122
- }
311123
- };
311124
311102
  var EVENT_RIPGREP_FALLBACK = "gemini_cli.ripgrep_fallback";
311125
311103
  var RipgrepFallbackEvent = class {
311126
311104
  error;
@@ -311926,8 +311904,8 @@ var Float64Vector = import_vector.default.Float64Vector;
311926
311904
  var PointerVector = import_vector.default.PointerVector;
311927
311905
 
311928
311906
  // packages/core/dist/src/generated/git-commit.js
311929
- var GIT_COMMIT_INFO = "5ea5107d0";
311930
- var CLI_VERSION = "0.22.0-preview.0";
311907
+ var GIT_COMMIT_INFO = "a585bfa99";
311908
+ var CLI_VERSION = "0.22.0-preview.2";
311931
311909
 
311932
311910
  // packages/core/dist/src/ide/detect-ide.js
311933
311911
  var IDE_DEFINITIONS = {
@@ -314465,17 +314443,6 @@ function logApiRequest(config3, event) {
314465
314443
  logger6.emit(event.toSemanticLogRecord(config3));
314466
314444
  });
314467
314445
  }
314468
- function logFlashFallback(config3, event) {
314469
- ClearcutLogger.getInstance(config3)?.logFlashFallbackEvent();
314470
- bufferTelemetryEvent(() => {
314471
- const logger6 = import_api_logs.logs.getLogger(SERVICE_NAME);
314472
- const logRecord = {
314473
- body: event.toLogBody(),
314474
- attributes: event.toOpenTelemetryAttributes(config3)
314475
- };
314476
- logger6.emit(logRecord);
314477
- });
314478
- }
314479
314446
  function logRipgrepFallback(config3, event) {
314480
314447
  ClearcutLogger.getInstance(config3)?.logRipgrepFallbackEvent();
314481
314448
  bufferTelemetryEvent(() => {
@@ -315115,7 +315082,7 @@ async function createContentGenerator(config3, gcConfig, sessionId2) {
315115
315082
  return FakeContentGenerator.fromFile(gcConfig.fakeResponses);
315116
315083
  }
315117
315084
  const version4 = await getVersion();
315118
- const model = getEffectiveModel(gcConfig.isInFallbackMode(), gcConfig.getModel(), gcConfig.getPreviewFeatures());
315085
+ const model = getEffectiveModel(gcConfig.getModel(), gcConfig.getPreviewFeatures());
315119
315086
  const customHeadersEnv = process.env["GEMINI_CLI_CUSTOM_HEADERS"] || void 0;
315120
315087
  const userAgent = `GeminiCLI/${version4}/${model} (${process.platform}; ${process.arch})`;
315121
315088
  const customHeadersMap = parseCustomHeaders(customHeadersEnv);
@@ -352629,114 +352596,88 @@ async function modifyWithEditor(originalParams, modifyContext, editorType, _abor
352629
352596
  // packages/core/dist/src/utils/llm-edit-fixer.js
352630
352597
  import { createHash as createHash8 } from "node:crypto";
352631
352598
 
352632
- // packages/core/dist/src/utils/partUtils.js
352633
- function partToString(value, options2) {
352634
- if (!value) {
352635
- return "";
352636
- }
352637
- if (typeof value === "string") {
352638
- return value;
352639
- }
352640
- if (Array.isArray(value)) {
352641
- return value.map((part2) => partToString(part2, options2)).join("");
352599
+ // packages/core/dist/src/utils/secure-browser-launcher.js
352600
+ import { execFile as execFile6 } from "node:child_process";
352601
+ import { promisify as promisify13 } from "node:util";
352602
+ import { platform as platform10 } from "node:os";
352603
+ import { URL as URL6 } from "node:url";
352604
+ var execFileAsync5 = promisify13(execFile6);
352605
+ function validateUrl(url5) {
352606
+ let parsedUrl;
352607
+ try {
352608
+ parsedUrl = new URL6(url5);
352609
+ } catch (_error) {
352610
+ throw new Error(`Invalid URL: ${url5}`);
352642
352611
  }
352643
- const part = value;
352644
- if (options2?.verbose) {
352645
- if (part.videoMetadata !== void 0) {
352646
- return `[Video Metadata]`;
352647
- }
352648
- if (part.thought !== void 0) {
352649
- return `[Thought: ${part.thought}]`;
352650
- }
352651
- if (part.codeExecutionResult !== void 0) {
352652
- return `[Code Execution Result]`;
352653
- }
352654
- if (part.executableCode !== void 0) {
352655
- return `[Executable Code]`;
352656
- }
352657
- if (part.fileData !== void 0) {
352658
- return `[File Data]`;
352659
- }
352660
- if (part.functionCall !== void 0) {
352661
- return `[Function Call: ${part.functionCall.name}]`;
352662
- }
352663
- if (part.functionResponse !== void 0) {
352664
- return `[Function Response: ${part.functionResponse.name}]`;
352665
- }
352666
- if (part.inlineData !== void 0) {
352667
- return `<${part.inlineData.mimeType}>`;
352668
- }
352612
+ if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
352613
+ throw new Error(`Unsafe protocol: ${parsedUrl.protocol}. Only HTTP and HTTPS are allowed.`);
352669
352614
  }
352670
- return part.text ?? "";
352671
- }
352672
- function getResponseText(response) {
352673
- if (response.candidates && response.candidates.length > 0) {
352674
- const candidate = response.candidates[0];
352675
- if (candidate.content && candidate.content.parts && candidate.content.parts.length > 0) {
352676
- return candidate.content.parts.filter((part) => part.text).map((part) => part.text).join("");
352677
- }
352615
+ if (/[\r\n\x00-\x1f]/.test(url5)) {
352616
+ throw new Error("URL contains invalid characters");
352678
352617
  }
352679
- return null;
352680
352618
  }
352681
-
352682
- // packages/core/dist/src/utils/errorReporting.js
352683
- import fs40 from "node:fs/promises";
352684
- import os13 from "node:os";
352685
- import path40 from "node:path";
352686
- async function reportError(error2, baseMessage, context2, type = "general", reportingDir = os13.tmpdir()) {
352687
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
352688
- const reportFileName = `gemini-client-error-${type}-${timestamp}.json`;
352689
- const reportPath = path40.join(reportingDir, reportFileName);
352690
- let errorToReport;
352691
- if (error2 instanceof Error) {
352692
- errorToReport = { message: error2.message, stack: error2.stack };
352693
- } else if (typeof error2 === "object" && error2 !== null && "message" in error2) {
352694
- errorToReport = {
352695
- message: String(error2.message)
352696
- };
352697
- } else {
352698
- errorToReport = { message: String(error2) };
352699
- }
352700
- const reportContent = { error: errorToReport };
352701
- if (context2) {
352702
- reportContent.context = context2;
352703
- }
352704
- let stringifiedReportContent;
352705
- try {
352706
- stringifiedReportContent = JSON.stringify(reportContent, null, 2);
352707
- } catch (stringifyError) {
352708
- console.error(`${baseMessage} Could not stringify report content (likely due to context):`, stringifyError);
352709
- console.error("Original error that triggered report generation:", error2);
352710
- if (context2) {
352711
- console.error("Original context could not be stringified or included in report.");
352712
- }
352713
- try {
352714
- const minimalReportContent = { error: errorToReport };
352715
- stringifiedReportContent = JSON.stringify(minimalReportContent, null, 2);
352716
- await fs40.writeFile(reportPath, stringifiedReportContent);
352717
- console.error(`${baseMessage} Partial report (excluding context) available at: ${reportPath}`);
352718
- } catch (minimalWriteError) {
352719
- console.error(`${baseMessage} Failed to write even a minimal error report:`, minimalWriteError);
352720
- }
352721
- return;
352619
+ async function openBrowserSecurely(url5) {
352620
+ validateUrl(url5);
352621
+ const platformName = platform10();
352622
+ let command;
352623
+ let args2;
352624
+ switch (platformName) {
352625
+ case "darwin":
352626
+ command = "open";
352627
+ args2 = [url5];
352628
+ break;
352629
+ case "win32":
352630
+ command = "powershell.exe";
352631
+ args2 = [
352632
+ "-NoProfile",
352633
+ "-NonInteractive",
352634
+ "-WindowStyle",
352635
+ "Hidden",
352636
+ "-Command",
352637
+ `Start-Process '${url5.replace(/'/g, "''")}'`
352638
+ ];
352639
+ break;
352640
+ case "linux":
352641
+ case "freebsd":
352642
+ case "openbsd":
352643
+ command = "xdg-open";
352644
+ args2 = [url5];
352645
+ break;
352646
+ default:
352647
+ throw new Error(`Unsupported platform: ${platformName}`);
352722
352648
  }
352649
+ const options2 = {
352650
+ // Don't inherit parent's environment to avoid potential issues
352651
+ env: {
352652
+ ...process.env,
352653
+ // Ensure we're not in a shell that might interpret special characters
352654
+ SHELL: void 0
352655
+ },
352656
+ // Detach the browser process so it doesn't block
352657
+ detached: true,
352658
+ stdio: "ignore"
352659
+ };
352723
352660
  try {
352724
- await fs40.writeFile(reportPath, stringifiedReportContent);
352725
- console.error(`${baseMessage} Full report available at: ${reportPath}`);
352726
- } catch (writeError) {
352727
- console.error(`${baseMessage} Additionally, failed to write detailed error report:`, writeError);
352728
- console.error("Original error that triggered report generation:", error2);
352729
- if (context2) {
352730
- try {
352731
- console.error("Original context:", context2);
352732
- } catch {
352661
+ await execFileAsync5(command, args2, options2);
352662
+ } catch (error2) {
352663
+ if ((platformName === "linux" || platformName === "freebsd" || platformName === "openbsd") && command === "xdg-open") {
352664
+ const fallbackCommands = [
352665
+ "gnome-open",
352666
+ "kde-open",
352667
+ "firefox",
352668
+ "chromium",
352669
+ "google-chrome"
352670
+ ];
352671
+ for (const fallbackCommand of fallbackCommands) {
352733
352672
  try {
352734
- console.error("Original context (stringified, truncated):", JSON.stringify(context2).substring(0, 1e3));
352673
+ await execFileAsync5(fallbackCommand, [url5], options2);
352674
+ return;
352735
352675
  } catch {
352736
- console.error("Original context could not be logged or stringified.");
352676
+ continue;
352737
352677
  }
352738
352678
  }
352739
352679
  }
352680
+ throw new Error(`Failed to open browser: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
352740
352681
  }
352741
352682
  }
352742
352683
 
@@ -353014,33 +352955,6 @@ Suggested retry after 60s.`, googleApiError, 60);
353014
352955
  return error2;
353015
352956
  }
353016
352957
 
353017
- // packages/core/dist/src/utils/delay.js
353018
- function createAbortError() {
353019
- const abortError = new Error("Aborted");
353020
- abortError.name = "AbortError";
353021
- return abortError;
353022
- }
353023
- function delay2(ms, signal) {
353024
- if (!signal) {
353025
- return new Promise((resolve14) => setTimeout(resolve14, ms));
353026
- }
353027
- if (signal.aborted) {
353028
- return Promise.reject(createAbortError());
353029
- }
353030
- return new Promise((resolve14, reject) => {
353031
- const onAbort = () => {
353032
- clearTimeout(timeoutId);
353033
- signal.removeEventListener("abort", onAbort);
353034
- reject(createAbortError());
353035
- };
353036
- const timeoutId = setTimeout(() => {
353037
- signal.removeEventListener("abort", onAbort);
353038
- resolve14();
353039
- }, ms);
353040
- signal.addEventListener("abort", onAbort, { once: true });
353041
- });
353042
- }
353043
-
353044
352958
  // packages/core/dist/src/availability/errorClassification.js
353045
352959
  function classifyFailureKind(error2) {
353046
352960
  if (error2 instanceof TerminalQuotaError) {
@@ -353057,23 +352971,31 @@ function classifyFailureKind(error2) {
353057
352971
 
353058
352972
  // packages/core/dist/src/config/models.js
353059
352973
  var PREVIEW_GEMINI_MODEL = "gemini-3-pro-preview";
352974
+ var PREVIEW_GEMINI_FLASH_MODEL = "gemini-3-flash-preview";
353060
352975
  var DEFAULT_GEMINI_MODEL = "gemini-2.5-pro";
353061
352976
  var DEFAULT_GEMINI_FLASH_MODEL = "gemini-2.5-flash";
353062
352977
  var DEFAULT_GEMINI_FLASH_LITE_MODEL = "gemini-2.5-flash-lite";
353063
- var DEFAULT_GEMINI_MODEL_AUTO = "auto";
352978
+ var PREVIEW_GEMINI_MODEL_AUTO = "auto-gemini-3";
352979
+ var DEFAULT_GEMINI_MODEL_AUTO = "auto-gemini-2.5";
352980
+ var GEMINI_MODEL_ALIAS_AUTO = "auto";
353064
352981
  var GEMINI_MODEL_ALIAS_PRO = "pro";
353065
352982
  var GEMINI_MODEL_ALIAS_FLASH = "flash";
353066
352983
  var GEMINI_MODEL_ALIAS_FLASH_LITE = "flash-lite";
353067
352984
  var DEFAULT_GEMINI_EMBEDDING_MODEL = "gemini-embedding-001";
353068
352985
  var DEFAULT_THINKING_MODE = 8192;
353069
- function resolveModel(requestedModel, previewFeaturesEnabled) {
352986
+ function resolveModel(requestedModel, previewFeaturesEnabled = false) {
353070
352987
  switch (requestedModel) {
353071
- case DEFAULT_GEMINI_MODEL_AUTO:
352988
+ case PREVIEW_GEMINI_MODEL_AUTO: {
352989
+ return PREVIEW_GEMINI_MODEL;
352990
+ }
352991
+ case DEFAULT_GEMINI_MODEL_AUTO: {
352992
+ return DEFAULT_GEMINI_MODEL;
352993
+ }
353072
352994
  case GEMINI_MODEL_ALIAS_PRO: {
353073
352995
  return previewFeaturesEnabled ? PREVIEW_GEMINI_MODEL : DEFAULT_GEMINI_MODEL;
353074
352996
  }
353075
352997
  case GEMINI_MODEL_ALIAS_FLASH: {
353076
- return DEFAULT_GEMINI_FLASH_MODEL;
352998
+ return previewFeaturesEnabled ? PREVIEW_GEMINI_FLASH_MODEL : DEFAULT_GEMINI_FLASH_MODEL;
353077
352999
  }
353078
353000
  case GEMINI_MODEL_ALIAS_FLASH_LITE: {
353079
353001
  return DEFAULT_GEMINI_FLASH_LITE_MODEL;
@@ -353083,15 +353005,23 @@ function resolveModel(requestedModel, previewFeaturesEnabled) {
353083
353005
  }
353084
353006
  }
353085
353007
  }
353086
- function getEffectiveModel(isInFallbackMode, requestedModel, previewFeaturesEnabled) {
353087
- const resolvedModel = resolveModel(requestedModel, previewFeaturesEnabled);
353088
- if (!isInFallbackMode) {
353089
- return resolvedModel;
353090
- }
353091
- if (resolvedModel.includes("lite")) {
353092
- return resolvedModel;
353008
+ function resolveClassifierModel(requestedModel, modelAlias, previewFeaturesEnabled = false) {
353009
+ if (modelAlias === GEMINI_MODEL_ALIAS_FLASH) {
353010
+ if (requestedModel === DEFAULT_GEMINI_MODEL_AUTO || requestedModel === DEFAULT_GEMINI_MODEL) {
353011
+ return DEFAULT_GEMINI_FLASH_MODEL;
353012
+ }
353013
+ if (requestedModel === PREVIEW_GEMINI_MODEL_AUTO || requestedModel === PREVIEW_GEMINI_MODEL) {
353014
+ return PREVIEW_GEMINI_FLASH_MODEL;
353015
+ }
353016
+ return resolveModel(GEMINI_MODEL_ALIAS_FLASH, previewFeaturesEnabled);
353093
353017
  }
353094
- return DEFAULT_GEMINI_FLASH_MODEL;
353018
+ return resolveModel(requestedModel, previewFeaturesEnabled);
353019
+ }
353020
+ function getEffectiveModel(requestedModel, previewFeaturesEnabled) {
353021
+ return resolveModel(requestedModel, previewFeaturesEnabled);
353022
+ }
353023
+ function isPreviewModel(model) {
353024
+ return model === PREVIEW_GEMINI_MODEL || model === PREVIEW_GEMINI_FLASH_MODEL || model === PREVIEW_GEMINI_MODEL_AUTO;
353095
353025
  }
353096
353026
  function isGemini2Model(model) {
353097
353027
  return /^gemini-2(\.|$)/.test(model);
@@ -353118,13 +353048,8 @@ var DEFAULT_CHAIN = [
353118
353048
  definePolicy({ model: DEFAULT_GEMINI_FLASH_MODEL, isLastResort: true })
353119
353049
  ];
353120
353050
  var PREVIEW_CHAIN = [
353121
- definePolicy({
353122
- model: PREVIEW_GEMINI_MODEL,
353123
- stateTransitions: { transient: "sticky_retry" },
353124
- actions: { transient: "silent" }
353125
- }),
353126
- definePolicy({ model: DEFAULT_GEMINI_MODEL }),
353127
- definePolicy({ model: DEFAULT_GEMINI_FLASH_MODEL, isLastResort: true })
353051
+ definePolicy({ model: PREVIEW_GEMINI_MODEL }),
353052
+ definePolicy({ model: PREVIEW_GEMINI_FLASH_MODEL, isLastResort: true })
353128
353053
  ];
353129
353054
  function getModelPolicyChain(options2) {
353130
353055
  if (options2.previewEnabled) {
@@ -353132,6 +353057,9 @@ function getModelPolicyChain(options2) {
353132
353057
  }
353133
353058
  return cloneChain(DEFAULT_CHAIN);
353134
353059
  }
353060
+ function createSingleModelChain(model) {
353061
+ return [definePolicy({ model, isLastResort: true })];
353062
+ }
353135
353063
  function createDefaultPolicy(model, options2) {
353136
353064
  return definePolicy({ model, isLastResort: options2?.isLastResort });
353137
353065
  }
@@ -353158,28 +353086,33 @@ function cloneChain(chain2) {
353158
353086
  }
353159
353087
 
353160
353088
  // packages/core/dist/src/availability/policyHelpers.js
353161
- function resolvePolicyChain(config3, preferredModel) {
353162
- const chain2 = getModelPolicyChain({
353163
- previewEnabled: !!config3.getPreviewFeatures(),
353164
- userTier: config3.getUserTier()
353165
- });
353166
- const activeModel = preferredModel ?? getEffectiveModel(config3.isInFallbackMode(), config3.getModel(), config3.getPreviewFeatures());
353167
- if (activeModel === "auto") {
353168
- return [...chain2];
353089
+ function resolvePolicyChain(config3, preferredModel, wrapsAround = false) {
353090
+ const modelFromConfig = preferredModel ?? config3.getActiveModel?.() ?? config3.getModel();
353091
+ let chain2;
353092
+ if (config3.getModel() === PREVIEW_GEMINI_MODEL_AUTO || config3.getModel() === DEFAULT_GEMINI_MODEL_AUTO) {
353093
+ chain2 = getModelPolicyChain({
353094
+ previewEnabled: config3.getModel() === PREVIEW_GEMINI_MODEL_AUTO,
353095
+ userTier: config3.getUserTier()
353096
+ });
353097
+ } else {
353098
+ chain2 = createSingleModelChain(modelFromConfig);
353169
353099
  }
353170
- if (chain2.some((policy) => policy.model === activeModel)) {
353171
- return [...chain2];
353100
+ const activeModel = resolveModel(modelFromConfig);
353101
+ const activeIndex = chain2.findIndex((policy) => policy.model === activeModel);
353102
+ if (activeIndex !== -1) {
353103
+ return wrapsAround ? [...chain2.slice(activeIndex), ...chain2.slice(0, activeIndex)] : [...chain2.slice(activeIndex)];
353172
353104
  }
353173
353105
  return [createDefaultPolicy(activeModel, { isLastResort: true })];
353174
353106
  }
353175
- function buildFallbackPolicyContext(chain2, failedModel) {
353107
+ function buildFallbackPolicyContext(chain2, failedModel, wrapsAround = false) {
353176
353108
  const index = chain2.findIndex((policy) => policy.model === failedModel);
353177
353109
  if (index === -1) {
353178
353110
  return { failedPolicy: void 0, candidates: chain2 };
353179
353111
  }
353112
+ const candidates = wrapsAround ? [...chain2.slice(index + 1), ...chain2.slice(0, index)] : [...chain2.slice(index + 1)];
353180
353113
  return {
353181
353114
  failedPolicy: chain2[index],
353182
- candidates: [...chain2.slice(index + 1), ...chain2.slice(0, index)]
353115
+ candidates
353183
353116
  };
353184
353117
  }
353185
353118
  function resolvePolicyAction(failureKind, policy) {
@@ -353246,6 +353179,230 @@ function applyAvailabilityTransition(getContext, failureKind) {
353246
353179
  }
353247
353180
  }
353248
353181
 
353182
+ // packages/core/dist/src/fallback/handler.js
353183
+ var UPGRADE_URL_PAGE = "https://goo.gle/set-up-gemini-code-assist";
353184
+ async function handleFallback(config3, failedModel, authType, error2) {
353185
+ return handlePolicyDrivenFallback(config3, failedModel, authType, error2);
353186
+ }
353187
+ async function handlePolicyDrivenFallback(config3, failedModel, authType, error2) {
353188
+ if (authType !== AuthType2.LOGIN_WITH_GOOGLE) {
353189
+ return null;
353190
+ }
353191
+ const chain2 = resolvePolicyChain(config3);
353192
+ const { failedPolicy, candidates } = buildFallbackPolicyContext(chain2, failedModel);
353193
+ const failureKind = classifyFailureKind(error2);
353194
+ const availability = config3.getModelAvailabilityService();
353195
+ const getAvailabilityContext = () => {
353196
+ if (!failedPolicy)
353197
+ return void 0;
353198
+ return { service: availability, policy: failedPolicy };
353199
+ };
353200
+ let fallbackModel;
353201
+ if (!candidates.length) {
353202
+ fallbackModel = failedModel;
353203
+ } else {
353204
+ const selection = availability.selectFirstAvailable(candidates.map((policy) => policy.model));
353205
+ const lastResortPolicy = candidates.find((policy) => policy.isLastResort);
353206
+ const selectedFallbackModel = selection.selectedModel ?? lastResortPolicy?.model;
353207
+ const selectedPolicy = candidates.find((policy) => policy.model === selectedFallbackModel);
353208
+ if (!selectedFallbackModel || selectedFallbackModel === failedModel || !selectedPolicy) {
353209
+ return null;
353210
+ }
353211
+ fallbackModel = selectedFallbackModel;
353212
+ const action = resolvePolicyAction(failureKind, selectedPolicy);
353213
+ if (action === "silent") {
353214
+ applyAvailabilityTransition(getAvailabilityContext, failureKind);
353215
+ return processIntent(config3, "retry_always", fallbackModel);
353216
+ }
353217
+ const recommendation = {
353218
+ ...selection,
353219
+ selectedModel: fallbackModel,
353220
+ action,
353221
+ failureKind,
353222
+ failedPolicy,
353223
+ selectedPolicy
353224
+ };
353225
+ void recommendation;
353226
+ }
353227
+ const handler = config3.getFallbackModelHandler();
353228
+ if (typeof handler !== "function") {
353229
+ return null;
353230
+ }
353231
+ try {
353232
+ const intent = await handler(failedModel, fallbackModel, error2);
353233
+ if (intent === "retry_always" || intent === "retry_once") {
353234
+ applyAvailabilityTransition(getAvailabilityContext, failureKind);
353235
+ }
353236
+ return await processIntent(config3, intent, fallbackModel);
353237
+ } catch (handlerError) {
353238
+ debugLogger.error("Fallback handler failed:", handlerError);
353239
+ return null;
353240
+ }
353241
+ }
353242
+ async function handleUpgrade() {
353243
+ try {
353244
+ await openBrowserSecurely(UPGRADE_URL_PAGE);
353245
+ } catch (error2) {
353246
+ debugLogger.warn("Failed to open browser automatically:", getErrorMessage(error2));
353247
+ }
353248
+ }
353249
+ async function processIntent(config3, intent, fallbackModel) {
353250
+ switch (intent) {
353251
+ case "retry_always":
353252
+ config3.setActiveModel(fallbackModel);
353253
+ return true;
353254
+ case "retry_once":
353255
+ return true;
353256
+ case "stop":
353257
+ return false;
353258
+ case "retry_later":
353259
+ return false;
353260
+ case "upgrade":
353261
+ await handleUpgrade();
353262
+ return false;
353263
+ default:
353264
+ throw new Error(`Unexpected fallback intent received from fallbackModelHandler: "${intent}"`);
353265
+ }
353266
+ }
353267
+
353268
+ // packages/core/dist/src/utils/partUtils.js
353269
+ function partToString(value, options2) {
353270
+ if (!value) {
353271
+ return "";
353272
+ }
353273
+ if (typeof value === "string") {
353274
+ return value;
353275
+ }
353276
+ if (Array.isArray(value)) {
353277
+ return value.map((part2) => partToString(part2, options2)).join("");
353278
+ }
353279
+ const part = value;
353280
+ if (options2?.verbose) {
353281
+ if (part.videoMetadata !== void 0) {
353282
+ return `[Video Metadata]`;
353283
+ }
353284
+ if (part.thought !== void 0) {
353285
+ return `[Thought: ${part.thought}]`;
353286
+ }
353287
+ if (part.codeExecutionResult !== void 0) {
353288
+ return `[Code Execution Result]`;
353289
+ }
353290
+ if (part.executableCode !== void 0) {
353291
+ return `[Executable Code]`;
353292
+ }
353293
+ if (part.fileData !== void 0) {
353294
+ return `[File Data]`;
353295
+ }
353296
+ if (part.functionCall !== void 0) {
353297
+ return `[Function Call: ${part.functionCall.name}]`;
353298
+ }
353299
+ if (part.functionResponse !== void 0) {
353300
+ return `[Function Response: ${part.functionResponse.name}]`;
353301
+ }
353302
+ if (part.inlineData !== void 0) {
353303
+ return `<${part.inlineData.mimeType}>`;
353304
+ }
353305
+ }
353306
+ return part.text ?? "";
353307
+ }
353308
+ function getResponseText(response) {
353309
+ if (response.candidates && response.candidates.length > 0) {
353310
+ const candidate = response.candidates[0];
353311
+ if (candidate.content && candidate.content.parts && candidate.content.parts.length > 0) {
353312
+ return candidate.content.parts.filter((part) => part.text).map((part) => part.text).join("");
353313
+ }
353314
+ }
353315
+ return null;
353316
+ }
353317
+
353318
+ // packages/core/dist/src/utils/errorReporting.js
353319
+ import fs40 from "node:fs/promises";
353320
+ import os13 from "node:os";
353321
+ import path40 from "node:path";
353322
+ async function reportError(error2, baseMessage, context2, type = "general", reportingDir = os13.tmpdir()) {
353323
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
353324
+ const reportFileName = `gemini-client-error-${type}-${timestamp}.json`;
353325
+ const reportPath = path40.join(reportingDir, reportFileName);
353326
+ let errorToReport;
353327
+ if (error2 instanceof Error) {
353328
+ errorToReport = { message: error2.message, stack: error2.stack };
353329
+ } else if (typeof error2 === "object" && error2 !== null && "message" in error2) {
353330
+ errorToReport = {
353331
+ message: String(error2.message)
353332
+ };
353333
+ } else {
353334
+ errorToReport = { message: String(error2) };
353335
+ }
353336
+ const reportContent = { error: errorToReport };
353337
+ if (context2) {
353338
+ reportContent.context = context2;
353339
+ }
353340
+ let stringifiedReportContent;
353341
+ try {
353342
+ stringifiedReportContent = JSON.stringify(reportContent, null, 2);
353343
+ } catch (stringifyError) {
353344
+ console.error(`${baseMessage} Could not stringify report content (likely due to context):`, stringifyError);
353345
+ console.error("Original error that triggered report generation:", error2);
353346
+ if (context2) {
353347
+ console.error("Original context could not be stringified or included in report.");
353348
+ }
353349
+ try {
353350
+ const minimalReportContent = { error: errorToReport };
353351
+ stringifiedReportContent = JSON.stringify(minimalReportContent, null, 2);
353352
+ await fs40.writeFile(reportPath, stringifiedReportContent);
353353
+ console.error(`${baseMessage} Partial report (excluding context) available at: ${reportPath}`);
353354
+ } catch (minimalWriteError) {
353355
+ console.error(`${baseMessage} Failed to write even a minimal error report:`, minimalWriteError);
353356
+ }
353357
+ return;
353358
+ }
353359
+ try {
353360
+ await fs40.writeFile(reportPath, stringifiedReportContent);
353361
+ console.error(`${baseMessage} Full report available at: ${reportPath}`);
353362
+ } catch (writeError) {
353363
+ console.error(`${baseMessage} Additionally, failed to write detailed error report:`, writeError);
353364
+ console.error("Original error that triggered report generation:", error2);
353365
+ if (context2) {
353366
+ try {
353367
+ console.error("Original context:", context2);
353368
+ } catch {
353369
+ try {
353370
+ console.error("Original context (stringified, truncated):", JSON.stringify(context2).substring(0, 1e3));
353371
+ } catch {
353372
+ console.error("Original context could not be logged or stringified.");
353373
+ }
353374
+ }
353375
+ }
353376
+ }
353377
+ }
353378
+
353379
+ // packages/core/dist/src/utils/delay.js
353380
+ function createAbortError() {
353381
+ const abortError = new Error("Aborted");
353382
+ abortError.name = "AbortError";
353383
+ return abortError;
353384
+ }
353385
+ function delay2(ms, signal) {
353386
+ if (!signal) {
353387
+ return new Promise((resolve14) => setTimeout(resolve14, ms));
353388
+ }
353389
+ if (signal.aborted) {
353390
+ return Promise.reject(createAbortError());
353391
+ }
353392
+ return new Promise((resolve14, reject) => {
353393
+ const onAbort = () => {
353394
+ clearTimeout(timeoutId);
353395
+ signal.removeEventListener("abort", onAbort);
353396
+ reject(createAbortError());
353397
+ };
353398
+ const timeoutId = setTimeout(() => {
353399
+ signal.removeEventListener("abort", onAbort);
353400
+ resolve14();
353401
+ }, ms);
353402
+ signal.addEventListener("abort", onAbort, { once: true });
353403
+ });
353404
+ }
353405
+
353249
353406
  // packages/core/dist/src/utils/retry.js
353250
353407
  var DEFAULT_RETRY_OPTIONS = {
353251
353408
  maxAttempts: 3,
@@ -353342,14 +353499,9 @@ async function retryWithBackoff(fn, options2) {
353342
353499
  throw error2;
353343
353500
  }
353344
353501
  const classifiedError = classifyGoogleError(error2);
353345
- const failureKind = classifyFailureKind(classifiedError);
353346
- const appliedImmediate = failureKind === "terminal" || failureKind === "not_found";
353347
- if (appliedImmediate) {
353348
- applyAvailabilityTransition(getAvailabilityContext, failureKind);
353349
- }
353350
353502
  const errorCode = getErrorStatus(error2);
353351
353503
  if (classifiedError instanceof TerminalQuotaError || classifiedError instanceof ModelNotFoundError) {
353352
- if (onPersistent429 && authType === AuthType2.LOGIN_WITH_GOOGLE) {
353504
+ if (onPersistent429) {
353353
353505
  try {
353354
353506
  const fallbackModel = await onPersistent429(authType, classifiedError);
353355
353507
  if (fallbackModel) {
@@ -353366,7 +353518,7 @@ async function retryWithBackoff(fn, options2) {
353366
353518
  const is500 = errorCode !== void 0 && errorCode >= 500 && errorCode < 600;
353367
353519
  if (classifiedError instanceof RetryableQuotaError || is500) {
353368
353520
  if (attempt >= maxAttempts) {
353369
- if (onPersistent429 && authType === AuthType2.LOGIN_WITH_GOOGLE) {
353521
+ if (onPersistent429) {
353370
353522
  try {
353371
353523
  const fallbackModel = await onPersistent429(authType, classifiedError);
353372
353524
  if (fallbackModel) {
@@ -353378,9 +353530,6 @@ async function retryWithBackoff(fn, options2) {
353378
353530
  console.warn("Model fallback failed:", fallbackError);
353379
353531
  }
353380
353532
  }
353381
- if (!appliedImmediate) {
353382
- applyAvailabilityTransition(getAvailabilityContext, failureKind);
353383
- }
353384
353533
  throw classifiedError instanceof RetryableQuotaError ? classifiedError : error2;
353385
353534
  }
353386
353535
  if (classifiedError instanceof RetryableQuotaError) {
@@ -353398,9 +353547,6 @@ async function retryWithBackoff(fn, options2) {
353398
353547
  }
353399
353548
  }
353400
353549
  if (attempt >= maxAttempts || !shouldRetryOnError(error2, retryFetchErrors)) {
353401
- if (!appliedImmediate) {
353402
- applyAvailabilityTransition(getAvailabilityContext, failureKind);
353403
- }
353404
353550
  throw error2;
353405
353551
  }
353406
353552
  const errorStatus = getErrorStatus(error2);
@@ -353440,9 +353586,11 @@ var DEFAULT_MAX_ATTEMPTS = 5;
353440
353586
  var BaseLlmClient = class {
353441
353587
  contentGenerator;
353442
353588
  config;
353443
- constructor(contentGenerator, config3) {
353589
+ authType;
353590
+ constructor(contentGenerator, config3, authType) {
353444
353591
  this.contentGenerator = contentGenerator;
353445
353592
  this.config = config3;
353593
+ this.authType = authType;
353446
353594
  }
353447
353595
  async generateJson(options2) {
353448
353596
  const { schema, modelConfigKey, contents, systemInstruction, abortSignal, promptId, maxAttempts } = options2;
@@ -353552,7 +353700,9 @@ var BaseLlmClient = class {
353552
353700
  return await retryWithBackoff(apiCall, {
353553
353701
  shouldRetryOnContent,
353554
353702
  maxAttempts: availabilityMaxAttempts ?? maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
353555
- getAvailabilityContext
353703
+ getAvailabilityContext,
353704
+ onPersistent429: this.config.isInteractive() ? (authType, error2) => handleFallback(this.config, requestParams.model, authType, error2) : void 0,
353705
+ authType: this.authType ?? this.config.getContentGeneratorConfig()?.authType
353556
353706
  });
353557
353707
  } catch (error2) {
353558
353708
  if (abortSignal?.aborted) {
@@ -360740,7 +360890,7 @@ var WriteFileTool = class _WriteFileTool extends BaseDeclarativeTool {
360740
360890
 
360741
360891
  // packages/core/dist/src/utils/fetch.js
360742
360892
  var import_undici2 = __toESM(require_undici(), 1);
360743
- import { URL as URL6 } from "node:url";
360893
+ import { URL as URL7 } from "node:url";
360744
360894
  var PRIVATE_IP_RANGES = [
360745
360895
  /^10\./,
360746
360896
  /^127\./,
@@ -360760,7 +360910,7 @@ var FetchError2 = class extends Error {
360760
360910
  };
360761
360911
  function isPrivateIp(url5) {
360762
360912
  try {
360763
- const hostname3 = new URL6(url5).hostname;
360913
+ const hostname3 = new URL7(url5).hostname;
360764
360914
  return PRIVATE_IP_RANGES.some((range2) => range2.test(hostname3));
360765
360915
  } catch (_e) {
360766
360916
  return false;
@@ -368025,225 +368175,6 @@ var ChatRecordingService = class {
368025
368175
  }
368026
368176
  };
368027
368177
 
368028
- // packages/core/dist/src/utils/secure-browser-launcher.js
368029
- import { execFile as execFile6 } from "node:child_process";
368030
- import { promisify as promisify13 } from "node:util";
368031
- import { platform as platform10 } from "node:os";
368032
- import { URL as URL7 } from "node:url";
368033
- var execFileAsync5 = promisify13(execFile6);
368034
- function validateUrl(url5) {
368035
- let parsedUrl;
368036
- try {
368037
- parsedUrl = new URL7(url5);
368038
- } catch (_error) {
368039
- throw new Error(`Invalid URL: ${url5}`);
368040
- }
368041
- if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
368042
- throw new Error(`Unsafe protocol: ${parsedUrl.protocol}. Only HTTP and HTTPS are allowed.`);
368043
- }
368044
- if (/[\r\n\x00-\x1f]/.test(url5)) {
368045
- throw new Error("URL contains invalid characters");
368046
- }
368047
- }
368048
- async function openBrowserSecurely(url5) {
368049
- validateUrl(url5);
368050
- const platformName = platform10();
368051
- let command;
368052
- let args2;
368053
- switch (platformName) {
368054
- case "darwin":
368055
- command = "open";
368056
- args2 = [url5];
368057
- break;
368058
- case "win32":
368059
- command = "powershell.exe";
368060
- args2 = [
368061
- "-NoProfile",
368062
- "-NonInteractive",
368063
- "-WindowStyle",
368064
- "Hidden",
368065
- "-Command",
368066
- `Start-Process '${url5.replace(/'/g, "''")}'`
368067
- ];
368068
- break;
368069
- case "linux":
368070
- case "freebsd":
368071
- case "openbsd":
368072
- command = "xdg-open";
368073
- args2 = [url5];
368074
- break;
368075
- default:
368076
- throw new Error(`Unsupported platform: ${platformName}`);
368077
- }
368078
- const options2 = {
368079
- // Don't inherit parent's environment to avoid potential issues
368080
- env: {
368081
- ...process.env,
368082
- // Ensure we're not in a shell that might interpret special characters
368083
- SHELL: void 0
368084
- },
368085
- // Detach the browser process so it doesn't block
368086
- detached: true,
368087
- stdio: "ignore"
368088
- };
368089
- try {
368090
- await execFileAsync5(command, args2, options2);
368091
- } catch (error2) {
368092
- if ((platformName === "linux" || platformName === "freebsd" || platformName === "openbsd") && command === "xdg-open") {
368093
- const fallbackCommands = [
368094
- "gnome-open",
368095
- "kde-open",
368096
- "firefox",
368097
- "chromium",
368098
- "google-chrome"
368099
- ];
368100
- for (const fallbackCommand of fallbackCommands) {
368101
- try {
368102
- await execFileAsync5(fallbackCommand, [url5], options2);
368103
- return;
368104
- } catch {
368105
- continue;
368106
- }
368107
- }
368108
- }
368109
- throw new Error(`Failed to open browser: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
368110
- }
368111
- }
368112
-
368113
- // packages/core/dist/src/fallback/handler.js
368114
- init_events();
368115
- var UPGRADE_URL_PAGE = "https://goo.gle/set-up-gemini-code-assist";
368116
- async function handleFallback(config3, failedModel, authType, error2) {
368117
- if (config3.isModelAvailabilityServiceEnabled()) {
368118
- return handlePolicyDrivenFallback(config3, failedModel, authType, error2);
368119
- }
368120
- return legacyHandleFallback(config3, failedModel, authType, error2);
368121
- }
368122
- async function legacyHandleFallback(config3, failedModel, authType, error2) {
368123
- if (authType !== AuthType2.LOGIN_WITH_GOOGLE)
368124
- return null;
368125
- if (error2 instanceof ModelNotFoundError && failedModel !== PREVIEW_GEMINI_MODEL) {
368126
- return null;
368127
- }
368128
- const shouldActivatePreviewFallback = failedModel === PREVIEW_GEMINI_MODEL && !(error2 instanceof TerminalQuotaError);
368129
- if (shouldActivatePreviewFallback) {
368130
- config3.setPreviewModelBypassMode(true);
368131
- if (config3.isPreviewModelFallbackMode()) {
368132
- return true;
368133
- }
368134
- }
368135
- const fallbackModel = shouldActivatePreviewFallback ? DEFAULT_GEMINI_MODEL : DEFAULT_GEMINI_FLASH_MODEL;
368136
- const fallbackModelHandler = config3.fallbackModelHandler;
368137
- if (typeof fallbackModelHandler !== "function")
368138
- return null;
368139
- try {
368140
- const intent = await fallbackModelHandler(failedModel, fallbackModel, error2);
368141
- return await processIntent(config3, intent, failedModel, fallbackModel, authType, error2);
368142
- } catch (handlerError) {
368143
- console.error("Fallback UI handler failed:", handlerError);
368144
- return null;
368145
- }
368146
- }
368147
- async function handlePolicyDrivenFallback(config3, failedModel, authType, error2) {
368148
- if (authType !== AuthType2.LOGIN_WITH_GOOGLE) {
368149
- return null;
368150
- }
368151
- const chain2 = resolvePolicyChain(config3);
368152
- const { failedPolicy, candidates } = buildFallbackPolicyContext(chain2, failedModel);
368153
- const failureKind = classifyFailureKind(error2);
368154
- if (!candidates.length) {
368155
- return null;
368156
- }
368157
- const availability = config3.getModelAvailabilityService();
368158
- const selection = availability.selectFirstAvailable(candidates.map((policy) => policy.model));
368159
- const lastResortPolicy = candidates.find((policy) => policy.isLastResort);
368160
- const fallbackModel = selection.selectedModel ?? lastResortPolicy?.model;
368161
- const selectedPolicy = candidates.find((policy) => policy.model === fallbackModel);
368162
- if (!fallbackModel || fallbackModel === failedModel || !selectedPolicy) {
368163
- return null;
368164
- }
368165
- const action = resolvePolicyAction(failureKind, selectedPolicy);
368166
- if (action === "silent") {
368167
- return processIntent(config3, "retry_always", failedModel, fallbackModel, authType, error2);
368168
- }
368169
- const recommendation = {
368170
- ...selection,
368171
- selectedModel: fallbackModel,
368172
- action,
368173
- failureKind,
368174
- failedPolicy,
368175
- selectedPolicy
368176
- };
368177
- void recommendation;
368178
- const handler = config3.getFallbackModelHandler();
368179
- if (typeof handler !== "function") {
368180
- return null;
368181
- }
368182
- try {
368183
- const intent = await handler(failedModel, fallbackModel, error2);
368184
- return await processIntent(config3, intent, failedModel, fallbackModel, authType, error2);
368185
- } catch (handlerError) {
368186
- debugLogger.error("Fallback handler failed:", handlerError);
368187
- return null;
368188
- }
368189
- }
368190
- async function handleUpgrade() {
368191
- try {
368192
- await openBrowserSecurely(UPGRADE_URL_PAGE);
368193
- } catch (error2) {
368194
- debugLogger.warn("Failed to open browser automatically:", getErrorMessage(error2));
368195
- }
368196
- }
368197
- async function processIntent(config3, intent, failedModel, fallbackModel, authType, error2) {
368198
- const isAvailabilityEnabled = config3.isModelAvailabilityServiceEnabled();
368199
- switch (intent) {
368200
- case "retry_always":
368201
- if (isAvailabilityEnabled) {
368202
- config3.setActiveModel(fallbackModel);
368203
- } else {
368204
- if (failedModel === PREVIEW_GEMINI_MODEL && !(error2 instanceof TerminalQuotaError)) {
368205
- activatePreviewModelFallbackMode(config3);
368206
- } else {
368207
- activateFallbackMode(config3, authType);
368208
- }
368209
- }
368210
- return true;
368211
- case "retry_once":
368212
- if (isAvailabilityEnabled) {
368213
- config3.setActiveModel(fallbackModel);
368214
- }
368215
- return true;
368216
- case "stop":
368217
- if (isAvailabilityEnabled) {
368218
- config3.setActiveModel(fallbackModel);
368219
- } else {
368220
- activateFallbackMode(config3, authType);
368221
- }
368222
- return false;
368223
- case "retry_later":
368224
- return false;
368225
- case "upgrade":
368226
- await handleUpgrade();
368227
- return false;
368228
- default:
368229
- throw new Error(`Unexpected fallback intent received from fallbackModelHandler: "${intent}"`);
368230
- }
368231
- }
368232
- function activateFallbackMode(config3, authType) {
368233
- if (!config3.isInFallbackMode()) {
368234
- config3.setFallbackMode(true);
368235
- coreEvents.emitFallbackModeChanged(true);
368236
- if (authType) {
368237
- logFlashFallback(config3, new FlashFallbackEvent(authType));
368238
- }
368239
- }
368240
- }
368241
- function activatePreviewModelFallbackMode(config3) {
368242
- if (!config3.isPreviewModelFallbackMode()) {
368243
- config3.setPreviewModelFallbackMode(true);
368244
- }
368245
- }
368246
-
368247
368178
  // packages/core/dist/src/core/geminiRequest.js
368248
368179
  function partListUnionToString(value) {
368249
368180
  return partToString(value, { verbose: true });
@@ -368537,7 +368468,7 @@ var GeminiChat = class {
368537
368468
  try {
368538
368469
  let lastError = new Error("Request failed after all retries.");
368539
368470
  let maxAttempts = INVALID_CONTENT_RETRY_OPTIONS.maxAttempts;
368540
- if (this.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL) {
368471
+ if (this.config.isPreviewModelFallbackMode() && isPreviewModel(model)) {
368541
368472
  maxAttempts = 1;
368542
368473
  }
368543
368474
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
@@ -368582,7 +368513,7 @@ var GeminiChat = class {
368582
368513
  }
368583
368514
  throw lastError;
368584
368515
  } else {
368585
- if (model === PREVIEW_GEMINI_MODEL && !this.config.isPreviewModelBypassMode()) {
368516
+ if (isPreviewModel(model) && !this.config.isPreviewModelBypassMode()) {
368586
368517
  this.config.setPreviewModelFallbackMode(false);
368587
368518
  }
368588
368519
  }
@@ -368607,10 +368538,11 @@ var GeminiChat = class {
368607
368538
  let lastConfig = currentGenerateContentConfig;
368608
368539
  let lastContentsToUse = requestContents;
368609
368540
  const getAvailabilityContext = createAvailabilityContextProvider(this.config, () => lastModelToUse);
368541
+ const initialActiveModel = this.config.getActiveModel();
368610
368542
  const apiCall = async () => {
368611
- let modelToUse;
368612
- if (this.config.isModelAvailabilityServiceEnabled()) {
368613
- modelToUse = this.config.getActiveModel();
368543
+ let modelToUse = resolveModel(lastModelToUse, this.config.getPreviewFeatures());
368544
+ if (this.config.getActiveModel() !== initialActiveModel) {
368545
+ modelToUse = resolveModel(this.config.getActiveModel(), this.config.getPreviewFeatures());
368614
368546
  if (modelToUse !== lastModelToUse) {
368615
368547
  const { generateContentConfig: newConfig } = this.config.modelConfigService.getResolvedConfig({
368616
368548
  model: modelToUse
@@ -368623,11 +368555,6 @@ var GeminiChat = class {
368623
368555
  currentGenerateContentConfig.abortSignal = abortSignal;
368624
368556
  }
368625
368557
  }
368626
- } else {
368627
- modelToUse = getEffectiveModel(this.config.isInFallbackMode(), model, this.config.getPreviewFeatures());
368628
- if (this.config.isPreviewModelBypassMode() && modelToUse === PREVIEW_GEMINI_MODEL) {
368629
- modelToUse = DEFAULT_GEMINI_MODEL;
368630
- }
368631
368558
  }
368632
368559
  lastModelToUse = modelToUse;
368633
368560
  const config3 = {
@@ -368650,7 +368577,7 @@ var GeminiChat = class {
368650
368577
  };
368651
368578
  delete config3.thinkingConfig?.thinkingLevel;
368652
368579
  }
368653
- let contentsToUse = modelToUse === PREVIEW_GEMINI_MODEL ? contentsForPreviewModel : requestContents;
368580
+ let contentsToUse = isPreviewModel(modelToUse) ? contentsForPreviewModel : requestContents;
368654
368581
  const hooksEnabled = this.config.getEnableHooks();
368655
368582
  const messageBus = this.config.getMessageBus();
368656
368583
  if (hooksEnabled && messageBus) {
@@ -368702,7 +368629,7 @@ var GeminiChat = class {
368702
368629
  authType: this.config.getContentGeneratorConfig()?.authType,
368703
368630
  retryFetchErrors: this.config.getRetryFetchErrors(),
368704
368631
  signal: generateContentConfig.abortSignal,
368705
- maxAttempts: availabilityMaxAttempts ?? (this.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL ? 1 : void 0),
368632
+ maxAttempts: availabilityMaxAttempts ?? (this.config.isPreviewModelFallbackMode() && isPreviewModel(model) ? 1 : void 0),
368706
368633
  getAvailabilityContext
368707
368634
  });
368708
368635
  const originalRequest = {
@@ -369161,7 +369088,7 @@ var CodebaseInvestigatorAgent = {
369161
369088
  // The 'output' parameter is now strongly typed as CodebaseInvestigationReportSchema
369162
369089
  processOutput: (output) => JSON.stringify(output, null, 2),
369163
369090
  modelConfig: {
369164
- model: GEMINI_MODEL_ALIAS_PRO,
369091
+ model: DEFAULT_GEMINI_MODEL,
369165
369092
  temp: 0.1,
369166
369093
  top_p: 0.95,
369167
369094
  thinkingBudget: -1
@@ -369468,8 +369395,8 @@ function getCoreSystemPrompt(config3, userMemory) {
369468
369395
  throw new Error(`missing system prompt file '${systemMdPath}'`);
369469
369396
  }
369470
369397
  }
369471
- const desiredModel = getEffectiveModel(config3.isInFallbackMode(), config3.getModel(), config3.getPreviewFeatures());
369472
- const isGemini3 = desiredModel === PREVIEW_GEMINI_MODEL;
369398
+ const desiredModel = resolveModel(config3.getActiveModel(), config3.getPreviewFeatures());
369399
+ const isGemini3 = isPreviewModel(desiredModel);
369473
369400
  const mandatesVariant = isGemini3 ? `
369474
369401
  - **Do not call tools in silence:** You must provide to the user very short and concise natural explanation (one sentence) before calling tools.` : ``;
369475
369402
  const enableCodebaseInvestigator = config3.getToolRegistry().getAllToolNames().includes(CodebaseInvestigatorAgent.name);
@@ -369501,7 +369428,7 @@ ${config3.getAgentRegistry().getDirectoryContext()}`,
369501
369428
 
369502
369429
  ## Software Engineering Tasks
369503
369430
  When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this sequence:
369504
- 1. **Understand:** Think about the user's request and the relevant codebase context. Use '${GREP_TOOL_NAME}' and '${GLOB_TOOL_NAME}' search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions.
369431
+ 1. **Understand:** Think about the user's request and the relevant codebase context. Use '${GREP_TOOL_NAME}' and '${GLOB_TOOL_NAME}' search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions.
369505
369432
  Use '${READ_FILE_TOOL_NAME}' to understand context and validate any assumptions you may have. If you need to read multiple files, you should make multiple parallel calls to '${READ_FILE_TOOL_NAME}'.
369506
369433
  2. **Plan:** Build a coherent and grounded (based on the understanding in step 1) plan for how you intend to resolve the user's task. Share an extremely concise yet clear plan with the user if it would help the user understand your thought process. As part of the plan, you should use an iterative development process that includes writing unit tests to verify your changes. Use output logs or debug statements as part of this process to arrive at a solution.`,
369507
369434
  primaryWorkflows_prefix_ci: `
@@ -369525,8 +369452,7 @@ When requested to perform tasks like fixing bugs, adding features, refactoring,
369525
369452
  When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this sequence:
369526
369453
  1. **Understand:** Think about the user's request and the relevant codebase context. Use '${GREP_TOOL_NAME}' and '${GLOB_TOOL_NAME}' search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use '${READ_FILE_TOOL_NAME}' to understand context and validate any assumptions you may have. If you need to read multiple files, you should make multiple parallel calls to '${READ_FILE_TOOL_NAME}'.
369527
369454
  2. **Plan:** Build a coherent and grounded (based on the understanding in step 1) plan for how you intend to resolve the user's task. For complex tasks, break them down into smaller, manageable subtasks and use the \`${WRITE_TODOS_TOOL_NAME}\` tool to track your progress. Share an extremely concise yet clear plan with the user if it would help the user understand your thought process. As part of the plan, you should use an iterative development process that includes writing unit tests to verify your changes. Use output logs or debug statements as part of this process to arrive at a solution.`,
369528
- primaryWorkflows_suffix: `3. **Implement:** Use the available tools (e.g., '${EDIT_TOOL_NAME}', '${WRITE_FILE_TOOL_NAME}' '${SHELL_TOOL_NAME}' ...) to act on the plan, strictly adhering to the project's established conventions (detailed under 'Core
369529
- Mandates').
369455
+ primaryWorkflows_suffix: `3. **Implement:** Use the available tools (e.g., '${EDIT_TOOL_NAME}', '${WRITE_FILE_TOOL_NAME}' '${SHELL_TOOL_NAME}' ...) to act on the plan, strictly adhering to the project's established conventions (detailed under 'Core Mandates').
369530
369456
  4. **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands.
369531
369457
  5. **Verify (Standards):** VERY IMPORTANT: After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project (or obtained from the user). This ensures code quality and adherence to standards.${interactiveMode ? " If unsure about these commands, you can ask the user if they'd like you to run them and if so how to." : ""}
369532
369458
  6. **Finalize:** After all verification passes, consider the task complete. Do not remove or revert any changes or created files (like tests). Await the user's next instruction.
@@ -369718,7 +369644,7 @@ The structure MUST be as follows:
369718
369644
  - Build Command: \`npm run build\`
369719
369645
  - Testing: Tests are run with \`npm test\`. Test files must end in \`.test.ts\`.
369720
369646
  - API Endpoint: The primary API endpoint is \`https://api.example.com/v2\`.
369721
-
369647
+
369722
369648
  -->
369723
369649
  </key_knowledge>
369724
369650
 
@@ -370250,6 +370176,8 @@ function modelStringToModelConfigAlias(model) {
370250
370176
  switch (model) {
370251
370177
  case PREVIEW_GEMINI_MODEL:
370252
370178
  return "chat-compression-3-pro";
370179
+ case PREVIEW_GEMINI_FLASH_MODEL:
370180
+ return "chat-compression-3-flash";
370253
370181
  case DEFAULT_GEMINI_MODEL:
370254
370182
  return "chat-compression-2.5-pro";
370255
370183
  case DEFAULT_GEMINI_FLASH_MODEL:
@@ -370644,8 +370572,7 @@ var GeminiClient = class {
370644
370572
  if (this.currentSequenceModel) {
370645
370573
  return this.currentSequenceModel;
370646
370574
  }
370647
- const configModel = this.config.getModel();
370648
- return getEffectiveModel(this.config.isInFallbackMode(), configModel, this.config.getPreviewFeatures());
370575
+ return this.config.getActiveModel();
370649
370576
  }
370650
370577
  async *sendMessageStream(request3, signal, prompt_id, turns = MAX_TURNS, isInvalidStreamRetry = false) {
370651
370578
  if (!isInvalidStreamRetry) {
@@ -375985,25 +375912,15 @@ var ClassifierStrategy = class {
375985
375912
  const routerResponse = ClassifierResponseSchema.parse(jsonResponse);
375986
375913
  const reasoning = routerResponse.reasoning;
375987
375914
  const latencyMs = Date.now() - startTime;
375988
- if (routerResponse.model_choice === FLASH_MODEL) {
375989
- return {
375990
- model: resolveModel(GEMINI_MODEL_ALIAS_FLASH, config3.getPreviewFeatures()),
375991
- metadata: {
375992
- source: "Classifier",
375993
- latencyMs,
375994
- reasoning
375995
- }
375996
- };
375997
- } else {
375998
- return {
375999
- model: resolveModel(GEMINI_MODEL_ALIAS_PRO, config3.getPreviewFeatures()),
376000
- metadata: {
376001
- source: "Classifier",
376002
- reasoning,
376003
- latencyMs
376004
- }
376005
- };
376006
- }
375915
+ const selectedModel = resolveClassifierModel(config3.getModel(), routerResponse.model_choice, config3.getPreviewFeatures());
375916
+ return {
375917
+ model: selectedModel,
375918
+ metadata: {
375919
+ source: "Classifier",
375920
+ latencyMs,
375921
+ reasoning
375922
+ }
375923
+ };
376007
375924
  } catch (error2) {
376008
375925
  debugLogger.warn(`[Routing] ClassifierStrategy failed:`, error2);
376009
375926
  return null;
@@ -376069,19 +375986,28 @@ var CompositeStrategy = class {
376069
375986
  var FallbackStrategy = class {
376070
375987
  name = "fallback";
376071
375988
  async route(_context, config3, _baseLlmClient) {
376072
- const isInFallbackMode = config3.isInFallbackMode();
376073
- if (!isInFallbackMode) {
375989
+ if (!config3.isModelAvailabilityServiceEnabled()) {
376074
375990
  return null;
376075
375991
  }
376076
- const effectiveModel = getEffectiveModel(isInFallbackMode, config3.getModel(), config3.getPreviewFeatures());
376077
- return {
376078
- model: effectiveModel,
376079
- metadata: {
376080
- source: this.name,
376081
- latencyMs: 0,
376082
- reasoning: `In fallback mode. Using: ${effectiveModel}`
376083
- }
376084
- };
375992
+ const requestedModel = config3.getModel();
375993
+ const resolvedModel = resolveModel(requestedModel, config3.getPreviewFeatures());
375994
+ const service = config3.getModelAvailabilityService();
375995
+ const snapshot = service.snapshot(resolvedModel);
375996
+ if (snapshot.available) {
375997
+ return null;
375998
+ }
375999
+ const selection = selectModelForAvailability(config3, requestedModel);
376000
+ if (selection?.selectedModel && selection.selectedModel !== requestedModel) {
376001
+ return {
376002
+ model: selection.selectedModel,
376003
+ metadata: {
376004
+ source: this.name,
376005
+ latencyMs: 0,
376006
+ reasoning: `Model ${requestedModel} is unavailable (${snapshot.reason}). Using fallback: ${selection.selectedModel}`
376007
+ }
376008
+ };
376009
+ }
376010
+ return null;
376085
376011
  }
376086
376012
  };
376087
376013
 
@@ -376090,10 +376016,10 @@ var OverrideStrategy = class {
376090
376016
  name = "override";
376091
376017
  async route(_context, config3, _baseLlmClient) {
376092
376018
  const overrideModel = config3.getModel();
376093
- if (overrideModel === DEFAULT_GEMINI_MODEL_AUTO)
376019
+ if (overrideModel === DEFAULT_GEMINI_MODEL_AUTO || overrideModel === PREVIEW_GEMINI_MODEL_AUTO)
376094
376020
  return null;
376095
376021
  return {
376096
- model: resolveModel(overrideModel, config3.getPreviewFeatures()),
376022
+ model: getEffectiveModel(overrideModel, config3.getPreviewFeatures()),
376097
376023
  metadata: {
376098
376024
  source: this.name,
376099
376025
  latencyMs: 0,
@@ -376130,11 +376056,6 @@ var ModelRouterService = class {
376130
376056
  let decision;
376131
376057
  try {
376132
376058
  decision = await this.strategy.route(context2, this.config, this.config.getBaseLlmClient());
376133
- if (decision.model === DEFAULT_GEMINI_MODEL && this.config.getPreviewFeatures() && !decision.metadata.source.includes("override")) {
376134
- decision.model = PREVIEW_GEMINI_MODEL;
376135
- decision.metadata.source += " (Preview Model)";
376136
- decision.metadata.reasoning += " (Upgraded to Preview Model)";
376137
- }
376138
376059
  const event = new ModelRoutingEvent(
376139
376060
  decision.model,
376140
376061
  decision.metadata.source,
@@ -376366,6 +376287,12 @@ var DEFAULT_MODEL_CONFIGS = {
376366
376287
  model: "gemini-3-pro-preview"
376367
376288
  }
376368
376289
  },
376290
+ "gemini-3-flash-preview": {
376291
+ extends: "chat-base-3",
376292
+ modelConfig: {
376293
+ model: "gemini-3-flash-preview"
376294
+ }
376295
+ },
376369
376296
  "gemini-2.5-pro": {
376370
376297
  extends: "chat-base-2.5",
376371
376298
  modelConfig: {
@@ -376489,6 +376416,11 @@ var DEFAULT_MODEL_CONFIGS = {
376489
376416
  model: "gemini-3-pro-preview"
376490
376417
  }
376491
376418
  },
376419
+ "chat-compression-3-flash": {
376420
+ modelConfig: {
376421
+ model: "gemini-3-flash-preview"
376422
+ }
376423
+ },
376492
376424
  "chat-compression-2.5-pro": {
376493
376425
  modelConfig: {
376494
376426
  model: "gemini-2.5-pro"
@@ -381062,6 +380994,7 @@ var HookSystem = class {
381062
380994
  };
381063
380995
 
381064
380996
  // packages/core/dist/src/agents/registry.js
380997
+ init_events();
381065
380998
  function getModelConfigAlias(definition) {
381066
380999
  return `${definition.name}-config`;
381067
381000
  }
@@ -381077,6 +381010,9 @@ var AgentRegistry = class {
381077
381010
  */
381078
381011
  async initialize() {
381079
381012
  this.loadBuiltInAgents();
381013
+ coreEvents.on(CoreEvent.ModelChanged, () => {
381014
+ this.loadBuiltInAgents();
381015
+ });
381080
381016
  if (this.config.getDebugMode()) {
381081
381017
  debugLogger.log(`[AgentRegistry] Initialized with ${this.agents.size} agents.`);
381082
381018
  }
@@ -381084,11 +381020,12 @@ var AgentRegistry = class {
381084
381020
  loadBuiltInAgents() {
381085
381021
  const investigatorSettings = this.config.getCodebaseInvestigatorSettings();
381086
381022
  if (investigatorSettings?.enabled) {
381087
- let model = investigatorSettings.model ?? CodebaseInvestigatorAgent.modelConfig.model;
381088
- if (this.config.getModel() === PREVIEW_GEMINI_MODEL) {
381089
- if (model === GEMINI_MODEL_ALIAS_PRO || model === DEFAULT_GEMINI_MODEL_AUTO) {
381090
- model = PREVIEW_GEMINI_MODEL;
381091
- }
381023
+ let model;
381024
+ const settingsModel = investigatorSettings.model;
381025
+ if (settingsModel && settingsModel !== GEMINI_MODEL_ALIAS_AUTO) {
381026
+ model = settingsModel;
381027
+ } else {
381028
+ model = isPreviewModel(this.config.getModel()) ? PREVIEW_GEMINI_FLASH_MODEL : DEFAULT_GEMINI_MODEL;
381092
381029
  }
381093
381030
  const agentDef = {
381094
381031
  ...CodebaseInvestigatorAgent,
@@ -382303,7 +382240,7 @@ var __filename = fileURLToPath10(import.meta.url);
382303
382240
  var __dirname5 = path60.dirname(__filename);
382304
382241
  async function getVersion() {
382305
382242
  const pkgJson = await getPackageJson(__dirname5);
382306
- return "0.22.0-preview.0";
382243
+ return "0.22.0-preview.2";
382307
382244
  }
382308
382245
 
382309
382246
  // packages/core/dist/src/code_assist/experiments/client_metadata.js
@@ -385404,6 +385341,7 @@ var Config = class {
385404
385341
  bugCommand;
385405
385342
  model;
385406
385343
  previewFeatures;
385344
+ hasAccessToPreviewModel = false;
385407
385345
  noBrowser;
385408
385346
  folderTrust;
385409
385347
  ideMode;
@@ -385517,7 +385455,7 @@ var Config = class {
385517
385455
  this.bugCommand = params.bugCommand;
385518
385456
  this.model = params.model;
385519
385457
  this._activeModel = params.model;
385520
- this.enableModelAvailabilityService = params.enableModelAvailabilityService ?? false;
385458
+ this.enableModelAvailabilityService = true;
385521
385459
  this.enableAgents = params.enableAgents ?? false;
385522
385460
  this.experimentalJitContext = params.experimentalJitContext ?? false;
385523
385461
  this.modelAvailabilityService = new ModelAvailabilityService();
@@ -385553,7 +385491,7 @@ var Config = class {
385553
385491
  this.truncateToolOutputLines = params.truncateToolOutputLines ?? DEFAULT_TRUNCATE_TOOL_OUTPUT_LINES;
385554
385492
  this.enableToolOutputTruncation = params.enableToolOutputTruncation ?? true;
385555
385493
  this.useSmartEdit = params.useSmartEdit ?? true;
385556
- this.useWriteTodos = params.useWriteTodos ?? true;
385494
+ this.useWriteTodos = isPreviewModel(this.model) ? false : params.useWriteTodos ?? true;
385557
385495
  this.enableHooks = params.enableHooks ?? false;
385558
385496
  this.disabledHooks = (params.hooks && "disabled" in params.hooks ? params.hooks.disabled : void 0) ?? [];
385559
385497
  const hasHooks = params.hooks && Object.keys(params.hooks).length > 0;
@@ -385662,16 +385600,19 @@ var Config = class {
385662
385600
  if (this.contentGeneratorConfig?.authType === AuthType2.USE_GEMINI && authMethod !== AuthType2.USE_GEMINI) {
385663
385601
  this.geminiClient.stripThoughtsFromHistory();
385664
385602
  }
385603
+ this.modelAvailabilityService.reset();
385665
385604
  const newContentGeneratorConfig = await createContentGeneratorConfig(this, authMethod);
385666
385605
  this.contentGenerator = await createContentGenerator(newContentGeneratorConfig, this, this.getSessionId());
385667
385606
  this.contentGeneratorConfig = newContentGeneratorConfig;
385668
385607
  this.baseLlmClient = new BaseLlmClient(this.contentGenerator, this);
385669
- const previewFeatures = this.getPreviewFeatures();
385670
385608
  const codeAssistServer = getCodeAssistServer(this);
385671
385609
  if (codeAssistServer) {
385610
+ if (codeAssistServer.projectId) {
385611
+ await this.refreshUserQuota();
385612
+ }
385672
385613
  this.experimentsPromise = getExperiments(codeAssistServer).then((experiments) => {
385673
385614
  this.setExperiments(experiments);
385674
- if (previewFeatures === void 0) {
385615
+ if (this.getPreviewFeatures() === void 0) {
385675
385616
  const remotePreviewFeatures = experiments.flags[ExperimentFlags.ENABLE_PREVIEW]?.boolValue;
385676
385617
  if (remotePreviewFeatures === true) {
385677
385618
  this.setPreviewFeatures(remotePreviewFeatures);
@@ -385684,7 +385625,14 @@ var Config = class {
385684
385625
  this.experiments = void 0;
385685
385626
  this.experimentsPromise = void 0;
385686
385627
  }
385628
+ const authType = this.contentGeneratorConfig.authType;
385629
+ if (authType === AuthType2.USE_GEMINI || authType === AuthType2.USE_VERTEX_AI) {
385630
+ this.setHasAccessToPreviewModel(true);
385631
+ }
385687
385632
  this.inFallbackMode = false;
385633
+ if (!this.hasAccessToPreviewModel && isPreviewModel(this.model)) {
385634
+ this.setModel(DEFAULT_GEMINI_MODEL_AUTO);
385635
+ }
385688
385636
  }
385689
385637
  async getExperimentsAsync() {
385690
385638
  if (this.experiments) {
@@ -385748,7 +385696,6 @@ var Config = class {
385748
385696
  setActiveModel(model) {
385749
385697
  if (this._activeModel !== model) {
385750
385698
  this._activeModel = model;
385751
- coreEvents.emitModelChanged(model);
385752
385699
  }
385753
385700
  }
385754
385701
  resetTurn() {
@@ -385829,7 +385776,39 @@ var Config = class {
385829
385776
  return this.previewFeatures;
385830
385777
  }
385831
385778
  setPreviewFeatures(previewFeatures) {
385779
+ if (this.previewFeatures === previewFeatures) {
385780
+ return;
385781
+ }
385832
385782
  this.previewFeatures = previewFeatures;
385783
+ const currentModel = this.getModel();
385784
+ if (!previewFeatures && isPreviewModel(currentModel)) {
385785
+ this.setModel(DEFAULT_GEMINI_MODEL_AUTO);
385786
+ } else if (previewFeatures && currentModel === DEFAULT_GEMINI_MODEL_AUTO) {
385787
+ this.setModel(PREVIEW_GEMINI_MODEL_AUTO);
385788
+ }
385789
+ }
385790
+ getHasAccessToPreviewModel() {
385791
+ return this.hasAccessToPreviewModel;
385792
+ }
385793
+ setHasAccessToPreviewModel(hasAccess) {
385794
+ this.hasAccessToPreviewModel = hasAccess;
385795
+ }
385796
+ async refreshUserQuota() {
385797
+ const codeAssistServer = getCodeAssistServer(this);
385798
+ if (!codeAssistServer || !codeAssistServer.projectId) {
385799
+ return void 0;
385800
+ }
385801
+ try {
385802
+ const quota = await codeAssistServer.retrieveUserQuota({
385803
+ project: codeAssistServer.projectId
385804
+ });
385805
+ const hasAccess = quota.buckets?.some((b) => b.modelId === PREVIEW_GEMINI_MODEL) ?? false;
385806
+ this.setHasAccessToPreviewModel(hasAccess);
385807
+ return quota;
385808
+ } catch (e3) {
385809
+ debugLogger.debug("Failed to retrieve user quota", e3);
385810
+ return void 0;
385811
+ }
385833
385812
  }
385834
385813
  getCoreTools() {
385835
385814
  return this.coreTools;