@google/gemini-cli 0.41.0-preview.1 → 0.42.0-nightly.20260501.gcaa046641

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 (93) hide show
  1. package/bundle/{chunk-36LZQV4W.js → chunk-2HOG45IA.js} +1047 -1240
  2. package/bundle/{chunk-NGB7ZVQL.js → chunk-2WK6K7H4.js} +67 -507
  3. package/bundle/{chunk-DOHALVIP.js → chunk-3Y7ZPPS2.js} +1047 -1240
  4. package/bundle/chunk-4SBF4FWA.js +512 -0
  5. package/bundle/{chunk-XRLFHCHC.js → chunk-533APETE.js} +30 -12
  6. package/bundle/{chunk-T5I4M6M4.js → chunk-747IFMEA.js} +3 -3
  7. package/bundle/chunk-CTSXRP2T.js +512 -0
  8. package/bundle/{chunk-DCHOW6BK.js → chunk-CVJABGPV.js} +2 -2
  9. package/bundle/{chunk-VWYB6GSK.js → chunk-DDX3KSOF.js} +67 -507
  10. package/bundle/{chunk-DAEE6Y5T.js → chunk-EGV36KAI.js} +1047 -1240
  11. package/bundle/chunk-ESRGVL52.js +512 -0
  12. package/bundle/{chunk-SAJ72M2G.js → chunk-FABHOVMY.js} +23 -7
  13. package/bundle/chunk-FNLKMX3W.js +391 -0
  14. package/bundle/chunk-FTIY7CSS.js +391 -0
  15. package/bundle/{chunk-C5CRFFTY.js → chunk-GXIITUGM.js} +1 -1
  16. package/bundle/{chunk-45OGXTFK.js → chunk-HIYYW6PF.js} +3 -3
  17. package/bundle/chunk-IDYSRNE5.js +511 -0
  18. package/bundle/{chunk-QRSHDIRX.js → chunk-IJA7QQHF.js} +1 -1
  19. package/bundle/{chunk-U6WUS35U.js → chunk-ILECTCCH.js} +2 -2
  20. package/bundle/{chunk-R4LSW45D.js → chunk-J44J2AAV.js} +1 -1
  21. package/bundle/{chunk-KCDF3RDO.js → chunk-JPGLBVDA.js} +3 -3
  22. package/bundle/{chunk-VJ6K3S57.js → chunk-K5CA5JX2.js} +2 -2
  23. package/bundle/{chunk-6NFVEILC.js → chunk-L6URBAMF.js} +262 -81
  24. package/bundle/{chunk-5Z2T77EB.js → chunk-NNAHWZGK.js} +66 -507
  25. package/bundle/{chunk-KJ4M7JXR.js → chunk-SFDJ7FIE.js} +2 -2
  26. package/bundle/{chunk-QY23ZEK3.js → chunk-SYZNFSS3.js} +262 -81
  27. package/bundle/chunk-TBIPLAJP.js +391 -0
  28. package/bundle/{chunk-FFVUMIL3.js → chunk-TMQACI5N.js} +1047 -1240
  29. package/bundle/{chunk-XO6NKGWV.js → chunk-UCTXAZT6.js} +262 -81
  30. package/bundle/{chunk-VLSVN2FJ.js → chunk-USFRINC4.js} +1 -1
  31. package/bundle/chunk-VJOUKBFO.js +391 -0
  32. package/bundle/{chunk-EQSLZT5Z.js → chunk-VUMF52YD.js} +271 -81
  33. package/bundle/{chunk-5QI3ZXQB.js → chunk-WGWUS5AF.js} +67 -507
  34. package/bundle/{chunk-TBBDQEFQ.js → chunk-WTLXL6OZ.js} +3 -3
  35. package/bundle/{cleanup-3COTQVPP.js → cleanup-GQXJGC2H.js} +3 -3
  36. package/bundle/{cleanup-FIE6MCAE.js → cleanup-OSSEOJVY.js} +3 -3
  37. package/bundle/{cleanup-PREOBLFK.js → cleanup-TDBASRR5.js} +3 -3
  38. package/bundle/{cleanup-YY2EUT56.js → cleanup-XLWNSNLT.js} +3 -3
  39. package/bundle/{core-GZOFEER4.js → core-JH4LXS4F.js} +8 -2
  40. package/bundle/{devtoolsService-QXOHXSMJ.js → devtoolsService-DFWZ34A5.js} +3 -3
  41. package/bundle/{devtoolsService-DV36S632.js → devtoolsService-KZLK5WRW.js} +3 -3
  42. package/bundle/{devtoolsService-JPBL5I7F.js → devtoolsService-XIWMIEMB.js} +3 -3
  43. package/bundle/{devtoolsService-M4LZEBZD.js → devtoolsService-ZV5MJUBY.js} +3 -3
  44. package/bundle/{dist-HASTHPE3.js → dist-ATBEVH4R.js} +8 -2
  45. package/bundle/{dist-JVRDP7SO.js → dist-BOCIGIGG.js} +8 -2
  46. package/bundle/{dist-NSJ6AA4L.js → dist-TDGPCKNF.js} +8 -2
  47. package/bundle/docs/changelogs/index.md +18 -0
  48. package/bundle/docs/changelogs/latest.md +167 -242
  49. package/bundle/docs/changelogs/preview.md +99 -385
  50. package/bundle/docs/cli/cli-reference.md +1 -0
  51. package/bundle/docs/cli/creating-skills.md +165 -38
  52. package/bundle/docs/cli/custom-commands.md +1 -0
  53. package/bundle/docs/cli/model-routing.md +3 -3
  54. package/bundle/docs/cli/plan-mode.md +2 -1
  55. package/bundle/docs/cli/skills-best-practices.md +78 -0
  56. package/bundle/docs/cli/skills.md +98 -93
  57. package/bundle/docs/cli/tutorials/session-management.md +13 -0
  58. package/bundle/docs/cli/tutorials/skills-getting-started.md +140 -92
  59. package/bundle/docs/cli/using-agent-skills.md +89 -0
  60. package/bundle/docs/core/gemma-setup.md +83 -0
  61. package/bundle/docs/core/index.md +3 -2
  62. package/bundle/docs/core/local-model-routing.md +14 -7
  63. package/bundle/docs/reference/commands.md +14 -4
  64. package/bundle/docs/reference/configuration.md +76 -4
  65. package/bundle/docs/reference/keyboard-shortcuts.md +1 -1
  66. package/bundle/docs/reference/policy-engine.md +14 -3
  67. package/bundle/docs/sidebar.json +24 -2
  68. package/bundle/docs/tools/activate-skill.md +1 -1
  69. package/bundle/{gemini-IGRTXHCM.js → gemini-ETBA6M7V.js} +1067 -850
  70. package/bundle/{gemini-KIM7O55W.js → gemini-FUGMMZB7.js} +1067 -850
  71. package/bundle/{gemini-SFFHSCEY.js → gemini-QDNEMFTK.js} +1067 -850
  72. package/bundle/{gemini-FTUVOUHP.js → gemini-TZ26TZKD.js} +1067 -848
  73. package/bundle/gemini.js +20 -13
  74. package/bundle/{interactiveCli-LTPR447O.js → interactiveCli-74QXEIGP.js} +682 -609
  75. package/bundle/{interactiveCli-K4FIT7TA.js → interactiveCli-IBVICRF7.js} +682 -609
  76. package/bundle/{interactiveCli-7HPLINVC.js → interactiveCli-OKS4NPC7.js} +682 -609
  77. package/bundle/{interactiveCli-JOX7MFFH.js → interactiveCli-ZS4ZQWNV.js} +682 -609
  78. package/bundle/{liteRtServerManager-BENLLSF2.js → liteRtServerManager-I5CSGWRL.js} +5 -4
  79. package/bundle/{liteRtServerManager-KDO6UAQ5.js → liteRtServerManager-IDNLXYHP.js} +5 -4
  80. package/bundle/{liteRtServerManager-MQIQXXZQ.js → liteRtServerManager-J33F7APP.js} +5 -4
  81. package/bundle/{liteRtServerManager-VGYEHFUE.js → liteRtServerManager-RJF74BUI.js} +5 -4
  82. package/bundle/{memoryDiscovery-FN3IAPBT.js → memoryDiscovery-LIJKMASE.js} +1 -1
  83. package/bundle/{memoryDiscovery-R7PAR2NY.js → memoryDiscovery-WVH7QDNJ.js} +1 -1
  84. package/bundle/node_modules/@google/gemini-cli-devtools/package.json +1 -1
  85. package/bundle/{oauth2-provider-JPCBTTS2.js → oauth2-provider-7UM3XCQ4.js} +2 -2
  86. package/bundle/{oauth2-provider-EWMNT6D6.js → oauth2-provider-BFW5HE2U.js} +2 -2
  87. package/bundle/{oauth2-provider-M3WV4GJM.js → oauth2-provider-LONBXYVY.js} +2 -2
  88. package/bundle/{oauth2-provider-UVXCM7G3.js → oauth2-provider-N65VILW5.js} +2 -2
  89. package/bundle/{start-4MSISK2E.js → start-3B4FNGNM.js} +7 -6
  90. package/bundle/{start-ATOE57Z4.js → start-3OM5OXD2.js} +7 -6
  91. package/bundle/{start-AVEON6UU.js → start-N3S3BSEF.js} +7 -6
  92. package/bundle/{start-KBB2UTE5.js → start-PLPHF43U.js} +7 -6
  93. package/package.json +1 -1
@@ -9,7 +9,6 @@ import {
9
9
  INSTALL_WARNING_MESSAGE,
10
10
  McpPromptLoader,
11
11
  McpServerEnablementManager,
12
- RELAUNCH_EXIT_CODE,
13
12
  canLoadServer,
14
13
  checkForAllExtensionUpdates,
15
14
  checkForExtensionUpdate,
@@ -42,18 +41,18 @@ import {
42
41
  updateAllUpdatableExtensions,
43
42
  updateExtension,
44
43
  validateAuthMethod
45
- } from "./chunk-DOHALVIP.js";
44
+ } from "./chunk-3Y7ZPPS2.js";
46
45
  import {
47
46
  appEvents
48
47
  } from "./chunk-5PS3AYFU.js";
49
48
  import {
50
49
  startCommand,
51
50
  startServer
52
- } from "./chunk-TBBDQEFQ.js";
51
+ } from "./chunk-WTLXL6OZ.js";
53
52
  import {
54
53
  exitCli,
55
54
  require_source
56
- } from "./chunk-VLSVN2FJ.js";
55
+ } from "./chunk-GXIITUGM.js";
57
56
  import {
58
57
  DEFAULT_PORT,
59
58
  GEMMA_MODEL_NAME,
@@ -87,7 +86,11 @@ import {
87
86
  readServerProcessInfo,
88
87
  resolveGemmaConfig,
89
88
  saveModelChange
90
- } from "./chunk-5Z2T77EB.js";
89
+ } from "./chunk-NNAHWZGK.js";
90
+ import {
91
+ RELAUNCH_EXIT_CODE
92
+ } from "./chunk-FNLKMX3W.js";
93
+ import "./chunk-IDYSRNE5.js";
91
94
  import {
92
95
  cleanupCheckpoints,
93
96
  registerCleanup,
@@ -96,7 +99,7 @@ import {
96
99
  runExitCleanup,
97
100
  runSyncCleanup,
98
101
  setupSignalHandlers
99
- } from "./chunk-DCHOW6BK.js";
102
+ } from "./chunk-SFDJ7FIE.js";
100
103
  import {
101
104
  AuthType,
102
105
  ChatRecordingService,
@@ -116,6 +119,7 @@ import {
116
119
  ReadManyFilesTool,
117
120
  Scheduler,
118
121
  ShellExecutionService,
122
+ SimpleExtensionLoader,
119
123
  StreamJsonFormatter,
120
124
  ToolCallEvent,
121
125
  UserAccountManager,
@@ -155,6 +159,7 @@ import {
155
159
  getVersion,
156
160
  isGeminiWorktree,
157
161
  isHeadlessMode,
162
+ isTextPart,
158
163
  isWithinRoot,
159
164
  listExtensions,
160
165
  listInboxPatches,
@@ -183,7 +188,7 @@ import {
183
188
  updatePolicy,
184
189
  writeToStderr,
185
190
  writeToStdout
186
- } from "./chunk-EQSLZT5Z.js";
191
+ } from "./chunk-VUMF52YD.js";
187
192
  import {
188
193
  ASK_USER_TOOL_NAME,
189
194
  DEFAULT_FILE_FILTERING_OPTIONS,
@@ -227,7 +232,7 @@ import {
227
232
  loadServerHierarchicalMemory,
228
233
  resolveToRealPath,
229
234
  setGeminiMdFilename
230
- } from "./chunk-XRLFHCHC.js";
235
+ } from "./chunk-533APETE.js";
231
236
  import "./chunk-664ZODQF.js";
232
237
  import "./chunk-RJTRUG2J.js";
233
238
  import "./chunk-IUUIT4SU.js";
@@ -7806,7 +7811,7 @@ async function loadSandboxConfig(settings, argv) {
7806
7811
  }
7807
7812
  const command2 = getSandboxCommand(sandboxValue);
7808
7813
  const packageJson = await getPackageJson(__dirname3);
7809
- const image = process.env["GEMINI_SANDBOX_IMAGE"] ?? "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.41.0-preview.0" ?? customImage ?? packageJson?.config?.sandboxImageUri;
7814
+ const image = process.env["GEMINI_SANDBOX_IMAGE"] ?? "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.42.0-nightly.20260428.g59b2dea0e" ?? customImage ?? packageJson?.config?.sandboxImageUri;
7810
7815
  const isNative = command2 === "windows-native" || command2 === "sandbox-exec" || command2 === "lxc";
7811
7816
  return command2 && (image || isNative) ? { enabled: true, allowedPaths, networkAccess, command: command2, image } : void 0;
7812
7817
  }
@@ -8208,7 +8213,7 @@ function isDebugMode(argv) {
8208
8213
  );
8209
8214
  }
8210
8215
  async function loadCliConfig(settings, sessionId, argv, options = {}) {
8211
- const { cwd = process3.cwd(), projectHooks } = options;
8216
+ const { cwd = process3.cwd(), projectHooks, skipExtensions = false } = options;
8212
8217
  const debugMode = isDebugMode(argv);
8213
8218
  const worktreeSettings = options.worktreeSettings ?? await resolveWorktreeSettings(cwd);
8214
8219
  if (argv.sandbox) {
@@ -8254,18 +8259,21 @@ async function loadCliConfig(settings, sessionId, argv, options = {}) {
8254
8259
  });
8255
8260
  includeDirectories.push(...ideFolders);
8256
8261
  }
8257
- const extensionManager = new ExtensionManager({
8258
- settings,
8259
- requestConsent: requestConsentNonInteractive,
8260
- requestSetting: promptForSetting,
8261
- workspaceDir: cwd,
8262
- enabledExtensionOverrides: argv.extensions,
8263
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
8264
- eventEmitter: coreEvents,
8265
- clientVersion: await getVersion()
8266
- });
8267
- await extensionManager.loadExtensions();
8268
- const extensionPlanSettings = extensionManager.getExtensions().find((ext) => ext.isActive && ext.plan?.directory)?.plan;
8262
+ let extensionManager;
8263
+ if (!skipExtensions) {
8264
+ extensionManager = new ExtensionManager({
8265
+ settings,
8266
+ requestConsent: requestConsentNonInteractive,
8267
+ requestSetting: promptForSetting,
8268
+ workspaceDir: cwd,
8269
+ enabledExtensionOverrides: argv.extensions,
8270
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
8271
+ eventEmitter: coreEvents,
8272
+ clientVersion: await getVersion()
8273
+ });
8274
+ await extensionManager.loadExtensions();
8275
+ }
8276
+ const extensionPlanSettings = extensionManager?.getExtensions()?.find((ext) => ext.isActive && ext.plan?.directory)?.plan;
8269
8277
  const experimentalJitContext = settings.experimental.jitContext ?? true;
8270
8278
  let extensionRegistryURI = process3.env["GEMINI_CLI_EXTENSION_REGISTRY_URI"] ?? (trustedFolder ? settings.experimental?.extensionRegistryURI : void 0);
8271
8279
  if (extensionRegistryURI && !extensionRegistryURI.startsWith("http")) {
@@ -8276,12 +8284,13 @@ async function loadCliConfig(settings, sessionId, argv, options = {}) {
8276
8284
  let memoryContent = "";
8277
8285
  let fileCount = 0;
8278
8286
  let filePaths = [];
8287
+ const finalExtensionLoader = extensionManager ?? new SimpleExtensionLoader([]);
8279
8288
  if (!experimentalJitContext) {
8280
8289
  const result = await loadServerHierarchicalMemory(
8281
8290
  cwd,
8282
8291
  settings.context?.loadMemoryFromIncludeDirectories || false ? includeDirectories : [],
8283
8292
  fileService,
8284
- extensionManager,
8293
+ finalExtensionLoader,
8285
8294
  trustedFolder,
8286
8295
  memoryImportFormat,
8287
8296
  memoryFileFiltering,
@@ -8465,7 +8474,13 @@ async function loadCliConfig(settings, sessionId, argv, options = {}) {
8465
8474
  const ide = detectIdeFromEnv();
8466
8475
  if (ide && (ide.name !== "vscode" || process3.env["TERM_PROGRAM"] === "vscode")) {
8467
8476
  clientName = `acp-${ide.name}`;
8477
+ } else {
8478
+ clientName = "acp";
8468
8479
  }
8480
+ } else if (argv.isCommand) {
8481
+ clientName = "cli-command";
8482
+ } else {
8483
+ clientName = "tui";
8469
8484
  }
8470
8485
  let profileSelector = void 0;
8471
8486
  if (settings.experimental?.stressTestProfile) {
@@ -8539,7 +8554,7 @@ async function loadCliConfig(settings, sessionId, argv, options = {}) {
8539
8554
  listSessions: argv.listSessions || false,
8540
8555
  deleteSession: argv.deleteSession,
8541
8556
  enabledExtensions: argv.extensions,
8542
- extensionLoader: extensionManager,
8557
+ extensionLoader: finalExtensionLoader,
8543
8558
  extensionRegistryURI,
8544
8559
  enableExtensionReloading: settings.experimental?.extensionReloading,
8545
8560
  enableAgents: settings.experimental?.enableAgents,
@@ -8660,6 +8675,15 @@ async function resolveWorktreeSettings(cwd) {
8660
8675
  }
8661
8676
 
8662
8677
  // packages/cli/src/utils/readStdin.ts
8678
+ function truncateUtf8Bytes(str, maxBytes) {
8679
+ const buf = Buffer.from(str, "utf8");
8680
+ if (buf.length <= maxBytes) return str;
8681
+ let end = maxBytes;
8682
+ while (end > 0 && (buf[end] & 192) === 128) {
8683
+ end--;
8684
+ }
8685
+ return buf.subarray(0, end).toString("utf8");
8686
+ }
8663
8687
  async function readStdin() {
8664
8688
  const MAX_STDIN_SIZE = 8 * 1024 * 1024;
8665
8689
  return new Promise((resolve9, reject) => {
@@ -8677,9 +8701,10 @@ async function readStdin() {
8677
8701
  clearTimeout(pipedInputTimerId);
8678
8702
  pipedInputTimerId = null;
8679
8703
  }
8680
- if (totalSize + chunk.length > MAX_STDIN_SIZE) {
8681
- const remainingSize = MAX_STDIN_SIZE - totalSize;
8682
- data += chunk.slice(0, remainingSize);
8704
+ const chunkByteLength = Buffer.byteLength(chunk, "utf8");
8705
+ if (totalSize + chunkByteLength > MAX_STDIN_SIZE) {
8706
+ const remainingBytes = MAX_STDIN_SIZE - totalSize;
8707
+ data += truncateUtf8Bytes(chunk, remainingBytes);
8683
8708
  debugLogger.warn(
8684
8709
  `Warning: stdin input truncated to ${MAX_STDIN_SIZE} bytes.`
8685
8710
  );
@@ -8688,7 +8713,7 @@ async function readStdin() {
8688
8713
  break;
8689
8714
  }
8690
8715
  data += chunk;
8691
- totalSize += chunk.length;
8716
+ totalSize += chunkByteLength;
8692
8717
  }
8693
8718
  };
8694
8719
  const onEnd = () => {
@@ -10183,7 +10208,7 @@ async function runNonInteractive({
10183
10208
  }
10184
10209
  });
10185
10210
  if (process.env["GEMINI_CLI_ACTIVITY_LOG_TARGET"]) {
10186
- const { setupInitialActivityLogger } = await import("./devtoolsService-QXOHXSMJ.js");
10211
+ const { setupInitialActivityLogger } = await import("./devtoolsService-DFWZ34A5.js");
10187
10212
  setupInitialActivityLogger(config);
10188
10213
  }
10189
10214
  const { stdout: workingStdout } = createWorkingStdio();
@@ -10370,7 +10395,13 @@ async function runNonInteractive({
10370
10395
  const formatter = new JsonFormatter();
10371
10396
  const stats = uiTelemetryService.getMetrics();
10372
10397
  textOutput.write(
10373
- formatter.format(config.getSessionId(), responseText, stats)
10398
+ formatter.format(
10399
+ config.getSessionId(),
10400
+ responseText,
10401
+ stats,
10402
+ void 0,
10403
+ warnings
10404
+ )
10374
10405
  );
10375
10406
  } else {
10376
10407
  textOutput.ensureTrailingNewline();
@@ -10441,6 +10472,7 @@ async function runNonInteractive({
10441
10472
  let responseText = "";
10442
10473
  let preToolResponseText;
10443
10474
  let streamEnded = false;
10475
+ const warnings = [];
10444
10476
  for await (const event of session.stream({ streamId })) {
10445
10477
  if (streamEnded) break;
10446
10478
  switch (event.type) {
@@ -10539,10 +10571,19 @@ async function runNonInteractive({
10539
10571
  }
10540
10572
  const errorCode = event._meta?.["code"];
10541
10573
  if (errorCode === "AGENT_EXECUTION_BLOCKED") {
10574
+ const blockMessage = `Agent execution blocked: ${event.message.trim()}`;
10542
10575
  if (config.getOutputFormat() === "text" /* TEXT */) {
10543
- process.stderr.write(`[WARNING] ${event.message}
10576
+ process.stderr.write(`[WARNING] ${blockMessage}
10544
10577
  `);
10578
+ } else if (streamFormatter) {
10579
+ streamFormatter.emitEvent({
10580
+ type: "error" /* ERROR */,
10581
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10582
+ severity: "warning",
10583
+ message: stripAnsi(blockMessage)
10584
+ });
10545
10585
  }
10586
+ warnings.push(blockMessage);
10546
10587
  break;
10547
10588
  }
10548
10589
  const severity = event.status === "RESOURCE_EXHAUSTED" ? "error" : "warning";
@@ -10555,9 +10596,10 @@ async function runNonInteractive({
10555
10596
  type: "error" /* ERROR */,
10556
10597
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10557
10598
  severity,
10558
- message: event.message
10599
+ message: stripAnsi(event.message)
10559
10600
  });
10560
10601
  }
10602
+ warnings.push(event.message);
10561
10603
  break;
10562
10604
  }
10563
10605
  case "agent_end": {
@@ -10634,7 +10676,7 @@ async function runNonInteractive2(params) {
10634
10676
  }
10635
10677
  });
10636
10678
  if (process.env["GEMINI_CLI_ACTIVITY_LOG_TARGET"]) {
10637
- const { setupInitialActivityLogger } = await import("./devtoolsService-QXOHXSMJ.js");
10679
+ const { setupInitialActivityLogger } = await import("./devtoolsService-DFWZ34A5.js");
10638
10680
  setupInitialActivityLogger(config);
10639
10681
  }
10640
10682
  const { stdout: workingStdout } = createWorkingStdio();
@@ -10777,6 +10819,8 @@ async function runNonInteractive2(params) {
10777
10819
  }
10778
10820
  let currentMessages = [{ role: "user", parts: query }];
10779
10821
  let turnCount = 0;
10822
+ let invalidStreamError;
10823
+ const warnings = [];
10780
10824
  while (true) {
10781
10825
  turnCount++;
10782
10826
  if (config.getMaxSessionTurns() >= 0 && turnCount > config.getMaxSessionTurns()) {
@@ -10826,23 +10870,27 @@ async function runNonInteractive2(params) {
10826
10870
  }
10827
10871
  toolCallRequests.push(event.value);
10828
10872
  } else if (event.type === "loop_detected" /* LoopDetected */) {
10873
+ const message = "Loop detected, stopping execution";
10829
10874
  if (streamFormatter) {
10830
10875
  streamFormatter.emitEvent({
10831
10876
  type: "error" /* ERROR */,
10832
10877
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10833
10878
  severity: "warning",
10834
- message: "Loop detected, stopping execution"
10879
+ message
10835
10880
  });
10836
10881
  }
10882
+ warnings.push(message);
10837
10883
  } else if (event.type === "max_session_turns" /* MaxSessionTurns */) {
10884
+ const message = "Maximum session turns exceeded";
10838
10885
  if (streamFormatter) {
10839
10886
  streamFormatter.emitEvent({
10840
10887
  type: "error" /* ERROR */,
10841
10888
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10842
10889
  severity: "error",
10843
- message: "Maximum session turns exceeded"
10890
+ message
10844
10891
  });
10845
10892
  }
10893
+ warnings.push(message);
10846
10894
  } else if (event.type === "error" /* Error */) {
10847
10895
  throw event.value.error;
10848
10896
  } else if (event.type === "agent_execution_stopped" /* AgentExecutionStopped */) {
@@ -10869,8 +10917,31 @@ async function runNonInteractive2(params) {
10869
10917
  const blockMessage = `Agent execution blocked: ${event.value.systemMessage?.trim() || event.value.reason}`;
10870
10918
  if (config.getOutputFormat() === "text" /* TEXT */) {
10871
10919
  process.stderr.write(`[WARNING] ${blockMessage}
10920
+ `);
10921
+ } else if (streamFormatter) {
10922
+ streamFormatter.emitEvent({
10923
+ type: "error" /* ERROR */,
10924
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10925
+ severity: "warning",
10926
+ message: stripAnsi(blockMessage)
10927
+ });
10928
+ }
10929
+ warnings.push(blockMessage);
10930
+ } else if (event.type === "invalid_stream" /* InvalidStream */) {
10931
+ invalidStreamError = "Invalid stream: The model returned an empty response or malformed tool call.";
10932
+ if (streamFormatter) {
10933
+ streamFormatter.emitEvent({
10934
+ type: "error" /* ERROR */,
10935
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10936
+ severity: "error",
10937
+ message: invalidStreamError
10938
+ });
10939
+ } else if (config.getOutputFormat() === "text" /* TEXT */) {
10940
+ process.stderr.write(`[ERROR] ${invalidStreamError}
10872
10941
  `);
10873
10942
  }
10943
+ toolCallRequests.length = 0;
10944
+ break;
10874
10945
  }
10875
10946
  }
10876
10947
  if (toolCallRequests.length > 0) {
@@ -10943,7 +11014,13 @@ async function runNonInteractive2(params) {
10943
11014
  const formatter = new JsonFormatter();
10944
11015
  const stats = uiTelemetryService.getMetrics();
10945
11016
  textOutput.write(
10946
- formatter.format(config.getSessionId(), responseText, stats)
11017
+ formatter.format(
11018
+ config.getSessionId(),
11019
+ responseText,
11020
+ stats,
11021
+ void 0,
11022
+ warnings
11023
+ )
10947
11024
  );
10948
11025
  } else {
10949
11026
  textOutput.ensureTrailingNewline();
@@ -10958,14 +11035,20 @@ async function runNonInteractive2(params) {
10958
11035
  streamFormatter.emitEvent({
10959
11036
  type: "result" /* RESULT */,
10960
11037
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10961
- status: "success",
11038
+ status: invalidStreamError ? "error" : "success",
10962
11039
  stats: streamFormatter.convertToStreamStats(metrics, durationMs)
10963
11040
  });
10964
11041
  } else if (config.getOutputFormat() === "json" /* JSON */) {
10965
11042
  const formatter = new JsonFormatter();
10966
11043
  const stats = uiTelemetryService.getMetrics();
10967
11044
  textOutput.write(
10968
- formatter.format(config.getSessionId(), responseText, stats)
11045
+ formatter.format(
11046
+ config.getSessionId(),
11047
+ responseText,
11048
+ stats,
11049
+ invalidStreamError ? { type: "INVALID_STREAM", message: invalidStreamError } : void 0,
11050
+ warnings
11051
+ )
10969
11052
  );
10970
11053
  } else {
10971
11054
  textOutput.ensureTrailingNewline();
@@ -12524,59 +12607,8 @@ var RequestError = class _RequestError extends Error {
12524
12607
  }
12525
12608
  };
12526
12609
 
12527
- // packages/cli/src/acp/fileSystemService.ts
12528
- import os5 from "node:os";
12529
- import path10 from "node:path";
12530
- var AcpFileSystemService = class {
12531
- constructor(connection, sessionId, capabilities, fallback, root) {
12532
- this.connection = connection;
12533
- this.sessionId = sessionId;
12534
- this.capabilities = capabilities;
12535
- this.fallback = fallback;
12536
- this.root = root;
12537
- }
12538
- geminiDir = path10.join(os5.homedir(), ".gemini");
12539
- shouldUseFallback(filePath) {
12540
- return !isWithinRoot(filePath, this.root) || isWithinRoot(filePath, this.geminiDir);
12541
- }
12542
- normalizeFileSystemError(err) {
12543
- const errorMessage = err instanceof Error ? err.message : String(err);
12544
- if (errorMessage.includes("Resource not found") || errorMessage.includes("ENOENT") || errorMessage.includes("does not exist") || errorMessage.includes("No such file")) {
12545
- const newErr = new Error(errorMessage);
12546
- newErr.code = "ENOENT";
12547
- throw newErr;
12548
- }
12549
- throw err;
12550
- }
12551
- async readTextFile(filePath) {
12552
- if (!this.capabilities.readTextFile || this.shouldUseFallback(filePath)) {
12553
- return this.fallback.readTextFile(filePath);
12554
- }
12555
- try {
12556
- const response = await this.connection.readTextFile({
12557
- path: filePath,
12558
- sessionId: this.sessionId
12559
- });
12560
- return response.content;
12561
- } catch (err) {
12562
- this.normalizeFileSystemError(err);
12563
- }
12564
- }
12565
- async writeTextFile(filePath, content) {
12566
- if (!this.capabilities.writeTextFile || this.shouldUseFallback(filePath)) {
12567
- return this.fallback.writeTextFile(filePath, content);
12568
- }
12569
- try {
12570
- await this.connection.writeTextFile({
12571
- path: filePath,
12572
- content,
12573
- sessionId: this.sessionId
12574
- });
12575
- } catch (err) {
12576
- this.normalizeFileSystemError(err);
12577
- }
12578
- }
12579
- };
12610
+ // packages/cli/src/acp/acpStdioTransport.ts
12611
+ import { Readable, Writable } from "node:stream";
12580
12612
 
12581
12613
  // packages/cli/src/acp/acpErrors.ts
12582
12614
  function getAcpErrorMessage(error) {
@@ -12598,10 +12630,12 @@ function extractRecursiveMessage(input) {
12598
12630
  return input;
12599
12631
  }
12600
12632
 
12601
- // packages/cli/src/acp/acpClient.ts
12602
- import { Readable, Writable } from "node:stream";
12633
+ // packages/cli/src/acp/acpSessionManager.ts
12634
+ import { randomUUID as randomUUID2 } from "node:crypto";
12635
+
12636
+ // packages/cli/src/acp/acpSession.ts
12603
12637
  import * as fs12 from "node:fs/promises";
12604
- import * as path13 from "node:path";
12638
+ import * as path12 from "node:path";
12605
12639
  import { randomUUID } from "node:crypto";
12606
12640
 
12607
12641
  // packages/cli/src/acp/commands/commandRegistry.ts
@@ -13073,7 +13107,7 @@ var UpdateExtensionCommand = class {
13073
13107
 
13074
13108
  // packages/cli/src/acp/commands/init.ts
13075
13109
  import * as fs10 from "node:fs";
13076
- import * as path11 from "node:path";
13110
+ import * as path10 from "node:path";
13077
13111
  var InitCommand = class {
13078
13112
  name = "init";
13079
13113
  description = "Analyzes the project and creates a tailored GEMINI.md file";
@@ -13083,7 +13117,7 @@ var InitCommand = class {
13083
13117
  if (!targetDir) {
13084
13118
  throw new Error("Command requires a workspace.");
13085
13119
  }
13086
- const geminiMdPath = path11.join(targetDir, "GEMINI.md");
13120
+ const geminiMdPath = path10.join(targetDir, "GEMINI.md");
13087
13121
  const result = performInit(fs10.existsSync(geminiMdPath));
13088
13122
  switch (result.type) {
13089
13123
  case "message":
@@ -13116,7 +13150,7 @@ ${result.content}`
13116
13150
 
13117
13151
  // packages/cli/src/acp/commands/restore.ts
13118
13152
  import * as fs11 from "node:fs/promises";
13119
- import * as path12 from "node:path";
13153
+ import * as path11 from "node:path";
13120
13154
  var RestoreCommand = class {
13121
13155
  name = "restore";
13122
13156
  description = "Restore to a previous checkpoint, or list available checkpoints to restore. This will reset the conversation and file history to the state it was in when the checkpoint was created";
@@ -13138,7 +13172,7 @@ var RestoreCommand = class {
13138
13172
  }
13139
13173
  const selectedFile = argsStr.endsWith(".json") ? argsStr : `${argsStr}.json`;
13140
13174
  const checkpointDir = config.storage.getProjectTempCheckpointsDir();
13141
- const filePath = path12.join(checkpointDir, selectedFile);
13175
+ const filePath = path11.join(checkpointDir, selectedFile);
13142
13176
  let data;
13143
13177
  try {
13144
13178
  data = await fs11.readFile(filePath, "utf-8");
@@ -13212,7 +13246,7 @@ var ListCheckpointsCommand = class {
13212
13246
  }
13213
13247
  const checkpointFiles = /* @__PURE__ */ new Map();
13214
13248
  for (const file of jsonFiles) {
13215
- const filePath = path12.join(checkpointDir, file);
13249
+ const filePath = path11.join(checkpointDir, file);
13216
13250
  const data = await fs11.readFile(filePath, "utf-8");
13217
13251
  checkpointFiles.set(file, data);
13218
13252
  }
@@ -13319,7 +13353,7 @@ var HelpCommand = class {
13319
13353
  }
13320
13354
  };
13321
13355
 
13322
- // packages/cli/src/acp/commandHandler.ts
13356
+ // packages/cli/src/acp/acpCommandHandler.ts
13323
13357
  var CommandHandler = class _CommandHandler {
13324
13358
  registry;
13325
13359
  constructor() {
@@ -13406,7 +13440,7 @@ var CommandHandler = class _CommandHandler {
13406
13440
  }
13407
13441
  };
13408
13442
 
13409
- // packages/cli/src/acp/acpClient.ts
13443
+ // packages/cli/src/acp/acpUtils.ts
13410
13444
  function hasMeta(obj) {
13411
13445
  return typeof obj === "object" && obj !== null && "_meta" in obj;
13412
13446
  }
@@ -13419,380 +13453,273 @@ var RequestPermissionResponseSchema = external_exports.object({
13419
13453
  })
13420
13454
  ])
13421
13455
  });
13422
- async function runAcpClient(config, settings, argv) {
13423
- const { stdout: workingStdout } = createWorkingStdio();
13424
- const stdout = Writable.toWeb(workingStdout);
13425
- const stdin = Readable.toWeb(process.stdin);
13426
- const stream = ndJsonStream(stdout, stdin);
13427
- const connection = new AgentSideConnection(
13428
- (connection2) => new GeminiAgent(config, settings, argv, connection2),
13429
- stream
13430
- );
13431
- await connection.closed.finally(runExitCleanup);
13432
- }
13433
- var GeminiAgent = class _GeminiAgent {
13434
- constructor(context, settings, argv, connection) {
13435
- this.context = context;
13436
- this.settings = settings;
13437
- this.argv = argv;
13438
- this.connection = connection;
13439
- }
13440
- static callIdCounter = 0;
13441
- static generateCallId(name) {
13442
- return `${name}-${Date.now()}-${++_GeminiAgent.callIdCounter}`;
13456
+ function toToolCallContent(toolResult) {
13457
+ if (toolResult.error?.message) {
13458
+ throw new Error(toolResult.error.message);
13443
13459
  }
13444
- sessions = /* @__PURE__ */ new Map();
13445
- clientCapabilities;
13446
- apiKey;
13447
- baseUrl;
13448
- customHeaders;
13449
- async initialize(args) {
13450
- this.clientCapabilities = args.clientCapabilities;
13451
- const authMethods = [
13452
- {
13453
- id: "oauth-personal" /* LOGIN_WITH_GOOGLE */,
13454
- name: "Log in with Google",
13455
- description: "Log in with your Google account"
13456
- },
13457
- {
13458
- id: "gemini-api-key" /* USE_GEMINI */,
13459
- name: "Gemini API key",
13460
- description: "Use an API key with Gemini Developer API",
13461
- _meta: {
13462
- "api-key": {
13463
- provider: "google"
13464
- }
13465
- }
13466
- },
13467
- {
13468
- id: "vertex-ai" /* USE_VERTEX_AI */,
13469
- name: "Vertex AI",
13470
- description: "Use an API key with Vertex AI GenAI API"
13471
- },
13472
- {
13473
- id: "gateway" /* GATEWAY */,
13474
- name: "AI API Gateway",
13475
- description: "Use a custom AI API Gateway",
13476
- _meta: {
13477
- gateway: {
13478
- protocol: "google",
13479
- restartRequired: "false"
13460
+ if (toolResult.returnDisplay) {
13461
+ if (typeof toolResult.returnDisplay === "string") {
13462
+ return {
13463
+ type: "content",
13464
+ content: { type: "text", text: toolResult.returnDisplay }
13465
+ };
13466
+ } else {
13467
+ if ("fileName" in toolResult.returnDisplay) {
13468
+ return {
13469
+ type: "diff",
13470
+ path: toolResult.returnDisplay.filePath ?? toolResult.returnDisplay.fileName,
13471
+ oldText: toolResult.returnDisplay.originalContent,
13472
+ newText: toolResult.returnDisplay.newContent,
13473
+ _meta: {
13474
+ kind: !toolResult.returnDisplay.originalContent ? "add" : toolResult.returnDisplay.newContent === "" ? "delete" : "modify"
13480
13475
  }
13481
- }
13482
- }
13483
- ];
13484
- await this.context.config.initialize();
13485
- const version = await getVersion();
13486
- return {
13487
- protocolVersion: PROTOCOL_VERSION,
13488
- authMethods,
13489
- agentInfo: {
13490
- name: "gemini-cli",
13491
- title: "Gemini CLI",
13492
- version
13493
- },
13494
- agentCapabilities: {
13495
- loadSession: true,
13496
- promptCapabilities: {
13497
- image: true,
13498
- audio: true,
13499
- embeddedContext: true
13500
- },
13501
- mcpCapabilities: {
13502
- http: true,
13503
- sse: true
13504
- }
13505
- }
13506
- };
13507
- }
13508
- async authenticate(req) {
13509
- const { methodId } = req;
13510
- const method = external_exports.nativeEnum(AuthType).parse(methodId);
13511
- const selectedAuthType = this.settings.merged.security.auth.selectedType;
13512
- if (selectedAuthType && selectedAuthType !== method) {
13513
- await clearCachedCredentialFile();
13514
- }
13515
- const meta = hasMeta(req) ? req._meta : void 0;
13516
- const apiKey = typeof meta?.["api-key"] === "string" ? meta["api-key"] : void 0;
13517
- try {
13518
- if (apiKey) {
13519
- this.apiKey = apiKey;
13520
- }
13521
- const gatewaySchema = external_exports.object({
13522
- baseUrl: external_exports.string().optional(),
13523
- headers: external_exports.record(external_exports.string()).optional()
13524
- });
13525
- let baseUrl;
13526
- let headers;
13527
- if (meta?.["gateway"]) {
13528
- const result = gatewaySchema.safeParse(meta["gateway"]);
13529
- if (result.success) {
13530
- baseUrl = result.data.baseUrl;
13531
- headers = result.data.headers;
13532
- } else {
13533
- throw new RequestError(
13534
- -32602,
13535
- `Malformed gateway payload: ${result.error.message}`
13536
- );
13537
- }
13476
+ };
13538
13477
  }
13539
- this.baseUrl = baseUrl;
13540
- this.customHeaders = headers;
13541
- await this.context.config.refreshAuth(
13542
- method,
13543
- apiKey ?? this.apiKey,
13544
- baseUrl,
13545
- headers
13546
- );
13547
- } catch (e) {
13548
- throw new RequestError(-32e3, getAcpErrorMessage(e));
13478
+ return null;
13549
13479
  }
13550
- this.settings.setValue(
13551
- "User" /* User */,
13552
- "security.auth.selectedType",
13553
- method
13554
- );
13480
+ } else {
13481
+ return null;
13555
13482
  }
13556
- async newSession({
13557
- cwd,
13558
- mcpServers
13559
- }) {
13560
- const sessionId = randomUUID();
13561
- const loadedSettings = loadSettings(cwd);
13562
- const config = await this.newSessionConfig(
13563
- sessionId,
13564
- cwd,
13565
- mcpServers,
13566
- loadedSettings
13567
- );
13568
- const authType = loadedSettings.merged.security.auth.selectedType || "gemini-api-key" /* USE_GEMINI */;
13569
- let isAuthenticated = false;
13570
- let authErrorMessage = "";
13571
- try {
13572
- await config.refreshAuth(
13573
- authType,
13574
- this.apiKey,
13575
- this.baseUrl,
13576
- this.customHeaders
13577
- );
13578
- isAuthenticated = true;
13579
- const contentGeneratorConfig = config.getContentGeneratorConfig();
13580
- if (authType === "gemini-api-key" /* USE_GEMINI */ && (!contentGeneratorConfig || !contentGeneratorConfig.apiKey)) {
13581
- isAuthenticated = false;
13582
- authErrorMessage = "Gemini API key is missing or not configured.";
13583
- }
13584
- } catch (e) {
13585
- isAuthenticated = false;
13586
- authErrorMessage = getAcpErrorMessage(e);
13587
- debugLogger.error(
13588
- `Authentication failed: ${e instanceof Error ? e.stack : e}`
13589
- );
13590
- }
13591
- if (!isAuthenticated) {
13592
- throw new RequestError(
13593
- -32e3,
13594
- authErrorMessage || "Authentication required."
13595
- );
13596
- }
13597
- if (this.clientCapabilities?.fs) {
13598
- const acpFileSystemService = new AcpFileSystemService(
13599
- this.connection,
13600
- sessionId,
13601
- this.clientCapabilities.fs,
13602
- config.getFileSystemService(),
13603
- cwd
13604
- );
13605
- config.setFileSystemService(acpFileSystemService);
13606
- }
13607
- await config.initialize();
13608
- startupProfiler.flush(config);
13609
- startAutoMemoryIfEnabled(config);
13610
- const geminiClient = config.getGeminiClient();
13611
- const chat = await geminiClient.startChat();
13612
- const session = new Session(
13613
- sessionId,
13614
- chat,
13615
- config,
13616
- this.connection,
13617
- this.settings
13618
- );
13619
- this.sessions.set(sessionId, session);
13620
- setTimeout(() => {
13621
- session.sendAvailableCommands();
13622
- }, 0);
13623
- const { availableModels, currentModelId } = buildAvailableModels(
13624
- config,
13625
- loadedSettings
13626
- );
13627
- const response = {
13628
- sessionId,
13629
- modes: {
13630
- availableModes: buildAvailableModes(config.isPlanEnabled()),
13631
- currentModeId: config.getApprovalMode()
13632
- },
13633
- models: {
13634
- availableModels,
13635
- currentModelId
13636
- }
13637
- };
13638
- return response;
13639
- }
13640
- async loadSession({
13641
- sessionId,
13642
- cwd,
13643
- mcpServers
13644
- }) {
13645
- const config = await this.initializeSessionConfig(
13646
- sessionId,
13647
- cwd,
13648
- mcpServers
13649
- );
13650
- const sessionSelector = new SessionSelector(config.storage);
13651
- const { sessionData, sessionPath } = await sessionSelector.resolveSession(sessionId);
13652
- const clientHistory = convertSessionToClientHistory(sessionData.messages);
13653
- const geminiClient = config.getGeminiClient();
13654
- await geminiClient.initialize();
13655
- await geminiClient.resumeChat(clientHistory, {
13656
- conversation: sessionData,
13657
- filePath: sessionPath
13658
- });
13659
- const session = new Session(
13660
- sessionId,
13661
- geminiClient.getChat(),
13662
- config,
13663
- this.connection,
13664
- this.settings
13665
- );
13666
- this.sessions.set(sessionId, session);
13667
- session.streamHistory(sessionData.messages);
13668
- setTimeout(() => {
13669
- session.sendAvailableCommands();
13670
- }, 0);
13671
- const { availableModels, currentModelId } = buildAvailableModels(
13672
- config,
13673
- this.settings
13674
- );
13675
- const response = {
13676
- modes: {
13677
- availableModes: buildAvailableModes(config.isPlanEnabled()),
13678
- currentModeId: config.getApprovalMode()
13679
- },
13680
- models: {
13681
- availableModels,
13682
- currentModelId
13683
- }
13684
- };
13685
- return response;
13686
- }
13687
- async initializeSessionConfig(sessionId, cwd, mcpServers) {
13688
- const selectedAuthType = this.settings.merged.security.auth.selectedType;
13689
- if (!selectedAuthType) {
13690
- throw RequestError.authRequired();
13691
- }
13692
- const config = await this.newSessionConfig(sessionId, cwd, mcpServers);
13693
- try {
13694
- await config.refreshAuth(
13695
- selectedAuthType,
13696
- this.apiKey,
13697
- this.baseUrl,
13698
- this.customHeaders
13699
- );
13700
- } catch (e) {
13701
- debugLogger.error(`Authentication failed: ${e}`);
13702
- throw RequestError.authRequired();
13703
- }
13704
- if (this.clientCapabilities?.fs) {
13705
- const acpFileSystemService = new AcpFileSystemService(
13706
- this.connection,
13707
- sessionId,
13708
- this.clientCapabilities.fs,
13709
- config.getFileSystemService(),
13710
- cwd
13711
- );
13712
- config.setFileSystemService(acpFileSystemService);
13713
- }
13714
- await config.initialize();
13715
- startupProfiler.flush(config);
13716
- startAutoMemoryIfEnabled(config);
13717
- return config;
13483
+ }
13484
+ var basicPermissionOptions = [
13485
+ {
13486
+ optionId: "proceed_once" /* ProceedOnce */,
13487
+ name: "Allow",
13488
+ kind: "allow_once"
13489
+ },
13490
+ {
13491
+ optionId: "cancel" /* Cancel */,
13492
+ name: "Reject",
13493
+ kind: "reject_once"
13718
13494
  }
13719
- async newSessionConfig(sessionId, cwd, mcpServers, loadedSettings) {
13720
- const currentSettings = loadedSettings || this.settings;
13721
- const mergedMcpServers = { ...currentSettings.merged.mcpServers };
13722
- for (const server of mcpServers) {
13723
- if ("type" in server && (server.type === "sse" || server.type === "http")) {
13724
- const headers = Object.fromEntries(
13725
- server.headers.map(({ name, value }) => [name, value])
13726
- );
13727
- mergedMcpServers[server.name] = new MCPServerConfig(
13728
- void 0,
13729
- // command
13730
- void 0,
13731
- // args
13732
- void 0,
13733
- // env
13734
- void 0,
13735
- // cwd
13736
- server.type === "sse" ? server.url : void 0,
13737
- // url (sse)
13738
- server.type === "http" ? server.url : void 0,
13739
- // httpUrl
13740
- headers
13741
- );
13742
- } else if ("command" in server) {
13743
- const env2 = {};
13744
- for (const { name: envName, value } of server.env) {
13745
- env2[envName] = value;
13495
+ ];
13496
+ function toPermissionOptions(confirmation, config, enablePermanentToolApproval = false) {
13497
+ const disableAlwaysAllow = config.getDisableAlwaysAllow();
13498
+ const options = [];
13499
+ if (!disableAlwaysAllow) {
13500
+ switch (confirmation.type) {
13501
+ case "edit":
13502
+ options.push({
13503
+ optionId: "proceed_always" /* ProceedAlways */,
13504
+ name: "Allow for this session",
13505
+ kind: "allow_always"
13506
+ });
13507
+ if (enablePermanentToolApproval) {
13508
+ options.push({
13509
+ optionId: "proceed_always_and_save" /* ProceedAlwaysAndSave */,
13510
+ name: "Allow for this file in all future sessions",
13511
+ kind: "allow_always"
13512
+ });
13746
13513
  }
13747
- mergedMcpServers[server.name] = new MCPServerConfig(
13748
- server.command,
13749
- server.args,
13750
- env2,
13751
- cwd
13514
+ break;
13515
+ case "exec":
13516
+ options.push({
13517
+ optionId: "proceed_always" /* ProceedAlways */,
13518
+ name: "Allow for this session",
13519
+ kind: "allow_always"
13520
+ });
13521
+ if (enablePermanentToolApproval) {
13522
+ options.push({
13523
+ optionId: "proceed_always_and_save" /* ProceedAlwaysAndSave */,
13524
+ name: "Allow this command for all future sessions",
13525
+ kind: "allow_always"
13526
+ });
13527
+ }
13528
+ break;
13529
+ case "mcp":
13530
+ options.push(
13531
+ {
13532
+ optionId: "proceed_always_server" /* ProceedAlwaysServer */,
13533
+ name: "Allow all server tools for this session",
13534
+ kind: "allow_always"
13535
+ },
13536
+ {
13537
+ optionId: "proceed_always_tool" /* ProceedAlwaysTool */,
13538
+ name: "Allow tool for this session",
13539
+ kind: "allow_always"
13540
+ }
13752
13541
  );
13753
- }
13542
+ if (enablePermanentToolApproval) {
13543
+ options.push({
13544
+ optionId: "proceed_always_and_save" /* ProceedAlwaysAndSave */,
13545
+ name: "Allow tool for all future sessions",
13546
+ kind: "allow_always"
13547
+ });
13548
+ }
13549
+ break;
13550
+ case "info":
13551
+ options.push({
13552
+ optionId: "proceed_always" /* ProceedAlways */,
13553
+ name: "Allow for this session",
13554
+ kind: "allow_always"
13555
+ });
13556
+ if (enablePermanentToolApproval) {
13557
+ options.push({
13558
+ optionId: "proceed_always_and_save" /* ProceedAlwaysAndSave */,
13559
+ name: "Allow for all future sessions",
13560
+ kind: "allow_always"
13561
+ });
13562
+ }
13563
+ break;
13564
+ case "ask_user":
13565
+ case "exit_plan_mode":
13566
+ break;
13567
+ default:
13568
+ break;
13754
13569
  }
13755
- const settings = {
13756
- ...currentSettings.merged,
13757
- mcpServers: mergedMcpServers
13758
- };
13759
- const config = await loadCliConfig(settings, sessionId, this.argv, { cwd });
13760
- createPolicyUpdater2(
13761
- config.getPolicyEngine(),
13762
- config.messageBus,
13763
- config.storage
13764
- );
13765
- return config;
13766
13570
  }
13767
- async cancel(params) {
13768
- const session = this.sessions.get(params.sessionId);
13769
- if (!session) {
13770
- throw new Error(`Session not found: ${params.sessionId}`);
13571
+ options.push(...basicPermissionOptions);
13572
+ switch (confirmation.type) {
13573
+ case "edit":
13574
+ case "exec":
13575
+ case "mcp":
13576
+ case "info":
13577
+ case "ask_user":
13578
+ case "exit_plan_mode":
13579
+ case "sandbox_expansion":
13580
+ break;
13581
+ default: {
13582
+ const unreachable = confirmation;
13583
+ throw new Error(`Unexpected: ${unreachable}`);
13771
13584
  }
13772
- await session.cancelPendingPrompt();
13773
13585
  }
13774
- async prompt(params) {
13775
- const session = this.sessions.get(params.sessionId);
13776
- if (!session) {
13777
- throw new Error(`Session not found: ${params.sessionId}`);
13586
+ return options;
13587
+ }
13588
+ function toAcpToolKind(kind) {
13589
+ switch (kind) {
13590
+ case "read" /* Read */:
13591
+ case "edit" /* Edit */:
13592
+ case "execute" /* Execute */:
13593
+ case "search" /* Search */:
13594
+ case "delete" /* Delete */:
13595
+ case "move" /* Move */:
13596
+ case "think" /* Think */:
13597
+ case "fetch" /* Fetch */:
13598
+ case "switch_mode" /* SwitchMode */:
13599
+ case "other" /* Other */:
13600
+ return kind;
13601
+ case "agent" /* Agent */:
13602
+ return "think";
13603
+ case "plan" /* Plan */:
13604
+ case "communicate" /* Communicate */:
13605
+ default:
13606
+ return "other";
13607
+ }
13608
+ }
13609
+ function buildAvailableModes(isPlanEnabled) {
13610
+ const modes = [
13611
+ {
13612
+ id: "default" /* DEFAULT */,
13613
+ name: "Default",
13614
+ description: "Prompts for approval"
13615
+ },
13616
+ {
13617
+ id: "autoEdit" /* AUTO_EDIT */,
13618
+ name: "Auto Edit",
13619
+ description: "Auto-approves edit tools"
13620
+ },
13621
+ {
13622
+ id: "yolo" /* YOLO */,
13623
+ name: "YOLO",
13624
+ description: "Auto-approves all tools"
13778
13625
  }
13779
- return session.prompt(params);
13626
+ ];
13627
+ if (isPlanEnabled) {
13628
+ modes.push({
13629
+ id: "plan" /* PLAN */,
13630
+ name: "Plan",
13631
+ description: "Read-only mode"
13632
+ });
13780
13633
  }
13781
- async setSessionMode(params) {
13782
- const session = this.sessions.get(params.sessionId);
13783
- if (!session) {
13784
- throw new Error(`Session not found: ${params.sessionId}`);
13634
+ return modes;
13635
+ }
13636
+ function buildAvailableModels(config, settings) {
13637
+ const preferredModel = config.getModel() || DEFAULT_GEMINI_MODEL_AUTO;
13638
+ const shouldShowPreviewModels = config.getHasAccessToPreviewModel();
13639
+ const useGemini31 = config.getGemini31LaunchedSync?.() ?? false;
13640
+ const useGemini31FlashLite = config.getGemini31FlashLiteLaunchedSync?.() ?? false;
13641
+ const selectedAuthType = settings.merged.security.auth.selectedType;
13642
+ const useCustomToolModel = useGemini31 && selectedAuthType === "gemini-api-key" /* USE_GEMINI */;
13643
+ if (config.getExperimentalDynamicModelConfiguration?.() === true && config.getModelConfigService) {
13644
+ const options = config.getModelConfigService().getAvailableModelOptions({
13645
+ useGemini3_1: useGemini31,
13646
+ useGemini3_1FlashLite: useGemini31FlashLite,
13647
+ useCustomTools: useCustomToolModel,
13648
+ hasAccessToPreview: shouldShowPreviewModels
13649
+ });
13650
+ return {
13651
+ availableModels: options,
13652
+ currentModelId: preferredModel
13653
+ };
13654
+ }
13655
+ const mainOptions = [
13656
+ {
13657
+ value: DEFAULT_GEMINI_MODEL_AUTO,
13658
+ title: getDisplayString(DEFAULT_GEMINI_MODEL_AUTO),
13659
+ description: "Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash"
13785
13660
  }
13786
- return session.setMode(params.modeId);
13661
+ ];
13662
+ if (shouldShowPreviewModels) {
13663
+ mainOptions.unshift({
13664
+ value: PREVIEW_GEMINI_MODEL_AUTO,
13665
+ title: getDisplayString(PREVIEW_GEMINI_MODEL_AUTO),
13666
+ description: useGemini31 ? "Let Gemini CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash" : "Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash"
13667
+ });
13787
13668
  }
13788
- async unstable_setSessionModel(params) {
13789
- const session = this.sessions.get(params.sessionId);
13790
- if (!session) {
13791
- throw new Error(`Session not found: ${params.sessionId}`);
13669
+ const manualOptions = [
13670
+ {
13671
+ value: DEFAULT_GEMINI_MODEL,
13672
+ title: getDisplayString(DEFAULT_GEMINI_MODEL)
13673
+ },
13674
+ {
13675
+ value: DEFAULT_GEMINI_FLASH_MODEL,
13676
+ title: getDisplayString(DEFAULT_GEMINI_FLASH_MODEL)
13677
+ },
13678
+ {
13679
+ value: DEFAULT_GEMINI_FLASH_LITE_MODEL,
13680
+ title: getDisplayString(DEFAULT_GEMINI_FLASH_LITE_MODEL)
13792
13681
  }
13793
- return session.setModel(params.modelId);
13682
+ ];
13683
+ if (shouldShowPreviewModels) {
13684
+ const previewProModel = useGemini31 ? PREVIEW_GEMINI_3_1_MODEL : PREVIEW_GEMINI_MODEL;
13685
+ const previewProValue = useCustomToolModel ? PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL : previewProModel;
13686
+ const previewOptions = [
13687
+ {
13688
+ value: previewProValue,
13689
+ title: getDisplayString(previewProModel)
13690
+ },
13691
+ {
13692
+ value: PREVIEW_GEMINI_FLASH_MODEL,
13693
+ title: getDisplayString(PREVIEW_GEMINI_FLASH_MODEL)
13694
+ }
13695
+ ];
13696
+ if (useGemini31FlashLite) {
13697
+ previewOptions.push({
13698
+ value: PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL,
13699
+ title: getDisplayString(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL)
13700
+ });
13701
+ }
13702
+ manualOptions.unshift(...previewOptions);
13794
13703
  }
13795
- };
13704
+ const scaleOptions = (options) => options.map((o) => ({
13705
+ modelId: o.value,
13706
+ name: o.title,
13707
+ description: o.description
13708
+ }));
13709
+ return {
13710
+ availableModels: [
13711
+ ...scaleOptions(mainOptions),
13712
+ ...scaleOptions(manualOptions)
13713
+ ],
13714
+ currentModelId: preferredModel
13715
+ };
13716
+ }
13717
+
13718
+ // packages/cli/src/acp/acpSession.ts
13719
+ var StructuredErrorSchema = external_exports.object({
13720
+ status: external_exports.number().optional(),
13721
+ message: external_exports.string().optional()
13722
+ });
13796
13723
  var Session = class {
13797
13724
  constructor(id, chat, context, connection, settings) {
13798
13725
  this.id = id;
@@ -13803,6 +13730,10 @@ var Session = class {
13803
13730
  }
13804
13731
  pendingPrompt = null;
13805
13732
  commandHandler = new CommandHandler();
13733
+ callIdCounter = 0;
13734
+ generateCallId(name) {
13735
+ return `${name}-${Date.now()}-${++this.callIdCounter}`;
13736
+ }
13806
13737
  async cancelPendingPrompt() {
13807
13738
  if (!this.pendingPrompt) {
13808
13739
  throw new Error("Not currently generating");
@@ -13903,16 +13834,13 @@ ${thought.description}`;
13903
13834
  this.pendingPrompt = pendingSend;
13904
13835
  await this.context.config.waitForMcpInit();
13905
13836
  const promptId = Math.random().toString(16).slice(2);
13906
- const chat = this.chat;
13907
13837
  const parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
13908
13838
  let commandText = "";
13909
13839
  for (const part of parts) {
13910
13840
  if (typeof part === "object" && part !== null) {
13911
- if ("text" in part) {
13841
+ if (isTextPart(part)) {
13912
13842
  const text = part.text;
13913
- if (typeof text === "string") {
13914
- commandText += text;
13915
- }
13843
+ commandText += text;
13916
13844
  } else {
13917
13845
  break;
13918
13846
  }
@@ -13936,80 +13864,108 @@ ${thought.description}`;
13936
13864
  let totalInputTokens = 0;
13937
13865
  let totalOutputTokens = 0;
13938
13866
  const modelUsageMap = /* @__PURE__ */ new Map();
13939
- let nextMessage = { role: "user", parts };
13940
- while (nextMessage !== null) {
13867
+ let currentParts = parts;
13868
+ let turnCount = 0;
13869
+ const maxTurns = this.context.config.getMaxSessionTurns();
13870
+ while (true) {
13871
+ turnCount++;
13872
+ if (maxTurns >= 0 && turnCount > maxTurns) {
13873
+ return {
13874
+ stopReason: "max_turn_requests",
13875
+ _meta: {
13876
+ quota: {
13877
+ token_count: {
13878
+ input_tokens: totalInputTokens,
13879
+ output_tokens: totalOutputTokens
13880
+ },
13881
+ model_usage: Array.from(modelUsageMap.entries()).map(
13882
+ ([modelName, counts]) => ({
13883
+ model: modelName,
13884
+ token_count: {
13885
+ input_tokens: counts.input,
13886
+ output_tokens: counts.output
13887
+ }
13888
+ })
13889
+ )
13890
+ }
13891
+ }
13892
+ };
13893
+ }
13941
13894
  if (pendingSend.signal.aborted) {
13942
- chat.addHistory(nextMessage);
13943
- return { stopReason: "cancelled" /* Cancelled */ };
13895
+ return { stopReason: "cancelled" };
13944
13896
  }
13945
- const functionCalls = [];
13897
+ const toolCallRequests = [];
13898
+ let stopReason = "end_turn";
13899
+ let turnModelId = this.context.config.getModel();
13900
+ let turnInputTokens = 0;
13901
+ let turnOutputTokens = 0;
13946
13902
  try {
13947
- const routingContext = {
13948
- history: chat.getHistory(
13949
- /*curated=*/
13950
- true
13951
- ),
13952
- request: nextMessage?.parts ?? [],
13953
- signal: pendingSend.signal,
13954
- requestedModel: this.context.config.getModel()
13955
- };
13956
- const router = this.context.config.getModelRouterService();
13957
- const { model } = await router.route(routingContext);
13958
- const responseStream = await chat.sendMessageStream(
13959
- { model },
13960
- nextMessage?.parts ?? [],
13961
- promptId,
13903
+ const responseStream = this.context.geminiClient.sendMessageStream(
13904
+ currentParts,
13962
13905
  pendingSend.signal,
13963
- "main" /* MAIN */
13906
+ promptId
13964
13907
  );
13965
- nextMessage = null;
13966
- let turnInputTokens = 0;
13967
- let turnOutputTokens = 0;
13968
- let turnModelId = model;
13969
- for await (const resp of responseStream) {
13908
+ for await (const event of responseStream) {
13970
13909
  if (pendingSend.signal.aborted) {
13971
- return { stopReason: "cancelled" /* Cancelled */ };
13972
- }
13973
- if (resp.type === "chunk" /* CHUNK */ && resp.value.usageMetadata) {
13974
- turnInputTokens = resp.value.usageMetadata.promptTokenCount ?? turnInputTokens;
13975
- turnOutputTokens = resp.value.usageMetadata.candidatesTokenCount ?? turnOutputTokens;
13976
- if (resp.value.modelVersion) {
13977
- turnModelId = resp.value.modelVersion;
13978
- }
13910
+ return { stopReason: "cancelled" };
13979
13911
  }
13980
- if (resp.type === "chunk" /* CHUNK */ && resp.value.candidates && resp.value.candidates.length > 0) {
13981
- const candidate = resp.value.candidates[0];
13982
- for (const part of candidate.content?.parts ?? []) {
13983
- if (!part.text) {
13984
- continue;
13985
- }
13912
+ switch (event.type) {
13913
+ case "content" /* Content */: {
13986
13914
  const content = {
13987
13915
  type: "text",
13988
- text: part.text
13916
+ text: event.value
13989
13917
  };
13990
- this.sendUpdate({
13991
- sessionUpdate: part.thought ? "agent_thought_chunk" : "agent_message_chunk",
13918
+ await this.sendUpdate({
13919
+ sessionUpdate: "agent_message_chunk",
13992
13920
  content
13993
13921
  });
13922
+ break;
13923
+ }
13924
+ case "thought" /* Thought */: {
13925
+ const thoughtText = `**${event.value.subject}**
13926
+ ${event.value.description}`;
13927
+ await this.sendUpdate({
13928
+ sessionUpdate: "agent_thought_chunk",
13929
+ content: { type: "text", text: thoughtText }
13930
+ });
13931
+ break;
13994
13932
  }
13933
+ case "tool_call_request" /* ToolCallRequest */:
13934
+ toolCallRequests.push(event.value);
13935
+ break;
13936
+ case "finished" /* Finished */: {
13937
+ const usage2 = event.value.usageMetadata;
13938
+ if (usage2) {
13939
+ turnInputTokens = usage2.promptTokenCount ?? turnInputTokens;
13940
+ turnOutputTokens = usage2.candidatesTokenCount ?? turnOutputTokens;
13941
+ }
13942
+ break;
13943
+ }
13944
+ case "model_info" /* ModelInfo */:
13945
+ turnModelId = event.value;
13946
+ break;
13947
+ case "max_session_turns" /* MaxSessionTurns */:
13948
+ stopReason = "max_turn_requests";
13949
+ break;
13950
+ case "loop_detected" /* LoopDetected */:
13951
+ stopReason = "max_turn_requests";
13952
+ break;
13953
+ case "context_window_will_overflow" /* ContextWindowWillOverflow */:
13954
+ stopReason = "max_tokens";
13955
+ break;
13956
+ case "error" /* Error */: {
13957
+ const parseResult = StructuredErrorSchema.safeParse(
13958
+ event.value.error
13959
+ );
13960
+ const errData = parseResult.success ? parseResult.data : {};
13961
+ throw new RequestError(
13962
+ errData.status ?? 500,
13963
+ errData.message ?? "Unknown stream execution error."
13964
+ );
13965
+ }
13966
+ default:
13967
+ break;
13995
13968
  }
13996
- if (resp.type === "chunk" /* CHUNK */ && resp.value.functionCalls) {
13997
- functionCalls.push(...resp.value.functionCalls);
13998
- }
13999
- }
14000
- totalInputTokens += turnInputTokens;
14001
- totalOutputTokens += turnOutputTokens;
14002
- if (turnInputTokens > 0 || turnOutputTokens > 0) {
14003
- const existing = modelUsageMap.get(turnModelId) ?? {
14004
- input: 0,
14005
- output: 0
14006
- };
14007
- existing.input += turnInputTokens;
14008
- existing.output += turnOutputTokens;
14009
- modelUsageMap.set(turnModelId, existing);
14010
- }
14011
- if (pendingSend.signal.aborted) {
14012
- return { stopReason: "cancelled" /* Cancelled */ };
14013
13969
  }
14014
13970
  } catch (error) {
14015
13971
  if (getErrorStatus(error) === 429) {
@@ -14019,7 +13975,10 @@ ${thought.description}`;
14019
13975
  );
14020
13976
  }
14021
13977
  if (pendingSend.signal.aborted || error instanceof Error && error.name === "AbortError") {
14022
- return { stopReason: "cancelled" /* Cancelled */ };
13978
+ return { stopReason: "cancelled" };
13979
+ }
13980
+ if (error instanceof RequestError) {
13981
+ throw error;
14023
13982
  }
14024
13983
  if (error instanceof InvalidStreamError || error && typeof error === "object" && "type" in error && (error.type === "NO_RESPONSE_TEXT" || error.type === "NO_FINISH_REASON" || error.type === "MALFORMED_FUNCTION_CALL" || error.type === "UNEXPECTED_TOOL_CALL")) {
14025
13984
  return {
@@ -14048,14 +14007,53 @@ ${thought.description}`;
14048
14007
  getAcpErrorMessage(error)
14049
14008
  );
14050
14009
  }
14051
- if (functionCalls.length > 0) {
14052
- const toolResponseParts = [];
14053
- for (const fc of functionCalls) {
14054
- const response = await this.runTool(pendingSend.signal, promptId, fc);
14055
- toolResponseParts.push(...response);
14056
- }
14057
- nextMessage = { role: "user", parts: toolResponseParts };
14010
+ totalInputTokens += turnInputTokens;
14011
+ totalOutputTokens += turnOutputTokens;
14012
+ if (turnInputTokens > 0 || turnOutputTokens > 0) {
14013
+ const existing = modelUsageMap.get(turnModelId) ?? {
14014
+ input: 0,
14015
+ output: 0
14016
+ };
14017
+ existing.input += turnInputTokens;
14018
+ existing.output += turnOutputTokens;
14019
+ modelUsageMap.set(turnModelId, existing);
14020
+ }
14021
+ if (stopReason !== "end_turn") {
14022
+ return {
14023
+ stopReason,
14024
+ _meta: {
14025
+ quota: {
14026
+ token_count: {
14027
+ input_tokens: totalInputTokens,
14028
+ output_tokens: totalOutputTokens
14029
+ },
14030
+ model_usage: Array.from(modelUsageMap.entries()).map(
14031
+ ([modelName, counts]) => ({
14032
+ model: modelName,
14033
+ token_count: {
14034
+ input_tokens: counts.input,
14035
+ output_tokens: counts.output
14036
+ }
14037
+ })
14038
+ )
14039
+ }
14040
+ }
14041
+ };
14042
+ }
14043
+ if (toolCallRequests.length === 0) {
14044
+ break;
14045
+ }
14046
+ const toolResponseParts = [];
14047
+ for (const tReq of toolCallRequests) {
14048
+ const fc = {
14049
+ id: tReq.callId,
14050
+ name: tReq.name,
14051
+ args: tReq.args
14052
+ };
14053
+ const response = await this.runTool(pendingSend.signal, promptId, fc);
14054
+ toolResponseParts.push(...response);
14058
14055
  }
14056
+ currentParts = toolResponseParts;
14059
14057
  }
14060
14058
  const modelUsageArray = Array.from(modelUsageMap.entries()).map(
14061
14059
  ([modelName, counts]) => ({
@@ -14102,7 +14100,7 @@ ${thought.description}`;
14102
14100
  await this.connection.sessionUpdate(params);
14103
14101
  }
14104
14102
  async runTool(abortSignal, promptId, fc) {
14105
- const callId = fc.id ?? GeminiAgent.generateCallId(fc.name || "unknown");
14103
+ const callId = fc.id ?? this.generateCallId(fc.name || "unknown");
14106
14104
  const args = fc.args ?? {};
14107
14105
  const startTime = Date.now();
14108
14106
  const errorResponse = (error) => {
@@ -14394,7 +14392,7 @@ ${thought.description}`;
14394
14392
  let resolvedSuccessfully = false;
14395
14393
  let readDirectly = false;
14396
14394
  try {
14397
- const absolutePath = path13.resolve(
14395
+ const absolutePath = path12.resolve(
14398
14396
  this.context.config.getTargetDir(),
14399
14397
  pathName
14400
14398
  );
@@ -14470,7 +14468,7 @@ ${thought.description}`;
14470
14468
  }
14471
14469
  }
14472
14470
  if (!validationError) {
14473
- if ((path13.isAbsolute(pathName) || !isWithinRoot(
14471
+ if ((path12.isAbsolute(pathName) || !isWithinRoot(
14474
14472
  absolutePath,
14475
14473
  this.context.config.getTargetDir()
14476
14474
  )) && !readDirectly) {
@@ -14574,7 +14572,7 @@ ${contentToPush}`;
14574
14572
  const lines = globResult.llmContent.split("\n");
14575
14573
  if (lines.length > 1 && lines[1]) {
14576
14574
  const firstMatchAbsolute = lines[1].trim();
14577
- currentPathSpec = path13.relative(
14575
+ currentPathSpec = path12.relative(
14578
14576
  this.context.config.getTargetDir(),
14579
14577
  firstMatchAbsolute
14580
14578
  );
@@ -14656,7 +14654,7 @@ ${contentToPush}`;
14656
14654
  const toolArgs = {
14657
14655
  include: pathSpecsToRead
14658
14656
  };
14659
- const callId = GeminiAgent.generateCallId(readManyFilesTool.name);
14657
+ const callId = this.generateCallId(readManyFilesTool.name);
14660
14658
  try {
14661
14659
  const invocation = readManyFilesTool.build(toolArgs);
14662
14660
  await this.sendUpdate({
@@ -14734,321 +14732,524 @@ Content from @${filePathSpecInContent}:
14734
14732
  throw error;
14735
14733
  }
14736
14734
  }
14737
- if (directContents.length > 0) {
14738
- const hasReferenceStart = processedQueryParts.some(
14739
- (p) => "text" in p && typeof p.text === "string" && p.text.includes(REFERENCE_CONTENT_START)
14735
+ if (directContents.length > 0) {
14736
+ const hasReferenceStart = processedQueryParts.some(
14737
+ (p) => "text" in p && typeof p.text === "string" && p.text.includes(REFERENCE_CONTENT_START)
14738
+ );
14739
+ if (!hasReferenceStart) {
14740
+ processedQueryParts.push({
14741
+ text: `
14742
+ ${REFERENCE_CONTENT_START}`
14743
+ });
14744
+ }
14745
+ for (const item of directContents) {
14746
+ processedQueryParts.push({
14747
+ text: `
14748
+ Content from @${item.spec}:
14749
+ `
14750
+ });
14751
+ if (item.content) {
14752
+ processedQueryParts.push({ text: item.content });
14753
+ } else if (item.part) {
14754
+ processedQueryParts.push(item.part);
14755
+ }
14756
+ }
14757
+ }
14758
+ if (embeddedContext.length > 0) {
14759
+ processedQueryParts.push({
14760
+ text: "\n--- Content from referenced context ---"
14761
+ });
14762
+ for (const contextPart of embeddedContext) {
14763
+ processedQueryParts.push({
14764
+ text: `
14765
+ Content from @${contextPart.uri}:
14766
+ `
14767
+ });
14768
+ if ("text" in contextPart) {
14769
+ processedQueryParts.push({
14770
+ text: contextPart.text
14771
+ });
14772
+ } else {
14773
+ processedQueryParts.push({
14774
+ inlineData: {
14775
+ mimeType: contextPart.mimeType ?? "application/octet-stream",
14776
+ data: contextPart.blob
14777
+ }
14778
+ });
14779
+ }
14780
+ }
14781
+ }
14782
+ return processedQueryParts;
14783
+ }
14784
+ debug(msg) {
14785
+ if (this.context.config.getDebugMode()) {
14786
+ debugLogger.warn(msg);
14787
+ }
14788
+ }
14789
+ };
14790
+
14791
+ // packages/cli/src/acp/acpFileSystemService.ts
14792
+ import os5 from "node:os";
14793
+ import path13 from "node:path";
14794
+ var AcpFileSystemService = class {
14795
+ constructor(connection, sessionId, capabilities, fallback, root) {
14796
+ this.connection = connection;
14797
+ this.sessionId = sessionId;
14798
+ this.capabilities = capabilities;
14799
+ this.fallback = fallback;
14800
+ this.root = root;
14801
+ }
14802
+ geminiDir = path13.join(os5.homedir(), ".gemini");
14803
+ shouldUseFallback(filePath) {
14804
+ return !isWithinRoot(filePath, this.root) || isWithinRoot(filePath, this.geminiDir);
14805
+ }
14806
+ normalizeFileSystemError(err) {
14807
+ const errorMessage = err instanceof Error ? err.message : String(err);
14808
+ if (errorMessage.includes("Resource not found") || errorMessage.includes("ENOENT") || errorMessage.includes("does not exist") || errorMessage.includes("No such file")) {
14809
+ const newErr = new Error(errorMessage);
14810
+ newErr.code = "ENOENT";
14811
+ throw newErr;
14812
+ }
14813
+ throw err;
14814
+ }
14815
+ async readTextFile(filePath) {
14816
+ if (!this.capabilities.readTextFile || this.shouldUseFallback(filePath)) {
14817
+ return this.fallback.readTextFile(filePath);
14818
+ }
14819
+ try {
14820
+ const response = await this.connection.readTextFile({
14821
+ path: filePath,
14822
+ sessionId: this.sessionId
14823
+ });
14824
+ return response.content;
14825
+ } catch (err) {
14826
+ this.normalizeFileSystemError(err);
14827
+ }
14828
+ }
14829
+ async writeTextFile(filePath, content) {
14830
+ if (!this.capabilities.writeTextFile || this.shouldUseFallback(filePath)) {
14831
+ return this.fallback.writeTextFile(filePath, content);
14832
+ }
14833
+ try {
14834
+ await this.connection.writeTextFile({
14835
+ path: filePath,
14836
+ content,
14837
+ sessionId: this.sessionId
14838
+ });
14839
+ } catch (err) {
14840
+ this.normalizeFileSystemError(err);
14841
+ }
14842
+ }
14843
+ };
14844
+
14845
+ // packages/cli/src/acp/acpSessionManager.ts
14846
+ var AcpSessionManager = class {
14847
+ constructor(settings, argv, connection) {
14848
+ this.settings = settings;
14849
+ this.argv = argv;
14850
+ this.connection = connection;
14851
+ }
14852
+ sessions = /* @__PURE__ */ new Map();
14853
+ clientCapabilities;
14854
+ setClientCapabilities(capabilities) {
14855
+ this.clientCapabilities = capabilities;
14856
+ }
14857
+ getSession(sessionId) {
14858
+ return this.sessions.get(sessionId);
14859
+ }
14860
+ async newSession({ cwd, mcpServers }, authDetails) {
14861
+ const sessionId = randomUUID2();
14862
+ const loadedSettings = loadSettings(cwd);
14863
+ const config = await this.newSessionConfig(
14864
+ sessionId,
14865
+ cwd,
14866
+ mcpServers,
14867
+ loadedSettings
14868
+ );
14869
+ const authType = loadedSettings.merged.security.auth.selectedType || "gemini-api-key" /* USE_GEMINI */;
14870
+ let isAuthenticated = false;
14871
+ let authErrorMessage = "";
14872
+ try {
14873
+ await config.refreshAuth(
14874
+ authType,
14875
+ authDetails.apiKey,
14876
+ authDetails.baseUrl,
14877
+ authDetails.customHeaders
14878
+ );
14879
+ isAuthenticated = true;
14880
+ const contentGeneratorConfig = config.getContentGeneratorConfig();
14881
+ if (authType === "gemini-api-key" /* USE_GEMINI */ && (!contentGeneratorConfig || !contentGeneratorConfig.apiKey)) {
14882
+ isAuthenticated = false;
14883
+ authErrorMessage = "Gemini API key is missing or not configured.";
14884
+ }
14885
+ } catch (e) {
14886
+ isAuthenticated = false;
14887
+ authErrorMessage = getAcpErrorMessage(e);
14888
+ debugLogger.error(
14889
+ `Authentication failed: ${e instanceof Error ? e.stack : e}`
14890
+ );
14891
+ }
14892
+ if (!isAuthenticated) {
14893
+ throw new RequestError(
14894
+ -32e3,
14895
+ authErrorMessage || "Authentication required."
14896
+ );
14897
+ }
14898
+ if (this.clientCapabilities?.fs) {
14899
+ const acpFileSystemService = new AcpFileSystemService(
14900
+ this.connection,
14901
+ sessionId,
14902
+ this.clientCapabilities.fs,
14903
+ config.getFileSystemService(),
14904
+ cwd
14905
+ );
14906
+ config.setFileSystemService(acpFileSystemService);
14907
+ }
14908
+ await config.initialize();
14909
+ startupProfiler.flush(config);
14910
+ startAutoMemoryIfEnabled(config);
14911
+ const geminiClient = config.getGeminiClient();
14912
+ const chat = await geminiClient.startChat();
14913
+ const session = new Session(
14914
+ sessionId,
14915
+ chat,
14916
+ config,
14917
+ this.connection,
14918
+ this.settings
14919
+ );
14920
+ this.sessions.set(sessionId, session);
14921
+ setTimeout(() => {
14922
+ session.sendAvailableCommands();
14923
+ }, 0);
14924
+ const { availableModels, currentModelId } = buildAvailableModels(
14925
+ config,
14926
+ loadedSettings
14927
+ );
14928
+ const response = {
14929
+ sessionId,
14930
+ modes: {
14931
+ availableModes: buildAvailableModes(config.isPlanEnabled()),
14932
+ currentModeId: config.getApprovalMode()
14933
+ },
14934
+ models: {
14935
+ availableModels,
14936
+ currentModelId
14937
+ }
14938
+ };
14939
+ return response;
14940
+ }
14941
+ async loadSession({ sessionId, cwd, mcpServers }, authDetails) {
14942
+ const config = await this.initializeSessionConfig(
14943
+ sessionId,
14944
+ cwd,
14945
+ mcpServers,
14946
+ authDetails
14947
+ );
14948
+ const sessionSelector = new SessionSelector(config.storage);
14949
+ const { sessionData, sessionPath } = await sessionSelector.resolveSession(sessionId);
14950
+ const clientHistory = convertSessionToClientHistory(sessionData.messages);
14951
+ const geminiClient = config.getGeminiClient();
14952
+ await geminiClient.initialize();
14953
+ await geminiClient.resumeChat(clientHistory, {
14954
+ conversation: sessionData,
14955
+ filePath: sessionPath
14956
+ });
14957
+ const session = new Session(
14958
+ sessionId,
14959
+ geminiClient.getChat(),
14960
+ config,
14961
+ this.connection,
14962
+ this.settings
14963
+ );
14964
+ this.sessions.set(sessionId, session);
14965
+ session.streamHistory(sessionData.messages);
14966
+ setTimeout(() => {
14967
+ session.sendAvailableCommands();
14968
+ }, 0);
14969
+ const { availableModels, currentModelId } = buildAvailableModels(
14970
+ config,
14971
+ this.settings
14972
+ );
14973
+ const response = {
14974
+ modes: {
14975
+ availableModes: buildAvailableModes(config.isPlanEnabled()),
14976
+ currentModeId: config.getApprovalMode()
14977
+ },
14978
+ models: {
14979
+ availableModels,
14980
+ currentModelId
14981
+ }
14982
+ };
14983
+ return response;
14984
+ }
14985
+ async initializeSessionConfig(sessionId, cwd, mcpServers, authDetails) {
14986
+ const selectedAuthType = this.settings.merged.security.auth.selectedType;
14987
+ if (!selectedAuthType) {
14988
+ throw RequestError.authRequired();
14989
+ }
14990
+ const config = await this.newSessionConfig(sessionId, cwd, mcpServers);
14991
+ try {
14992
+ await config.refreshAuth(
14993
+ selectedAuthType,
14994
+ authDetails.apiKey,
14995
+ authDetails.baseUrl,
14996
+ authDetails.customHeaders
14997
+ );
14998
+ } catch (e) {
14999
+ debugLogger.error(`Authentication failed: ${e}`);
15000
+ throw RequestError.authRequired();
15001
+ }
15002
+ if (this.clientCapabilities?.fs) {
15003
+ const acpFileSystemService = new AcpFileSystemService(
15004
+ this.connection,
15005
+ sessionId,
15006
+ this.clientCapabilities.fs,
15007
+ config.getFileSystemService(),
15008
+ cwd
14740
15009
  );
14741
- if (!hasReferenceStart) {
14742
- processedQueryParts.push({
14743
- text: `
14744
- ${REFERENCE_CONTENT_START}`
14745
- });
14746
- }
14747
- for (const item of directContents) {
14748
- processedQueryParts.push({
14749
- text: `
14750
- Content from @${item.spec}:
14751
- `
14752
- });
14753
- if (item.content) {
14754
- processedQueryParts.push({ text: item.content });
14755
- } else if (item.part) {
14756
- processedQueryParts.push(item.part);
14757
- }
14758
- }
15010
+ config.setFileSystemService(acpFileSystemService);
14759
15011
  }
14760
- if (embeddedContext.length > 0) {
14761
- processedQueryParts.push({
14762
- text: "\n--- Content from referenced context ---"
14763
- });
14764
- for (const contextPart of embeddedContext) {
14765
- processedQueryParts.push({
14766
- text: `
14767
- Content from @${contextPart.uri}:
14768
- `
14769
- });
14770
- if ("text" in contextPart) {
14771
- processedQueryParts.push({
14772
- text: contextPart.text
14773
- });
14774
- } else {
14775
- processedQueryParts.push({
14776
- inlineData: {
14777
- mimeType: contextPart.mimeType ?? "application/octet-stream",
14778
- data: contextPart.blob
14779
- }
14780
- });
15012
+ await config.initialize();
15013
+ startupProfiler.flush(config);
15014
+ startAutoMemoryIfEnabled(config);
15015
+ return config;
15016
+ }
15017
+ async newSessionConfig(sessionId, cwd, mcpServers, loadedSettings) {
15018
+ const currentSettings = loadedSettings || this.settings;
15019
+ const mergedMcpServers = { ...currentSettings.merged.mcpServers };
15020
+ for (const server of mcpServers) {
15021
+ if ("type" in server && (server.type === "sse" || server.type === "http")) {
15022
+ const headers = Object.fromEntries(
15023
+ server.headers.map(({ name, value }) => [name, value])
15024
+ );
15025
+ mergedMcpServers[server.name] = new MCPServerConfig(
15026
+ void 0,
15027
+ // command
15028
+ void 0,
15029
+ // args
15030
+ void 0,
15031
+ // env
15032
+ void 0,
15033
+ // cwd
15034
+ server.type === "sse" ? server.url : void 0,
15035
+ // url (sse)
15036
+ server.type === "http" ? server.url : void 0,
15037
+ // httpUrl
15038
+ headers
15039
+ );
15040
+ } else if ("command" in server) {
15041
+ const env2 = {};
15042
+ for (const { name: envName, value } of server.env) {
15043
+ env2[envName] = value;
14781
15044
  }
15045
+ mergedMcpServers[server.name] = new MCPServerConfig(
15046
+ server.command,
15047
+ server.args,
15048
+ env2,
15049
+ cwd
15050
+ );
14782
15051
  }
14783
15052
  }
14784
- return processedQueryParts;
14785
- }
14786
- debug(msg) {
14787
- if (this.context.config.getDebugMode()) {
14788
- debugLogger.warn(msg);
14789
- }
15053
+ const settings = {
15054
+ ...currentSettings.merged,
15055
+ mcpServers: mergedMcpServers
15056
+ };
15057
+ const config = await loadCliConfig(settings, sessionId, this.argv, { cwd });
15058
+ createPolicyUpdater(
15059
+ config.getPolicyEngine(),
15060
+ config.messageBus,
15061
+ config.storage
15062
+ );
15063
+ return config;
14790
15064
  }
14791
15065
  };
14792
- function toToolCallContent(toolResult) {
14793
- if (toolResult.error?.message) {
14794
- throw new Error(toolResult.error.message);
15066
+
15067
+ // packages/cli/src/acp/acpRpcDispatcher.ts
15068
+ var GeminiAgent = class {
15069
+ constructor(context, settings, argv, connection) {
15070
+ this.context = context;
15071
+ this.settings = settings;
15072
+ this.sessionManager = new AcpSessionManager(settings, argv, connection);
14795
15073
  }
14796
- if (toolResult.returnDisplay) {
14797
- if (typeof toolResult.returnDisplay === "string") {
14798
- return {
14799
- type: "content",
14800
- content: { type: "text", text: toolResult.returnDisplay }
14801
- };
14802
- } else {
14803
- if ("fileName" in toolResult.returnDisplay) {
14804
- return {
14805
- type: "diff",
14806
- path: toolResult.returnDisplay.filePath ?? toolResult.returnDisplay.fileName,
14807
- oldText: toolResult.returnDisplay.originalContent,
14808
- newText: toolResult.returnDisplay.newContent,
14809
- _meta: {
14810
- kind: !toolResult.returnDisplay.originalContent ? "add" : toolResult.returnDisplay.newContent === "" ? "delete" : "modify"
14811
- }
14812
- };
14813
- }
14814
- return null;
15074
+ apiKey;
15075
+ baseUrl;
15076
+ customHeaders;
15077
+ sessionManager;
15078
+ async initialize(args) {
15079
+ if (args.clientCapabilities) {
15080
+ this.sessionManager.setClientCapabilities(args.clientCapabilities);
14815
15081
  }
14816
- } else {
14817
- return null;
14818
- }
14819
- }
14820
- var basicPermissionOptions = [
14821
- {
14822
- optionId: "proceed_once" /* ProceedOnce */,
14823
- name: "Allow",
14824
- kind: "allow_once"
14825
- },
14826
- {
14827
- optionId: "cancel" /* Cancel */,
14828
- name: "Reject",
14829
- kind: "reject_once"
14830
- }
14831
- ];
14832
- function toPermissionOptions(confirmation, config, enablePermanentToolApproval = false) {
14833
- const disableAlwaysAllow = config.getDisableAlwaysAllow();
14834
- const options = [];
14835
- if (!disableAlwaysAllow) {
14836
- switch (confirmation.type) {
14837
- case "edit":
14838
- options.push({
14839
- optionId: "proceed_always" /* ProceedAlways */,
14840
- name: "Allow for this session",
14841
- kind: "allow_always"
14842
- });
14843
- if (enablePermanentToolApproval) {
14844
- options.push({
14845
- optionId: "proceed_always_and_save" /* ProceedAlwaysAndSave */,
14846
- name: "Allow for this file in all future sessions",
14847
- kind: "allow_always"
14848
- });
14849
- }
14850
- break;
14851
- case "exec":
14852
- options.push({
14853
- optionId: "proceed_always" /* ProceedAlways */,
14854
- name: "Allow for this session",
14855
- kind: "allow_always"
14856
- });
14857
- if (enablePermanentToolApproval) {
14858
- options.push({
14859
- optionId: "proceed_always_and_save" /* ProceedAlwaysAndSave */,
14860
- name: "Allow this command for all future sessions",
14861
- kind: "allow_always"
14862
- });
15082
+ const authMethods = [
15083
+ {
15084
+ id: "oauth-personal" /* LOGIN_WITH_GOOGLE */,
15085
+ name: "Log in with Google",
15086
+ description: "Log in with your Google account"
15087
+ },
15088
+ {
15089
+ id: "gemini-api-key" /* USE_GEMINI */,
15090
+ name: "Gemini API key",
15091
+ description: "Use an API key with Gemini Developer API",
15092
+ _meta: {
15093
+ "api-key": {
15094
+ provider: "google"
15095
+ }
14863
15096
  }
14864
- break;
14865
- case "mcp":
14866
- options.push(
14867
- {
14868
- optionId: "proceed_always_server" /* ProceedAlwaysServer */,
14869
- name: "Allow all server tools for this session",
14870
- kind: "allow_always"
14871
- },
14872
- {
14873
- optionId: "proceed_always_tool" /* ProceedAlwaysTool */,
14874
- name: "Allow tool for this session",
14875
- kind: "allow_always"
15097
+ },
15098
+ {
15099
+ id: "vertex-ai" /* USE_VERTEX_AI */,
15100
+ name: "Vertex AI",
15101
+ description: "Use an API key with Vertex AI GenAI API"
15102
+ },
15103
+ {
15104
+ id: "gateway" /* GATEWAY */,
15105
+ name: "AI API Gateway",
15106
+ description: "Use a custom AI API Gateway",
15107
+ _meta: {
15108
+ gateway: {
15109
+ protocol: "google",
15110
+ restartRequired: "false"
14876
15111
  }
14877
- );
14878
- if (enablePermanentToolApproval) {
14879
- options.push({
14880
- optionId: "proceed_always_and_save" /* ProceedAlwaysAndSave */,
14881
- name: "Allow tool for all future sessions",
14882
- kind: "allow_always"
14883
- });
14884
15112
  }
14885
- break;
14886
- case "info":
14887
- options.push({
14888
- optionId: "proceed_always" /* ProceedAlways */,
14889
- name: "Allow for this session",
14890
- kind: "allow_always"
14891
- });
14892
- if (enablePermanentToolApproval) {
14893
- options.push({
14894
- optionId: "proceed_always_and_save" /* ProceedAlwaysAndSave */,
14895
- name: "Allow for all future sessions",
14896
- kind: "allow_always"
14897
- });
15113
+ }
15114
+ ];
15115
+ await this.context.config.initialize();
15116
+ const version = await getVersion();
15117
+ return {
15118
+ protocolVersion: PROTOCOL_VERSION,
15119
+ authMethods,
15120
+ agentInfo: {
15121
+ name: "gemini-cli",
15122
+ title: "Gemini CLI",
15123
+ version
15124
+ },
15125
+ agentCapabilities: {
15126
+ loadSession: true,
15127
+ promptCapabilities: {
15128
+ image: true,
15129
+ audio: true,
15130
+ embeddedContext: true
15131
+ },
15132
+ mcpCapabilities: {
15133
+ http: true,
15134
+ sse: true
14898
15135
  }
14899
- break;
14900
- case "ask_user":
14901
- case "exit_plan_mode":
14902
- break;
14903
- default:
14904
- break;
14905
- }
15136
+ }
15137
+ };
14906
15138
  }
14907
- options.push(...basicPermissionOptions);
14908
- switch (confirmation.type) {
14909
- case "edit":
14910
- case "exec":
14911
- case "mcp":
14912
- case "info":
14913
- case "ask_user":
14914
- case "exit_plan_mode":
14915
- case "sandbox_expansion":
14916
- break;
14917
- default: {
14918
- const unreachable = confirmation;
14919
- throw new Error(`Unexpected: ${unreachable}`);
15139
+ async authenticate(req) {
15140
+ const { methodId } = req;
15141
+ const method = external_exports.nativeEnum(AuthType).parse(methodId);
15142
+ const selectedAuthType = this.settings.merged.security.auth.selectedType;
15143
+ if (selectedAuthType && selectedAuthType !== method) {
15144
+ await clearCachedCredentialFile();
14920
15145
  }
14921
- }
14922
- return options;
14923
- }
14924
- function toAcpToolKind(kind) {
14925
- switch (kind) {
14926
- case "read" /* Read */:
14927
- case "edit" /* Edit */:
14928
- case "execute" /* Execute */:
14929
- case "search" /* Search */:
14930
- case "delete" /* Delete */:
14931
- case "move" /* Move */:
14932
- case "think" /* Think */:
14933
- case "fetch" /* Fetch */:
14934
- case "switch_mode" /* SwitchMode */:
14935
- case "other" /* Other */:
14936
- return kind;
14937
- case "agent" /* Agent */:
14938
- return "think";
14939
- case "plan" /* Plan */:
14940
- case "communicate" /* Communicate */:
14941
- default:
14942
- return "other";
14943
- }
14944
- }
14945
- function buildAvailableModes(isPlanEnabled) {
14946
- const modes = [
14947
- {
14948
- id: "default" /* DEFAULT */,
14949
- name: "Default",
14950
- description: "Prompts for approval"
14951
- },
14952
- {
14953
- id: "autoEdit" /* AUTO_EDIT */,
14954
- name: "Auto Edit",
14955
- description: "Auto-approves edit tools"
14956
- },
14957
- {
14958
- id: "yolo" /* YOLO */,
14959
- name: "YOLO",
14960
- description: "Auto-approves all tools"
15146
+ const meta = hasMeta(req) ? req._meta : void 0;
15147
+ const apiKey = typeof meta?.["api-key"] === "string" ? meta["api-key"] : void 0;
15148
+ try {
15149
+ if (apiKey) {
15150
+ this.apiKey = apiKey;
15151
+ }
15152
+ const gatewaySchema = external_exports.object({
15153
+ baseUrl: external_exports.string().optional(),
15154
+ headers: external_exports.record(external_exports.string()).optional()
15155
+ });
15156
+ let baseUrl;
15157
+ let headers;
15158
+ if (meta?.["gateway"]) {
15159
+ const result = gatewaySchema.safeParse(meta["gateway"]);
15160
+ if (result.success) {
15161
+ baseUrl = result.data.baseUrl;
15162
+ headers = result.data.headers;
15163
+ } else {
15164
+ throw new RequestError(
15165
+ -32602,
15166
+ `Malformed gateway payload: ${result.error.message}`
15167
+ );
15168
+ }
15169
+ }
15170
+ this.baseUrl = baseUrl;
15171
+ this.customHeaders = headers;
15172
+ await this.context.config.refreshAuth(
15173
+ method,
15174
+ apiKey ?? this.apiKey,
15175
+ baseUrl,
15176
+ headers
15177
+ );
15178
+ } catch (e) {
15179
+ throw new RequestError(-32e3, getAcpErrorMessage(e));
14961
15180
  }
14962
- ];
14963
- if (isPlanEnabled) {
14964
- modes.push({
14965
- id: "plan" /* PLAN */,
14966
- name: "Plan",
14967
- description: "Read-only mode"
14968
- });
15181
+ this.settings.setValue(
15182
+ "User" /* User */,
15183
+ "security.auth.selectedType",
15184
+ method
15185
+ );
14969
15186
  }
14970
- return modes;
14971
- }
14972
- function buildAvailableModels(config, settings) {
14973
- const preferredModel = config.getModel() || DEFAULT_GEMINI_MODEL_AUTO;
14974
- const shouldShowPreviewModels = config.getHasAccessToPreviewModel();
14975
- const useGemini31 = config.getGemini31LaunchedSync?.() ?? false;
14976
- const useGemini31FlashLite = config.getGemini31FlashLiteLaunchedSync?.() ?? false;
14977
- const selectedAuthType = settings.merged.security.auth.selectedType;
14978
- const useCustomToolModel = useGemini31 && selectedAuthType === "gemini-api-key" /* USE_GEMINI */;
14979
- if (config.getExperimentalDynamicModelConfiguration?.() === true && config.getModelConfigService) {
14980
- const options = config.getModelConfigService().getAvailableModelOptions({
14981
- useGemini3_1: useGemini31,
14982
- useGemini3_1FlashLite: useGemini31FlashLite,
14983
- useCustomTools: useCustomToolModel,
14984
- hasAccessToPreview: shouldShowPreviewModels
14985
- });
15187
+ getAuthDetails() {
14986
15188
  return {
14987
- availableModels: options,
14988
- currentModelId: preferredModel
15189
+ apiKey: this.apiKey,
15190
+ baseUrl: this.baseUrl,
15191
+ customHeaders: this.customHeaders
14989
15192
  };
14990
15193
  }
14991
- const mainOptions = [
14992
- {
14993
- value: DEFAULT_GEMINI_MODEL_AUTO,
14994
- title: getDisplayString(DEFAULT_GEMINI_MODEL_AUTO),
14995
- description: "Let Gemini CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash"
15194
+ async newSession(params) {
15195
+ return this.sessionManager.newSession(params, this.getAuthDetails());
15196
+ }
15197
+ async loadSession(params) {
15198
+ return this.sessionManager.loadSession(params, this.getAuthDetails());
15199
+ }
15200
+ async cancel(params) {
15201
+ const session = this.sessionManager.getSession(params.sessionId);
15202
+ if (!session) {
15203
+ throw new RequestError(
15204
+ -32602,
15205
+ `Session not found: ${params.sessionId}`
15206
+ );
14996
15207
  }
14997
- ];
14998
- if (shouldShowPreviewModels) {
14999
- mainOptions.unshift({
15000
- value: PREVIEW_GEMINI_MODEL_AUTO,
15001
- title: getDisplayString(PREVIEW_GEMINI_MODEL_AUTO),
15002
- description: useGemini31 ? "Let Gemini CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash" : "Let Gemini CLI decide the best model for the task: gemini-3-pro, gemini-3-flash"
15003
- });
15208
+ await session.cancelPendingPrompt();
15004
15209
  }
15005
- const manualOptions = [
15006
- {
15007
- value: DEFAULT_GEMINI_MODEL,
15008
- title: getDisplayString(DEFAULT_GEMINI_MODEL)
15009
- },
15010
- {
15011
- value: DEFAULT_GEMINI_FLASH_MODEL,
15012
- title: getDisplayString(DEFAULT_GEMINI_FLASH_MODEL)
15013
- },
15014
- {
15015
- value: DEFAULT_GEMINI_FLASH_LITE_MODEL,
15016
- title: getDisplayString(DEFAULT_GEMINI_FLASH_LITE_MODEL)
15210
+ async prompt(params) {
15211
+ const session = this.sessionManager.getSession(params.sessionId);
15212
+ if (!session) {
15213
+ throw new RequestError(
15214
+ -32602,
15215
+ `Session not found: ${params.sessionId}`
15216
+ );
15017
15217
  }
15018
- ];
15019
- if (shouldShowPreviewModels) {
15020
- const previewProModel = useGemini31 ? PREVIEW_GEMINI_3_1_MODEL : PREVIEW_GEMINI_MODEL;
15021
- const previewProValue = useCustomToolModel ? PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL : previewProModel;
15022
- const previewOptions = [
15023
- {
15024
- value: previewProValue,
15025
- title: getDisplayString(previewProModel)
15026
- },
15027
- {
15028
- value: PREVIEW_GEMINI_FLASH_MODEL,
15029
- title: getDisplayString(PREVIEW_GEMINI_FLASH_MODEL)
15030
- }
15031
- ];
15032
- if (useGemini31FlashLite) {
15033
- previewOptions.push({
15034
- value: PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL,
15035
- title: getDisplayString(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL)
15036
- });
15218
+ return session.prompt(params);
15219
+ }
15220
+ async setSessionMode(params) {
15221
+ const session = this.sessionManager.getSession(params.sessionId);
15222
+ if (!session) {
15223
+ throw new RequestError(
15224
+ -32602,
15225
+ `Session not found: ${params.sessionId}`
15226
+ );
15037
15227
  }
15038
- manualOptions.unshift(...previewOptions);
15228
+ return session.setMode(params.modeId);
15039
15229
  }
15040
- const scaleOptions = (options) => options.map((o) => ({
15041
- modelId: o.value,
15042
- name: o.title,
15043
- description: o.description
15044
- }));
15045
- return {
15046
- availableModels: [
15047
- ...scaleOptions(mainOptions),
15048
- ...scaleOptions(manualOptions)
15049
- ],
15050
- currentModelId: preferredModel
15051
- };
15230
+ async unstable_setSessionModel(params) {
15231
+ const session = this.sessionManager.getSession(params.sessionId);
15232
+ if (!session) {
15233
+ throw new RequestError(
15234
+ -32602,
15235
+ `Session not found: ${params.sessionId}`
15236
+ );
15237
+ }
15238
+ return session.setModel(params.modelId);
15239
+ }
15240
+ };
15241
+
15242
+ // packages/cli/src/acp/acpStdioTransport.ts
15243
+ async function runAcpClient(config, settings, argv) {
15244
+ const { stdout: workingStdout } = createWorkingStdio();
15245
+ const stdout = Writable.toWeb(workingStdout);
15246
+ const stdin = Readable.toWeb(process.stdin);
15247
+ const stream = ndJsonStream(stdout, stdin);
15248
+ const connection = new AgentSideConnection(
15249
+ (connection2) => new GeminiAgent(config, settings, argv, connection2),
15250
+ stream
15251
+ );
15252
+ await connection.closed.finally(runExitCleanup);
15052
15253
  }
15053
15254
 
15054
15255
  // packages/cli/src/validateNonInterActiveAuth.ts
@@ -15410,7 +15611,7 @@ function getNodeMemoryArgs(isDebugMode2) {
15410
15611
  `Current heap size ${currentMaxOldSpaceSizeMb.toFixed(2)} MB`
15411
15612
  );
15412
15613
  }
15413
- if (process.env["GEMINI_CLI_NO_RELAUNCH"]) {
15614
+ if (process.env["IS_BINARY"] === "true" || process.env["GEMINI_CLI_NO_RELAUNCH"] || process.env["SANDBOX"]) {
15414
15615
  return [];
15415
15616
  }
15416
15617
  const args = [];
@@ -15495,7 +15696,7 @@ async function resolveSessionId(resumeArg, sessionIdArg) {
15495
15696
  }
15496
15697
  }
15497
15698
  async function startInteractiveUI(config, settings, startupWarnings, workspaceRoot = process.cwd(), resumedSessionData, initializationResult) {
15498
- const { startInteractiveUI: doStartUI } = await import("./interactiveCli-JOX7MFFH.js");
15699
+ const { startInteractiveUI: doStartUI } = await import("./interactiveCli-ZS4ZQWNV.js");
15499
15700
  await doStartUI(
15500
15701
  config,
15501
15702
  settings,
@@ -15506,12 +15707,13 @@ async function startInteractiveUI(config, settings, startupWarnings, workspaceRo
15506
15707
  );
15507
15708
  }
15508
15709
  async function main() {
15710
+ let config;
15509
15711
  const cliStartupHandle = startupProfiler.start("cli_startup");
15510
15712
  const adminControlsListner = setupAdminControlsListener();
15511
15713
  registerCleanup(adminControlsListner.cleanup);
15512
15714
  const cleanupStdio = patchStdio();
15513
15715
  registerSyncCleanup(() => {
15514
- initializeOutputListenersAndFlush();
15716
+ initializeOutputListenersAndFlush(config);
15515
15717
  cleanupStdio();
15516
15718
  });
15517
15719
  setupUnhandledRejectionHandler();
@@ -15606,7 +15808,8 @@ async function main() {
15606
15808
  }
15607
15809
  }
15608
15810
  const partialConfig = await loadCliConfig(settings.merged, sessionId, argv, {
15609
- projectHooks: settings.workspace.settings.hooks
15811
+ projectHooks: settings.workspace.settings.hooks,
15812
+ skipExtensions: true
15610
15813
  });
15611
15814
  adminControlsListner.setConfig(partialConfig);
15612
15815
  let initialAuthFailed = false;
@@ -15691,7 +15894,7 @@ ${finalArgs[promptIndex + 1]}`;
15691
15894
  }
15692
15895
  {
15693
15896
  const loadConfigHandle = startupProfiler.start("load_cli_config");
15694
- const config = await loadCliConfig(settings.merged, sessionId, argv, {
15897
+ config = await loadCliConfig(settings.merged, sessionId, argv, {
15695
15898
  projectHooks: settings.workspace.settings.hooks,
15696
15899
  worktreeSettings: worktreeInfo
15697
15900
  });
@@ -15699,7 +15902,7 @@ ${finalArgs[promptIndex + 1]}`;
15699
15902
  await config.storage.initialize();
15700
15903
  adminControlsListner.setConfig(config);
15701
15904
  if (config.isInteractive() && settings.merged.general.devtools) {
15702
- const { setupInitialActivityLogger } = await import("./devtoolsService-QXOHXSMJ.js");
15905
+ const { setupInitialActivityLogger } = await import("./devtoolsService-DFWZ34A5.js");
15703
15906
  setupInitialActivityLogger(config);
15704
15907
  }
15705
15908
  registerTelemetryConfig(config);
@@ -15758,7 +15961,7 @@ ${finalArgs[promptIndex + 1]}`;
15758
15961
  const initAppHandle = startupProfiler.start("initialize_app");
15759
15962
  const initializationResult = await initializeApp(config, settings);
15760
15963
  initAppHandle?.end();
15761
- import("./liteRtServerManager-VGYEHFUE.js").then(({ LiteRtServerManager }) => {
15964
+ import("./liteRtServerManager-IDNLXYHP.js").then(({ LiteRtServerManager }) => {
15762
15965
  const mergedGemma = settings.merged.experimental?.gemmaModelRouter;
15763
15966
  if (!mergedGemma) return;
15764
15967
  const userGemma = settings.forScope("User" /* User */).settings.experimental?.gemmaModelRouter;
@@ -15865,7 +16068,7 @@ ${input}` : wrappedContext;
15865
16068
  if (config.getDebugMode()) {
15866
16069
  debugLogger.log("Session ID: %s", sessionId);
15867
16070
  }
15868
- initializeOutputListenersAndFlush();
16071
+ initializeOutputListenersAndFlush(config);
15869
16072
  await runNonInteractive2({
15870
16073
  config,
15871
16074
  settings,
@@ -15877,7 +16080,7 @@ ${input}` : wrappedContext;
15877
16080
  process.exit(ExitCodes.SUCCESS);
15878
16081
  }
15879
16082
  }
15880
- function initializeOutputListenersAndFlush() {
16083
+ function initializeOutputListenersAndFlush(config) {
15881
16084
  if (coreEvents.listenerCount("output" /* Output */) === 0) {
15882
16085
  coreEvents.on("output" /* Output */, (payload) => {
15883
16086
  if (payload.isStderr) {
@@ -15886,22 +16089,38 @@ function initializeOutputListenersAndFlush() {
15886
16089
  writeToStdout(payload.chunk, payload.encoding);
15887
16090
  }
15888
16091
  });
15889
- if (coreEvents.listenerCount("console-log" /* ConsoleLog */) === 0) {
15890
- coreEvents.on("console-log" /* ConsoleLog */, (payload) => {
15891
- if (payload.type === "error" || payload.type === "warn") {
15892
- writeToStderr(payload.content + "\n");
15893
- } else {
15894
- writeToStderr(payload.content + "\n");
16092
+ }
16093
+ if (coreEvents.listenerCount("console-log" /* ConsoleLog */) === 0) {
16094
+ coreEvents.on("console-log" /* ConsoleLog */, (payload) => {
16095
+ if (payload.type === "error" || payload.type === "warn") {
16096
+ writeToStderr(payload.content + "\n");
16097
+ } else {
16098
+ writeToStderr(payload.content + "\n");
16099
+ }
16100
+ });
16101
+ }
16102
+ if (coreEvents.listenerCount("user-feedback" /* UserFeedback */) === 0) {
16103
+ coreEvents.on("user-feedback" /* UserFeedback */, (payload) => {
16104
+ writeToStderr(payload.message + "\n");
16105
+ });
16106
+ }
16107
+ const outputFormat = config?.getOutputFormat();
16108
+ const forceToStderr = outputFormat === "json" || config === void 0;
16109
+ coreEvents.drainBacklogs(
16110
+ (event, args) => {
16111
+ if (forceToStderr && event === "output" /* Output */) {
16112
+ const payload = args[0];
16113
+ if (!payload.isStderr) {
16114
+ return {
16115
+ event,
16116
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
16117
+ args: [{ ...payload, isStderr: true }]
16118
+ };
15895
16119
  }
15896
- });
15897
- }
15898
- if (coreEvents.listenerCount("user-feedback" /* UserFeedback */) === 0) {
15899
- coreEvents.on("user-feedback" /* UserFeedback */, (payload) => {
15900
- writeToStderr(payload.message + "\n");
15901
- });
16120
+ }
16121
+ return { event, args };
15902
16122
  }
15903
- }
15904
- coreEvents.drainBacklogs();
16123
+ );
15905
16124
  }
15906
16125
  function setupAdminControlsListener() {
15907
16126
  let pendingSettings;