@google/gemini-cli-a2a-server 0.19.0-preview.0 → 0.20.0-nightly.20251127.5bed97064

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.
@@ -307803,8 +307803,8 @@ var Float64Vector = import_vector.default.Float64Vector;
307803
307803
  var PointerVector = import_vector.default.PointerVector;
307804
307804
 
307805
307805
  // packages/core/dist/src/generated/git-commit.js
307806
- var GIT_COMMIT_INFO = "d2a6cff4d";
307807
- var CLI_VERSION = "0.19.0-preview.0";
307806
+ var GIT_COMMIT_INFO = "5bed97064";
307807
+ var CLI_VERSION = "0.20.0-nightly.20251127.5bed97064";
307808
307808
 
307809
307809
  // packages/core/dist/src/ide/detect-ide.js
307810
307810
  var IDE_DEFINITIONS = {
@@ -310731,7 +310731,7 @@ async function createContentGenerator(config3, gcConfig, sessionId2) {
310731
310731
  if (gcConfig.fakeResponses) {
310732
310732
  return FakeContentGenerator.fromFile(gcConfig.fakeResponses);
310733
310733
  }
310734
- const version4 = "0.19.0-preview.0";
310734
+ const version4 = "0.20.0-nightly.20251127.5bed97064";
310735
310735
  const customHeadersEnv = process.env["GEMINI_CLI_CUSTOM_HEADERS"] || void 0;
310736
310736
  const userAgent = `GeminiCLI/${version4} (${process.platform}; ${process.arch})`;
310737
310737
  const customHeadersMap = parseCustomHeaders(customHeadersEnv);
@@ -355301,6 +355301,11 @@ var ShellToolInvocation = class extends BaseToolInvocation {
355301
355301
  const isWindows5 = os16.platform() === "win32";
355302
355302
  const tempFileName = `shell_pgrep_${crypto20.randomBytes(6).toString("hex")}.tmp`;
355303
355303
  const tempFilePath = path43.join(os16.tmpdir(), tempFileName);
355304
+ const timeoutMs = this.config.getShellToolInactivityTimeout();
355305
+ const timeoutController = new AbortController();
355306
+ let timeoutTimer;
355307
+ const combinedController = new AbortController();
355308
+ const onAbort = () => combinedController.abort();
355304
355309
  try {
355305
355310
  const commandToExecute = isWindows5 ? strippedCommand : (() => {
355306
355311
  let command = strippedCommand.trim();
@@ -355312,7 +355317,23 @@ var ShellToolInvocation = class extends BaseToolInvocation {
355312
355317
  let cumulativeOutput = "";
355313
355318
  let lastUpdateTime = Date.now();
355314
355319
  let isBinaryStream = false;
355320
+ const resetTimeout = () => {
355321
+ if (timeoutMs <= 0) {
355322
+ return;
355323
+ }
355324
+ if (timeoutTimer)
355325
+ clearTimeout(timeoutTimer);
355326
+ timeoutTimer = setTimeout(() => {
355327
+ timeoutController.abort();
355328
+ }, timeoutMs);
355329
+ };
355330
+ signal.addEventListener("abort", onAbort, { once: true });
355331
+ timeoutController.signal.addEventListener("abort", onAbort, {
355332
+ once: true
355333
+ });
355334
+ resetTimeout();
355315
355335
  const { result: resultPromise, pid } = await ShellExecutionService.execute(commandToExecute, cwd, (event) => {
355336
+ resetTimeout();
355316
355337
  if (!updateOutput) {
355317
355338
  return;
355318
355339
  }
@@ -355344,7 +355365,7 @@ var ShellToolInvocation = class extends BaseToolInvocation {
355344
355365
  updateOutput(cumulativeOutput);
355345
355366
  lastUpdateTime = Date.now();
355346
355367
  }
355347
- }, signal, this.config.getEnableInteractiveShell(), shellExecutionConfig ?? {});
355368
+ }, combinedController.signal, this.config.getEnableInteractiveShell(), shellExecutionConfig ?? {});
355348
355369
  if (pid && setPidCallback) {
355349
355370
  setPidCallback(pid);
355350
355371
  }
@@ -355369,8 +355390,14 @@ var ShellToolInvocation = class extends BaseToolInvocation {
355369
355390
  }
355370
355391
  }
355371
355392
  let llmContent = "";
355393
+ let timeoutMessage = "";
355372
355394
  if (result.aborted) {
355373
- llmContent = "Command was cancelled by user before it could complete.";
355395
+ if (timeoutController.signal.aborted) {
355396
+ timeoutMessage = `Command was automatically cancelled because it exceeded the timeout of ${(timeoutMs / 6e4).toFixed(1)} minutes without output.`;
355397
+ llmContent = timeoutMessage;
355398
+ } else {
355399
+ llmContent = "Command was cancelled by user before it could complete.";
355400
+ }
355374
355401
  if (result.output.trim()) {
355375
355402
  llmContent += ` Below is the output before it was cancelled:
355376
355403
  ${result.output}`;
@@ -355399,7 +355426,11 @@ ${result.output}`;
355399
355426
  returnDisplayMessage = result.output;
355400
355427
  } else {
355401
355428
  if (result.aborted) {
355402
- returnDisplayMessage = "Command cancelled by user.";
355429
+ if (timeoutMessage) {
355430
+ returnDisplayMessage = timeoutMessage;
355431
+ } else {
355432
+ returnDisplayMessage = "Command cancelled by user.";
355433
+ }
355403
355434
  } else if (result.signal) {
355404
355435
  returnDisplayMessage = `Command terminated by signal: ${result.signal}`;
355405
355436
  } else if (result.error) {
@@ -355430,6 +355461,10 @@ ${result.output}`;
355430
355461
  ...executionError
355431
355462
  };
355432
355463
  } finally {
355464
+ if (timeoutTimer)
355465
+ clearTimeout(timeoutTimer);
355466
+ signal.removeEventListener("abort", onAbort);
355467
+ timeoutController.signal.removeEventListener("abort", onAbort);
355433
355468
  if (fs41.existsSync(tempFilePath)) {
355434
355469
  fs41.unlinkSync(tempFilePath);
355435
355470
  }
@@ -361453,6 +361488,580 @@ function getResponseTextFromParts(parts2) {
361453
361488
  import * as fs44 from "node:fs/promises";
361454
361489
  import * as path46 from "node:path";
361455
361490
  var import_fast_levenshtein = __toESM(require_levenshtein(), 1);
361491
+
361492
+ // packages/core/dist/src/hooks/hookTranslator.js
361493
+ var HookTranslator = class {
361494
+ };
361495
+ function hasTextProperty(value) {
361496
+ return typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
361497
+ }
361498
+ function isContentWithParts(content) {
361499
+ return typeof content === "object" && content !== null && "role" in content && "parts" in content;
361500
+ }
361501
+ function extractGenerationConfig(request3) {
361502
+ if (request3.config && typeof request3.config === "object") {
361503
+ const config3 = request3.config;
361504
+ return {
361505
+ temperature: config3.temperature,
361506
+ maxOutputTokens: config3.maxOutputTokens,
361507
+ topP: config3.topP,
361508
+ topK: config3.topK
361509
+ };
361510
+ }
361511
+ return void 0;
361512
+ }
361513
+ var HookTranslatorGenAIv1 = class extends HookTranslator {
361514
+ /**
361515
+ * Convert genai SDK GenerateContentParameters to stable LLMRequest
361516
+ *
361517
+ * Note: This implementation intentionally extracts only text content from parts.
361518
+ * Non-text parts (images, function calls, etc.) are filtered out in v1 to provide
361519
+ * a simplified, stable interface for hooks. This allows hooks to focus on text
361520
+ * manipulation without needing to handle complex multimodal content.
361521
+ * Future versions may expose additional content types if needed.
361522
+ */
361523
+ toHookLLMRequest(sdkRequest) {
361524
+ const messages = [];
361525
+ if (sdkRequest.contents) {
361526
+ const contents = Array.isArray(sdkRequest.contents) ? sdkRequest.contents : [sdkRequest.contents];
361527
+ for (const content of contents) {
361528
+ if (typeof content === "string") {
361529
+ messages.push({
361530
+ role: "user",
361531
+ content
361532
+ });
361533
+ } else if (isContentWithParts(content)) {
361534
+ const role = content.role === "model" ? "model" : content.role === "system" ? "system" : "user";
361535
+ const parts2 = Array.isArray(content.parts) ? content.parts : [content.parts];
361536
+ const textContent2 = parts2.filter(hasTextProperty).map((part) => part.text).join("");
361537
+ if (textContent2) {
361538
+ messages.push({
361539
+ role,
361540
+ content: textContent2
361541
+ });
361542
+ }
361543
+ }
361544
+ }
361545
+ }
361546
+ const config3 = extractGenerationConfig(sdkRequest);
361547
+ return {
361548
+ model: sdkRequest.model || DEFAULT_GEMINI_FLASH_MODEL,
361549
+ messages,
361550
+ config: {
361551
+ temperature: config3?.temperature,
361552
+ maxOutputTokens: config3?.maxOutputTokens,
361553
+ topP: config3?.topP,
361554
+ topK: config3?.topK
361555
+ }
361556
+ };
361557
+ }
361558
+ /**
361559
+ * Convert stable LLMRequest to genai SDK GenerateContentParameters
361560
+ */
361561
+ fromHookLLMRequest(hookRequest, baseRequest) {
361562
+ const contents = hookRequest.messages.map((message) => ({
361563
+ role: message.role === "model" ? "model" : message.role,
361564
+ parts: [
361565
+ {
361566
+ text: typeof message.content === "string" ? message.content : String(message.content)
361567
+ }
361568
+ ]
361569
+ }));
361570
+ const result = {
361571
+ ...baseRequest,
361572
+ model: hookRequest.model,
361573
+ contents
361574
+ };
361575
+ if (hookRequest.config) {
361576
+ const baseConfig = baseRequest ? extractGenerationConfig(baseRequest) : void 0;
361577
+ result.config = {
361578
+ ...baseConfig,
361579
+ temperature: hookRequest.config.temperature,
361580
+ maxOutputTokens: hookRequest.config.maxOutputTokens,
361581
+ topP: hookRequest.config.topP,
361582
+ topK: hookRequest.config.topK
361583
+ };
361584
+ }
361585
+ return result;
361586
+ }
361587
+ /**
361588
+ * Convert genai SDK GenerateContentResponse to stable LLMResponse
361589
+ */
361590
+ toHookLLMResponse(sdkResponse) {
361591
+ return {
361592
+ text: sdkResponse.text,
361593
+ candidates: (sdkResponse.candidates || []).map((candidate) => {
361594
+ const textParts = candidate.content?.parts?.filter(hasTextProperty).map((part) => part.text) || [];
361595
+ return {
361596
+ content: {
361597
+ role: "model",
361598
+ parts: textParts
361599
+ },
361600
+ finishReason: candidate.finishReason,
361601
+ index: candidate.index,
361602
+ safetyRatings: candidate.safetyRatings?.map((rating) => ({
361603
+ category: String(rating.category || ""),
361604
+ probability: String(rating.probability || "")
361605
+ }))
361606
+ };
361607
+ }),
361608
+ usageMetadata: sdkResponse.usageMetadata ? {
361609
+ promptTokenCount: sdkResponse.usageMetadata.promptTokenCount,
361610
+ candidatesTokenCount: sdkResponse.usageMetadata.candidatesTokenCount,
361611
+ totalTokenCount: sdkResponse.usageMetadata.totalTokenCount
361612
+ } : void 0
361613
+ };
361614
+ }
361615
+ /**
361616
+ * Convert stable LLMResponse to genai SDK GenerateContentResponse
361617
+ */
361618
+ fromHookLLMResponse(hookResponse) {
361619
+ const response = {
361620
+ text: hookResponse.text,
361621
+ candidates: hookResponse.candidates.map((candidate) => ({
361622
+ content: {
361623
+ role: "model",
361624
+ parts: candidate.content.parts.map((part) => ({
361625
+ text: part
361626
+ }))
361627
+ },
361628
+ finishReason: candidate.finishReason,
361629
+ index: candidate.index,
361630
+ safetyRatings: candidate.safetyRatings
361631
+ })),
361632
+ usageMetadata: hookResponse.usageMetadata
361633
+ };
361634
+ return response;
361635
+ }
361636
+ /**
361637
+ * Convert genai SDK ToolConfig to stable HookToolConfig
361638
+ */
361639
+ toHookToolConfig(sdkToolConfig) {
361640
+ return {
361641
+ mode: sdkToolConfig.functionCallingConfig?.mode,
361642
+ allowedFunctionNames: sdkToolConfig.functionCallingConfig?.allowedFunctionNames
361643
+ };
361644
+ }
361645
+ /**
361646
+ * Convert stable HookToolConfig to genai SDK ToolConfig
361647
+ */
361648
+ fromHookToolConfig(hookToolConfig) {
361649
+ const functionCallingConfig = hookToolConfig.mode || hookToolConfig.allowedFunctionNames ? {
361650
+ mode: hookToolConfig.mode,
361651
+ allowedFunctionNames: hookToolConfig.allowedFunctionNames
361652
+ } : void 0;
361653
+ return {
361654
+ functionCallingConfig
361655
+ };
361656
+ }
361657
+ };
361658
+ var defaultHookTranslator = new HookTranslatorGenAIv1();
361659
+
361660
+ // packages/core/dist/src/hooks/types.js
361661
+ var HookEventName;
361662
+ (function(HookEventName2) {
361663
+ HookEventName2["BeforeTool"] = "BeforeTool";
361664
+ HookEventName2["AfterTool"] = "AfterTool";
361665
+ HookEventName2["BeforeAgent"] = "BeforeAgent";
361666
+ HookEventName2["Notification"] = "Notification";
361667
+ HookEventName2["AfterAgent"] = "AfterAgent";
361668
+ HookEventName2["SessionStart"] = "SessionStart";
361669
+ HookEventName2["SessionEnd"] = "SessionEnd";
361670
+ HookEventName2["PreCompress"] = "PreCompress";
361671
+ HookEventName2["BeforeModel"] = "BeforeModel";
361672
+ HookEventName2["AfterModel"] = "AfterModel";
361673
+ HookEventName2["BeforeToolSelection"] = "BeforeToolSelection";
361674
+ })(HookEventName || (HookEventName = {}));
361675
+ var HookType;
361676
+ (function(HookType2) {
361677
+ HookType2["Command"] = "command";
361678
+ })(HookType || (HookType = {}));
361679
+ function createHookOutput(eventName, data) {
361680
+ switch (eventName) {
361681
+ case "BeforeModel":
361682
+ return new BeforeModelHookOutput(data);
361683
+ case "AfterModel":
361684
+ return new AfterModelHookOutput(data);
361685
+ case "BeforeToolSelection":
361686
+ return new BeforeToolSelectionHookOutput(data);
361687
+ default:
361688
+ return new DefaultHookOutput(data);
361689
+ }
361690
+ }
361691
+ var DefaultHookOutput = class {
361692
+ continue;
361693
+ stopReason;
361694
+ suppressOutput;
361695
+ systemMessage;
361696
+ decision;
361697
+ reason;
361698
+ hookSpecificOutput;
361699
+ constructor(data = {}) {
361700
+ this.continue = data.continue;
361701
+ this.stopReason = data.stopReason;
361702
+ this.suppressOutput = data.suppressOutput;
361703
+ this.systemMessage = data.systemMessage;
361704
+ this.decision = data.decision;
361705
+ this.reason = data.reason;
361706
+ this.hookSpecificOutput = data.hookSpecificOutput;
361707
+ }
361708
+ /**
361709
+ * Check if this output represents a blocking decision
361710
+ */
361711
+ isBlockingDecision() {
361712
+ return this.decision === "block" || this.decision === "deny";
361713
+ }
361714
+ /**
361715
+ * Check if this output requests to stop execution
361716
+ */
361717
+ shouldStopExecution() {
361718
+ return this.continue === false;
361719
+ }
361720
+ /**
361721
+ * Get the effective reason for blocking or stopping
361722
+ */
361723
+ getEffectiveReason() {
361724
+ return this.reason || this.stopReason || "No reason provided";
361725
+ }
361726
+ /**
361727
+ * Apply LLM request modifications (specific method for BeforeModel hooks)
361728
+ */
361729
+ applyLLMRequestModifications(target) {
361730
+ return target;
361731
+ }
361732
+ /**
361733
+ * Apply tool config modifications (specific method for BeforeToolSelection hooks)
361734
+ */
361735
+ applyToolConfigModifications(target) {
361736
+ return target;
361737
+ }
361738
+ /**
361739
+ * Get additional context for adding to responses
361740
+ */
361741
+ getAdditionalContext() {
361742
+ if (this.hookSpecificOutput && "additionalContext" in this.hookSpecificOutput) {
361743
+ const context2 = this.hookSpecificOutput["additionalContext"];
361744
+ return typeof context2 === "string" ? context2 : void 0;
361745
+ }
361746
+ return void 0;
361747
+ }
361748
+ /**
361749
+ * Check if execution should be blocked and return error info
361750
+ */
361751
+ getBlockingError() {
361752
+ if (this.isBlockingDecision()) {
361753
+ return {
361754
+ blocked: true,
361755
+ reason: this.getEffectiveReason()
361756
+ };
361757
+ }
361758
+ return { blocked: false, reason: "" };
361759
+ }
361760
+ };
361761
+ var BeforeToolHookOutput = class extends DefaultHookOutput {
361762
+ /**
361763
+ * Get the effective blocking reason, considering compatibility fields
361764
+ */
361765
+ getEffectiveReason() {
361766
+ if (this.hookSpecificOutput) {
361767
+ if ("permissionDecisionReason" in this.hookSpecificOutput) {
361768
+ const compatReason = this.hookSpecificOutput["permissionDecisionReason"];
361769
+ if (typeof compatReason === "string") {
361770
+ return compatReason;
361771
+ }
361772
+ }
361773
+ }
361774
+ return super.getEffectiveReason();
361775
+ }
361776
+ /**
361777
+ * Check if this output represents a blocking decision, considering compatibility fields
361778
+ */
361779
+ isBlockingDecision() {
361780
+ if (this.hookSpecificOutput && "permissionDecision" in this.hookSpecificOutput) {
361781
+ const compatDecision = this.hookSpecificOutput["permissionDecision"];
361782
+ if (compatDecision === "block" || compatDecision === "deny") {
361783
+ return true;
361784
+ }
361785
+ }
361786
+ return super.isBlockingDecision();
361787
+ }
361788
+ };
361789
+ var BeforeModelHookOutput = class extends DefaultHookOutput {
361790
+ /**
361791
+ * Get synthetic LLM response if provided by hook
361792
+ */
361793
+ getSyntheticResponse() {
361794
+ if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
361795
+ const hookResponse = this.hookSpecificOutput["llm_response"];
361796
+ if (hookResponse) {
361797
+ return defaultHookTranslator.fromHookLLMResponse(hookResponse);
361798
+ }
361799
+ }
361800
+ return void 0;
361801
+ }
361802
+ /**
361803
+ * Apply modifications to LLM request
361804
+ */
361805
+ applyLLMRequestModifications(target) {
361806
+ if (this.hookSpecificOutput && "llm_request" in this.hookSpecificOutput) {
361807
+ const hookRequest = this.hookSpecificOutput["llm_request"];
361808
+ if (hookRequest) {
361809
+ const sdkRequest = defaultHookTranslator.fromHookLLMRequest(hookRequest, target);
361810
+ return {
361811
+ ...target,
361812
+ ...sdkRequest
361813
+ };
361814
+ }
361815
+ }
361816
+ return target;
361817
+ }
361818
+ };
361819
+ var BeforeToolSelectionHookOutput = class extends DefaultHookOutput {
361820
+ /**
361821
+ * Apply tool configuration modifications
361822
+ */
361823
+ applyToolConfigModifications(target) {
361824
+ if (this.hookSpecificOutput && "toolConfig" in this.hookSpecificOutput) {
361825
+ const hookToolConfig = this.hookSpecificOutput["toolConfig"];
361826
+ if (hookToolConfig) {
361827
+ const sdkToolConfig = defaultHookTranslator.fromHookToolConfig(hookToolConfig);
361828
+ return {
361829
+ ...target,
361830
+ tools: target.tools || [],
361831
+ toolConfig: sdkToolConfig
361832
+ };
361833
+ }
361834
+ }
361835
+ return target;
361836
+ }
361837
+ };
361838
+ var AfterModelHookOutput = class extends DefaultHookOutput {
361839
+ /**
361840
+ * Get modified LLM response if provided by hook
361841
+ */
361842
+ getModifiedResponse() {
361843
+ if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
361844
+ const hookResponse = this.hookSpecificOutput["llm_response"];
361845
+ if (hookResponse?.candidates?.[0]?.content?.parts?.length) {
361846
+ return defaultHookTranslator.fromHookLLMResponse(hookResponse);
361847
+ }
361848
+ }
361849
+ if (this.shouldStopExecution()) {
361850
+ const stopResponse = {
361851
+ candidates: [
361852
+ {
361853
+ content: {
361854
+ role: "model",
361855
+ parts: [this.getEffectiveReason() || "Execution stopped by hook"]
361856
+ },
361857
+ finishReason: "STOP"
361858
+ }
361859
+ ]
361860
+ };
361861
+ return defaultHookTranslator.fromHookLLMResponse(stopResponse);
361862
+ }
361863
+ return void 0;
361864
+ }
361865
+ };
361866
+ var NotificationType;
361867
+ (function(NotificationType2) {
361868
+ NotificationType2["ToolPermission"] = "ToolPermission";
361869
+ })(NotificationType || (NotificationType = {}));
361870
+ var SessionStartSource;
361871
+ (function(SessionStartSource2) {
361872
+ SessionStartSource2["Startup"] = "startup";
361873
+ SessionStartSource2["Resume"] = "resume";
361874
+ SessionStartSource2["Clear"] = "clear";
361875
+ SessionStartSource2["Compress"] = "compress";
361876
+ })(SessionStartSource || (SessionStartSource = {}));
361877
+ var SessionEndReason;
361878
+ (function(SessionEndReason2) {
361879
+ SessionEndReason2["Exit"] = "exit";
361880
+ SessionEndReason2["Clear"] = "clear";
361881
+ SessionEndReason2["Logout"] = "logout";
361882
+ SessionEndReason2["PromptInputExit"] = "prompt_input_exit";
361883
+ SessionEndReason2["Other"] = "other";
361884
+ })(SessionEndReason || (SessionEndReason = {}));
361885
+ var PreCompressTrigger;
361886
+ (function(PreCompressTrigger2) {
361887
+ PreCompressTrigger2["Manual"] = "manual";
361888
+ PreCompressTrigger2["Auto"] = "auto";
361889
+ })(PreCompressTrigger || (PreCompressTrigger = {}));
361890
+
361891
+ // packages/core/dist/src/core/coreToolHookTriggers.js
361892
+ function toSerializableDetails(details) {
361893
+ const base = {
361894
+ type: details.type,
361895
+ title: details.title
361896
+ };
361897
+ switch (details.type) {
361898
+ case "edit":
361899
+ return {
361900
+ ...base,
361901
+ fileName: details.fileName,
361902
+ filePath: details.filePath,
361903
+ fileDiff: details.fileDiff,
361904
+ originalContent: details.originalContent,
361905
+ newContent: details.newContent,
361906
+ isModifying: details.isModifying
361907
+ };
361908
+ case "exec":
361909
+ return {
361910
+ ...base,
361911
+ command: details.command,
361912
+ rootCommand: details.rootCommand
361913
+ };
361914
+ case "mcp":
361915
+ return {
361916
+ ...base,
361917
+ serverName: details.serverName,
361918
+ toolName: details.toolName,
361919
+ toolDisplayName: details.toolDisplayName
361920
+ };
361921
+ case "info":
361922
+ return {
361923
+ ...base,
361924
+ prompt: details.prompt,
361925
+ urls: details.urls
361926
+ };
361927
+ default:
361928
+ return base;
361929
+ }
361930
+ }
361931
+ function getNotificationMessage(confirmationDetails) {
361932
+ switch (confirmationDetails.type) {
361933
+ case "edit":
361934
+ return `Tool ${confirmationDetails.title} requires editing`;
361935
+ case "exec":
361936
+ return `Tool ${confirmationDetails.title} requires execution`;
361937
+ case "mcp":
361938
+ return `Tool ${confirmationDetails.title} requires MCP`;
361939
+ case "info":
361940
+ return `Tool ${confirmationDetails.title} requires information`;
361941
+ default:
361942
+ return `Tool requires confirmation`;
361943
+ }
361944
+ }
361945
+ async function fireToolNotificationHook(messageBus, confirmationDetails) {
361946
+ try {
361947
+ const message = getNotificationMessage(confirmationDetails);
361948
+ const serializedDetails = toSerializableDetails(confirmationDetails);
361949
+ await messageBus.request({
361950
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
361951
+ eventName: "Notification",
361952
+ input: {
361953
+ notification_type: NotificationType.ToolPermission,
361954
+ message,
361955
+ details: serializedDetails
361956
+ }
361957
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
361958
+ } catch (error2) {
361959
+ debugLogger.warn(`Notification hook failed for ${confirmationDetails.title}:`, error2);
361960
+ }
361961
+ }
361962
+ async function fireBeforeToolHook(messageBus, toolName, toolInput) {
361963
+ try {
361964
+ const response = await messageBus.request({
361965
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
361966
+ eventName: "BeforeTool",
361967
+ input: {
361968
+ tool_name: toolName,
361969
+ tool_input: toolInput
361970
+ }
361971
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
361972
+ return response.output ? createHookOutput("BeforeTool", response.output) : void 0;
361973
+ } catch (error2) {
361974
+ debugLogger.warn(`BeforeTool hook failed for ${toolName}:`, error2);
361975
+ return void 0;
361976
+ }
361977
+ }
361978
+ async function fireAfterToolHook(messageBus, toolName, toolInput, toolResponse) {
361979
+ try {
361980
+ const response = await messageBus.request({
361981
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
361982
+ eventName: "AfterTool",
361983
+ input: {
361984
+ tool_name: toolName,
361985
+ tool_input: toolInput,
361986
+ tool_response: toolResponse
361987
+ }
361988
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
361989
+ return response.output ? createHookOutput("AfterTool", response.output) : void 0;
361990
+ } catch (error2) {
361991
+ debugLogger.warn(`AfterTool hook failed for ${toolName}:`, error2);
361992
+ return void 0;
361993
+ }
361994
+ }
361995
+ async function executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, liveOutputCallback, shellExecutionConfig, setPidCallback) {
361996
+ const toolInput = invocation.params || {};
361997
+ if (hooksEnabled && messageBus) {
361998
+ const beforeOutput = await fireBeforeToolHook(messageBus, toolName, toolInput);
361999
+ const blockingError = beforeOutput?.getBlockingError();
362000
+ if (blockingError?.blocked) {
362001
+ return {
362002
+ llmContent: `Tool execution blocked: ${blockingError.reason}`,
362003
+ returnDisplay: `Tool execution blocked: ${blockingError.reason}`,
362004
+ error: {
362005
+ type: ToolErrorType.EXECUTION_FAILED,
362006
+ message: blockingError.reason
362007
+ }
362008
+ };
362009
+ }
362010
+ if (beforeOutput?.shouldStopExecution()) {
362011
+ const reason = beforeOutput.getEffectiveReason();
362012
+ return {
362013
+ llmContent: `Agent execution stopped by hook: ${reason}`,
362014
+ returnDisplay: `Agent execution stopped by hook: ${reason}`,
362015
+ error: {
362016
+ type: ToolErrorType.EXECUTION_FAILED,
362017
+ message: `Agent execution stopped: ${reason}`
362018
+ }
362019
+ };
362020
+ }
362021
+ }
362022
+ let toolResult;
362023
+ if (setPidCallback && invocation instanceof ShellToolInvocation) {
362024
+ toolResult = await invocation.execute(signal, liveOutputCallback, shellExecutionConfig, setPidCallback);
362025
+ } else {
362026
+ toolResult = await invocation.execute(signal, liveOutputCallback, shellExecutionConfig);
362027
+ }
362028
+ if (hooksEnabled && messageBus) {
362029
+ const afterOutput = await fireAfterToolHook(messageBus, toolName, toolInput, {
362030
+ llmContent: toolResult.llmContent,
362031
+ returnDisplay: toolResult.returnDisplay,
362032
+ error: toolResult.error
362033
+ });
362034
+ if (afterOutput?.shouldStopExecution()) {
362035
+ const reason = afterOutput.getEffectiveReason();
362036
+ return {
362037
+ llmContent: `Agent execution stopped by hook: ${reason}`,
362038
+ returnDisplay: `Agent execution stopped by hook: ${reason}`,
362039
+ error: {
362040
+ type: ToolErrorType.EXECUTION_FAILED,
362041
+ message: `Agent execution stopped: ${reason}`
362042
+ }
362043
+ };
362044
+ }
362045
+ const additionalContext = afterOutput?.getAdditionalContext();
362046
+ if (additionalContext) {
362047
+ if (typeof toolResult.llmContent === "string") {
362048
+ toolResult.llmContent += "\n\n" + additionalContext;
362049
+ } else if (Array.isArray(toolResult.llmContent)) {
362050
+ toolResult.llmContent.push({ text: "\n\n" + additionalContext });
362051
+ } else if (toolResult.llmContent) {
362052
+ toolResult.llmContent = [
362053
+ toolResult.llmContent,
362054
+ { text: "\n\n" + additionalContext }
362055
+ ];
362056
+ } else {
362057
+ toolResult.llmContent = additionalContext;
362058
+ }
362059
+ }
362060
+ }
362061
+ return toolResult;
362062
+ }
362063
+
362064
+ // packages/core/dist/src/core/coreToolScheduler.js
361456
362065
  function createFunctionResponsePart(callId, toolName, output) {
361457
362066
  return {
361458
362067
  functionResponse: {
@@ -361908,6 +362517,11 @@ var CoreToolScheduler = class _CoreToolScheduler {
361908
362517
  this.setToolCallOutcome(reqInfo.callId, ToolConfirmationOutcome.ProceedAlways);
361909
362518
  this.setStatusInternal(reqInfo.callId, "scheduled", signal);
361910
362519
  } else {
362520
+ const messageBus = this.config.getMessageBus();
362521
+ const hooksEnabled = this.config.getEnableHooks();
362522
+ if (hooksEnabled && messageBus) {
362523
+ await fireToolNotificationHook(messageBus, confirmationDetails);
362524
+ }
361911
362525
  if (confirmationDetails.type === "edit" && confirmationDetails.ideConfirmation) {
361912
362526
  confirmationDetails.ideConfirmation.then((resolution) => {
361913
362527
  if (resolution.status === "accepted") {
@@ -362017,6 +362631,8 @@ var CoreToolScheduler = class _CoreToolScheduler {
362017
362631
  this.notifyToolCallsUpdate();
362018
362632
  } : void 0;
362019
362633
  const shellExecutionConfig = this.config.getShellExecutionConfig();
362634
+ const hooksEnabled = this.config.getEnableHooks();
362635
+ const messageBus = this.config.getMessageBus();
362020
362636
  await runInDevTraceSpan({
362021
362637
  name: toolCall.tool.name,
362022
362638
  attributes: { type: "tool-call" }
@@ -362030,9 +362646,9 @@ var CoreToolScheduler = class _CoreToolScheduler {
362030
362646
  this.toolCalls = this.toolCalls.map((tc) => tc.request.callId === callId && tc.status === "executing" ? { ...tc, pid } : tc);
362031
362647
  this.notifyToolCallsUpdate();
362032
362648
  };
362033
- promise = invocation.execute(signal, liveOutputCallback, shellExecutionConfig, setPidCallback);
362649
+ promise = executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, liveOutputCallback, shellExecutionConfig, setPidCallback);
362034
362650
  } else {
362035
- promise = invocation.execute(signal, liveOutputCallback, shellExecutionConfig);
362651
+ promise = executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, liveOutputCallback, shellExecutionConfig);
362036
362652
  }
362037
362653
  try {
362038
362654
  const toolResult = await promise;
@@ -362569,9 +363185,97 @@ async function openBrowserSecurely(url5) {
362569
363185
  }
362570
363186
  }
362571
363187
 
363188
+ // packages/core/dist/src/availability/policyCatalog.js
363189
+ var DEFAULT_ACTIONS = {
363190
+ terminal: "prompt",
363191
+ transient: "prompt",
363192
+ not_found: "prompt",
363193
+ unknown: "prompt"
363194
+ };
363195
+ var DEFAULT_STATE = {
363196
+ terminal: "terminal",
363197
+ transient: "terminal",
363198
+ not_found: "terminal",
363199
+ unknown: "terminal"
363200
+ };
363201
+ var DEFAULT_CHAIN = [
363202
+ definePolicy({ model: DEFAULT_GEMINI_MODEL }),
363203
+ definePolicy({ model: DEFAULT_GEMINI_FLASH_MODEL, isLastResort: true })
363204
+ ];
363205
+ var PREVIEW_CHAIN = [
363206
+ definePolicy({
363207
+ model: PREVIEW_GEMINI_MODEL,
363208
+ stateTransitions: { transient: "sticky_retry" }
363209
+ }),
363210
+ definePolicy({ model: DEFAULT_GEMINI_MODEL }),
363211
+ definePolicy({ model: DEFAULT_GEMINI_FLASH_MODEL, isLastResort: true })
363212
+ ];
363213
+ function getModelPolicyChain(options2) {
363214
+ if (options2.previewEnabled) {
363215
+ return cloneChain(PREVIEW_CHAIN);
363216
+ }
363217
+ return cloneChain(DEFAULT_CHAIN);
363218
+ }
363219
+ function createDefaultPolicy(model) {
363220
+ return definePolicy({ model });
363221
+ }
363222
+ function definePolicy(config3) {
363223
+ return {
363224
+ model: config3.model,
363225
+ isLastResort: config3.isLastResort,
363226
+ actions: { ...DEFAULT_ACTIONS, ...config3.actions ?? {} },
363227
+ stateTransitions: {
363228
+ ...DEFAULT_STATE,
363229
+ ...config3.stateTransitions ?? {}
363230
+ }
363231
+ };
363232
+ }
363233
+ function clonePolicy(policy) {
363234
+ return {
363235
+ ...policy,
363236
+ actions: { ...policy.actions },
363237
+ stateTransitions: { ...policy.stateTransitions }
363238
+ };
363239
+ }
363240
+ function cloneChain(chain2) {
363241
+ return chain2.map(clonePolicy);
363242
+ }
363243
+
363244
+ // packages/core/dist/src/availability/policyHelpers.js
363245
+ function resolvePolicyChain(config3) {
363246
+ const chain2 = getModelPolicyChain({
363247
+ previewEnabled: !!config3.getPreviewFeatures(),
363248
+ userTier: config3.getUserTier()
363249
+ });
363250
+ const activeModel = getEffectiveModel(config3.isInFallbackMode(), config3.getModel(), config3.getPreviewFeatures());
363251
+ if (chain2.some((policy) => policy.model === activeModel)) {
363252
+ return chain2;
363253
+ }
363254
+ return [createDefaultPolicy(activeModel), ...chain2];
363255
+ }
363256
+ function buildFallbackPolicyContext(chain2, failedModel) {
363257
+ const index = chain2.findIndex((policy) => policy.model === failedModel);
363258
+ if (index === -1) {
363259
+ return { failedPolicy: void 0, candidates: chain2 };
363260
+ }
363261
+ return {
363262
+ failedPolicy: chain2[index],
363263
+ candidates: chain2.slice(index + 1)
363264
+ };
363265
+ }
363266
+ function resolvePolicyAction(failureKind, policy) {
363267
+ return policy.actions?.[failureKind] ?? "prompt";
363268
+ }
363269
+
362572
363270
  // packages/core/dist/src/fallback/handler.js
362573
363271
  var UPGRADE_URL_PAGE = "https://goo.gle/set-up-gemini-code-assist";
362574
363272
  async function handleFallback(config3, failedModel, authType, error2) {
363273
+ if (config3.isModelAvailabilityServiceEnabled()) {
363274
+ return handlePolicyDrivenFallback(config3, failedModel, authType, error2);
363275
+ }
363276
+ return legacyHandleFallback(config3, failedModel, authType, error2);
363277
+ }
363278
+ async function legacyHandleFallback(config3, failedModel, authType, error2) {
362575
363279
  if (authType !== AuthType2.LOGIN_WITH_GOOGLE)
362576
363280
  return null;
362577
363281
  if (error2 instanceof ModelNotFoundError && failedModel !== PREVIEW_GEMINI_MODEL) {
@@ -362590,30 +363294,56 @@ async function handleFallback(config3, failedModel, authType, error2) {
362590
363294
  return null;
362591
363295
  try {
362592
363296
  const intent = await fallbackModelHandler(failedModel, fallbackModel, error2);
362593
- switch (intent) {
362594
- case "retry_always":
362595
- if (shouldActivatePreviewFallback) {
362596
- activatePreviewModelFallbackMode(config3);
362597
- } else {
362598
- activateFallbackMode(config3, authType);
362599
- }
362600
- return true;
362601
- // Signal retryWithBackoff to continue.
362602
- case "retry_once":
362603
- return true;
362604
- case "stop":
362605
- activateFallbackMode(config3, authType);
362606
- return false;
362607
- case "retry_later":
362608
- return false;
362609
- case "upgrade":
362610
- await handleUpgrade();
362611
- return false;
362612
- default:
362613
- throw new Error(`Unexpected fallback intent received from fallbackModelHandler: "${intent}"`);
362614
- }
363297
+ return await processIntent(config3, intent, failedModel, fallbackModel, authType, error2);
363298
+ } catch (handlerError) {
363299
+ console.error("Fallback UI handler failed:", handlerError);
363300
+ return null;
363301
+ }
363302
+ }
363303
+ async function handlePolicyDrivenFallback(config3, failedModel, authType, error2) {
363304
+ if (authType !== AuthType2.LOGIN_WITH_GOOGLE) {
363305
+ return null;
363306
+ }
363307
+ const chain2 = resolvePolicyChain(config3);
363308
+ const { failedPolicy, candidates } = buildFallbackPolicyContext(chain2, failedModel);
363309
+ if (!candidates.length) {
363310
+ return null;
363311
+ }
363312
+ const availability = config3.getModelAvailabilityService();
363313
+ const selection = availability.selectFirstAvailable(candidates.map((policy) => policy.model));
363314
+ let lastResortPolicy = candidates.find((policy) => policy.isLastResort);
363315
+ if (!lastResortPolicy) {
363316
+ debugLogger.warn("No isLastResort policy found in candidates, using last candidate as fallback.");
363317
+ lastResortPolicy = candidates[candidates.length - 1];
363318
+ }
363319
+ const fallbackModel = selection.selectedModel ?? lastResortPolicy.model;
363320
+ const selectedPolicy = candidates.find((policy) => policy.model === fallbackModel) ?? lastResortPolicy;
363321
+ if (!fallbackModel || fallbackModel === failedModel) {
363322
+ return null;
363323
+ }
363324
+ const failureKind = classifyFailureKind(error2);
363325
+ const action = resolvePolicyAction(failureKind, selectedPolicy);
363326
+ if (action === "silent") {
363327
+ return processIntent(config3, "retry_always", failedModel, fallbackModel, authType, error2);
363328
+ }
363329
+ const recommendation = {
363330
+ ...selection,
363331
+ selectedModel: fallbackModel,
363332
+ action,
363333
+ failureKind,
363334
+ failedPolicy,
363335
+ selectedPolicy
363336
+ };
363337
+ void recommendation;
363338
+ const handler = config3.getFallbackModelHandler();
363339
+ if (typeof handler !== "function") {
363340
+ return null;
363341
+ }
363342
+ try {
363343
+ const intent = await handler(failedModel, fallbackModel, error2);
363344
+ return await processIntent(config3, intent, failedModel, fallbackModel, authType);
362615
363345
  } catch (handlerError) {
362616
- debugLogger.error("Fallback UI handler failed:", handlerError);
363346
+ debugLogger.error("Fallback handler failed:", handlerError);
362617
363347
  return null;
362618
363348
  }
362619
363349
  }
@@ -362624,6 +363354,29 @@ async function handleUpgrade() {
362624
363354
  debugLogger.warn("Failed to open browser automatically:", getErrorMessage(error2));
362625
363355
  }
362626
363356
  }
363357
+ async function processIntent(config3, intent, failedModel, fallbackModel, authType, error2) {
363358
+ switch (intent) {
363359
+ case "retry_always":
363360
+ if (failedModel === PREVIEW_GEMINI_MODEL && !(error2 instanceof TerminalQuotaError)) {
363361
+ activatePreviewModelFallbackMode(config3);
363362
+ } else {
363363
+ activateFallbackMode(config3, authType);
363364
+ }
363365
+ return true;
363366
+ case "retry_once":
363367
+ return true;
363368
+ case "stop":
363369
+ activateFallbackMode(config3, authType);
363370
+ return false;
363371
+ case "retry_later":
363372
+ return false;
363373
+ case "upgrade":
363374
+ await handleUpgrade();
363375
+ return false;
363376
+ default:
363377
+ throw new Error(`Unexpected fallback intent received from fallbackModelHandler: "${intent}"`);
363378
+ }
363379
+ }
362627
363380
  function activateFallbackMode(config3, authType) {
362628
363381
  if (!config3.isInFallbackMode()) {
362629
363382
  config3.setFallbackMode(true);
@@ -362638,12 +363391,154 @@ function activatePreviewModelFallbackMode(config3) {
362638
363391
  config3.setPreviewModelFallbackMode(true);
362639
363392
  }
362640
363393
  }
363394
+ function classifyFailureKind(error2) {
363395
+ if (error2 instanceof TerminalQuotaError) {
363396
+ return "terminal";
363397
+ }
363398
+ if (error2 instanceof RetryableQuotaError) {
363399
+ return "transient";
363400
+ }
363401
+ if (error2 instanceof ModelNotFoundError) {
363402
+ return "not_found";
363403
+ }
363404
+ return "unknown";
363405
+ }
362641
363406
 
362642
363407
  // packages/core/dist/src/core/geminiRequest.js
362643
363408
  function partListUnionToString(value) {
362644
363409
  return partToString(value, { verbose: true });
362645
363410
  }
362646
363411
 
363412
+ // packages/core/dist/src/utils/tokenCalculation.js
363413
+ var ASCII_TOKENS_PER_CHAR = 0.25;
363414
+ var NON_ASCII_TOKENS_PER_CHAR = 1.3;
363415
+ function estimateTokenCountSync(parts2) {
363416
+ let totalTokens = 0;
363417
+ for (const part of parts2) {
363418
+ if (typeof part.text === "string") {
363419
+ for (const char of part.text) {
363420
+ if (char.codePointAt(0) <= 127) {
363421
+ totalTokens += ASCII_TOKENS_PER_CHAR;
363422
+ } else {
363423
+ totalTokens += NON_ASCII_TOKENS_PER_CHAR;
363424
+ }
363425
+ }
363426
+ } else {
363427
+ totalTokens += JSON.stringify(part).length / 4;
363428
+ }
363429
+ }
363430
+ return Math.floor(totalTokens);
363431
+ }
363432
+ async function calculateRequestTokenCount(request3, contentGenerator, model) {
363433
+ const parts2 = Array.isArray(request3) ? request3.map((p) => typeof p === "string" ? { text: p } : p) : typeof request3 === "string" ? [{ text: request3 }] : [request3];
363434
+ const hasMedia = parts2.some((p) => {
363435
+ const isMedia = "inlineData" in p || "fileData" in p;
363436
+ return isMedia;
363437
+ });
363438
+ if (hasMedia) {
363439
+ try {
363440
+ const response = await contentGenerator.countTokens({
363441
+ model,
363442
+ contents: [{ role: "user", parts: parts2 }]
363443
+ });
363444
+ return response.totalTokens ?? 0;
363445
+ } catch {
363446
+ return estimateTokenCountSync(parts2);
363447
+ }
363448
+ }
363449
+ return estimateTokenCountSync(parts2);
363450
+ }
363451
+
363452
+ // packages/core/dist/src/core/geminiChatHookTriggers.js
363453
+ async function fireBeforeModelHook(messageBus, llmRequest) {
363454
+ try {
363455
+ const response = await messageBus.request({
363456
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
363457
+ eventName: "BeforeModel",
363458
+ input: {
363459
+ llm_request: llmRequest
363460
+ }
363461
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
363462
+ const beforeResultFinalOutput = response.output ? createHookOutput("BeforeModel", response.output) : void 0;
363463
+ const hookOutput = beforeResultFinalOutput;
363464
+ const blockingError = hookOutput?.getBlockingError();
363465
+ if (blockingError?.blocked || hookOutput?.shouldStopExecution()) {
363466
+ const beforeModelOutput = hookOutput;
363467
+ const syntheticResponse = beforeModelOutput.getSyntheticResponse();
363468
+ const reason = hookOutput?.getEffectiveReason() || "Model call blocked by hook";
363469
+ return {
363470
+ blocked: true,
363471
+ reason,
363472
+ syntheticResponse
363473
+ };
363474
+ }
363475
+ if (hookOutput) {
363476
+ const beforeModelOutput = hookOutput;
363477
+ const modifiedRequest = beforeModelOutput.applyLLMRequestModifications(llmRequest);
363478
+ return {
363479
+ blocked: false,
363480
+ modifiedConfig: modifiedRequest.config,
363481
+ modifiedContents: modifiedRequest.contents
363482
+ };
363483
+ }
363484
+ return { blocked: false };
363485
+ } catch (error2) {
363486
+ debugLogger.warn(`BeforeModel hook failed:`, error2);
363487
+ return { blocked: false };
363488
+ }
363489
+ }
363490
+ async function fireBeforeToolSelectionHook(messageBus, llmRequest) {
363491
+ try {
363492
+ const response = await messageBus.request({
363493
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
363494
+ eventName: "BeforeToolSelection",
363495
+ input: {
363496
+ llm_request: llmRequest
363497
+ }
363498
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
363499
+ const toolSelectionResultFinalOutput = response.output ? createHookOutput("BeforeToolSelection", response.output) : void 0;
363500
+ if (toolSelectionResultFinalOutput) {
363501
+ const beforeToolSelectionOutput = toolSelectionResultFinalOutput;
363502
+ const modifiedConfig = beforeToolSelectionOutput.applyToolConfigModifications({
363503
+ toolConfig: llmRequest.config?.toolConfig,
363504
+ tools: llmRequest.config?.tools
363505
+ });
363506
+ return {
363507
+ toolConfig: modifiedConfig.toolConfig,
363508
+ tools: modifiedConfig.tools
363509
+ };
363510
+ }
363511
+ return {};
363512
+ } catch (error2) {
363513
+ debugLogger.warn(`BeforeToolSelection hook failed:`, error2);
363514
+ return {};
363515
+ }
363516
+ }
363517
+ async function fireAfterModelHook(messageBus, originalRequest, chunk2) {
363518
+ try {
363519
+ const response = await messageBus.request({
363520
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
363521
+ eventName: "AfterModel",
363522
+ input: {
363523
+ llm_request: originalRequest,
363524
+ llm_response: chunk2
363525
+ }
363526
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
363527
+ const afterResultFinalOutput = response.output ? createHookOutput("AfterModel", response.output) : void 0;
363528
+ if (afterResultFinalOutput) {
363529
+ const afterModelOutput = afterResultFinalOutput;
363530
+ const modifiedResponse = afterModelOutput.getModifiedResponse();
363531
+ if (modifiedResponse) {
363532
+ return { response: modifiedResponse };
363533
+ }
363534
+ }
363535
+ return { response: chunk2 };
363536
+ } catch (error2) {
363537
+ debugLogger.warn(`AfterModel hook failed:`, error2);
363538
+ return { response: chunk2 };
363539
+ }
363540
+ }
363541
+
362647
363542
  // packages/core/dist/src/core/geminiChat.js
362648
363543
  var StreamEventType;
362649
363544
  (function(StreamEventType2) {
@@ -362746,7 +363641,7 @@ var GeminiChat = class {
362746
363641
  validateHistory2(history);
362747
363642
  this.chatRecordingService = new ChatRecordingService(config3);
362748
363643
  this.chatRecordingService.initialize(resumedSessionData);
362749
- this.lastPromptTokenCount = Math.ceil(JSON.stringify(this.history).length / 4);
363644
+ this.lastPromptTokenCount = estimateTokenCountSync(this.history.flatMap((c4) => c4.parts || []));
362750
363645
  }
362751
363646
  setSystemInstruction(sysInstr) {
362752
363647
  this.systemInstruction = sysInstr;
@@ -362798,12 +363693,11 @@ var GeminiChat = class {
362798
363693
  }
362799
363694
  this.history.push(userContent);
362800
363695
  const requestContents = this.getHistory(true);
362801
- const self2 = this;
362802
- return async function* () {
363696
+ const streamWithRetries = async function* () {
362803
363697
  try {
362804
363698
  let lastError = new Error("Request failed after all retries.");
362805
363699
  let maxAttempts = INVALID_CONTENT_RETRY_OPTIONS.maxAttempts;
362806
- if (self2.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL) {
363700
+ if (this.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL) {
362807
363701
  maxAttempts = 1;
362808
363702
  }
362809
363703
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
@@ -362814,7 +363708,7 @@ var GeminiChat = class {
362814
363708
  if (attempt > 0) {
362815
363709
  generateContentConfig.temperature = 1;
362816
363710
  }
362817
- const stream3 = await self2.makeApiCallAndProcessStream(model, generateContentConfig, requestContents, prompt_id);
363711
+ const stream3 = await this.makeApiCallAndProcessStream(model, generateContentConfig, requestContents, prompt_id);
362818
363712
  for await (const chunk2 of stream3) {
362819
363713
  yield { type: StreamEventType.CHUNK, value: chunk2 };
362820
363714
  }
@@ -362825,7 +363719,7 @@ var GeminiChat = class {
362825
363719
  const isContentError = error2 instanceof InvalidStreamError;
362826
363720
  if (isContentError && isGemini2Model(model)) {
362827
363721
  if (attempt < maxAttempts - 1) {
362828
- logContentRetry(self2.config, new ContentRetryEvent(attempt, error2.type, INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs, model));
363722
+ logContentRetry(this.config, new ContentRetryEvent(attempt, error2.type, INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs, model));
362829
363723
  await new Promise((res) => setTimeout(res, INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs * (attempt + 1)));
362830
363724
  continue;
362831
363725
  }
@@ -362835,23 +363729,27 @@ var GeminiChat = class {
362835
363729
  }
362836
363730
  if (lastError) {
362837
363731
  if (lastError instanceof InvalidStreamError && isGemini2Model(model)) {
362838
- logContentRetryFailure(self2.config, new ContentRetryFailureEvent(maxAttempts, lastError.type, model));
363732
+ logContentRetryFailure(this.config, new ContentRetryFailureEvent(maxAttempts, lastError.type, model));
362839
363733
  }
362840
363734
  throw lastError;
362841
363735
  } else {
362842
- if (model === PREVIEW_GEMINI_MODEL && !self2.config.isPreviewModelBypassMode()) {
362843
- self2.config.setPreviewModelFallbackMode(false);
363736
+ if (model === PREVIEW_GEMINI_MODEL && !this.config.isPreviewModelBypassMode()) {
363737
+ this.config.setPreviewModelFallbackMode(false);
362844
363738
  }
362845
363739
  }
362846
363740
  } finally {
362847
363741
  streamDoneResolver();
362848
363742
  }
362849
- }();
363743
+ };
363744
+ return streamWithRetries.call(this);
362850
363745
  }
362851
363746
  async makeApiCallAndProcessStream(model, generateContentConfig, requestContents, prompt_id) {
362852
363747
  let effectiveModel = model;
362853
363748
  const contentsForPreviewModel = this.ensureActiveLoopHasThoughtSignatures(requestContents);
362854
- const apiCall = () => {
363749
+ let lastModelToUse = model;
363750
+ let lastConfig = generateContentConfig;
363751
+ let lastContentsToUse = requestContents;
363752
+ const apiCall = async () => {
362855
363753
  let modelToUse = getEffectiveModel(this.config.isInFallbackMode(), model, this.config.getPreviewFeatures());
362856
363754
  if (this.config.isPreviewModelBypassMode() && modelToUse === PREVIEW_GEMINI_MODEL) {
362857
363755
  modelToUse = DEFAULT_GEMINI_MODEL;
@@ -362877,9 +363775,49 @@ var GeminiChat = class {
362877
363775
  };
362878
363776
  delete config3.thinkingConfig?.thinkingLevel;
362879
363777
  }
363778
+ let contentsToUse = modelToUse === PREVIEW_GEMINI_MODEL ? contentsForPreviewModel : requestContents;
363779
+ const hooksEnabled = this.config.getEnableHooks();
363780
+ const messageBus = this.config.getMessageBus();
363781
+ if (hooksEnabled && messageBus) {
363782
+ const beforeModelResult = await fireBeforeModelHook(messageBus, {
363783
+ model: modelToUse,
363784
+ config: config3,
363785
+ contents: contentsToUse
363786
+ });
363787
+ if (beforeModelResult.blocked) {
363788
+ const syntheticResponse = beforeModelResult.syntheticResponse;
363789
+ if (syntheticResponse) {
363790
+ return async function* () {
363791
+ yield syntheticResponse;
363792
+ }();
363793
+ }
363794
+ return async function* () {
363795
+ }();
363796
+ }
363797
+ if (beforeModelResult.modifiedConfig) {
363798
+ Object.assign(config3, beforeModelResult.modifiedConfig);
363799
+ }
363800
+ if (beforeModelResult.modifiedContents && Array.isArray(beforeModelResult.modifiedContents)) {
363801
+ contentsToUse = beforeModelResult.modifiedContents;
363802
+ }
363803
+ const toolSelectionResult = await fireBeforeToolSelectionHook(messageBus, {
363804
+ model: modelToUse,
363805
+ config: config3,
363806
+ contents: contentsToUse
363807
+ });
363808
+ if (toolSelectionResult.toolConfig) {
363809
+ config3.toolConfig = toolSelectionResult.toolConfig;
363810
+ }
363811
+ if (toolSelectionResult.tools && Array.isArray(toolSelectionResult.tools)) {
363812
+ config3.tools = toolSelectionResult.tools;
363813
+ }
363814
+ }
363815
+ lastModelToUse = modelToUse;
363816
+ lastConfig = config3;
363817
+ lastContentsToUse = contentsToUse;
362880
363818
  return this.config.getContentGenerator().generateContentStream({
362881
363819
  model: modelToUse,
362882
- contents: modelToUse === PREVIEW_GEMINI_MODEL ? contentsForPreviewModel : requestContents,
363820
+ contents: contentsToUse,
362883
363821
  config: config3
362884
363822
  }, prompt_id);
362885
363823
  };
@@ -362891,7 +363829,12 @@ var GeminiChat = class {
362891
363829
  signal: generateContentConfig.abortSignal,
362892
363830
  maxAttempts: this.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL ? 1 : void 0
362893
363831
  });
362894
- return this.processStreamResponse(effectiveModel, streamResponse);
363832
+ const originalRequest = {
363833
+ model: lastModelToUse,
363834
+ config: lastConfig,
363835
+ contents: lastContentsToUse
363836
+ };
363837
+ return this.processStreamResponse(effectiveModel, streamResponse, originalRequest);
362895
363838
  }
362896
363839
  /**
362897
363840
  * Returns the chat history.
@@ -363015,7 +363958,7 @@ This error was probably caused by cyclic schema references in one of the followi
363015
363958
  }
363016
363959
  }
363017
363960
  }
363018
- async *processStreamResponse(model, streamResponse) {
363961
+ async *processStreamResponse(model, streamResponse, originalRequest) {
363019
363962
  const modelResponseParts = [];
363020
363963
  let hasToolCall = false;
363021
363964
  let finishReason;
@@ -363042,7 +363985,14 @@ This error was probably caused by cyclic schema references in one of the followi
363042
363985
  this.lastPromptTokenCount = chunk2.usageMetadata.promptTokenCount;
363043
363986
  }
363044
363987
  }
363045
- yield chunk2;
363988
+ const hooksEnabled = this.config.getEnableHooks();
363989
+ const messageBus = this.config.getMessageBus();
363990
+ if (hooksEnabled && messageBus && originalRequest && chunk2) {
363991
+ const hookResult = await fireAfterModelHook(messageBus, originalRequest, chunk2);
363992
+ yield hookResult.response;
363993
+ } else {
363994
+ yield chunk2;
363995
+ }
363046
363996
  }
363047
363997
  const consolidatedParts = [];
363048
363998
  for (const part of modelResponseParts) {
@@ -363643,15 +364593,18 @@ function getCoreSystemPrompt(config3, userMemory) {
363643
364593
  }
363644
364594
  }
363645
364595
  const desiredModel = getEffectiveModel(config3.isInFallbackMode(), config3.getModel(), config3.getPreviewFeatures());
363646
- const useChattySystemPrompt = desiredModel === PREVIEW_GEMINI_MODEL;
364596
+ const isGemini3 = desiredModel === PREVIEW_GEMINI_MODEL;
364597
+ const mandatesVariant = isGemini3 ? `
364598
+ - **Do not call tools in silence:** You must provide to the user very short and concise natural explanation (one sentence) before calling tools.` : ``;
363647
364599
  const enableCodebaseInvestigator = config3.getToolRegistry().getAllToolNames().includes(CodebaseInvestigatorAgent.name);
363648
364600
  const enableWriteTodosTool = config3.getToolRegistry().getAllToolNames().includes(WriteTodosTool.Name);
364601
+ const interactiveMode = config3.isInteractiveShellEnabled();
363649
364602
  let basePrompt;
363650
364603
  if (systemMdEnabled) {
363651
364604
  basePrompt = fs46.readFileSync(systemMdPath, "utf8");
363652
364605
  } else {
363653
364606
  const promptConfig = {
363654
- preamble: `You are an interactive CLI agent specializing in software engineering tasks. Your primary goal is to help users safely and efficiently, adhering strictly to the following instructions and utilizing your available tools.`,
364607
+ preamble: `You are ${interactiveMode ? "an interactive " : "a non-interactive "}CLI agent specializing in software engineering tasks. Your primary goal is to help users safely and efficiently, adhering strictly to the following instructions and utilizing your available tools.`,
363655
364608
  coreMandates: `
363656
364609
  # Core Mandates
363657
364610
 
@@ -363661,9 +364614,10 @@ function getCoreSystemPrompt(config3, userMemory) {
363661
364614
  - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically.
363662
364615
  - **Comments:** Add code comments sparingly. Focus on *why* something is done, especially for complex logic, rather than *what* is done. Only add high-value comments if necessary for clarity or if requested by the user. Do not edit comments that are separate from the code you are changing. *NEVER* talk to the user or describe your changes through comments.
363663
364616
  - **Proactiveness:** Fulfill the user's request thoroughly. When adding features or fixing bugs, this includes adding tests to ensure quality. Consider all created files, especially tests, to be permanent artifacts unless the user says otherwise.
363664
- - **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If asked *how* to do something, explain first, don't just do it.
364617
+ - ${interactiveMode ? `**Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If asked *how* to do something, explain first, don't just do it.` : `**Handle Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request.`}
363665
364618
  - **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked.
363666
- - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes.`,
364619
+ - **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes.${mandatesVariant}${!interactiveMode ? `
364620
+ - **Continue the work** You are not to interact with the user. Do your best to complete the task at hand, using your best judgement and avoid asking user for any additional information.` : ""}`,
363667
364621
  primaryWorkflows_prefix: `
363668
364622
  # Primary Workflows
363669
364623
 
@@ -363696,14 +364650,14 @@ When requested to perform tasks like fixing bugs, adding features, refactoring,
363696
364650
  primaryWorkflows_suffix: `3. **Implement:** Use the available tools (e.g., '${EDIT_TOOL_NAME}', '${WRITE_FILE_TOOL_NAME}' '${SHELL_TOOL_NAME}' ...) to act on the plan, strictly adhering to the project's established conventions (detailed under 'Core
363697
364651
  Mandates').
363698
364652
  4. **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands.
363699
- 5. **Verify (Standards):** VERY IMPORTANT: After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project (or obtained from the user). This ensures code quality and adherence to standards. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
364653
+ 5. **Verify (Standards):** VERY IMPORTANT: After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project (or obtained from the user). This ensures code quality and adherence to standards.${interactiveMode ? " If unsure about these commands, you can ask the user if they'd like you to run them and if so how to." : ""}
363700
364654
  6. **Finalize:** After all verification passes, consider the task complete. Do not remove or revert any changes or created files (like tests). Await the user's next instruction.
363701
364655
 
363702
364656
  ## New Applications
363703
364657
 
363704
364658
  **Goal:** Autonomously implement and deliver a visually appealing, substantially complete, and functional prototype. Utilize all tools at your disposal to implement the application. Some tools you may especially find useful are '${WRITE_FILE_TOOL_NAME}', '${EDIT_TOOL_NAME}' and '${SHELL_TOOL_NAME}'.
363705
364659
 
363706
- 1. **Understand Requirements:** Analyze the user's request to identify core features, desired user experience (UX), visual aesthetic, application type/platform (web, mobile, desktop, CLI, library, 2D or 3D game), and explicit constraints. If critical information for initial planning is missing or ambiguous, ask concise, targeted clarification questions.
364660
+ 1. **Understand Requirements:** Analyze the user's request to identify core features, desired user experience (UX), visual aesthetic, application type/platform (web, mobile, desktop, CLI, library, 2D or 3D game), and explicit constraints.${interactiveMode ? " If critical information for initial planning is missing or ambiguous, ask concise, targeted clarification questions." : ""}
363707
364661
  2. **Propose Plan:** Formulate an internal development plan. Present a clear, concise, high-level summary to the user. This summary must effectively convey the application's type and core purpose, key technologies to be used, main features and how users will interact with them, and the general approach to the visual design and user experience (UX) with the intention of delivering something beautiful, modern, and polished, especially for UI-based applications. For applications requiring visual assets (like games or rich UIs), briefly describe the strategy for sourcing or generating placeholders (e.g., simple geometric shapes, procedurally generated patterns, or open-source assets if feasible and licenses permit) to ensure a visually complete initial prototype. Ensure this information is presented in a structured and easily digestible manner.
363708
364662
  - When key technologies aren't specified, prefer the following:
363709
364663
  - **Websites (Frontend):** React (JavaScript/TypeScript) or Angular with Bootstrap CSS, incorporating Material Design principles for UI/UX.
@@ -363713,10 +364667,17 @@ Mandates').
363713
364667
  - **Mobile App:** Compose Multiplatform (Kotlin Multiplatform) or Flutter (Dart) using Material Design libraries and principles, when sharing code between Android and iOS. Jetpack Compose (Kotlin JVM) with Material Design principles or SwiftUI (Swift) for native apps targeted at either Android or iOS, respectively.
363714
364668
  - **3d Games:** HTML/CSS/JavaScript with Three.js.
363715
364669
  - **2d Games:** HTML/CSS/JavaScript.
363716
- 3. **User Approval:** Obtain user approval for the proposed plan.
364670
+ ${function() {
364671
+ if (interactiveMode) {
364672
+ return `3. **User Approval:** Obtain user approval for the proposed plan.
363717
364673
  4. **Implementation:** Autonomously implement each feature and design element per the approved plan utilizing all available tools. When starting ensure you scaffold the application using '${SHELL_TOOL_NAME}' for commands like 'npm init', 'npx create-react-app'. Aim for full scope completion. Proactively create or source necessary placeholder assets (e.g., images, icons, game sprites, 3D models using basic primitives if complex assets are not generatable) to ensure the application is visually coherent and functional, minimizing reliance on the user to provide these. If the model can generate simple assets (e.g., a uniformly colored square sprite, a simple 3D cube), it should do so. Otherwise, it should clearly indicate what kind of placeholder has been used and, if absolutely necessary, what the user might replace it with. Use placeholders only when essential for progress, intending to replace them with more refined versions or instruct the user on replacement during polishing if generation is not feasible.
363718
364674
  5. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.
363719
- 6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.`,
364675
+ 6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.`;
364676
+ } else {
364677
+ return `3. **Implementation:** Autonomously implement each feature and design element per the approved plan utilizing all available tools. When starting ensure you scaffold the application using '${SHELL_TOOL_NAME}' for commands like 'npm init', 'npx create-react-app'. Aim for full scope completion. Proactively create or source necessary placeholder assets (e.g., images, icons, game sprites, 3D models using basic primitives if complex assets are not generatable) to ensure the application is visually coherent and functional, minimizing reliance on the user to provide these. If the model can generate simple assets (e.g., a uniformly colored square sprite, a simple 3D cube), it should do so. Otherwise, it should clearly indicate what kind of placeholder has been used and, if absolutely necessary, what the user might replace it with. Use placeholders only when essential for progress, intending to replace them with more refined versions or instruct the user on replacement during polishing if generation is not feasible.
364678
+ 4. **Verify:** Review work against the original request, the approved plan. Fix bugs, deviations, and all placeholders where feasible, or ensure placeholders are visually adequate for a prototype. Ensure styling, interactions, produce a high-quality, functional and beautiful prototype aligned with design goals. Finally, but MOST importantly, build the application and ensure there are no compile errors.`;
364679
+ }
364680
+ }()}`,
363720
364681
  operationalGuidelines: `
363721
364682
  # Operational Guidelines
363722
364683
  ${function() {
@@ -363740,12 +364701,12 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
363740
364701
  ## Tone and Style (CLI Interaction)
363741
364702
  - **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
363742
364703
  - **Minimal Output:** Aim for fewer than 3 lines of text output (excluding tool use/code generation) per response whenever practical. Focus strictly on the user's query.
363743
- - **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
363744
- ${function() {
363745
- if (useChattySystemPrompt) {
364704
+ - **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.${function() {
364705
+ if (isGemini3) {
363746
364706
  return "";
363747
364707
  } else {
363748
- return '- **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.';
364708
+ return `
364709
+ - **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.`;
363749
364710
  }
363750
364711
  }()}
363751
364712
  - **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
@@ -363759,15 +364720,16 @@ ${function() {
363759
364720
  ## Tool Usage
363760
364721
  - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
363761
364722
  - **Command Execution:** Use the '${SHELL_TOOL_NAME}' tool for running shell commands, remembering the safety rule to explain modifying commands first.
363762
- - **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
363763
364723
  ${function() {
363764
- if (!config3.isInteractiveShellEnabled()) {
363765
- return `- **Interactive Commands:** Some commands are interactive, meaning they can accept user input during their execution (e.g. ssh, vim). Only execute non-interactive commands. Use non-interactive versions of commands (e.g. \`npm init -y\` instead of \`npm init\`) when available. Interactive shell commands are not supported and may cause hangs until canceled by the user.`;
364724
+ if (interactiveMode) {
364725
+ return `- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`. If unsure, ask the user.
364726
+ - **Interactive Commands:** Prefer non-interactive commands when it makes sense; however, some commands are only interactive and expect user input during their execution (e.g. ssh, vim). If you choose to execute an interactive command consider letting the user know they can press \`ctrl + f\` to focus into the shell to provide input.`;
363766
364727
  } else {
363767
- return `- **Interactive Commands:** Prefer non-interactive commands when it makes sense; however, some commands are only interactive and expect user input during their execution (e.g. ssh, vim). If you choose to execute an interactive command consider letting the user know they can press \`ctrl + f\` to focus into the shell to provide input.`;
364728
+ return `- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`.
364729
+ - **Interactive Commands:** Only execute non-interactive commands.`;
363768
364730
  }
363769
364731
  }()}
363770
- - **Remembering Facts:** Use the '${MEMORY_TOOL_NAME}' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information. If unsure whether to save something, you can ask the user, "Should I remember that for you?"
364732
+ - **Remembering Facts:** Use the '${MEMORY_TOOL_NAME}' tool to remember specific, *user-related* facts or preferences when the user explicitly asks, or when they state a clear, concise piece of information that would help personalize or streamline *your future interactions with them* (e.g., preferred coding style, common project paths they use, personal tool aliases). This tool is for user-specific information that should persist across sessions. Do *not* use it for general project context or information.${interactiveMode ? ` If unsure whether to save something, you can ask the user, "Should I remember that for you?"` : ""}
363771
364733
  - **Respect User Confirmations:** Most tool calls (also denoted as 'function calls') will first require confirmation from the user, where they will either approve or cancel the function call. If a user cancels a function call, respect their choice and do _not_ try to make the function call again. It is okay to request the tool call again _only_ if the user requests that same tool call on a subsequent prompt. When a user cancels a function call, assume best intentions from the user and consider inquiring if they prefer any alternative paths forward.
363772
364734
 
363773
364735
  ## Interaction Details
@@ -363807,8 +364769,8 @@ ${function() {
363807
364769
  - \`git log -n 3\` to review recent commit messages and match their style (verbosity, formatting, signature line, etc.)
363808
364770
  - Combine shell commands whenever possible to save time/steps, e.g. \`git status && git diff HEAD && git log -n 3\`.
363809
364771
  - Always propose a draft commit message. Never just ask the user to give you the full commit message.
363810
- - Prefer commit messages that are clear, concise, and focused more on "why" and less on "what".
363811
- - Keep the user informed and ask for clarification or confirmation where needed.
364772
+ - Prefer commit messages that are clear, concise, and focused more on "why" and less on "what".${interactiveMode ? `
364773
+ - Keep the user informed and ask for clarification or confirmation where needed.` : ""}
363812
364774
  - After each commit, confirm that it was successful by running \`git status\`.
363813
364775
  - If a commit fails, never attempt to work around the issues without being asked to do so.
363814
364776
  - Never push changes to a remote repository without being asked explicitly by the user.
@@ -364476,7 +365438,7 @@ var ChatCompressionService = class {
364476
365438
  ...historyToKeep
364477
365439
  ];
364478
365440
  const fullNewHistory = await getInitialChatHistory(config3, extraHistory);
364479
- const newTokenCount = Math.floor(fullNewHistory.reduce((total, content) => total + JSON.stringify(content).length, 0) / 4);
365441
+ const newTokenCount = await calculateRequestTokenCount(fullNewHistory.flatMap((c4) => c4.parts || []), config3.getContentGenerator(), model);
364480
365442
  logChatCompression(config3, makeChatCompressionEvent({
364481
365443
  tokens_before: originalTokenCount,
364482
365444
  tokens_after: newTokenCount
@@ -364503,405 +365465,6 @@ var ChatCompressionService = class {
364503
365465
  }
364504
365466
  };
364505
365467
 
364506
- // packages/core/dist/src/hooks/hookTranslator.js
364507
- var HookTranslator = class {
364508
- };
364509
- function hasTextProperty(value) {
364510
- return typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
364511
- }
364512
- function isContentWithParts(content) {
364513
- return typeof content === "object" && content !== null && "role" in content && "parts" in content;
364514
- }
364515
- function extractGenerationConfig(request3) {
364516
- if (request3.config && typeof request3.config === "object") {
364517
- const config3 = request3.config;
364518
- return {
364519
- temperature: config3.temperature,
364520
- maxOutputTokens: config3.maxOutputTokens,
364521
- topP: config3.topP,
364522
- topK: config3.topK
364523
- };
364524
- }
364525
- return void 0;
364526
- }
364527
- var HookTranslatorGenAIv1 = class extends HookTranslator {
364528
- /**
364529
- * Convert genai SDK GenerateContentParameters to stable LLMRequest
364530
- *
364531
- * Note: This implementation intentionally extracts only text content from parts.
364532
- * Non-text parts (images, function calls, etc.) are filtered out in v1 to provide
364533
- * a simplified, stable interface for hooks. This allows hooks to focus on text
364534
- * manipulation without needing to handle complex multimodal content.
364535
- * Future versions may expose additional content types if needed.
364536
- */
364537
- toHookLLMRequest(sdkRequest) {
364538
- const messages = [];
364539
- if (sdkRequest.contents) {
364540
- const contents = Array.isArray(sdkRequest.contents) ? sdkRequest.contents : [sdkRequest.contents];
364541
- for (const content of contents) {
364542
- if (typeof content === "string") {
364543
- messages.push({
364544
- role: "user",
364545
- content
364546
- });
364547
- } else if (isContentWithParts(content)) {
364548
- const role = content.role === "model" ? "model" : content.role === "system" ? "system" : "user";
364549
- const parts2 = Array.isArray(content.parts) ? content.parts : [content.parts];
364550
- const textContent2 = parts2.filter(hasTextProperty).map((part) => part.text).join("");
364551
- if (textContent2) {
364552
- messages.push({
364553
- role,
364554
- content: textContent2
364555
- });
364556
- }
364557
- }
364558
- }
364559
- }
364560
- const config3 = extractGenerationConfig(sdkRequest);
364561
- return {
364562
- model: sdkRequest.model || DEFAULT_GEMINI_FLASH_MODEL,
364563
- messages,
364564
- config: {
364565
- temperature: config3?.temperature,
364566
- maxOutputTokens: config3?.maxOutputTokens,
364567
- topP: config3?.topP,
364568
- topK: config3?.topK
364569
- }
364570
- };
364571
- }
364572
- /**
364573
- * Convert stable LLMRequest to genai SDK GenerateContentParameters
364574
- */
364575
- fromHookLLMRequest(hookRequest, baseRequest) {
364576
- const contents = hookRequest.messages.map((message) => ({
364577
- role: message.role === "model" ? "model" : message.role,
364578
- parts: [
364579
- {
364580
- text: typeof message.content === "string" ? message.content : String(message.content)
364581
- }
364582
- ]
364583
- }));
364584
- const result = {
364585
- ...baseRequest,
364586
- model: hookRequest.model,
364587
- contents
364588
- };
364589
- if (hookRequest.config) {
364590
- const baseConfig = baseRequest ? extractGenerationConfig(baseRequest) : void 0;
364591
- result.config = {
364592
- ...baseConfig,
364593
- temperature: hookRequest.config.temperature,
364594
- maxOutputTokens: hookRequest.config.maxOutputTokens,
364595
- topP: hookRequest.config.topP,
364596
- topK: hookRequest.config.topK
364597
- };
364598
- }
364599
- return result;
364600
- }
364601
- /**
364602
- * Convert genai SDK GenerateContentResponse to stable LLMResponse
364603
- */
364604
- toHookLLMResponse(sdkResponse) {
364605
- return {
364606
- text: sdkResponse.text,
364607
- candidates: (sdkResponse.candidates || []).map((candidate) => {
364608
- const textParts = candidate.content?.parts?.filter(hasTextProperty).map((part) => part.text) || [];
364609
- return {
364610
- content: {
364611
- role: "model",
364612
- parts: textParts
364613
- },
364614
- finishReason: candidate.finishReason,
364615
- index: candidate.index,
364616
- safetyRatings: candidate.safetyRatings?.map((rating) => ({
364617
- category: String(rating.category || ""),
364618
- probability: String(rating.probability || "")
364619
- }))
364620
- };
364621
- }),
364622
- usageMetadata: sdkResponse.usageMetadata ? {
364623
- promptTokenCount: sdkResponse.usageMetadata.promptTokenCount,
364624
- candidatesTokenCount: sdkResponse.usageMetadata.candidatesTokenCount,
364625
- totalTokenCount: sdkResponse.usageMetadata.totalTokenCount
364626
- } : void 0
364627
- };
364628
- }
364629
- /**
364630
- * Convert stable LLMResponse to genai SDK GenerateContentResponse
364631
- */
364632
- fromHookLLMResponse(hookResponse) {
364633
- const response = {
364634
- text: hookResponse.text,
364635
- candidates: hookResponse.candidates.map((candidate) => ({
364636
- content: {
364637
- role: "model",
364638
- parts: candidate.content.parts.map((part) => ({
364639
- text: part
364640
- }))
364641
- },
364642
- finishReason: candidate.finishReason,
364643
- index: candidate.index,
364644
- safetyRatings: candidate.safetyRatings
364645
- })),
364646
- usageMetadata: hookResponse.usageMetadata
364647
- };
364648
- return response;
364649
- }
364650
- /**
364651
- * Convert genai SDK ToolConfig to stable HookToolConfig
364652
- */
364653
- toHookToolConfig(sdkToolConfig) {
364654
- return {
364655
- mode: sdkToolConfig.functionCallingConfig?.mode,
364656
- allowedFunctionNames: sdkToolConfig.functionCallingConfig?.allowedFunctionNames
364657
- };
364658
- }
364659
- /**
364660
- * Convert stable HookToolConfig to genai SDK ToolConfig
364661
- */
364662
- fromHookToolConfig(hookToolConfig) {
364663
- const functionCallingConfig = hookToolConfig.mode || hookToolConfig.allowedFunctionNames ? {
364664
- mode: hookToolConfig.mode,
364665
- allowedFunctionNames: hookToolConfig.allowedFunctionNames
364666
- } : void 0;
364667
- return {
364668
- functionCallingConfig
364669
- };
364670
- }
364671
- };
364672
- var defaultHookTranslator = new HookTranslatorGenAIv1();
364673
-
364674
- // packages/core/dist/src/hooks/types.js
364675
- var HookEventName;
364676
- (function(HookEventName2) {
364677
- HookEventName2["BeforeTool"] = "BeforeTool";
364678
- HookEventName2["AfterTool"] = "AfterTool";
364679
- HookEventName2["BeforeAgent"] = "BeforeAgent";
364680
- HookEventName2["Notification"] = "Notification";
364681
- HookEventName2["AfterAgent"] = "AfterAgent";
364682
- HookEventName2["SessionStart"] = "SessionStart";
364683
- HookEventName2["SessionEnd"] = "SessionEnd";
364684
- HookEventName2["PreCompress"] = "PreCompress";
364685
- HookEventName2["BeforeModel"] = "BeforeModel";
364686
- HookEventName2["AfterModel"] = "AfterModel";
364687
- HookEventName2["BeforeToolSelection"] = "BeforeToolSelection";
364688
- })(HookEventName || (HookEventName = {}));
364689
- var HookType;
364690
- (function(HookType2) {
364691
- HookType2["Command"] = "command";
364692
- })(HookType || (HookType = {}));
364693
- function createHookOutput(eventName, data) {
364694
- switch (eventName) {
364695
- case "BeforeModel":
364696
- return new BeforeModelHookOutput(data);
364697
- case "AfterModel":
364698
- return new AfterModelHookOutput(data);
364699
- case "BeforeToolSelection":
364700
- return new BeforeToolSelectionHookOutput(data);
364701
- default:
364702
- return new DefaultHookOutput(data);
364703
- }
364704
- }
364705
- var DefaultHookOutput = class {
364706
- continue;
364707
- stopReason;
364708
- suppressOutput;
364709
- systemMessage;
364710
- decision;
364711
- reason;
364712
- hookSpecificOutput;
364713
- constructor(data = {}) {
364714
- this.continue = data.continue;
364715
- this.stopReason = data.stopReason;
364716
- this.suppressOutput = data.suppressOutput;
364717
- this.systemMessage = data.systemMessage;
364718
- this.decision = data.decision;
364719
- this.reason = data.reason;
364720
- this.hookSpecificOutput = data.hookSpecificOutput;
364721
- }
364722
- /**
364723
- * Check if this output represents a blocking decision
364724
- */
364725
- isBlockingDecision() {
364726
- return this.decision === "block" || this.decision === "deny";
364727
- }
364728
- /**
364729
- * Check if this output requests to stop execution
364730
- */
364731
- shouldStopExecution() {
364732
- return this.continue === false;
364733
- }
364734
- /**
364735
- * Get the effective reason for blocking or stopping
364736
- */
364737
- getEffectiveReason() {
364738
- return this.reason || this.stopReason || "No reason provided";
364739
- }
364740
- /**
364741
- * Apply LLM request modifications (specific method for BeforeModel hooks)
364742
- */
364743
- applyLLMRequestModifications(target) {
364744
- return target;
364745
- }
364746
- /**
364747
- * Apply tool config modifications (specific method for BeforeToolSelection hooks)
364748
- */
364749
- applyToolConfigModifications(target) {
364750
- return target;
364751
- }
364752
- /**
364753
- * Get additional context for adding to responses
364754
- */
364755
- getAdditionalContext() {
364756
- if (this.hookSpecificOutput && "additionalContext" in this.hookSpecificOutput) {
364757
- const context2 = this.hookSpecificOutput["additionalContext"];
364758
- return typeof context2 === "string" ? context2 : void 0;
364759
- }
364760
- return void 0;
364761
- }
364762
- /**
364763
- * Check if execution should be blocked and return error info
364764
- */
364765
- getBlockingError() {
364766
- if (this.isBlockingDecision()) {
364767
- return {
364768
- blocked: true,
364769
- reason: this.getEffectiveReason()
364770
- };
364771
- }
364772
- return { blocked: false, reason: "" };
364773
- }
364774
- };
364775
- var BeforeToolHookOutput = class extends DefaultHookOutput {
364776
- /**
364777
- * Get the effective blocking reason, considering compatibility fields
364778
- */
364779
- getEffectiveReason() {
364780
- if (this.hookSpecificOutput) {
364781
- if ("permissionDecisionReason" in this.hookSpecificOutput) {
364782
- const compatReason = this.hookSpecificOutput["permissionDecisionReason"];
364783
- if (typeof compatReason === "string") {
364784
- return compatReason;
364785
- }
364786
- }
364787
- }
364788
- return super.getEffectiveReason();
364789
- }
364790
- /**
364791
- * Check if this output represents a blocking decision, considering compatibility fields
364792
- */
364793
- isBlockingDecision() {
364794
- if (this.hookSpecificOutput && "permissionDecision" in this.hookSpecificOutput) {
364795
- const compatDecision = this.hookSpecificOutput["permissionDecision"];
364796
- if (compatDecision === "block" || compatDecision === "deny") {
364797
- return true;
364798
- }
364799
- }
364800
- return super.isBlockingDecision();
364801
- }
364802
- };
364803
- var BeforeModelHookOutput = class extends DefaultHookOutput {
364804
- /**
364805
- * Get synthetic LLM response if provided by hook
364806
- */
364807
- getSyntheticResponse() {
364808
- if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
364809
- const hookResponse = this.hookSpecificOutput["llm_response"];
364810
- if (hookResponse) {
364811
- return defaultHookTranslator.fromHookLLMResponse(hookResponse);
364812
- }
364813
- }
364814
- return void 0;
364815
- }
364816
- /**
364817
- * Apply modifications to LLM request
364818
- */
364819
- applyLLMRequestModifications(target) {
364820
- if (this.hookSpecificOutput && "llm_request" in this.hookSpecificOutput) {
364821
- const hookRequest = this.hookSpecificOutput["llm_request"];
364822
- if (hookRequest) {
364823
- const sdkRequest = defaultHookTranslator.fromHookLLMRequest(hookRequest, target);
364824
- return {
364825
- ...target,
364826
- ...sdkRequest
364827
- };
364828
- }
364829
- }
364830
- return target;
364831
- }
364832
- };
364833
- var BeforeToolSelectionHookOutput = class extends DefaultHookOutput {
364834
- /**
364835
- * Apply tool configuration modifications
364836
- */
364837
- applyToolConfigModifications(target) {
364838
- if (this.hookSpecificOutput && "toolConfig" in this.hookSpecificOutput) {
364839
- const hookToolConfig = this.hookSpecificOutput["toolConfig"];
364840
- if (hookToolConfig) {
364841
- const sdkToolConfig = defaultHookTranslator.fromHookToolConfig(hookToolConfig);
364842
- return {
364843
- ...target,
364844
- tools: target.tools || [],
364845
- toolConfig: sdkToolConfig
364846
- };
364847
- }
364848
- }
364849
- return target;
364850
- }
364851
- };
364852
- var AfterModelHookOutput = class extends DefaultHookOutput {
364853
- /**
364854
- * Get modified LLM response if provided by hook
364855
- */
364856
- getModifiedResponse() {
364857
- if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
364858
- const hookResponse = this.hookSpecificOutput["llm_response"];
364859
- if (hookResponse?.candidates?.[0]?.content?.parts?.length) {
364860
- return defaultHookTranslator.fromHookLLMResponse(hookResponse);
364861
- }
364862
- }
364863
- if (this.shouldStopExecution()) {
364864
- const stopResponse = {
364865
- candidates: [
364866
- {
364867
- content: {
364868
- role: "model",
364869
- parts: [this.getEffectiveReason() || "Execution stopped by hook"]
364870
- },
364871
- finishReason: "STOP"
364872
- }
364873
- ]
364874
- };
364875
- return defaultHookTranslator.fromHookLLMResponse(stopResponse);
364876
- }
364877
- return void 0;
364878
- }
364879
- };
364880
- var NotificationType;
364881
- (function(NotificationType2) {
364882
- NotificationType2["ToolPermission"] = "ToolPermission";
364883
- })(NotificationType || (NotificationType = {}));
364884
- var SessionStartSource;
364885
- (function(SessionStartSource2) {
364886
- SessionStartSource2["Startup"] = "startup";
364887
- SessionStartSource2["Resume"] = "resume";
364888
- SessionStartSource2["Clear"] = "clear";
364889
- SessionStartSource2["Compress"] = "compress";
364890
- })(SessionStartSource || (SessionStartSource = {}));
364891
- var SessionEndReason;
364892
- (function(SessionEndReason2) {
364893
- SessionEndReason2["Exit"] = "exit";
364894
- SessionEndReason2["Clear"] = "clear";
364895
- SessionEndReason2["Logout"] = "logout";
364896
- SessionEndReason2["PromptInputExit"] = "prompt_input_exit";
364897
- SessionEndReason2["Other"] = "other";
364898
- })(SessionEndReason || (SessionEndReason = {}));
364899
- var PreCompressTrigger;
364900
- (function(PreCompressTrigger2) {
364901
- PreCompressTrigger2["Manual"] = "manual";
364902
- PreCompressTrigger2["Auto"] = "auto";
364903
- })(PreCompressTrigger || (PreCompressTrigger = {}));
364904
-
364905
365468
  // packages/core/dist/src/core/clientHookTriggers.js
364906
365469
  async function fireBeforeAgentHook(messageBus, request3) {
364907
365470
  try {
@@ -364940,23 +365503,6 @@ async function fireAfterAgentHook(messageBus, request3, responseText) {
364940
365503
 
364941
365504
  // packages/core/dist/src/core/client.js
364942
365505
  var MAX_TURNS = 100;
364943
- function estimateTextOnlyLength(request3) {
364944
- if (typeof request3 === "string") {
364945
- return request3.length;
364946
- }
364947
- if (!Array.isArray(request3)) {
364948
- return 0;
364949
- }
364950
- let textLength = 0;
364951
- for (const part of request3) {
364952
- if (typeof part === "string") {
364953
- textLength += part.length;
364954
- } else if (typeof part === "object" && part !== null && "text" in part && part.text) {
364955
- textLength += part.text.length;
364956
- }
364957
- }
364958
- return textLength;
364959
- }
364960
365506
  var GeminiClient = class {
364961
365507
  config;
364962
365508
  chat;
@@ -365237,7 +365783,7 @@ var GeminiClient = class {
365237
365783
  return new Turn(this.getChat(), prompt_id);
365238
365784
  }
365239
365785
  const modelForLimitCheck = this._getEffectiveModelForCurrentTurn();
365240
- const estimatedRequestTokenCount = Math.floor(estimateTextOnlyLength(request3) / 4);
365786
+ const estimatedRequestTokenCount = await calculateRequestTokenCount(request3, this.getContentGeneratorOrFail(), modelForLimitCheck);
365241
365787
  const remainingTokenCount = tokenLimit(modelForLimitCheck) - this.getChat().getLastPromptTokenCount();
365242
365788
  if (estimatedRequestTokenCount > remainingTokenCount * 0.95) {
365243
365789
  yield {
@@ -370307,6 +370853,81 @@ var StandardFileSystemService = class {
370307
370853
  }
370308
370854
  };
370309
370855
 
370856
+ // packages/core/dist/src/availability/modelAvailabilityService.js
370857
+ var ModelAvailabilityService = class {
370858
+ health = /* @__PURE__ */ new Map();
370859
+ markTerminal(model, reason) {
370860
+ this.setState(model, {
370861
+ status: "terminal",
370862
+ reason
370863
+ });
370864
+ }
370865
+ markHealthy(model) {
370866
+ this.clearState(model);
370867
+ }
370868
+ markRetryOncePerTurn(model) {
370869
+ const currentState = this.health.get(model);
370870
+ if (currentState?.status === "terminal") {
370871
+ return;
370872
+ }
370873
+ let consumed = false;
370874
+ if (currentState?.status === "sticky_retry") {
370875
+ consumed = currentState.consumed;
370876
+ }
370877
+ this.setState(model, {
370878
+ status: "sticky_retry",
370879
+ reason: "retry_once_per_turn",
370880
+ consumed
370881
+ });
370882
+ }
370883
+ consumeStickyAttempt(model) {
370884
+ const state = this.health.get(model);
370885
+ if (state?.status === "sticky_retry") {
370886
+ this.setState(model, { ...state, consumed: true });
370887
+ }
370888
+ }
370889
+ snapshot(model) {
370890
+ const state = this.health.get(model);
370891
+ if (!state) {
370892
+ return { available: true };
370893
+ }
370894
+ if (state.status === "terminal") {
370895
+ return { available: false, reason: state.reason };
370896
+ }
370897
+ if (state.status === "sticky_retry" && state.consumed) {
370898
+ return { available: false, reason: state.reason };
370899
+ }
370900
+ return { available: true };
370901
+ }
370902
+ selectFirstAvailable(models) {
370903
+ const skipped = [];
370904
+ for (const model of models) {
370905
+ const snapshot = this.snapshot(model);
370906
+ if (snapshot.available) {
370907
+ const state = this.health.get(model);
370908
+ const attempts = state?.status === "sticky_retry" ? 1 : void 0;
370909
+ return { selectedModel: model, skipped, attempts };
370910
+ } else {
370911
+ skipped.push({ model, reason: snapshot.reason ?? "unknown" });
370912
+ }
370913
+ }
370914
+ return { selectedModel: null, skipped };
370915
+ }
370916
+ resetTurn() {
370917
+ for (const [model, state] of this.health.entries()) {
370918
+ if (state.status === "sticky_retry") {
370919
+ this.setState(model, { ...state, consumed: false });
370920
+ }
370921
+ }
370922
+ }
370923
+ setState(model, nextState) {
370924
+ this.health.set(model, nextState);
370925
+ }
370926
+ clearState(model) {
370927
+ this.health.delete(model);
370928
+ }
370929
+ };
370930
+
370310
370931
  // packages/core/dist/src/routing/strategies/defaultStrategy.js
370311
370932
  var DefaultStrategy = class {
370312
370933
  name = "default";
@@ -373914,7 +374535,7 @@ async function getClientMetadata() {
373914
374535
  clientMetadataPromise = (async () => ({
373915
374536
  ideName: "IDE_UNSPECIFIED",
373916
374537
  pluginType: "GEMINI",
373917
- ideVersion: "0.19.0-preview.0",
374538
+ ideVersion: "0.20.0-nightly.20251127.5bed97064",
373918
374539
  platform: getPlatform(),
373919
374540
  updateChannel: await getReleaseChannel(__dirname5)
373920
374541
  }))();
@@ -376601,7 +377222,9 @@ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDire
376601
377222
  }
376602
377223
  async function refreshServerHierarchicalMemory(config3) {
376603
377224
  const result = await loadServerHierarchicalMemory(config3.getWorkingDir(), config3.shouldLoadMemoryFromIncludeDirectories() ? config3.getWorkspaceContext().getDirectories() : [], config3.getDebugMode(), config3.getFileService(), config3.getExtensionLoader(), config3.isTrustedFolder(), config3.getImportFormat(), config3.getFileFilteringOptions(), config3.getDiscoveryMaxDirs());
376604
- config3.setUserMemory(result.memoryContent);
377225
+ const mcpInstructions = config3.getMcpClientManager()?.getMcpInstructions() || "";
377226
+ const finalMemory = [result.memoryContent, mcpInstructions.trimStart()].filter(Boolean).join("\n\n");
377227
+ config3.setUserMemory(finalMemory);
376605
377228
  config3.setGeminiMdFileCount(result.fileCount);
376606
377229
  config3.setGeminiMdFilePaths(result.filePaths);
376607
377230
  coreEvents.emit(CoreEvent.MemoryChanged, result);
@@ -377585,6 +378208,30 @@ var GoogleCredentialProvider = class {
377585
378208
  codeVerifier() {
377586
378209
  return "";
377587
378210
  }
378211
+ /**
378212
+ * Returns the project ID used for quota.
378213
+ */
378214
+ async getQuotaProjectId() {
378215
+ const client = await this.auth.getClient();
378216
+ return client.quotaProjectId;
378217
+ }
378218
+ /**
378219
+ * Returns custom headers to be added to the request.
378220
+ */
378221
+ async getRequestHeaders() {
378222
+ const headers = {};
378223
+ const configHeaders = this.config?.headers ?? {};
378224
+ const userProjectHeaderKey = Object.keys(configHeaders).find((key) => key.toLowerCase() === "x-goog-user-project");
378225
+ if (userProjectHeaderKey) {
378226
+ headers[userProjectHeaderKey] = configHeaders[userProjectHeaderKey];
378227
+ } else {
378228
+ const quotaProjectId = await this.getQuotaProjectId();
378229
+ if (quotaProjectId) {
378230
+ headers["X-Goog-User-Project"] = quotaProjectId;
378231
+ }
378232
+ }
378233
+ return headers;
378234
+ }
377588
378235
  };
377589
378236
 
377590
378237
  // packages/core/dist/src/mcp/sa-impersonation-provider.js
@@ -378567,6 +379214,9 @@ var McpClient = class {
378567
379214
  getServerConfig() {
378568
379215
  return this.serverConfig;
378569
379216
  }
379217
+ getInstructions() {
379218
+ return this.client?.getInstructions();
379219
+ }
378570
379220
  };
378571
379221
  var serverStatuses = /* @__PURE__ */ new Map();
378572
379222
  var mcpDiscoveryState = MCPDiscoveryState.NOT_STARTED;
@@ -379045,7 +379695,7 @@ async function createTransport(mcpServerName, mcpServerConfig, debugMode) {
379045
379695
  }
379046
379696
  if (mcpServerConfig.httpUrl || mcpServerConfig.url) {
379047
379697
  const authProvider = createAuthProvider(mcpServerConfig);
379048
- const headers = {};
379698
+ const headers = await authProvider?.getRequestHeaders?.() ?? {};
379049
379699
  if (authProvider === void 0) {
379050
379700
  let accessToken = null;
379051
379701
  let hasOAuthConfig = mcpServerConfig.oauth?.enabled;
@@ -379322,6 +379972,19 @@ var McpClientManager = class {
379322
379972
  }
379323
379973
  return mcpServers;
379324
379974
  }
379975
+ getMcpInstructions() {
379976
+ const instructions = [];
379977
+ for (const [name4, client] of this.clients) {
379978
+ if (client.getServerConfig().useInstructions) {
379979
+ const clientInstructions = client.getInstructions();
379980
+ if (clientInstructions) {
379981
+ instructions.push(`# Instructions for MCP Server '${name4}'
379982
+ ${clientInstructions}`);
379983
+ }
379984
+ }
379985
+ }
379986
+ return instructions.join("\n\n");
379987
+ }
379325
379988
  };
379326
379989
 
379327
379990
  // packages/core/dist/src/config/config.js
@@ -379369,6 +380032,7 @@ var Config = class {
379369
380032
  geminiClient;
379370
380033
  baseLlmClient;
379371
380034
  modelRouterService;
380035
+ modelAvailabilityService;
379372
380036
  fileFiltering;
379373
380037
  fileDiscoveryService = null;
379374
380038
  gitService = void 0;
@@ -379423,6 +380087,7 @@ var Config = class {
379423
380087
  continueOnFailedApiCall;
379424
380088
  retryFetchErrors;
379425
380089
  enableShellOutputEfficiency;
380090
+ shellToolInactivityTimeout;
379426
380091
  fakeResponses;
379427
380092
  recordResponses;
379428
380093
  disableYoloMode;
@@ -379484,6 +380149,7 @@ var Config = class {
379484
380149
  this.bugCommand = params.bugCommand;
379485
380150
  this.model = params.model;
379486
380151
  this.enableModelAvailabilityService = params.enableModelAvailabilityService ?? false;
380152
+ this.modelAvailabilityService = new ModelAvailabilityService();
379487
380153
  this.previewFeatures = params.previewFeatures ?? void 0;
379488
380154
  this.maxSessionTurns = params.maxSessionTurns ?? -1;
379489
380155
  this.experimentalZedIntegration = params.experimentalZedIntegration ?? false;
@@ -379530,6 +380196,7 @@ var Config = class {
379530
380196
  };
379531
380197
  this.continueOnFailedApiCall = params.continueOnFailedApiCall ?? true;
379532
380198
  this.enableShellOutputEfficiency = params.enableShellOutputEfficiency ?? true;
380199
+ this.shellToolInactivityTimeout = (params.shellToolInactivityTimeout ?? 300) * 1e3;
379533
380200
  this.extensionManagement = params.extensionManagement ?? true;
379534
380201
  this.enableExtensionReloading = params.enableExtensionReloading ?? false;
379535
380202
  this.storage = new Storage2(this.targetDir);
@@ -379890,6 +380557,9 @@ var Config = class {
379890
380557
  getModelRouterService() {
379891
380558
  return this.modelRouterService;
379892
380559
  }
380560
+ getModelAvailabilityService() {
380561
+ return this.modelAvailabilityService;
380562
+ }
379893
380563
  getEnableRecursiveFileSearch() {
379894
380564
  return this.fileFiltering.enableRecursiveFileSearch;
379895
380565
  }
@@ -380070,6 +380740,9 @@ var Config = class {
380070
380740
  getEnableShellOutputEfficiency() {
380071
380741
  return this.enableShellOutputEfficiency;
380072
380742
  }
380743
+ getShellToolInactivityTimeout() {
380744
+ return this.shellToolInactivityTimeout;
380745
+ }
380073
380746
  getShellExecutionConfig() {
380074
380747
  return this.shellExecutionConfig;
380075
380748
  }