@google/gemini-cli-a2a-server 0.15.0-nightly.20251111.51f952e7 → 0.16.0-nightly.20251112.c961f274

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.
@@ -1973,7 +1973,7 @@ var require_ms2 = __commonJS({
1973
1973
  var require_pretty_print = __commonJS({
1974
1974
  "node_modules/logform/pretty-print.js"(exports2, module2) {
1975
1975
  "use strict";
1976
- var inspect4 = __require("util").inspect;
1976
+ var inspect5 = __require("util").inspect;
1977
1977
  var format2 = require_format();
1978
1978
  var { LEVEL, MESSAGE, SPLAT } = require_triple_beam();
1979
1979
  module2.exports = format2((info2, opts = {}) => {
@@ -1981,7 +1981,7 @@ var require_pretty_print = __commonJS({
1981
1981
  delete stripped[LEVEL];
1982
1982
  delete stripped[MESSAGE];
1983
1983
  delete stripped[SPLAT];
1984
- info2[MESSAGE] = inspect4(stripped, false, opts.depth || null, opts.colorize);
1984
+ info2[MESSAGE] = inspect5(stripped, false, opts.depth || null, opts.colorize);
1985
1985
  return info2;
1986
1986
  });
1987
1987
  }
@@ -3091,8 +3091,8 @@ var require_buffer_list = __commonJS({
3091
3091
  var _require = __require("buffer");
3092
3092
  var Buffer9 = _require.Buffer;
3093
3093
  var _require2 = __require("util");
3094
- var inspect4 = _require2.inspect;
3095
- var custom2 = inspect4 && inspect4.custom || "inspect";
3094
+ var inspect5 = _require2.inspect;
3095
+ var custom2 = inspect5 && inspect5.custom || "inspect";
3096
3096
  function copyBuffer(src, target, offset) {
3097
3097
  Buffer9.prototype.copy.call(src, target, offset);
3098
3098
  }
@@ -3249,7 +3249,7 @@ var require_buffer_list = __commonJS({
3249
3249
  }, {
3250
3250
  key: custom2,
3251
3251
  value: function value(_, options2) {
3252
- return inspect4(this, _objectSpread(_objectSpread({}, options2), {}, {
3252
+ return inspect5(this, _objectSpread(_objectSpread({}, options2), {}, {
3253
3253
  // Only inspect one level.
3254
3254
  depth: 0,
3255
3255
  // It should not recurse.
@@ -26452,7 +26452,7 @@ var require_object_inspect = __commonJS({
26452
26452
  } else if (indexOf(seen, obj) >= 0) {
26453
26453
  return "[Circular]";
26454
26454
  }
26455
- function inspect4(value, from, noIndent) {
26455
+ function inspect5(value, from, noIndent) {
26456
26456
  if (from) {
26457
26457
  seen = $arrSlice.call(seen);
26458
26458
  seen.push(from);
@@ -26470,7 +26470,7 @@ var require_object_inspect = __commonJS({
26470
26470
  }
26471
26471
  if (typeof obj === "function" && !isRegExp2(obj)) {
26472
26472
  var name4 = nameOf(obj);
26473
- var keys = arrObjKeys(obj, inspect4);
26473
+ var keys = arrObjKeys(obj, inspect5);
26474
26474
  return "[Function" + (name4 ? ": " + name4 : " (anonymous)") + "]" + (keys.length > 0 ? " { " + $join.call(keys, ", ") + " }" : "");
26475
26475
  }
26476
26476
  if (isSymbol2(obj)) {
@@ -26494,16 +26494,16 @@ var require_object_inspect = __commonJS({
26494
26494
  if (obj.length === 0) {
26495
26495
  return "[]";
26496
26496
  }
26497
- var xs = arrObjKeys(obj, inspect4);
26497
+ var xs = arrObjKeys(obj, inspect5);
26498
26498
  if (indent && !singleLineValues(xs)) {
26499
26499
  return "[" + indentedJoin(xs, indent) + "]";
26500
26500
  }
26501
26501
  return "[ " + $join.call(xs, ", ") + " ]";
26502
26502
  }
26503
26503
  if (isError2(obj)) {
26504
- var parts2 = arrObjKeys(obj, inspect4);
26504
+ var parts2 = arrObjKeys(obj, inspect5);
26505
26505
  if (!("cause" in Error.prototype) && "cause" in obj && !isEnumerable.call(obj, "cause")) {
26506
- return "{ [" + String(obj) + "] " + $join.call($concat.call("[cause]: " + inspect4(obj.cause), parts2), ", ") + " }";
26506
+ return "{ [" + String(obj) + "] " + $join.call($concat.call("[cause]: " + inspect5(obj.cause), parts2), ", ") + " }";
26507
26507
  }
26508
26508
  if (parts2.length === 0) {
26509
26509
  return "[" + String(obj) + "]";
@@ -26521,7 +26521,7 @@ var require_object_inspect = __commonJS({
26521
26521
  var mapParts = [];
26522
26522
  if (mapForEach) {
26523
26523
  mapForEach.call(obj, function(value, key) {
26524
- mapParts.push(inspect4(key, obj, true) + " => " + inspect4(value, obj));
26524
+ mapParts.push(inspect5(key, obj, true) + " => " + inspect5(value, obj));
26525
26525
  });
26526
26526
  }
26527
26527
  return collectionOf("Map", mapSize.call(obj), mapParts, indent);
@@ -26530,7 +26530,7 @@ var require_object_inspect = __commonJS({
26530
26530
  var setParts = [];
26531
26531
  if (setForEach) {
26532
26532
  setForEach.call(obj, function(value) {
26533
- setParts.push(inspect4(value, obj));
26533
+ setParts.push(inspect5(value, obj));
26534
26534
  });
26535
26535
  }
26536
26536
  return collectionOf("Set", setSize.call(obj), setParts, indent);
@@ -26545,16 +26545,16 @@ var require_object_inspect = __commonJS({
26545
26545
  return weakCollectionOf("WeakRef");
26546
26546
  }
26547
26547
  if (isNumber4(obj)) {
26548
- return markBoxed(inspect4(Number(obj)));
26548
+ return markBoxed(inspect5(Number(obj)));
26549
26549
  }
26550
26550
  if (isBigInt(obj)) {
26551
- return markBoxed(inspect4(bigIntValueOf.call(obj)));
26551
+ return markBoxed(inspect5(bigIntValueOf.call(obj)));
26552
26552
  }
26553
26553
  if (isBoolean2(obj)) {
26554
26554
  return markBoxed(booleanValueOf.call(obj));
26555
26555
  }
26556
26556
  if (isString2(obj)) {
26557
- return markBoxed(inspect4(String(obj)));
26557
+ return markBoxed(inspect5(String(obj)));
26558
26558
  }
26559
26559
  if (typeof window !== "undefined" && obj === window) {
26560
26560
  return "{ [object Window] }";
@@ -26563,7 +26563,7 @@ var require_object_inspect = __commonJS({
26563
26563
  return "{ [object globalThis] }";
26564
26564
  }
26565
26565
  if (!isDate2(obj) && !isRegExp2(obj)) {
26566
- var ys = arrObjKeys(obj, inspect4);
26566
+ var ys = arrObjKeys(obj, inspect5);
26567
26567
  var isPlainObject4 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
26568
26568
  var protoTag = obj instanceof Object ? "" : "null prototype";
26569
26569
  var stringTag = !isPlainObject4 && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
@@ -26817,13 +26817,13 @@ var require_object_inspect = __commonJS({
26817
26817
  var lineJoiner = "\n" + indent.prev + indent.base;
26818
26818
  return lineJoiner + $join.call(xs, "," + lineJoiner) + "\n" + indent.prev;
26819
26819
  }
26820
- function arrObjKeys(obj, inspect4) {
26820
+ function arrObjKeys(obj, inspect5) {
26821
26821
  var isArr = isArray2(obj);
26822
26822
  var xs = [];
26823
26823
  if (isArr) {
26824
26824
  xs.length = obj.length;
26825
26825
  for (var i3 = 0; i3 < obj.length; i3++) {
26826
- xs[i3] = has(obj, i3) ? inspect4(obj[i3], obj) : "";
26826
+ xs[i3] = has(obj, i3) ? inspect5(obj[i3], obj) : "";
26827
26827
  }
26828
26828
  }
26829
26829
  var syms = typeof gOPS === "function" ? gOPS(obj) : [];
@@ -26844,15 +26844,15 @@ var require_object_inspect = __commonJS({
26844
26844
  if (hasShammedSymbols && symMap["$" + key] instanceof Symbol) {
26845
26845
  continue;
26846
26846
  } else if ($test.call(/[^\w$]/, key)) {
26847
- xs.push(inspect4(key, obj) + ": " + inspect4(obj[key], obj));
26847
+ xs.push(inspect5(key, obj) + ": " + inspect5(obj[key], obj));
26848
26848
  } else {
26849
- xs.push(key + ": " + inspect4(obj[key], obj));
26849
+ xs.push(key + ": " + inspect5(obj[key], obj));
26850
26850
  }
26851
26851
  }
26852
26852
  if (typeof gOPS === "function") {
26853
26853
  for (var j = 0; j < syms.length; j++) {
26854
26854
  if (isEnumerable.call(obj, syms[j])) {
26855
- xs.push("[" + inspect4(syms[j]) + "]: " + inspect4(obj[syms[j]], obj));
26855
+ xs.push("[" + inspect5(syms[j]) + "]: " + inspect5(obj[syms[j]], obj));
26856
26856
  }
26857
26857
  }
26858
26858
  }
@@ -26865,7 +26865,7 @@ var require_object_inspect = __commonJS({
26865
26865
  var require_side_channel_list = __commonJS({
26866
26866
  "node_modules/side-channel-list/index.js"(exports2, module2) {
26867
26867
  "use strict";
26868
- var inspect4 = require_object_inspect();
26868
+ var inspect5 = require_object_inspect();
26869
26869
  var $TypeError = require_type();
26870
26870
  var listGetNode = function(list3, key, isDelete) {
26871
26871
  var prev = list3;
@@ -26919,7 +26919,7 @@ var require_side_channel_list = __commonJS({
26919
26919
  var channel = {
26920
26920
  assert: function(key) {
26921
26921
  if (!channel.has(key)) {
26922
- throw new $TypeError("Side channel does not contain " + inspect4(key));
26922
+ throw new $TypeError("Side channel does not contain " + inspect5(key));
26923
26923
  }
26924
26924
  },
26925
26925
  "delete": function(key) {
@@ -27779,7 +27779,7 @@ var require_side_channel_map = __commonJS({
27779
27779
  "use strict";
27780
27780
  var GetIntrinsic = require_get_intrinsic();
27781
27781
  var callBound = require_call_bound();
27782
- var inspect4 = require_object_inspect();
27782
+ var inspect5 = require_object_inspect();
27783
27783
  var $TypeError = require_type();
27784
27784
  var $Map = GetIntrinsic("%Map%", true);
27785
27785
  var $mapGet = callBound("Map.prototype.get", true);
@@ -27793,7 +27793,7 @@ var require_side_channel_map = __commonJS({
27793
27793
  var channel = {
27794
27794
  assert: function(key) {
27795
27795
  if (!channel.has(key)) {
27796
- throw new $TypeError("Side channel does not contain " + inspect4(key));
27796
+ throw new $TypeError("Side channel does not contain " + inspect5(key));
27797
27797
  }
27798
27798
  },
27799
27799
  "delete": function(key) {
@@ -27835,7 +27835,7 @@ var require_side_channel_weakmap = __commonJS({
27835
27835
  "use strict";
27836
27836
  var GetIntrinsic = require_get_intrinsic();
27837
27837
  var callBound = require_call_bound();
27838
- var inspect4 = require_object_inspect();
27838
+ var inspect5 = require_object_inspect();
27839
27839
  var getSideChannelMap = require_side_channel_map();
27840
27840
  var $TypeError = require_type();
27841
27841
  var $WeakMap = GetIntrinsic("%WeakMap%", true);
@@ -27851,7 +27851,7 @@ var require_side_channel_weakmap = __commonJS({
27851
27851
  var channel = {
27852
27852
  assert: function(key) {
27853
27853
  if (!channel.has(key)) {
27854
- throw new $TypeError("Side channel does not contain " + inspect4(key));
27854
+ throw new $TypeError("Side channel does not contain " + inspect5(key));
27855
27855
  }
27856
27856
  },
27857
27857
  "delete": function(key) {
@@ -27907,7 +27907,7 @@ var require_side_channel = __commonJS({
27907
27907
  "node_modules/side-channel/index.js"(exports2, module2) {
27908
27908
  "use strict";
27909
27909
  var $TypeError = require_type();
27910
- var inspect4 = require_object_inspect();
27910
+ var inspect5 = require_object_inspect();
27911
27911
  var getSideChannelList = require_side_channel_list();
27912
27912
  var getSideChannelMap = require_side_channel_map();
27913
27913
  var getSideChannelWeakMap = require_side_channel_weakmap();
@@ -27917,7 +27917,7 @@ var require_side_channel = __commonJS({
27917
27917
  var channel = {
27918
27918
  assert: function(key) {
27919
27919
  if (!channel.has(key)) {
27920
- throw new $TypeError("Side channel does not contain " + inspect4(key));
27920
+ throw new $TypeError("Side channel does not contain " + inspect5(key));
27921
27921
  }
27922
27922
  },
27923
27923
  "delete": function(key) {
@@ -218884,7 +218884,7 @@ var require_data_url = __commonJS({
218884
218884
  var require_webidl = __commonJS({
218885
218885
  "node_modules/undici/lib/web/webidl/index.js"(exports2, module2) {
218886
218886
  "use strict";
218887
- var { types: types4, inspect: inspect4 } = __require("node:util");
218887
+ var { types: types4, inspect: inspect5 } = __require("node:util");
218888
218888
  var { markAsUncloneable } = __require("node:worker_threads");
218889
218889
  var UNDEFINED = 1;
218890
218890
  var BOOLEAN = 2;
@@ -219076,7 +219076,7 @@ var require_webidl = __commonJS({
219076
219076
  case SYMBOL:
219077
219077
  return `Symbol(${V2.description})`;
219078
219078
  case OBJECT:
219079
- return inspect4(V2);
219079
+ return inspect5(V2);
219080
219080
  case STRING:
219081
219081
  return `"${V2}"`;
219082
219082
  case BIGINT:
@@ -274152,6 +274152,7 @@ import { homedir as homedir5 } from "node:os";
274152
274152
 
274153
274153
  // packages/core/dist/src/config/config.js
274154
274154
  import * as path63 from "node:path";
274155
+ import { inspect as inspect4 } from "node:util";
274155
274156
  import process22 from "node:process";
274156
274157
 
274157
274158
  // node_modules/@google/genai/dist/node/index.mjs
@@ -293121,16 +293122,14 @@ var CodeAssistServer = class {
293121
293122
  });
293122
293123
  let bufferedLines = [];
293123
293124
  for await (const line of rl) {
293124
- if (line === "") {
293125
+ if (line.startsWith("data: ")) {
293126
+ bufferedLines.push(line.slice(6).trim());
293127
+ } else if (line === "") {
293125
293128
  if (bufferedLines.length === 0) {
293126
293129
  continue;
293127
293130
  }
293128
293131
  yield JSON.parse(bufferedLines.join("\n"));
293129
293132
  bufferedLines = [];
293130
- } else if (line.startsWith("data: ")) {
293131
- bufferedLines.push(line.slice(6).trim());
293132
- } else {
293133
- throw new Error(`Unexpected line format in response: ${line}`);
293134
293133
  }
293135
293134
  }
293136
293135
  }();
@@ -293642,7 +293641,7 @@ function hasCycleInSchema(schema) {
293642
293641
  }
293643
293642
  if ("$ref" in node && typeof node.$ref === "string") {
293644
293643
  const ref = node.$ref;
293645
- if (ref === "#/" || pathRefs.has(ref)) {
293644
+ if (ref === "#" || ref === "#/" || pathRefs.has(ref)) {
293646
293645
  return true;
293647
293646
  }
293648
293647
  if (visitedRefs.has(ref)) {
@@ -294032,6 +294031,7 @@ function getCommonAttributes(config2) {
294032
294031
  return {
294033
294032
  "session.id": config2.getSessionId(),
294034
294033
  "installation.id": installationManager.getInstallationId(),
294034
+ interactive: config2.isInteractive(),
294035
294035
  ...email && { "user.email": email }
294036
294036
  };
294037
294037
  }
@@ -295261,23 +295261,29 @@ var LoopDetectedEvent = class {
295261
295261
  "event.timestamp";
295262
295262
  loop_type;
295263
295263
  prompt_id;
295264
- constructor(loop_type, prompt_id) {
295264
+ confirmed_by_model;
295265
+ constructor(loop_type, prompt_id, confirmed_by_model) {
295265
295266
  this["event.name"] = "loop_detected";
295266
295267
  this["event.timestamp"] = (/* @__PURE__ */ new Date()).toISOString();
295267
295268
  this.loop_type = loop_type;
295268
295269
  this.prompt_id = prompt_id;
295270
+ this.confirmed_by_model = confirmed_by_model;
295269
295271
  }
295270
295272
  toOpenTelemetryAttributes(config2) {
295271
- return {
295273
+ const attributes = {
295272
295274
  ...getCommonAttributes(config2),
295273
295275
  "event.name": this["event.name"],
295274
295276
  "event.timestamp": this["event.timestamp"],
295275
295277
  loop_type: this.loop_type,
295276
295278
  prompt_id: this.prompt_id
295277
295279
  };
295280
+ if (this.confirmed_by_model) {
295281
+ attributes["confirmed_by_model"] = this.confirmed_by_model;
295282
+ }
295283
+ return attributes;
295278
295284
  }
295279
295285
  toLogBody() {
295280
- return `Loop detected. Type: ${this.loop_type}.`;
295286
+ return `Loop detected. Type: ${this.loop_type}.${this.confirmed_by_model ? ` Confirmed by: ${this.confirmed_by_model}` : ""}`;
295281
295287
  }
295282
295288
  };
295283
295289
  var LoopDetectionDisabledEvent = class {
@@ -295567,6 +295573,37 @@ var ToolOutputTruncatedEvent = class {
295567
295573
  return `Tool output truncated for ${this.tool_name}.`;
295568
295574
  }
295569
295575
  };
295576
+ var EVENT_LLM_LOOP_CHECK = "gemini_cli.llm_loop_check";
295577
+ var LlmLoopCheckEvent = class {
295578
+ "event.name";
295579
+ "event.timestamp";
295580
+ prompt_id;
295581
+ flash_confidence;
295582
+ main_model;
295583
+ main_model_confidence;
295584
+ constructor(prompt_id, flash_confidence, main_model, main_model_confidence) {
295585
+ this["event.name"] = "llm_loop_check";
295586
+ this["event.timestamp"] = (/* @__PURE__ */ new Date()).toISOString();
295587
+ this.prompt_id = prompt_id;
295588
+ this.flash_confidence = flash_confidence;
295589
+ this.main_model = main_model;
295590
+ this.main_model_confidence = main_model_confidence;
295591
+ }
295592
+ toOpenTelemetryAttributes(config2) {
295593
+ return {
295594
+ ...getCommonAttributes(config2),
295595
+ "event.name": EVENT_LLM_LOOP_CHECK,
295596
+ "event.timestamp": this["event.timestamp"],
295597
+ prompt_id: this.prompt_id,
295598
+ flash_confidence: this.flash_confidence,
295599
+ main_model: this.main_model,
295600
+ main_model_confidence: this.main_model_confidence
295601
+ };
295602
+ }
295603
+ toLogBody() {
295604
+ return this.main_model_confidence === -1 ? `LLM loop check. Flash confidence: ${this.flash_confidence.toFixed(2)}. Main model (${this.main_model}) check skipped` : `LLM loop check. Flash confidence: ${this.flash_confidence.toFixed(2)}. Main model (${this.main_model}) confidence: ${this.main_model_confidence.toFixed(2)}`;
295605
+ }
295606
+ };
295570
295607
  var EVENT_SMART_EDIT_STRATEGY = "gemini_cli.smart_edit_strategy";
295571
295608
  var SmartEditStrategyEvent = class {
295572
295609
  "event.name";
@@ -295871,6 +295908,11 @@ var EventMetadataKey;
295871
295908
  EventMetadataKey2[EventMetadataKey2["GEMINI_CLI_AGENT_RECOVERY_REASON"] = 122] = "GEMINI_CLI_AGENT_RECOVERY_REASON";
295872
295909
  EventMetadataKey2[EventMetadataKey2["GEMINI_CLI_AGENT_RECOVERY_DURATION_MS"] = 123] = "GEMINI_CLI_AGENT_RECOVERY_DURATION_MS";
295873
295910
  EventMetadataKey2[EventMetadataKey2["GEMINI_CLI_AGENT_RECOVERY_SUCCESS"] = 124] = "GEMINI_CLI_AGENT_RECOVERY_SUCCESS";
295911
+ EventMetadataKey2[EventMetadataKey2["GEMINI_CLI_INTERACTIVE"] = 125] = "GEMINI_CLI_INTERACTIVE";
295912
+ EventMetadataKey2[EventMetadataKey2["GEMINI_CLI_LLM_LOOP_CHECK_FLASH_CONFIDENCE"] = 126] = "GEMINI_CLI_LLM_LOOP_CHECK_FLASH_CONFIDENCE";
295913
+ EventMetadataKey2[EventMetadataKey2["GEMINI_CLI_LLM_LOOP_CHECK_MAIN_MODEL"] = 127] = "GEMINI_CLI_LLM_LOOP_CHECK_MAIN_MODEL";
295914
+ EventMetadataKey2[EventMetadataKey2["GEMINI_CLI_LLM_LOOP_CHECK_MAIN_MODEL_CONFIDENCE"] = 128] = "GEMINI_CLI_LLM_LOOP_CHECK_MAIN_MODEL_CONFIDENCE";
295915
+ EventMetadataKey2[EventMetadataKey2["GEMINI_CLI_LOOP_DETECTED_CONFIRMED_BY_MODEL"] = 129] = "GEMINI_CLI_LOOP_DETECTED_CONFIRMED_BY_MODEL";
295874
295916
  })(EventMetadataKey || (EventMetadataKey = {}));
295875
295917
 
295876
295918
  // node_modules/mnemonist/index.mjs
@@ -295896,8 +295938,8 @@ var Float64Vector = import_vector.default.Float64Vector;
295896
295938
  var PointerVector = import_vector.default.PointerVector;
295897
295939
 
295898
295940
  // packages/core/dist/src/generated/git-commit.js
295899
- var GIT_COMMIT_INFO = "51f952e7";
295900
- var CLI_VERSION = "0.15.0-nightly.20251111.51f952e7";
295941
+ var GIT_COMMIT_INFO = "c961f274";
295942
+ var CLI_VERSION = "0.16.0-nightly.20251112.c961f274";
295901
295943
 
295902
295944
  // packages/core/dist/src/ide/detect-ide.js
295903
295945
  var IDE_DEFINITIONS = {
@@ -296000,6 +296042,7 @@ var EventNames;
296000
296042
  EventNames2["AGENT_FINISH"] = "agent_finish";
296001
296043
  EventNames2["RECOVERY_ATTEMPT"] = "recovery_attempt";
296002
296044
  EventNames2["WEB_FETCH_FALLBACK_ATTEMPT"] = "web_fetch_fallback_attempt";
296045
+ EventNames2["LLM_LOOP_CHECK"] = "llm_loop_check";
296003
296046
  })(EventNames || (EventNames = {}));
296004
296047
  function determineSurface() {
296005
296048
  if (process.env["SURFACE"]) {
@@ -296491,6 +296534,12 @@ var ClearcutLogger = class _ClearcutLogger {
296491
296534
  value: JSON.stringify(event.loop_type)
296492
296535
  }
296493
296536
  ];
296537
+ if (event.confirmed_by_model) {
296538
+ data.push({
296539
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_LOOP_DETECTED_CONFIRMED_BY_MODEL,
296540
+ value: event.confirmed_by_model
296541
+ });
296542
+ }
296494
296543
  this.enqueueLogEvent(this.createLogEvent(EventNames.LOOP_DETECTED, data));
296495
296544
  this.flushIfNeeded();
296496
296545
  }
@@ -296926,6 +296975,28 @@ var ClearcutLogger = class _ClearcutLogger {
296926
296975
  this.enqueueLogEvent(this.createLogEvent(EventNames.WEB_FETCH_FALLBACK_ATTEMPT, data));
296927
296976
  this.flushIfNeeded();
296928
296977
  }
296978
+ logLlmLoopCheckEvent(event) {
296979
+ const data = [
296980
+ {
296981
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
296982
+ value: event.prompt_id
296983
+ },
296984
+ {
296985
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_LLM_LOOP_CHECK_FLASH_CONFIDENCE,
296986
+ value: event.flash_confidence.toString()
296987
+ },
296988
+ {
296989
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_LLM_LOOP_CHECK_MAIN_MODEL,
296990
+ value: event.main_model
296991
+ },
296992
+ {
296993
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_LLM_LOOP_CHECK_MAIN_MODEL_CONFIDENCE,
296994
+ value: event.main_model_confidence.toString()
296995
+ }
296996
+ ];
296997
+ this.enqueueLogEvent(this.createLogEvent(EventNames.LLM_LOOP_CHECK, data));
296998
+ this.flushIfNeeded();
296999
+ }
296929
297000
  /**
296930
297001
  * Adds default fields to data, and returns a new data array. This fields
296931
297002
  * should exist on all log events.
@@ -296955,6 +297026,10 @@ var ClearcutLogger = class _ClearcutLogger {
296955
297026
  {
296956
297027
  gemini_cli_key: EventMetadataKey.GEMINI_CLI_USER_SETTINGS,
296957
297028
  value: this.getConfigJson()
297029
+ },
297030
+ {
297031
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_INTERACTIVE,
297032
+ value: this.config?.isInteractive().toString() ?? "false"
296958
297033
  }
296959
297034
  ];
296960
297035
  return [...data, ...defaultLogMetadata];
@@ -298356,6 +298431,17 @@ function logWebFetchFallbackAttempt(config2, event) {
298356
298431
  };
298357
298432
  logger6.emit(logRecord);
298358
298433
  }
298434
+ function logLlmLoopCheck(config2, event) {
298435
+ ClearcutLogger.getInstance(config2)?.logLlmLoopCheckEvent(event);
298436
+ if (!isTelemetrySdkInitialized())
298437
+ return;
298438
+ const logger6 = import_api_logs.logs.getLogger(SERVICE_NAME);
298439
+ const logRecord = {
298440
+ body: event.toLogBody(),
298441
+ attributes: event.toOpenTelemetryAttributes(config2)
298442
+ };
298443
+ logger6.emit(logRecord);
298444
+ }
298359
298445
 
298360
298446
  // packages/core/dist/src/utils/quotaErrorDetection.js
298361
298447
  function isApiError(error) {
@@ -298698,7 +298784,7 @@ async function createContentGenerator(config2, gcConfig, sessionId2) {
298698
298784
  if (gcConfig.fakeResponses) {
298699
298785
  return FakeContentGenerator.fromFile(gcConfig.fakeResponses);
298700
298786
  }
298701
- const version3 = "0.15.0-nightly.20251111.51f952e7";
298787
+ const version3 = "0.16.0-nightly.20251112.c961f274";
298702
298788
  const userAgent = `GeminiCLI/${version3} (${process.platform}; ${process.arch})`;
298703
298789
  const baseHeaders = {
298704
298790
  "User-Agent": userAgent
@@ -300904,7 +300990,7 @@ var MemoryToolInvocation = class _MemoryToolInvocation extends BaseToolInvocatio
300904
300990
  var MemoryTool = class _MemoryTool extends BaseDeclarativeTool {
300905
300991
  static Name = MEMORY_TOOL_NAME;
300906
300992
  constructor(messageBus) {
300907
- super(_MemoryTool.Name, "Save Memory", memoryToolDescription, Kind.Think, memoryToolSchemaData.parametersJsonSchema, true, false, messageBus);
300993
+ super(_MemoryTool.Name, "SaveMemory", memoryToolDescription, Kind.Think, memoryToolSchemaData.parametersJsonSchema, true, false, messageBus);
300908
300994
  }
300909
300995
  validateToolParamValues(params) {
300910
300996
  if (params.fact.trim() === "") {
@@ -320607,83 +320693,61 @@ async function ensureRgPath() {
320607
320693
  }
320608
320694
  throw new Error("Cannot use ripgrep.");
320609
320695
  }
320696
+ function resolveAndValidatePath(config2, relativePath) {
320697
+ if (!relativePath) {
320698
+ return null;
320699
+ }
320700
+ const targetDir = config2.getTargetDir();
320701
+ const targetPath = path33.resolve(targetDir, relativePath);
320702
+ const workspaceContext = config2.getWorkspaceContext();
320703
+ if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
320704
+ const directories = workspaceContext.getDirectories();
320705
+ throw new Error(`Path validation failed: Attempted path "${relativePath}" resolves outside the allowed workspace directories: ${directories.join(", ")}`);
320706
+ }
320707
+ try {
320708
+ const stats = fs31.statSync(targetPath);
320709
+ if (!stats.isDirectory() && !stats.isFile()) {
320710
+ throw new Error(`Path is not a valid directory or file: ${targetPath} (CWD: ${targetDir})`);
320711
+ }
320712
+ } catch (error) {
320713
+ if (isNodeError(error) && error.code === "ENOENT") {
320714
+ throw new Error(`Path does not exist: ${targetPath} (CWD: ${targetDir})`);
320715
+ }
320716
+ throw new Error(`Failed to access path stats for ${targetPath}: ${error}`);
320717
+ }
320718
+ return targetPath;
320719
+ }
320610
320720
  var GrepToolInvocation2 = class extends BaseToolInvocation {
320611
320721
  config;
320612
320722
  constructor(config2, params, messageBus, _toolName, _toolDisplayName) {
320613
320723
  super(params, messageBus, _toolName, _toolDisplayName);
320614
320724
  this.config = config2;
320615
320725
  }
320616
- /**
320617
- * Checks if a path is within the root directory and resolves it.
320618
- * @param relativePath Path relative to the root directory (or undefined for root).
320619
- * @returns The absolute path if valid and exists, or null if no path specified (to search all directories).
320620
- * @throws {Error} If path is outside root, doesn't exist, or isn't a directory.
320621
- */
320622
- resolveAndValidatePath(relativePath) {
320623
- if (!relativePath) {
320624
- return null;
320625
- }
320626
- const targetPath = path33.resolve(this.config.getTargetDir(), relativePath);
320627
- const workspaceContext = this.config.getWorkspaceContext();
320628
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
320629
- const directories = workspaceContext.getDirectories();
320630
- throw new Error(`Path validation failed: Attempted path "${relativePath}" resolves outside the allowed workspace directories: ${directories.join(", ")}`);
320631
- }
320632
- try {
320633
- const stats = fs31.statSync(targetPath);
320634
- if (!stats.isDirectory()) {
320635
- throw new Error(`Path is not a directory: ${targetPath}`);
320636
- }
320637
- } catch (error) {
320638
- if (isNodeError(error) && error.code !== "ENOENT") {
320639
- throw new Error(`Path does not exist: ${targetPath}`);
320640
- }
320641
- throw new Error(`Failed to access path stats for ${targetPath}: ${error}`);
320642
- }
320643
- return targetPath;
320644
- }
320645
320726
  async execute(signal) {
320646
320727
  try {
320647
- const workspaceContext = this.config.getWorkspaceContext();
320648
- const searchDirAbs = this.resolveAndValidatePath(this.params.dir_path);
320649
- const searchDirDisplay = this.params.dir_path || ".";
320650
- let searchDirectories;
320651
- if (searchDirAbs === null) {
320652
- searchDirectories = workspaceContext.getDirectories();
320653
- } else {
320654
- searchDirectories = [searchDirAbs];
320655
- }
320656
- let allMatches = [];
320728
+ const pathParam = this.params.dir_path || ".";
320729
+ const searchDirAbs = resolveAndValidatePath(this.config, pathParam);
320730
+ const searchDirDisplay = pathParam;
320657
320731
  const totalMaxMatches = DEFAULT_TOTAL_MAX_MATCHES;
320658
320732
  if (this.config.getDebugMode()) {
320659
320733
  debugLogger.log(`[GrepTool] Total result limit: ${totalMaxMatches}`);
320660
320734
  }
320661
- for (const searchDir of searchDirectories) {
320662
- const searchResult = await this.performRipgrepSearch({
320663
- pattern: this.params.pattern,
320664
- path: searchDir,
320665
- include: this.params.include,
320666
- signal
320667
- });
320668
- if (searchDirectories.length > 1) {
320669
- const dirName = path33.basename(searchDir);
320670
- searchResult.forEach((match2) => {
320671
- match2.filePath = path33.join(dirName, match2.filePath);
320672
- });
320673
- }
320674
- allMatches = allMatches.concat(searchResult);
320675
- if (allMatches.length >= totalMaxMatches) {
320676
- allMatches = allMatches.slice(0, totalMaxMatches);
320677
- break;
320678
- }
320679
- }
320680
- let searchLocationDescription;
320681
- if (searchDirAbs === null) {
320682
- const numDirs = workspaceContext.getDirectories().length;
320683
- searchLocationDescription = numDirs > 1 ? `across ${numDirs} workspace directories` : `in the workspace directory`;
320684
- } else {
320685
- searchLocationDescription = `in path "${searchDirDisplay}"`;
320735
+ let allMatches = await this.performRipgrepSearch({
320736
+ pattern: this.params.pattern,
320737
+ path: searchDirAbs,
320738
+ include: this.params.include,
320739
+ case_sensitive: this.params.case_sensitive,
320740
+ fixed_strings: this.params.fixed_strings,
320741
+ context: this.params.context,
320742
+ after: this.params.after,
320743
+ before: this.params.before,
320744
+ no_ignore: this.params.no_ignore,
320745
+ signal
320746
+ });
320747
+ if (allMatches.length >= totalMaxMatches) {
320748
+ allMatches = allMatches.slice(0, totalMaxMatches);
320686
320749
  }
320750
+ const searchLocationDescription = `in path "${searchDirDisplay}"`;
320687
320751
  if (allMatches.length === 0) {
320688
320752
  const noMatchMsg = `No matches found for pattern "${this.params.pattern}" ${searchLocationDescription}${this.params.include ? ` (filter: "${this.params.include}")` : ""}.`;
320689
320753
  return { llmContent: noMatchMsg, returnDisplay: `No matches found` };
@@ -320763,24 +320827,43 @@ var GrepToolInvocation2 = class extends BaseToolInvocation {
320763
320827
  return results;
320764
320828
  }
320765
320829
  async performRipgrepSearch(options2) {
320766
- const { pattern, path: absolutePath, include } = options2;
320767
- const rgArgs = ["--json", "--ignore-case", "--regexp", pattern];
320830
+ const { pattern, path: absolutePath, include, case_sensitive, fixed_strings, context: context2, after, before, no_ignore } = options2;
320831
+ const rgArgs = ["--json"];
320832
+ if (!case_sensitive) {
320833
+ rgArgs.push("--ignore-case");
320834
+ }
320835
+ if (fixed_strings) {
320836
+ rgArgs.push("--fixed-strings");
320837
+ rgArgs.push(pattern);
320838
+ } else {
320839
+ rgArgs.push("--regexp", pattern);
320840
+ }
320841
+ if (context2) {
320842
+ rgArgs.push("--context", context2.toString());
320843
+ }
320844
+ if (after) {
320845
+ rgArgs.push("--after-context", after.toString());
320846
+ }
320847
+ if (before) {
320848
+ rgArgs.push("--before-context", before.toString());
320849
+ }
320850
+ if (no_ignore) {
320851
+ rgArgs.push("--no-ignore");
320852
+ }
320768
320853
  if (include) {
320769
320854
  rgArgs.push("--glob", include);
320770
320855
  }
320771
- const excludes = [
320772
- ".git",
320773
- "node_modules",
320774
- "bower_components",
320775
- "*.log",
320776
- "*.tmp",
320777
- "build",
320778
- "dist",
320779
- "coverage"
320780
- ];
320781
- excludes.forEach((exclude) => {
320782
- rgArgs.push("--glob", `!${exclude}`);
320783
- });
320856
+ if (!no_ignore) {
320857
+ const fileExclusions = new FileExclusions(this.config);
320858
+ const excludes = fileExclusions.getGlobExcludes([
320859
+ ...COMMON_DIRECTORY_EXCLUDES,
320860
+ "*.log",
320861
+ "*.tmp"
320862
+ ]);
320863
+ excludes.forEach((exclude) => {
320864
+ rgArgs.push("--glob", `!${exclude}`);
320865
+ });
320866
+ }
320784
320867
  rgArgs.push("--threads", "4");
320785
320868
  rgArgs.push(absolutePath);
320786
320869
  try {
@@ -320832,20 +320915,13 @@ var GrepToolInvocation2 = class extends BaseToolInvocation {
320832
320915
  if (this.params.include) {
320833
320916
  description += ` in ${this.params.include}`;
320834
320917
  }
320835
- if (this.params.dir_path) {
320836
- const resolvedPath = path33.resolve(this.config.getTargetDir(), this.params.dir_path);
320837
- if (resolvedPath === this.config.getTargetDir() || this.params.dir_path === ".") {
320838
- description += ` within ./`;
320839
- } else {
320840
- const relativePath = makeRelative(resolvedPath, this.config.getTargetDir());
320841
- description += ` within ${shortenPath(relativePath)}`;
320842
- }
320918
+ const pathParam = this.params.dir_path || ".";
320919
+ const resolvedPath = path33.resolve(this.config.getTargetDir(), pathParam);
320920
+ if (resolvedPath === this.config.getTargetDir() || pathParam === ".") {
320921
+ description += ` within ./`;
320843
320922
  } else {
320844
- const workspaceContext = this.config.getWorkspaceContext();
320845
- const directories = workspaceContext.getDirectories();
320846
- if (directories.length > 1) {
320847
- description += ` across all workspace directories`;
320848
- }
320923
+ const relativePath = makeRelative(resolvedPath, this.config.getTargetDir());
320924
+ description += ` within ${shortenPath(relativePath)}`;
320849
320925
  }
320850
320926
  return description;
320851
320927
  }
@@ -320857,21 +320933,45 @@ var RipGrepTool = class _RipGrepTool extends BaseDeclarativeTool {
320857
320933
  super(
320858
320934
  _RipGrepTool.Name,
320859
320935
  "SearchText",
320860
- "Searches for a regular expression pattern within the content of files in a specified directory (or current working directory). Can filter files by a glob pattern. Returns the lines containing matches, along with their file paths and line numbers. Total results limited to 20,000 matches like VSCode.",
320936
+ 'FAST, optimized search powered by `ripgrep`. PREFERRED over standard `run_shell_command("grep ...")` due to better performance and automatic output limiting (max 20k matches).',
320861
320937
  Kind.Search,
320862
320938
  {
320863
320939
  properties: {
320864
320940
  pattern: {
320865
- description: "The regular expression (regex) pattern to search for within file contents (e.g., 'function\\s+myFunction', 'import\\s+\\{.*\\}\\s+from\\s+.*').",
320941
+ description: "The pattern to search for. By default, treated as a Rust-flavored regular expression. Use '\\b' for precise symbol matching (e.g., '\\bMatchMe\\b').",
320866
320942
  type: "string"
320867
320943
  },
320868
320944
  dir_path: {
320869
- description: "Optional: The absolute path to the directory to search within. If omitted, searches the current working directory.",
320945
+ description: "Directory or file to search. Directories are searched recursively. Relative paths are resolved against current working directory. Defaults to current working directory ('.') if omitted.",
320870
320946
  type: "string"
320871
320947
  },
320872
320948
  include: {
320873
- description: "Optional: A glob pattern to filter which files are searched (e.g., '*.js', '*.{ts,tsx}', 'src/**'). If omitted, searches all files (respecting potential global ignores).",
320949
+ description: "Glob pattern to filter files (e.g., '*.ts', 'src/**'). Recommended for large repositories to reduce noise. Defaults to all files if omitted.",
320874
320950
  type: "string"
320951
+ },
320952
+ case_sensitive: {
320953
+ description: "If true, search is case-sensitive. Defaults to false (ignore case) if omitted.",
320954
+ type: "boolean"
320955
+ },
320956
+ fixed_strings: {
320957
+ description: "If true, treats the `pattern` as a literal string instead of a regular expression. Defaults to false (basic regex) if omitted.",
320958
+ type: "boolean"
320959
+ },
320960
+ context: {
320961
+ description: "Show this many lines of context around each match (equivalent to grep -C). Defaults to 0 if omitted.",
320962
+ type: "integer"
320963
+ },
320964
+ after: {
320965
+ description: "Show this many lines after each match (equivalent to grep -A). Defaults to 0 if omitted.",
320966
+ type: "integer"
320967
+ },
320968
+ before: {
320969
+ description: "Show this many lines before each match (equivalent to grep -B). Defaults to 0 if omitted.",
320970
+ type: "integer"
320971
+ },
320972
+ no_ignore: {
320973
+ description: "If true, searches all files including those usually ignored (like in .gitignore, build/, dist/, etc). Defaults to false if omitted.",
320974
+ type: "boolean"
320875
320975
  }
320876
320976
  },
320877
320977
  required: ["pattern"],
@@ -320885,35 +320985,6 @@ var RipGrepTool = class _RipGrepTool extends BaseDeclarativeTool {
320885
320985
  );
320886
320986
  this.config = config2;
320887
320987
  }
320888
- /**
320889
- * Checks if a path is within the root directory and resolves it.
320890
- * @param relativePath Path relative to the root directory (or undefined for root).
320891
- * @returns The absolute path if valid and exists, or null if no path specified (to search all directories).
320892
- * @throws {Error} If path is outside root, doesn't exist, or isn't a directory.
320893
- */
320894
- resolveAndValidatePath(relativePath) {
320895
- if (!relativePath) {
320896
- return null;
320897
- }
320898
- const targetPath = path33.resolve(this.config.getTargetDir(), relativePath);
320899
- const workspaceContext = this.config.getWorkspaceContext();
320900
- if (!workspaceContext.isPathWithinWorkspace(targetPath)) {
320901
- const directories = workspaceContext.getDirectories();
320902
- throw new Error(`Path validation failed: Attempted path "${relativePath}" resolves outside the allowed workspace directories: ${directories.join(", ")}`);
320903
- }
320904
- try {
320905
- const stats = fs31.statSync(targetPath);
320906
- if (!stats.isDirectory()) {
320907
- throw new Error(`Path is not a directory: ${targetPath}`);
320908
- }
320909
- } catch (error) {
320910
- if (isNodeError(error) && error.code !== "ENOENT") {
320911
- throw new Error(`Path does not exist: ${targetPath}`);
320912
- }
320913
- throw new Error(`Failed to access path stats for ${targetPath}: ${error}`);
320914
- }
320915
- return targetPath;
320916
- }
320917
320988
  /**
320918
320989
  * Validates the parameters for the tool
320919
320990
  * @param params Parameters to validate
@@ -320926,7 +320997,7 @@ var RipGrepTool = class _RipGrepTool extends BaseDeclarativeTool {
320926
320997
  }
320927
320998
  if (params.dir_path) {
320928
320999
  try {
320929
- this.resolveAndValidatePath(params.dir_path);
321000
+ resolveAndValidatePath(this.config, params.dir_path);
320930
321001
  } catch (error) {
320931
321002
  return getErrorMessage(error);
320932
321003
  }
@@ -330912,14 +330983,7 @@ var EditToolInvocation2 = class extends BaseToolInvocation {
330912
330983
  currentContent: contentForLlmEditFixer,
330913
330984
  abortSignal
330914
330985
  });
330915
- const secondError = getErrorReplaceResult(
330916
- params,
330917
- secondAttemptResult.occurrences,
330918
- 1,
330919
- // expectedReplacements is always 1 for smart_edit
330920
- secondAttemptResult.finalOldString,
330921
- secondAttemptResult.finalNewString
330922
- );
330986
+ const secondError = getErrorReplaceResult(params, secondAttemptResult.occurrences, params.expected_replacements ?? 1, secondAttemptResult.finalOldString, secondAttemptResult.finalNewString);
330923
330987
  if (secondError) {
330924
330988
  const event2 = new SmartEditCorrectionEvent("failure");
330925
330989
  logSmartEditCorrectionEvent(this.config, event2);
@@ -330950,7 +331014,7 @@ var EditToolInvocation2 = class extends BaseToolInvocation {
330950
331014
  * @throws File system errors if reading the file fails unexpectedly (e.g., permissions)
330951
331015
  */
330952
331016
  async calculateEdit(params, abortSignal) {
330953
- const expectedReplacements = 1;
331017
+ const expectedReplacements = params.expected_replacements ?? 1;
330954
331018
  let currentContent = null;
330955
331019
  let fileExists2 = false;
330956
331020
  let originalLineEnding = "\n";
@@ -331201,7 +331265,7 @@ var SmartEditTool = class _SmartEditTool extends BaseDeclarativeTool {
331201
331265
  super(
331202
331266
  _SmartEditTool.Name,
331203
331267
  "Edit",
331204
- `Replaces text within a file. Replaces a single occurrence. This tool requires providing significant context around the change to ensure precise targeting. Always use the ${READ_FILE_TOOL_NAME} tool to examine the file's current content before attempting a text replacement.
331268
+ `Replaces text within a file. By default, replaces a single occurrence, but can replace multiple occurrences when \`expected_replacements\` is specified. This tool requires providing significant context around the change to ensure precise targeting. Always use the ${READ_FILE_TOOL_NAME} tool to examine the file's current content before attempting a text replacement.
331205
331269
 
331206
331270
  The user has the ability to modify the \`new_string\` content. If modified, this will be stated in the response.
331207
331271
 
@@ -331212,7 +331276,7 @@ var SmartEditTool = class _SmartEditTool extends BaseDeclarativeTool {
331212
331276
  4. NEVER escape \`old_string\` or \`new_string\`, that would break the exact literal text requirement.
331213
331277
  **Important:** If ANY of the above are not satisfied, the tool will fail. CRITICAL for \`old_string\`: Must uniquely identify the single instance to change. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string matches multiple locations, or does not match exactly, the tool will fail.
331214
331278
  5. Prefer to break down complex and long changes into multiple smaller atomic calls to this tool. Always check the content of the file after changes or not finding a string to match.
331215
- **Multiple replacements:** If there are multiple and ambiguous occurences of the \`old_string\` in the file, the tool will also fail.`,
331279
+ **Multiple replacements:** Set \`expected_replacements\` to the number of occurrences you want to replace. The tool will replace ALL occurrences that match \`old_string\` exactly. Ensure the number of replacements matches your expectation.`,
331216
331280
  Kind.Edit,
331217
331281
  {
331218
331282
  properties: {
@@ -331239,12 +331303,17 @@ A good instruction should concisely answer:
331239
331303
  type: "string"
331240
331304
  },
331241
331305
  old_string: {
331242
- description: "The exact literal text to replace, preferably unescaped. Include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string is not the exact literal text (i.e. you escaped it) or does not match exactly, the tool will fail.",
331306
+ description: "The exact literal text to replace, preferably unescaped. For single replacements (default), include at least 3 lines of context BEFORE and AFTER the target text, matching whitespace and indentation precisely. If this string is not the exact literal text (i.e. you escaped it) or does not match exactly, the tool will fail.",
331243
331307
  type: "string"
331244
331308
  },
331245
331309
  new_string: {
331246
331310
  description: "The exact literal text to replace `old_string` with, preferably unescaped. Provide the EXACT text. Ensure the resulting code is correct and idiomatic.",
331247
331311
  type: "string"
331312
+ },
331313
+ expected_replacements: {
331314
+ type: "number",
331315
+ description: "Number of replacements expected. Defaults to 1 if not specified. Use when you want to replace multiple occurrences.",
331316
+ minimum: 1
331248
331317
  }
331249
331318
  },
331250
331319
  required: ["file_path", "instruction", "old_string", "new_string"],
@@ -331328,23 +331397,6 @@ import path42 from "node:path";
331328
331397
  import os16, { EOL as EOL2 } from "node:os";
331329
331398
  import crypto20 from "node:crypto";
331330
331399
 
331331
- // packages/core/dist/src/config/models.js
331332
- var DEFAULT_GEMINI_MODEL = "gemini-2.5-pro";
331333
- var DEFAULT_GEMINI_FLASH_MODEL = "gemini-2.5-flash";
331334
- var DEFAULT_GEMINI_FLASH_LITE_MODEL = "gemini-2.5-flash-lite";
331335
- var DEFAULT_GEMINI_MODEL_AUTO = "auto";
331336
- var DEFAULT_GEMINI_EMBEDDING_MODEL = "gemini-embedding-001";
331337
- var DEFAULT_THINKING_MODE = 8192;
331338
- function getEffectiveModel(isInFallbackMode, requestedModel) {
331339
- if (!isInFallbackMode) {
331340
- return requestedModel;
331341
- }
331342
- if (requestedModel.includes("lite")) {
331343
- return requestedModel;
331344
- }
331345
- return DEFAULT_GEMINI_FLASH_MODEL;
331346
- }
331347
-
331348
331400
  // packages/core/dist/src/utils/summarizer.js
331349
331401
  var SUMMARIZE_TOOL_OUTPUT_PROMPT = `Summarize the following tool output to be a maximum of {maxOutputTokens} tokens. The summary should be concise and capture the main points of the tool output.
331350
331402
 
@@ -331359,17 +331411,15 @@ Text to summarize:
331359
331411
 
331360
331412
  Return the summary string which should first contain an overall summarization of text followed by the full stack trace of errors and warnings in the tool output.
331361
331413
  `;
331362
- async function summarizeToolOutput(textToSummarize, geminiClient, abortSignal, maxOutputTokens = 2e3) {
331414
+ async function summarizeToolOutput(config2, modelConfigKey, textToSummarize, geminiClient, abortSignal) {
331415
+ const maxOutputTokens = config2.modelConfigService.getResolvedConfig(modelConfigKey).generateContentConfig.maxOutputTokens ?? 2e3;
331363
331416
  if (!textToSummarize || textToSummarize.length < maxOutputTokens) {
331364
331417
  return textToSummarize;
331365
331418
  }
331366
331419
  const prompt = SUMMARIZE_TOOL_OUTPUT_PROMPT.replace("{maxOutputTokens}", String(maxOutputTokens)).replace("{textToSummarize}", textToSummarize);
331367
331420
  const contents = [{ role: "user", parts: [{ text: prompt }] }];
331368
- const toolOutputSummarizerConfig = {
331369
- maxOutputTokens
331370
- };
331371
331421
  try {
331372
- const parsedResponse = await geminiClient.generateContent(contents, toolOutputSummarizerConfig, abortSignal, DEFAULT_GEMINI_FLASH_LITE_MODEL);
331422
+ const parsedResponse = await geminiClient.generateContent(modelConfigKey, contents, abortSignal);
331373
331423
  return getResponseText(parsedResponse) || textToSummarize;
331374
331424
  } catch (error) {
331375
331425
  debugLogger.warn("Failed to summarize tool output.", error);
@@ -337136,7 +337186,7 @@ ${result.output}`;
337136
337186
  }
337137
337187
  } : {};
337138
337188
  if (summarizeConfig && summarizeConfig[SHELL_TOOL_NAME]) {
337139
- const summary = await summarizeToolOutput(llmContent, this.config.getGeminiClient(), signal, summarizeConfig[SHELL_TOOL_NAME].tokenBudget);
337189
+ const summary = await summarizeToolOutput(this.config, { model: "summarizer-shell" }, llmContent, this.config.getGeminiClient(), signal);
337140
337190
  return {
337141
337191
  llmContent: summary,
337142
337192
  returnDisplay: returnDisplayMessage,
@@ -342562,7 +342612,7 @@ I was unable to access the URL directly. Instead, I have fetched the raw content
342562
342612
  ${textContent2}
342563
342613
  ---
342564
342614
  `;
342565
- const result = await geminiClient.generateContent([{ role: "user", parts: [{ text: fallbackPrompt }] }], {}, signal, DEFAULT_GEMINI_FLASH_MODEL);
342615
+ const result = await geminiClient.generateContent({ model: "web-fetch-fallback" }, [{ role: "user", parts: [{ text: fallbackPrompt }] }], signal);
342566
342616
  const resultText = getResponseText(result) || "";
342567
342617
  return {
342568
342618
  llmContent: resultText,
@@ -342620,13 +342670,7 @@ ${textContent2}
342620
342670
  }
342621
342671
  const geminiClient = this.config.getGeminiClient();
342622
342672
  try {
342623
- const response = await geminiClient.generateContent(
342624
- [{ role: "user", parts: [{ text: userPrompt }] }],
342625
- { tools: [{ urlContext: {} }] },
342626
- signal,
342627
- // Pass signal
342628
- DEFAULT_GEMINI_FLASH_MODEL
342629
- );
342673
+ const response = await geminiClient.generateContent({ model: "web-fetch" }, [{ role: "user", parts: [{ text: userPrompt }] }], signal);
342630
342674
  debugLogger.debug(`[WebFetchTool] Full response for prompt "${userPrompt.substring(0, 50)}...":`, JSON.stringify(response, null, 2));
342631
342675
  let responseText = getResponseText(response) || "";
342632
342676
  const urlContextMeta = response.candidates?.[0]?.urlContextMetadata;
@@ -343084,7 +343128,7 @@ var WebSearchToolInvocation = class extends BaseToolInvocation {
343084
343128
  async execute(signal) {
343085
343129
  const geminiClient = this.config.getGeminiClient();
343086
343130
  try {
343087
- const response = await geminiClient.generateContent([{ role: "user", parts: [{ text: this.params.query }] }], { tools: [{ googleSearch: {} }] }, signal, DEFAULT_GEMINI_FLASH_MODEL);
343131
+ const response = await geminiClient.generateContent({ model: "web-search" }, [{ role: "user", parts: [{ text: this.params.query }] }], signal);
343088
343132
  const responseText = getResponseText(response);
343089
343133
  const groundingMetadata = response.candidates?.[0]?.groundingMetadata;
343090
343134
  const sources = groundingMetadata?.groundingChunks;
@@ -343413,10 +343457,12 @@ async function getEnvironmentContext(config2) {
343413
343457
  });
343414
343458
  const platform10 = process.platform;
343415
343459
  const directoryContext = await getDirectoryContextString(config2);
343460
+ const tempDir = config2.storage.getProjectTempDir();
343416
343461
  const context2 = `
343417
343462
  This is the Gemini CLI. We are setting up the context for our chat.
343418
343463
  Today's date is ${today} (formatted according to the user's locale).
343419
343464
  My operating system is: ${platform10}
343465
+ The project's temporary directory is: ${tempDir}
343420
343466
  ${directoryContext}
343421
343467
  `.trim();
343422
343468
  const initialParts = [{ text: context2 }];
@@ -343441,6 +343487,22 @@ My setup is complete. I will provide my first command in the next turn.
343441
343487
  ];
343442
343488
  }
343443
343489
 
343490
+ // packages/core/dist/src/config/models.js
343491
+ var DEFAULT_GEMINI_MODEL = "gemini-2.5-pro";
343492
+ var DEFAULT_GEMINI_FLASH_MODEL = "gemini-2.5-flash";
343493
+ var DEFAULT_GEMINI_MODEL_AUTO = "auto";
343494
+ var DEFAULT_GEMINI_EMBEDDING_MODEL = "gemini-embedding-001";
343495
+ var DEFAULT_THINKING_MODE = 8192;
343496
+ function getEffectiveModel(isInFallbackMode, requestedModel) {
343497
+ if (!isInFallbackMode) {
343498
+ return requestedModel;
343499
+ }
343500
+ if (requestedModel.includes("lite")) {
343501
+ return requestedModel;
343502
+ }
343503
+ return DEFAULT_GEMINI_FLASH_MODEL;
343504
+ }
343505
+
343444
343506
  // packages/core/dist/src/utils/generateContentResponseUtilities.js
343445
343507
  function getResponseTextFromParts(parts2) {
343446
343508
  if (!parts2) {
@@ -344623,13 +344685,13 @@ var GeminiChat = class {
344623
344685
  sendPromise = Promise.resolve();
344624
344686
  chatRecordingService;
344625
344687
  lastPromptTokenCount;
344626
- constructor(config2, generationConfig = {}, history = []) {
344688
+ constructor(config2, generationConfig = {}, history = [], resumedSessionData) {
344627
344689
  this.config = config2;
344628
344690
  this.generationConfig = generationConfig;
344629
344691
  this.history = history;
344630
344692
  validateHistory2(history);
344631
344693
  this.chatRecordingService = new ChatRecordingService(config2);
344632
- this.chatRecordingService.initialize();
344694
+ this.chatRecordingService.initialize(resumedSessionData);
344633
344695
  this.lastPromptTokenCount = Math.ceil(JSON.stringify(this.history).length / 4);
344634
344696
  }
344635
344697
  setSystemInstruction(sysInstr) {
@@ -345311,7 +345373,7 @@ ${todoListString}` : "Successfully cleared the todo list.";
345311
345373
  var WriteTodosTool = class _WriteTodosTool extends BaseDeclarativeTool {
345312
345374
  static Name = WRITE_TODOS_TOOL_NAME;
345313
345375
  constructor() {
345314
- super(_WriteTodosTool.Name, "Write Todos", WRITE_TODOS_DESCRIPTION, Kind.Other, {
345376
+ super(_WriteTodosTool.Name, "WriteTodos", WRITE_TODOS_DESCRIPTION, Kind.Other, {
345315
345377
  type: "object",
345316
345378
  properties: {
345317
345379
  todos: {
@@ -345435,7 +345497,7 @@ function getCoreSystemPrompt(config2, userMemory) {
345435
345497
  ## Software Engineering Tasks
345436
345498
  When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this sequence:
345437
345499
  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.
345438
- Use '${READ_FILE_TOOL_NAME}' and '${READ_MANY_FILES_TOOL_NAME}' to understand context and validate any assumptions you may have.
345500
+ 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}'.
345439
345501
  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.`,
345440
345502
  primaryWorkflows_prefix_ci: `
345441
345503
  # Primary Workflows
@@ -345456,7 +345518,7 @@ When requested to perform tasks like fixing bugs, adding features, refactoring,
345456
345518
 
345457
345519
  ## Software Engineering Tasks
345458
345520
  When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this sequence:
345459
- 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}' and '${READ_MANY_FILES_TOOL_NAME}' to understand context and validate any assumptions you may have.
345521
+ 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}'.
345460
345522
  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.`,
345461
345523
  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
345462
345524
  Mandates').
@@ -345471,9 +345533,9 @@ Mandates').
345471
345533
  1. **Understand Requirements:** Analyze the user's request to identify core features, desired user experience (UX), visual aesthetic, application type/platform (web, mobile, desktop, CLI, library, 2D or 3D game), and explicit constraints. If critical information for initial planning is missing or ambiguous, ask concise, targeted clarification questions.
345472
345534
  2. **Propose Plan:** Formulate an internal development plan. Present a clear, concise, high-level summary to the user. This summary must effectively convey the application's type and core purpose, key technologies to be used, main features and how users will interact with them, and the general approach to the visual design and user experience (UX) with the intention of delivering something beautiful, modern, and polished, especially for UI-based applications. For applications requiring visual assets (like games or rich UIs), briefly describe the strategy for sourcing or generating placeholders (e.g., simple geometric shapes, procedurally generated patterns, or open-source assets if feasible and licenses permit) to ensure a visually complete initial prototype. Ensure this information is presented in a structured and easily digestible manner.
345473
345535
  - When key technologies aren't specified, prefer the following:
345474
- - **Websites (Frontend):** React (JavaScript/TypeScript) with Bootstrap CSS, incorporating Material Design principles for UI/UX.
345536
+ - **Websites (Frontend):** React (JavaScript/TypeScript) or Angular with Bootstrap CSS, incorporating Material Design principles for UI/UX.
345475
345537
  - **Back-End APIs:** Node.js with Express.js (JavaScript/TypeScript) or Python with FastAPI.
345476
- - **Full-stack:** Next.js (React/Node.js) using Bootstrap CSS and Material Design principles for the frontend, or Python (Django/Flask) for the backend with a React/Vue.js frontend styled with Bootstrap CSS and Material Design principles.
345538
+ - **Full-stack:** Next.js (React/Node.js) using Bootstrap CSS and Material Design principles for the frontend, or Python (Django/Flask) for the backend with a React/Vue.js/Angular frontend styled with Bootstrap CSS and Material Design principles.
345477
345539
  - **CLIs:** Python or Go.
345478
345540
  - **Mobile App:** Compose Multiplatform (Kotlin Multiplatform) or Flutter (Dart) using Material Design libraries and principles, when sharing code between Android and iOS. Jetpack Compose (Kotlin JVM) with Material Design principles or SwiftUI (Swift) for native apps targeted at either Android or iOS, respectively.
345479
345541
  - **3d Games:** HTML/CSS/JavaScript with Three.js.
@@ -345486,7 +345548,6 @@ Mandates').
345486
345548
  # Operational Guidelines
345487
345549
  ${function() {
345488
345550
  if (config2.getEnableShellOutputEfficiency()) {
345489
- const tempDir = config2.storage.getProjectTempDir();
345490
345551
  return `
345491
345552
  ## Shell tool output token efficiency:
345492
345553
 
@@ -345496,8 +345557,8 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
345496
345557
  - Aim to minimize tool output tokens while still capturing necessary information.
345497
345558
  - If a command is expected to produce a lot of output, use quiet or silent flags where available and appropriate.
345498
345559
  - Always consider the trade-off between output verbosity and the need for information. If a command's full output is essential for understanding the result, avoid overly aggressive quieting that might obscure important details.
345499
- - If a command does not have quiet/silent flags or for commands with potentially long output that may not be useful, redirect stdout and stderr to temp files in the project's temporary directory: ${tempDir}. For example: 'command > ${path48.posix.join(tempDir, "out.log")} 2> ${path48.posix.join(tempDir, "err.log")}'.
345500
- - After the command runs, inspect the temp files (e.g. '${path48.posix.join(tempDir, "out.log")}' and '${path48.posix.join(tempDir, "err.log")}') using commands like 'grep', 'tail', 'head', ... (or platform equivalents). Remove the temp files when done.
345560
+ - If a command does not have quiet/silent flags or for commands with potentially long output that may not be useful, redirect stdout and stderr to temp files in the project's temporary directory. For example: 'command > <temp_dir>/out.log 2> <temp_dir>/err.log'.
345561
+ - After the command runs, inspect the temp files (e.g. '<temp_dir>/out.log' and '<temp_dir>/err.log') using commands like 'grep', 'tail', 'head', ... (or platform equivalents). Remove the temp files when done.
345501
345562
  `;
345502
345563
  }
345503
345564
  return "";
@@ -345578,7 +345639,7 @@ ${function() {
345578
345639
  }()}`,
345579
345640
  finalReminder: `
345580
345641
  # Final Reminder
345581
- Your core function is efficient and safe assistance. Balance extreme conciseness with the crucial need for clarity, especially regarding safety and potential system modifications. Always prioritize user control and project conventions. Never make assumptions about the contents of files; instead use '${READ_FILE_TOOL_NAME}' or '${READ_MANY_FILES_TOOL_NAME}' to ensure you aren't making broad assumptions. Finally, you are an agent - please keep going until the user's query is completely resolved.`
345642
+ Your core function is efficient and safe assistance. Balance extreme conciseness with the crucial need for clarity, especially regarding safety and potential system modifications. Always prioritize user control and project conventions. Never make assumptions about the contents of files; instead use '${READ_FILE_TOOL_NAME}' to ensure you aren't making broad assumptions. Finally, you are an agent - please keep going until the user's query is completely resolved.`
345582
345643
  };
345583
345644
  const orderedPrompts = [
345584
345645
  "preamble",
@@ -345780,6 +345841,8 @@ var LLM_CHECK_AFTER_TURNS = 30;
345780
345841
  var DEFAULT_LLM_CHECK_INTERVAL = 3;
345781
345842
  var MIN_LLM_CHECK_INTERVAL = 5;
345782
345843
  var MAX_LLM_CHECK_INTERVAL = 15;
345844
+ var LLM_CONFIDENCE_THRESHOLD = 0.9;
345845
+ var DOUBLE_CHECK_MODEL_ALIAS = "loop-detection-double-check";
345783
345846
  var LOOP_DETECTION_SYSTEM_PROMPT = `You are a sophisticated AI diagnostic agent specializing in identifying when a conversational AI is stuck in an unproductive state. Your task is to analyze the provided conversation history and determine if the assistant has ceased to make meaningful progress.
345784
345847
 
345785
345848
  An unproductive state is characterized by one or more of the following patterns over the last 5 or more assistant turns:
@@ -345790,6 +345853,20 @@ Cognitive Loop: The assistant seems unable to determine the next logical step. I
345790
345853
 
345791
345854
  Crucially, differentiate between a true unproductive state and legitimate, incremental progress.
345792
345855
  For example, a series of 'tool_A' or 'tool_B' tool calls that make small, distinct changes to the same file (like adding docstrings to functions one by one) is considered forward progress and is NOT a loop. A loop would be repeatedly replacing the same text with the same content, or cycling between a small set of files with no net change.`;
345856
+ var LOOP_DETECTION_SCHEMA = {
345857
+ type: "object",
345858
+ properties: {
345859
+ unproductive_state_analysis: {
345860
+ type: "string",
345861
+ description: "Your reasoning on if the conversation is looping without forward progress."
345862
+ },
345863
+ unproductive_state_confidence: {
345864
+ type: "number",
345865
+ description: "A number between 0.0 and 1.0 representing your confidence that the conversation is in an unproductive state."
345866
+ }
345867
+ },
345868
+ required: ["unproductive_state_analysis", "unproductive_state_confidence"]
345869
+ };
345793
345870
  var LoopDetectionService = class {
345794
345871
  config;
345795
345872
  promptId = "";
@@ -346017,49 +346094,67 @@ var LoopDetectionService = class {
346017
346094
  parts: [{ text: "Recent conversation history:" }]
346018
346095
  });
346019
346096
  }
346020
- const schema = {
346021
- type: "object",
346022
- properties: {
346023
- unproductive_state_analysis: {
346024
- type: "string",
346025
- description: "Your reasoning on if the conversation is looping without forward progress."
346026
- },
346027
- unproductive_state_confidence: {
346028
- type: "number",
346029
- description: "A number between 0.0 and 1.0 representing your confidence that the conversation is in an unproductive state."
346030
- }
346031
- },
346032
- required: [
346033
- "unproductive_state_analysis",
346034
- "unproductive_state_confidence"
346035
- ]
346036
- };
346037
- let result;
346097
+ const flashResult = await this.queryLoopDetectionModel("loop-detection", contents, signal);
346098
+ if (!flashResult) {
346099
+ return false;
346100
+ }
346101
+ const flashConfidence = flashResult["unproductive_state_confidence"];
346102
+ const doubleCheckModelName = this.config.modelConfigService.getResolvedConfig({
346103
+ model: DOUBLE_CHECK_MODEL_ALIAS
346104
+ }).model;
346105
+ if (flashConfidence < LLM_CONFIDENCE_THRESHOLD) {
346106
+ logLlmLoopCheck(this.config, new LlmLoopCheckEvent(this.promptId, flashConfidence, doubleCheckModelName, -1));
346107
+ this.updateCheckInterval(flashConfidence);
346108
+ return false;
346109
+ }
346110
+ if (this.config.isInFallbackMode()) {
346111
+ const flashModelName = this.config.modelConfigService.getResolvedConfig({
346112
+ model: "loop-detection"
346113
+ }).model;
346114
+ this.handleConfirmedLoop(flashResult, flashModelName);
346115
+ return true;
346116
+ }
346117
+ const mainModelResult = await this.queryLoopDetectionModel(DOUBLE_CHECK_MODEL_ALIAS, contents, signal);
346118
+ const mainModelConfidence = mainModelResult ? mainModelResult["unproductive_state_confidence"] : 0;
346119
+ logLlmLoopCheck(this.config, new LlmLoopCheckEvent(this.promptId, flashConfidence, doubleCheckModelName, mainModelConfidence));
346120
+ if (mainModelResult) {
346121
+ if (mainModelConfidence >= LLM_CONFIDENCE_THRESHOLD) {
346122
+ this.handleConfirmedLoop(mainModelResult, doubleCheckModelName);
346123
+ return true;
346124
+ } else {
346125
+ this.updateCheckInterval(mainModelConfidence);
346126
+ }
346127
+ }
346128
+ return false;
346129
+ }
346130
+ async queryLoopDetectionModel(model, contents, signal) {
346038
346131
  try {
346039
- result = await this.config.getBaseLlmClient().generateJson({
346040
- modelConfigKey: { model: "loop-detection" },
346132
+ const result = await this.config.getBaseLlmClient().generateJson({
346133
+ modelConfigKey: { model },
346041
346134
  contents,
346042
- schema,
346135
+ schema: LOOP_DETECTION_SCHEMA,
346043
346136
  systemInstruction: LOOP_DETECTION_SYSTEM_PROMPT,
346044
346137
  abortSignal: signal,
346045
- promptId: this.promptId
346138
+ promptId: this.promptId,
346139
+ maxAttempts: 2
346046
346140
  });
346141
+ if (result && typeof result["unproductive_state_confidence"] === "number") {
346142
+ return result;
346143
+ }
346144
+ return null;
346047
346145
  } catch (e2) {
346048
346146
  this.config.getDebugMode() ? debugLogger.warn(e2) : debugLogger.debug(e2);
346049
- return false;
346147
+ return null;
346050
346148
  }
346051
- if (typeof result["unproductive_state_confidence"] === "number") {
346052
- if (result["unproductive_state_confidence"] > 0.9) {
346053
- if (typeof result["unproductive_state_analysis"] === "string" && result["unproductive_state_analysis"]) {
346054
- debugLogger.warn(result["unproductive_state_analysis"]);
346055
- }
346056
- logLoopDetected(this.config, new LoopDetectedEvent(LoopType.LLM_DETECTED_LOOP, this.promptId));
346057
- return true;
346058
- } else {
346059
- this.llmCheckInterval = Math.round(MIN_LLM_CHECK_INTERVAL + (MAX_LLM_CHECK_INTERVAL - MIN_LLM_CHECK_INTERVAL) * (1 - result["unproductive_state_confidence"]));
346060
- }
346149
+ }
346150
+ handleConfirmedLoop(result, modelName) {
346151
+ if (typeof result["unproductive_state_analysis"] === "string" && result["unproductive_state_analysis"]) {
346152
+ debugLogger.warn(result["unproductive_state_analysis"]);
346061
346153
  }
346062
- return false;
346154
+ logLoopDetected(this.config, new LoopDetectedEvent(LoopType.LLM_DETECTED_LOOP, this.promptId, modelName));
346155
+ }
346156
+ updateCheckInterval(unproductive_state_confidence) {
346157
+ this.llmCheckInterval = Math.round(MIN_LLM_CHECK_INTERVAL + (MAX_LLM_CHECK_INTERVAL - MIN_LLM_CHECK_INTERVAL) * (1 - unproductive_state_confidence));
346063
346158
  }
346064
346159
  /**
346065
346160
  * Resets all loop detection state.
@@ -346291,6 +346386,9 @@ var GeminiClient = class {
346291
346386
  this.chat = await this.startChat();
346292
346387
  this.updateTelemetryTokenCount();
346293
346388
  }
346389
+ async resumeChat(history, resumedSessionData) {
346390
+ this.chat = await this.startChat(history, resumedSessionData);
346391
+ }
346294
346392
  getChatRecordingService() {
346295
346393
  return this.chat?.getChatRecordingService();
346296
346394
  }
@@ -346309,7 +346407,7 @@ var GeminiClient = class {
346309
346407
  parts: [{ text: await getDirectoryContextString(this.config) }]
346310
346408
  });
346311
346409
  }
346312
- async startChat(extraHistory) {
346410
+ async startChat(extraHistory, resumedSessionData) {
346313
346411
  this.forceFullIdeContext = true;
346314
346412
  this.hasFailedCompressionAttempt = false;
346315
346413
  const toolRegistry = this.config.getToolRegistry();
@@ -346331,7 +346429,7 @@ var GeminiClient = class {
346331
346429
  systemInstruction,
346332
346430
  ...config2,
346333
346431
  tools
346334
- }, history);
346432
+ }, history, resumedSessionData);
346335
346433
  } catch (error) {
346336
346434
  await reportError(error, "Error initializing Gemini chat session.", history, "startChat");
346337
346435
  throw new Error(`Failed to initialize chat: ${getErrorMessage(error)}`);
@@ -346583,25 +346681,27 @@ var GeminiClient = class {
346583
346681
  }
346584
346682
  return turn;
346585
346683
  }
346586
- async generateContent(contents, generationConfig, abortSignal, model) {
346587
- let currentAttemptModel = model;
346588
- const configToUse = {
346589
- ...this.generateContentConfig,
346590
- ...generationConfig
346591
- };
346684
+ async generateContent(modelConfigKey, contents, abortSignal) {
346685
+ const desiredModelConfig = this.config.modelConfigService.getResolvedConfig(modelConfigKey);
346686
+ let { model: currentAttemptModel, generateContentConfig: currentAttemptGenerateContentConfig } = desiredModelConfig;
346687
+ const fallbackModelConfig = this.config.modelConfigService.getResolvedConfig({
346688
+ ...modelConfigKey,
346689
+ model: DEFAULT_GEMINI_FLASH_MODEL
346690
+ });
346592
346691
  try {
346593
346692
  const userMemory = this.config.getUserMemory();
346594
346693
  const systemInstruction = getCoreSystemPrompt(this.config, userMemory);
346595
- const requestConfig = {
346596
- abortSignal,
346597
- ...configToUse,
346598
- systemInstruction
346599
- };
346600
346694
  const apiCall = () => {
346601
- const modelToUse = this.config.isInFallbackMode() ? DEFAULT_GEMINI_FLASH_MODEL : model;
346602
- currentAttemptModel = modelToUse;
346695
+ const modelConfigToUse = this.config.isInFallbackMode() ? fallbackModelConfig : desiredModelConfig;
346696
+ currentAttemptModel = modelConfigToUse.model;
346697
+ currentAttemptGenerateContentConfig = modelConfigToUse.generateContentConfig;
346698
+ const requestConfig = {
346699
+ ...currentAttemptGenerateContentConfig,
346700
+ abortSignal,
346701
+ systemInstruction
346702
+ };
346603
346703
  return this.getContentGeneratorOrFail().generateContent({
346604
- model: modelToUse,
346704
+ model: currentAttemptModel,
346605
346705
  config: requestConfig,
346606
346706
  contents
346607
346707
  }, this.lastPromptId);
@@ -346621,7 +346721,7 @@ var GeminiClient = class {
346621
346721
  }
346622
346722
  await reportError(error, `Error generating content via API with model ${currentAttemptModel}.`, {
346623
346723
  requestContents: contents,
346624
- requestConfig: configToUse
346724
+ requestConfig: currentAttemptGenerateContentConfig
346625
346725
  }, "generateContent-api");
346626
346726
  throw new Error(`Failed to generate content with model ${currentAttemptModel}: ${getErrorMessage(error)}`);
346627
346727
  }
@@ -352094,7 +352194,7 @@ var DEFAULT_MODEL_CONFIGS = {
352094
352194
  }
352095
352195
  }
352096
352196
  },
352097
- "web-search-tool": {
352197
+ "web-search": {
352098
352198
  extends: "gemini-2.5-flash-base",
352099
352199
  modelConfig: {
352100
352200
  generateContentConfig: {
@@ -352102,7 +352202,7 @@ var DEFAULT_MODEL_CONFIGS = {
352102
352202
  }
352103
352203
  }
352104
352204
  },
352105
- "web-fetch-tool": {
352205
+ "web-fetch": {
352106
352206
  extends: "gemini-2.5-flash-base",
352107
352207
  modelConfig: {
352108
352208
  generateContentConfig: {
@@ -352110,10 +352210,21 @@ var DEFAULT_MODEL_CONFIGS = {
352110
352210
  }
352111
352211
  }
352112
352212
  },
352213
+ // TODO(joshualitt): During cleanup, make modelConfig optional.
352214
+ "web-fetch-fallback": {
352215
+ extends: "gemini-2.5-flash-base",
352216
+ modelConfig: {}
352217
+ },
352113
352218
  "loop-detection": {
352114
352219
  extends: "gemini-2.5-flash-base",
352115
352220
  modelConfig: {}
352116
352221
  },
352222
+ "loop-detection-double-check": {
352223
+ extends: "base",
352224
+ modelConfig: {
352225
+ model: "gemini-2.5-pro"
352226
+ }
352227
+ },
352117
352228
  "llm-edit-fixer": {
352118
352229
  extends: "gemini-2.5-flash-base",
352119
352230
  modelConfig: {}
@@ -354966,7 +355077,7 @@ async function getClientMetadata() {
354966
355077
  if (!clientMetadataPromise) {
354967
355078
  clientMetadataPromise = (async () => ({
354968
355079
  ideName: "GEMINI_CLI",
354969
- ideVersion: "0.15.0-nightly.20251111.51f952e7",
355080
+ ideVersion: "0.16.0-nightly.20251112.c961f274",
354970
355081
  platform: getPlatform(),
354971
355082
  updateChannel: await getReleaseChannel(__dirname5)
354972
355083
  }))();
@@ -355000,6 +355111,12 @@ function parseExperiments(response) {
355000
355111
  };
355001
355112
  }
355002
355113
 
355114
+ // packages/core/dist/src/code_assist/experiments/flagNames.js
355115
+ var ExperimentFlags = {
355116
+ CONTEXT_COMPRESSION_THRESHOLD: "GeminiCLIContextCompression__threshold_fraction",
355117
+ USER_CACHING: "GcliUserCaching__user_caching"
355118
+ };
355119
+
355003
355120
  // packages/core/dist/src/utils/memoryDiscovery.js
355004
355121
  import * as fs54 from "node:fs/promises";
355005
355122
  import * as fsSync from "node:fs";
@@ -357857,8 +357974,8 @@ var ErrorEvent = class extends Event {
357857
357974
  * @param inspect - The inspect function to use (prevents having to import it from `util`)
357858
357975
  * @returns A string representation of the error
357859
357976
  */
357860
- [Symbol.for("nodejs.util.inspect.custom")](_depth, options2, inspect4) {
357861
- return inspect4(inspectableError(this), options2);
357977
+ [Symbol.for("nodejs.util.inspect.custom")](_depth, options2, inspect5) {
357978
+ return inspect5(inspectableError(this), options2);
357862
357979
  }
357863
357980
  /**
357864
357981
  * Deno "hides" the `message` and `code` properties of the `ErrorEvent` instance,
@@ -357871,8 +357988,8 @@ var ErrorEvent = class extends Event {
357871
357988
  * @param options - The options passed to `Deno.inspect`
357872
357989
  * @returns A string representation of the error
357873
357990
  */
357874
- [Symbol.for("Deno.customInspect")](inspect4, options2) {
357875
- return inspect4(inspectableError(this), options2);
357991
+ [Symbol.for("Deno.customInspect")](inspect5, options2) {
357992
+ return inspect5(inspectableError(this), options2);
357876
357993
  }
357877
357994
  };
357878
357995
  function syntaxError(message) {
@@ -360442,6 +360559,8 @@ var Config = class {
360442
360559
  ideMode;
360443
360560
  inFallbackMode = false;
360444
360561
  maxSessionTurns;
360562
+ listSessions;
360563
+ deleteSession;
360445
360564
  listExtensions;
360446
360565
  _extensionLoader;
360447
360566
  _enabledExtensions;
@@ -360538,6 +360657,8 @@ var Config = class {
360538
360657
  this.model = params.model;
360539
360658
  this.maxSessionTurns = params.maxSessionTurns ?? -1;
360540
360659
  this.experimentalZedIntegration = params.experimentalZedIntegration ?? false;
360660
+ this.listSessions = params.listSessions ?? false;
360661
+ this.deleteSession = params.deleteSession;
360541
360662
  this.listExtensions = params.listExtensions ?? false;
360542
360663
  this._extensionLoader = params.extensionLoader ?? new SimpleExtensionLoader([]);
360543
360664
  this._enabledExtensions = params.enabledExtensions ?? [];
@@ -360646,6 +360767,26 @@ var Config = class {
360646
360767
  await this.getExtensionLoader().start(this)
360647
360768
  ]);
360648
360769
  await this.geminiClient.initialize();
360770
+ this.checkDeprecatedTools();
360771
+ }
360772
+ checkDeprecatedTools() {
360773
+ const deprecatedTools = [
360774
+ {
360775
+ name: READ_MANY_FILES_TOOL_NAME,
360776
+ alternateName: "ReadManyFilesTool"
360777
+ }
360778
+ ];
360779
+ const checkList = (list3, listName) => {
360780
+ if (!list3)
360781
+ return;
360782
+ for (const tool of deprecatedTools) {
360783
+ if (list3.includes(tool.name) || list3.includes(tool.alternateName)) {
360784
+ coreEvents.emitFeedback("warning", `The tool '${tool.name}' (or '${tool.alternateName}') specified in '${listName}' is deprecated and will be removed in v0.14.0.`);
360785
+ }
360786
+ }
360787
+ };
360788
+ checkList(this.coreTools, "tools.core");
360789
+ checkList(this.allowedTools, "tools.allowed");
360649
360790
  }
360650
360791
  getContentGenerator() {
360651
360792
  return this.contentGenerator;
@@ -360697,6 +360838,9 @@ var Config = class {
360697
360838
  getSessionId() {
360698
360839
  return this.sessionId;
360699
360840
  }
360841
+ setSessionId(sessionId2) {
360842
+ this.sessionId = sessionId2;
360843
+ }
360700
360844
  shouldLoadMemoryFromIncludeDirectories() {
360701
360845
  return this.loadMemoryFromIncludeDirectories;
360702
360846
  }
@@ -360941,6 +361085,12 @@ var Config = class {
360941
361085
  getListExtensions() {
360942
361086
  return this.listExtensions;
360943
361087
  }
361088
+ getListSessions() {
361089
+ return this.listSessions;
361090
+ }
361091
+ getDeleteSession() {
361092
+ return this.deleteSession;
361093
+ }
360944
361094
  getExtensionManagement() {
360945
361095
  return this.extensionManagement;
360946
361096
  }
@@ -361006,19 +361156,27 @@ var Config = class {
361006
361156
  if (this.compressionThreshold) {
361007
361157
  return this.compressionThreshold;
361008
361158
  }
361009
- if (this.experimentsPromise) {
361010
- try {
361011
- await this.experimentsPromise;
361012
- } catch (e2) {
361013
- debugLogger.debug("Failed to fetch experiments", e2);
361014
- }
361015
- }
361016
- const remoteThreshold = this.experiments?.flags["GeminiCLIContextCompression__threshold_fraction"]?.floatValue;
361159
+ await this.ensureExperimentsLoaded();
361160
+ const remoteThreshold = this.experiments?.flags[ExperimentFlags.CONTEXT_COMPRESSION_THRESHOLD]?.floatValue;
361017
361161
  if (remoteThreshold === 0) {
361018
361162
  return void 0;
361019
361163
  }
361020
361164
  return remoteThreshold;
361021
361165
  }
361166
+ async getUserCaching() {
361167
+ await this.ensureExperimentsLoaded();
361168
+ return this.experiments?.flags[ExperimentFlags.USER_CACHING]?.boolValue;
361169
+ }
361170
+ async ensureExperimentsLoaded() {
361171
+ if (!this.experimentsPromise) {
361172
+ return;
361173
+ }
361174
+ try {
361175
+ await this.experimentsPromise;
361176
+ } catch (e2) {
361177
+ debugLogger.debug("Failed to fetch experiments", e2);
361178
+ }
361179
+ }
361022
361180
  isInteractiveShellEnabled() {
361023
361181
  return this.interactive && this.ptyInfo !== "child_process" && this.enableInteractiveShell;
361024
361182
  }
@@ -361197,6 +361355,42 @@ var Config = class {
361197
361355
  */
361198
361356
  setExperiments(experiments) {
361199
361357
  this.experiments = experiments;
361358
+ const flagSummaries = Object.entries(experiments.flags ?? {}).sort(([a2], [b]) => a2.localeCompare(b)).map(([name4, flag]) => {
361359
+ const summary2 = { name: name4 };
361360
+ if (flag.boolValue !== void 0) {
361361
+ summary2["boolValue"] = flag.boolValue;
361362
+ }
361363
+ if (flag.floatValue !== void 0) {
361364
+ summary2["floatValue"] = flag.floatValue;
361365
+ }
361366
+ if (flag.intValue !== void 0) {
361367
+ summary2["intValue"] = flag.intValue;
361368
+ }
361369
+ if (flag.stringValue !== void 0) {
361370
+ summary2["stringValue"] = flag.stringValue;
361371
+ }
361372
+ const int32Length = flag.int32ListValue?.values?.length ?? 0;
361373
+ if (int32Length > 0) {
361374
+ summary2["int32ListLength"] = int32Length;
361375
+ }
361376
+ const stringListLength = flag.stringListValue?.values?.length ?? 0;
361377
+ if (stringListLength > 0) {
361378
+ summary2["stringListLength"] = stringListLength;
361379
+ }
361380
+ return summary2;
361381
+ });
361382
+ const summary = {
361383
+ experimentIds: experiments.experimentIds ?? [],
361384
+ flags: flagSummaries
361385
+ };
361386
+ const summaryString = inspect4(summary, {
361387
+ depth: null,
361388
+ maxArrayLength: null,
361389
+ maxStringLength: null,
361390
+ breakLength: 80,
361391
+ compact: false
361392
+ });
361393
+ debugLogger.debug("Experiments loaded", summaryString);
361200
361394
  }
361201
361395
  };
361202
361396