@google/gemini-cli 0.62.0-preview.0 → 0.63.0-nightly.20260928.g2fe7c2d3f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/bundle/{chunk-VNI6B2SC.js → chunk-2AXHER6I.js} +1 -1
  2. package/bundle/{chunk-7P7I4GYC.js → chunk-4PBNRKYJ.js} +1 -1
  3. package/bundle/{chunk-UDX2JG4X.js → chunk-4SQTLFVK.js} +45 -11
  4. package/bundle/{chunk-ZOLMIYBF.js → chunk-5G7FE6LZ.js} +109 -62
  5. package/bundle/{chunk-UCTTKDYX.js → chunk-7ZCWMSGJ.js} +1 -1
  6. package/bundle/{chunk-7LRWECUM.js → chunk-B3EF23HT.js} +612 -158
  7. package/bundle/{chunk-4B6A2PDH.js → chunk-BRTA6WWG.js} +9 -8
  8. package/bundle/{chunk-IP26BEPK.js → chunk-C2KZGMGL.js} +1 -1
  9. package/bundle/{chunk-67JFSAOI.js → chunk-DEI3TS7C.js} +8 -5
  10. package/bundle/{chunk-QE6MNPCN.js → chunk-EATZTV2L.js} +45 -11
  11. package/bundle/chunk-EORMOPQX.js +17368 -0
  12. package/bundle/{chunk-YHJCOL52.js → chunk-ERMD62K5.js} +8372 -14832
  13. package/bundle/chunk-EYGY6SJV.js +512 -0
  14. package/bundle/{chunk-FX7H3YXM.js → chunk-I5ZBUXWS.js} +1 -1
  15. package/bundle/{chunk-X3MDVQ2M.js → chunk-I7XQQVIO.js} +1 -1
  16. package/bundle/{chunk-IZ7EEAUQ.js → chunk-KCZCDPS2.js} +2 -2
  17. package/bundle/{chunk-2MIF7TLR.js → chunk-KRI5JA76.js} +680 -165
  18. package/bundle/{chunk-DSHGGNYE.js → chunk-KSWUQTWU.js} +3 -3
  19. package/bundle/chunk-LNPKSDNP.js +102951 -0
  20. package/bundle/{chunk-RQBLUWGO.js → chunk-PAIQESPE.js} +3 -3
  21. package/bundle/{chunk-LXVOSY26.js → chunk-PGIM2K4Q.js} +1 -1
  22. package/bundle/{chunk-HCJU65X4.js → chunk-QX7M3XMQ.js} +3 -3
  23. package/bundle/{chunk-KYWRBXUN.js → chunk-QYTRARRL.js} +2 -2
  24. package/bundle/{chunk-4SYYS7FT.js → chunk-RFR5KZGU.js} +1 -1
  25. package/bundle/{chunk-UVWRONOW.js → chunk-SJFSOFYJ.js} +2 -2
  26. package/bundle/chunk-SZK5XAFL.js +398 -0
  27. package/bundle/chunk-TXWIPUPY.js +400484 -0
  28. package/bundle/{chunk-ZNLZV6KB.js → chunk-UOXIYBXB.js} +1 -1
  29. package/bundle/chunk-VAGYZO4R.js +1571 -0
  30. package/bundle/chunk-VNGBTT2C.js +154 -0
  31. package/bundle/chunk-YZPLV23A.js +118 -0
  32. package/bundle/{chunk-ZXPUBJYD.js → chunk-ZAM747AR.js} +1 -1
  33. package/bundle/{cleanup-FHA2KSXH.js → cleanup-5PD3O5L7.js} +2 -2
  34. package/bundle/{cleanup-HY2KJG6D.js → cleanup-6IDD7Q3X.js} +2 -2
  35. package/bundle/{cleanup-UNKT2DM4.js → cleanup-7UL3PRLF.js} +2 -2
  36. package/bundle/cleanup-UTIIPF3A.js +32 -0
  37. package/bundle/{core-FGYHAZ6H.js → core-IIFMZU4H.js} +11 -1
  38. package/bundle/{devtoolsService-WDMSDVS7.js → devtoolsService-67KG4JD7.js} +2 -2
  39. package/bundle/{devtoolsService-FYN3P465.js → devtoolsService-A7VWEFDQ.js} +4 -3
  40. package/bundle/{devtoolsService-2RNXWTDT.js → devtoolsService-AK7UU2FI.js} +2 -2
  41. package/bundle/devtoolsService-REQSIEPU.js +4359 -0
  42. package/bundle/{dist-42YIZWSU.js → dist-5HHK4577.js} +11 -1
  43. package/bundle/{core-CYZFUAYU.js → dist-I74UZ4GA.js} +11 -1
  44. package/bundle/dist-QMOHSH2B.js +2248 -0
  45. package/bundle/docs/changelogs/index.md +16 -0
  46. package/bundle/docs/changelogs/latest.md +34 -55
  47. package/bundle/docs/changelogs/preview.md +65 -29
  48. package/bundle/{gemini-H6C5T6NZ.js → gemini-I47O5YI2.js} +21 -21
  49. package/bundle/{gemini-5VI65FOO.js → gemini-OFIYPHV5.js} +221 -205
  50. package/bundle/{gemini-DRDYGTKK.js → gemini-PGIEQLQD.js} +21 -21
  51. package/bundle/gemini-PLPMSDXJ.js +17863 -0
  52. package/bundle/gemini.js +7 -7
  53. package/bundle/{interactiveCli-TLTKI2C4.js → interactiveCli-CJEDKYUL.js} +31 -14
  54. package/bundle/{interactiveCli-SOVSAZ32.js → interactiveCli-JF6LE6RN.js} +334 -298
  55. package/bundle/{interactiveCli-KSL5ASTL.js → interactiveCli-JLFFVRVY.js} +31 -14
  56. package/bundle/interactiveCli-OG4JE4CU.js +34907 -0
  57. package/bundle/{liteRtServerManager-KO56TKLF.js → liteRtServerManager-4LVWWKUV.js} +4 -4
  58. package/bundle/{liteRtServerManager-T2GG72NW.js → liteRtServerManager-DVDNFJNH.js} +4 -4
  59. package/bundle/{liteRtServerManager-2CCV35OQ.js → liteRtServerManager-G4WG2Q45.js} +4 -4
  60. package/bundle/liteRtServerManager-MZO6JMNV.js +65 -0
  61. package/bundle/{oauth2-provider-TBQ7JUDB.js → oauth2-provider-CEQ4PAUC.js} +1 -1
  62. package/bundle/{oauth2-provider-BSRUMVCL.js → oauth2-provider-IBKEWCFT.js} +38 -72
  63. package/bundle/{oauth2-provider-UY26FDAA.js → oauth2-provider-KPLVYPVA.js} +1 -1
  64. package/bundle/oauth2-provider-UHJTSOLD.js +235 -0
  65. package/bundle/{start-NGSQCGCK.js → start-2A3VVOAH.js} +6 -6
  66. package/bundle/{start-RUS2QGZK.js → start-6PINHVUA.js} +6 -6
  67. package/bundle/{start-GCXJMSER.js → start-BZAGKSC2.js} +6 -6
  68. package/bundle/start-ZRUVAD7P.js +18 -0
  69. package/package.json +1 -1
@@ -252396,14 +252396,21 @@ function trimTrailingSpacesAndDots(str2) {
252396
252396
  return str2.slice(0, end + 1);
252397
252397
  }
252398
252398
  var GIT_SFN_REGEX = /^(git|gi[0-9a-f]{4})~\d+$/;
252399
- var ENV_SFN_REGEX = /^(env|en[0-9a-f]{4})~\d+$/;
252399
+ var ENV_SFN_REGEX = /^(env|en[0-9a-f]{4})~\d+(\..+)?$/i;
252400
252400
  var NODE_MODULES_SFN_REGEX = /^(node_m|no[0-9a-f]{4})~\d+$/;
252401
252401
  var GHA_CREDS_SFN_REGEX = /^(gha-cr|gh[0-9a-f]{4})~\d+\.jso(n)?$/;
252402
+ var SAFE_ENV_TEMPLATES = /* @__PURE__ */ new Set([
252403
+ ".env.example",
252404
+ ".env.sample",
252405
+ ".env.template",
252406
+ ".env.dist"
252407
+ ]);
252402
252408
  function hasBlockedPathSegment(p) {
252403
252409
  const segments = p.split(/[/\\]/);
252404
252410
  for (const segment of segments) {
252405
252411
  const clean = trimTrailingSpacesAndDots(segment.split(":")[0]).toLowerCase();
252406
- if (clean === ".git" || clean === ".env" || clean === "node_modules" || GIT_SFN_REGEX.test(clean) || ENV_SFN_REGEX.test(clean) || NODE_MODULES_SFN_REGEX.test(clean)) {
252412
+ const isEnvFile = clean === ".env" || clean.startsWith(".env.") && !SAFE_ENV_TEMPLATES.has(clean);
252413
+ if (clean === ".git" || isEnvFile || clean === "node_modules" || GIT_SFN_REGEX.test(clean) || ENV_SFN_REGEX.test(clean) || NODE_MODULES_SFN_REGEX.test(clean)) {
252407
252414
  return true;
252408
252415
  }
252409
252416
  if (clean.startsWith("gha-creds-") && clean.endsWith(".json") || GHA_CREDS_SFN_REGEX.test(clean)) {
@@ -253700,6 +253707,7 @@ var REFERENCE_CONTENT_END = "--- End of content ---";
253700
253707
  var DEFAULT_MAX_LINES_TEXT_FILE = 2e3;
253701
253708
  var MAX_LINE_LENGTH_TEXT_FILE = 2e3;
253702
253709
  var MAX_FILE_SIZE_MB = 20;
253710
+ var MAX_STORED_TOOL_OUTPUT_BYTES = 64 * 1024;
253703
253711
  var EMPTY_RESPONSE_COMPRESS_SUGGESTION = "The model returned an empty text response. If your context window is near capacity, try using /compress.";
253704
253712
  var THINKING_ONLY_COMPRESS_SUGGESTION = "The model returned reasoning thoughts but no final response text. If your context window is near capacity, try using /compress.";
253705
253713
  var MAX_TOKENS_EXCEEDED_SUGGESTION = "Model response was truncated because it exceeded the token limit. Try using /compress to free up context space.";
@@ -253783,8 +253791,41 @@ function decodeUTF32(buf, littleEndian) {
253783
253791
  }
253784
253792
  return out2;
253785
253793
  }
253786
- async function readFileWithEncoding(filePath) {
253787
- const full = await fs7.promises.readFile(filePath);
253794
+ async function readSecureFileBuffer(filePath, expectedStats) {
253795
+ const initialStats = expectedStats ?? await fs7.promises.stat(filePath);
253796
+ let fileHandle;
253797
+ try {
253798
+ if (typeof fs7.promises.open === "function") {
253799
+ try {
253800
+ fileHandle = await fs7.promises.open(filePath, "r");
253801
+ } catch {
253802
+ }
253803
+ if (fileHandle && typeof fileHandle.stat === "function") {
253804
+ const handleStats = await fileHandle.stat();
253805
+ if (initialStats.dev !== void 0 && initialStats.ino !== void 0 && handleStats && handleStats.dev !== void 0 && handleStats.ino !== void 0 && (initialStats.dev !== handleStats.dev || initialStats.ino !== handleStats.ino)) {
253806
+ throw new Error(`File device or inode changed during read: ${filePath}`);
253807
+ }
253808
+ }
253809
+ }
253810
+ const contentBuffer = fileHandle ? await fileHandle.readFile() : await fs7.promises.readFile(filePath);
253811
+ let postStats;
253812
+ try {
253813
+ postStats = await fs7.promises.stat(filePath);
253814
+ } catch {
253815
+ }
253816
+ if (postStats && initialStats.dev !== void 0 && initialStats.ino !== void 0 && postStats.dev !== void 0 && postStats.ino !== void 0 && (initialStats.dev !== postStats.dev || initialStats.ino !== postStats.ino)) {
253817
+ throw new Error(`File device or inode changed during read: ${filePath}`);
253818
+ }
253819
+ return contentBuffer;
253820
+ } finally {
253821
+ if (fileHandle) {
253822
+ await fileHandle.close().catch(() => {
253823
+ });
253824
+ }
253825
+ }
253826
+ }
253827
+ async function readFileWithEncoding(filePath, expectedStats) {
253828
+ const full = await readSecureFileBuffer(filePath, expectedStats);
253788
253829
  if (full.length === 0)
253789
253830
  return "";
253790
253831
  const bom = detectBOM(full);
@@ -254011,14 +254052,14 @@ async function processSingleFileContent(filePath, rootDirectory, _fileSystemServ
254011
254052
  returnDisplay: `Skipped large SVG file (>1MB): ${relativePathForDisplay}`
254012
254053
  };
254013
254054
  }
254014
- const content = await readFileWithEncoding(filePath);
254055
+ const content = await readFileWithEncoding(filePath, stats);
254015
254056
  return {
254016
254057
  llmContent: content,
254017
254058
  returnDisplay: `Read SVG as text: ${relativePathForDisplay}`
254018
254059
  };
254019
254060
  }
254020
254061
  case "text": {
254021
- const content = await readFileWithEncoding(filePath);
254062
+ const content = await readFileWithEncoding(filePath, stats);
254022
254063
  const lines = content.split(/\r?\n/);
254023
254064
  const originalLineCount = lines.length;
254024
254065
  let sliceStart = 0;
@@ -254068,7 +254109,7 @@ async function processSingleFileContent(filePath, rootDirectory, _fileSystemServ
254068
254109
  errorType: ToolErrorType.READ_CONTENT_FAILURE
254069
254110
  };
254070
254111
  }
254071
- const contentBuffer = await fs7.promises.readFile(filePath);
254112
+ const contentBuffer = await readSecureFileBuffer(filePath, stats);
254072
254113
  const base64Data = contentBuffer.toString("base64");
254073
254114
  return {
254074
254115
  llmContent: {
@@ -254084,7 +254125,7 @@ async function processSingleFileContent(filePath, rootDirectory, _fileSystemServ
254084
254125
  case "pdf":
254085
254126
  case "video": {
254086
254127
  const mimeType = getSpecificMimeType(filePath) ?? "application/octet-stream";
254087
- const contentBuffer = await fs7.promises.readFile(filePath);
254128
+ const contentBuffer = await readSecureFileBuffer(filePath, stats);
254088
254129
  const base64Data = contentBuffer.toString("base64");
254089
254130
  return {
254090
254131
  llmContent: {
@@ -283412,8 +283453,8 @@ function isValidToolName(name3, options = {}) {
283412
283453
  }
283413
283454
 
283414
283455
  // packages/core/dist/src/generated/git-commit.js
283415
- var GIT_COMMIT_INFO = "f50ba8608";
283416
- var CLI_VERSION = "0.62.0-preview.0";
283456
+ var GIT_COMMIT_INFO = "2fe7c2d3f";
283457
+ var CLI_VERSION = "0.63.0-nightly.20260923.gf50ba8608";
283417
283458
 
283418
283459
  // packages/core/dist/src/ide/detect-ide.js
283419
283460
  var IDE_DEFINITIONS = {
@@ -286379,7 +286420,12 @@ var ChatRecordingService = class {
286379
286420
  if (this.kind === "subagent") {
286380
286421
  filename = `${safeSessionId}.jsonl`;
286381
286422
  } else {
286382
- filename = `${SESSION_FILE_PREFIX}${timestamp2}-${safeSessionId.slice(0, 8)}.jsonl`;
286423
+ const shortId = safeSessionId.slice(0, 8);
286424
+ filename = `${SESSION_FILE_PREFIX}${timestamp2}-${shortId}.jsonl`;
286425
+ let collisionIndex = 1;
286426
+ while (fs32.existsSync(path29.join(chatsDir, filename))) {
286427
+ filename = `${SESSION_FILE_PREFIX}${timestamp2}-${collisionIndex++}-${shortId}.jsonl`;
286428
+ }
286383
286429
  }
286384
286430
  this.conversationFile = path29.join(chatsDir, filename);
286385
286431
  const directories = this.kind === "subagent" ? [
@@ -306707,7 +306753,7 @@ function getVersion() {
306707
306753
  }
306708
306754
  versionPromise = (async () => {
306709
306755
  const pkgJson = await getPackageJson(__dirname4);
306710
- return "0.62.0-preview.0";
306756
+ return "0.63.0-nightly.20260928.g2fe7c2d3f";
306711
306757
  })();
306712
306758
  return versionPromise;
306713
306759
  }
@@ -313293,10 +313339,11 @@ function getSafeGitEnv(baseEnv = process.env) {
313293
313339
  }
313294
313340
  return {
313295
313341
  ...cleanedEnv,
313342
+ GIT_TERMINAL_PROMPT: "0",
313296
313343
  GIT_CONFIG_GLOBAL: devNullPath,
313297
313344
  GIT_CONFIG_SYSTEM: devNullPath,
313298
313345
  GIT_CONFIG_NOSYSTEM: "1",
313299
- GIT_CONFIG_COUNT: "8",
313346
+ GIT_CONFIG_COUNT: "7",
313300
313347
  GIT_CONFIG_KEY_0: "credential.helper",
313301
313348
  GIT_CONFIG_VALUE_0: "",
313302
313349
  GIT_CONFIG_KEY_1: "core.fsmonitor",
@@ -313310,9 +313357,7 @@ function getSafeGitEnv(baseEnv = process.env) {
313310
313357
  GIT_CONFIG_KEY_5: "core.editor",
313311
313358
  GIT_CONFIG_VALUE_5: "",
313312
313359
  GIT_CONFIG_KEY_6: "sequence.editor",
313313
- GIT_CONFIG_VALUE_6: "",
313314
- GIT_CONFIG_KEY_7: "diff.external",
313315
- GIT_CONFIG_VALUE_7: ""
313360
+ GIT_CONFIG_VALUE_6: ""
313316
313361
  };
313317
313362
  }
313318
313363
  async function getAbsoluteGitDir(cwd) {
@@ -313607,7 +313652,14 @@ var ReadFileToolInvocation = class extends BaseToolInvocation {
313607
313652
  };
313608
313653
  }
313609
313654
  async execute(_options) {
313610
- const validationError = this.config.validatePathAccess(this.resolvedPath, "read");
313655
+ const sanitizedPath = resolveDefensiveToolPath(this.params.file_path, this.config.getTargetDir());
313656
+ let targetPathToRead = this.resolvedPath;
313657
+ try {
313658
+ targetPathToRead = resolveToRealPath(path52.resolve(this.config.getTargetDir(), sanitizedPath));
313659
+ } catch {
313660
+ targetPathToRead = path52.resolve(this.config.getTargetDir(), sanitizedPath);
313661
+ }
313662
+ const validationError = this.config.validatePathAccess(targetPathToRead, "read");
313611
313663
  if (validationError) {
313612
313664
  return {
313613
313665
  llmContent: validationError,
@@ -313618,7 +313670,7 @@ var ReadFileToolInvocation = class extends BaseToolInvocation {
313618
313670
  }
313619
313671
  };
313620
313672
  }
313621
- const result2 = await processSingleFileContent(this.resolvedPath, this.config.getTargetDir(), this.config.getFileSystemService(), this.params.start_line, this.params.end_line);
313673
+ const result2 = await processSingleFileContent(targetPathToRead, this.config.getTargetDir(), this.config.getFileSystemService(), this.params.start_line, this.params.end_line);
313622
313674
  if (result2.error) {
313623
313675
  return {
313624
313676
  llmContent: result2.llmContent,
@@ -313644,12 +313696,12 @@ ${result2.llmContent}`;
313644
313696
  llmContent = result2.llmContent || "";
313645
313697
  }
313646
313698
  const lines = typeof result2.llmContent === "string" ? result2.llmContent.split("\n").length : void 0;
313647
- const mimetype = getSpecificMimeType(this.resolvedPath);
313699
+ const mimetype = getSpecificMimeType(targetPathToRead);
313648
313700
  const programming_language = getProgrammingLanguage({
313649
- file_path: this.resolvedPath
313701
+ file_path: targetPathToRead
313650
313702
  });
313651
- logFileOperation(this.config, new FileOperationEvent(READ_FILE_TOOL_NAME, FileOperation.READ, lines, mimetype, path52.extname(this.resolvedPath), programming_language));
313652
- const jitContext = await discoverJitContext(this.config, this.resolvedPath);
313703
+ logFileOperation(this.config, new FileOperationEvent(READ_FILE_TOOL_NAME, FileOperation.READ, lines, mimetype, path52.extname(targetPathToRead), programming_language));
313704
+ const jitContext = await discoverJitContext(this.config, targetPathToRead);
313653
313705
  if (jitContext) {
313654
313706
  if (typeof llmContent === "string") {
313655
313707
  llmContent = appendJitContext(llmContent, jitContext);
@@ -313799,7 +313851,7 @@ var ReadMcpResourceToolInvocation = class extends BaseToolInvocation {
313799
313851
  }
313800
313852
  }
313801
313853
  return {
313802
- llmContent: contentText || "No content returned from resource.",
313854
+ llmContent: contentText ? wrapUntrusted(contentText) : "No content returned from resource.",
313803
313855
  returnDisplay: this.resource ? `Successfully read resource "${this.resource.name}" from server "${this.resource.serverName}"` : `Successfully read resource: ${uri}`
313804
313856
  };
313805
313857
  } catch (e2) {
@@ -313873,7 +313925,7 @@ var ListMcpResourcesToolInvocation = class extends BaseToolInvocation {
313873
313925
  content += "\n";
313874
313926
  }
313875
313927
  return {
313876
- llmContent: content,
313928
+ llmContent: wrapUntrusted(content),
313877
313929
  returnDisplay: `Listed ${resources.length} resources.`
313878
313930
  };
313879
313931
  }
@@ -322337,7 +322389,7 @@ var ActivateSkillTool = class _ActivateSkillTool extends BaseDeclarativeTool {
322337
322389
  };
322338
322390
 
322339
322391
  // packages/core/dist/src/tools/shell.js
322340
- import fsPromises9 from "node:fs/promises";
322392
+ import fsPromises10 from "node:fs/promises";
322341
322393
  import fs51 from "node:fs";
322342
322394
  import path61 from "node:path";
322343
322395
  import os32 from "node:os";
@@ -322397,6 +322449,7 @@ import { spawn as cpSpawn } from "node:child_process";
322397
322449
  import { TextDecoder as TextDecoder2 } from "node:util";
322398
322450
  import os30 from "node:os";
322399
322451
  import fs49, { mkdirSync as mkdirSync4 } from "node:fs";
322452
+ import fsPromises9 from "node:fs/promises";
322400
322453
  import path59 from "node:path";
322401
322454
  var import_headless3 = __toESM(require_xterm_headless(), 1);
322402
322455
 
@@ -323447,6 +323500,7 @@ var ShellExecutionService = class _ShellExecutionService {
323447
323500
  static activeChildProcesses = /* @__PURE__ */ new Map();
323448
323501
  static backgroundLogPids = /* @__PURE__ */ new Set();
323449
323502
  static backgroundLogStreams = /* @__PURE__ */ new Map();
323503
+ static backgroundTempDirs = /* @__PURE__ */ new Map();
323450
323504
  static backgroundProcessHistory = /* @__PURE__ */ new Map();
323451
323505
  static getLogDir() {
323452
323506
  return path59.join(Storage.getGlobalTempDir(), "background-processes");
@@ -323474,6 +323528,10 @@ ${truncated}`;
323474
323528
  }
323475
323529
  }
323476
323530
  static async cleanupLogStream(pid) {
323531
+ const tempDir = this.backgroundTempDirs.get(pid);
323532
+ this.backgroundTempDirs.delete(pid);
323533
+ const rmPromise = tempDir ? fsPromises9.rm(tempDir, { recursive: true, force: true }).catch(() => {
323534
+ }) : Promise.resolve();
323477
323535
  const stream2 = this.backgroundLogStreams.get(pid);
323478
323536
  if (stream2) {
323479
323537
  await new Promise((resolve29) => {
@@ -323482,6 +323540,7 @@ ${truncated}`;
323482
323540
  this.backgroundLogStreams.delete(pid);
323483
323541
  }
323484
323542
  this.backgroundLogPids.delete(pid);
323543
+ await rmPromise;
323485
323544
  }
323486
323545
  /**
323487
323546
  * Executes a shell command using `node-pty`, capturing all output and lifecycle events.
@@ -323574,8 +323633,7 @@ ${truncated}`;
323574
323633
  ["core.sshCommand", ""],
323575
323634
  ["core.pager", "cat"],
323576
323635
  ["core.editor", ""],
323577
- ["sequence.editor", ""],
323578
- ["diff.external", ""]
323636
+ ["sequence.editor", ""]
323579
323637
  ];
323580
323638
  for (const [overrideKey, overrideVal] of defaultGitOverrides) {
323581
323639
  const keyVar = `GIT_CONFIG_KEY_${gitConfigCount}`;
@@ -323653,6 +323711,33 @@ ${truncated}`;
323653
323711
  }
323654
323712
  }
323655
323713
  }
323714
+ if (child.stdout) {
323715
+ child.stdout.removeAllListeners();
323716
+ try {
323717
+ child.stdout.destroy();
323718
+ } catch {
323719
+ }
323720
+ }
323721
+ if (child.stderr) {
323722
+ child.stderr.removeAllListeners();
323723
+ try {
323724
+ child.stderr.destroy();
323725
+ } catch {
323726
+ }
323727
+ }
323728
+ const stdin = child.stdin;
323729
+ if (stdin) {
323730
+ stdin.removeAllListeners();
323731
+ try {
323732
+ stdin.destroy();
323733
+ } catch {
323734
+ }
323735
+ }
323736
+ child.removeAllListeners("error");
323737
+ child.removeAllListeners("close");
323738
+ state.sniffChunks.length = 0;
323739
+ stdoutDecoder = null;
323740
+ stderrDecoder = null;
323656
323741
  return;
323657
323742
  };
323658
323743
  var cleanup = cleanup2;
@@ -323680,7 +323765,8 @@ ${truncated}`;
323680
323765
  process: child,
323681
323766
  state,
323682
323767
  command: shellExecutionConfig.originalCommand ?? commandToExecute,
323683
- sessionId: shellExecutionConfig.sessionId
323768
+ sessionId: shellExecutionConfig.sessionId,
323769
+ tempDir: shellExecutionConfig.tempDir
323684
323770
  });
323685
323771
  }
323686
323772
  const lifecycleHandle = child.pid ? ExecutionLifecycleService.attachExecution(child.pid, {
@@ -323784,6 +323870,7 @@ ${truncated}`;
323784
323870
  cleanup2();
323785
323871
  cmdCleanup?.();
323786
323872
  let combinedOutput = state.output;
323873
+ state.output = "";
323787
323874
  if (state.truncated) {
323788
323875
  const truncationMessage = `
323789
323876
  [GEMINI_CLI_WARNING: Output truncated. The buffer is limited to ${MAX_CHILD_PROCESS_BUFFER_SIZE / (1024 * 1024)}MB.]`;
@@ -323819,9 +323906,8 @@ ${truncated}`;
323819
323906
  historyItem.endTime = Date.now();
323820
323907
  }
323821
323908
  onOutputEvent(event);
323822
- _ShellExecutionService.cleanupLogStream(pid).then(() => {
323823
- _ShellExecutionService.activeChildProcesses.delete(pid);
323824
- });
323909
+ _ShellExecutionService.activeChildProcesses.delete(pid);
323910
+ _ShellExecutionService.cleanupLogStream(pid);
323825
323911
  ExecutionLifecycleService.completeWithResult(pid, resultPayload);
323826
323912
  } else {
323827
323913
  resolveWithoutPid?.(resultPayload);
@@ -324031,7 +324117,8 @@ ${truncated}`;
324031
324117
  maxSerializedLines: shellExecutionConfig.maxSerializedLines,
324032
324118
  command: shellExecutionConfig.originalCommand ?? commandToExecute,
324033
324119
  sessionId: shellExecutionConfig.sessionId,
324034
- cancelRender
324120
+ cancelRender,
324121
+ tempDir: shellExecutionConfig.tempDir
324035
324122
  });
324036
324123
  const result2 = ExecutionLifecycleService.attachExecution(assignedPid, {
324037
324124
  executionMethod: ptyInfo?.name ?? "node-pty",
@@ -324448,18 +324535,32 @@ ${truncated}`;
324448
324535
  * This resolves the execution promise but keeps the PTY active.
324449
324536
  *
324450
324537
  * @param pid The process ID of the target PTY.
324538
+ * @param sessionId Optional session ID for process history tracking.
324539
+ * @param command Optional command string for display.
324540
+ * @param tempDir Optional temporary directory path owned by this execution to clean up on exit.
324451
324541
  */
324452
- static background(pid, sessionId, command) {
324453
- if (this.backgroundLogPids.has(pid)) {
324454
- return;
324455
- }
324542
+ static background(pid, sessionId, command, tempDir) {
324456
324543
  const activePty = this.activePtys.get(pid);
324457
324544
  const activeChild = this.activeChildProcesses.get(pid);
324545
+ const resolvedTempDir = tempDir ?? activePty?.tempDir ?? activeChild?.tempDir;
324458
324546
  const resolvedSessionId = sessionId ?? activePty?.sessionId ?? activeChild?.sessionId;
324459
324547
  const resolvedCommand = command ?? activePty?.command ?? activeChild?.command ?? "unknown command";
324460
324548
  if (!resolvedSessionId) {
324461
324549
  throw new Error("Session ID is required for background operations");
324462
324550
  }
324551
+ if (!activePty && !activeChild) {
324552
+ if (resolvedTempDir) {
324553
+ fsPromises9.rm(resolvedTempDir, { recursive: true, force: true }).catch(() => {
324554
+ });
324555
+ }
324556
+ return;
324557
+ }
324558
+ if (resolvedTempDir) {
324559
+ this.backgroundTempDirs.set(pid, resolvedTempDir);
324560
+ }
324561
+ if (this.backgroundLogPids.has(pid)) {
324562
+ return;
324563
+ }
324463
324564
  const MAX_BACKGROUND_PROCESS_HISTORY_SIZE = 100;
324464
324565
  const history = this.backgroundProcessHistory.get(resolvedSessionId) ?? /* @__PURE__ */ new Map();
324465
324566
  if (history.size >= MAX_BACKGROUND_PROCESS_HISTORY_SIZE) {
@@ -324471,7 +324572,8 @@ ${truncated}`;
324471
324572
  history.set(pid, {
324472
324573
  command: resolvedCommand,
324473
324574
  status: "running",
324474
- startTime: Date.now()
324575
+ startTime: Date.now(),
324576
+ ...resolvedTempDir ? { tempDir: resolvedTempDir } : {}
324475
324577
  });
324476
324578
  this.backgroundProcessHistory.set(resolvedSessionId, history);
324477
324579
  const logPath = this.getLogFilePath(pid);
@@ -324611,8 +324713,15 @@ ${truncated}`;
324611
324713
  } catch {
324612
324714
  }
324613
324715
  }
324716
+ for (const tempDir of this.backgroundTempDirs.values()) {
324717
+ try {
324718
+ fs49.rmSync(tempDir, { recursive: true, force: true });
324719
+ } catch {
324720
+ }
324721
+ }
324614
324722
  this.backgroundLogPids.clear();
324615
324723
  this.backgroundLogStreams.clear();
324724
+ this.backgroundTempDirs.clear();
324616
324725
  this.backgroundProcessHistory.clear();
324617
324726
  }
324618
324727
  };
@@ -324904,15 +325013,19 @@ exit $__code`;
324904
325013
  getExplanation() {
324905
325014
  return this.getContextualDetails().trim();
324906
325015
  }
325016
+ hasTaintedOrBuildFileRisk() {
325017
+ const command = stripShellWrapper(this.params.command);
325018
+ const history = this.getHistory();
325019
+ const untrustedContext = extractUntrustedContext(history);
325020
+ const untrustedFlags = findUntrustedFlags(command, untrustedContext);
325021
+ const modifiedBuildFiles = getModifiedBuildFiles(this.context.config);
325022
+ const isBuildCmd = isBuildOrTestCommand(command);
325023
+ return untrustedFlags.length > 0 || isBuildCmd && modifiedBuildFiles.length > 0;
325024
+ }
324907
325025
  getPolicyUpdateOptions(outcome) {
324908
325026
  if (outcome === ToolConfirmationOutcome.ProceedAlwaysAndSave || outcome === ToolConfirmationOutcome.ProceedAlways) {
324909
325027
  const command = stripShellWrapper(this.params.command);
324910
- const history = this.getHistory();
324911
- const untrustedContext = extractUntrustedContext(history);
324912
- const untrustedFlags = findUntrustedFlags(command, untrustedContext);
324913
- const modifiedBuildFiles = getModifiedBuildFiles(this.context.config);
324914
- const isBuildCmd = isBuildOrTestCommand(command);
324915
- if (untrustedFlags.length > 0 || isBuildCmd && modifiedBuildFiles.length > 0) {
325028
+ if (this.hasTaintedOrBuildFileRisk()) {
324916
325029
  return void 0;
324917
325030
  }
324918
325031
  const rootCommands = [...new Set(getCommandRoots(command))];
@@ -324928,24 +325041,18 @@ exit $__code`;
324928
325041
  if (forcedDecision === "deny") {
324929
325042
  return super.shouldConfirmExecute(abortSignal, forcedDecision);
324930
325043
  }
324931
- const command = stripShellWrapper(this.params.command);
324932
- const history = this.getHistory();
324933
- const untrustedContext = extractUntrustedContext(history);
324934
- const untrustedFlags = findUntrustedFlags(command, untrustedContext);
324935
- const modifiedBuildFiles = getModifiedBuildFiles(this.context.config);
324936
- const isBuildCmd = isBuildOrTestCommand(command);
324937
- if (untrustedFlags.length > 0 || isBuildCmd && modifiedBuildFiles.length > 0) {
325044
+ if (this.hasTaintedOrBuildFileRisk()) {
324938
325045
  return this.getConfirmationDetails(abortSignal);
324939
325046
  }
324940
- if (this.context.config.getApprovalMode() === ApprovalMode.YOLO) {
325047
+ if (this.context.config.getApprovalMode() === ApprovalMode.YOLO && forcedDecision !== "ask_user") {
324941
325048
  return super.shouldConfirmExecute(abortSignal, forcedDecision);
324942
325049
  }
324943
325050
  if (this.params[PARAM_ADDITIONAL_PERMISSIONS]) {
324944
325051
  return this.getConfirmationDetails(abortSignal);
324945
325052
  }
324946
325053
  if (this.context.config.getSandboxEnabled()) {
324947
- const command2 = stripShellWrapper(this.params.command);
324948
- const rootCommands = getCommandRoots(command2);
325054
+ const command = stripShellWrapper(this.params.command);
325055
+ const rootCommands = getCommandRoots(command);
324949
325056
  const rawRootCommand = rootCommands[0];
324950
325057
  if (rawRootCommand) {
324951
325058
  const rootCommand = normalizeCommand(rawRootCommand);
@@ -324956,7 +325063,7 @@ exit $__code`;
324956
325063
  const approved = this.context.config.sandboxPolicyManager.getCommandPermissions(rootCommand);
324957
325064
  const hasNetwork = modeConfig.network || approved.network;
324958
325065
  const missingNetwork = !!proactive.network && !hasNetwork;
324959
- const parsed = parseCommandDetails(command2);
325066
+ const parsed = parseCommandDetails(command);
324960
325067
  const subCommand = parsed?.details[0]?.args?.[0];
324961
325068
  const needsNetwork = isNetworkReliantCommand(rootCommand, subCommand);
324962
325069
  if (needsNetwork) {
@@ -325076,6 +325183,7 @@ exit $__code`;
325076
325183
  const isWindows3 = os32.platform() === "win32";
325077
325184
  let tempFilePath = "";
325078
325185
  let tempDir = "";
325186
+ let isBackgrounded = false;
325079
325187
  const timeoutMs = this.context.config.getShellToolInactivityTimeout();
325080
325188
  const timeoutController = new AbortController();
325081
325189
  let timeoutTimer;
@@ -325218,7 +325326,8 @@ exit $__code`;
325218
325326
  }
325219
325327
  },
325220
325328
  backgroundCompletionBehavior: this.context.config.getShellBackgroundCompletionBehavior(),
325221
- originalCommand: strippedCommand
325329
+ originalCommand: strippedCommand,
325330
+ tempDir
325222
325331
  });
325223
325332
  if (pid) {
325224
325333
  if (setExecutionIdCallback) {
@@ -325231,7 +325340,12 @@ exit $__code`;
325231
325340
  let promotionTimer = setTimeout(() => {
325232
325341
  promotionTimer = null;
325233
325342
  if (!completed) {
325234
- ShellExecutionService.background(pid, sessionId, strippedCommand);
325343
+ try {
325344
+ ShellExecutionService.background(pid, sessionId, strippedCommand, tempDir);
325345
+ isBackgrounded = true;
325346
+ } catch (err2) {
325347
+ debugLogger.error("Failed to background shell execution:", err2);
325348
+ }
325235
325349
  }
325236
325350
  }, delay3);
325237
325351
  const clearPromotionTimer = () => {
@@ -325268,20 +325382,22 @@ ${cumulativeOutput}`,
325268
325382
  }
325269
325383
  }
325270
325384
  const result2 = await resultPromise;
325271
- if (!result2.backgrounded) {
325385
+ if (result2.backgrounded) {
325386
+ isBackgrounded = true;
325387
+ } else {
325272
325388
  flushOutput();
325273
325389
  }
325274
325390
  const backgroundPIDs = [];
325275
325391
  if (os32.platform() !== "win32") {
325276
325392
  let tempFileExists = false;
325277
325393
  try {
325278
- await fsPromises9.access(tempFilePath);
325394
+ await fsPromises10.access(tempFilePath);
325279
325395
  tempFileExists = true;
325280
325396
  } catch {
325281
325397
  tempFileExists = false;
325282
325398
  }
325283
325399
  if (tempFileExists) {
325284
- const backgroundPIDContent = await fsPromises9.readFile(tempFilePath, "utf8");
325400
+ const backgroundPIDContent = await fsPromises10.readFile(tempFilePath, "utf8");
325285
325401
  const backgroundPIDLines = backgroundPIDContent.split("\n").map((line) => line.trim()).filter(Boolean);
325286
325402
  for (const line of backgroundPIDLines) {
325287
325403
  if (!/^\d+$/.test(line)) {
@@ -325507,16 +325623,16 @@ ${result2.output}`;
325507
325623
  }
325508
325624
  signal.removeEventListener("abort", onAbort);
325509
325625
  timeoutController.signal.removeEventListener("abort", onAbort);
325510
- if (!this.params.is_background) {
325626
+ if (!isBackgrounded) {
325511
325627
  if (tempFilePath) {
325512
325628
  try {
325513
- await fsPromises9.unlink(tempFilePath);
325629
+ await fsPromises10.unlink(tempFilePath);
325514
325630
  } catch {
325515
325631
  }
325516
325632
  }
325517
325633
  if (tempDir) {
325518
325634
  try {
325519
- await fsPromises9.rm(tempDir, { recursive: true, force: true });
325635
+ await fsPromises10.rm(tempDir, { recursive: true, force: true });
325520
325636
  } catch {
325521
325637
  }
325522
325638
  }
@@ -331471,7 +331587,7 @@ var WebSearchToolInvocation = class extends BaseToolInvocation {
331471
331587
  return {
331472
331588
  llmContent: `Web search results for "${this.params.query}":
331473
331589
 
331474
- ${modifiedResponseText}`,
331590
+ ${wrapUntrusted(modifiedResponseText)}`,
331475
331591
  returnDisplay: `Search results for "${this.params.query}" returned.`,
331476
331592
  sources
331477
331593
  };
@@ -335883,6 +335999,133 @@ var PreCompressTrigger;
335883
335999
 
335884
336000
  // packages/core/dist/src/context/chatCompressionService.js
335885
336001
  var DEFAULT_COMPRESSION_TOKEN_THRESHOLD = 0.5;
336002
+ var RECENT_TURNS_PROTECTED = 3;
336003
+ var RETRIEVAL_TOOL_NAMES_EXEMPT_FROM_COLLAPSE = /* @__PURE__ */ new Set([
336004
+ "read_file",
336005
+ "read_many_files",
336006
+ "get_internal_docs",
336007
+ "read_mcp_resource",
336008
+ "grep",
336009
+ "rip_grep",
336010
+ "glob",
336011
+ "search_file_content",
336012
+ "find_files"
336013
+ ]);
336014
+ function isExemptRetrievalTool(toolName, exemptTools = RETRIEVAL_TOOL_NAMES_EXEMPT_FROM_COLLAPSE) {
336015
+ if (!toolName) {
336016
+ return false;
336017
+ }
336018
+ const normalized2 = toolName.toLowerCase();
336019
+ if (exemptTools.has(normalized2)) {
336020
+ return true;
336021
+ }
336022
+ return normalized2.endsWith("read_file") || normalized2.endsWith("read_files") || normalized2.endsWith("read_many_files") || normalized2.endsWith("read_resource");
336023
+ }
336024
+ var COLLAPSED_FUNCTION_RESPONSE_MAX_BYTES = 2048;
336025
+ var defaultGraphemeSegmenter = new Intl.Segmenter(void 0, {
336026
+ granularity: "grapheme"
336027
+ });
336028
+ function collapseOlderFunctionResponses(history, maxBytesPerOldResponse = COLLAPSED_FUNCTION_RESPONSE_MAX_BYTES, segmenter2 = defaultGraphemeSegmenter, protectedTurns = RECENT_TURNS_PROTECTED, exemptTools = RETRIEVAL_TOOL_NAMES_EXEMPT_FROM_COLLAPSE) {
336029
+ const toolIndices = [];
336030
+ for (let i3 = 0; i3 < history.length; i3++) {
336031
+ if (history[i3].role === "user" && history[i3].parts?.some((p) => !!p.functionResponse)) {
336032
+ toolIndices.push(i3);
336033
+ }
336034
+ }
336035
+ if (toolIndices.length <= protectedTurns) {
336036
+ return history;
336037
+ }
336038
+ const cutoffToolIndex = toolIndices[toolIndices.length - protectedTurns];
336039
+ const collapseString = (str2) => {
336040
+ const totalBytes = Buffer.byteLength(str2, "utf8");
336041
+ if (totalBytes <= maxBytesPerOldResponse) {
336042
+ return str2;
336043
+ }
336044
+ const previewBytes = maxBytesPerOldResponse;
336045
+ let preview = "";
336046
+ let currentBytes = 0;
336047
+ for (const { segment } of segmenter2.segment(str2)) {
336048
+ const segmentBytes = Buffer.byteLength(segment, "utf8");
336049
+ if (currentBytes + segmentBytes > previewBytes) {
336050
+ break;
336051
+ }
336052
+ preview += segment;
336053
+ currentBytes += segmentBytes;
336054
+ }
336055
+ const omittedBytes = totalBytes - currentBytes;
336056
+ return `${preview}
336057
+ ... [Tool output collapsed from previous turn: ${omittedBytes} bytes omitted to conserve memory] ...`;
336058
+ };
336059
+ const collapseValue = (val) => {
336060
+ if (typeof val === "string") {
336061
+ return collapseString(val);
336062
+ }
336063
+ if (Array.isArray(val)) {
336064
+ let arrayModified = false;
336065
+ const newVal = val.map((item) => {
336066
+ const collapsed = collapseValue(item);
336067
+ if (collapsed !== item) {
336068
+ arrayModified = true;
336069
+ }
336070
+ return collapsed;
336071
+ });
336072
+ return arrayModified ? newVal : val;
336073
+ }
336074
+ if (typeof val === "object" && val !== null) {
336075
+ const proto = Object.getPrototypeOf(val);
336076
+ if (proto !== Object.prototype && proto !== null) {
336077
+ return val;
336078
+ }
336079
+ let objModified = false;
336080
+ const copy = {};
336081
+ for (const [k, v] of Object.entries(val)) {
336082
+ const collapsed = collapseValue(v);
336083
+ if (collapsed !== v) {
336084
+ objModified = true;
336085
+ }
336086
+ copy[k] = collapsed;
336087
+ }
336088
+ return objModified ? copy : val;
336089
+ }
336090
+ return val;
336091
+ };
336092
+ let modified = false;
336093
+ const newHistory = history.map((content, idx) => {
336094
+ if (idx >= cutoffToolIndex || content.role !== "user" || !content.parts) {
336095
+ return content;
336096
+ }
336097
+ let partsModified = false;
336098
+ const newParts = content.parts.map((part) => {
336099
+ if (!part.functionResponse?.response) {
336100
+ return part;
336101
+ }
336102
+ if (isExemptRetrievalTool(part.functionResponse.name, exemptTools)) {
336103
+ return part;
336104
+ }
336105
+ const resp = part.functionResponse.response;
336106
+ const newResp = collapseValue(resp);
336107
+ if (newResp !== resp) {
336108
+ partsModified = true;
336109
+ return {
336110
+ ...part,
336111
+ functionResponse: {
336112
+ // eslint-disable-next-line @typescript-eslint/no-misused-spread
336113
+ ...part.functionResponse,
336114
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
336115
+ response: newResp
336116
+ }
336117
+ };
336118
+ }
336119
+ return part;
336120
+ });
336121
+ if (partsModified) {
336122
+ modified = true;
336123
+ return { ...content, parts: newParts };
336124
+ }
336125
+ return content;
336126
+ });
336127
+ return modified ? newHistory : history;
336128
+ }
335886
336129
  var COMPRESSION_PRESERVE_THRESHOLD = 0.3;
335887
336130
  var COMPRESSION_FUNCTION_RESPONSE_TOKEN_BUDGET = 5e4;
335888
336131
  function findCompressSplitPoint(contents, fraction) {
@@ -336011,10 +336254,12 @@ var ChatCompressionService = class {
336011
336254
  }
336012
336255
  const trigger = force ? PreCompressTrigger.Manual : PreCompressTrigger.Auto;
336013
336256
  await config2.getHookSystem()?.firePreCompressEvent(trigger);
336014
- const originalTokenCount = chat.getLastPromptTokenCount();
336257
+ const lastPromptTokenCount = chat.getLastPromptTokenCount();
336258
+ const originalTokenCount = lastPromptTokenCount > 0 ? lastPromptTokenCount : estimateTokenCountSync(curatedHistory.flatMap((c4) => c4.parts || []));
336015
336259
  if (!force) {
336016
336260
  const threshold = await config2.getCompressionThreshold() ?? DEFAULT_COMPRESSION_TOKEN_THRESHOLD;
336017
- if (originalTokenCount < threshold * tokenLimit(model)) {
336261
+ const isOverModelThreshold = originalTokenCount >= threshold * tokenLimit(model);
336262
+ if (!isOverModelThreshold) {
336018
336263
  return {
336019
336264
  newHistory: null,
336020
336265
  info: {
@@ -336152,6 +336397,8 @@ First, reason in your scratchpad. Then, generate the updated <state_snapshot>.`
336152
336397
  }
336153
336398
  };
336154
336399
  } else {
336400
+ historyToCompressTruncated.length = 0;
336401
+ originalHistoryToCompress.length = 0;
336155
336402
  return {
336156
336403
  newHistory: extraHistory,
336157
336404
  info: {
@@ -336164,6 +336411,169 @@ First, reason in your scratchpad. Then, generate the updated <state_snapshot>.`
336164
336411
  }
336165
336412
  };
336166
336413
 
336414
+ // packages/core/dist/src/utils/tool-utils.js
336415
+ var import_fast_levenshtein2 = __toESM(require_levenshtein(), 1);
336416
+ function isToolCallResponseInfo(data) {
336417
+ return typeof data === "object" && data !== null && "callId" in data && "responseParts" in data;
336418
+ }
336419
+ function getToolSuggestion(unknownToolName, allToolNames, topN = 3) {
336420
+ const matches = allToolNames.map((toolName) => ({
336421
+ name: toolName,
336422
+ distance: import_fast_levenshtein2.default.get(unknownToolName, toolName)
336423
+ }));
336424
+ matches.sort((a2, b) => a2.distance - b.distance);
336425
+ const topNResults = matches.slice(0, topN);
336426
+ if (topNResults.length === 0) {
336427
+ return "";
336428
+ }
336429
+ const suggestedNames = topNResults.map((match2) => `"${match2.name}"`).join(", ");
336430
+ if (topNResults.length > 1) {
336431
+ return ` Did you mean one of: ${suggestedNames}?`;
336432
+ } else {
336433
+ return ` Did you mean ${suggestedNames}?`;
336434
+ }
336435
+ }
336436
+ function doesToolInvocationMatch(toolOrToolName, invocation, patterns) {
336437
+ let toolNames;
336438
+ if (isTool(toolOrToolName)) {
336439
+ toolNames = [toolOrToolName.name, toolOrToolName.constructor.name];
336440
+ } else {
336441
+ toolNames = [toolOrToolName];
336442
+ }
336443
+ if (toolNames.some((name3) => SHELL_TOOL_NAMES.includes(name3))) {
336444
+ toolNames = [.../* @__PURE__ */ new Set([...toolNames, ...SHELL_TOOL_NAMES])];
336445
+ }
336446
+ for (const pattern of patterns) {
336447
+ const openParen = pattern.indexOf("(");
336448
+ if (openParen === -1) {
336449
+ if (toolNames.includes(pattern)) {
336450
+ return true;
336451
+ }
336452
+ continue;
336453
+ }
336454
+ const patternToolName = pattern.substring(0, openParen);
336455
+ if (!toolNames.includes(patternToolName)) {
336456
+ continue;
336457
+ }
336458
+ if (!pattern.endsWith(")")) {
336459
+ continue;
336460
+ }
336461
+ const argPattern = pattern.substring(openParen + 1, pattern.length - 1);
336462
+ let command;
336463
+ if (typeof invocation === "string") {
336464
+ command = invocation;
336465
+ } else {
336466
+ if (!("command" in invocation.params)) {
336467
+ continue;
336468
+ }
336469
+ command = String(invocation.params.command);
336470
+ }
336471
+ if (toolNames.some((name3) => SHELL_TOOL_NAMES.includes(name3))) {
336472
+ if (command === argPattern || command.startsWith(argPattern + " ")) {
336473
+ return true;
336474
+ }
336475
+ }
336476
+ }
336477
+ return false;
336478
+ }
336479
+ var segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
336480
+ function truncateToolOutput(text, maxBytes = MAX_STORED_TOOL_OUTPUT_BYTES, savedFilePath) {
336481
+ if (Buffer.byteLength(text, "utf8") <= maxBytes) {
336482
+ return text;
336483
+ }
336484
+ const suffix = savedFilePath ? `
336485
+ ... [Tool output truncated to conserve memory. For full output see: ${savedFilePath}]` : "\n... [Tool output truncated to conserve memory]";
336486
+ const targetBytes = Math.max(0, maxBytes - Buffer.byteLength(suffix, "utf8"));
336487
+ let accumulatedBytes = 0;
336488
+ let truncatedText = "";
336489
+ for (const { segment } of segmenter.segment(text)) {
336490
+ const segmentBytes = Buffer.byteLength(segment, "utf8");
336491
+ if (accumulatedBytes + segmentBytes > targetBytes) {
336492
+ break;
336493
+ }
336494
+ accumulatedBytes += segmentBytes;
336495
+ truncatedText += segment;
336496
+ }
336497
+ return truncatedText + suffix;
336498
+ }
336499
+ function truncateFunctionResponsePart(part, maxBytes = MAX_STORED_TOOL_OUTPUT_BYTES, savedFilePath) {
336500
+ if (part.text && Buffer.byteLength(part.text, "utf8") > maxBytes) {
336501
+ return {
336502
+ ...part,
336503
+ text: truncateToolOutput(part.text, maxBytes, savedFilePath)
336504
+ };
336505
+ }
336506
+ if (!part.functionResponse?.response) {
336507
+ return part;
336508
+ }
336509
+ const resp = part.functionResponse.response;
336510
+ if (typeof resp === "string") {
336511
+ if (Buffer.byteLength(resp, "utf8") > maxBytes) {
336512
+ return {
336513
+ ...part,
336514
+ functionResponse: {
336515
+ // eslint-disable-next-line @typescript-eslint/no-misused-spread
336516
+ ...part.functionResponse,
336517
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
336518
+ response: truncateToolOutput(resp, maxBytes, savedFilePath)
336519
+ }
336520
+ };
336521
+ }
336522
+ return part;
336523
+ }
336524
+ if (typeof resp === "object" && resp !== null) {
336525
+ const truncateValue = (val) => {
336526
+ if (typeof val === "string") {
336527
+ if (Buffer.byteLength(val, "utf8") > maxBytes) {
336528
+ return truncateToolOutput(val, maxBytes, savedFilePath);
336529
+ }
336530
+ return val;
336531
+ }
336532
+ if (Array.isArray(val)) {
336533
+ let arrayModified = false;
336534
+ const newVal = val.map((item) => {
336535
+ const truncated = truncateValue(item);
336536
+ if (truncated !== item) {
336537
+ arrayModified = true;
336538
+ }
336539
+ return truncated;
336540
+ });
336541
+ return arrayModified ? newVal : val;
336542
+ }
336543
+ if (typeof val === "object" && val !== null) {
336544
+ const proto = Object.getPrototypeOf(val);
336545
+ if (proto !== Object.prototype && proto !== null) {
336546
+ return val;
336547
+ }
336548
+ let objModified = false;
336549
+ const copy = {};
336550
+ for (const [k, v] of Object.entries(val)) {
336551
+ const truncated = truncateValue(v);
336552
+ if (truncated !== v) {
336553
+ objModified = true;
336554
+ }
336555
+ copy[k] = truncated;
336556
+ }
336557
+ return objModified ? copy : val;
336558
+ }
336559
+ return val;
336560
+ };
336561
+ const newResp = truncateValue(resp);
336562
+ if (newResp !== resp) {
336563
+ return {
336564
+ ...part,
336565
+ functionResponse: {
336566
+ // eslint-disable-next-line @typescript-eslint/no-misused-spread
336567
+ ...part.functionResponse,
336568
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
336569
+ response: newResp
336570
+ }
336571
+ };
336572
+ }
336573
+ }
336574
+ return part;
336575
+ }
336576
+
336167
336577
  // packages/core/dist/src/agents/types.js
336168
336578
  var AgentTerminateMode;
336169
336579
  (function(AgentTerminateMode2) {
@@ -340529,7 +340939,7 @@ var A2AAuthProviderFactory = class _A2AAuthProviderFactory {
340529
340939
  return provider;
340530
340940
  }
340531
340941
  case "oauth2": {
340532
- const { OAuth2AuthProvider } = await import("./oauth2-provider-TBQ7JUDB.js");
340942
+ const { OAuth2AuthProvider } = await import("./oauth2-provider-CEQ4PAUC.js");
340533
340943
  const provider = new OAuth2AuthProvider(authConfig, options.agentName ?? "unknown", agentCard, options.agentCardUrl);
340534
340944
  await provider.initialize();
340535
340945
  return provider;
@@ -341651,72 +342061,6 @@ function getToolCallContext() {
341651
342061
  return toolCallContext.getStore();
341652
342062
  }
341653
342063
 
341654
- // packages/core/dist/src/utils/tool-utils.js
341655
- var import_fast_levenshtein2 = __toESM(require_levenshtein(), 1);
341656
- function isToolCallResponseInfo(data) {
341657
- return typeof data === "object" && data !== null && "callId" in data && "responseParts" in data;
341658
- }
341659
- function getToolSuggestion(unknownToolName, allToolNames, topN = 3) {
341660
- const matches = allToolNames.map((toolName) => ({
341661
- name: toolName,
341662
- distance: import_fast_levenshtein2.default.get(unknownToolName, toolName)
341663
- }));
341664
- matches.sort((a2, b) => a2.distance - b.distance);
341665
- const topNResults = matches.slice(0, topN);
341666
- if (topNResults.length === 0) {
341667
- return "";
341668
- }
341669
- const suggestedNames = topNResults.map((match2) => `"${match2.name}"`).join(", ");
341670
- if (topNResults.length > 1) {
341671
- return ` Did you mean one of: ${suggestedNames}?`;
341672
- } else {
341673
- return ` Did you mean ${suggestedNames}?`;
341674
- }
341675
- }
341676
- function doesToolInvocationMatch(toolOrToolName, invocation, patterns) {
341677
- let toolNames;
341678
- if (isTool(toolOrToolName)) {
341679
- toolNames = [toolOrToolName.name, toolOrToolName.constructor.name];
341680
- } else {
341681
- toolNames = [toolOrToolName];
341682
- }
341683
- if (toolNames.some((name3) => SHELL_TOOL_NAMES.includes(name3))) {
341684
- toolNames = [.../* @__PURE__ */ new Set([...toolNames, ...SHELL_TOOL_NAMES])];
341685
- }
341686
- for (const pattern of patterns) {
341687
- const openParen = pattern.indexOf("(");
341688
- if (openParen === -1) {
341689
- if (toolNames.includes(pattern)) {
341690
- return true;
341691
- }
341692
- continue;
341693
- }
341694
- const patternToolName = pattern.substring(0, openParen);
341695
- if (!toolNames.includes(patternToolName)) {
341696
- continue;
341697
- }
341698
- if (!pattern.endsWith(")")) {
341699
- continue;
341700
- }
341701
- const argPattern = pattern.substring(openParen + 1, pattern.length - 1);
341702
- let command;
341703
- if (typeof invocation === "string") {
341704
- command = invocation;
341705
- } else {
341706
- if (!("command" in invocation.params)) {
341707
- continue;
341708
- }
341709
- command = String(invocation.params.command);
341710
- }
341711
- if (toolNames.some((name3) => SHELL_TOOL_NAMES.includes(name3))) {
341712
- if (command === argPattern || command.startsWith(argPattern + " ")) {
341713
- return true;
341714
- }
341715
- }
341716
- }
341717
- return false;
341718
- }
341719
-
341720
342064
  // packages/core/dist/src/scheduler/state-manager.js
341721
342065
  var SchedulerStateManager = class {
341722
342066
  messageBus;
@@ -343425,7 +343769,7 @@ ${summary}
343425
343769
 
343426
343770
  // packages/core/dist/src/context/toolOutputMaskingService.js
343427
343771
  import path68 from "node:path";
343428
- import * as fsPromises10 from "node:fs/promises";
343772
+ import * as fsPromises11 from "node:fs/promises";
343429
343773
  var DEFAULT_TOOL_PROTECTION_THRESHOLD = 5e4;
343430
343774
  var DEFAULT_MIN_PRUNABLE_TOKENS_THRESHOLD = 3e4;
343431
343775
  var DEFAULT_PROTECT_LATEST_TURN = true;
@@ -343502,7 +343846,7 @@ var ToolOutputMaskingService = class {
343502
343846
  const safeSessionId = sanitizeFilenamePart(sessionId);
343503
343847
  toolOutputsDir = path68.join(toolOutputsDir, `session-${safeSessionId}`);
343504
343848
  }
343505
- await fsPromises10.mkdir(toolOutputsDir, { recursive: true });
343849
+ await fsPromises11.mkdir(toolOutputsDir, { recursive: true });
343506
343850
  for (const item of prunableParts) {
343507
343851
  const { contentIndex, partIndex, content, tokens } = item;
343508
343852
  const contentRecord = newHistory[contentIndex];
@@ -343515,7 +343859,7 @@ var ToolOutputMaskingService = class {
343515
343859
  const safeCallId = sanitizeFilenamePart(callId).toLowerCase();
343516
343860
  const fileName = `${safeToolName}_${safeCallId}_${Math.random().toString(36).substring(7)}.txt`;
343517
343861
  const filePath = path68.join(toolOutputsDir, fileName);
343518
- await fsPromises10.writeFile(filePath, content, "utf-8");
343862
+ await fsPromises11.writeFile(filePath, content, "utf-8");
343519
343863
  const originalResponse = (
343520
343864
  // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
343521
343865
  part.functionResponse.response || {}
@@ -346768,6 +347112,15 @@ var GeminiClient = class {
346768
347112
  coreEvents.off(CoreEvent.ApprovalModeChanged, this.handleApprovalModeChanged);
346769
347113
  }
346770
347114
  async resumeChat(history, resumedSessionData) {
347115
+ if (resumedSessionData?.filePath) {
347116
+ const previousRecordingService = this.chat?.getChatRecordingService?.();
347117
+ if (previousRecordingService && previousRecordingService.getConversationFilePath?.() !== resumedSessionData.filePath) {
347118
+ try {
347119
+ await previousRecordingService.deleteCurrentSessionIfNotResumableAsync?.();
347120
+ } catch {
347121
+ }
347122
+ }
347123
+ }
346771
347124
  this.chat = await this.startChat(history, resumedSessionData);
346772
347125
  this.updateTelemetryTokenCount();
346773
347126
  }
@@ -347612,13 +347965,16 @@ var ToolExecutor = class {
347612
347965
  const originalContentLength = content.length;
347613
347966
  const { outputFile: savedPath } = await saveTruncatedToolOutput(content, toolName, callId, this.config.storage.getProjectTempDir(), this.context.promptId);
347614
347967
  outputFile = savedPath;
347615
- const truncatedContent = formatTruncatedToolOutput(content, outputFile, threshold);
347968
+ let truncatedContent = formatTruncatedToolOutput(content, outputFile, threshold);
347616
347969
  logToolOutputTruncated(this.config, new ToolOutputTruncatedEvent(call.request.prompt_id, {
347617
347970
  toolName,
347618
347971
  originalContentLength,
347619
347972
  truncatedContentLength: truncatedContent.length,
347620
347973
  threshold
347621
347974
  }));
347975
+ if (typeof truncatedContent === "string" && Buffer.byteLength(truncatedContent, "utf8") > MAX_STORED_TOOL_OUTPUT_BYTES) {
347976
+ truncatedContent = truncateToolOutput(truncatedContent, MAX_STORED_TOOL_OUTPUT_BYTES);
347977
+ }
347622
347978
  return { truncatedContent, outputFile };
347623
347979
  }
347624
347980
  } else if (Array.isArray(content) && content.length === 1 && "tool" in call && call.tool instanceof DiscoveredMCPTool) {
@@ -347630,7 +347986,10 @@ var ToolExecutor = class {
347630
347986
  const originalContentLength = textContent2.length;
347631
347987
  const { outputFile: savedPath } = await saveTruncatedToolOutput(textContent2, toolName, callId, this.config.storage.getProjectTempDir(), this.context.promptId);
347632
347988
  outputFile = savedPath;
347633
- const truncatedText = formatTruncatedToolOutput(textContent2, outputFile, threshold);
347989
+ let truncatedText = formatTruncatedToolOutput(textContent2, outputFile, threshold);
347990
+ if (typeof truncatedText === "string" && Buffer.byteLength(truncatedText, "utf8") > MAX_STORED_TOOL_OUTPUT_BYTES) {
347991
+ truncatedText = truncateToolOutput(truncatedText, MAX_STORED_TOOL_OUTPUT_BYTES);
347992
+ }
347634
347993
  const truncatedContent = [
347635
347994
  { ...firstPart, text: truncatedText }
347636
347995
  ];
@@ -347644,7 +348003,45 @@ var ToolExecutor = class {
347644
348003
  }
347645
348004
  }
347646
348005
  }
347647
- return { truncatedContent: content, outputFile };
348006
+ const ensureOutputFile = async (rawText) => {
348007
+ if (!outputFile) {
348008
+ try {
348009
+ const { outputFile: savedPath } = await saveTruncatedToolOutput(rawText, toolName, callId, this.config.storage.getProjectTempDir(), this.context.promptId);
348010
+ outputFile = savedPath;
348011
+ } catch {
348012
+ }
348013
+ }
348014
+ return outputFile;
348015
+ };
348016
+ let finalContent = content;
348017
+ if (typeof finalContent === "string") {
348018
+ if (Buffer.byteLength(finalContent, "utf8") > MAX_STORED_TOOL_OUTPUT_BYTES) {
348019
+ const savedPath = await ensureOutputFile(finalContent);
348020
+ finalContent = truncateToolOutput(finalContent, MAX_STORED_TOOL_OUTPUT_BYTES, savedPath);
348021
+ }
348022
+ } else if (Array.isArray(finalContent)) {
348023
+ finalContent = await Promise.all(finalContent.map(async (part) => {
348024
+ if (typeof part === "string" && Buffer.byteLength(part, "utf8") > MAX_STORED_TOOL_OUTPUT_BYTES) {
348025
+ const savedPath = await ensureOutputFile(part);
348026
+ return truncateToolOutput(part, MAX_STORED_TOOL_OUTPUT_BYTES, savedPath);
348027
+ }
348028
+ if (typeof part === "object" && part !== null && "text" in part && typeof part.text === "string" && Buffer.byteLength(part.text, "utf8") > MAX_STORED_TOOL_OUTPUT_BYTES) {
348029
+ const savedPath = await ensureOutputFile(part.text);
348030
+ return {
348031
+ ...part,
348032
+ text: truncateToolOutput(part.text, MAX_STORED_TOOL_OUTPUT_BYTES, savedPath)
348033
+ };
348034
+ }
348035
+ return part;
348036
+ }));
348037
+ } else if (typeof finalContent === "object" && finalContent !== null && "text" in finalContent && typeof finalContent.text === "string" && Buffer.byteLength(finalContent.text, "utf8") > MAX_STORED_TOOL_OUTPUT_BYTES) {
348038
+ const savedPath = await ensureOutputFile(finalContent.text);
348039
+ finalContent = {
348040
+ ...finalContent,
348041
+ text: truncateToolOutput(finalContent.text, MAX_STORED_TOOL_OUTPUT_BYTES, savedPath)
348042
+ };
348043
+ }
348044
+ return { truncatedContent: finalContent, outputFile };
347648
348045
  }
347649
348046
  async createCancelledResult(call, reason, toolResult) {
347650
348047
  const errorMessage = `[Operation Cancelled] ${reason}`;
@@ -347813,6 +348210,9 @@ var ToolModificationHandler = class {
347813
348210
  };
347814
348211
 
347815
348212
  // packages/core/dist/src/scheduler/scheduler.js
348213
+ function isTaintRiskDetectable(invocation) {
348214
+ return typeof invocation === "object" && invocation !== null && "hasTaintedOrBuildFileRisk" in invocation && typeof invocation.hasTaintedOrBuildFileRisk === "function";
348215
+ }
347816
348216
  var createErrorResponse = (request, error40, errorType) => ({
347817
348217
  callId: request.callId,
347818
348218
  error: error40,
@@ -348172,6 +348572,10 @@ var Scheduler = class {
348172
348572
  if (hookDecision === "ask") {
348173
348573
  decision = PolicyDecision.ASK_USER;
348174
348574
  }
348575
+ const hasTaintRisk = isTaintRiskDetectable(toolCall.invocation) && toolCall.invocation.hasTaintedOrBuildFileRisk();
348576
+ if (decision === PolicyDecision.ALLOW && hasTaintRisk) {
348577
+ decision = this.config.isInteractive?.() ?? true ? PolicyDecision.ASK_USER : PolicyDecision.DENY;
348578
+ }
348175
348579
  if (decision === PolicyDecision.DENY) {
348176
348580
  const { errorMessage, errorType } = getPolicyDenialError(this.config, rule);
348177
348581
  this.state.updateStatus(callId, CoreToolCallStatus.Error, createErrorResponse(toolCall.request, new Error(errorMessage), errorType));
@@ -348180,6 +348584,7 @@ var Scheduler = class {
348180
348584
  let outcome = ToolConfirmationOutcome.ProceedOnce;
348181
348585
  let lastDetails;
348182
348586
  if (decision === PolicyDecision.ASK_USER) {
348587
+ const forcedDecision = hookDecision === "ask" || policyDecision === PolicyDecision.ALLOW && hasTaintRisk ? "ask_user" : void 0;
348183
348588
  const result2 = await resolveConfirmation(toolCall, signal, {
348184
348589
  config: this.config,
348185
348590
  messageBus: this.messageBus,
@@ -348189,7 +348594,7 @@ var Scheduler = class {
348189
348594
  schedulerId: this.schedulerId,
348190
348595
  onWaitingForConfirmation: this.onWaitingForConfirmation,
348191
348596
  systemMessage: hookSystemMessage,
348192
- forcedDecision: hookDecision === "ask" ? "ask_user" : void 0
348597
+ forcedDecision
348193
348598
  });
348194
348599
  outcome = result2.outcome;
348195
348600
  lastDetails = result2.lastDetails;
@@ -348460,14 +348865,14 @@ function normalizeSpace(text) {
348460
348865
  return text.replace(/\s+/g, " ").trim();
348461
348866
  }
348462
348867
  function safeSlice(text, start2, end) {
348463
- const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
348464
- const segments = Array.from(segmenter.segment(text));
348868
+ const segmenter2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
348869
+ const segments = Array.from(segmenter2.segment(text));
348465
348870
  return segments.slice(start2, end).map((s2) => s2.segment).join("");
348466
348871
  }
348467
348872
  function safeLength(text) {
348468
- const segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
348873
+ const segmenter2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
348469
348874
  let count2 = 0;
348470
- for (const _ of segmenter.segment(text)) {
348875
+ for (const _ of segmenter2.segment(text)) {
348471
348876
  count2++;
348472
348877
  }
348473
348878
  return count2;
@@ -349592,13 +349997,30 @@ var LocalAgentExecutor = class _LocalAgentExecutor {
349592
349997
  }
349593
349998
  async tryCompressChat(chat, prompt_id, abortSignal) {
349594
349999
  const model = this.definition.modelConfig.model ?? DEFAULT_GEMINI_MODEL;
350000
+ const threshold = await this.context.config.getCompressionThreshold() ?? DEFAULT_COMPRESSION_TOKEN_THRESHOLD;
350001
+ const modelLimit = tokenLimit(model);
350002
+ const lastPromptTokenCount = chat.getLastPromptTokenCount();
350003
+ const currentHistory = chat.getHistory(false);
350004
+ const originalTokenCount = lastPromptTokenCount > 0 ? lastPromptTokenCount : estimateTokenCountSync(currentHistory.flatMap((c4) => c4.parts || []));
350005
+ if (originalTokenCount >= threshold * modelLimit) {
350006
+ const collapsedHistory = collapseOlderFunctionResponses(currentHistory);
350007
+ if (collapsedHistory !== currentHistory) {
350008
+ const existingTurns = chat.getHistoryTurns?.(false) ?? [];
350009
+ const turns = collapsedHistory.map((c4, idx) => ({
350010
+ id: existingTurns[idx]?.id ?? randomUUID13(),
350011
+ content: c4
350012
+ }));
350013
+ chat.setHistory(turns);
350014
+ }
350015
+ }
349595
350016
  const { newHistory, info: info2 } = await this.compressionService.compress(chat, prompt_id, false, model, this.context.config, this.hasFailedCompressionAttempt, abortSignal);
349596
350017
  if (info2.compressionStatus === CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT) {
349597
350018
  this.hasFailedCompressionAttempt = true;
349598
350019
  } else if (info2.compressionStatus === CompressionStatus.COMPRESSED) {
349599
350020
  if (newHistory) {
349600
- const turns = newHistory.map((c4) => ({
349601
- id: randomUUID13(),
350021
+ const existingTurns = chat.getHistoryTurns?.(false) ?? [];
350022
+ const turns = newHistory.map((c4, idx) => ({
350023
+ id: existingTurns[idx]?.id ?? randomUUID13(),
349602
350024
  content: c4
349603
350025
  }));
349604
350026
  chat.setHistory(turns);
@@ -349606,8 +350028,9 @@ var LocalAgentExecutor = class _LocalAgentExecutor {
349606
350028
  }
349607
350029
  } else if (info2.compressionStatus === CompressionStatus.CONTENT_TRUNCATED) {
349608
350030
  if (newHistory) {
349609
- const turns = newHistory.map((c4) => ({
349610
- id: randomUUID13(),
350031
+ const existingTurns = chat.getHistoryTurns?.(false) ?? [];
350032
+ const turns = newHistory.map((c4, idx) => ({
350033
+ id: existingTurns[idx]?.id ?? randomUUID13(),
349611
350034
  content: c4
349612
350035
  }));
349613
350036
  chat.setHistory(turns);
@@ -349790,6 +350213,15 @@ var LocalAgentExecutor = class _LocalAgentExecutor {
349790
350213
  signal,
349791
350214
  onWaitingForConfirmation
349792
350215
  });
350216
+ for (const call of completedCalls) {
350217
+ const outputFile = call.response?.outputFile;
350218
+ if (call.response?.responseParts) {
350219
+ call.response.responseParts = call.response.responseParts.map((p) => truncateFunctionResponsePart(p, MAX_STORED_TOOL_OUTPUT_BYTES, outputFile));
350220
+ }
350221
+ if (typeof call.response?.resultDisplay === "string" && Buffer.byteLength(call.response.resultDisplay, "utf8") > MAX_STORED_TOOL_OUTPUT_BYTES) {
350222
+ call.response.resultDisplay = truncateToolOutput(call.response.resultDisplay, MAX_STORED_TOOL_OUTPUT_BYTES, outputFile);
350223
+ }
350224
+ }
349793
350225
  chat.recordCompletedToolCalls(model, completedCalls);
349794
350226
  for (const call of completedCalls) {
349795
350227
  const toolName = toolNameMap.get(call.request.callId) || call.request.name;
@@ -349855,7 +350287,7 @@ var LocalAgentExecutor = class _LocalAgentExecutor {
349855
350287
  const callId = functionCall.id ?? `${promptId}-${index}`;
349856
350288
  const part = syncResults.get(callId);
349857
350289
  if (part) {
349858
- toolResponseParts.push(part);
350290
+ toolResponseParts.push(truncateFunctionResponsePart(part, MAX_STORED_TOOL_OUTPUT_BYTES));
349859
350291
  continue;
349860
350292
  }
349861
350293
  const isAborted2 = signal.aborted;
@@ -362802,11 +363234,14 @@ var PolicyEngine = class {
362802
363234
  isAlwaysAllowRule(rule) {
362803
363235
  return rule.priority !== void 0 && Math.round(rule.priority % 1 * 1e3) === ALWAYS_ALLOW_PRIORITY_FRACTION;
362804
363236
  }
362805
- shouldDowngradeForRedirection(command, allowRedirection) {
363237
+ shouldDowngradeForRedirection(command, allowRedirection, rule) {
362806
363238
  if (allowRedirection)
362807
363239
  return false;
362808
363240
  if (!hasRedirection(command))
362809
363241
  return false;
363242
+ if (rule?.argsPattern && !allowRedirection) {
363243
+ return true;
363244
+ }
362810
363245
  if (this.approvalMode === ApprovalMode.AUTO_EDIT || this.approvalMode === ApprovalMode.YOLO) {
362811
363246
  return false;
362812
363247
  }
@@ -362893,7 +363328,7 @@ var PolicyEngine = class {
362893
363328
  }
362894
363329
  let aggregateDecision = ruleDecision;
362895
363330
  let responsibleRule = rule && ruleDecision === rule.decision ? rule : void 0;
362896
- if (this.shouldDowngradeForRedirection(command, allowRedirection)) {
363331
+ if (this.shouldDowngradeForRedirection(command, allowRedirection, rule)) {
362897
363332
  if (aggregateDecision === PolicyDecision.ALLOW) {
362898
363333
  debugLogger.debug(`[PolicyEngine.check] Downgrading ALLOW to ASK_USER for redirected command: ${command}`);
362899
363334
  aggregateDecision = PolicyDecision.ASK_USER;
@@ -362932,7 +363367,7 @@ var PolicyEngine = class {
362932
363367
  }
362933
363368
  aggregateDecision = PolicyDecision.ASK_USER;
362934
363369
  }
362935
- if (subResult.decision === PolicyDecision.ALLOW && this.shouldDowngradeForRedirection(subCmd, allowRedirection)) {
363370
+ if (subResult.decision === PolicyDecision.ALLOW && this.shouldDowngradeForRedirection(subCmd, subResult.rule?.allowRedirection ?? allowRedirection, subResult.rule)) {
362936
363371
  if (aggregateDecision === PolicyDecision.ALLOW) {
362937
363372
  aggregateDecision = PolicyDecision.ASK_USER;
362938
363373
  responsibleRule = void 0;
@@ -363116,6 +363551,9 @@ var PolicyEngine = class {
363116
363551
  }
363117
363552
  }
363118
363553
  }
363554
+ if (this.nonInteractive && decision === PolicyDecision.ASK_USER) {
363555
+ decision = PolicyDecision.DENY;
363556
+ }
363119
363557
  return {
363120
363558
  decision,
363121
363559
  rule: matchedRule
@@ -365811,7 +366249,7 @@ var SecurityValidator = class {
365811
366249
  };
365812
366250
  function getWindowsPowerShellPath() {
365813
366251
  let systemRoot = process.env["SystemRoot"] || process.env["systemroot"] || process.env["windir"] || process.env["WINDIR"] || "C:\\Windows";
365814
- if (!/^[a-zA-Z]:\\/.test(systemRoot)) {
366252
+ if (!/^[a-zA-Z]:\\Windows\\?$/i.test(systemRoot) || systemRoot.includes("..")) {
365815
366253
  systemRoot = "C:\\Windows";
365816
366254
  }
365817
366255
  const pathModule = os33.platform() === "win32" ? path87.win32 : path87.posix;
@@ -367032,7 +367470,8 @@ import * as fs77 from "node:fs";
367032
367470
 
367033
367471
  // packages/core/dist/src/safety/built-in.js
367034
367472
  import * as path89 from "node:path";
367035
- var VSCODE_SFN_REGEX = /^(vscode|vs[0-9a-f]{4})~\d+$/;
367473
+ var VSCODE_SFN_REGEX = /^(vscode|vs[0-9a-f]{4})~\d+(\..+)?$/i;
367474
+ var GEMINI_SFN_REGEX = /^(gemini|ge[0-9a-f]{4})~\d+(\..+)?$/i;
367036
367475
  var AllowedPathChecker = class {
367037
367476
  async check(input) {
367038
367477
  const { toolCall, context: context2 } = input;
@@ -367055,6 +367494,7 @@ var AllowedPathChecker = class {
367055
367494
  }
367056
367495
  let hasBlockedSegment = false;
367057
367496
  let isVscodePath = false;
367497
+ let isGeminiPath = false;
367058
367498
  for (const resolvedDir of resolvedAllowedDirs) {
367059
367499
  if (!this.isPathAllowed(resolvedPath, resolvedDir))
367060
367500
  continue;
@@ -367068,6 +367508,9 @@ var AllowedPathChecker = class {
367068
367508
  if (clean === ".vscode" || VSCODE_SFN_REGEX.test(clean)) {
367069
367509
  isVscodePath = true;
367070
367510
  }
367511
+ if (clean === ".gemini" || GEMINI_SFN_REGEX.test(clean)) {
367512
+ isGeminiPath = true;
367513
+ }
367071
367514
  }
367072
367515
  }
367073
367516
  if (hasBlockedSegment) {
@@ -367076,6 +367519,12 @@ var AllowedPathChecker = class {
367076
367519
  reason: `Access to sensitive path "${p}" in argument "${argName}" is blocked.`
367077
367520
  };
367078
367521
  }
367522
+ if (isGeminiPath) {
367523
+ return {
367524
+ decision: SafetyCheckDecision.ASK_USER,
367525
+ reason: `Modifying .gemini configuration files requires explicit user confirmation.`
367526
+ };
367527
+ }
367079
367528
  if (isVscodePath) {
367080
367529
  return {
367081
367530
  decision: SafetyCheckDecision.ASK_USER,
@@ -390275,7 +390724,7 @@ var LegacyAgentSession = class extends AgentSession {
390275
390724
  };
390276
390725
 
390277
390726
  // packages/core/dist/src/tools/read-many-files.js
390278
- import * as fsPromises11 from "node:fs/promises";
390727
+ import * as fsPromises12 from "node:fs/promises";
390279
390728
  import * as path107 from "node:path";
390280
390729
  function getDefaultExcludes(config2) {
390281
390730
  return config2?.getFileExclusions().getReadManyFilesExcludes() ?? [];
@@ -390324,7 +390773,7 @@ ${finalExclusionPatternsForDescription.slice(0, 2).join("`, `")}${finalExclusion
390324
390773
  const fullPath = path107.join(dir, normalizedP);
390325
390774
  let exists2 = false;
390326
390775
  try {
390327
- const st = await fsPromises11.stat(fullPath);
390776
+ const st = await fsPromises12.stat(fullPath);
390328
390777
  exists2 = st.isFile();
390329
390778
  } catch {
390330
390779
  exists2 = false;
@@ -398322,6 +398771,7 @@ export {
398322
398771
  DEFAULT_MAX_LINES_TEXT_FILE,
398323
398772
  MAX_LINE_LENGTH_TEXT_FILE,
398324
398773
  MAX_FILE_SIZE_MB,
398774
+ MAX_STORED_TOOL_OUTPUT_BYTES,
398325
398775
  EMPTY_RESPONSE_COMPRESS_SUGGESTION,
398326
398776
  THINKING_ONLY_COMPRESS_SUGGESTION,
398327
398777
  MAX_TOKENS_EXCEEDED_SUGGESTION,
@@ -398333,6 +398783,7 @@ export {
398333
398783
  loadWasmBinary,
398334
398784
  DEFAULT_ENCODING,
398335
398785
  detectBOM,
398786
+ readSecureFileBuffer,
398336
398787
  readFileWithEncoding,
398337
398788
  getSpecificMimeType,
398338
398789
  canonicalizeMacosPath,
@@ -399095,6 +399546,11 @@ export {
399095
399546
  SessionStartSource,
399096
399547
  SessionEndReason,
399097
399548
  PreCompressTrigger,
399549
+ isToolCallResponseInfo,
399550
+ getToolSuggestion,
399551
+ doesToolInvocationMatch,
399552
+ truncateToolOutput,
399553
+ truncateFunctionResponsePart,
399098
399554
  AgentTerminateMode,
399099
399555
  DEFAULT_QUERY_STRING,
399100
399556
  DEFAULT_MAX_TURNS,
@@ -399129,9 +399585,6 @@ export {
399129
399585
  exchangeCodeForToken,
399130
399586
  refreshAccessToken,
399131
399587
  ModelConfigService,
399132
- isToolCallResponseInfo,
399133
- getToolSuggestion,
399134
- doesToolInvocationMatch,
399135
399588
  getPolicyDenialError,
399136
399589
  checkPolicy,
399137
399590
  updatePolicy,
@@ -399241,6 +399694,7 @@ export {
399241
399694
  createPathSecurityCache,
399242
399695
  clearSecurityCacheForTesting,
399243
399696
  SecurityValidator,
399697
+ getWindowsPowerShellPath,
399244
399698
  isDirectorySecure,
399245
399699
  normalizeSecurityPath,
399246
399700
  isPathSecureSync,