@google/gemini-cli-a2a-server 0.19.0-preview.0 → 0.20.0-nightly.20251130.576fda18e

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.
@@ -304821,6 +304821,9 @@ var CodeAssistServer = class {
304821
304821
  };
304822
304822
  return await this.requestPost("listExperiments", req);
304823
304823
  }
304824
+ async retrieveUserQuota(req) {
304825
+ return await this.requestPost("retrieveUserQuota", req);
304826
+ }
304824
304827
  async requestPost(method, req, signal) {
304825
304828
  const res = await this.client.request({
304826
304829
  url: this.getMethodUrl(method),
@@ -306930,6 +306933,7 @@ var ApiResponseEvent = class {
306930
306933
  prompt;
306931
306934
  response;
306932
306935
  usage;
306936
+ finish_reasons;
306933
306937
  constructor(model, duration_ms, prompt_details, response_details, auth_type, usage_data, response_text) {
306934
306938
  this["event.name"] = "api_response";
306935
306939
  this["event.timestamp"] = (/* @__PURE__ */ new Date()).toISOString();
@@ -306948,6 +306952,7 @@ var ApiResponseEvent = class {
306948
306952
  tool_token_count: usage_data?.toolUsePromptTokenCount ?? 0,
306949
306953
  total_token_count: usage_data?.totalTokenCount ?? 0
306950
306954
  };
306955
+ this.finish_reasons = toFinishReasons(this.response.candidates);
306951
306956
  }
306952
306957
  toLogRecord(config3) {
306953
306958
  const attributes = {
@@ -306964,7 +306969,8 @@ var ApiResponseEvent = class {
306964
306969
  total_token_count: this.usage.total_token_count,
306965
306970
  prompt_id: this.prompt.prompt_id,
306966
306971
  auth_type: this.auth_type,
306967
- status_code: this.status_code
306972
+ status_code: this.status_code,
306973
+ finish_reasons: this.finish_reasons
306968
306974
  };
306969
306975
  if (this.response_text) {
306970
306976
  attributes["response_text"] = this.response_text;
@@ -306986,7 +306992,7 @@ var ApiResponseEvent = class {
306986
306992
  "event.name": EVENT_GEN_AI_OPERATION_DETAILS,
306987
306993
  "event.timestamp": this["event.timestamp"],
306988
306994
  "gen_ai.response.id": this.response.response_id,
306989
- "gen_ai.response.finish_reasons": toFinishReasons(this.response.candidates),
306995
+ "gen_ai.response.finish_reasons": this.finish_reasons,
306990
306996
  "gen_ai.output.messages": JSON.stringify(toOutputMessages(this.response.candidates)),
306991
306997
  ...toGenerateContentConfigAttributes(this.prompt.generate_content_config),
306992
306998
  ...getConventionAttributes(this)
@@ -307803,8 +307809,8 @@ var Float64Vector = import_vector.default.Float64Vector;
307803
307809
  var PointerVector = import_vector.default.PointerVector;
307804
307810
 
307805
307811
  // packages/core/dist/src/generated/git-commit.js
307806
- var GIT_COMMIT_INFO = "d2a6cff4d";
307807
- var CLI_VERSION = "0.19.0-preview.0";
307812
+ var GIT_COMMIT_INFO = "576fda18e";
307813
+ var CLI_VERSION = "0.20.0-nightly.20251130.576fda18e";
307808
307814
 
307809
307815
  // packages/core/dist/src/ide/detect-ide.js
307810
307816
  var IDE_DEFINITIONS = {
@@ -310731,7 +310737,7 @@ async function createContentGenerator(config3, gcConfig, sessionId2) {
310731
310737
  if (gcConfig.fakeResponses) {
310732
310738
  return FakeContentGenerator.fromFile(gcConfig.fakeResponses);
310733
310739
  }
310734
- const version4 = "0.19.0-preview.0";
310740
+ const version4 = "0.20.0-nightly.20251130.576fda18e";
310735
310741
  const customHeadersEnv = process.env["GEMINI_CLI_CUSTOM_HEADERS"] || void 0;
310736
310742
  const userAgent = `GeminiCLI/${version4} (${process.platform}; ${process.arch})`;
310737
310743
  const customHeadersMap = parseCustomHeaders(customHeadersEnv);
@@ -354764,7 +354770,8 @@ var ShellExecutionService = class {
354764
354770
  ...process.env,
354765
354771
  GEMINI_CLI: "1",
354766
354772
  TERM: "xterm-256color",
354767
- PAGER: "cat"
354773
+ PAGER: "cat",
354774
+ GIT_PAGER: "cat"
354768
354775
  }
354769
354776
  });
354770
354777
  const result = new Promise((resolve14) => {
@@ -354932,7 +354939,8 @@ var ShellExecutionService = class {
354932
354939
  ...process.env,
354933
354940
  GEMINI_CLI: "1",
354934
354941
  TERM: "xterm-256color",
354935
- PAGER: shellExecutionConfig.pager ?? "cat"
354942
+ PAGER: shellExecutionConfig.pager ?? "cat",
354943
+ GIT_PAGER: shellExecutionConfig.pager ?? "cat"
354936
354944
  },
354937
354945
  handleFlowControl: true
354938
354946
  });
@@ -355301,6 +355309,11 @@ var ShellToolInvocation = class extends BaseToolInvocation {
355301
355309
  const isWindows5 = os16.platform() === "win32";
355302
355310
  const tempFileName = `shell_pgrep_${crypto20.randomBytes(6).toString("hex")}.tmp`;
355303
355311
  const tempFilePath = path43.join(os16.tmpdir(), tempFileName);
355312
+ const timeoutMs = this.config.getShellToolInactivityTimeout();
355313
+ const timeoutController = new AbortController();
355314
+ let timeoutTimer;
355315
+ const combinedController = new AbortController();
355316
+ const onAbort = () => combinedController.abort();
355304
355317
  try {
355305
355318
  const commandToExecute = isWindows5 ? strippedCommand : (() => {
355306
355319
  let command = strippedCommand.trim();
@@ -355312,7 +355325,23 @@ var ShellToolInvocation = class extends BaseToolInvocation {
355312
355325
  let cumulativeOutput = "";
355313
355326
  let lastUpdateTime = Date.now();
355314
355327
  let isBinaryStream = false;
355328
+ const resetTimeout = () => {
355329
+ if (timeoutMs <= 0) {
355330
+ return;
355331
+ }
355332
+ if (timeoutTimer)
355333
+ clearTimeout(timeoutTimer);
355334
+ timeoutTimer = setTimeout(() => {
355335
+ timeoutController.abort();
355336
+ }, timeoutMs);
355337
+ };
355338
+ signal.addEventListener("abort", onAbort, { once: true });
355339
+ timeoutController.signal.addEventListener("abort", onAbort, {
355340
+ once: true
355341
+ });
355342
+ resetTimeout();
355315
355343
  const { result: resultPromise, pid } = await ShellExecutionService.execute(commandToExecute, cwd, (event) => {
355344
+ resetTimeout();
355316
355345
  if (!updateOutput) {
355317
355346
  return;
355318
355347
  }
@@ -355344,7 +355373,7 @@ var ShellToolInvocation = class extends BaseToolInvocation {
355344
355373
  updateOutput(cumulativeOutput);
355345
355374
  lastUpdateTime = Date.now();
355346
355375
  }
355347
- }, signal, this.config.getEnableInteractiveShell(), shellExecutionConfig ?? {});
355376
+ }, combinedController.signal, this.config.getEnableInteractiveShell(), { ...shellExecutionConfig, pager: "cat" });
355348
355377
  if (pid && setPidCallback) {
355349
355378
  setPidCallback(pid);
355350
355379
  }
@@ -355369,8 +355398,14 @@ var ShellToolInvocation = class extends BaseToolInvocation {
355369
355398
  }
355370
355399
  }
355371
355400
  let llmContent = "";
355401
+ let timeoutMessage = "";
355372
355402
  if (result.aborted) {
355373
- llmContent = "Command was cancelled by user before it could complete.";
355403
+ if (timeoutController.signal.aborted) {
355404
+ timeoutMessage = `Command was automatically cancelled because it exceeded the timeout of ${(timeoutMs / 6e4).toFixed(1)} minutes without output.`;
355405
+ llmContent = timeoutMessage;
355406
+ } else {
355407
+ llmContent = "Command was cancelled by user before it could complete.";
355408
+ }
355374
355409
  if (result.output.trim()) {
355375
355410
  llmContent += ` Below is the output before it was cancelled:
355376
355411
  ${result.output}`;
@@ -355399,7 +355434,11 @@ ${result.output}`;
355399
355434
  returnDisplayMessage = result.output;
355400
355435
  } else {
355401
355436
  if (result.aborted) {
355402
- returnDisplayMessage = "Command cancelled by user.";
355437
+ if (timeoutMessage) {
355438
+ returnDisplayMessage = timeoutMessage;
355439
+ } else {
355440
+ returnDisplayMessage = "Command cancelled by user.";
355441
+ }
355403
355442
  } else if (result.signal) {
355404
355443
  returnDisplayMessage = `Command terminated by signal: ${result.signal}`;
355405
355444
  } else if (result.error) {
@@ -355430,6 +355469,10 @@ ${result.output}`;
355430
355469
  ...executionError
355431
355470
  };
355432
355471
  } finally {
355472
+ if (timeoutTimer)
355473
+ clearTimeout(timeoutTimer);
355474
+ signal.removeEventListener("abort", onAbort);
355475
+ timeoutController.signal.removeEventListener("abort", onAbort);
355433
355476
  if (fs41.existsSync(tempFilePath)) {
355434
355477
  fs41.unlinkSync(tempFilePath);
355435
355478
  }
@@ -361453,6 +361496,580 @@ function getResponseTextFromParts(parts2) {
361453
361496
  import * as fs44 from "node:fs/promises";
361454
361497
  import * as path46 from "node:path";
361455
361498
  var import_fast_levenshtein = __toESM(require_levenshtein(), 1);
361499
+
361500
+ // packages/core/dist/src/hooks/hookTranslator.js
361501
+ var HookTranslator = class {
361502
+ };
361503
+ function hasTextProperty(value) {
361504
+ return typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
361505
+ }
361506
+ function isContentWithParts(content) {
361507
+ return typeof content === "object" && content !== null && "role" in content && "parts" in content;
361508
+ }
361509
+ function extractGenerationConfig(request3) {
361510
+ if (request3.config && typeof request3.config === "object") {
361511
+ const config3 = request3.config;
361512
+ return {
361513
+ temperature: config3.temperature,
361514
+ maxOutputTokens: config3.maxOutputTokens,
361515
+ topP: config3.topP,
361516
+ topK: config3.topK
361517
+ };
361518
+ }
361519
+ return void 0;
361520
+ }
361521
+ var HookTranslatorGenAIv1 = class extends HookTranslator {
361522
+ /**
361523
+ * Convert genai SDK GenerateContentParameters to stable LLMRequest
361524
+ *
361525
+ * Note: This implementation intentionally extracts only text content from parts.
361526
+ * Non-text parts (images, function calls, etc.) are filtered out in v1 to provide
361527
+ * a simplified, stable interface for hooks. This allows hooks to focus on text
361528
+ * manipulation without needing to handle complex multimodal content.
361529
+ * Future versions may expose additional content types if needed.
361530
+ */
361531
+ toHookLLMRequest(sdkRequest) {
361532
+ const messages = [];
361533
+ if (sdkRequest.contents) {
361534
+ const contents = Array.isArray(sdkRequest.contents) ? sdkRequest.contents : [sdkRequest.contents];
361535
+ for (const content of contents) {
361536
+ if (typeof content === "string") {
361537
+ messages.push({
361538
+ role: "user",
361539
+ content
361540
+ });
361541
+ } else if (isContentWithParts(content)) {
361542
+ const role = content.role === "model" ? "model" : content.role === "system" ? "system" : "user";
361543
+ const parts2 = Array.isArray(content.parts) ? content.parts : [content.parts];
361544
+ const textContent2 = parts2.filter(hasTextProperty).map((part) => part.text).join("");
361545
+ if (textContent2) {
361546
+ messages.push({
361547
+ role,
361548
+ content: textContent2
361549
+ });
361550
+ }
361551
+ }
361552
+ }
361553
+ }
361554
+ const config3 = extractGenerationConfig(sdkRequest);
361555
+ return {
361556
+ model: sdkRequest.model || DEFAULT_GEMINI_FLASH_MODEL,
361557
+ messages,
361558
+ config: {
361559
+ temperature: config3?.temperature,
361560
+ maxOutputTokens: config3?.maxOutputTokens,
361561
+ topP: config3?.topP,
361562
+ topK: config3?.topK
361563
+ }
361564
+ };
361565
+ }
361566
+ /**
361567
+ * Convert stable LLMRequest to genai SDK GenerateContentParameters
361568
+ */
361569
+ fromHookLLMRequest(hookRequest, baseRequest) {
361570
+ const contents = hookRequest.messages.map((message) => ({
361571
+ role: message.role === "model" ? "model" : message.role,
361572
+ parts: [
361573
+ {
361574
+ text: typeof message.content === "string" ? message.content : String(message.content)
361575
+ }
361576
+ ]
361577
+ }));
361578
+ const result = {
361579
+ ...baseRequest,
361580
+ model: hookRequest.model,
361581
+ contents
361582
+ };
361583
+ if (hookRequest.config) {
361584
+ const baseConfig = baseRequest ? extractGenerationConfig(baseRequest) : void 0;
361585
+ result.config = {
361586
+ ...baseConfig,
361587
+ temperature: hookRequest.config.temperature,
361588
+ maxOutputTokens: hookRequest.config.maxOutputTokens,
361589
+ topP: hookRequest.config.topP,
361590
+ topK: hookRequest.config.topK
361591
+ };
361592
+ }
361593
+ return result;
361594
+ }
361595
+ /**
361596
+ * Convert genai SDK GenerateContentResponse to stable LLMResponse
361597
+ */
361598
+ toHookLLMResponse(sdkResponse) {
361599
+ return {
361600
+ text: sdkResponse.text,
361601
+ candidates: (sdkResponse.candidates || []).map((candidate) => {
361602
+ const textParts = candidate.content?.parts?.filter(hasTextProperty).map((part) => part.text) || [];
361603
+ return {
361604
+ content: {
361605
+ role: "model",
361606
+ parts: textParts
361607
+ },
361608
+ finishReason: candidate.finishReason,
361609
+ index: candidate.index,
361610
+ safetyRatings: candidate.safetyRatings?.map((rating) => ({
361611
+ category: String(rating.category || ""),
361612
+ probability: String(rating.probability || "")
361613
+ }))
361614
+ };
361615
+ }),
361616
+ usageMetadata: sdkResponse.usageMetadata ? {
361617
+ promptTokenCount: sdkResponse.usageMetadata.promptTokenCount,
361618
+ candidatesTokenCount: sdkResponse.usageMetadata.candidatesTokenCount,
361619
+ totalTokenCount: sdkResponse.usageMetadata.totalTokenCount
361620
+ } : void 0
361621
+ };
361622
+ }
361623
+ /**
361624
+ * Convert stable LLMResponse to genai SDK GenerateContentResponse
361625
+ */
361626
+ fromHookLLMResponse(hookResponse) {
361627
+ const response = {
361628
+ text: hookResponse.text,
361629
+ candidates: hookResponse.candidates.map((candidate) => ({
361630
+ content: {
361631
+ role: "model",
361632
+ parts: candidate.content.parts.map((part) => ({
361633
+ text: part
361634
+ }))
361635
+ },
361636
+ finishReason: candidate.finishReason,
361637
+ index: candidate.index,
361638
+ safetyRatings: candidate.safetyRatings
361639
+ })),
361640
+ usageMetadata: hookResponse.usageMetadata
361641
+ };
361642
+ return response;
361643
+ }
361644
+ /**
361645
+ * Convert genai SDK ToolConfig to stable HookToolConfig
361646
+ */
361647
+ toHookToolConfig(sdkToolConfig) {
361648
+ return {
361649
+ mode: sdkToolConfig.functionCallingConfig?.mode,
361650
+ allowedFunctionNames: sdkToolConfig.functionCallingConfig?.allowedFunctionNames
361651
+ };
361652
+ }
361653
+ /**
361654
+ * Convert stable HookToolConfig to genai SDK ToolConfig
361655
+ */
361656
+ fromHookToolConfig(hookToolConfig) {
361657
+ const functionCallingConfig = hookToolConfig.mode || hookToolConfig.allowedFunctionNames ? {
361658
+ mode: hookToolConfig.mode,
361659
+ allowedFunctionNames: hookToolConfig.allowedFunctionNames
361660
+ } : void 0;
361661
+ return {
361662
+ functionCallingConfig
361663
+ };
361664
+ }
361665
+ };
361666
+ var defaultHookTranslator = new HookTranslatorGenAIv1();
361667
+
361668
+ // packages/core/dist/src/hooks/types.js
361669
+ var HookEventName;
361670
+ (function(HookEventName2) {
361671
+ HookEventName2["BeforeTool"] = "BeforeTool";
361672
+ HookEventName2["AfterTool"] = "AfterTool";
361673
+ HookEventName2["BeforeAgent"] = "BeforeAgent";
361674
+ HookEventName2["Notification"] = "Notification";
361675
+ HookEventName2["AfterAgent"] = "AfterAgent";
361676
+ HookEventName2["SessionStart"] = "SessionStart";
361677
+ HookEventName2["SessionEnd"] = "SessionEnd";
361678
+ HookEventName2["PreCompress"] = "PreCompress";
361679
+ HookEventName2["BeforeModel"] = "BeforeModel";
361680
+ HookEventName2["AfterModel"] = "AfterModel";
361681
+ HookEventName2["BeforeToolSelection"] = "BeforeToolSelection";
361682
+ })(HookEventName || (HookEventName = {}));
361683
+ var HookType;
361684
+ (function(HookType2) {
361685
+ HookType2["Command"] = "command";
361686
+ })(HookType || (HookType = {}));
361687
+ function createHookOutput(eventName, data) {
361688
+ switch (eventName) {
361689
+ case "BeforeModel":
361690
+ return new BeforeModelHookOutput(data);
361691
+ case "AfterModel":
361692
+ return new AfterModelHookOutput(data);
361693
+ case "BeforeToolSelection":
361694
+ return new BeforeToolSelectionHookOutput(data);
361695
+ default:
361696
+ return new DefaultHookOutput(data);
361697
+ }
361698
+ }
361699
+ var DefaultHookOutput = class {
361700
+ continue;
361701
+ stopReason;
361702
+ suppressOutput;
361703
+ systemMessage;
361704
+ decision;
361705
+ reason;
361706
+ hookSpecificOutput;
361707
+ constructor(data = {}) {
361708
+ this.continue = data.continue;
361709
+ this.stopReason = data.stopReason;
361710
+ this.suppressOutput = data.suppressOutput;
361711
+ this.systemMessage = data.systemMessage;
361712
+ this.decision = data.decision;
361713
+ this.reason = data.reason;
361714
+ this.hookSpecificOutput = data.hookSpecificOutput;
361715
+ }
361716
+ /**
361717
+ * Check if this output represents a blocking decision
361718
+ */
361719
+ isBlockingDecision() {
361720
+ return this.decision === "block" || this.decision === "deny";
361721
+ }
361722
+ /**
361723
+ * Check if this output requests to stop execution
361724
+ */
361725
+ shouldStopExecution() {
361726
+ return this.continue === false;
361727
+ }
361728
+ /**
361729
+ * Get the effective reason for blocking or stopping
361730
+ */
361731
+ getEffectiveReason() {
361732
+ return this.reason || this.stopReason || "No reason provided";
361733
+ }
361734
+ /**
361735
+ * Apply LLM request modifications (specific method for BeforeModel hooks)
361736
+ */
361737
+ applyLLMRequestModifications(target) {
361738
+ return target;
361739
+ }
361740
+ /**
361741
+ * Apply tool config modifications (specific method for BeforeToolSelection hooks)
361742
+ */
361743
+ applyToolConfigModifications(target) {
361744
+ return target;
361745
+ }
361746
+ /**
361747
+ * Get additional context for adding to responses
361748
+ */
361749
+ getAdditionalContext() {
361750
+ if (this.hookSpecificOutput && "additionalContext" in this.hookSpecificOutput) {
361751
+ const context2 = this.hookSpecificOutput["additionalContext"];
361752
+ return typeof context2 === "string" ? context2 : void 0;
361753
+ }
361754
+ return void 0;
361755
+ }
361756
+ /**
361757
+ * Check if execution should be blocked and return error info
361758
+ */
361759
+ getBlockingError() {
361760
+ if (this.isBlockingDecision()) {
361761
+ return {
361762
+ blocked: true,
361763
+ reason: this.getEffectiveReason()
361764
+ };
361765
+ }
361766
+ return { blocked: false, reason: "" };
361767
+ }
361768
+ };
361769
+ var BeforeToolHookOutput = class extends DefaultHookOutput {
361770
+ /**
361771
+ * Get the effective blocking reason, considering compatibility fields
361772
+ */
361773
+ getEffectiveReason() {
361774
+ if (this.hookSpecificOutput) {
361775
+ if ("permissionDecisionReason" in this.hookSpecificOutput) {
361776
+ const compatReason = this.hookSpecificOutput["permissionDecisionReason"];
361777
+ if (typeof compatReason === "string") {
361778
+ return compatReason;
361779
+ }
361780
+ }
361781
+ }
361782
+ return super.getEffectiveReason();
361783
+ }
361784
+ /**
361785
+ * Check if this output represents a blocking decision, considering compatibility fields
361786
+ */
361787
+ isBlockingDecision() {
361788
+ if (this.hookSpecificOutput && "permissionDecision" in this.hookSpecificOutput) {
361789
+ const compatDecision = this.hookSpecificOutput["permissionDecision"];
361790
+ if (compatDecision === "block" || compatDecision === "deny") {
361791
+ return true;
361792
+ }
361793
+ }
361794
+ return super.isBlockingDecision();
361795
+ }
361796
+ };
361797
+ var BeforeModelHookOutput = class extends DefaultHookOutput {
361798
+ /**
361799
+ * Get synthetic LLM response if provided by hook
361800
+ */
361801
+ getSyntheticResponse() {
361802
+ if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
361803
+ const hookResponse = this.hookSpecificOutput["llm_response"];
361804
+ if (hookResponse) {
361805
+ return defaultHookTranslator.fromHookLLMResponse(hookResponse);
361806
+ }
361807
+ }
361808
+ return void 0;
361809
+ }
361810
+ /**
361811
+ * Apply modifications to LLM request
361812
+ */
361813
+ applyLLMRequestModifications(target) {
361814
+ if (this.hookSpecificOutput && "llm_request" in this.hookSpecificOutput) {
361815
+ const hookRequest = this.hookSpecificOutput["llm_request"];
361816
+ if (hookRequest) {
361817
+ const sdkRequest = defaultHookTranslator.fromHookLLMRequest(hookRequest, target);
361818
+ return {
361819
+ ...target,
361820
+ ...sdkRequest
361821
+ };
361822
+ }
361823
+ }
361824
+ return target;
361825
+ }
361826
+ };
361827
+ var BeforeToolSelectionHookOutput = class extends DefaultHookOutput {
361828
+ /**
361829
+ * Apply tool configuration modifications
361830
+ */
361831
+ applyToolConfigModifications(target) {
361832
+ if (this.hookSpecificOutput && "toolConfig" in this.hookSpecificOutput) {
361833
+ const hookToolConfig = this.hookSpecificOutput["toolConfig"];
361834
+ if (hookToolConfig) {
361835
+ const sdkToolConfig = defaultHookTranslator.fromHookToolConfig(hookToolConfig);
361836
+ return {
361837
+ ...target,
361838
+ tools: target.tools || [],
361839
+ toolConfig: sdkToolConfig
361840
+ };
361841
+ }
361842
+ }
361843
+ return target;
361844
+ }
361845
+ };
361846
+ var AfterModelHookOutput = class extends DefaultHookOutput {
361847
+ /**
361848
+ * Get modified LLM response if provided by hook
361849
+ */
361850
+ getModifiedResponse() {
361851
+ if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
361852
+ const hookResponse = this.hookSpecificOutput["llm_response"];
361853
+ if (hookResponse?.candidates?.[0]?.content?.parts?.length) {
361854
+ return defaultHookTranslator.fromHookLLMResponse(hookResponse);
361855
+ }
361856
+ }
361857
+ if (this.shouldStopExecution()) {
361858
+ const stopResponse = {
361859
+ candidates: [
361860
+ {
361861
+ content: {
361862
+ role: "model",
361863
+ parts: [this.getEffectiveReason() || "Execution stopped by hook"]
361864
+ },
361865
+ finishReason: "STOP"
361866
+ }
361867
+ ]
361868
+ };
361869
+ return defaultHookTranslator.fromHookLLMResponse(stopResponse);
361870
+ }
361871
+ return void 0;
361872
+ }
361873
+ };
361874
+ var NotificationType;
361875
+ (function(NotificationType2) {
361876
+ NotificationType2["ToolPermission"] = "ToolPermission";
361877
+ })(NotificationType || (NotificationType = {}));
361878
+ var SessionStartSource;
361879
+ (function(SessionStartSource2) {
361880
+ SessionStartSource2["Startup"] = "startup";
361881
+ SessionStartSource2["Resume"] = "resume";
361882
+ SessionStartSource2["Clear"] = "clear";
361883
+ SessionStartSource2["Compress"] = "compress";
361884
+ })(SessionStartSource || (SessionStartSource = {}));
361885
+ var SessionEndReason;
361886
+ (function(SessionEndReason2) {
361887
+ SessionEndReason2["Exit"] = "exit";
361888
+ SessionEndReason2["Clear"] = "clear";
361889
+ SessionEndReason2["Logout"] = "logout";
361890
+ SessionEndReason2["PromptInputExit"] = "prompt_input_exit";
361891
+ SessionEndReason2["Other"] = "other";
361892
+ })(SessionEndReason || (SessionEndReason = {}));
361893
+ var PreCompressTrigger;
361894
+ (function(PreCompressTrigger2) {
361895
+ PreCompressTrigger2["Manual"] = "manual";
361896
+ PreCompressTrigger2["Auto"] = "auto";
361897
+ })(PreCompressTrigger || (PreCompressTrigger = {}));
361898
+
361899
+ // packages/core/dist/src/core/coreToolHookTriggers.js
361900
+ function toSerializableDetails(details) {
361901
+ const base = {
361902
+ type: details.type,
361903
+ title: details.title
361904
+ };
361905
+ switch (details.type) {
361906
+ case "edit":
361907
+ return {
361908
+ ...base,
361909
+ fileName: details.fileName,
361910
+ filePath: details.filePath,
361911
+ fileDiff: details.fileDiff,
361912
+ originalContent: details.originalContent,
361913
+ newContent: details.newContent,
361914
+ isModifying: details.isModifying
361915
+ };
361916
+ case "exec":
361917
+ return {
361918
+ ...base,
361919
+ command: details.command,
361920
+ rootCommand: details.rootCommand
361921
+ };
361922
+ case "mcp":
361923
+ return {
361924
+ ...base,
361925
+ serverName: details.serverName,
361926
+ toolName: details.toolName,
361927
+ toolDisplayName: details.toolDisplayName
361928
+ };
361929
+ case "info":
361930
+ return {
361931
+ ...base,
361932
+ prompt: details.prompt,
361933
+ urls: details.urls
361934
+ };
361935
+ default:
361936
+ return base;
361937
+ }
361938
+ }
361939
+ function getNotificationMessage(confirmationDetails) {
361940
+ switch (confirmationDetails.type) {
361941
+ case "edit":
361942
+ return `Tool ${confirmationDetails.title} requires editing`;
361943
+ case "exec":
361944
+ return `Tool ${confirmationDetails.title} requires execution`;
361945
+ case "mcp":
361946
+ return `Tool ${confirmationDetails.title} requires MCP`;
361947
+ case "info":
361948
+ return `Tool ${confirmationDetails.title} requires information`;
361949
+ default:
361950
+ return `Tool requires confirmation`;
361951
+ }
361952
+ }
361953
+ async function fireToolNotificationHook(messageBus, confirmationDetails) {
361954
+ try {
361955
+ const message = getNotificationMessage(confirmationDetails);
361956
+ const serializedDetails = toSerializableDetails(confirmationDetails);
361957
+ await messageBus.request({
361958
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
361959
+ eventName: "Notification",
361960
+ input: {
361961
+ notification_type: NotificationType.ToolPermission,
361962
+ message,
361963
+ details: serializedDetails
361964
+ }
361965
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
361966
+ } catch (error2) {
361967
+ debugLogger.warn(`Notification hook failed for ${confirmationDetails.title}:`, error2);
361968
+ }
361969
+ }
361970
+ async function fireBeforeToolHook(messageBus, toolName, toolInput) {
361971
+ try {
361972
+ const response = await messageBus.request({
361973
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
361974
+ eventName: "BeforeTool",
361975
+ input: {
361976
+ tool_name: toolName,
361977
+ tool_input: toolInput
361978
+ }
361979
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
361980
+ return response.output ? createHookOutput("BeforeTool", response.output) : void 0;
361981
+ } catch (error2) {
361982
+ debugLogger.warn(`BeforeTool hook failed for ${toolName}:`, error2);
361983
+ return void 0;
361984
+ }
361985
+ }
361986
+ async function fireAfterToolHook(messageBus, toolName, toolInput, toolResponse) {
361987
+ try {
361988
+ const response = await messageBus.request({
361989
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
361990
+ eventName: "AfterTool",
361991
+ input: {
361992
+ tool_name: toolName,
361993
+ tool_input: toolInput,
361994
+ tool_response: toolResponse
361995
+ }
361996
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
361997
+ return response.output ? createHookOutput("AfterTool", response.output) : void 0;
361998
+ } catch (error2) {
361999
+ debugLogger.warn(`AfterTool hook failed for ${toolName}:`, error2);
362000
+ return void 0;
362001
+ }
362002
+ }
362003
+ async function executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, liveOutputCallback, shellExecutionConfig, setPidCallback) {
362004
+ const toolInput = invocation.params || {};
362005
+ if (hooksEnabled && messageBus) {
362006
+ const beforeOutput = await fireBeforeToolHook(messageBus, toolName, toolInput);
362007
+ const blockingError = beforeOutput?.getBlockingError();
362008
+ if (blockingError?.blocked) {
362009
+ return {
362010
+ llmContent: `Tool execution blocked: ${blockingError.reason}`,
362011
+ returnDisplay: `Tool execution blocked: ${blockingError.reason}`,
362012
+ error: {
362013
+ type: ToolErrorType.EXECUTION_FAILED,
362014
+ message: blockingError.reason
362015
+ }
362016
+ };
362017
+ }
362018
+ if (beforeOutput?.shouldStopExecution()) {
362019
+ const reason = beforeOutput.getEffectiveReason();
362020
+ return {
362021
+ llmContent: `Agent execution stopped by hook: ${reason}`,
362022
+ returnDisplay: `Agent execution stopped by hook: ${reason}`,
362023
+ error: {
362024
+ type: ToolErrorType.EXECUTION_FAILED,
362025
+ message: `Agent execution stopped: ${reason}`
362026
+ }
362027
+ };
362028
+ }
362029
+ }
362030
+ let toolResult;
362031
+ if (setPidCallback && invocation instanceof ShellToolInvocation) {
362032
+ toolResult = await invocation.execute(signal, liveOutputCallback, shellExecutionConfig, setPidCallback);
362033
+ } else {
362034
+ toolResult = await invocation.execute(signal, liveOutputCallback, shellExecutionConfig);
362035
+ }
362036
+ if (hooksEnabled && messageBus) {
362037
+ const afterOutput = await fireAfterToolHook(messageBus, toolName, toolInput, {
362038
+ llmContent: toolResult.llmContent,
362039
+ returnDisplay: toolResult.returnDisplay,
362040
+ error: toolResult.error
362041
+ });
362042
+ if (afterOutput?.shouldStopExecution()) {
362043
+ const reason = afterOutput.getEffectiveReason();
362044
+ return {
362045
+ llmContent: `Agent execution stopped by hook: ${reason}`,
362046
+ returnDisplay: `Agent execution stopped by hook: ${reason}`,
362047
+ error: {
362048
+ type: ToolErrorType.EXECUTION_FAILED,
362049
+ message: `Agent execution stopped: ${reason}`
362050
+ }
362051
+ };
362052
+ }
362053
+ const additionalContext = afterOutput?.getAdditionalContext();
362054
+ if (additionalContext) {
362055
+ if (typeof toolResult.llmContent === "string") {
362056
+ toolResult.llmContent += "\n\n" + additionalContext;
362057
+ } else if (Array.isArray(toolResult.llmContent)) {
362058
+ toolResult.llmContent.push({ text: "\n\n" + additionalContext });
362059
+ } else if (toolResult.llmContent) {
362060
+ toolResult.llmContent = [
362061
+ toolResult.llmContent,
362062
+ { text: "\n\n" + additionalContext }
362063
+ ];
362064
+ } else {
362065
+ toolResult.llmContent = additionalContext;
362066
+ }
362067
+ }
362068
+ }
362069
+ return toolResult;
362070
+ }
362071
+
362072
+ // packages/core/dist/src/core/coreToolScheduler.js
361456
362073
  function createFunctionResponsePart(callId, toolName, output) {
361457
362074
  return {
361458
362075
  functionResponse: {
@@ -361908,6 +362525,11 @@ var CoreToolScheduler = class _CoreToolScheduler {
361908
362525
  this.setToolCallOutcome(reqInfo.callId, ToolConfirmationOutcome.ProceedAlways);
361909
362526
  this.setStatusInternal(reqInfo.callId, "scheduled", signal);
361910
362527
  } else {
362528
+ const messageBus = this.config.getMessageBus();
362529
+ const hooksEnabled = this.config.getEnableHooks();
362530
+ if (hooksEnabled && messageBus) {
362531
+ await fireToolNotificationHook(messageBus, confirmationDetails);
362532
+ }
361911
362533
  if (confirmationDetails.type === "edit" && confirmationDetails.ideConfirmation) {
361912
362534
  confirmationDetails.ideConfirmation.then((resolution) => {
361913
362535
  if (resolution.status === "accepted") {
@@ -362017,6 +362639,8 @@ var CoreToolScheduler = class _CoreToolScheduler {
362017
362639
  this.notifyToolCallsUpdate();
362018
362640
  } : void 0;
362019
362641
  const shellExecutionConfig = this.config.getShellExecutionConfig();
362642
+ const hooksEnabled = this.config.getEnableHooks();
362643
+ const messageBus = this.config.getMessageBus();
362020
362644
  await runInDevTraceSpan({
362021
362645
  name: toolCall.tool.name,
362022
362646
  attributes: { type: "tool-call" }
@@ -362030,9 +362654,9 @@ var CoreToolScheduler = class _CoreToolScheduler {
362030
362654
  this.toolCalls = this.toolCalls.map((tc) => tc.request.callId === callId && tc.status === "executing" ? { ...tc, pid } : tc);
362031
362655
  this.notifyToolCallsUpdate();
362032
362656
  };
362033
- promise = invocation.execute(signal, liveOutputCallback, shellExecutionConfig, setPidCallback);
362657
+ promise = executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, liveOutputCallback, shellExecutionConfig, setPidCallback);
362034
362658
  } else {
362035
- promise = invocation.execute(signal, liveOutputCallback, shellExecutionConfig);
362659
+ promise = executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, liveOutputCallback, shellExecutionConfig);
362036
362660
  }
362037
362661
  try {
362038
362662
  const toolResult = await promise;
@@ -362569,9 +363193,97 @@ async function openBrowserSecurely(url5) {
362569
363193
  }
362570
363194
  }
362571
363195
 
363196
+ // packages/core/dist/src/availability/policyCatalog.js
363197
+ var DEFAULT_ACTIONS = {
363198
+ terminal: "prompt",
363199
+ transient: "prompt",
363200
+ not_found: "prompt",
363201
+ unknown: "prompt"
363202
+ };
363203
+ var DEFAULT_STATE = {
363204
+ terminal: "terminal",
363205
+ transient: "terminal",
363206
+ not_found: "terminal",
363207
+ unknown: "terminal"
363208
+ };
363209
+ var DEFAULT_CHAIN = [
363210
+ definePolicy({ model: DEFAULT_GEMINI_MODEL }),
363211
+ definePolicy({ model: DEFAULT_GEMINI_FLASH_MODEL, isLastResort: true })
363212
+ ];
363213
+ var PREVIEW_CHAIN = [
363214
+ definePolicy({
363215
+ model: PREVIEW_GEMINI_MODEL,
363216
+ stateTransitions: { transient: "sticky_retry" }
363217
+ }),
363218
+ definePolicy({ model: DEFAULT_GEMINI_MODEL }),
363219
+ definePolicy({ model: DEFAULT_GEMINI_FLASH_MODEL, isLastResort: true })
363220
+ ];
363221
+ function getModelPolicyChain(options2) {
363222
+ if (options2.previewEnabled) {
363223
+ return cloneChain(PREVIEW_CHAIN);
363224
+ }
363225
+ return cloneChain(DEFAULT_CHAIN);
363226
+ }
363227
+ function createDefaultPolicy(model) {
363228
+ return definePolicy({ model });
363229
+ }
363230
+ function definePolicy(config3) {
363231
+ return {
363232
+ model: config3.model,
363233
+ isLastResort: config3.isLastResort,
363234
+ actions: { ...DEFAULT_ACTIONS, ...config3.actions ?? {} },
363235
+ stateTransitions: {
363236
+ ...DEFAULT_STATE,
363237
+ ...config3.stateTransitions ?? {}
363238
+ }
363239
+ };
363240
+ }
363241
+ function clonePolicy(policy) {
363242
+ return {
363243
+ ...policy,
363244
+ actions: { ...policy.actions },
363245
+ stateTransitions: { ...policy.stateTransitions }
363246
+ };
363247
+ }
363248
+ function cloneChain(chain2) {
363249
+ return chain2.map(clonePolicy);
363250
+ }
363251
+
363252
+ // packages/core/dist/src/availability/policyHelpers.js
363253
+ function resolvePolicyChain(config3) {
363254
+ const chain2 = getModelPolicyChain({
363255
+ previewEnabled: !!config3.getPreviewFeatures(),
363256
+ userTier: config3.getUserTier()
363257
+ });
363258
+ const activeModel = getEffectiveModel(config3.isInFallbackMode(), config3.getModel(), config3.getPreviewFeatures());
363259
+ if (chain2.some((policy) => policy.model === activeModel)) {
363260
+ return chain2;
363261
+ }
363262
+ return [createDefaultPolicy(activeModel), ...chain2];
363263
+ }
363264
+ function buildFallbackPolicyContext(chain2, failedModel) {
363265
+ const index = chain2.findIndex((policy) => policy.model === failedModel);
363266
+ if (index === -1) {
363267
+ return { failedPolicy: void 0, candidates: chain2 };
363268
+ }
363269
+ return {
363270
+ failedPolicy: chain2[index],
363271
+ candidates: chain2.slice(index + 1)
363272
+ };
363273
+ }
363274
+ function resolvePolicyAction(failureKind, policy) {
363275
+ return policy.actions?.[failureKind] ?? "prompt";
363276
+ }
363277
+
362572
363278
  // packages/core/dist/src/fallback/handler.js
362573
363279
  var UPGRADE_URL_PAGE = "https://goo.gle/set-up-gemini-code-assist";
362574
363280
  async function handleFallback(config3, failedModel, authType, error2) {
363281
+ if (config3.isModelAvailabilityServiceEnabled()) {
363282
+ return handlePolicyDrivenFallback(config3, failedModel, authType, error2);
363283
+ }
363284
+ return legacyHandleFallback(config3, failedModel, authType, error2);
363285
+ }
363286
+ async function legacyHandleFallback(config3, failedModel, authType, error2) {
362575
363287
  if (authType !== AuthType2.LOGIN_WITH_GOOGLE)
362576
363288
  return null;
362577
363289
  if (error2 instanceof ModelNotFoundError && failedModel !== PREVIEW_GEMINI_MODEL) {
@@ -362590,30 +363302,56 @@ async function handleFallback(config3, failedModel, authType, error2) {
362590
363302
  return null;
362591
363303
  try {
362592
363304
  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
- }
363305
+ return await processIntent(config3, intent, failedModel, fallbackModel, authType, error2);
363306
+ } catch (handlerError) {
363307
+ console.error("Fallback UI handler failed:", handlerError);
363308
+ return null;
363309
+ }
363310
+ }
363311
+ async function handlePolicyDrivenFallback(config3, failedModel, authType, error2) {
363312
+ if (authType !== AuthType2.LOGIN_WITH_GOOGLE) {
363313
+ return null;
363314
+ }
363315
+ const chain2 = resolvePolicyChain(config3);
363316
+ const { failedPolicy, candidates } = buildFallbackPolicyContext(chain2, failedModel);
363317
+ if (!candidates.length) {
363318
+ return null;
363319
+ }
363320
+ const availability = config3.getModelAvailabilityService();
363321
+ const selection = availability.selectFirstAvailable(candidates.map((policy) => policy.model));
363322
+ let lastResortPolicy = candidates.find((policy) => policy.isLastResort);
363323
+ if (!lastResortPolicy) {
363324
+ debugLogger.warn("No isLastResort policy found in candidates, using last candidate as fallback.");
363325
+ lastResortPolicy = candidates[candidates.length - 1];
363326
+ }
363327
+ const fallbackModel = selection.selectedModel ?? lastResortPolicy.model;
363328
+ const selectedPolicy = candidates.find((policy) => policy.model === fallbackModel) ?? lastResortPolicy;
363329
+ if (!fallbackModel || fallbackModel === failedModel) {
363330
+ return null;
363331
+ }
363332
+ const failureKind = classifyFailureKind(error2);
363333
+ const action = resolvePolicyAction(failureKind, selectedPolicy);
363334
+ if (action === "silent") {
363335
+ return processIntent(config3, "retry_always", failedModel, fallbackModel, authType, error2);
363336
+ }
363337
+ const recommendation = {
363338
+ ...selection,
363339
+ selectedModel: fallbackModel,
363340
+ action,
363341
+ failureKind,
363342
+ failedPolicy,
363343
+ selectedPolicy
363344
+ };
363345
+ void recommendation;
363346
+ const handler = config3.getFallbackModelHandler();
363347
+ if (typeof handler !== "function") {
363348
+ return null;
363349
+ }
363350
+ try {
363351
+ const intent = await handler(failedModel, fallbackModel, error2);
363352
+ return await processIntent(config3, intent, failedModel, fallbackModel, authType);
362615
363353
  } catch (handlerError) {
362616
- debugLogger.error("Fallback UI handler failed:", handlerError);
363354
+ debugLogger.error("Fallback handler failed:", handlerError);
362617
363355
  return null;
362618
363356
  }
362619
363357
  }
@@ -362624,6 +363362,29 @@ async function handleUpgrade() {
362624
363362
  debugLogger.warn("Failed to open browser automatically:", getErrorMessage(error2));
362625
363363
  }
362626
363364
  }
363365
+ async function processIntent(config3, intent, failedModel, fallbackModel, authType, error2) {
363366
+ switch (intent) {
363367
+ case "retry_always":
363368
+ if (failedModel === PREVIEW_GEMINI_MODEL && !(error2 instanceof TerminalQuotaError)) {
363369
+ activatePreviewModelFallbackMode(config3);
363370
+ } else {
363371
+ activateFallbackMode(config3, authType);
363372
+ }
363373
+ return true;
363374
+ case "retry_once":
363375
+ return true;
363376
+ case "stop":
363377
+ activateFallbackMode(config3, authType);
363378
+ return false;
363379
+ case "retry_later":
363380
+ return false;
363381
+ case "upgrade":
363382
+ await handleUpgrade();
363383
+ return false;
363384
+ default:
363385
+ throw new Error(`Unexpected fallback intent received from fallbackModelHandler: "${intent}"`);
363386
+ }
363387
+ }
362627
363388
  function activateFallbackMode(config3, authType) {
362628
363389
  if (!config3.isInFallbackMode()) {
362629
363390
  config3.setFallbackMode(true);
@@ -362638,12 +363399,154 @@ function activatePreviewModelFallbackMode(config3) {
362638
363399
  config3.setPreviewModelFallbackMode(true);
362639
363400
  }
362640
363401
  }
363402
+ function classifyFailureKind(error2) {
363403
+ if (error2 instanceof TerminalQuotaError) {
363404
+ return "terminal";
363405
+ }
363406
+ if (error2 instanceof RetryableQuotaError) {
363407
+ return "transient";
363408
+ }
363409
+ if (error2 instanceof ModelNotFoundError) {
363410
+ return "not_found";
363411
+ }
363412
+ return "unknown";
363413
+ }
362641
363414
 
362642
363415
  // packages/core/dist/src/core/geminiRequest.js
362643
363416
  function partListUnionToString(value) {
362644
363417
  return partToString(value, { verbose: true });
362645
363418
  }
362646
363419
 
363420
+ // packages/core/dist/src/utils/tokenCalculation.js
363421
+ var ASCII_TOKENS_PER_CHAR = 0.25;
363422
+ var NON_ASCII_TOKENS_PER_CHAR = 1.3;
363423
+ function estimateTokenCountSync(parts2) {
363424
+ let totalTokens = 0;
363425
+ for (const part of parts2) {
363426
+ if (typeof part.text === "string") {
363427
+ for (const char of part.text) {
363428
+ if (char.codePointAt(0) <= 127) {
363429
+ totalTokens += ASCII_TOKENS_PER_CHAR;
363430
+ } else {
363431
+ totalTokens += NON_ASCII_TOKENS_PER_CHAR;
363432
+ }
363433
+ }
363434
+ } else {
363435
+ totalTokens += JSON.stringify(part).length / 4;
363436
+ }
363437
+ }
363438
+ return Math.floor(totalTokens);
363439
+ }
363440
+ async function calculateRequestTokenCount(request3, contentGenerator, model) {
363441
+ const parts2 = Array.isArray(request3) ? request3.map((p) => typeof p === "string" ? { text: p } : p) : typeof request3 === "string" ? [{ text: request3 }] : [request3];
363442
+ const hasMedia = parts2.some((p) => {
363443
+ const isMedia = "inlineData" in p || "fileData" in p;
363444
+ return isMedia;
363445
+ });
363446
+ if (hasMedia) {
363447
+ try {
363448
+ const response = await contentGenerator.countTokens({
363449
+ model,
363450
+ contents: [{ role: "user", parts: parts2 }]
363451
+ });
363452
+ return response.totalTokens ?? 0;
363453
+ } catch {
363454
+ return estimateTokenCountSync(parts2);
363455
+ }
363456
+ }
363457
+ return estimateTokenCountSync(parts2);
363458
+ }
363459
+
363460
+ // packages/core/dist/src/core/geminiChatHookTriggers.js
363461
+ async function fireBeforeModelHook(messageBus, llmRequest) {
363462
+ try {
363463
+ const response = await messageBus.request({
363464
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
363465
+ eventName: "BeforeModel",
363466
+ input: {
363467
+ llm_request: llmRequest
363468
+ }
363469
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
363470
+ const beforeResultFinalOutput = response.output ? createHookOutput("BeforeModel", response.output) : void 0;
363471
+ const hookOutput = beforeResultFinalOutput;
363472
+ const blockingError = hookOutput?.getBlockingError();
363473
+ if (blockingError?.blocked || hookOutput?.shouldStopExecution()) {
363474
+ const beforeModelOutput = hookOutput;
363475
+ const syntheticResponse = beforeModelOutput.getSyntheticResponse();
363476
+ const reason = hookOutput?.getEffectiveReason() || "Model call blocked by hook";
363477
+ return {
363478
+ blocked: true,
363479
+ reason,
363480
+ syntheticResponse
363481
+ };
363482
+ }
363483
+ if (hookOutput) {
363484
+ const beforeModelOutput = hookOutput;
363485
+ const modifiedRequest = beforeModelOutput.applyLLMRequestModifications(llmRequest);
363486
+ return {
363487
+ blocked: false,
363488
+ modifiedConfig: modifiedRequest.config,
363489
+ modifiedContents: modifiedRequest.contents
363490
+ };
363491
+ }
363492
+ return { blocked: false };
363493
+ } catch (error2) {
363494
+ debugLogger.warn(`BeforeModel hook failed:`, error2);
363495
+ return { blocked: false };
363496
+ }
363497
+ }
363498
+ async function fireBeforeToolSelectionHook(messageBus, llmRequest) {
363499
+ try {
363500
+ const response = await messageBus.request({
363501
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
363502
+ eventName: "BeforeToolSelection",
363503
+ input: {
363504
+ llm_request: llmRequest
363505
+ }
363506
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
363507
+ const toolSelectionResultFinalOutput = response.output ? createHookOutput("BeforeToolSelection", response.output) : void 0;
363508
+ if (toolSelectionResultFinalOutput) {
363509
+ const beforeToolSelectionOutput = toolSelectionResultFinalOutput;
363510
+ const modifiedConfig = beforeToolSelectionOutput.applyToolConfigModifications({
363511
+ toolConfig: llmRequest.config?.toolConfig,
363512
+ tools: llmRequest.config?.tools
363513
+ });
363514
+ return {
363515
+ toolConfig: modifiedConfig.toolConfig,
363516
+ tools: modifiedConfig.tools
363517
+ };
363518
+ }
363519
+ return {};
363520
+ } catch (error2) {
363521
+ debugLogger.warn(`BeforeToolSelection hook failed:`, error2);
363522
+ return {};
363523
+ }
363524
+ }
363525
+ async function fireAfterModelHook(messageBus, originalRequest, chunk2) {
363526
+ try {
363527
+ const response = await messageBus.request({
363528
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
363529
+ eventName: "AfterModel",
363530
+ input: {
363531
+ llm_request: originalRequest,
363532
+ llm_response: chunk2
363533
+ }
363534
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
363535
+ const afterResultFinalOutput = response.output ? createHookOutput("AfterModel", response.output) : void 0;
363536
+ if (afterResultFinalOutput) {
363537
+ const afterModelOutput = afterResultFinalOutput;
363538
+ const modifiedResponse = afterModelOutput.getModifiedResponse();
363539
+ if (modifiedResponse) {
363540
+ return { response: modifiedResponse };
363541
+ }
363542
+ }
363543
+ return { response: chunk2 };
363544
+ } catch (error2) {
363545
+ debugLogger.warn(`AfterModel hook failed:`, error2);
363546
+ return { response: chunk2 };
363547
+ }
363548
+ }
363549
+
362647
363550
  // packages/core/dist/src/core/geminiChat.js
362648
363551
  var StreamEventType;
362649
363552
  (function(StreamEventType2) {
@@ -362746,7 +363649,7 @@ var GeminiChat = class {
362746
363649
  validateHistory2(history);
362747
363650
  this.chatRecordingService = new ChatRecordingService(config3);
362748
363651
  this.chatRecordingService.initialize(resumedSessionData);
362749
- this.lastPromptTokenCount = Math.ceil(JSON.stringify(this.history).length / 4);
363652
+ this.lastPromptTokenCount = estimateTokenCountSync(this.history.flatMap((c4) => c4.parts || []));
362750
363653
  }
362751
363654
  setSystemInstruction(sysInstr) {
362752
363655
  this.systemInstruction = sysInstr;
@@ -362798,12 +363701,11 @@ var GeminiChat = class {
362798
363701
  }
362799
363702
  this.history.push(userContent);
362800
363703
  const requestContents = this.getHistory(true);
362801
- const self2 = this;
362802
- return async function* () {
363704
+ const streamWithRetries = async function* () {
362803
363705
  try {
362804
363706
  let lastError = new Error("Request failed after all retries.");
362805
363707
  let maxAttempts = INVALID_CONTENT_RETRY_OPTIONS.maxAttempts;
362806
- if (self2.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL) {
363708
+ if (this.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL) {
362807
363709
  maxAttempts = 1;
362808
363710
  }
362809
363711
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
@@ -362814,7 +363716,7 @@ var GeminiChat = class {
362814
363716
  if (attempt > 0) {
362815
363717
  generateContentConfig.temperature = 1;
362816
363718
  }
362817
- const stream3 = await self2.makeApiCallAndProcessStream(model, generateContentConfig, requestContents, prompt_id);
363719
+ const stream3 = await this.makeApiCallAndProcessStream(model, generateContentConfig, requestContents, prompt_id);
362818
363720
  for await (const chunk2 of stream3) {
362819
363721
  yield { type: StreamEventType.CHUNK, value: chunk2 };
362820
363722
  }
@@ -362825,7 +363727,7 @@ var GeminiChat = class {
362825
363727
  const isContentError = error2 instanceof InvalidStreamError;
362826
363728
  if (isContentError && isGemini2Model(model)) {
362827
363729
  if (attempt < maxAttempts - 1) {
362828
- logContentRetry(self2.config, new ContentRetryEvent(attempt, error2.type, INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs, model));
363730
+ logContentRetry(this.config, new ContentRetryEvent(attempt, error2.type, INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs, model));
362829
363731
  await new Promise((res) => setTimeout(res, INVALID_CONTENT_RETRY_OPTIONS.initialDelayMs * (attempt + 1)));
362830
363732
  continue;
362831
363733
  }
@@ -362835,23 +363737,27 @@ var GeminiChat = class {
362835
363737
  }
362836
363738
  if (lastError) {
362837
363739
  if (lastError instanceof InvalidStreamError && isGemini2Model(model)) {
362838
- logContentRetryFailure(self2.config, new ContentRetryFailureEvent(maxAttempts, lastError.type, model));
363740
+ logContentRetryFailure(this.config, new ContentRetryFailureEvent(maxAttempts, lastError.type, model));
362839
363741
  }
362840
363742
  throw lastError;
362841
363743
  } else {
362842
- if (model === PREVIEW_GEMINI_MODEL && !self2.config.isPreviewModelBypassMode()) {
362843
- self2.config.setPreviewModelFallbackMode(false);
363744
+ if (model === PREVIEW_GEMINI_MODEL && !this.config.isPreviewModelBypassMode()) {
363745
+ this.config.setPreviewModelFallbackMode(false);
362844
363746
  }
362845
363747
  }
362846
363748
  } finally {
362847
363749
  streamDoneResolver();
362848
363750
  }
362849
- }();
363751
+ };
363752
+ return streamWithRetries.call(this);
362850
363753
  }
362851
363754
  async makeApiCallAndProcessStream(model, generateContentConfig, requestContents, prompt_id) {
362852
363755
  let effectiveModel = model;
362853
363756
  const contentsForPreviewModel = this.ensureActiveLoopHasThoughtSignatures(requestContents);
362854
- const apiCall = () => {
363757
+ let lastModelToUse = model;
363758
+ let lastConfig = generateContentConfig;
363759
+ let lastContentsToUse = requestContents;
363760
+ const apiCall = async () => {
362855
363761
  let modelToUse = getEffectiveModel(this.config.isInFallbackMode(), model, this.config.getPreviewFeatures());
362856
363762
  if (this.config.isPreviewModelBypassMode() && modelToUse === PREVIEW_GEMINI_MODEL) {
362857
363763
  modelToUse = DEFAULT_GEMINI_MODEL;
@@ -362877,9 +363783,49 @@ var GeminiChat = class {
362877
363783
  };
362878
363784
  delete config3.thinkingConfig?.thinkingLevel;
362879
363785
  }
363786
+ let contentsToUse = modelToUse === PREVIEW_GEMINI_MODEL ? contentsForPreviewModel : requestContents;
363787
+ const hooksEnabled = this.config.getEnableHooks();
363788
+ const messageBus = this.config.getMessageBus();
363789
+ if (hooksEnabled && messageBus) {
363790
+ const beforeModelResult = await fireBeforeModelHook(messageBus, {
363791
+ model: modelToUse,
363792
+ config: config3,
363793
+ contents: contentsToUse
363794
+ });
363795
+ if (beforeModelResult.blocked) {
363796
+ const syntheticResponse = beforeModelResult.syntheticResponse;
363797
+ if (syntheticResponse) {
363798
+ return async function* () {
363799
+ yield syntheticResponse;
363800
+ }();
363801
+ }
363802
+ return async function* () {
363803
+ }();
363804
+ }
363805
+ if (beforeModelResult.modifiedConfig) {
363806
+ Object.assign(config3, beforeModelResult.modifiedConfig);
363807
+ }
363808
+ if (beforeModelResult.modifiedContents && Array.isArray(beforeModelResult.modifiedContents)) {
363809
+ contentsToUse = beforeModelResult.modifiedContents;
363810
+ }
363811
+ const toolSelectionResult = await fireBeforeToolSelectionHook(messageBus, {
363812
+ model: modelToUse,
363813
+ config: config3,
363814
+ contents: contentsToUse
363815
+ });
363816
+ if (toolSelectionResult.toolConfig) {
363817
+ config3.toolConfig = toolSelectionResult.toolConfig;
363818
+ }
363819
+ if (toolSelectionResult.tools && Array.isArray(toolSelectionResult.tools)) {
363820
+ config3.tools = toolSelectionResult.tools;
363821
+ }
363822
+ }
363823
+ lastModelToUse = modelToUse;
363824
+ lastConfig = config3;
363825
+ lastContentsToUse = contentsToUse;
362880
363826
  return this.config.getContentGenerator().generateContentStream({
362881
363827
  model: modelToUse,
362882
- contents: modelToUse === PREVIEW_GEMINI_MODEL ? contentsForPreviewModel : requestContents,
363828
+ contents: contentsToUse,
362883
363829
  config: config3
362884
363830
  }, prompt_id);
362885
363831
  };
@@ -362891,7 +363837,12 @@ var GeminiChat = class {
362891
363837
  signal: generateContentConfig.abortSignal,
362892
363838
  maxAttempts: this.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL ? 1 : void 0
362893
363839
  });
362894
- return this.processStreamResponse(effectiveModel, streamResponse);
363840
+ const originalRequest = {
363841
+ model: lastModelToUse,
363842
+ config: lastConfig,
363843
+ contents: lastContentsToUse
363844
+ };
363845
+ return this.processStreamResponse(effectiveModel, streamResponse, originalRequest);
362895
363846
  }
362896
363847
  /**
362897
363848
  * Returns the chat history.
@@ -363015,7 +363966,7 @@ This error was probably caused by cyclic schema references in one of the followi
363015
363966
  }
363016
363967
  }
363017
363968
  }
363018
- async *processStreamResponse(model, streamResponse) {
363969
+ async *processStreamResponse(model, streamResponse, originalRequest) {
363019
363970
  const modelResponseParts = [];
363020
363971
  let hasToolCall = false;
363021
363972
  let finishReason;
@@ -363042,7 +363993,14 @@ This error was probably caused by cyclic schema references in one of the followi
363042
363993
  this.lastPromptTokenCount = chunk2.usageMetadata.promptTokenCount;
363043
363994
  }
363044
363995
  }
363045
- yield chunk2;
363996
+ const hooksEnabled = this.config.getEnableHooks();
363997
+ const messageBus = this.config.getMessageBus();
363998
+ if (hooksEnabled && messageBus && originalRequest && chunk2) {
363999
+ const hookResult = await fireAfterModelHook(messageBus, originalRequest, chunk2);
364000
+ yield hookResult.response;
364001
+ } else {
364002
+ yield chunk2;
364003
+ }
363046
364004
  }
363047
364005
  const consolidatedParts = [];
363048
364006
  for (const part of modelResponseParts) {
@@ -363643,15 +364601,18 @@ function getCoreSystemPrompt(config3, userMemory) {
363643
364601
  }
363644
364602
  }
363645
364603
  const desiredModel = getEffectiveModel(config3.isInFallbackMode(), config3.getModel(), config3.getPreviewFeatures());
363646
- const useChattySystemPrompt = desiredModel === PREVIEW_GEMINI_MODEL;
364604
+ const isGemini3 = desiredModel === PREVIEW_GEMINI_MODEL;
364605
+ const mandatesVariant = isGemini3 ? `
364606
+ - **Do not call tools in silence:** You must provide to the user very short and concise natural explanation (one sentence) before calling tools.` : ``;
363647
364607
  const enableCodebaseInvestigator = config3.getToolRegistry().getAllToolNames().includes(CodebaseInvestigatorAgent.name);
363648
364608
  const enableWriteTodosTool = config3.getToolRegistry().getAllToolNames().includes(WriteTodosTool.Name);
364609
+ const interactiveMode = config3.isInteractiveShellEnabled();
363649
364610
  let basePrompt;
363650
364611
  if (systemMdEnabled) {
363651
364612
  basePrompt = fs46.readFileSync(systemMdPath, "utf8");
363652
364613
  } else {
363653
364614
  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.`,
364615
+ 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
364616
  coreMandates: `
363656
364617
  # Core Mandates
363657
364618
 
@@ -363661,9 +364622,10 @@ function getCoreSystemPrompt(config3, userMemory) {
363661
364622
  - **Idiomatic Changes:** When editing, understand the local context (imports, functions/classes) to ensure your changes integrate naturally and idiomatically.
363662
364623
  - **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
364624
  - **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.
364625
+ - ${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
364626
  - **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.`,
364627
+ - **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 ? `
364628
+ - **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
364629
  primaryWorkflows_prefix: `
363668
364630
  # Primary Workflows
363669
364631
 
@@ -363696,14 +364658,14 @@ When requested to perform tasks like fixing bugs, adding features, refactoring,
363696
364658
  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
364659
  Mandates').
363698
364660
  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.
364661
+ 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
364662
  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
364663
 
363702
364664
  ## New Applications
363703
364665
 
363704
364666
  **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
364667
 
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.
364668
+ 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
364669
  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
364670
  - When key technologies aren't specified, prefer the following:
363709
364671
  - **Websites (Frontend):** React (JavaScript/TypeScript) or Angular with Bootstrap CSS, incorporating Material Design principles for UI/UX.
@@ -363713,10 +364675,17 @@ Mandates').
363713
364675
  - **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
364676
  - **3d Games:** HTML/CSS/JavaScript with Three.js.
363715
364677
  - **2d Games:** HTML/CSS/JavaScript.
363716
- 3. **User Approval:** Obtain user approval for the proposed plan.
364678
+ ${function() {
364679
+ if (interactiveMode) {
364680
+ return `3. **User Approval:** Obtain user approval for the proposed plan.
363717
364681
  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
364682
  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.`,
364683
+ 6. **Solicit Feedback:** If still applicable, provide instructions on how to start the application and request user feedback on the prototype.`;
364684
+ } else {
364685
+ 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.
364686
+ 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.`;
364687
+ }
364688
+ }()}`,
363720
364689
  operationalGuidelines: `
363721
364690
  # Operational Guidelines
363722
364691
  ${function() {
@@ -363740,12 +364709,12 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
363740
364709
  ## Tone and Style (CLI Interaction)
363741
364710
  - **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
363742
364711
  - **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) {
364712
+ - **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() {
364713
+ if (isGemini3) {
363746
364714
  return "";
363747
364715
  } 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.';
364716
+ return `
364717
+ - **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
364718
  }
363750
364719
  }()}
363751
364720
  - **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
@@ -363759,15 +364728,16 @@ ${function() {
363759
364728
  ## Tool Usage
363760
364729
  - **Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
363761
364730
  - **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
364731
  ${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.`;
364732
+ if (interactiveMode) {
364733
+ 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.
364734
+ - **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
364735
  } 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.`;
364736
+ return `- **Background Processes:** Use background processes (via \`&\`) for commands that are unlikely to stop on their own, e.g. \`node server.js &\`.
364737
+ - **Interactive Commands:** Only execute non-interactive commands.`;
363768
364738
  }
363769
364739
  }()}
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?"
364740
+ - **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
364741
  - **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
364742
 
363773
364743
  ## Interaction Details
@@ -363807,8 +364777,8 @@ ${function() {
363807
364777
  - \`git log -n 3\` to review recent commit messages and match their style (verbosity, formatting, signature line, etc.)
363808
364778
  - Combine shell commands whenever possible to save time/steps, e.g. \`git status && git diff HEAD && git log -n 3\`.
363809
364779
  - 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.
364780
+ - Prefer commit messages that are clear, concise, and focused more on "why" and less on "what".${interactiveMode ? `
364781
+ - Keep the user informed and ask for clarification or confirmation where needed.` : ""}
363812
364782
  - After each commit, confirm that it was successful by running \`git status\`.
363813
364783
  - If a commit fails, never attempt to work around the issues without being asked to do so.
363814
364784
  - Never push changes to a remote repository without being asked explicitly by the user.
@@ -364476,7 +365446,7 @@ var ChatCompressionService = class {
364476
365446
  ...historyToKeep
364477
365447
  ];
364478
365448
  const fullNewHistory = await getInitialChatHistory(config3, extraHistory);
364479
- const newTokenCount = Math.floor(fullNewHistory.reduce((total, content) => total + JSON.stringify(content).length, 0) / 4);
365449
+ const newTokenCount = await calculateRequestTokenCount(fullNewHistory.flatMap((c4) => c4.parts || []), config3.getContentGenerator(), model);
364480
365450
  logChatCompression(config3, makeChatCompressionEvent({
364481
365451
  tokens_before: originalTokenCount,
364482
365452
  tokens_after: newTokenCount
@@ -364503,405 +365473,6 @@ var ChatCompressionService = class {
364503
365473
  }
364504
365474
  };
364505
365475
 
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
365476
  // packages/core/dist/src/core/clientHookTriggers.js
364906
365477
  async function fireBeforeAgentHook(messageBus, request3) {
364907
365478
  try {
@@ -364940,23 +365511,6 @@ async function fireAfterAgentHook(messageBus, request3, responseText) {
364940
365511
 
364941
365512
  // packages/core/dist/src/core/client.js
364942
365513
  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
365514
  var GeminiClient = class {
364961
365515
  config;
364962
365516
  chat;
@@ -365237,7 +365791,7 @@ var GeminiClient = class {
365237
365791
  return new Turn(this.getChat(), prompt_id);
365238
365792
  }
365239
365793
  const modelForLimitCheck = this._getEffectiveModelForCurrentTurn();
365240
- const estimatedRequestTokenCount = Math.floor(estimateTextOnlyLength(request3) / 4);
365794
+ const estimatedRequestTokenCount = await calculateRequestTokenCount(request3, this.getContentGeneratorOrFail(), modelForLimitCheck);
365241
365795
  const remainingTokenCount = tokenLimit(modelForLimitCheck) - this.getChat().getLastPromptTokenCount();
365242
365796
  if (estimatedRequestTokenCount > remainingTokenCount * 0.95) {
365243
365797
  yield {
@@ -370307,6 +370861,81 @@ var StandardFileSystemService = class {
370307
370861
  }
370308
370862
  };
370309
370863
 
370864
+ // packages/core/dist/src/availability/modelAvailabilityService.js
370865
+ var ModelAvailabilityService = class {
370866
+ health = /* @__PURE__ */ new Map();
370867
+ markTerminal(model, reason) {
370868
+ this.setState(model, {
370869
+ status: "terminal",
370870
+ reason
370871
+ });
370872
+ }
370873
+ markHealthy(model) {
370874
+ this.clearState(model);
370875
+ }
370876
+ markRetryOncePerTurn(model) {
370877
+ const currentState = this.health.get(model);
370878
+ if (currentState?.status === "terminal") {
370879
+ return;
370880
+ }
370881
+ let consumed = false;
370882
+ if (currentState?.status === "sticky_retry") {
370883
+ consumed = currentState.consumed;
370884
+ }
370885
+ this.setState(model, {
370886
+ status: "sticky_retry",
370887
+ reason: "retry_once_per_turn",
370888
+ consumed
370889
+ });
370890
+ }
370891
+ consumeStickyAttempt(model) {
370892
+ const state = this.health.get(model);
370893
+ if (state?.status === "sticky_retry") {
370894
+ this.setState(model, { ...state, consumed: true });
370895
+ }
370896
+ }
370897
+ snapshot(model) {
370898
+ const state = this.health.get(model);
370899
+ if (!state) {
370900
+ return { available: true };
370901
+ }
370902
+ if (state.status === "terminal") {
370903
+ return { available: false, reason: state.reason };
370904
+ }
370905
+ if (state.status === "sticky_retry" && state.consumed) {
370906
+ return { available: false, reason: state.reason };
370907
+ }
370908
+ return { available: true };
370909
+ }
370910
+ selectFirstAvailable(models) {
370911
+ const skipped = [];
370912
+ for (const model of models) {
370913
+ const snapshot = this.snapshot(model);
370914
+ if (snapshot.available) {
370915
+ const state = this.health.get(model);
370916
+ const attempts = state?.status === "sticky_retry" ? 1 : void 0;
370917
+ return { selectedModel: model, skipped, attempts };
370918
+ } else {
370919
+ skipped.push({ model, reason: snapshot.reason ?? "unknown" });
370920
+ }
370921
+ }
370922
+ return { selectedModel: null, skipped };
370923
+ }
370924
+ resetTurn() {
370925
+ for (const [model, state] of this.health.entries()) {
370926
+ if (state.status === "sticky_retry") {
370927
+ this.setState(model, { ...state, consumed: false });
370928
+ }
370929
+ }
370930
+ }
370931
+ setState(model, nextState) {
370932
+ this.health.set(model, nextState);
370933
+ }
370934
+ clearState(model) {
370935
+ this.health.delete(model);
370936
+ }
370937
+ };
370938
+
370310
370939
  // packages/core/dist/src/routing/strategies/defaultStrategy.js
370311
370940
  var DefaultStrategy = class {
370312
370941
  name = "default";
@@ -373914,7 +374543,7 @@ async function getClientMetadata() {
373914
374543
  clientMetadataPromise = (async () => ({
373915
374544
  ideName: "IDE_UNSPECIFIED",
373916
374545
  pluginType: "GEMINI",
373917
- ideVersion: "0.19.0-preview.0",
374546
+ ideVersion: "0.20.0-nightly.20251130.576fda18e",
373918
374547
  platform: getPlatform(),
373919
374548
  updateChannel: await getReleaseChannel(__dirname5)
373920
374549
  }))();
@@ -376601,7 +377230,9 @@ async function loadServerHierarchicalMemory(currentWorkingDirectory, includeDire
376601
377230
  }
376602
377231
  async function refreshServerHierarchicalMemory(config3) {
376603
377232
  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);
377233
+ const mcpInstructions = config3.getMcpClientManager()?.getMcpInstructions() || "";
377234
+ const finalMemory = [result.memoryContent, mcpInstructions.trimStart()].filter(Boolean).join("\n\n");
377235
+ config3.setUserMemory(finalMemory);
376605
377236
  config3.setGeminiMdFileCount(result.fileCount);
376606
377237
  config3.setGeminiMdFilePaths(result.filePaths);
376607
377238
  coreEvents.emit(CoreEvent.MemoryChanged, result);
@@ -377585,6 +378216,30 @@ var GoogleCredentialProvider = class {
377585
378216
  codeVerifier() {
377586
378217
  return "";
377587
378218
  }
378219
+ /**
378220
+ * Returns the project ID used for quota.
378221
+ */
378222
+ async getQuotaProjectId() {
378223
+ const client = await this.auth.getClient();
378224
+ return client.quotaProjectId;
378225
+ }
378226
+ /**
378227
+ * Returns custom headers to be added to the request.
378228
+ */
378229
+ async getRequestHeaders() {
378230
+ const headers = {};
378231
+ const configHeaders = this.config?.headers ?? {};
378232
+ const userProjectHeaderKey = Object.keys(configHeaders).find((key) => key.toLowerCase() === "x-goog-user-project");
378233
+ if (userProjectHeaderKey) {
378234
+ headers[userProjectHeaderKey] = configHeaders[userProjectHeaderKey];
378235
+ } else {
378236
+ const quotaProjectId = await this.getQuotaProjectId();
378237
+ if (quotaProjectId) {
378238
+ headers["X-Goog-User-Project"] = quotaProjectId;
378239
+ }
378240
+ }
378241
+ return headers;
378242
+ }
377588
378243
  };
377589
378244
 
377590
378245
  // packages/core/dist/src/mcp/sa-impersonation-provider.js
@@ -378567,6 +379222,9 @@ var McpClient = class {
378567
379222
  getServerConfig() {
378568
379223
  return this.serverConfig;
378569
379224
  }
379225
+ getInstructions() {
379226
+ return this.client?.getInstructions();
379227
+ }
378570
379228
  };
378571
379229
  var serverStatuses = /* @__PURE__ */ new Map();
378572
379230
  var mcpDiscoveryState = MCPDiscoveryState.NOT_STARTED;
@@ -379045,7 +379703,7 @@ async function createTransport(mcpServerName, mcpServerConfig, debugMode) {
379045
379703
  }
379046
379704
  if (mcpServerConfig.httpUrl || mcpServerConfig.url) {
379047
379705
  const authProvider = createAuthProvider(mcpServerConfig);
379048
- const headers = {};
379706
+ const headers = await authProvider?.getRequestHeaders?.() ?? {};
379049
379707
  if (authProvider === void 0) {
379050
379708
  let accessToken = null;
379051
379709
  let hasOAuthConfig = mcpServerConfig.oauth?.enabled;
@@ -379322,6 +379980,19 @@ var McpClientManager = class {
379322
379980
  }
379323
379981
  return mcpServers;
379324
379982
  }
379983
+ getMcpInstructions() {
379984
+ const instructions = [];
379985
+ for (const [name4, client] of this.clients) {
379986
+ if (client.getServerConfig().useInstructions) {
379987
+ const clientInstructions = client.getInstructions();
379988
+ if (clientInstructions) {
379989
+ instructions.push(`# Instructions for MCP Server '${name4}'
379990
+ ${clientInstructions}`);
379991
+ }
379992
+ }
379993
+ }
379994
+ return instructions.join("\n\n");
379995
+ }
379325
379996
  };
379326
379997
 
379327
379998
  // packages/core/dist/src/config/config.js
@@ -379369,6 +380040,7 @@ var Config = class {
379369
380040
  geminiClient;
379370
380041
  baseLlmClient;
379371
380042
  modelRouterService;
380043
+ modelAvailabilityService;
379372
380044
  fileFiltering;
379373
380045
  fileDiscoveryService = null;
379374
380046
  gitService = void 0;
@@ -379423,6 +380095,7 @@ var Config = class {
379423
380095
  continueOnFailedApiCall;
379424
380096
  retryFetchErrors;
379425
380097
  enableShellOutputEfficiency;
380098
+ shellToolInactivityTimeout;
379426
380099
  fakeResponses;
379427
380100
  recordResponses;
379428
380101
  disableYoloMode;
@@ -379484,6 +380157,7 @@ var Config = class {
379484
380157
  this.bugCommand = params.bugCommand;
379485
380158
  this.model = params.model;
379486
380159
  this.enableModelAvailabilityService = params.enableModelAvailabilityService ?? false;
380160
+ this.modelAvailabilityService = new ModelAvailabilityService();
379487
380161
  this.previewFeatures = params.previewFeatures ?? void 0;
379488
380162
  this.maxSessionTurns = params.maxSessionTurns ?? -1;
379489
380163
  this.experimentalZedIntegration = params.experimentalZedIntegration ?? false;
@@ -379530,6 +380204,7 @@ var Config = class {
379530
380204
  };
379531
380205
  this.continueOnFailedApiCall = params.continueOnFailedApiCall ?? true;
379532
380206
  this.enableShellOutputEfficiency = params.enableShellOutputEfficiency ?? true;
380207
+ this.shellToolInactivityTimeout = (params.shellToolInactivityTimeout ?? 300) * 1e3;
379533
380208
  this.extensionManagement = params.extensionManagement ?? true;
379534
380209
  this.enableExtensionReloading = params.enableExtensionReloading ?? false;
379535
380210
  this.storage = new Storage2(this.targetDir);
@@ -379890,6 +380565,9 @@ var Config = class {
379890
380565
  getModelRouterService() {
379891
380566
  return this.modelRouterService;
379892
380567
  }
380568
+ getModelAvailabilityService() {
380569
+ return this.modelAvailabilityService;
380570
+ }
379893
380571
  getEnableRecursiveFileSearch() {
379894
380572
  return this.fileFiltering.enableRecursiveFileSearch;
379895
380573
  }
@@ -380070,6 +380748,9 @@ var Config = class {
380070
380748
  getEnableShellOutputEfficiency() {
380071
380749
  return this.enableShellOutputEfficiency;
380072
380750
  }
380751
+ getShellToolInactivityTimeout() {
380752
+ return this.shellToolInactivityTimeout;
380753
+ }
380073
380754
  getShellExecutionConfig() {
380074
380755
  return this.shellExecutionConfig;
380075
380756
  }