@google/gemini-cli-a2a-server 0.19.0-nightly.20251124.e177314a4 → 0.19.0-nightly.20251126.03845198c

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.
@@ -54965,11 +54965,11 @@ var require_verify_stream = __commonJS({
54965
54965
  var toString2 = require_tostring();
54966
54966
  var util4 = __require("util");
54967
54967
  var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;
54968
- function isObject3(thing) {
54968
+ function isObject4(thing) {
54969
54969
  return Object.prototype.toString.call(thing) === "[object Object]";
54970
54970
  }
54971
54971
  function safeJsonParse(thing) {
54972
- if (isObject3(thing))
54972
+ if (isObject4(thing))
54973
54973
  return thing;
54974
54974
  try {
54975
54975
  return JSON.parse(thing);
@@ -61890,7 +61890,7 @@ var require_event_target_shim = __commonJS({
61890
61890
  var CAPTURE = 1;
61891
61891
  var BUBBLE = 2;
61892
61892
  var ATTRIBUTE = 3;
61893
- function isObject3(x2) {
61893
+ function isObject4(x2) {
61894
61894
  return x2 !== null && typeof x2 === "object";
61895
61895
  }
61896
61896
  function getListeners(eventTarget) {
@@ -61916,7 +61916,7 @@ var require_event_target_shim = __commonJS({
61916
61916
  return null;
61917
61917
  },
61918
61918
  set(listener) {
61919
- if (typeof listener !== "function" && !isObject3(listener)) {
61919
+ if (typeof listener !== "function" && !isObject4(listener)) {
61920
61920
  listener = null;
61921
61921
  }
61922
61922
  const listeners = getListeners(this);
@@ -62007,11 +62007,11 @@ var require_event_target_shim = __commonJS({
62007
62007
  if (listener == null) {
62008
62008
  return;
62009
62009
  }
62010
- if (typeof listener !== "function" && !isObject3(listener)) {
62010
+ if (typeof listener !== "function" && !isObject4(listener)) {
62011
62011
  throw new TypeError("'listener' should be a function or an object.");
62012
62012
  }
62013
62013
  const listeners = getListeners(this);
62014
- const optionsIsObj = isObject3(options2);
62014
+ const optionsIsObj = isObject4(options2);
62015
62015
  const capture = optionsIsObj ? Boolean(options2.capture) : Boolean(options2);
62016
62016
  const listenerType = capture ? CAPTURE : BUBBLE;
62017
62017
  const newNode = {
@@ -62048,7 +62048,7 @@ var require_event_target_shim = __commonJS({
62048
62048
  return;
62049
62049
  }
62050
62050
  const listeners = getListeners(this);
62051
- const capture = isObject3(options2) ? Boolean(options2.capture) : Boolean(options2);
62051
+ const capture = isObject4(options2) ? Boolean(options2.capture) : Boolean(options2);
62052
62052
  const listenerType = capture ? CAPTURE : BUBBLE;
62053
62053
  let prev = null;
62054
62054
  let node = listeners.get(eventName);
@@ -67220,11 +67220,11 @@ var require_ponyfill_es2018 = __commonJS({
67220
67220
  throw new TypeError(`${context2} is not a function.`);
67221
67221
  }
67222
67222
  }
67223
- function isObject3(x2) {
67223
+ function isObject4(x2) {
67224
67224
  return typeof x2 === "object" && x2 !== null || typeof x2 === "function";
67225
67225
  }
67226
67226
  function assertObject2(x2, context2) {
67227
- if (!isObject3(x2)) {
67227
+ if (!isObject4(x2)) {
67228
67228
  throw new TypeError(`${context2} is not an object.`);
67229
67229
  }
67230
67230
  }
@@ -73427,7 +73427,7 @@ var require_gaxios2 = __commonJS({
73427
73427
  var retry_js_1 = require_retry4();
73428
73428
  var stream_1 = __require("stream");
73429
73429
  var interceptor_js_1 = require_interceptor2();
73430
- var randomUUID7 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
73430
+ var randomUUID8 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
73431
73431
  var HTTP_STATUS_NO_CONTENT = 204;
73432
73432
  var Gaxios = class {
73433
73433
  agentCache = /* @__PURE__ */ new Map();
@@ -73700,7 +73700,7 @@ var require_gaxios2 = __commonJS({
73700
73700
  */
73701
73701
  ["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
73702
73702
  if (opts.multipart?.length) {
73703
- const boundary = await randomUUID7();
73703
+ const boundary = await randomUUID8();
73704
73704
  preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
73705
73705
  opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
73706
73706
  } else if (shouldDirectlyPassData) {
@@ -102305,15 +102305,15 @@ var require_merge = __commonJS({
102305
102305
  for (let i4 = 0, j = two.length; i4 < j; i4++) {
102306
102306
  result.push(takeValue(two[i4]));
102307
102307
  }
102308
- } else if (isObject3(two)) {
102308
+ } else if (isObject4(two)) {
102309
102309
  const keys = Object.keys(two);
102310
102310
  for (let i4 = 0, j = keys.length; i4 < j; i4++) {
102311
102311
  const key = keys[i4];
102312
102312
  result[key] = takeValue(two[key]);
102313
102313
  }
102314
102314
  }
102315
- } else if (isObject3(one)) {
102316
- if (isObject3(two)) {
102315
+ } else if (isObject4(one)) {
102316
+ if (isObject4(two)) {
102317
102317
  if (!shouldMerge(one, two)) {
102318
102318
  return two;
102319
102319
  }
@@ -102334,7 +102334,7 @@ var require_merge = __commonJS({
102334
102334
  if (wasObjectReferenced(one, key, objects) || wasObjectReferenced(two, key, objects)) {
102335
102335
  delete result[key];
102336
102336
  } else {
102337
- if (isObject3(obj1) && isObject3(obj2)) {
102337
+ if (isObject4(obj1) && isObject4(obj2)) {
102338
102338
  const arr1 = objects.get(obj1) || [];
102339
102339
  const arr2 = objects.get(obj2) || [];
102340
102340
  arr1.push({ obj: one, key });
@@ -102368,7 +102368,7 @@ var require_merge = __commonJS({
102368
102368
  function isFunction3(value) {
102369
102369
  return typeof value === "function";
102370
102370
  }
102371
- function isObject3(value) {
102371
+ function isObject4(value) {
102372
102372
  return !isPrimitive2(value) && !isArray2(value) && !isFunction3(value) && typeof value === "object";
102373
102373
  }
102374
102374
  function isPrimitive2(value) {
@@ -108173,7 +108173,7 @@ var require_minimal = __commonJS({
108173
108173
  util4.isString = function isString2(value) {
108174
108174
  return typeof value === "string" || value instanceof String;
108175
108175
  };
108176
- util4.isObject = function isObject3(value) {
108176
+ util4.isObject = function isObject4(value) {
108177
108177
  return value && typeof value === "object";
108178
108178
  };
108179
108179
  util4.isset = /**
@@ -129791,8 +129791,8 @@ var require_root2 = __commonJS({
129791
129791
  return metrics2;
129792
129792
  }();
129793
129793
  collector.logs = function() {
129794
- var logs2 = {};
129795
- logs2.v1 = function() {
129794
+ var logs3 = {};
129795
+ logs3.v1 = function() {
129796
129796
  var v13 = {};
129797
129797
  v13.LogsService = function() {
129798
129798
  function LogsService(rpcImpl, requestDelimited, responseDelimited) {
@@ -130132,7 +130132,7 @@ var require_root2 = __commonJS({
130132
130132
  }();
130133
130133
  return v13;
130134
130134
  }();
130135
- return logs2;
130135
+ return logs3;
130136
130136
  }();
130137
130137
  return collector;
130138
130138
  }();
@@ -133598,8 +133598,8 @@ var require_root2 = __commonJS({
133598
133598
  return metrics2;
133599
133599
  }();
133600
133600
  proto.logs = function() {
133601
- var logs2 = {};
133602
- logs2.v1 = function() {
133601
+ var logs3 = {};
133602
+ logs3.v1 = function() {
133603
133603
  var v13 = {};
133604
133604
  v13.LogsData = function() {
133605
133605
  function LogsData(properties) {
@@ -134537,7 +134537,7 @@ var require_root2 = __commonJS({
134537
134537
  }();
134538
134538
  return v13;
134539
134539
  }();
134540
- return logs2;
134540
+ return logs3;
134541
134541
  }();
134542
134542
  return proto;
134543
134543
  }();
@@ -140578,8 +140578,8 @@ var require_ConsoleLogRecordExporter = __commonJS({
140578
140578
  * @param logs
140579
140579
  * @param resultCallback
140580
140580
  */
140581
- export(logs2, resultCallback) {
140582
- this._sendLogRecords(logs2, resultCallback);
140581
+ export(logs3, resultCallback) {
140582
+ this._sendLogRecords(logs3, resultCallback);
140583
140583
  }
140584
140584
  /**
140585
140585
  * Shutdown the exporter.
@@ -140688,14 +140688,14 @@ var require_InMemoryLogRecordExporter = __commonJS({
140688
140688
  * When false, exported log records will not be stored in-memory.
140689
140689
  */
140690
140690
  _stopped = false;
140691
- export(logs2, resultCallback) {
140691
+ export(logs3, resultCallback) {
140692
140692
  if (this._stopped) {
140693
140693
  return resultCallback({
140694
140694
  code: core_1.ExportResultCode.FAILED,
140695
140695
  error: new Error("Exporter has been stopped")
140696
140696
  });
140697
140697
  }
140698
- this._finishedLogRecords.push(...logs2);
140698
+ this._finishedLogRecords.push(...logs3);
140699
140699
  resultCallback({ code: core_1.ExportResultCode.SUCCESS });
140700
140700
  }
140701
140701
  shutdown() {
@@ -217736,9 +217736,9 @@ var require_src60 = __commonJS({
217736
217736
  autoPaginate: options2.autoPaginate
217737
217737
  }, options2.gaxOptions);
217738
217738
  const resp = await this.loggingService.listLogs(reqOpts, gaxOptions);
217739
- const [logs2] = resp;
217740
- if (logs2) {
217741
- resp[0] = logs2.map((logName) => this.log(logName));
217739
+ const [logs3] = resp;
217740
+ if (logs3) {
217741
+ resp[0] = logs3.map((logName) => this.log(logName));
217742
217742
  }
217743
217743
  return resp;
217744
217744
  }
@@ -218873,7 +218873,7 @@ var require_cross_spawn = __commonJS({
218873
218873
  var cp = __require("child_process");
218874
218874
  var parse8 = require_parse6();
218875
218875
  var enoent = require_enoent();
218876
- function spawn9(command, args2, options2) {
218876
+ function spawn10(command, args2, options2) {
218877
218877
  const parsed = parse8(command, args2, options2);
218878
218878
  const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
218879
218879
  enoent.hookChildProcess(spawned, parsed);
@@ -218885,8 +218885,8 @@ var require_cross_spawn = __commonJS({
218885
218885
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
218886
218886
  return result;
218887
218887
  }
218888
- module2.exports = spawn9;
218889
- module2.exports.spawn = spawn9;
218888
+ module2.exports = spawn10;
218889
+ module2.exports.spawn = spawn10;
218890
218890
  module2.exports.sync = spawnSync4;
218891
218891
  module2.exports._parse = parse8;
218892
218892
  module2.exports._enoent = enoent;
@@ -268712,7 +268712,7 @@ var require_picomatch = __commonJS({
268712
268712
  var parse8 = require_parse11();
268713
268713
  var utils = require_utils22();
268714
268714
  var constants6 = require_constants11();
268715
- var isObject3 = (val) => val && typeof val === "object" && !Array.isArray(val);
268715
+ var isObject4 = (val) => val && typeof val === "object" && !Array.isArray(val);
268716
268716
  var picomatch2 = (glob2, options2, returnState = false) => {
268717
268717
  if (Array.isArray(glob2)) {
268718
268718
  const fns = glob2.map((input) => picomatch2(input, options2, returnState));
@@ -268725,7 +268725,7 @@ var require_picomatch = __commonJS({
268725
268725
  };
268726
268726
  return arrayMatcher;
268727
268727
  }
268728
- const isState = isObject3(glob2) && glob2.tokens && glob2.input;
268728
+ const isState = isObject4(glob2) && glob2.tokens && glob2.input;
268729
268729
  if (glob2 === "" || typeof glob2 !== "string" && !isState) {
268730
268730
  throw new TypeError("Expected pattern to be a non-empty string");
268731
268731
  }
@@ -305113,6 +305113,9 @@ var MessageBusType;
305113
305113
  MessageBusType2["TOOL_EXECUTION_SUCCESS"] = "tool-execution-success";
305114
305114
  MessageBusType2["TOOL_EXECUTION_FAILURE"] = "tool-execution-failure";
305115
305115
  MessageBusType2["UPDATE_POLICY"] = "update-policy";
305116
+ MessageBusType2["HOOK_EXECUTION_REQUEST"] = "hook-execution-request";
305117
+ MessageBusType2["HOOK_EXECUTION_RESPONSE"] = "hook-execution-response";
305118
+ MessageBusType2["HOOK_POLICY_DECISION"] = "hook-policy-decision";
305116
305119
  })(MessageBusType || (MessageBusType = {}));
305117
305120
 
305118
305121
  // packages/core/dist/src/tools/tools.js
@@ -305785,6 +305788,27 @@ function getCommonAttributes(config2) {
305785
305788
  };
305786
305789
  }
305787
305790
 
305791
+ // packages/core/dist/src/telemetry/sanitize.js
305792
+ function sanitizeHookName(hookName) {
305793
+ if (!hookName || !hookName.trim()) {
305794
+ return "unknown-command";
305795
+ }
305796
+ const parts2 = hookName.trim().split(/\s+/);
305797
+ if (parts2.length === 0) {
305798
+ return "unknown-command";
305799
+ }
305800
+ const command = parts2[0];
305801
+ if (!command) {
305802
+ return "unknown-command";
305803
+ }
305804
+ if (command.includes("/") || command.includes("\\")) {
305805
+ const pathParts = command.split(/[/\\]/);
305806
+ const basename13 = pathParts[pathParts.length - 1];
305807
+ return basename13 || "unknown-command";
305808
+ }
305809
+ return command;
305810
+ }
305811
+
305788
305812
  // packages/core/dist/src/telemetry/metrics.js
305789
305813
  var EVENT_CHAT_COMPRESSION = "gemini_cli.chat_compression";
305790
305814
  var TOOL_CALL_COUNT = "gemini_cli.tool.call.count";
@@ -305801,6 +305825,8 @@ var CONTENT_RETRY_FAILURE_COUNT = "gemini_cli.chat.content_retry_failure.count";
305801
305825
  var MODEL_ROUTING_LATENCY = "gemini_cli.model_routing.latency";
305802
305826
  var MODEL_ROUTING_FAILURE_COUNT = "gemini_cli.model_routing.failure.count";
305803
305827
  var MODEL_SLASH_COMMAND_CALL_COUNT = "gemini_cli.slash_command.model.call_count";
305828
+ var EVENT_HOOK_CALL_COUNT = "gemini_cli.hook_call.count";
305829
+ var EVENT_HOOK_CALL_LATENCY = "gemini_cli.hook_call.latency";
305804
305830
  var AGENT_RUN_COUNT = "gemini_cli.agent.run.count";
305805
305831
  var AGENT_DURATION_MS = "gemini_cli.agent.duration";
305806
305832
  var AGENT_TURNS = "gemini_cli.agent.turns";
@@ -305921,6 +305947,12 @@ var COUNTER_DEFINITIONS = {
305921
305947
  valueType: ValueType.INT,
305922
305948
  assign: (c4) => exitFailCounter = c4,
305923
305949
  attributes: {}
305950
+ },
305951
+ [EVENT_HOOK_CALL_COUNT]: {
305952
+ description: "Counts hook calls, tagged by hook event name and success.",
305953
+ valueType: ValueType.INT,
305954
+ assign: (c4) => hookCallCounter = c4,
305955
+ attributes: {}
305924
305956
  }
305925
305957
  };
305926
305958
  var HISTOGRAM_DEFINITIONS = {
@@ -305986,6 +306018,13 @@ var HISTOGRAM_DEFINITIONS = {
305986
306018
  valueType: ValueType.DOUBLE,
305987
306019
  assign: (h3) => genAiClientOperationDurationHistogram = h3,
305988
306020
  attributes: {}
306021
+ },
306022
+ [EVENT_HOOK_CALL_LATENCY]: {
306023
+ description: "Latency of hook calls in milliseconds.",
306024
+ unit: "ms",
306025
+ valueType: ValueType.INT,
306026
+ assign: (c4) => hookCallLatencyHistogram = c4,
306027
+ attributes: {}
305989
306028
  }
305990
306029
  };
305991
306030
  var PERFORMANCE_COUNTER_DEFINITIONS = {
@@ -306142,6 +306181,8 @@ var agentRecoveryAttemptDurationHistogram;
306142
306181
  var flickerFrameCounter;
306143
306182
  var exitFailCounter;
306144
306183
  var slowRenderHistogram;
306184
+ var hookCallCounter;
306185
+ var hookCallLatencyHistogram;
306145
306186
  var genAiClientTokenUsageHistogram;
306146
306187
  var genAiClientOperationDurationHistogram;
306147
306188
  var startupTimeHistogram;
@@ -306407,6 +306448,19 @@ function recordApiResponseMetrics(config2, durationMs, attributes) {
306407
306448
  });
306408
306449
  }
306409
306450
  }
306451
+ function recordHookCallMetrics(config2, hookEventName, hookName, durationMs, success) {
306452
+ if (!hookCallCounter || !hookCallLatencyHistogram || !isMetricsInitialized)
306453
+ return;
306454
+ const sanitizedHookName = sanitizeHookName(hookName);
306455
+ const metricAttributes = {
306456
+ ...baseMetricDefinition.getCommonAttributes(config2),
306457
+ hook_event_name: hookEventName,
306458
+ hook_name: sanitizedHookName,
306459
+ success
306460
+ };
306461
+ hookCallCounter.add(1, metricAttributes);
306462
+ hookCallLatencyHistogram.record(durationMs, metricAttributes);
306463
+ }
306410
306464
 
306411
306465
  // packages/core/dist/src/telemetry/types.js
306412
306466
  init_esm2();
@@ -307506,6 +307560,66 @@ var WebFetchFallbackAttemptEvent = class {
307506
307560
  return `Web fetch fallback attempt. Reason: ${this.reason}`;
307507
307561
  }
307508
307562
  };
307563
+ var EVENT_HOOK_CALL = "gemini_cli.hook_call";
307564
+ var HookCallEvent = class {
307565
+ "event.name";
307566
+ "event.timestamp";
307567
+ hook_event_name;
307568
+ hook_type;
307569
+ hook_name;
307570
+ hook_input;
307571
+ hook_output;
307572
+ exit_code;
307573
+ stdout;
307574
+ stderr;
307575
+ duration_ms;
307576
+ success;
307577
+ error;
307578
+ constructor(hookEventName, hookType, hookName, hookInput, durationMs, success, hookOutput, exitCode, stdout, stderr, error) {
307579
+ this["event.name"] = "hook_call";
307580
+ this["event.timestamp"] = (/* @__PURE__ */ new Date()).toISOString();
307581
+ this.hook_event_name = hookEventName;
307582
+ this.hook_type = hookType;
307583
+ this.hook_name = hookName;
307584
+ this.hook_input = hookInput;
307585
+ this.hook_output = hookOutput;
307586
+ this.exit_code = exitCode;
307587
+ this.stdout = stdout;
307588
+ this.stderr = stderr;
307589
+ this.duration_ms = durationMs;
307590
+ this.success = success;
307591
+ this.error = error;
307592
+ }
307593
+ toOpenTelemetryAttributes(config2) {
307594
+ const attributes = {
307595
+ ...getCommonAttributes(config2),
307596
+ "event.name": EVENT_HOOK_CALL,
307597
+ "event.timestamp": this["event.timestamp"],
307598
+ hook_event_name: this.hook_event_name,
307599
+ hook_type: this.hook_type,
307600
+ // Sanitize hook_name unless full logging is enabled
307601
+ hook_name: config2.getTelemetryLogPromptsEnabled() ? this.hook_name : sanitizeHookName(this.hook_name),
307602
+ duration_ms: this.duration_ms,
307603
+ success: this.success,
307604
+ exit_code: this.exit_code
307605
+ };
307606
+ if (config2.getTelemetryLogPromptsEnabled()) {
307607
+ attributes["hook_input"] = safeJsonStringify(this.hook_input, 2);
307608
+ attributes["hook_output"] = safeJsonStringify(this.hook_output, 2);
307609
+ attributes["stdout"] = this.stdout;
307610
+ attributes["stderr"] = this.stderr;
307611
+ }
307612
+ if (this.error) {
307613
+ attributes["error"] = this.error;
307614
+ }
307615
+ return attributes;
307616
+ }
307617
+ toLogBody() {
307618
+ const hookId = `${this.hook_event_name}.${this.hook_name}`;
307619
+ const status = `${this.success ? "succeeded" : "failed"}`;
307620
+ return `Hook call ${hookId} ${status} in ${this.duration_ms}ms`;
307621
+ }
307622
+ };
307509
307623
 
307510
307624
  // packages/core/dist/src/telemetry/loggers.js
307511
307625
  var import_api_logs = __toESM(require_src21(), 1);
@@ -307689,8 +307803,8 @@ var Float64Vector = import_vector.default.Float64Vector;
307689
307803
  var PointerVector = import_vector.default.PointerVector;
307690
307804
 
307691
307805
  // packages/core/dist/src/generated/git-commit.js
307692
- var GIT_COMMIT_INFO = "e177314a4";
307693
- var CLI_VERSION = "0.19.0-nightly.20251124.e177314a4";
307806
+ var GIT_COMMIT_INFO = "03845198c";
307807
+ var CLI_VERSION = "0.19.0-nightly.20251126.03845198c";
307694
307808
 
307695
307809
  // packages/core/dist/src/ide/detect-ide.js
307696
307810
  var IDE_DEFINITIONS = {
@@ -308902,8 +309016,8 @@ var FileSpanExporter = class extends FileExporter {
308902
309016
  }
308903
309017
  };
308904
309018
  var FileLogExporter = class extends FileExporter {
308905
- export(logs2, resultCallback) {
308906
- const data = logs2.map((log) => this.serialize(log)).join("");
309019
+ export(logs3, resultCallback) {
309020
+ const data = logs3.map((log) => this.serialize(log)).join("");
308907
309021
  this.writeStream.write(data, (err2) => {
308908
309022
  resultCallback({
308909
309023
  code: err2 ? import_core3.ExportResultCode.FAILED : import_core3.ExportResultCode.SUCCESS,
@@ -308960,9 +309074,9 @@ var GcpLogExporter = class {
308960
309074
  this.logging = new import_logging.Logging({ projectId });
308961
309075
  this.log = this.logging.log("gemini_cli");
308962
309076
  }
308963
- export(logs2, resultCallback) {
309077
+ export(logs3, resultCallback) {
308964
309078
  try {
308965
- const entries2 = logs2.map((log) => {
309079
+ const entries2 = logs3.map((log) => {
308966
309080
  const entry = this.log.entry({
308967
309081
  severity: this.mapSeverityToCloudLogging(log.severityNumber),
308968
309082
  timestamp: new Date((0, import_core4.hrTimeToMilliseconds)(log.hrTime)),
@@ -310238,6 +310352,17 @@ function logLlmLoopCheck(config2, event) {
310238
310352
  };
310239
310353
  logger6.emit(logRecord);
310240
310354
  }
310355
+ function logHookCall(config2, event) {
310356
+ if (!isTelemetrySdkInitialized())
310357
+ return;
310358
+ const logger6 = import_api_logs.logs.getLogger(SERVICE_NAME);
310359
+ const logRecord = {
310360
+ body: event.toLogBody(),
310361
+ attributes: event.toOpenTelemetryAttributes(config2)
310362
+ };
310363
+ logger6.emit(logRecord);
310364
+ recordHookCallMetrics(config2, event.hook_event_name, event.hook_name, event.duration_ms, event.success);
310365
+ }
310241
310366
 
310242
310367
  // packages/core/dist/src/utils/quotaErrorDetection.js
310243
310368
  function isApiError(error) {
@@ -310581,7 +310706,7 @@ async function createContentGenerator(config2, gcConfig, sessionId2) {
310581
310706
  if (gcConfig.fakeResponses) {
310582
310707
  return FakeContentGenerator.fromFile(gcConfig.fakeResponses);
310583
310708
  }
310584
- const version3 = "0.19.0-nightly.20251124.e177314a4";
310709
+ const version3 = "0.19.0-nightly.20251126.03845198c";
310585
310710
  const userAgent = `GeminiCLI/${version3} (${process.platform}; ${process.arch})`;
310586
310711
  const baseHeaders = {
310587
310712
  "User-Agent": userAgent
@@ -333275,6 +333400,19 @@ var PolicyDecision;
333275
333400
  PolicyDecision2["DENY"] = "deny";
333276
333401
  PolicyDecision2["ASK_USER"] = "ask_user";
333277
333402
  })(PolicyDecision || (PolicyDecision = {}));
333403
+ var VALID_HOOK_SOURCES = [
333404
+ "project",
333405
+ "user",
333406
+ "system",
333407
+ "extension"
333408
+ ];
333409
+ function getHookSource(input) {
333410
+ const source = input["hook_source"];
333411
+ if (typeof source === "string" && VALID_HOOK_SOURCES.includes(source)) {
333412
+ return source;
333413
+ }
333414
+ return "project";
333415
+ }
333278
333416
  var ApprovalMode;
333279
333417
  (function(ApprovalMode2) {
333280
333418
  ApprovalMode2["DEFAULT"] = "default";
@@ -356971,13 +357109,14 @@ async function handleFallback(config2, failedModel, authType, error) {
356971
357109
  if (error instanceof ModelNotFoundError && failedModel !== PREVIEW_GEMINI_MODEL) {
356972
357110
  return null;
356973
357111
  }
356974
- if (failedModel === PREVIEW_GEMINI_MODEL) {
357112
+ const shouldActivatePreviewFallback = failedModel === PREVIEW_GEMINI_MODEL && !(error instanceof TerminalQuotaError);
357113
+ if (shouldActivatePreviewFallback) {
356975
357114
  config2.setPreviewModelBypassMode(true);
356976
357115
  if (config2.isPreviewModelFallbackMode()) {
356977
357116
  return true;
356978
357117
  }
356979
357118
  }
356980
- const fallbackModel = failedModel === PREVIEW_GEMINI_MODEL ? DEFAULT_GEMINI_MODEL : DEFAULT_GEMINI_FLASH_MODEL;
357119
+ const fallbackModel = shouldActivatePreviewFallback ? DEFAULT_GEMINI_MODEL : DEFAULT_GEMINI_FLASH_MODEL;
356981
357120
  const fallbackModelHandler = config2.fallbackModelHandler;
356982
357121
  if (typeof fallbackModelHandler !== "function")
356983
357122
  return null;
@@ -356985,7 +357124,7 @@ async function handleFallback(config2, failedModel, authType, error) {
356985
357124
  const intent = await fallbackModelHandler(failedModel, fallbackModel, error);
356986
357125
  switch (intent) {
356987
357126
  case "retry_always":
356988
- if (failedModel === PREVIEW_GEMINI_MODEL) {
357127
+ if (shouldActivatePreviewFallback) {
356989
357128
  activatePreviewModelFallbackMode(config2);
356990
357129
  } else {
356991
357130
  activateFallbackMode(config2, authType);
@@ -357006,7 +357145,7 @@ async function handleFallback(config2, failedModel, authType, error) {
357006
357145
  throw new Error(`Unexpected fallback intent received from fallbackModelHandler: "${intent}"`);
357007
357146
  }
357008
357147
  } catch (handlerError) {
357009
- console.error("Fallback UI handler failed:", handlerError);
357148
+ debugLogger.error("Fallback UI handler failed:", handlerError);
357010
357149
  return null;
357011
357150
  }
357012
357151
  }
@@ -357284,7 +357423,7 @@ var GeminiChat = class {
357284
357423
  signal: generateContentConfig.abortSignal,
357285
357424
  maxAttempts: this.config.isPreviewModelFallbackMode() && model === PREVIEW_GEMINI_MODEL ? 1 : void 0
357286
357425
  });
357287
- return this.processStreamResponse(model, streamResponse);
357426
+ return this.processStreamResponse(effectiveModel, streamResponse);
357288
357427
  }
357289
357428
  /**
357290
357429
  * Returns the chat history.
@@ -357671,6 +357810,13 @@ ${[...this.pendingCitations].sort().join("\n")}`
357671
357810
  getDebugResponses() {
357672
357811
  return this.debugResponses;
357673
357812
  }
357813
+ /**
357814
+ * Get the concatenated response text from all responses in this turn.
357815
+ * This extracts and joins all text content from the model's responses.
357816
+ */
357817
+ getResponseText() {
357818
+ return this.debugResponses.map((response) => getResponseText(response)).filter((text) => text !== null).join(" ");
357819
+ }
357674
357820
  };
357675
357821
  function getCitations(resp) {
357676
357822
  return (resp.candidates?.[0]?.citationMetadata?.citations ?? []).filter((citation) => citation.uri !== void 0).map((citation) => {
@@ -358028,6 +358174,8 @@ function getCoreSystemPrompt(config2, userMemory) {
358028
358174
  throw new Error(`missing system prompt file '${systemMdPath}'`);
358029
358175
  }
358030
358176
  }
358177
+ const desiredModel = getEffectiveModel(config2.isInFallbackMode(), config2.getModel(), config2.getPreviewFeatures());
358178
+ const useChattySystemPrompt = desiredModel === PREVIEW_GEMINI_MODEL;
358031
358179
  const enableCodebaseInvestigator = config2.getToolRegistry().getAllToolNames().includes(CodebaseInvestigatorAgent.name);
358032
358180
  const enableWriteTodosTool = config2.getToolRegistry().getAllToolNames().includes(WriteTodosTool.Name);
358033
358181
  let basePrompt;
@@ -358125,7 +358273,13 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
358125
358273
  - **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
358126
358274
  - **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.
358127
358275
  - **Clarity over Brevity (When Needed):** While conciseness is key, prioritize clarity for essential explanations or when seeking necessary clarification if a request is ambiguous.
358128
- - **No Chitchat:** Avoid conversational filler, preambles ("Okay, I will now..."), or postambles ("I have finished the changes..."). Get straight to the action or answer.
358276
+ ${function() {
358277
+ if (useChattySystemPrompt) {
358278
+ return "";
358279
+ } else {
358280
+ 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.';
358281
+ }
358282
+ }()}
358129
358283
  - **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
358130
358284
  - **Tools vs. Text:** Use tools for actions, text output *only* for communication. Do not add explanatory comments within tool calls or code blocks unless specifically part of the required code/command itself.
358131
358285
  - **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -358769,6 +358923,20 @@ function findCompressSplitPoint(contents, fraction) {
358769
358923
  }
358770
358924
  return lastSplitPoint;
358771
358925
  }
358926
+ function modelStringToModelConfigAlias(model) {
358927
+ switch (model) {
358928
+ case PREVIEW_GEMINI_MODEL:
358929
+ return "chat-compression-3-pro";
358930
+ case DEFAULT_GEMINI_MODEL:
358931
+ return "chat-compression-2.5-pro";
358932
+ case DEFAULT_GEMINI_FLASH_MODEL:
358933
+ return "chat-compression-2.5-flash";
358934
+ case DEFAULT_GEMINI_FLASH_LITE_MODEL:
358935
+ return "chat-compression-2.5-flash-lite";
358936
+ default:
358937
+ return "chat-compression-default";
358938
+ }
358939
+ }
358772
358940
  var ChatCompressionService = class {
358773
358941
  async compress(chat, promptId, force, model, config2, hasFailedCompressionAttempt) {
358774
358942
  const curatedHistory = chat.getHistory(true);
@@ -358809,8 +358977,8 @@ var ChatCompressionService = class {
358809
358977
  }
358810
358978
  };
358811
358979
  }
358812
- const summaryResponse = await config2.getContentGenerator().generateContent({
358813
- model,
358980
+ const summaryResponse = await config2.getBaseLlmClient().generateContent({
358981
+ modelConfigKey: { model: modelStringToModelConfigAlias(model) },
358814
358982
  contents: [
358815
358983
  ...historyToCompress,
358816
358984
  {
@@ -358822,10 +358990,11 @@ var ChatCompressionService = class {
358822
358990
  ]
358823
358991
  }
358824
358992
  ],
358825
- config: {
358826
- systemInstruction: { text: getCompressionPrompt() }
358827
- }
358828
- }, promptId);
358993
+ systemInstruction: { text: getCompressionPrompt() },
358994
+ promptId,
358995
+ // TODO(joshualitt): wire up a sensible abort signal,
358996
+ abortSignal: new AbortController().signal
358997
+ });
358829
358998
  const summary = getResponseText(summaryResponse) ?? "";
358830
358999
  const extraHistory = [
358831
359000
  {
@@ -358866,8 +359035,460 @@ var ChatCompressionService = class {
358866
359035
  }
358867
359036
  };
358868
359037
 
359038
+ // packages/core/dist/src/hooks/hookTranslator.js
359039
+ var HookTranslator = class {
359040
+ };
359041
+ function hasTextProperty(value) {
359042
+ return typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
359043
+ }
359044
+ function isContentWithParts(content) {
359045
+ return typeof content === "object" && content !== null && "role" in content && "parts" in content;
359046
+ }
359047
+ function extractGenerationConfig(request3) {
359048
+ if (request3.config && typeof request3.config === "object") {
359049
+ const config2 = request3.config;
359050
+ return {
359051
+ temperature: config2.temperature,
359052
+ maxOutputTokens: config2.maxOutputTokens,
359053
+ topP: config2.topP,
359054
+ topK: config2.topK
359055
+ };
359056
+ }
359057
+ return void 0;
359058
+ }
359059
+ var HookTranslatorGenAIv1 = class extends HookTranslator {
359060
+ /**
359061
+ * Convert genai SDK GenerateContentParameters to stable LLMRequest
359062
+ *
359063
+ * Note: This implementation intentionally extracts only text content from parts.
359064
+ * Non-text parts (images, function calls, etc.) are filtered out in v1 to provide
359065
+ * a simplified, stable interface for hooks. This allows hooks to focus on text
359066
+ * manipulation without needing to handle complex multimodal content.
359067
+ * Future versions may expose additional content types if needed.
359068
+ */
359069
+ toHookLLMRequest(sdkRequest) {
359070
+ const messages = [];
359071
+ if (sdkRequest.contents) {
359072
+ const contents = Array.isArray(sdkRequest.contents) ? sdkRequest.contents : [sdkRequest.contents];
359073
+ for (const content of contents) {
359074
+ if (typeof content === "string") {
359075
+ messages.push({
359076
+ role: "user",
359077
+ content
359078
+ });
359079
+ } else if (isContentWithParts(content)) {
359080
+ const role = content.role === "model" ? "model" : content.role === "system" ? "system" : "user";
359081
+ const parts2 = Array.isArray(content.parts) ? content.parts : [content.parts];
359082
+ const textContent2 = parts2.filter(hasTextProperty).map((part) => part.text).join("");
359083
+ if (textContent2) {
359084
+ messages.push({
359085
+ role,
359086
+ content: textContent2
359087
+ });
359088
+ }
359089
+ }
359090
+ }
359091
+ }
359092
+ const config2 = extractGenerationConfig(sdkRequest);
359093
+ return {
359094
+ model: sdkRequest.model || DEFAULT_GEMINI_FLASH_MODEL,
359095
+ messages,
359096
+ config: {
359097
+ temperature: config2?.temperature,
359098
+ maxOutputTokens: config2?.maxOutputTokens,
359099
+ topP: config2?.topP,
359100
+ topK: config2?.topK
359101
+ }
359102
+ };
359103
+ }
359104
+ /**
359105
+ * Convert stable LLMRequest to genai SDK GenerateContentParameters
359106
+ */
359107
+ fromHookLLMRequest(hookRequest, baseRequest) {
359108
+ const contents = hookRequest.messages.map((message) => ({
359109
+ role: message.role === "model" ? "model" : message.role,
359110
+ parts: [
359111
+ {
359112
+ text: typeof message.content === "string" ? message.content : String(message.content)
359113
+ }
359114
+ ]
359115
+ }));
359116
+ const result = {
359117
+ ...baseRequest,
359118
+ model: hookRequest.model,
359119
+ contents
359120
+ };
359121
+ if (hookRequest.config) {
359122
+ const baseConfig = baseRequest ? extractGenerationConfig(baseRequest) : void 0;
359123
+ result.config = {
359124
+ ...baseConfig,
359125
+ temperature: hookRequest.config.temperature,
359126
+ maxOutputTokens: hookRequest.config.maxOutputTokens,
359127
+ topP: hookRequest.config.topP,
359128
+ topK: hookRequest.config.topK
359129
+ };
359130
+ }
359131
+ return result;
359132
+ }
359133
+ /**
359134
+ * Convert genai SDK GenerateContentResponse to stable LLMResponse
359135
+ */
359136
+ toHookLLMResponse(sdkResponse) {
359137
+ return {
359138
+ text: sdkResponse.text,
359139
+ candidates: (sdkResponse.candidates || []).map((candidate) => {
359140
+ const textParts = candidate.content?.parts?.filter(hasTextProperty).map((part) => part.text) || [];
359141
+ return {
359142
+ content: {
359143
+ role: "model",
359144
+ parts: textParts
359145
+ },
359146
+ finishReason: candidate.finishReason,
359147
+ index: candidate.index,
359148
+ safetyRatings: candidate.safetyRatings?.map((rating) => ({
359149
+ category: String(rating.category || ""),
359150
+ probability: String(rating.probability || "")
359151
+ }))
359152
+ };
359153
+ }),
359154
+ usageMetadata: sdkResponse.usageMetadata ? {
359155
+ promptTokenCount: sdkResponse.usageMetadata.promptTokenCount,
359156
+ candidatesTokenCount: sdkResponse.usageMetadata.candidatesTokenCount,
359157
+ totalTokenCount: sdkResponse.usageMetadata.totalTokenCount
359158
+ } : void 0
359159
+ };
359160
+ }
359161
+ /**
359162
+ * Convert stable LLMResponse to genai SDK GenerateContentResponse
359163
+ */
359164
+ fromHookLLMResponse(hookResponse) {
359165
+ const response = {
359166
+ text: hookResponse.text,
359167
+ candidates: hookResponse.candidates.map((candidate) => ({
359168
+ content: {
359169
+ role: "model",
359170
+ parts: candidate.content.parts.map((part) => ({
359171
+ text: part
359172
+ }))
359173
+ },
359174
+ finishReason: candidate.finishReason,
359175
+ index: candidate.index,
359176
+ safetyRatings: candidate.safetyRatings
359177
+ })),
359178
+ usageMetadata: hookResponse.usageMetadata
359179
+ };
359180
+ return response;
359181
+ }
359182
+ /**
359183
+ * Convert genai SDK ToolConfig to stable HookToolConfig
359184
+ */
359185
+ toHookToolConfig(sdkToolConfig) {
359186
+ return {
359187
+ mode: sdkToolConfig.functionCallingConfig?.mode,
359188
+ allowedFunctionNames: sdkToolConfig.functionCallingConfig?.allowedFunctionNames
359189
+ };
359190
+ }
359191
+ /**
359192
+ * Convert stable HookToolConfig to genai SDK ToolConfig
359193
+ */
359194
+ fromHookToolConfig(hookToolConfig) {
359195
+ const functionCallingConfig = hookToolConfig.mode || hookToolConfig.allowedFunctionNames ? {
359196
+ mode: hookToolConfig.mode,
359197
+ allowedFunctionNames: hookToolConfig.allowedFunctionNames
359198
+ } : void 0;
359199
+ return {
359200
+ functionCallingConfig
359201
+ };
359202
+ }
359203
+ };
359204
+ var defaultHookTranslator = new HookTranslatorGenAIv1();
359205
+
359206
+ // packages/core/dist/src/hooks/types.js
359207
+ var HookEventName;
359208
+ (function(HookEventName2) {
359209
+ HookEventName2["BeforeTool"] = "BeforeTool";
359210
+ HookEventName2["AfterTool"] = "AfterTool";
359211
+ HookEventName2["BeforeAgent"] = "BeforeAgent";
359212
+ HookEventName2["Notification"] = "Notification";
359213
+ HookEventName2["AfterAgent"] = "AfterAgent";
359214
+ HookEventName2["SessionStart"] = "SessionStart";
359215
+ HookEventName2["SessionEnd"] = "SessionEnd";
359216
+ HookEventName2["PreCompress"] = "PreCompress";
359217
+ HookEventName2["BeforeModel"] = "BeforeModel";
359218
+ HookEventName2["AfterModel"] = "AfterModel";
359219
+ HookEventName2["BeforeToolSelection"] = "BeforeToolSelection";
359220
+ })(HookEventName || (HookEventName = {}));
359221
+ var HookType;
359222
+ (function(HookType2) {
359223
+ HookType2["Command"] = "command";
359224
+ })(HookType || (HookType = {}));
359225
+ function createHookOutput(eventName, data) {
359226
+ switch (eventName) {
359227
+ case "BeforeModel":
359228
+ return new BeforeModelHookOutput(data);
359229
+ case "AfterModel":
359230
+ return new AfterModelHookOutput(data);
359231
+ case "BeforeToolSelection":
359232
+ return new BeforeToolSelectionHookOutput(data);
359233
+ default:
359234
+ return new DefaultHookOutput(data);
359235
+ }
359236
+ }
359237
+ var DefaultHookOutput = class {
359238
+ continue;
359239
+ stopReason;
359240
+ suppressOutput;
359241
+ systemMessage;
359242
+ decision;
359243
+ reason;
359244
+ hookSpecificOutput;
359245
+ constructor(data = {}) {
359246
+ this.continue = data.continue;
359247
+ this.stopReason = data.stopReason;
359248
+ this.suppressOutput = data.suppressOutput;
359249
+ this.systemMessage = data.systemMessage;
359250
+ this.decision = data.decision;
359251
+ this.reason = data.reason;
359252
+ this.hookSpecificOutput = data.hookSpecificOutput;
359253
+ }
359254
+ /**
359255
+ * Check if this output represents a blocking decision
359256
+ */
359257
+ isBlockingDecision() {
359258
+ return this.decision === "block" || this.decision === "deny";
359259
+ }
359260
+ /**
359261
+ * Check if this output requests to stop execution
359262
+ */
359263
+ shouldStopExecution() {
359264
+ return this.continue === false;
359265
+ }
359266
+ /**
359267
+ * Get the effective reason for blocking or stopping
359268
+ */
359269
+ getEffectiveReason() {
359270
+ return this.reason || this.stopReason || "No reason provided";
359271
+ }
359272
+ /**
359273
+ * Apply LLM request modifications (specific method for BeforeModel hooks)
359274
+ */
359275
+ applyLLMRequestModifications(target) {
359276
+ return target;
359277
+ }
359278
+ /**
359279
+ * Apply tool config modifications (specific method for BeforeToolSelection hooks)
359280
+ */
359281
+ applyToolConfigModifications(target) {
359282
+ return target;
359283
+ }
359284
+ /**
359285
+ * Get additional context for adding to responses
359286
+ */
359287
+ getAdditionalContext() {
359288
+ if (this.hookSpecificOutput && "additionalContext" in this.hookSpecificOutput) {
359289
+ const context2 = this.hookSpecificOutput["additionalContext"];
359290
+ return typeof context2 === "string" ? context2 : void 0;
359291
+ }
359292
+ return void 0;
359293
+ }
359294
+ /**
359295
+ * Check if execution should be blocked and return error info
359296
+ */
359297
+ getBlockingError() {
359298
+ if (this.isBlockingDecision()) {
359299
+ return {
359300
+ blocked: true,
359301
+ reason: this.getEffectiveReason()
359302
+ };
359303
+ }
359304
+ return { blocked: false, reason: "" };
359305
+ }
359306
+ };
359307
+ var BeforeToolHookOutput = class extends DefaultHookOutput {
359308
+ /**
359309
+ * Get the effective blocking reason, considering compatibility fields
359310
+ */
359311
+ getEffectiveReason() {
359312
+ if (this.hookSpecificOutput) {
359313
+ if ("permissionDecisionReason" in this.hookSpecificOutput) {
359314
+ const compatReason = this.hookSpecificOutput["permissionDecisionReason"];
359315
+ if (typeof compatReason === "string") {
359316
+ return compatReason;
359317
+ }
359318
+ }
359319
+ }
359320
+ return super.getEffectiveReason();
359321
+ }
359322
+ /**
359323
+ * Check if this output represents a blocking decision, considering compatibility fields
359324
+ */
359325
+ isBlockingDecision() {
359326
+ if (this.hookSpecificOutput && "permissionDecision" in this.hookSpecificOutput) {
359327
+ const compatDecision = this.hookSpecificOutput["permissionDecision"];
359328
+ if (compatDecision === "block" || compatDecision === "deny") {
359329
+ return true;
359330
+ }
359331
+ }
359332
+ return super.isBlockingDecision();
359333
+ }
359334
+ };
359335
+ var BeforeModelHookOutput = class extends DefaultHookOutput {
359336
+ /**
359337
+ * Get synthetic LLM response if provided by hook
359338
+ */
359339
+ getSyntheticResponse() {
359340
+ if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
359341
+ const hookResponse = this.hookSpecificOutput["llm_response"];
359342
+ if (hookResponse) {
359343
+ return defaultHookTranslator.fromHookLLMResponse(hookResponse);
359344
+ }
359345
+ }
359346
+ return void 0;
359347
+ }
359348
+ /**
359349
+ * Apply modifications to LLM request
359350
+ */
359351
+ applyLLMRequestModifications(target) {
359352
+ if (this.hookSpecificOutput && "llm_request" in this.hookSpecificOutput) {
359353
+ const hookRequest = this.hookSpecificOutput["llm_request"];
359354
+ if (hookRequest) {
359355
+ const sdkRequest = defaultHookTranslator.fromHookLLMRequest(hookRequest, target);
359356
+ return {
359357
+ ...target,
359358
+ ...sdkRequest
359359
+ };
359360
+ }
359361
+ }
359362
+ return target;
359363
+ }
359364
+ };
359365
+ var BeforeToolSelectionHookOutput = class extends DefaultHookOutput {
359366
+ /**
359367
+ * Apply tool configuration modifications
359368
+ */
359369
+ applyToolConfigModifications(target) {
359370
+ if (this.hookSpecificOutput && "toolConfig" in this.hookSpecificOutput) {
359371
+ const hookToolConfig = this.hookSpecificOutput["toolConfig"];
359372
+ if (hookToolConfig) {
359373
+ const sdkToolConfig = defaultHookTranslator.fromHookToolConfig(hookToolConfig);
359374
+ return {
359375
+ ...target,
359376
+ tools: target.tools || [],
359377
+ toolConfig: sdkToolConfig
359378
+ };
359379
+ }
359380
+ }
359381
+ return target;
359382
+ }
359383
+ };
359384
+ var AfterModelHookOutput = class extends DefaultHookOutput {
359385
+ /**
359386
+ * Get modified LLM response if provided by hook
359387
+ */
359388
+ getModifiedResponse() {
359389
+ if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
359390
+ const hookResponse = this.hookSpecificOutput["llm_response"];
359391
+ if (hookResponse?.candidates?.[0]?.content?.parts?.length) {
359392
+ return defaultHookTranslator.fromHookLLMResponse(hookResponse);
359393
+ }
359394
+ }
359395
+ if (this.shouldStopExecution()) {
359396
+ const stopResponse = {
359397
+ candidates: [
359398
+ {
359399
+ content: {
359400
+ role: "model",
359401
+ parts: [this.getEffectiveReason() || "Execution stopped by hook"]
359402
+ },
359403
+ finishReason: "STOP"
359404
+ }
359405
+ ]
359406
+ };
359407
+ return defaultHookTranslator.fromHookLLMResponse(stopResponse);
359408
+ }
359409
+ return void 0;
359410
+ }
359411
+ };
359412
+ var NotificationType;
359413
+ (function(NotificationType2) {
359414
+ NotificationType2["ToolPermission"] = "ToolPermission";
359415
+ })(NotificationType || (NotificationType = {}));
359416
+ var SessionStartSource;
359417
+ (function(SessionStartSource2) {
359418
+ SessionStartSource2["Startup"] = "startup";
359419
+ SessionStartSource2["Resume"] = "resume";
359420
+ SessionStartSource2["Clear"] = "clear";
359421
+ SessionStartSource2["Compress"] = "compress";
359422
+ })(SessionStartSource || (SessionStartSource = {}));
359423
+ var SessionEndReason;
359424
+ (function(SessionEndReason2) {
359425
+ SessionEndReason2["Exit"] = "exit";
359426
+ SessionEndReason2["Clear"] = "clear";
359427
+ SessionEndReason2["Logout"] = "logout";
359428
+ SessionEndReason2["PromptInputExit"] = "prompt_input_exit";
359429
+ SessionEndReason2["Other"] = "other";
359430
+ })(SessionEndReason || (SessionEndReason = {}));
359431
+ var PreCompressTrigger;
359432
+ (function(PreCompressTrigger2) {
359433
+ PreCompressTrigger2["Manual"] = "manual";
359434
+ PreCompressTrigger2["Auto"] = "auto";
359435
+ })(PreCompressTrigger || (PreCompressTrigger = {}));
359436
+
359437
+ // packages/core/dist/src/core/clientHookTriggers.js
359438
+ async function fireBeforeAgentHook(messageBus, request3) {
359439
+ try {
359440
+ const promptText = partToString(request3);
359441
+ const response = await messageBus.request({
359442
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
359443
+ eventName: "BeforeAgent",
359444
+ input: {
359445
+ prompt: promptText
359446
+ }
359447
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
359448
+ return response.output ? createHookOutput("BeforeAgent", response.output) : void 0;
359449
+ } catch (error) {
359450
+ debugLogger.warn(`BeforeAgent hook failed: ${error}`);
359451
+ return void 0;
359452
+ }
359453
+ }
359454
+ async function fireAfterAgentHook(messageBus, request3, responseText) {
359455
+ try {
359456
+ const promptText = partToString(request3);
359457
+ const response = await messageBus.request({
359458
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
359459
+ eventName: "AfterAgent",
359460
+ input: {
359461
+ prompt: promptText,
359462
+ prompt_response: responseText,
359463
+ stop_hook_active: false
359464
+ }
359465
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
359466
+ return response.output ? createHookOutput("AfterAgent", response.output) : void 0;
359467
+ } catch (error) {
359468
+ debugLogger.warn(`AfterAgent hook failed: ${error}`);
359469
+ return void 0;
359470
+ }
359471
+ }
359472
+
358869
359473
  // packages/core/dist/src/core/client.js
358870
359474
  var MAX_TURNS = 100;
359475
+ function estimateTextOnlyLength(request3) {
359476
+ if (typeof request3 === "string") {
359477
+ return request3.length;
359478
+ }
359479
+ if (!Array.isArray(request3)) {
359480
+ return 0;
359481
+ }
359482
+ let textLength = 0;
359483
+ for (const part of request3) {
359484
+ if (typeof part === "string") {
359485
+ textLength += part.length;
359486
+ } else if (typeof part === "object" && part !== null && "text" in part && part.text) {
359487
+ textLength += part.text.length;
359488
+ }
359489
+ }
359490
+ return textLength;
359491
+ }
358871
359492
  var GeminiClient = class {
358872
359493
  config;
358873
359494
  chat;
@@ -359114,6 +359735,25 @@ var GeminiClient = class {
359114
359735
  return getEffectiveModel(this.config.isInFallbackMode(), configModel, this.config.getPreviewFeatures());
359115
359736
  }
359116
359737
  async *sendMessageStream(request3, signal, prompt_id, turns = MAX_TURNS, isInvalidStreamRetry = false) {
359738
+ const hooksEnabled = this.config.getEnableHooks();
359739
+ const messageBus = this.config.getMessageBus();
359740
+ if (hooksEnabled && messageBus) {
359741
+ const hookOutput = await fireBeforeAgentHook(messageBus, request3);
359742
+ if (hookOutput?.isBlockingDecision() || hookOutput?.shouldStopExecution()) {
359743
+ yield {
359744
+ type: GeminiEventType.Error,
359745
+ value: {
359746
+ error: new Error(`BeforeAgent hook blocked processing: ${hookOutput.getEffectiveReason()}`)
359747
+ }
359748
+ };
359749
+ return new Turn(this.getChat(), prompt_id);
359750
+ }
359751
+ const additionalContext = hookOutput?.getAdditionalContext();
359752
+ if (additionalContext) {
359753
+ const requestArray = Array.isArray(request3) ? request3 : [request3];
359754
+ request3 = [...requestArray, { text: additionalContext }];
359755
+ }
359756
+ }
359117
359757
  if (this.lastPromptId !== prompt_id) {
359118
359758
  this.loopDetector.reset(prompt_id);
359119
359759
  this.lastPromptId = prompt_id;
@@ -359129,7 +359769,7 @@ var GeminiClient = class {
359129
359769
  return new Turn(this.getChat(), prompt_id);
359130
359770
  }
359131
359771
  const modelForLimitCheck = this._getEffectiveModelForCurrentTurn();
359132
- const estimatedRequestTokenCount = Math.floor(JSON.stringify(request3).length / 4);
359772
+ const estimatedRequestTokenCount = Math.floor(estimateTextOnlyLength(request3) / 4);
359133
359773
  const remainingTokenCount = tokenLimit(modelForLimitCheck) - this.getChat().getLastPromptTokenCount();
359134
359774
  if (estimatedRequestTokenCount > remainingTokenCount * 0.95) {
359135
359775
  yield {
@@ -359222,7 +359862,16 @@ var GeminiClient = class {
359222
359862
  logNextSpeakerCheck(this.config, new NextSpeakerCheckEvent(prompt_id, turn.finishReason?.toString() || "", nextSpeakerCheck?.next_speaker || ""));
359223
359863
  if (nextSpeakerCheck?.next_speaker === "model") {
359224
359864
  const nextRequest = [{ text: "Please continue." }];
359225
- yield* this.sendMessageStream(nextRequest, signal, prompt_id, boundedTurns - 1);
359865
+ return yield* this.sendMessageStream(nextRequest, signal, prompt_id, boundedTurns - 1);
359866
+ }
359867
+ }
359868
+ if (hooksEnabled && messageBus) {
359869
+ const responseText = turn.getResponseText() || "[no response text]";
359870
+ const hookOutput = await fireAfterAgentHook(messageBus, request3, responseText);
359871
+ if (hookOutput?.isBlockingDecision() || hookOutput?.shouldStopExecution()) {
359872
+ const continueReason = hookOutput.getEffectiveReason();
359873
+ const continueRequest = [{ text: continueReason }];
359874
+ yield* this.sendMessageStream(continueRequest, signal, prompt_id, boundedTurns - 1);
359226
359875
  }
359227
359876
  }
359228
359877
  return turn;
@@ -364822,6 +365471,31 @@ var DEFAULT_MODEL_CONFIGS = {
364822
365471
  "next-speaker-checker": {
364823
365472
  extends: "gemini-2.5-flash-base",
364824
365473
  modelConfig: {}
365474
+ },
365475
+ "chat-compression-3-pro": {
365476
+ modelConfig: {
365477
+ model: "gemini-3-pro-preview"
365478
+ }
365479
+ },
365480
+ "chat-compression-2.5-pro": {
365481
+ modelConfig: {
365482
+ model: "gemini-2.5-pro"
365483
+ }
365484
+ },
365485
+ "chat-compression-2.5-flash": {
365486
+ modelConfig: {
365487
+ model: "gemini-2.5-flash"
365488
+ }
365489
+ },
365490
+ "chat-compression-2.5-flash-lite": {
365491
+ modelConfig: {
365492
+ model: "gemini-2.5-flash-lite"
365493
+ }
365494
+ },
365495
+ "chat-compression-default": {
365496
+ modelConfig: {
365497
+ model: "gemini-2.5-pro"
365498
+ }
364825
365499
  }
364826
365500
  }
364827
365501
  };
@@ -364973,6 +365647,7 @@ var WorkspaceContext = class {
364973
365647
  };
364974
365648
 
364975
365649
  // packages/core/dist/src/confirmation-bus/message-bus.js
365650
+ import { randomUUID as randomUUID6 } from "node:crypto";
364976
365651
  import { EventEmitter as EventEmitter10 } from "node:events";
364977
365652
  var MessageBus = class extends EventEmitter10 {
364978
365653
  policyEngine;
@@ -365030,6 +365705,27 @@ var MessageBus = class extends EventEmitter10 {
365030
365705
  default:
365031
365706
  throw new Error(`Unknown policy decision: ${decision}`);
365032
365707
  }
365708
+ } else if (message.type === MessageBusType.HOOK_EXECUTION_REQUEST) {
365709
+ const hookRequest = message;
365710
+ const decision = await this.policyEngine.checkHook(hookRequest);
365711
+ const effectiveDecision = decision === PolicyDecision.ALLOW ? "allow" : "deny";
365712
+ this.emitMessage({
365713
+ type: MessageBusType.HOOK_POLICY_DECISION,
365714
+ eventName: hookRequest.eventName,
365715
+ hookSource: getHookSource(hookRequest.input),
365716
+ decision: effectiveDecision,
365717
+ reason: decision !== PolicyDecision.ALLOW ? "Hook execution denied by policy" : void 0
365718
+ });
365719
+ if (decision === PolicyDecision.ALLOW) {
365720
+ this.emitMessage(message);
365721
+ } else {
365722
+ this.emitMessage({
365723
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
365724
+ correlationId: hookRequest.correlationId,
365725
+ success: false,
365726
+ error: new Error("Hook execution denied by policy")
365727
+ });
365728
+ }
365033
365729
  } else {
365034
365730
  this.emitMessage(message);
365035
365731
  }
@@ -365043,6 +365739,32 @@ var MessageBus = class extends EventEmitter10 {
365043
365739
  unsubscribe(type, listener) {
365044
365740
  this.off(type, listener);
365045
365741
  }
365742
+ /**
365743
+ * Request-response pattern: Publish a message and wait for a correlated response
365744
+ * This enables synchronous-style communication over the async MessageBus
365745
+ * The correlation ID is generated internally and added to the request
365746
+ */
365747
+ async request(request3, responseType, timeoutMs = 6e4) {
365748
+ const correlationId = randomUUID6();
365749
+ return new Promise((resolve14, reject) => {
365750
+ const timeoutId = setTimeout(() => {
365751
+ cleanup();
365752
+ reject(new Error(`Request timed out waiting for ${responseType}`));
365753
+ }, timeoutMs);
365754
+ const cleanup = () => {
365755
+ clearTimeout(timeoutId);
365756
+ this.unsubscribe(responseType, responseHandler);
365757
+ };
365758
+ const responseHandler = (response) => {
365759
+ if ("correlationId" in response && response.correlationId === correlationId) {
365760
+ cleanup();
365761
+ resolve14(response);
365762
+ }
365763
+ };
365764
+ this.subscribe(responseType, responseHandler);
365765
+ this.publish({ ...request3, correlationId });
365766
+ });
365767
+ }
365046
365768
  };
365047
365769
 
365048
365770
  // packages/core/dist/src/policy/stable-stringify.js
@@ -365136,18 +365858,31 @@ function ruleMatches(rule, toolCall, stringifiedArgs, serverName) {
365136
365858
  }
365137
365859
  return true;
365138
365860
  }
365861
+ function hookCheckerMatches(rule, context2) {
365862
+ if (rule.eventName && rule.eventName !== context2.eventName) {
365863
+ return false;
365864
+ }
365865
+ if (rule.hookSource && rule.hookSource !== context2.hookSource) {
365866
+ return false;
365867
+ }
365868
+ return true;
365869
+ }
365139
365870
  var PolicyEngine = class {
365140
365871
  rules;
365141
365872
  checkers;
365873
+ hookCheckers;
365142
365874
  defaultDecision;
365143
365875
  nonInteractive;
365144
365876
  checkerRunner;
365877
+ allowHooks;
365145
365878
  constructor(config2 = {}, checkerRunner) {
365146
365879
  this.rules = (config2.rules ?? []).sort((a2, b) => (b.priority ?? 0) - (a2.priority ?? 0));
365147
365880
  this.checkers = (config2.checkers ?? []).sort((a2, b) => (b.priority ?? 0) - (a2.priority ?? 0));
365881
+ this.hookCheckers = (config2.hookCheckers ?? []).sort((a2, b) => (b.priority ?? 0) - (a2.priority ?? 0));
365148
365882
  this.defaultDecision = config2.defaultDecision ?? PolicyDecision.ASK_USER;
365149
365883
  this.nonInteractive = config2.nonInteractive ?? false;
365150
365884
  this.checkerRunner = checkerRunner;
365885
+ this.allowHooks = config2.allowHooks ?? true;
365151
365886
  }
365152
365887
  /**
365153
365888
  * Check if a tool call is allowed based on the configured policies.
@@ -365230,6 +365965,64 @@ var PolicyEngine = class {
365230
365965
  getCheckers() {
365231
365966
  return this.checkers;
365232
365967
  }
365968
+ /**
365969
+ * Add a new hook checker to the policy engine.
365970
+ */
365971
+ addHookChecker(checker) {
365972
+ this.hookCheckers.push(checker);
365973
+ this.hookCheckers.sort((a2, b) => (b.priority ?? 0) - (a2.priority ?? 0));
365974
+ }
365975
+ /**
365976
+ * Get all current hook checkers.
365977
+ */
365978
+ getHookCheckers() {
365979
+ return this.hookCheckers;
365980
+ }
365981
+ /**
365982
+ * Check if a hook execution is allowed based on the configured policies.
365983
+ * Runs hook-specific safety checkers if configured.
365984
+ */
365985
+ async checkHook(request3) {
365986
+ if (!this.allowHooks) {
365987
+ return PolicyDecision.DENY;
365988
+ }
365989
+ const context2 = "input" in request3 ? {
365990
+ eventName: request3.eventName,
365991
+ hookSource: getHookSource(request3.input),
365992
+ trustedFolder: typeof request3.input["trusted_folder"] === "boolean" ? request3.input["trusted_folder"] : void 0
365993
+ } : request3;
365994
+ if (context2.trustedFolder === false && context2.hookSource === "project") {
365995
+ return PolicyDecision.DENY;
365996
+ }
365997
+ if (this.checkerRunner && this.hookCheckers.length > 0) {
365998
+ for (const checkerRule of this.hookCheckers) {
365999
+ if (hookCheckerMatches(checkerRule, context2)) {
366000
+ debugLogger.debug(`[PolicyEngine.checkHook] Running hook checker: ${checkerRule.checker.name} for event: ${context2.eventName}`);
366001
+ try {
366002
+ const syntheticCall = {
366003
+ name: `hook:${context2.eventName}`,
366004
+ args: {
366005
+ hookSource: context2.hookSource,
366006
+ trustedFolder: context2.trustedFolder
366007
+ }
366008
+ };
366009
+ const result = await this.checkerRunner.runChecker(syntheticCall, checkerRule.checker);
366010
+ if (result.decision === SafetyCheckDecision.DENY) {
366011
+ debugLogger.debug(`[PolicyEngine.checkHook] Hook checker denied: ${result.reason}`);
366012
+ return PolicyDecision.DENY;
366013
+ } else if (result.decision === SafetyCheckDecision.ASK_USER) {
366014
+ debugLogger.debug(`[PolicyEngine.checkHook] Hook checker requested ASK_USER: ${result.reason}`);
366015
+ return this.applyNonInteractiveMode(PolicyDecision.ASK_USER);
366016
+ }
366017
+ } catch (error) {
366018
+ debugLogger.debug(`[PolicyEngine.checkHook] Hook checker failed: ${error}`);
366019
+ return PolicyDecision.DENY;
366020
+ }
366021
+ }
366022
+ }
366023
+ }
366024
+ return PolicyDecision.ALLOW;
366025
+ }
365233
366026
  applyNonInteractiveMode(decision) {
365234
366027
  if (this.nonInteractive && decision === PolicyDecision.ASK_USER) {
365235
366028
  return PolicyDecision.DENY;
@@ -365238,6 +366031,1205 @@ var PolicyEngine = class {
365238
366031
  }
365239
366032
  };
365240
366033
 
366034
+ // packages/core/dist/src/hooks/hookRegistry.js
366035
+ var HookRegistryNotInitializedError = class extends Error {
366036
+ constructor(message = "Hook registry not initialized") {
366037
+ super(message);
366038
+ this.name = "HookRegistryNotInitializedError";
366039
+ }
366040
+ };
366041
+ var ConfigSource;
366042
+ (function(ConfigSource2) {
366043
+ ConfigSource2["Project"] = "project";
366044
+ ConfigSource2["User"] = "user";
366045
+ ConfigSource2["System"] = "system";
366046
+ ConfigSource2["Extensions"] = "extensions";
366047
+ })(ConfigSource || (ConfigSource = {}));
366048
+ var HookRegistry = class {
366049
+ config;
366050
+ entries = [];
366051
+ initialized = false;
366052
+ constructor(config2) {
366053
+ this.config = config2;
366054
+ }
366055
+ /**
366056
+ * Initialize the registry by processing hooks from config
366057
+ */
366058
+ async initialize() {
366059
+ if (this.initialized) {
366060
+ return;
366061
+ }
366062
+ this.entries = [];
366063
+ this.processHooksFromConfig();
366064
+ this.initialized = true;
366065
+ debugLogger.log(`Hook registry initialized with ${this.entries.length} hook entries`);
366066
+ }
366067
+ /**
366068
+ * Get all hook entries for a specific event
366069
+ */
366070
+ getHooksForEvent(eventName) {
366071
+ if (!this.initialized) {
366072
+ throw new HookRegistryNotInitializedError();
366073
+ }
366074
+ return this.entries.filter((entry) => entry.eventName === eventName && entry.enabled).sort((a2, b) => this.getSourcePriority(a2.source) - this.getSourcePriority(b.source));
366075
+ }
366076
+ /**
366077
+ * Get all registered hooks
366078
+ */
366079
+ getAllHooks() {
366080
+ if (!this.initialized) {
366081
+ throw new HookRegistryNotInitializedError();
366082
+ }
366083
+ return [...this.entries];
366084
+ }
366085
+ /**
366086
+ * Enable or disable a specific hook
366087
+ */
366088
+ setHookEnabled(hookName, enabled) {
366089
+ const updated = this.entries.filter((entry) => {
366090
+ const name4 = this.getHookName(entry);
366091
+ if (name4 === hookName) {
366092
+ entry.enabled = enabled;
366093
+ return true;
366094
+ }
366095
+ return false;
366096
+ });
366097
+ if (updated.length > 0) {
366098
+ debugLogger.log(`${enabled ? "Enabled" : "Disabled"} ${updated.length} hook(s) matching "${hookName}"`);
366099
+ } else {
366100
+ debugLogger.warn(`No hooks found matching "${hookName}"`);
366101
+ }
366102
+ }
366103
+ /**
366104
+ * Get hook name for display purposes
366105
+ */
366106
+ getHookName(entry) {
366107
+ return entry.config.command || "unknown-command";
366108
+ }
366109
+ /**
366110
+ * Process hooks from the config that was already loaded by the CLI
366111
+ */
366112
+ processHooksFromConfig() {
366113
+ const configHooks = this.config.getHooks();
366114
+ if (configHooks) {
366115
+ this.processHooksConfiguration(configHooks, ConfigSource.Project);
366116
+ }
366117
+ const extensions = this.config.getExtensions() || [];
366118
+ for (const extension of extensions) {
366119
+ if (extension.isActive && extension.hooks) {
366120
+ this.processHooksConfiguration(extension.hooks, ConfigSource.Extensions);
366121
+ }
366122
+ }
366123
+ }
366124
+ /**
366125
+ * Process hooks configuration and add entries
366126
+ */
366127
+ processHooksConfiguration(hooksConfig, source) {
366128
+ for (const [eventName, definitions] of Object.entries(hooksConfig)) {
366129
+ if (!this.isValidEventName(eventName)) {
366130
+ debugLogger.warn(`Invalid hook event name: ${eventName}`);
366131
+ continue;
366132
+ }
366133
+ const typedEventName = eventName;
366134
+ if (!Array.isArray(definitions)) {
366135
+ debugLogger.warn(`Hook definitions for event "${eventName}" from source "${source}" is not an array. Skipping.`);
366136
+ continue;
366137
+ }
366138
+ for (const definition of definitions) {
366139
+ this.processHookDefinition(definition, typedEventName, source);
366140
+ }
366141
+ }
366142
+ }
366143
+ /**
366144
+ * Process a single hook definition
366145
+ */
366146
+ processHookDefinition(definition, eventName, source) {
366147
+ if (!definition || typeof definition !== "object" || !Array.isArray(definition.hooks)) {
366148
+ debugLogger.warn(`Discarding invalid hook definition for ${eventName} from ${source}:`, definition);
366149
+ return;
366150
+ }
366151
+ for (const hookConfig of definition.hooks) {
366152
+ if (hookConfig && typeof hookConfig === "object" && this.validateHookConfig(hookConfig, eventName, source)) {
366153
+ this.entries.push({
366154
+ config: hookConfig,
366155
+ source,
366156
+ eventName,
366157
+ matcher: definition.matcher,
366158
+ sequential: definition.sequential,
366159
+ enabled: true
366160
+ });
366161
+ } else {
366162
+ debugLogger.warn(`Discarding invalid hook configuration for ${eventName} from ${source}:`, hookConfig);
366163
+ }
366164
+ }
366165
+ }
366166
+ /**
366167
+ * Validate a hook configuration
366168
+ */
366169
+ validateHookConfig(config2, eventName, source) {
366170
+ if (!config2.type || !["command", "plugin"].includes(config2.type)) {
366171
+ debugLogger.warn(`Invalid hook ${eventName} from ${source} type: ${config2.type}`);
366172
+ return false;
366173
+ }
366174
+ if (config2.type === "command" && !config2.command) {
366175
+ debugLogger.warn(`Command hook ${eventName} from ${source} missing command field`);
366176
+ return false;
366177
+ }
366178
+ return true;
366179
+ }
366180
+ /**
366181
+ * Check if an event name is valid
366182
+ */
366183
+ isValidEventName(eventName) {
366184
+ const validEventNames = Object.values(HookEventName);
366185
+ return validEventNames.includes(eventName);
366186
+ }
366187
+ /**
366188
+ * Get source priority (lower number = higher priority)
366189
+ */
366190
+ getSourcePriority(source) {
366191
+ switch (source) {
366192
+ case ConfigSource.Project:
366193
+ return 1;
366194
+ case ConfigSource.User:
366195
+ return 2;
366196
+ case ConfigSource.System:
366197
+ return 3;
366198
+ case ConfigSource.Extensions:
366199
+ return 4;
366200
+ default:
366201
+ return 999;
366202
+ }
366203
+ }
366204
+ };
366205
+
366206
+ // packages/core/dist/src/hooks/hookRunner.js
366207
+ import { spawn as spawn9 } from "node:child_process";
366208
+ var DEFAULT_HOOK_TIMEOUT = 6e4;
366209
+ var EXIT_CODE_SUCCESS = 0;
366210
+ var EXIT_CODE_BLOCKING_ERROR = 2;
366211
+ var EXIT_CODE_NON_BLOCKING_ERROR = 1;
366212
+ var HookRunner = class {
366213
+ constructor() {
366214
+ }
366215
+ /**
366216
+ * Execute a single hook
366217
+ */
366218
+ async executeHook(hookConfig, eventName, input) {
366219
+ const startTime = Date.now();
366220
+ try {
366221
+ return await this.executeCommandHook(hookConfig, eventName, input, startTime);
366222
+ } catch (error) {
366223
+ const duration = Date.now() - startTime;
366224
+ const hookSource = hookConfig.command || "unknown";
366225
+ const errorMessage = `Hook execution failed for event '${eventName}' (source: ${hookSource}): ${error}`;
366226
+ debugLogger.warn(`Hook execution error (non-fatal): ${errorMessage}`);
366227
+ return {
366228
+ hookConfig,
366229
+ eventName,
366230
+ success: false,
366231
+ error: error instanceof Error ? error : new Error(errorMessage),
366232
+ duration
366233
+ };
366234
+ }
366235
+ }
366236
+ /**
366237
+ * Execute multiple hooks in parallel
366238
+ */
366239
+ async executeHooksParallel(hookConfigs, eventName, input) {
366240
+ const promises3 = hookConfigs.map((config2) => this.executeHook(config2, eventName, input));
366241
+ return await Promise.all(promises3);
366242
+ }
366243
+ /**
366244
+ * Execute multiple hooks sequentially
366245
+ */
366246
+ async executeHooksSequential(hookConfigs, eventName, input) {
366247
+ const results = [];
366248
+ let currentInput = input;
366249
+ for (const config2 of hookConfigs) {
366250
+ const result = await this.executeHook(config2, eventName, currentInput);
366251
+ results.push(result);
366252
+ if (result.success && result.output) {
366253
+ currentInput = this.applyHookOutputToInput(currentInput, result.output, eventName);
366254
+ }
366255
+ }
366256
+ return results;
366257
+ }
366258
+ /**
366259
+ * Apply hook output to modify input for the next hook in sequential execution
366260
+ */
366261
+ applyHookOutputToInput(originalInput, hookOutput, eventName) {
366262
+ const modifiedInput = { ...originalInput };
366263
+ if (hookOutput.hookSpecificOutput) {
366264
+ switch (eventName) {
366265
+ case HookEventName.BeforeAgent:
366266
+ if ("additionalContext" in hookOutput.hookSpecificOutput) {
366267
+ const additionalContext = hookOutput.hookSpecificOutput["additionalContext"];
366268
+ if (typeof additionalContext === "string" && "prompt" in modifiedInput) {
366269
+ modifiedInput.prompt += "\n\n" + additionalContext;
366270
+ }
366271
+ }
366272
+ break;
366273
+ case HookEventName.BeforeModel:
366274
+ if ("llm_request" in hookOutput.hookSpecificOutput) {
366275
+ const hookBeforeModelOutput = hookOutput;
366276
+ if (hookBeforeModelOutput.hookSpecificOutput?.llm_request && "llm_request" in modifiedInput) {
366277
+ const currentRequest = modifiedInput.llm_request;
366278
+ const partialRequest = hookBeforeModelOutput.hookSpecificOutput.llm_request;
366279
+ modifiedInput.llm_request = {
366280
+ ...currentRequest,
366281
+ ...partialRequest
366282
+ };
366283
+ }
366284
+ }
366285
+ break;
366286
+ default:
366287
+ break;
366288
+ }
366289
+ }
366290
+ return modifiedInput;
366291
+ }
366292
+ /**
366293
+ * Execute a command hook
366294
+ */
366295
+ async executeCommandHook(hookConfig, eventName, input, startTime) {
366296
+ const timeout = hookConfig.timeout ?? DEFAULT_HOOK_TIMEOUT;
366297
+ return new Promise((resolve14) => {
366298
+ if (!hookConfig.command) {
366299
+ const errorMessage = "Command hook missing command";
366300
+ debugLogger.warn(`Hook configuration error (non-fatal): ${errorMessage}`);
366301
+ resolve14({
366302
+ hookConfig,
366303
+ eventName,
366304
+ success: false,
366305
+ error: new Error(errorMessage),
366306
+ duration: Date.now() - startTime
366307
+ });
366308
+ return;
366309
+ }
366310
+ let stdout = "";
366311
+ let stderr = "";
366312
+ let timedOut2 = false;
366313
+ const command = this.expandCommand(hookConfig.command, input);
366314
+ const env2 = {
366315
+ ...process.env,
366316
+ GEMINI_PROJECT_DIR: input.cwd,
366317
+ CLAUDE_PROJECT_DIR: input.cwd
366318
+ // For compatibility
366319
+ };
366320
+ const child = spawn9(command, {
366321
+ env: env2,
366322
+ cwd: input.cwd,
366323
+ stdio: ["pipe", "pipe", "pipe"],
366324
+ shell: true
366325
+ });
366326
+ const timeoutHandle = setTimeout(() => {
366327
+ timedOut2 = true;
366328
+ child.kill("SIGTERM");
366329
+ setTimeout(() => {
366330
+ if (!child.killed) {
366331
+ child.kill("SIGKILL");
366332
+ }
366333
+ }, 5e3);
366334
+ }, timeout);
366335
+ if (child.stdin) {
366336
+ child.stdin.write(JSON.stringify(input));
366337
+ child.stdin.end();
366338
+ }
366339
+ child.stdout?.on("data", (data) => {
366340
+ stdout += data.toString();
366341
+ });
366342
+ child.stderr?.on("data", (data) => {
366343
+ stderr += data.toString();
366344
+ });
366345
+ child.on("close", (exitCode) => {
366346
+ clearTimeout(timeoutHandle);
366347
+ const duration = Date.now() - startTime;
366348
+ if (timedOut2) {
366349
+ resolve14({
366350
+ hookConfig,
366351
+ eventName,
366352
+ success: false,
366353
+ error: new Error(`Hook timed out after ${timeout}ms`),
366354
+ stdout,
366355
+ stderr,
366356
+ duration
366357
+ });
366358
+ return;
366359
+ }
366360
+ let output;
366361
+ if (exitCode === EXIT_CODE_SUCCESS && stdout.trim()) {
366362
+ try {
366363
+ let parsed = JSON.parse(stdout.trim());
366364
+ if (typeof parsed === "string") {
366365
+ parsed = JSON.parse(parsed);
366366
+ }
366367
+ if (parsed) {
366368
+ output = parsed;
366369
+ }
366370
+ } catch {
366371
+ output = this.convertPlainTextToHookOutput(stdout.trim(), exitCode);
366372
+ }
366373
+ } else if (exitCode !== EXIT_CODE_SUCCESS && stderr.trim()) {
366374
+ output = this.convertPlainTextToHookOutput(stderr.trim(), exitCode || EXIT_CODE_NON_BLOCKING_ERROR);
366375
+ }
366376
+ resolve14({
366377
+ hookConfig,
366378
+ eventName,
366379
+ success: exitCode === EXIT_CODE_SUCCESS,
366380
+ output,
366381
+ stdout,
366382
+ stderr,
366383
+ exitCode: exitCode || EXIT_CODE_SUCCESS,
366384
+ duration
366385
+ });
366386
+ });
366387
+ child.on("error", (error) => {
366388
+ clearTimeout(timeoutHandle);
366389
+ const duration = Date.now() - startTime;
366390
+ resolve14({
366391
+ hookConfig,
366392
+ eventName,
366393
+ success: false,
366394
+ error,
366395
+ stdout,
366396
+ stderr,
366397
+ duration
366398
+ });
366399
+ });
366400
+ });
366401
+ }
366402
+ /**
366403
+ * Expand command with environment variables and input context
366404
+ */
366405
+ expandCommand(command, input) {
366406
+ return command.replace(/\$GEMINI_PROJECT_DIR/g, input.cwd).replace(/\$CLAUDE_PROJECT_DIR/g, input.cwd);
366407
+ }
366408
+ /**
366409
+ * Convert plain text output to structured HookOutput
366410
+ */
366411
+ convertPlainTextToHookOutput(text, exitCode) {
366412
+ if (exitCode === EXIT_CODE_SUCCESS) {
366413
+ return {
366414
+ decision: "allow",
366415
+ systemMessage: text
366416
+ };
366417
+ } else if (exitCode === EXIT_CODE_BLOCKING_ERROR) {
366418
+ return {
366419
+ decision: "deny",
366420
+ reason: text
366421
+ };
366422
+ } else {
366423
+ return {
366424
+ decision: "allow",
366425
+ systemMessage: `Warning: ${text}`
366426
+ };
366427
+ }
366428
+ }
366429
+ };
366430
+
366431
+ // packages/core/dist/src/hooks/hookAggregator.js
366432
+ var HookAggregator = class {
366433
+ /**
366434
+ * Aggregate results from multiple hook executions
366435
+ */
366436
+ aggregateResults(results, eventName) {
366437
+ const allOutputs = [];
366438
+ const errors = [];
366439
+ let totalDuration = 0;
366440
+ for (const result of results) {
366441
+ totalDuration += result.duration;
366442
+ if (result.error) {
366443
+ errors.push(result.error);
366444
+ }
366445
+ if (result.output) {
366446
+ allOutputs.push(result.output);
366447
+ }
366448
+ }
366449
+ const mergedOutput = this.mergeOutputs(allOutputs, eventName);
366450
+ const finalOutput = mergedOutput ? this.createSpecificHookOutput(mergedOutput, eventName) : void 0;
366451
+ return {
366452
+ success: errors.length === 0,
366453
+ finalOutput,
366454
+ allOutputs,
366455
+ errors,
366456
+ totalDuration
366457
+ };
366458
+ }
366459
+ /**
366460
+ * Merge hook outputs using event-specific strategies
366461
+ *
366462
+ * Note: We always use the merge logic even for single hooks to ensure
366463
+ * consistent default behaviors (e.g., default decision='allow' for OR logic)
366464
+ */
366465
+ mergeOutputs(outputs, eventName) {
366466
+ if (outputs.length === 0) {
366467
+ return void 0;
366468
+ }
366469
+ switch (eventName) {
366470
+ case HookEventName.BeforeTool:
366471
+ case HookEventName.AfterTool:
366472
+ case HookEventName.BeforeAgent:
366473
+ case HookEventName.AfterAgent:
366474
+ case HookEventName.SessionStart:
366475
+ return this.mergeWithOrDecision(outputs);
366476
+ case HookEventName.BeforeModel:
366477
+ case HookEventName.AfterModel:
366478
+ return this.mergeWithFieldReplacement(outputs);
366479
+ case HookEventName.BeforeToolSelection:
366480
+ return this.mergeToolSelectionOutputs(outputs);
366481
+ default:
366482
+ return this.mergeSimple(outputs);
366483
+ }
366484
+ }
366485
+ /**
366486
+ * Merge outputs with OR decision logic and message concatenation
366487
+ */
366488
+ mergeWithOrDecision(outputs) {
366489
+ const merged = {
366490
+ continue: true,
366491
+ suppressOutput: false
366492
+ };
366493
+ const messages = [];
366494
+ const reasons = [];
366495
+ const systemMessages = [];
366496
+ const additionalContexts = [];
366497
+ let hasBlockDecision = false;
366498
+ let hasContinueFalse = false;
366499
+ for (const output of outputs) {
366500
+ if (output.continue === false) {
366501
+ hasContinueFalse = true;
366502
+ merged.continue = false;
366503
+ if (output.stopReason) {
366504
+ messages.push(output.stopReason);
366505
+ }
366506
+ }
366507
+ const tempOutput = new DefaultHookOutput(output);
366508
+ if (tempOutput.isBlockingDecision()) {
366509
+ hasBlockDecision = true;
366510
+ merged.decision = output.decision;
366511
+ }
366512
+ if (output.reason) {
366513
+ reasons.push(output.reason);
366514
+ }
366515
+ if (output.systemMessage) {
366516
+ systemMessages.push(output.systemMessage);
366517
+ }
366518
+ if (output.suppressOutput) {
366519
+ merged.suppressOutput = true;
366520
+ }
366521
+ this.extractAdditionalContext(output, additionalContexts);
366522
+ }
366523
+ if (!hasBlockDecision && !hasContinueFalse) {
366524
+ merged.decision = "allow";
366525
+ }
366526
+ if (messages.length > 0) {
366527
+ merged.stopReason = messages.join("\n");
366528
+ }
366529
+ if (reasons.length > 0) {
366530
+ merged.reason = reasons.join("\n");
366531
+ }
366532
+ if (systemMessages.length > 0) {
366533
+ merged.systemMessage = systemMessages.join("\n");
366534
+ }
366535
+ if (additionalContexts.length > 0) {
366536
+ merged.hookSpecificOutput = {
366537
+ ...merged.hookSpecificOutput || {},
366538
+ additionalContext: additionalContexts.join("\n")
366539
+ };
366540
+ }
366541
+ return merged;
366542
+ }
366543
+ /**
366544
+ * Merge outputs with later fields replacing earlier fields
366545
+ */
366546
+ mergeWithFieldReplacement(outputs) {
366547
+ let merged = {};
366548
+ for (const output of outputs) {
366549
+ merged = {
366550
+ ...merged,
366551
+ ...output,
366552
+ hookSpecificOutput: {
366553
+ ...merged.hookSpecificOutput,
366554
+ ...output.hookSpecificOutput
366555
+ }
366556
+ };
366557
+ }
366558
+ return merged;
366559
+ }
366560
+ /**
366561
+ * Merge tool selection outputs with specific logic for tool config
366562
+ *
366563
+ * Tool Selection Strategy:
366564
+ * - The intent is to provide a UNION of tools from all hooks
366565
+ * - If any hook specifies NONE mode, no tools are available (most restrictive wins)
366566
+ * - If any hook specifies ANY mode (and no NONE), ANY mode is used
366567
+ * - Otherwise AUTO mode is used
366568
+ * - Function names are collected from all hooks and sorted for deterministic caching
366569
+ *
366570
+ * This means hooks can only add/enable tools, not filter them out individually.
366571
+ * If one hook restricts and another re-enables, the union takes the re-enabled tool.
366572
+ */
366573
+ mergeToolSelectionOutputs(outputs) {
366574
+ const merged = {};
366575
+ const allFunctionNames = /* @__PURE__ */ new Set();
366576
+ let hasNoneMode = false;
366577
+ let hasAnyMode = false;
366578
+ for (const output of outputs) {
366579
+ const toolConfig = output.hookSpecificOutput?.toolConfig;
366580
+ if (!toolConfig) {
366581
+ continue;
366582
+ }
366583
+ if (toolConfig.mode === "NONE") {
366584
+ hasNoneMode = true;
366585
+ } else if (toolConfig.mode === "ANY") {
366586
+ hasAnyMode = true;
366587
+ }
366588
+ if (toolConfig.allowedFunctionNames) {
366589
+ for (const name4 of toolConfig.allowedFunctionNames) {
366590
+ allFunctionNames.add(name4);
366591
+ }
366592
+ }
366593
+ }
366594
+ let finalMode;
366595
+ let finalFunctionNames = [];
366596
+ if (hasNoneMode) {
366597
+ finalMode = FunctionCallingConfigMode.NONE;
366598
+ finalFunctionNames = [];
366599
+ } else if (hasAnyMode) {
366600
+ finalMode = FunctionCallingConfigMode.ANY;
366601
+ finalFunctionNames = Array.from(allFunctionNames).sort();
366602
+ } else {
366603
+ finalMode = FunctionCallingConfigMode.AUTO;
366604
+ finalFunctionNames = Array.from(allFunctionNames).sort();
366605
+ }
366606
+ merged.hookSpecificOutput = {
366607
+ hookEventName: "BeforeToolSelection",
366608
+ toolConfig: {
366609
+ mode: finalMode,
366610
+ allowedFunctionNames: finalFunctionNames
366611
+ }
366612
+ };
366613
+ return merged;
366614
+ }
366615
+ /**
366616
+ * Simple merge for events without special logic
366617
+ */
366618
+ mergeSimple(outputs) {
366619
+ let merged = {};
366620
+ for (const output of outputs) {
366621
+ merged = { ...merged, ...output };
366622
+ }
366623
+ return merged;
366624
+ }
366625
+ /**
366626
+ * Create the appropriate specific hook output class based on event type
366627
+ */
366628
+ createSpecificHookOutput(output, eventName) {
366629
+ switch (eventName) {
366630
+ case HookEventName.BeforeTool:
366631
+ return new BeforeToolHookOutput(output);
366632
+ case HookEventName.BeforeModel:
366633
+ return new BeforeModelHookOutput(output);
366634
+ case HookEventName.BeforeToolSelection:
366635
+ return new BeforeToolSelectionHookOutput(output);
366636
+ case HookEventName.AfterModel:
366637
+ return new AfterModelHookOutput(output);
366638
+ default:
366639
+ return new DefaultHookOutput(output);
366640
+ }
366641
+ }
366642
+ /**
366643
+ * Extract additional context from hook-specific outputs
366644
+ */
366645
+ extractAdditionalContext(output, contexts) {
366646
+ const specific = output.hookSpecificOutput;
366647
+ if (!specific) {
366648
+ return;
366649
+ }
366650
+ if ("additionalContext" in specific && typeof specific["additionalContext"] === "string") {
366651
+ contexts.push(specific["additionalContext"]);
366652
+ }
366653
+ }
366654
+ };
366655
+
366656
+ // packages/core/dist/src/hooks/hookPlanner.js
366657
+ var HookPlanner = class {
366658
+ hookRegistry;
366659
+ constructor(hookRegistry) {
366660
+ this.hookRegistry = hookRegistry;
366661
+ }
366662
+ /**
366663
+ * Create execution plan for a hook event
366664
+ */
366665
+ createExecutionPlan(eventName, context2) {
366666
+ const hookEntries = this.hookRegistry.getHooksForEvent(eventName);
366667
+ if (hookEntries.length === 0) {
366668
+ return null;
366669
+ }
366670
+ const matchingEntries = hookEntries.filter((entry) => this.matchesContext(entry, context2));
366671
+ if (matchingEntries.length === 0) {
366672
+ return null;
366673
+ }
366674
+ const deduplicatedEntries = this.deduplicateHooks(matchingEntries);
366675
+ const hookConfigs = deduplicatedEntries.map((entry) => entry.config);
366676
+ const sequential = deduplicatedEntries.some((entry) => entry.sequential === true);
366677
+ const plan = {
366678
+ eventName,
366679
+ hookConfigs,
366680
+ sequential
366681
+ };
366682
+ debugLogger.debug(`Created execution plan for ${eventName}: ${hookConfigs.length} hook(s) to execute ${sequential ? "sequentially" : "in parallel"}`);
366683
+ return plan;
366684
+ }
366685
+ /**
366686
+ * Check if a hook entry matches the given context
366687
+ */
366688
+ matchesContext(entry, context2) {
366689
+ if (!entry.matcher || !context2) {
366690
+ return true;
366691
+ }
366692
+ const matcher = entry.matcher.trim();
366693
+ if (matcher === "" || matcher === "*") {
366694
+ return true;
366695
+ }
366696
+ if (context2.toolName) {
366697
+ return this.matchesToolName(matcher, context2.toolName);
366698
+ }
366699
+ if (context2.trigger) {
366700
+ return this.matchesTrigger(matcher, context2.trigger);
366701
+ }
366702
+ return true;
366703
+ }
366704
+ /**
366705
+ * Match tool name against matcher pattern
366706
+ */
366707
+ matchesToolName(matcher, toolName) {
366708
+ try {
366709
+ const regex2 = new RegExp(matcher);
366710
+ return regex2.test(toolName);
366711
+ } catch {
366712
+ return matcher === toolName;
366713
+ }
366714
+ }
366715
+ /**
366716
+ * Match trigger/source against matcher pattern
366717
+ */
366718
+ matchesTrigger(matcher, trigger) {
366719
+ return matcher === trigger;
366720
+ }
366721
+ /**
366722
+ * Deduplicate identical hook configurations
366723
+ */
366724
+ deduplicateHooks(entries2) {
366725
+ const seen = /* @__PURE__ */ new Set();
366726
+ const deduplicated = [];
366727
+ for (const entry of entries2) {
366728
+ const key = this.getHookKey(entry);
366729
+ if (!seen.has(key)) {
366730
+ seen.add(key);
366731
+ deduplicated.push(entry);
366732
+ } else {
366733
+ debugLogger.debug(`Deduplicated hook: ${key}`);
366734
+ }
366735
+ }
366736
+ return deduplicated;
366737
+ }
366738
+ /**
366739
+ * Generate a unique key for a hook entry
366740
+ */
366741
+ getHookKey(entry) {
366742
+ return `command:${entry.config.command}`;
366743
+ }
366744
+ };
366745
+
366746
+ // packages/core/dist/src/hooks/hookEventHandler.js
366747
+ function isObject3(value) {
366748
+ return typeof value === "object" && value !== null;
366749
+ }
366750
+ function validateBeforeToolInput(input) {
366751
+ const toolName = input["tool_name"];
366752
+ const toolInput = input["tool_input"];
366753
+ if (typeof toolName !== "string") {
366754
+ throw new Error("Invalid input for BeforeTool hook event: tool_name must be a string");
366755
+ }
366756
+ if (!isObject3(toolInput)) {
366757
+ throw new Error("Invalid input for BeforeTool hook event: tool_input must be an object");
366758
+ }
366759
+ return { toolName, toolInput };
366760
+ }
366761
+ function validateAfterToolInput(input) {
366762
+ const toolName = input["tool_name"];
366763
+ const toolInput = input["tool_input"];
366764
+ const toolResponse = input["tool_response"];
366765
+ if (typeof toolName !== "string") {
366766
+ throw new Error("Invalid input for AfterTool hook event: tool_name must be a string");
366767
+ }
366768
+ if (!isObject3(toolInput)) {
366769
+ throw new Error("Invalid input for AfterTool hook event: tool_input must be an object");
366770
+ }
366771
+ if (!isObject3(toolResponse)) {
366772
+ throw new Error("Invalid input for AfterTool hook event: tool_response must be an object");
366773
+ }
366774
+ return { toolName, toolInput, toolResponse };
366775
+ }
366776
+ function validateBeforeAgentInput(input) {
366777
+ const prompt = input["prompt"];
366778
+ if (typeof prompt !== "string") {
366779
+ throw new Error("Invalid input for BeforeAgent hook event: prompt must be a string");
366780
+ }
366781
+ return { prompt };
366782
+ }
366783
+ function validateAfterAgentInput(input) {
366784
+ const prompt = input["prompt"];
366785
+ const promptResponse = input["prompt_response"];
366786
+ const stopHookActive = input["stop_hook_active"];
366787
+ if (typeof prompt !== "string") {
366788
+ throw new Error("Invalid input for AfterAgent hook event: prompt must be a string");
366789
+ }
366790
+ if (typeof promptResponse !== "string") {
366791
+ throw new Error("Invalid input for AfterAgent hook event: prompt_response must be a string");
366792
+ }
366793
+ return {
366794
+ prompt,
366795
+ promptResponse,
366796
+ stopHookActive: typeof stopHookActive === "boolean" ? stopHookActive : false
366797
+ };
366798
+ }
366799
+ function validateModelInput(input, eventName) {
366800
+ const llmRequest = input["llm_request"];
366801
+ if (!isObject3(llmRequest)) {
366802
+ throw new Error(`Invalid input for ${eventName} hook event: llm_request must be an object`);
366803
+ }
366804
+ return { llmRequest };
366805
+ }
366806
+ function validateAfterModelInput(input) {
366807
+ const llmRequest = input["llm_request"];
366808
+ const llmResponse = input["llm_response"];
366809
+ if (!isObject3(llmRequest)) {
366810
+ throw new Error("Invalid input for AfterModel hook event: llm_request must be an object");
366811
+ }
366812
+ if (!isObject3(llmResponse)) {
366813
+ throw new Error("Invalid input for AfterModel hook event: llm_response must be an object");
366814
+ }
366815
+ return {
366816
+ llmRequest,
366817
+ llmResponse
366818
+ };
366819
+ }
366820
+ function validateNotificationInput(input) {
366821
+ const notificationType = input["notification_type"];
366822
+ const message = input["message"];
366823
+ const details = input["details"];
366824
+ if (typeof notificationType !== "string") {
366825
+ throw new Error("Invalid input for Notification hook event: notification_type must be a string");
366826
+ }
366827
+ if (typeof message !== "string") {
366828
+ throw new Error("Invalid input for Notification hook event: message must be a string");
366829
+ }
366830
+ if (!isObject3(details)) {
366831
+ throw new Error("Invalid input for Notification hook event: details must be an object");
366832
+ }
366833
+ return {
366834
+ notificationType,
366835
+ message,
366836
+ details
366837
+ };
366838
+ }
366839
+ var HookEventHandler = class {
366840
+ config;
366841
+ hookPlanner;
366842
+ hookRunner;
366843
+ hookAggregator;
366844
+ messageBus;
366845
+ constructor(config2, logger6, hookPlanner, hookRunner, hookAggregator, messageBus) {
366846
+ this.config = config2;
366847
+ this.hookPlanner = hookPlanner;
366848
+ this.hookRunner = hookRunner;
366849
+ this.hookAggregator = hookAggregator;
366850
+ this.messageBus = messageBus;
366851
+ if (this.messageBus) {
366852
+ this.messageBus.subscribe(MessageBusType.HOOK_EXECUTION_REQUEST, (request3) => this.handleHookExecutionRequest(request3));
366853
+ }
366854
+ }
366855
+ /**
366856
+ * Fire a BeforeTool event
366857
+ * Called by handleHookExecutionRequest - executes hooks directly
366858
+ */
366859
+ async fireBeforeToolEvent(toolName, toolInput) {
366860
+ const input = {
366861
+ ...this.createBaseInput(HookEventName.BeforeTool),
366862
+ tool_name: toolName,
366863
+ tool_input: toolInput
366864
+ };
366865
+ const context2 = { toolName };
366866
+ return await this.executeHooks(HookEventName.BeforeTool, input, context2);
366867
+ }
366868
+ /**
366869
+ * Fire an AfterTool event
366870
+ * Called by handleHookExecutionRequest - executes hooks directly
366871
+ */
366872
+ async fireAfterToolEvent(toolName, toolInput, toolResponse) {
366873
+ const input = {
366874
+ ...this.createBaseInput(HookEventName.AfterTool),
366875
+ tool_name: toolName,
366876
+ tool_input: toolInput,
366877
+ tool_response: toolResponse
366878
+ };
366879
+ const context2 = { toolName };
366880
+ return await this.executeHooks(HookEventName.AfterTool, input, context2);
366881
+ }
366882
+ /**
366883
+ * Fire a BeforeAgent event
366884
+ * Called by handleHookExecutionRequest - executes hooks directly
366885
+ */
366886
+ async fireBeforeAgentEvent(prompt) {
366887
+ const input = {
366888
+ ...this.createBaseInput(HookEventName.BeforeAgent),
366889
+ prompt
366890
+ };
366891
+ return await this.executeHooks(HookEventName.BeforeAgent, input);
366892
+ }
366893
+ /**
366894
+ * Fire a Notification event
366895
+ */
366896
+ async fireNotificationEvent(type, message, details) {
366897
+ const input = {
366898
+ ...this.createBaseInput(HookEventName.Notification),
366899
+ notification_type: type,
366900
+ message,
366901
+ details
366902
+ };
366903
+ return await this.executeHooks(HookEventName.Notification, input);
366904
+ }
366905
+ /**
366906
+ * Fire an AfterAgent event
366907
+ * Called by handleHookExecutionRequest - executes hooks directly
366908
+ */
366909
+ async fireAfterAgentEvent(prompt, promptResponse, stopHookActive = false) {
366910
+ const input = {
366911
+ ...this.createBaseInput(HookEventName.AfterAgent),
366912
+ prompt,
366913
+ prompt_response: promptResponse,
366914
+ stop_hook_active: stopHookActive
366915
+ };
366916
+ return await this.executeHooks(HookEventName.AfterAgent, input);
366917
+ }
366918
+ /**
366919
+ * Fire a SessionStart event
366920
+ */
366921
+ async fireSessionStartEvent(source) {
366922
+ const input = {
366923
+ ...this.createBaseInput(HookEventName.SessionStart),
366924
+ source
366925
+ };
366926
+ const context2 = { trigger: source };
366927
+ return await this.executeHooks(HookEventName.SessionStart, input, context2);
366928
+ }
366929
+ /**
366930
+ * Fire a SessionEnd event
366931
+ */
366932
+ async fireSessionEndEvent(reason) {
366933
+ const input = {
366934
+ ...this.createBaseInput(HookEventName.SessionEnd),
366935
+ reason
366936
+ };
366937
+ const context2 = { trigger: reason };
366938
+ return await this.executeHooks(HookEventName.SessionEnd, input, context2);
366939
+ }
366940
+ /**
366941
+ * Fire a PreCompress event
366942
+ */
366943
+ async firePreCompressEvent(trigger) {
366944
+ const input = {
366945
+ ...this.createBaseInput(HookEventName.PreCompress),
366946
+ trigger
366947
+ };
366948
+ const context2 = { trigger };
366949
+ return await this.executeHooks(HookEventName.PreCompress, input, context2);
366950
+ }
366951
+ /**
366952
+ * Fire a BeforeModel event
366953
+ * Called by handleHookExecutionRequest - executes hooks directly
366954
+ */
366955
+ async fireBeforeModelEvent(llmRequest) {
366956
+ const input = {
366957
+ ...this.createBaseInput(HookEventName.BeforeModel),
366958
+ llm_request: defaultHookTranslator.toHookLLMRequest(llmRequest)
366959
+ };
366960
+ return await this.executeHooks(HookEventName.BeforeModel, input);
366961
+ }
366962
+ /**
366963
+ * Fire an AfterModel event
366964
+ * Called by handleHookExecutionRequest - executes hooks directly
366965
+ */
366966
+ async fireAfterModelEvent(llmRequest, llmResponse) {
366967
+ const input = {
366968
+ ...this.createBaseInput(HookEventName.AfterModel),
366969
+ llm_request: defaultHookTranslator.toHookLLMRequest(llmRequest),
366970
+ llm_response: defaultHookTranslator.toHookLLMResponse(llmResponse)
366971
+ };
366972
+ return await this.executeHooks(HookEventName.AfterModel, input);
366973
+ }
366974
+ /**
366975
+ * Fire a BeforeToolSelection event
366976
+ * Called by handleHookExecutionRequest - executes hooks directly
366977
+ */
366978
+ async fireBeforeToolSelectionEvent(llmRequest) {
366979
+ const input = {
366980
+ ...this.createBaseInput(HookEventName.BeforeToolSelection),
366981
+ llm_request: defaultHookTranslator.toHookLLMRequest(llmRequest)
366982
+ };
366983
+ return await this.executeHooks(HookEventName.BeforeToolSelection, input);
366984
+ }
366985
+ /**
366986
+ * Execute hooks for a specific event (direct execution without MessageBus)
366987
+ * Used as fallback when MessageBus is not available
366988
+ */
366989
+ async executeHooks(eventName, input, context2) {
366990
+ try {
366991
+ const plan = this.hookPlanner.createExecutionPlan(eventName, context2);
366992
+ if (!plan || plan.hookConfigs.length === 0) {
366993
+ return {
366994
+ success: true,
366995
+ allOutputs: [],
366996
+ errors: [],
366997
+ totalDuration: 0
366998
+ };
366999
+ }
367000
+ const results = plan.sequential ? await this.hookRunner.executeHooksSequential(plan.hookConfigs, eventName, input) : await this.hookRunner.executeHooksParallel(plan.hookConfigs, eventName, input);
367001
+ const aggregated = this.hookAggregator.aggregateResults(results, eventName);
367002
+ this.processCommonHookOutputFields(aggregated);
367003
+ this.logHookExecution(eventName, input, results, aggregated);
367004
+ return aggregated;
367005
+ } catch (error) {
367006
+ debugLogger.error(`Hook event bus error for ${eventName}: ${error}`);
367007
+ return {
367008
+ success: false,
367009
+ allOutputs: [],
367010
+ errors: [error instanceof Error ? error : new Error(String(error))],
367011
+ totalDuration: 0
367012
+ };
367013
+ }
367014
+ }
367015
+ /**
367016
+ * Create base hook input with common fields
367017
+ */
367018
+ createBaseInput(eventName) {
367019
+ return {
367020
+ session_id: this.config.getSessionId(),
367021
+ transcript_path: "",
367022
+ // TODO: Implement transcript path when supported
367023
+ cwd: this.config.getWorkingDir(),
367024
+ hook_event_name: eventName,
367025
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
367026
+ };
367027
+ }
367028
+ /**
367029
+ * Log hook execution for observability
367030
+ */
367031
+ logHookExecution(eventName, input, results, aggregated) {
367032
+ const successCount = results.filter((r3) => r3.success).length;
367033
+ const errorCount = results.length - successCount;
367034
+ if (errorCount > 0) {
367035
+ debugLogger.warn(`Hook execution for ${eventName}: ${successCount} succeeded, ${errorCount} failed, total duration: ${aggregated.totalDuration}ms`);
367036
+ } else {
367037
+ debugLogger.debug(`Hook execution for ${eventName}: ${successCount} hooks executed successfully, total duration: ${aggregated.totalDuration}ms`);
367038
+ }
367039
+ for (const result of results) {
367040
+ const hookName = this.getHookNameFromResult(result);
367041
+ const hookType = this.getHookTypeFromResult(result);
367042
+ const hookCallEvent = new HookCallEvent(eventName, hookType, hookName, { ...input }, result.duration, result.success, result.output ? { ...result.output } : void 0, result.exitCode, result.stdout, result.stderr, result.error?.message);
367043
+ logHookCall(this.config, hookCallEvent);
367044
+ }
367045
+ for (const error of aggregated.errors) {
367046
+ debugLogger.error(`Hook execution error: ${error.message}`);
367047
+ }
367048
+ }
367049
+ /**
367050
+ * Process common hook output fields centrally
367051
+ */
367052
+ processCommonHookOutputFields(aggregated) {
367053
+ if (!aggregated.finalOutput) {
367054
+ return;
367055
+ }
367056
+ const systemMessage = aggregated.finalOutput.systemMessage;
367057
+ if (systemMessage && !aggregated.finalOutput.suppressOutput) {
367058
+ debugLogger.warn(`Hook system message: ${systemMessage}`);
367059
+ }
367060
+ if (aggregated.finalOutput.shouldStopExecution()) {
367061
+ const stopReason = aggregated.finalOutput.getEffectiveReason();
367062
+ debugLogger.log(`Hook requested to stop execution: ${stopReason}`);
367063
+ }
367064
+ }
367065
+ /**
367066
+ * Get hook name from execution result for telemetry
367067
+ */
367068
+ getHookNameFromResult(result) {
367069
+ return result.hookConfig.command || "unknown-command";
367070
+ }
367071
+ /**
367072
+ * Get hook type from execution result for telemetry
367073
+ */
367074
+ getHookTypeFromResult(result) {
367075
+ return result.hookConfig.type;
367076
+ }
367077
+ /**
367078
+ * Handle hook execution requests from MessageBus
367079
+ * This method routes the request to the appropriate fire*Event method
367080
+ * and publishes the response back through MessageBus
367081
+ *
367082
+ * The request input only contains event-specific fields. This method adds
367083
+ * the common base fields (session_id, cwd, etc.) before routing.
367084
+ */
367085
+ async handleHookExecutionRequest(request3) {
367086
+ try {
367087
+ const enrichedInput = {
367088
+ ...this.createBaseInput(request3.eventName),
367089
+ ...request3.input
367090
+ };
367091
+ let result;
367092
+ switch (request3.eventName) {
367093
+ case HookEventName.BeforeTool: {
367094
+ const { toolName, toolInput } = validateBeforeToolInput(enrichedInput);
367095
+ result = await this.fireBeforeToolEvent(toolName, toolInput);
367096
+ break;
367097
+ }
367098
+ case HookEventName.AfterTool: {
367099
+ const { toolName, toolInput, toolResponse } = validateAfterToolInput(enrichedInput);
367100
+ result = await this.fireAfterToolEvent(toolName, toolInput, toolResponse);
367101
+ break;
367102
+ }
367103
+ case HookEventName.BeforeAgent: {
367104
+ const { prompt } = validateBeforeAgentInput(enrichedInput);
367105
+ result = await this.fireBeforeAgentEvent(prompt);
367106
+ break;
367107
+ }
367108
+ case HookEventName.AfterAgent: {
367109
+ const { prompt, promptResponse, stopHookActive } = validateAfterAgentInput(enrichedInput);
367110
+ result = await this.fireAfterAgentEvent(prompt, promptResponse, stopHookActive);
367111
+ break;
367112
+ }
367113
+ case HookEventName.BeforeModel: {
367114
+ const { llmRequest } = validateModelInput(enrichedInput, "BeforeModel");
367115
+ const translatedRequest = defaultHookTranslator.toHookLLMRequest(llmRequest);
367116
+ enrichedInput["llm_request"] = translatedRequest;
367117
+ result = await this.fireBeforeModelEvent(llmRequest);
367118
+ break;
367119
+ }
367120
+ case HookEventName.AfterModel: {
367121
+ const { llmRequest, llmResponse } = validateAfterModelInput(enrichedInput);
367122
+ const translatedRequest = defaultHookTranslator.toHookLLMRequest(llmRequest);
367123
+ const translatedResponse = defaultHookTranslator.toHookLLMResponse(llmResponse);
367124
+ enrichedInput["llm_request"] = translatedRequest;
367125
+ enrichedInput["llm_response"] = translatedResponse;
367126
+ result = await this.fireAfterModelEvent(llmRequest, llmResponse);
367127
+ break;
367128
+ }
367129
+ case HookEventName.BeforeToolSelection: {
367130
+ const { llmRequest } = validateModelInput(enrichedInput, "BeforeToolSelection");
367131
+ const translatedRequest = defaultHookTranslator.toHookLLMRequest(llmRequest);
367132
+ enrichedInput["llm_request"] = translatedRequest;
367133
+ result = await this.fireBeforeToolSelectionEvent(llmRequest);
367134
+ break;
367135
+ }
367136
+ case HookEventName.Notification: {
367137
+ const { notificationType, message, details } = validateNotificationInput(enrichedInput);
367138
+ result = await this.fireNotificationEvent(notificationType, message, details);
367139
+ break;
367140
+ }
367141
+ default:
367142
+ throw new Error(`Unsupported hook event: ${request3.eventName}`);
367143
+ }
367144
+ if (this.messageBus) {
367145
+ this.messageBus.publish({
367146
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
367147
+ correlationId: request3.correlationId,
367148
+ success: result.success,
367149
+ output: result.finalOutput
367150
+ });
367151
+ }
367152
+ } catch (error) {
367153
+ if (this.messageBus) {
367154
+ this.messageBus.publish({
367155
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
367156
+ correlationId: request3.correlationId,
367157
+ success: false,
367158
+ error: error instanceof Error ? error : new Error(String(error))
367159
+ });
367160
+ }
367161
+ }
367162
+ }
367163
+ };
367164
+
367165
+ // packages/core/dist/src/hooks/hookSystem.js
367166
+ var import_api_logs2 = __toESM(require_src21(), 1);
367167
+ var HookSystem = class {
367168
+ hookRegistry;
367169
+ hookRunner;
367170
+ hookAggregator;
367171
+ hookPlanner;
367172
+ hookEventHandler;
367173
+ initialized = false;
367174
+ constructor(config2) {
367175
+ const logger6 = import_api_logs2.logs.getLogger(SERVICE_NAME);
367176
+ const messageBus = config2.getMessageBus();
367177
+ this.hookRegistry = new HookRegistry(config2);
367178
+ this.hookRunner = new HookRunner();
367179
+ this.hookAggregator = new HookAggregator();
367180
+ this.hookPlanner = new HookPlanner(this.hookRegistry);
367181
+ this.hookEventHandler = new HookEventHandler(config2, logger6, this.hookPlanner, this.hookRunner, this.hookAggregator, messageBus);
367182
+ }
367183
+ /**
367184
+ * Initialize the hook system
367185
+ */
367186
+ async initialize() {
367187
+ if (this.initialized) {
367188
+ return;
367189
+ }
367190
+ await this.hookRegistry.initialize();
367191
+ this.initialized = true;
367192
+ debugLogger.debug("Hook system initialized successfully");
367193
+ }
367194
+ /**
367195
+ * Get the hook event bus for firing events
367196
+ */
367197
+ getEventHandler() {
367198
+ if (!this.initialized) {
367199
+ throw new Error("Hook system not initialized");
367200
+ }
367201
+ return this.hookEventHandler;
367202
+ }
367203
+ /**
367204
+ * Get hook registry for management operations
367205
+ */
367206
+ getRegistry() {
367207
+ return this.hookRegistry;
367208
+ }
367209
+ /**
367210
+ * Enable or disable a hook
367211
+ */
367212
+ setHookEnabled(hookName, enabled) {
367213
+ this.hookRegistry.setHookEnabled(hookName, enabled);
367214
+ }
367215
+ /**
367216
+ * Get all registered hooks for display/management
367217
+ */
367218
+ getAllHooks() {
367219
+ return this.hookRegistry.getAllHooks();
367220
+ }
367221
+ /**
367222
+ * Get hook system status for debugging
367223
+ */
367224
+ getStatus() {
367225
+ const allHooks = this.initialized ? this.hookRegistry.getAllHooks() : [];
367226
+ return {
367227
+ initialized: this.initialized,
367228
+ totalHooks: allHooks.length
367229
+ };
367230
+ }
367231
+ };
367232
+
365241
367233
  // packages/core/dist/src/agents/registry.js
365242
367234
  function getModelConfigAlias(definition) {
365243
367235
  return `${definition.name}-config`;
@@ -367676,7 +369668,7 @@ async function readPackageUp(options2) {
367676
369668
  async function getPackageJson(cwd) {
367677
369669
  const result = await readPackageUp({ cwd });
367678
369670
  if (!result) {
367679
- return;
369671
+ return void 0;
367680
369672
  }
367681
369673
  return result.packageJson;
367682
369674
  }
@@ -367738,7 +369730,7 @@ async function getClientMetadata() {
367738
369730
  clientMetadataPromise = (async () => ({
367739
369731
  ideName: "IDE_UNSPECIFIED",
367740
369732
  pluginType: "GEMINI",
367741
- ideVersion: "0.19.0-nightly.20251124.e177314a4",
369733
+ ideVersion: "0.19.0-nightly.20251126.03845198c",
367742
369734
  platform: getPlatform(),
367743
369735
  updateChannel: await getReleaseChannel(__dirname5)
367744
369736
  }))();
@@ -373254,8 +375246,10 @@ var Config = class {
373254
375246
  hooks;
373255
375247
  experiments;
373256
375248
  experimentsPromise;
375249
+ hookSystem;
373257
375250
  previewModelFallbackMode = false;
373258
375251
  previewModelBypassMode = false;
375252
+ enableModelAvailabilityService;
373259
375253
  constructor(params) {
373260
375254
  this.sessionId = params.sessionId;
373261
375255
  this.embeddingModel = params.embeddingModel ?? DEFAULT_GEMINI_EMBEDDING_MODEL;
@@ -373304,6 +375298,7 @@ var Config = class {
373304
375298
  this.fileDiscoveryService = params.fileDiscoveryService ?? null;
373305
375299
  this.bugCommand = params.bugCommand;
373306
375300
  this.model = params.model;
375301
+ this.enableModelAvailabilityService = params.enableModelAvailabilityService ?? false;
373307
375302
  this.previewFeatures = params.previewFeatures ?? void 0;
373308
375303
  this.maxSessionTurns = params.maxSessionTurns ?? -1;
373309
375304
  this.experimentalZedIntegration = params.experimentalZedIntegration ?? false;
@@ -373413,6 +375408,10 @@ var Config = class {
373413
375408
  await this.mcpClientManager.startConfiguredMcpServers(),
373414
375409
  await this.getExtensionLoader().start(this)
373415
375410
  ]);
375411
+ if (this.enableHooks) {
375412
+ this.hookSystem = new HookSystem(this);
375413
+ await this.hookSystem.initialize();
375414
+ }
373416
375415
  await this.geminiClient.initialize();
373417
375416
  }
373418
375417
  getContentGenerator() {
@@ -373782,6 +375781,9 @@ var Config = class {
373782
375781
  getEnableExtensionReloading() {
373783
375782
  return this.enableExtensionReloading;
373784
375783
  }
375784
+ isModelAvailabilityServiceEnabled() {
375785
+ return this.enableModelAvailabilityService;
375786
+ }
373785
375787
  getNoBrowser() {
373786
375788
  return this.noBrowser;
373787
375789
  }
@@ -374016,6 +376018,12 @@ var Config = class {
374016
376018
  registry.sortTools();
374017
376019
  return registry;
374018
376020
  }
376021
+ /**
376022
+ * Get the hook system instance
376023
+ */
376024
+ getHookSystem() {
376025
+ return this.hookSystem;
376026
+ }
374019
376027
  /**
374020
376028
  * Get hooks configuration
374021
376029
  */
@@ -374207,220 +376215,8 @@ function parseAndFormatApiError(error, authType, userTier, currentModel, fallbac
374207
376215
  init_events();
374208
376216
 
374209
376217
  // packages/core/dist/src/utils/session.js
374210
- import { randomUUID as randomUUID6 } from "node:crypto";
374211
- var sessionId = randomUUID6();
374212
-
374213
- // packages/core/dist/src/hooks/hookTranslator.js
374214
- var HookTranslator = class {
374215
- };
374216
- function hasTextProperty(value) {
374217
- return typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
374218
- }
374219
- function isContentWithParts(content) {
374220
- return typeof content === "object" && content !== null && "role" in content && "parts" in content;
374221
- }
374222
- function extractGenerationConfig(request3) {
374223
- if (request3.config && typeof request3.config === "object") {
374224
- const config2 = request3.config;
374225
- return {
374226
- temperature: config2.temperature,
374227
- maxOutputTokens: config2.maxOutputTokens,
374228
- topP: config2.topP,
374229
- topK: config2.topK
374230
- };
374231
- }
374232
- return void 0;
374233
- }
374234
- var HookTranslatorGenAIv1 = class extends HookTranslator {
374235
- /**
374236
- * Convert genai SDK GenerateContentParameters to stable LLMRequest
374237
- *
374238
- * Note: This implementation intentionally extracts only text content from parts.
374239
- * Non-text parts (images, function calls, etc.) are filtered out in v1 to provide
374240
- * a simplified, stable interface for hooks. This allows hooks to focus on text
374241
- * manipulation without needing to handle complex multimodal content.
374242
- * Future versions may expose additional content types if needed.
374243
- */
374244
- toHookLLMRequest(sdkRequest) {
374245
- const messages = [];
374246
- if (sdkRequest.contents) {
374247
- const contents = Array.isArray(sdkRequest.contents) ? sdkRequest.contents : [sdkRequest.contents];
374248
- for (const content of contents) {
374249
- if (typeof content === "string") {
374250
- messages.push({
374251
- role: "user",
374252
- content
374253
- });
374254
- } else if (isContentWithParts(content)) {
374255
- const role = content.role === "model" ? "model" : content.role === "system" ? "system" : "user";
374256
- const parts2 = Array.isArray(content.parts) ? content.parts : [content.parts];
374257
- const textContent2 = parts2.filter(hasTextProperty).map((part) => part.text).join("");
374258
- if (textContent2) {
374259
- messages.push({
374260
- role,
374261
- content: textContent2
374262
- });
374263
- }
374264
- }
374265
- }
374266
- }
374267
- const config2 = extractGenerationConfig(sdkRequest);
374268
- return {
374269
- model: sdkRequest.model || DEFAULT_GEMINI_FLASH_MODEL,
374270
- messages,
374271
- config: {
374272
- temperature: config2?.temperature,
374273
- maxOutputTokens: config2?.maxOutputTokens,
374274
- topP: config2?.topP,
374275
- topK: config2?.topK
374276
- }
374277
- };
374278
- }
374279
- /**
374280
- * Convert stable LLMRequest to genai SDK GenerateContentParameters
374281
- */
374282
- fromHookLLMRequest(hookRequest, baseRequest) {
374283
- const contents = hookRequest.messages.map((message) => ({
374284
- role: message.role === "model" ? "model" : message.role,
374285
- parts: [
374286
- {
374287
- text: typeof message.content === "string" ? message.content : String(message.content)
374288
- }
374289
- ]
374290
- }));
374291
- const result = {
374292
- ...baseRequest,
374293
- model: hookRequest.model,
374294
- contents
374295
- };
374296
- if (hookRequest.config) {
374297
- const baseConfig = baseRequest ? extractGenerationConfig(baseRequest) : void 0;
374298
- result.config = {
374299
- ...baseConfig,
374300
- temperature: hookRequest.config.temperature,
374301
- maxOutputTokens: hookRequest.config.maxOutputTokens,
374302
- topP: hookRequest.config.topP,
374303
- topK: hookRequest.config.topK
374304
- };
374305
- }
374306
- return result;
374307
- }
374308
- /**
374309
- * Convert genai SDK GenerateContentResponse to stable LLMResponse
374310
- */
374311
- toHookLLMResponse(sdkResponse) {
374312
- return {
374313
- text: sdkResponse.text,
374314
- candidates: (sdkResponse.candidates || []).map((candidate) => {
374315
- const textParts = candidate.content?.parts?.filter(hasTextProperty).map((part) => part.text) || [];
374316
- return {
374317
- content: {
374318
- role: "model",
374319
- parts: textParts
374320
- },
374321
- finishReason: candidate.finishReason,
374322
- index: candidate.index,
374323
- safetyRatings: candidate.safetyRatings?.map((rating) => ({
374324
- category: String(rating.category || ""),
374325
- probability: String(rating.probability || "")
374326
- }))
374327
- };
374328
- }),
374329
- usageMetadata: sdkResponse.usageMetadata ? {
374330
- promptTokenCount: sdkResponse.usageMetadata.promptTokenCount,
374331
- candidatesTokenCount: sdkResponse.usageMetadata.candidatesTokenCount,
374332
- totalTokenCount: sdkResponse.usageMetadata.totalTokenCount
374333
- } : void 0
374334
- };
374335
- }
374336
- /**
374337
- * Convert stable LLMResponse to genai SDK GenerateContentResponse
374338
- */
374339
- fromHookLLMResponse(hookResponse) {
374340
- const response = {
374341
- text: hookResponse.text,
374342
- candidates: hookResponse.candidates.map((candidate) => ({
374343
- content: {
374344
- role: "model",
374345
- parts: candidate.content.parts.map((part) => ({
374346
- text: part
374347
- }))
374348
- },
374349
- finishReason: candidate.finishReason,
374350
- index: candidate.index,
374351
- safetyRatings: candidate.safetyRatings
374352
- })),
374353
- usageMetadata: hookResponse.usageMetadata
374354
- };
374355
- return response;
374356
- }
374357
- /**
374358
- * Convert genai SDK ToolConfig to stable HookToolConfig
374359
- */
374360
- toHookToolConfig(sdkToolConfig) {
374361
- return {
374362
- mode: sdkToolConfig.functionCallingConfig?.mode,
374363
- allowedFunctionNames: sdkToolConfig.functionCallingConfig?.allowedFunctionNames
374364
- };
374365
- }
374366
- /**
374367
- * Convert stable HookToolConfig to genai SDK ToolConfig
374368
- */
374369
- fromHookToolConfig(hookToolConfig) {
374370
- const functionCallingConfig = hookToolConfig.mode || hookToolConfig.allowedFunctionNames ? {
374371
- mode: hookToolConfig.mode,
374372
- allowedFunctionNames: hookToolConfig.allowedFunctionNames
374373
- } : void 0;
374374
- return {
374375
- functionCallingConfig
374376
- };
374377
- }
374378
- };
374379
- var defaultHookTranslator = new HookTranslatorGenAIv1();
374380
-
374381
- // packages/core/dist/src/hooks/types.js
374382
- var HookEventName;
374383
- (function(HookEventName2) {
374384
- HookEventName2["BeforeTool"] = "BeforeTool";
374385
- HookEventName2["AfterTool"] = "AfterTool";
374386
- HookEventName2["BeforeAgent"] = "BeforeAgent";
374387
- HookEventName2["Notification"] = "Notification";
374388
- HookEventName2["AfterAgent"] = "AfterAgent";
374389
- HookEventName2["SessionStart"] = "SessionStart";
374390
- HookEventName2["SessionEnd"] = "SessionEnd";
374391
- HookEventName2["PreCompress"] = "PreCompress";
374392
- HookEventName2["BeforeModel"] = "BeforeModel";
374393
- HookEventName2["AfterModel"] = "AfterModel";
374394
- HookEventName2["BeforeToolSelection"] = "BeforeToolSelection";
374395
- })(HookEventName || (HookEventName = {}));
374396
- var HookType;
374397
- (function(HookType2) {
374398
- HookType2["Command"] = "command";
374399
- })(HookType || (HookType = {}));
374400
- var NotificationType;
374401
- (function(NotificationType2) {
374402
- NotificationType2["ToolPermission"] = "ToolPermission";
374403
- })(NotificationType || (NotificationType = {}));
374404
- var SessionStartSource;
374405
- (function(SessionStartSource2) {
374406
- SessionStartSource2["Startup"] = "startup";
374407
- SessionStartSource2["Resume"] = "resume";
374408
- SessionStartSource2["Clear"] = "clear";
374409
- SessionStartSource2["Compress"] = "compress";
374410
- })(SessionStartSource || (SessionStartSource = {}));
374411
- var SessionEndReason;
374412
- (function(SessionEndReason2) {
374413
- SessionEndReason2["Exit"] = "exit";
374414
- SessionEndReason2["Clear"] = "clear";
374415
- SessionEndReason2["Logout"] = "logout";
374416
- SessionEndReason2["PromptInputExit"] = "prompt_input_exit";
374417
- SessionEndReason2["Other"] = "other";
374418
- })(SessionEndReason || (SessionEndReason = {}));
374419
- var PreCompressTrigger;
374420
- (function(PreCompressTrigger2) {
374421
- PreCompressTrigger2["Manual"] = "manual";
374422
- PreCompressTrigger2["Auto"] = "auto";
374423
- })(PreCompressTrigger || (PreCompressTrigger = {}));
376218
+ import { randomUUID as randomUUID7 } from "node:crypto";
376219
+ var sessionId = randomUUID7();
374424
376220
 
374425
376221
  // packages/core/dist/index.js
374426
376222
  init_keychain_token_storage();