@google/gemini-cli-a2a-server 0.19.0-nightly.20251123.dadd606c0 → 0.19.0-nightly.20251125.f6d97d448

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 = "dadd606c0";
307693
- var CLI_VERSION = "0.19.0-nightly.20251123.dadd606c0";
307806
+ var GIT_COMMIT_INFO = "f6d97d448";
307807
+ var CLI_VERSION = "0.19.0-nightly.20251125.f6d97d448";
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.20251123.dadd606c0";
310709
+ const version3 = "0.19.0-nightly.20251125.f6d97d448";
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";
@@ -357671,6 +357809,13 @@ ${[...this.pendingCitations].sort().join("\n")}`
357671
357809
  getDebugResponses() {
357672
357810
  return this.debugResponses;
357673
357811
  }
357812
+ /**
357813
+ * Get the concatenated response text from all responses in this turn.
357814
+ * This extracts and joins all text content from the model's responses.
357815
+ */
357816
+ getResponseText() {
357817
+ return this.debugResponses.map((response) => getResponseText(response)).filter((text) => text !== null).join(" ");
357818
+ }
357674
357819
  };
357675
357820
  function getCitations(resp) {
357676
357821
  return (resp.candidates?.[0]?.citationMetadata?.citations ?? []).filter((citation) => citation.uri !== void 0).map((citation) => {
@@ -358028,6 +358173,8 @@ function getCoreSystemPrompt(config2, userMemory) {
358028
358173
  throw new Error(`missing system prompt file '${systemMdPath}'`);
358029
358174
  }
358030
358175
  }
358176
+ const desiredModel = getEffectiveModel(config2.isInFallbackMode(), config2.getModel(), config2.getPreviewFeatures());
358177
+ const useChattySystemPrompt = desiredModel === PREVIEW_GEMINI_MODEL;
358031
358178
  const enableCodebaseInvestigator = config2.getToolRegistry().getAllToolNames().includes(CodebaseInvestigatorAgent.name);
358032
358179
  const enableWriteTodosTool = config2.getToolRegistry().getAllToolNames().includes(WriteTodosTool.Name);
358033
358180
  let basePrompt;
@@ -358125,7 +358272,13 @@ IT IS CRITICAL TO FOLLOW THESE GUIDELINES TO AVOID EXCESSIVE TOKEN CONSUMPTION.
358125
358272
  - **Concise & Direct:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
358126
358273
  - **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
358274
  - **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.
358275
+ ${function() {
358276
+ if (useChattySystemPrompt) {
358277
+ return "";
358278
+ } else {
358279
+ 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.';
358280
+ }
358281
+ }()}
358129
358282
  - **Formatting:** Use GitHub-flavored Markdown. Responses will be rendered in monospace.
358130
358283
  - **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
358284
  - **Handling Inability:** If unable/unwilling to fulfill a request, state so briefly (1-2 sentences) without excessive justification. Offer alternatives if appropriate.
@@ -358769,6 +358922,20 @@ function findCompressSplitPoint(contents, fraction) {
358769
358922
  }
358770
358923
  return lastSplitPoint;
358771
358924
  }
358925
+ function modelStringToModelConfigAlias(model) {
358926
+ switch (model) {
358927
+ case PREVIEW_GEMINI_MODEL:
358928
+ return "chat-compression-3-pro";
358929
+ case DEFAULT_GEMINI_MODEL:
358930
+ return "chat-compression-2.5-pro";
358931
+ case DEFAULT_GEMINI_FLASH_MODEL:
358932
+ return "chat-compression-2.5-flash";
358933
+ case DEFAULT_GEMINI_FLASH_LITE_MODEL:
358934
+ return "chat-compression-2.5-flash-lite";
358935
+ default:
358936
+ return "chat-compression-default";
358937
+ }
358938
+ }
358772
358939
  var ChatCompressionService = class {
358773
358940
  async compress(chat, promptId, force, model, config2, hasFailedCompressionAttempt) {
358774
358941
  const curatedHistory = chat.getHistory(true);
@@ -358809,8 +358976,8 @@ var ChatCompressionService = class {
358809
358976
  }
358810
358977
  };
358811
358978
  }
358812
- const summaryResponse = await config2.getContentGenerator().generateContent({
358813
- model,
358979
+ const summaryResponse = await config2.getBaseLlmClient().generateContent({
358980
+ modelConfigKey: { model: modelStringToModelConfigAlias(model) },
358814
358981
  contents: [
358815
358982
  ...historyToCompress,
358816
358983
  {
@@ -358822,10 +358989,11 @@ var ChatCompressionService = class {
358822
358989
  ]
358823
358990
  }
358824
358991
  ],
358825
- config: {
358826
- systemInstruction: { text: getCompressionPrompt() }
358827
- }
358828
- }, promptId);
358992
+ systemInstruction: { text: getCompressionPrompt() },
358993
+ promptId,
358994
+ // TODO(joshualitt): wire up a sensible abort signal,
358995
+ abortSignal: new AbortController().signal
358996
+ });
358829
358997
  const summary = getResponseText(summaryResponse) ?? "";
358830
358998
  const extraHistory = [
358831
358999
  {
@@ -358866,8 +359034,460 @@ var ChatCompressionService = class {
358866
359034
  }
358867
359035
  };
358868
359036
 
359037
+ // packages/core/dist/src/hooks/hookTranslator.js
359038
+ var HookTranslator = class {
359039
+ };
359040
+ function hasTextProperty(value) {
359041
+ return typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
359042
+ }
359043
+ function isContentWithParts(content) {
359044
+ return typeof content === "object" && content !== null && "role" in content && "parts" in content;
359045
+ }
359046
+ function extractGenerationConfig(request3) {
359047
+ if (request3.config && typeof request3.config === "object") {
359048
+ const config2 = request3.config;
359049
+ return {
359050
+ temperature: config2.temperature,
359051
+ maxOutputTokens: config2.maxOutputTokens,
359052
+ topP: config2.topP,
359053
+ topK: config2.topK
359054
+ };
359055
+ }
359056
+ return void 0;
359057
+ }
359058
+ var HookTranslatorGenAIv1 = class extends HookTranslator {
359059
+ /**
359060
+ * Convert genai SDK GenerateContentParameters to stable LLMRequest
359061
+ *
359062
+ * Note: This implementation intentionally extracts only text content from parts.
359063
+ * Non-text parts (images, function calls, etc.) are filtered out in v1 to provide
359064
+ * a simplified, stable interface for hooks. This allows hooks to focus on text
359065
+ * manipulation without needing to handle complex multimodal content.
359066
+ * Future versions may expose additional content types if needed.
359067
+ */
359068
+ toHookLLMRequest(sdkRequest) {
359069
+ const messages = [];
359070
+ if (sdkRequest.contents) {
359071
+ const contents = Array.isArray(sdkRequest.contents) ? sdkRequest.contents : [sdkRequest.contents];
359072
+ for (const content of contents) {
359073
+ if (typeof content === "string") {
359074
+ messages.push({
359075
+ role: "user",
359076
+ content
359077
+ });
359078
+ } else if (isContentWithParts(content)) {
359079
+ const role = content.role === "model" ? "model" : content.role === "system" ? "system" : "user";
359080
+ const parts2 = Array.isArray(content.parts) ? content.parts : [content.parts];
359081
+ const textContent2 = parts2.filter(hasTextProperty).map((part) => part.text).join("");
359082
+ if (textContent2) {
359083
+ messages.push({
359084
+ role,
359085
+ content: textContent2
359086
+ });
359087
+ }
359088
+ }
359089
+ }
359090
+ }
359091
+ const config2 = extractGenerationConfig(sdkRequest);
359092
+ return {
359093
+ model: sdkRequest.model || DEFAULT_GEMINI_FLASH_MODEL,
359094
+ messages,
359095
+ config: {
359096
+ temperature: config2?.temperature,
359097
+ maxOutputTokens: config2?.maxOutputTokens,
359098
+ topP: config2?.topP,
359099
+ topK: config2?.topK
359100
+ }
359101
+ };
359102
+ }
359103
+ /**
359104
+ * Convert stable LLMRequest to genai SDK GenerateContentParameters
359105
+ */
359106
+ fromHookLLMRequest(hookRequest, baseRequest) {
359107
+ const contents = hookRequest.messages.map((message) => ({
359108
+ role: message.role === "model" ? "model" : message.role,
359109
+ parts: [
359110
+ {
359111
+ text: typeof message.content === "string" ? message.content : String(message.content)
359112
+ }
359113
+ ]
359114
+ }));
359115
+ const result = {
359116
+ ...baseRequest,
359117
+ model: hookRequest.model,
359118
+ contents
359119
+ };
359120
+ if (hookRequest.config) {
359121
+ const baseConfig = baseRequest ? extractGenerationConfig(baseRequest) : void 0;
359122
+ result.config = {
359123
+ ...baseConfig,
359124
+ temperature: hookRequest.config.temperature,
359125
+ maxOutputTokens: hookRequest.config.maxOutputTokens,
359126
+ topP: hookRequest.config.topP,
359127
+ topK: hookRequest.config.topK
359128
+ };
359129
+ }
359130
+ return result;
359131
+ }
359132
+ /**
359133
+ * Convert genai SDK GenerateContentResponse to stable LLMResponse
359134
+ */
359135
+ toHookLLMResponse(sdkResponse) {
359136
+ return {
359137
+ text: sdkResponse.text,
359138
+ candidates: (sdkResponse.candidates || []).map((candidate) => {
359139
+ const textParts = candidate.content?.parts?.filter(hasTextProperty).map((part) => part.text) || [];
359140
+ return {
359141
+ content: {
359142
+ role: "model",
359143
+ parts: textParts
359144
+ },
359145
+ finishReason: candidate.finishReason,
359146
+ index: candidate.index,
359147
+ safetyRatings: candidate.safetyRatings?.map((rating) => ({
359148
+ category: String(rating.category || ""),
359149
+ probability: String(rating.probability || "")
359150
+ }))
359151
+ };
359152
+ }),
359153
+ usageMetadata: sdkResponse.usageMetadata ? {
359154
+ promptTokenCount: sdkResponse.usageMetadata.promptTokenCount,
359155
+ candidatesTokenCount: sdkResponse.usageMetadata.candidatesTokenCount,
359156
+ totalTokenCount: sdkResponse.usageMetadata.totalTokenCount
359157
+ } : void 0
359158
+ };
359159
+ }
359160
+ /**
359161
+ * Convert stable LLMResponse to genai SDK GenerateContentResponse
359162
+ */
359163
+ fromHookLLMResponse(hookResponse) {
359164
+ const response = {
359165
+ text: hookResponse.text,
359166
+ candidates: hookResponse.candidates.map((candidate) => ({
359167
+ content: {
359168
+ role: "model",
359169
+ parts: candidate.content.parts.map((part) => ({
359170
+ text: part
359171
+ }))
359172
+ },
359173
+ finishReason: candidate.finishReason,
359174
+ index: candidate.index,
359175
+ safetyRatings: candidate.safetyRatings
359176
+ })),
359177
+ usageMetadata: hookResponse.usageMetadata
359178
+ };
359179
+ return response;
359180
+ }
359181
+ /**
359182
+ * Convert genai SDK ToolConfig to stable HookToolConfig
359183
+ */
359184
+ toHookToolConfig(sdkToolConfig) {
359185
+ return {
359186
+ mode: sdkToolConfig.functionCallingConfig?.mode,
359187
+ allowedFunctionNames: sdkToolConfig.functionCallingConfig?.allowedFunctionNames
359188
+ };
359189
+ }
359190
+ /**
359191
+ * Convert stable HookToolConfig to genai SDK ToolConfig
359192
+ */
359193
+ fromHookToolConfig(hookToolConfig) {
359194
+ const functionCallingConfig = hookToolConfig.mode || hookToolConfig.allowedFunctionNames ? {
359195
+ mode: hookToolConfig.mode,
359196
+ allowedFunctionNames: hookToolConfig.allowedFunctionNames
359197
+ } : void 0;
359198
+ return {
359199
+ functionCallingConfig
359200
+ };
359201
+ }
359202
+ };
359203
+ var defaultHookTranslator = new HookTranslatorGenAIv1();
359204
+
359205
+ // packages/core/dist/src/hooks/types.js
359206
+ var HookEventName;
359207
+ (function(HookEventName2) {
359208
+ HookEventName2["BeforeTool"] = "BeforeTool";
359209
+ HookEventName2["AfterTool"] = "AfterTool";
359210
+ HookEventName2["BeforeAgent"] = "BeforeAgent";
359211
+ HookEventName2["Notification"] = "Notification";
359212
+ HookEventName2["AfterAgent"] = "AfterAgent";
359213
+ HookEventName2["SessionStart"] = "SessionStart";
359214
+ HookEventName2["SessionEnd"] = "SessionEnd";
359215
+ HookEventName2["PreCompress"] = "PreCompress";
359216
+ HookEventName2["BeforeModel"] = "BeforeModel";
359217
+ HookEventName2["AfterModel"] = "AfterModel";
359218
+ HookEventName2["BeforeToolSelection"] = "BeforeToolSelection";
359219
+ })(HookEventName || (HookEventName = {}));
359220
+ var HookType;
359221
+ (function(HookType2) {
359222
+ HookType2["Command"] = "command";
359223
+ })(HookType || (HookType = {}));
359224
+ function createHookOutput(eventName, data) {
359225
+ switch (eventName) {
359226
+ case "BeforeModel":
359227
+ return new BeforeModelHookOutput(data);
359228
+ case "AfterModel":
359229
+ return new AfterModelHookOutput(data);
359230
+ case "BeforeToolSelection":
359231
+ return new BeforeToolSelectionHookOutput(data);
359232
+ default:
359233
+ return new DefaultHookOutput(data);
359234
+ }
359235
+ }
359236
+ var DefaultHookOutput = class {
359237
+ continue;
359238
+ stopReason;
359239
+ suppressOutput;
359240
+ systemMessage;
359241
+ decision;
359242
+ reason;
359243
+ hookSpecificOutput;
359244
+ constructor(data = {}) {
359245
+ this.continue = data.continue;
359246
+ this.stopReason = data.stopReason;
359247
+ this.suppressOutput = data.suppressOutput;
359248
+ this.systemMessage = data.systemMessage;
359249
+ this.decision = data.decision;
359250
+ this.reason = data.reason;
359251
+ this.hookSpecificOutput = data.hookSpecificOutput;
359252
+ }
359253
+ /**
359254
+ * Check if this output represents a blocking decision
359255
+ */
359256
+ isBlockingDecision() {
359257
+ return this.decision === "block" || this.decision === "deny";
359258
+ }
359259
+ /**
359260
+ * Check if this output requests to stop execution
359261
+ */
359262
+ shouldStopExecution() {
359263
+ return this.continue === false;
359264
+ }
359265
+ /**
359266
+ * Get the effective reason for blocking or stopping
359267
+ */
359268
+ getEffectiveReason() {
359269
+ return this.reason || this.stopReason || "No reason provided";
359270
+ }
359271
+ /**
359272
+ * Apply LLM request modifications (specific method for BeforeModel hooks)
359273
+ */
359274
+ applyLLMRequestModifications(target) {
359275
+ return target;
359276
+ }
359277
+ /**
359278
+ * Apply tool config modifications (specific method for BeforeToolSelection hooks)
359279
+ */
359280
+ applyToolConfigModifications(target) {
359281
+ return target;
359282
+ }
359283
+ /**
359284
+ * Get additional context for adding to responses
359285
+ */
359286
+ getAdditionalContext() {
359287
+ if (this.hookSpecificOutput && "additionalContext" in this.hookSpecificOutput) {
359288
+ const context2 = this.hookSpecificOutput["additionalContext"];
359289
+ return typeof context2 === "string" ? context2 : void 0;
359290
+ }
359291
+ return void 0;
359292
+ }
359293
+ /**
359294
+ * Check if execution should be blocked and return error info
359295
+ */
359296
+ getBlockingError() {
359297
+ if (this.isBlockingDecision()) {
359298
+ return {
359299
+ blocked: true,
359300
+ reason: this.getEffectiveReason()
359301
+ };
359302
+ }
359303
+ return { blocked: false, reason: "" };
359304
+ }
359305
+ };
359306
+ var BeforeToolHookOutput = class extends DefaultHookOutput {
359307
+ /**
359308
+ * Get the effective blocking reason, considering compatibility fields
359309
+ */
359310
+ getEffectiveReason() {
359311
+ if (this.hookSpecificOutput) {
359312
+ if ("permissionDecisionReason" in this.hookSpecificOutput) {
359313
+ const compatReason = this.hookSpecificOutput["permissionDecisionReason"];
359314
+ if (typeof compatReason === "string") {
359315
+ return compatReason;
359316
+ }
359317
+ }
359318
+ }
359319
+ return super.getEffectiveReason();
359320
+ }
359321
+ /**
359322
+ * Check if this output represents a blocking decision, considering compatibility fields
359323
+ */
359324
+ isBlockingDecision() {
359325
+ if (this.hookSpecificOutput && "permissionDecision" in this.hookSpecificOutput) {
359326
+ const compatDecision = this.hookSpecificOutput["permissionDecision"];
359327
+ if (compatDecision === "block" || compatDecision === "deny") {
359328
+ return true;
359329
+ }
359330
+ }
359331
+ return super.isBlockingDecision();
359332
+ }
359333
+ };
359334
+ var BeforeModelHookOutput = class extends DefaultHookOutput {
359335
+ /**
359336
+ * Get synthetic LLM response if provided by hook
359337
+ */
359338
+ getSyntheticResponse() {
359339
+ if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
359340
+ const hookResponse = this.hookSpecificOutput["llm_response"];
359341
+ if (hookResponse) {
359342
+ return defaultHookTranslator.fromHookLLMResponse(hookResponse);
359343
+ }
359344
+ }
359345
+ return void 0;
359346
+ }
359347
+ /**
359348
+ * Apply modifications to LLM request
359349
+ */
359350
+ applyLLMRequestModifications(target) {
359351
+ if (this.hookSpecificOutput && "llm_request" in this.hookSpecificOutput) {
359352
+ const hookRequest = this.hookSpecificOutput["llm_request"];
359353
+ if (hookRequest) {
359354
+ const sdkRequest = defaultHookTranslator.fromHookLLMRequest(hookRequest, target);
359355
+ return {
359356
+ ...target,
359357
+ ...sdkRequest
359358
+ };
359359
+ }
359360
+ }
359361
+ return target;
359362
+ }
359363
+ };
359364
+ var BeforeToolSelectionHookOutput = class extends DefaultHookOutput {
359365
+ /**
359366
+ * Apply tool configuration modifications
359367
+ */
359368
+ applyToolConfigModifications(target) {
359369
+ if (this.hookSpecificOutput && "toolConfig" in this.hookSpecificOutput) {
359370
+ const hookToolConfig = this.hookSpecificOutput["toolConfig"];
359371
+ if (hookToolConfig) {
359372
+ const sdkToolConfig = defaultHookTranslator.fromHookToolConfig(hookToolConfig);
359373
+ return {
359374
+ ...target,
359375
+ tools: target.tools || [],
359376
+ toolConfig: sdkToolConfig
359377
+ };
359378
+ }
359379
+ }
359380
+ return target;
359381
+ }
359382
+ };
359383
+ var AfterModelHookOutput = class extends DefaultHookOutput {
359384
+ /**
359385
+ * Get modified LLM response if provided by hook
359386
+ */
359387
+ getModifiedResponse() {
359388
+ if (this.hookSpecificOutput && "llm_response" in this.hookSpecificOutput) {
359389
+ const hookResponse = this.hookSpecificOutput["llm_response"];
359390
+ if (hookResponse?.candidates?.[0]?.content?.parts?.length) {
359391
+ return defaultHookTranslator.fromHookLLMResponse(hookResponse);
359392
+ }
359393
+ }
359394
+ if (this.shouldStopExecution()) {
359395
+ const stopResponse = {
359396
+ candidates: [
359397
+ {
359398
+ content: {
359399
+ role: "model",
359400
+ parts: [this.getEffectiveReason() || "Execution stopped by hook"]
359401
+ },
359402
+ finishReason: "STOP"
359403
+ }
359404
+ ]
359405
+ };
359406
+ return defaultHookTranslator.fromHookLLMResponse(stopResponse);
359407
+ }
359408
+ return void 0;
359409
+ }
359410
+ };
359411
+ var NotificationType;
359412
+ (function(NotificationType2) {
359413
+ NotificationType2["ToolPermission"] = "ToolPermission";
359414
+ })(NotificationType || (NotificationType = {}));
359415
+ var SessionStartSource;
359416
+ (function(SessionStartSource2) {
359417
+ SessionStartSource2["Startup"] = "startup";
359418
+ SessionStartSource2["Resume"] = "resume";
359419
+ SessionStartSource2["Clear"] = "clear";
359420
+ SessionStartSource2["Compress"] = "compress";
359421
+ })(SessionStartSource || (SessionStartSource = {}));
359422
+ var SessionEndReason;
359423
+ (function(SessionEndReason2) {
359424
+ SessionEndReason2["Exit"] = "exit";
359425
+ SessionEndReason2["Clear"] = "clear";
359426
+ SessionEndReason2["Logout"] = "logout";
359427
+ SessionEndReason2["PromptInputExit"] = "prompt_input_exit";
359428
+ SessionEndReason2["Other"] = "other";
359429
+ })(SessionEndReason || (SessionEndReason = {}));
359430
+ var PreCompressTrigger;
359431
+ (function(PreCompressTrigger2) {
359432
+ PreCompressTrigger2["Manual"] = "manual";
359433
+ PreCompressTrigger2["Auto"] = "auto";
359434
+ })(PreCompressTrigger || (PreCompressTrigger = {}));
359435
+
359436
+ // packages/core/dist/src/core/clientHookTriggers.js
359437
+ async function fireBeforeAgentHook(messageBus, request3) {
359438
+ try {
359439
+ const promptText = partToString(request3);
359440
+ const response = await messageBus.request({
359441
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
359442
+ eventName: "BeforeAgent",
359443
+ input: {
359444
+ prompt: promptText
359445
+ }
359446
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
359447
+ return response.output ? createHookOutput("BeforeAgent", response.output) : void 0;
359448
+ } catch (error) {
359449
+ debugLogger.warn(`BeforeAgent hook failed: ${error}`);
359450
+ return void 0;
359451
+ }
359452
+ }
359453
+ async function fireAfterAgentHook(messageBus, request3, responseText) {
359454
+ try {
359455
+ const promptText = partToString(request3);
359456
+ const response = await messageBus.request({
359457
+ type: MessageBusType.HOOK_EXECUTION_REQUEST,
359458
+ eventName: "AfterAgent",
359459
+ input: {
359460
+ prompt: promptText,
359461
+ prompt_response: responseText,
359462
+ stop_hook_active: false
359463
+ }
359464
+ }, MessageBusType.HOOK_EXECUTION_RESPONSE);
359465
+ return response.output ? createHookOutput("AfterAgent", response.output) : void 0;
359466
+ } catch (error) {
359467
+ debugLogger.warn(`AfterAgent hook failed: ${error}`);
359468
+ return void 0;
359469
+ }
359470
+ }
359471
+
358869
359472
  // packages/core/dist/src/core/client.js
358870
359473
  var MAX_TURNS = 100;
359474
+ function estimateTextOnlyLength(request3) {
359475
+ if (typeof request3 === "string") {
359476
+ return request3.length;
359477
+ }
359478
+ if (!Array.isArray(request3)) {
359479
+ return 0;
359480
+ }
359481
+ let textLength = 0;
359482
+ for (const part of request3) {
359483
+ if (typeof part === "string") {
359484
+ textLength += part.length;
359485
+ } else if (typeof part === "object" && part !== null && "text" in part && part.text) {
359486
+ textLength += part.text.length;
359487
+ }
359488
+ }
359489
+ return textLength;
359490
+ }
358871
359491
  var GeminiClient = class {
358872
359492
  config;
358873
359493
  chat;
@@ -359114,6 +359734,25 @@ var GeminiClient = class {
359114
359734
  return getEffectiveModel(this.config.isInFallbackMode(), configModel, this.config.getPreviewFeatures());
359115
359735
  }
359116
359736
  async *sendMessageStream(request3, signal, prompt_id, turns = MAX_TURNS, isInvalidStreamRetry = false) {
359737
+ const hooksEnabled = this.config.getEnableHooks();
359738
+ const messageBus = this.config.getMessageBus();
359739
+ if (hooksEnabled && messageBus) {
359740
+ const hookOutput = await fireBeforeAgentHook(messageBus, request3);
359741
+ if (hookOutput?.isBlockingDecision() || hookOutput?.shouldStopExecution()) {
359742
+ yield {
359743
+ type: GeminiEventType.Error,
359744
+ value: {
359745
+ error: new Error(`BeforeAgent hook blocked processing: ${hookOutput.getEffectiveReason()}`)
359746
+ }
359747
+ };
359748
+ return new Turn(this.getChat(), prompt_id);
359749
+ }
359750
+ const additionalContext = hookOutput?.getAdditionalContext();
359751
+ if (additionalContext) {
359752
+ const requestArray = Array.isArray(request3) ? request3 : [request3];
359753
+ request3 = [...requestArray, { text: additionalContext }];
359754
+ }
359755
+ }
359117
359756
  if (this.lastPromptId !== prompt_id) {
359118
359757
  this.loopDetector.reset(prompt_id);
359119
359758
  this.lastPromptId = prompt_id;
@@ -359129,7 +359768,7 @@ var GeminiClient = class {
359129
359768
  return new Turn(this.getChat(), prompt_id);
359130
359769
  }
359131
359770
  const modelForLimitCheck = this._getEffectiveModelForCurrentTurn();
359132
- const estimatedRequestTokenCount = Math.floor(JSON.stringify(request3).length / 4);
359771
+ const estimatedRequestTokenCount = Math.floor(estimateTextOnlyLength(request3) / 4);
359133
359772
  const remainingTokenCount = tokenLimit(modelForLimitCheck) - this.getChat().getLastPromptTokenCount();
359134
359773
  if (estimatedRequestTokenCount > remainingTokenCount * 0.95) {
359135
359774
  yield {
@@ -359222,7 +359861,16 @@ var GeminiClient = class {
359222
359861
  logNextSpeakerCheck(this.config, new NextSpeakerCheckEvent(prompt_id, turn.finishReason?.toString() || "", nextSpeakerCheck?.next_speaker || ""));
359223
359862
  if (nextSpeakerCheck?.next_speaker === "model") {
359224
359863
  const nextRequest = [{ text: "Please continue." }];
359225
- yield* this.sendMessageStream(nextRequest, signal, prompt_id, boundedTurns - 1);
359864
+ return yield* this.sendMessageStream(nextRequest, signal, prompt_id, boundedTurns - 1);
359865
+ }
359866
+ }
359867
+ if (hooksEnabled && messageBus) {
359868
+ const responseText = turn.getResponseText() || "[no response text]";
359869
+ const hookOutput = await fireAfterAgentHook(messageBus, request3, responseText);
359870
+ if (hookOutput?.isBlockingDecision() || hookOutput?.shouldStopExecution()) {
359871
+ const continueReason = hookOutput.getEffectiveReason();
359872
+ const continueRequest = [{ text: continueReason }];
359873
+ yield* this.sendMessageStream(continueRequest, signal, prompt_id, boundedTurns - 1);
359226
359874
  }
359227
359875
  }
359228
359876
  return turn;
@@ -364822,6 +365470,31 @@ var DEFAULT_MODEL_CONFIGS = {
364822
365470
  "next-speaker-checker": {
364823
365471
  extends: "gemini-2.5-flash-base",
364824
365472
  modelConfig: {}
365473
+ },
365474
+ "chat-compression-3-pro": {
365475
+ modelConfig: {
365476
+ model: "gemini-3-pro-preview"
365477
+ }
365478
+ },
365479
+ "chat-compression-2.5-pro": {
365480
+ modelConfig: {
365481
+ model: "gemini-2.5-pro"
365482
+ }
365483
+ },
365484
+ "chat-compression-2.5-flash": {
365485
+ modelConfig: {
365486
+ model: "gemini-2.5-flash"
365487
+ }
365488
+ },
365489
+ "chat-compression-2.5-flash-lite": {
365490
+ modelConfig: {
365491
+ model: "gemini-2.5-flash-lite"
365492
+ }
365493
+ },
365494
+ "chat-compression-default": {
365495
+ modelConfig: {
365496
+ model: "gemini-2.5-pro"
365497
+ }
364825
365498
  }
364826
365499
  }
364827
365500
  };
@@ -364973,6 +365646,7 @@ var WorkspaceContext = class {
364973
365646
  };
364974
365647
 
364975
365648
  // packages/core/dist/src/confirmation-bus/message-bus.js
365649
+ import { randomUUID as randomUUID6 } from "node:crypto";
364976
365650
  import { EventEmitter as EventEmitter10 } from "node:events";
364977
365651
  var MessageBus = class extends EventEmitter10 {
364978
365652
  policyEngine;
@@ -365030,6 +365704,27 @@ var MessageBus = class extends EventEmitter10 {
365030
365704
  default:
365031
365705
  throw new Error(`Unknown policy decision: ${decision}`);
365032
365706
  }
365707
+ } else if (message.type === MessageBusType.HOOK_EXECUTION_REQUEST) {
365708
+ const hookRequest = message;
365709
+ const decision = await this.policyEngine.checkHook(hookRequest);
365710
+ const effectiveDecision = decision === PolicyDecision.ALLOW ? "allow" : "deny";
365711
+ this.emitMessage({
365712
+ type: MessageBusType.HOOK_POLICY_DECISION,
365713
+ eventName: hookRequest.eventName,
365714
+ hookSource: getHookSource(hookRequest.input),
365715
+ decision: effectiveDecision,
365716
+ reason: decision !== PolicyDecision.ALLOW ? "Hook execution denied by policy" : void 0
365717
+ });
365718
+ if (decision === PolicyDecision.ALLOW) {
365719
+ this.emitMessage(message);
365720
+ } else {
365721
+ this.emitMessage({
365722
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
365723
+ correlationId: hookRequest.correlationId,
365724
+ success: false,
365725
+ error: new Error("Hook execution denied by policy")
365726
+ });
365727
+ }
365033
365728
  } else {
365034
365729
  this.emitMessage(message);
365035
365730
  }
@@ -365043,6 +365738,32 @@ var MessageBus = class extends EventEmitter10 {
365043
365738
  unsubscribe(type, listener) {
365044
365739
  this.off(type, listener);
365045
365740
  }
365741
+ /**
365742
+ * Request-response pattern: Publish a message and wait for a correlated response
365743
+ * This enables synchronous-style communication over the async MessageBus
365744
+ * The correlation ID is generated internally and added to the request
365745
+ */
365746
+ async request(request3, responseType, timeoutMs = 6e4) {
365747
+ const correlationId = randomUUID6();
365748
+ return new Promise((resolve14, reject) => {
365749
+ const timeoutId = setTimeout(() => {
365750
+ cleanup();
365751
+ reject(new Error(`Request timed out waiting for ${responseType}`));
365752
+ }, timeoutMs);
365753
+ const cleanup = () => {
365754
+ clearTimeout(timeoutId);
365755
+ this.unsubscribe(responseType, responseHandler);
365756
+ };
365757
+ const responseHandler = (response) => {
365758
+ if ("correlationId" in response && response.correlationId === correlationId) {
365759
+ cleanup();
365760
+ resolve14(response);
365761
+ }
365762
+ };
365763
+ this.subscribe(responseType, responseHandler);
365764
+ this.publish({ ...request3, correlationId });
365765
+ });
365766
+ }
365046
365767
  };
365047
365768
 
365048
365769
  // packages/core/dist/src/policy/stable-stringify.js
@@ -365136,18 +365857,31 @@ function ruleMatches(rule, toolCall, stringifiedArgs, serverName) {
365136
365857
  }
365137
365858
  return true;
365138
365859
  }
365860
+ function hookCheckerMatches(rule, context2) {
365861
+ if (rule.eventName && rule.eventName !== context2.eventName) {
365862
+ return false;
365863
+ }
365864
+ if (rule.hookSource && rule.hookSource !== context2.hookSource) {
365865
+ return false;
365866
+ }
365867
+ return true;
365868
+ }
365139
365869
  var PolicyEngine = class {
365140
365870
  rules;
365141
365871
  checkers;
365872
+ hookCheckers;
365142
365873
  defaultDecision;
365143
365874
  nonInteractive;
365144
365875
  checkerRunner;
365876
+ allowHooks;
365145
365877
  constructor(config2 = {}, checkerRunner) {
365146
365878
  this.rules = (config2.rules ?? []).sort((a2, b) => (b.priority ?? 0) - (a2.priority ?? 0));
365147
365879
  this.checkers = (config2.checkers ?? []).sort((a2, b) => (b.priority ?? 0) - (a2.priority ?? 0));
365880
+ this.hookCheckers = (config2.hookCheckers ?? []).sort((a2, b) => (b.priority ?? 0) - (a2.priority ?? 0));
365148
365881
  this.defaultDecision = config2.defaultDecision ?? PolicyDecision.ASK_USER;
365149
365882
  this.nonInteractive = config2.nonInteractive ?? false;
365150
365883
  this.checkerRunner = checkerRunner;
365884
+ this.allowHooks = config2.allowHooks ?? true;
365151
365885
  }
365152
365886
  /**
365153
365887
  * Check if a tool call is allowed based on the configured policies.
@@ -365230,6 +365964,64 @@ var PolicyEngine = class {
365230
365964
  getCheckers() {
365231
365965
  return this.checkers;
365232
365966
  }
365967
+ /**
365968
+ * Add a new hook checker to the policy engine.
365969
+ */
365970
+ addHookChecker(checker) {
365971
+ this.hookCheckers.push(checker);
365972
+ this.hookCheckers.sort((a2, b) => (b.priority ?? 0) - (a2.priority ?? 0));
365973
+ }
365974
+ /**
365975
+ * Get all current hook checkers.
365976
+ */
365977
+ getHookCheckers() {
365978
+ return this.hookCheckers;
365979
+ }
365980
+ /**
365981
+ * Check if a hook execution is allowed based on the configured policies.
365982
+ * Runs hook-specific safety checkers if configured.
365983
+ */
365984
+ async checkHook(request3) {
365985
+ if (!this.allowHooks) {
365986
+ return PolicyDecision.DENY;
365987
+ }
365988
+ const context2 = "input" in request3 ? {
365989
+ eventName: request3.eventName,
365990
+ hookSource: getHookSource(request3.input),
365991
+ trustedFolder: typeof request3.input["trusted_folder"] === "boolean" ? request3.input["trusted_folder"] : void 0
365992
+ } : request3;
365993
+ if (context2.trustedFolder === false && context2.hookSource === "project") {
365994
+ return PolicyDecision.DENY;
365995
+ }
365996
+ if (this.checkerRunner && this.hookCheckers.length > 0) {
365997
+ for (const checkerRule of this.hookCheckers) {
365998
+ if (hookCheckerMatches(checkerRule, context2)) {
365999
+ debugLogger.debug(`[PolicyEngine.checkHook] Running hook checker: ${checkerRule.checker.name} for event: ${context2.eventName}`);
366000
+ try {
366001
+ const syntheticCall = {
366002
+ name: `hook:${context2.eventName}`,
366003
+ args: {
366004
+ hookSource: context2.hookSource,
366005
+ trustedFolder: context2.trustedFolder
366006
+ }
366007
+ };
366008
+ const result = await this.checkerRunner.runChecker(syntheticCall, checkerRule.checker);
366009
+ if (result.decision === SafetyCheckDecision.DENY) {
366010
+ debugLogger.debug(`[PolicyEngine.checkHook] Hook checker denied: ${result.reason}`);
366011
+ return PolicyDecision.DENY;
366012
+ } else if (result.decision === SafetyCheckDecision.ASK_USER) {
366013
+ debugLogger.debug(`[PolicyEngine.checkHook] Hook checker requested ASK_USER: ${result.reason}`);
366014
+ return this.applyNonInteractiveMode(PolicyDecision.ASK_USER);
366015
+ }
366016
+ } catch (error) {
366017
+ debugLogger.debug(`[PolicyEngine.checkHook] Hook checker failed: ${error}`);
366018
+ return PolicyDecision.DENY;
366019
+ }
366020
+ }
366021
+ }
366022
+ }
366023
+ return PolicyDecision.ALLOW;
366024
+ }
365233
366025
  applyNonInteractiveMode(decision) {
365234
366026
  if (this.nonInteractive && decision === PolicyDecision.ASK_USER) {
365235
366027
  return PolicyDecision.DENY;
@@ -365238,6 +366030,1205 @@ var PolicyEngine = class {
365238
366030
  }
365239
366031
  };
365240
366032
 
366033
+ // packages/core/dist/src/hooks/hookRegistry.js
366034
+ var HookRegistryNotInitializedError = class extends Error {
366035
+ constructor(message = "Hook registry not initialized") {
366036
+ super(message);
366037
+ this.name = "HookRegistryNotInitializedError";
366038
+ }
366039
+ };
366040
+ var ConfigSource;
366041
+ (function(ConfigSource2) {
366042
+ ConfigSource2["Project"] = "project";
366043
+ ConfigSource2["User"] = "user";
366044
+ ConfigSource2["System"] = "system";
366045
+ ConfigSource2["Extensions"] = "extensions";
366046
+ })(ConfigSource || (ConfigSource = {}));
366047
+ var HookRegistry = class {
366048
+ config;
366049
+ entries = [];
366050
+ initialized = false;
366051
+ constructor(config2) {
366052
+ this.config = config2;
366053
+ }
366054
+ /**
366055
+ * Initialize the registry by processing hooks from config
366056
+ */
366057
+ async initialize() {
366058
+ if (this.initialized) {
366059
+ return;
366060
+ }
366061
+ this.entries = [];
366062
+ this.processHooksFromConfig();
366063
+ this.initialized = true;
366064
+ debugLogger.log(`Hook registry initialized with ${this.entries.length} hook entries`);
366065
+ }
366066
+ /**
366067
+ * Get all hook entries for a specific event
366068
+ */
366069
+ getHooksForEvent(eventName) {
366070
+ if (!this.initialized) {
366071
+ throw new HookRegistryNotInitializedError();
366072
+ }
366073
+ return this.entries.filter((entry) => entry.eventName === eventName && entry.enabled).sort((a2, b) => this.getSourcePriority(a2.source) - this.getSourcePriority(b.source));
366074
+ }
366075
+ /**
366076
+ * Get all registered hooks
366077
+ */
366078
+ getAllHooks() {
366079
+ if (!this.initialized) {
366080
+ throw new HookRegistryNotInitializedError();
366081
+ }
366082
+ return [...this.entries];
366083
+ }
366084
+ /**
366085
+ * Enable or disable a specific hook
366086
+ */
366087
+ setHookEnabled(hookName, enabled) {
366088
+ const updated = this.entries.filter((entry) => {
366089
+ const name4 = this.getHookName(entry);
366090
+ if (name4 === hookName) {
366091
+ entry.enabled = enabled;
366092
+ return true;
366093
+ }
366094
+ return false;
366095
+ });
366096
+ if (updated.length > 0) {
366097
+ debugLogger.log(`${enabled ? "Enabled" : "Disabled"} ${updated.length} hook(s) matching "${hookName}"`);
366098
+ } else {
366099
+ debugLogger.warn(`No hooks found matching "${hookName}"`);
366100
+ }
366101
+ }
366102
+ /**
366103
+ * Get hook name for display purposes
366104
+ */
366105
+ getHookName(entry) {
366106
+ return entry.config.command || "unknown-command";
366107
+ }
366108
+ /**
366109
+ * Process hooks from the config that was already loaded by the CLI
366110
+ */
366111
+ processHooksFromConfig() {
366112
+ const configHooks = this.config.getHooks();
366113
+ if (configHooks) {
366114
+ this.processHooksConfiguration(configHooks, ConfigSource.Project);
366115
+ }
366116
+ const extensions = this.config.getExtensions() || [];
366117
+ for (const extension of extensions) {
366118
+ if (extension.isActive && extension.hooks) {
366119
+ this.processHooksConfiguration(extension.hooks, ConfigSource.Extensions);
366120
+ }
366121
+ }
366122
+ }
366123
+ /**
366124
+ * Process hooks configuration and add entries
366125
+ */
366126
+ processHooksConfiguration(hooksConfig, source) {
366127
+ for (const [eventName, definitions] of Object.entries(hooksConfig)) {
366128
+ if (!this.isValidEventName(eventName)) {
366129
+ debugLogger.warn(`Invalid hook event name: ${eventName}`);
366130
+ continue;
366131
+ }
366132
+ const typedEventName = eventName;
366133
+ if (!Array.isArray(definitions)) {
366134
+ debugLogger.warn(`Hook definitions for event "${eventName}" from source "${source}" is not an array. Skipping.`);
366135
+ continue;
366136
+ }
366137
+ for (const definition of definitions) {
366138
+ this.processHookDefinition(definition, typedEventName, source);
366139
+ }
366140
+ }
366141
+ }
366142
+ /**
366143
+ * Process a single hook definition
366144
+ */
366145
+ processHookDefinition(definition, eventName, source) {
366146
+ if (!definition || typeof definition !== "object" || !Array.isArray(definition.hooks)) {
366147
+ debugLogger.warn(`Discarding invalid hook definition for ${eventName} from ${source}:`, definition);
366148
+ return;
366149
+ }
366150
+ for (const hookConfig of definition.hooks) {
366151
+ if (hookConfig && typeof hookConfig === "object" && this.validateHookConfig(hookConfig, eventName, source)) {
366152
+ this.entries.push({
366153
+ config: hookConfig,
366154
+ source,
366155
+ eventName,
366156
+ matcher: definition.matcher,
366157
+ sequential: definition.sequential,
366158
+ enabled: true
366159
+ });
366160
+ } else {
366161
+ debugLogger.warn(`Discarding invalid hook configuration for ${eventName} from ${source}:`, hookConfig);
366162
+ }
366163
+ }
366164
+ }
366165
+ /**
366166
+ * Validate a hook configuration
366167
+ */
366168
+ validateHookConfig(config2, eventName, source) {
366169
+ if (!config2.type || !["command", "plugin"].includes(config2.type)) {
366170
+ debugLogger.warn(`Invalid hook ${eventName} from ${source} type: ${config2.type}`);
366171
+ return false;
366172
+ }
366173
+ if (config2.type === "command" && !config2.command) {
366174
+ debugLogger.warn(`Command hook ${eventName} from ${source} missing command field`);
366175
+ return false;
366176
+ }
366177
+ return true;
366178
+ }
366179
+ /**
366180
+ * Check if an event name is valid
366181
+ */
366182
+ isValidEventName(eventName) {
366183
+ const validEventNames = Object.values(HookEventName);
366184
+ return validEventNames.includes(eventName);
366185
+ }
366186
+ /**
366187
+ * Get source priority (lower number = higher priority)
366188
+ */
366189
+ getSourcePriority(source) {
366190
+ switch (source) {
366191
+ case ConfigSource.Project:
366192
+ return 1;
366193
+ case ConfigSource.User:
366194
+ return 2;
366195
+ case ConfigSource.System:
366196
+ return 3;
366197
+ case ConfigSource.Extensions:
366198
+ return 4;
366199
+ default:
366200
+ return 999;
366201
+ }
366202
+ }
366203
+ };
366204
+
366205
+ // packages/core/dist/src/hooks/hookRunner.js
366206
+ import { spawn as spawn9 } from "node:child_process";
366207
+ var DEFAULT_HOOK_TIMEOUT = 6e4;
366208
+ var EXIT_CODE_SUCCESS = 0;
366209
+ var EXIT_CODE_BLOCKING_ERROR = 2;
366210
+ var EXIT_CODE_NON_BLOCKING_ERROR = 1;
366211
+ var HookRunner = class {
366212
+ constructor() {
366213
+ }
366214
+ /**
366215
+ * Execute a single hook
366216
+ */
366217
+ async executeHook(hookConfig, eventName, input) {
366218
+ const startTime = Date.now();
366219
+ try {
366220
+ return await this.executeCommandHook(hookConfig, eventName, input, startTime);
366221
+ } catch (error) {
366222
+ const duration = Date.now() - startTime;
366223
+ const hookSource = hookConfig.command || "unknown";
366224
+ const errorMessage = `Hook execution failed for event '${eventName}' (source: ${hookSource}): ${error}`;
366225
+ debugLogger.warn(`Hook execution error (non-fatal): ${errorMessage}`);
366226
+ return {
366227
+ hookConfig,
366228
+ eventName,
366229
+ success: false,
366230
+ error: error instanceof Error ? error : new Error(errorMessage),
366231
+ duration
366232
+ };
366233
+ }
366234
+ }
366235
+ /**
366236
+ * Execute multiple hooks in parallel
366237
+ */
366238
+ async executeHooksParallel(hookConfigs, eventName, input) {
366239
+ const promises3 = hookConfigs.map((config2) => this.executeHook(config2, eventName, input));
366240
+ return await Promise.all(promises3);
366241
+ }
366242
+ /**
366243
+ * Execute multiple hooks sequentially
366244
+ */
366245
+ async executeHooksSequential(hookConfigs, eventName, input) {
366246
+ const results = [];
366247
+ let currentInput = input;
366248
+ for (const config2 of hookConfigs) {
366249
+ const result = await this.executeHook(config2, eventName, currentInput);
366250
+ results.push(result);
366251
+ if (result.success && result.output) {
366252
+ currentInput = this.applyHookOutputToInput(currentInput, result.output, eventName);
366253
+ }
366254
+ }
366255
+ return results;
366256
+ }
366257
+ /**
366258
+ * Apply hook output to modify input for the next hook in sequential execution
366259
+ */
366260
+ applyHookOutputToInput(originalInput, hookOutput, eventName) {
366261
+ const modifiedInput = { ...originalInput };
366262
+ if (hookOutput.hookSpecificOutput) {
366263
+ switch (eventName) {
366264
+ case HookEventName.BeforeAgent:
366265
+ if ("additionalContext" in hookOutput.hookSpecificOutput) {
366266
+ const additionalContext = hookOutput.hookSpecificOutput["additionalContext"];
366267
+ if (typeof additionalContext === "string" && "prompt" in modifiedInput) {
366268
+ modifiedInput.prompt += "\n\n" + additionalContext;
366269
+ }
366270
+ }
366271
+ break;
366272
+ case HookEventName.BeforeModel:
366273
+ if ("llm_request" in hookOutput.hookSpecificOutput) {
366274
+ const hookBeforeModelOutput = hookOutput;
366275
+ if (hookBeforeModelOutput.hookSpecificOutput?.llm_request && "llm_request" in modifiedInput) {
366276
+ const currentRequest = modifiedInput.llm_request;
366277
+ const partialRequest = hookBeforeModelOutput.hookSpecificOutput.llm_request;
366278
+ modifiedInput.llm_request = {
366279
+ ...currentRequest,
366280
+ ...partialRequest
366281
+ };
366282
+ }
366283
+ }
366284
+ break;
366285
+ default:
366286
+ break;
366287
+ }
366288
+ }
366289
+ return modifiedInput;
366290
+ }
366291
+ /**
366292
+ * Execute a command hook
366293
+ */
366294
+ async executeCommandHook(hookConfig, eventName, input, startTime) {
366295
+ const timeout = hookConfig.timeout ?? DEFAULT_HOOK_TIMEOUT;
366296
+ return new Promise((resolve14) => {
366297
+ if (!hookConfig.command) {
366298
+ const errorMessage = "Command hook missing command";
366299
+ debugLogger.warn(`Hook configuration error (non-fatal): ${errorMessage}`);
366300
+ resolve14({
366301
+ hookConfig,
366302
+ eventName,
366303
+ success: false,
366304
+ error: new Error(errorMessage),
366305
+ duration: Date.now() - startTime
366306
+ });
366307
+ return;
366308
+ }
366309
+ let stdout = "";
366310
+ let stderr = "";
366311
+ let timedOut2 = false;
366312
+ const command = this.expandCommand(hookConfig.command, input);
366313
+ const env2 = {
366314
+ ...process.env,
366315
+ GEMINI_PROJECT_DIR: input.cwd,
366316
+ CLAUDE_PROJECT_DIR: input.cwd
366317
+ // For compatibility
366318
+ };
366319
+ const child = spawn9(command, {
366320
+ env: env2,
366321
+ cwd: input.cwd,
366322
+ stdio: ["pipe", "pipe", "pipe"],
366323
+ shell: true
366324
+ });
366325
+ const timeoutHandle = setTimeout(() => {
366326
+ timedOut2 = true;
366327
+ child.kill("SIGTERM");
366328
+ setTimeout(() => {
366329
+ if (!child.killed) {
366330
+ child.kill("SIGKILL");
366331
+ }
366332
+ }, 5e3);
366333
+ }, timeout);
366334
+ if (child.stdin) {
366335
+ child.stdin.write(JSON.stringify(input));
366336
+ child.stdin.end();
366337
+ }
366338
+ child.stdout?.on("data", (data) => {
366339
+ stdout += data.toString();
366340
+ });
366341
+ child.stderr?.on("data", (data) => {
366342
+ stderr += data.toString();
366343
+ });
366344
+ child.on("close", (exitCode) => {
366345
+ clearTimeout(timeoutHandle);
366346
+ const duration = Date.now() - startTime;
366347
+ if (timedOut2) {
366348
+ resolve14({
366349
+ hookConfig,
366350
+ eventName,
366351
+ success: false,
366352
+ error: new Error(`Hook timed out after ${timeout}ms`),
366353
+ stdout,
366354
+ stderr,
366355
+ duration
366356
+ });
366357
+ return;
366358
+ }
366359
+ let output;
366360
+ if (exitCode === EXIT_CODE_SUCCESS && stdout.trim()) {
366361
+ try {
366362
+ let parsed = JSON.parse(stdout.trim());
366363
+ if (typeof parsed === "string") {
366364
+ parsed = JSON.parse(parsed);
366365
+ }
366366
+ if (parsed) {
366367
+ output = parsed;
366368
+ }
366369
+ } catch {
366370
+ output = this.convertPlainTextToHookOutput(stdout.trim(), exitCode);
366371
+ }
366372
+ } else if (exitCode !== EXIT_CODE_SUCCESS && stderr.trim()) {
366373
+ output = this.convertPlainTextToHookOutput(stderr.trim(), exitCode || EXIT_CODE_NON_BLOCKING_ERROR);
366374
+ }
366375
+ resolve14({
366376
+ hookConfig,
366377
+ eventName,
366378
+ success: exitCode === EXIT_CODE_SUCCESS,
366379
+ output,
366380
+ stdout,
366381
+ stderr,
366382
+ exitCode: exitCode || EXIT_CODE_SUCCESS,
366383
+ duration
366384
+ });
366385
+ });
366386
+ child.on("error", (error) => {
366387
+ clearTimeout(timeoutHandle);
366388
+ const duration = Date.now() - startTime;
366389
+ resolve14({
366390
+ hookConfig,
366391
+ eventName,
366392
+ success: false,
366393
+ error,
366394
+ stdout,
366395
+ stderr,
366396
+ duration
366397
+ });
366398
+ });
366399
+ });
366400
+ }
366401
+ /**
366402
+ * Expand command with environment variables and input context
366403
+ */
366404
+ expandCommand(command, input) {
366405
+ return command.replace(/\$GEMINI_PROJECT_DIR/g, input.cwd).replace(/\$CLAUDE_PROJECT_DIR/g, input.cwd);
366406
+ }
366407
+ /**
366408
+ * Convert plain text output to structured HookOutput
366409
+ */
366410
+ convertPlainTextToHookOutput(text, exitCode) {
366411
+ if (exitCode === EXIT_CODE_SUCCESS) {
366412
+ return {
366413
+ decision: "allow",
366414
+ systemMessage: text
366415
+ };
366416
+ } else if (exitCode === EXIT_CODE_BLOCKING_ERROR) {
366417
+ return {
366418
+ decision: "deny",
366419
+ reason: text
366420
+ };
366421
+ } else {
366422
+ return {
366423
+ decision: "allow",
366424
+ systemMessage: `Warning: ${text}`
366425
+ };
366426
+ }
366427
+ }
366428
+ };
366429
+
366430
+ // packages/core/dist/src/hooks/hookAggregator.js
366431
+ var HookAggregator = class {
366432
+ /**
366433
+ * Aggregate results from multiple hook executions
366434
+ */
366435
+ aggregateResults(results, eventName) {
366436
+ const allOutputs = [];
366437
+ const errors = [];
366438
+ let totalDuration = 0;
366439
+ for (const result of results) {
366440
+ totalDuration += result.duration;
366441
+ if (result.error) {
366442
+ errors.push(result.error);
366443
+ }
366444
+ if (result.output) {
366445
+ allOutputs.push(result.output);
366446
+ }
366447
+ }
366448
+ const mergedOutput = this.mergeOutputs(allOutputs, eventName);
366449
+ const finalOutput = mergedOutput ? this.createSpecificHookOutput(mergedOutput, eventName) : void 0;
366450
+ return {
366451
+ success: errors.length === 0,
366452
+ finalOutput,
366453
+ allOutputs,
366454
+ errors,
366455
+ totalDuration
366456
+ };
366457
+ }
366458
+ /**
366459
+ * Merge hook outputs using event-specific strategies
366460
+ *
366461
+ * Note: We always use the merge logic even for single hooks to ensure
366462
+ * consistent default behaviors (e.g., default decision='allow' for OR logic)
366463
+ */
366464
+ mergeOutputs(outputs, eventName) {
366465
+ if (outputs.length === 0) {
366466
+ return void 0;
366467
+ }
366468
+ switch (eventName) {
366469
+ case HookEventName.BeforeTool:
366470
+ case HookEventName.AfterTool:
366471
+ case HookEventName.BeforeAgent:
366472
+ case HookEventName.AfterAgent:
366473
+ case HookEventName.SessionStart:
366474
+ return this.mergeWithOrDecision(outputs);
366475
+ case HookEventName.BeforeModel:
366476
+ case HookEventName.AfterModel:
366477
+ return this.mergeWithFieldReplacement(outputs);
366478
+ case HookEventName.BeforeToolSelection:
366479
+ return this.mergeToolSelectionOutputs(outputs);
366480
+ default:
366481
+ return this.mergeSimple(outputs);
366482
+ }
366483
+ }
366484
+ /**
366485
+ * Merge outputs with OR decision logic and message concatenation
366486
+ */
366487
+ mergeWithOrDecision(outputs) {
366488
+ const merged = {
366489
+ continue: true,
366490
+ suppressOutput: false
366491
+ };
366492
+ const messages = [];
366493
+ const reasons = [];
366494
+ const systemMessages = [];
366495
+ const additionalContexts = [];
366496
+ let hasBlockDecision = false;
366497
+ let hasContinueFalse = false;
366498
+ for (const output of outputs) {
366499
+ if (output.continue === false) {
366500
+ hasContinueFalse = true;
366501
+ merged.continue = false;
366502
+ if (output.stopReason) {
366503
+ messages.push(output.stopReason);
366504
+ }
366505
+ }
366506
+ const tempOutput = new DefaultHookOutput(output);
366507
+ if (tempOutput.isBlockingDecision()) {
366508
+ hasBlockDecision = true;
366509
+ merged.decision = output.decision;
366510
+ }
366511
+ if (output.reason) {
366512
+ reasons.push(output.reason);
366513
+ }
366514
+ if (output.systemMessage) {
366515
+ systemMessages.push(output.systemMessage);
366516
+ }
366517
+ if (output.suppressOutput) {
366518
+ merged.suppressOutput = true;
366519
+ }
366520
+ this.extractAdditionalContext(output, additionalContexts);
366521
+ }
366522
+ if (!hasBlockDecision && !hasContinueFalse) {
366523
+ merged.decision = "allow";
366524
+ }
366525
+ if (messages.length > 0) {
366526
+ merged.stopReason = messages.join("\n");
366527
+ }
366528
+ if (reasons.length > 0) {
366529
+ merged.reason = reasons.join("\n");
366530
+ }
366531
+ if (systemMessages.length > 0) {
366532
+ merged.systemMessage = systemMessages.join("\n");
366533
+ }
366534
+ if (additionalContexts.length > 0) {
366535
+ merged.hookSpecificOutput = {
366536
+ ...merged.hookSpecificOutput || {},
366537
+ additionalContext: additionalContexts.join("\n")
366538
+ };
366539
+ }
366540
+ return merged;
366541
+ }
366542
+ /**
366543
+ * Merge outputs with later fields replacing earlier fields
366544
+ */
366545
+ mergeWithFieldReplacement(outputs) {
366546
+ let merged = {};
366547
+ for (const output of outputs) {
366548
+ merged = {
366549
+ ...merged,
366550
+ ...output,
366551
+ hookSpecificOutput: {
366552
+ ...merged.hookSpecificOutput,
366553
+ ...output.hookSpecificOutput
366554
+ }
366555
+ };
366556
+ }
366557
+ return merged;
366558
+ }
366559
+ /**
366560
+ * Merge tool selection outputs with specific logic for tool config
366561
+ *
366562
+ * Tool Selection Strategy:
366563
+ * - The intent is to provide a UNION of tools from all hooks
366564
+ * - If any hook specifies NONE mode, no tools are available (most restrictive wins)
366565
+ * - If any hook specifies ANY mode (and no NONE), ANY mode is used
366566
+ * - Otherwise AUTO mode is used
366567
+ * - Function names are collected from all hooks and sorted for deterministic caching
366568
+ *
366569
+ * This means hooks can only add/enable tools, not filter them out individually.
366570
+ * If one hook restricts and another re-enables, the union takes the re-enabled tool.
366571
+ */
366572
+ mergeToolSelectionOutputs(outputs) {
366573
+ const merged = {};
366574
+ const allFunctionNames = /* @__PURE__ */ new Set();
366575
+ let hasNoneMode = false;
366576
+ let hasAnyMode = false;
366577
+ for (const output of outputs) {
366578
+ const toolConfig = output.hookSpecificOutput?.toolConfig;
366579
+ if (!toolConfig) {
366580
+ continue;
366581
+ }
366582
+ if (toolConfig.mode === "NONE") {
366583
+ hasNoneMode = true;
366584
+ } else if (toolConfig.mode === "ANY") {
366585
+ hasAnyMode = true;
366586
+ }
366587
+ if (toolConfig.allowedFunctionNames) {
366588
+ for (const name4 of toolConfig.allowedFunctionNames) {
366589
+ allFunctionNames.add(name4);
366590
+ }
366591
+ }
366592
+ }
366593
+ let finalMode;
366594
+ let finalFunctionNames = [];
366595
+ if (hasNoneMode) {
366596
+ finalMode = FunctionCallingConfigMode.NONE;
366597
+ finalFunctionNames = [];
366598
+ } else if (hasAnyMode) {
366599
+ finalMode = FunctionCallingConfigMode.ANY;
366600
+ finalFunctionNames = Array.from(allFunctionNames).sort();
366601
+ } else {
366602
+ finalMode = FunctionCallingConfigMode.AUTO;
366603
+ finalFunctionNames = Array.from(allFunctionNames).sort();
366604
+ }
366605
+ merged.hookSpecificOutput = {
366606
+ hookEventName: "BeforeToolSelection",
366607
+ toolConfig: {
366608
+ mode: finalMode,
366609
+ allowedFunctionNames: finalFunctionNames
366610
+ }
366611
+ };
366612
+ return merged;
366613
+ }
366614
+ /**
366615
+ * Simple merge for events without special logic
366616
+ */
366617
+ mergeSimple(outputs) {
366618
+ let merged = {};
366619
+ for (const output of outputs) {
366620
+ merged = { ...merged, ...output };
366621
+ }
366622
+ return merged;
366623
+ }
366624
+ /**
366625
+ * Create the appropriate specific hook output class based on event type
366626
+ */
366627
+ createSpecificHookOutput(output, eventName) {
366628
+ switch (eventName) {
366629
+ case HookEventName.BeforeTool:
366630
+ return new BeforeToolHookOutput(output);
366631
+ case HookEventName.BeforeModel:
366632
+ return new BeforeModelHookOutput(output);
366633
+ case HookEventName.BeforeToolSelection:
366634
+ return new BeforeToolSelectionHookOutput(output);
366635
+ case HookEventName.AfterModel:
366636
+ return new AfterModelHookOutput(output);
366637
+ default:
366638
+ return new DefaultHookOutput(output);
366639
+ }
366640
+ }
366641
+ /**
366642
+ * Extract additional context from hook-specific outputs
366643
+ */
366644
+ extractAdditionalContext(output, contexts) {
366645
+ const specific = output.hookSpecificOutput;
366646
+ if (!specific) {
366647
+ return;
366648
+ }
366649
+ if ("additionalContext" in specific && typeof specific["additionalContext"] === "string") {
366650
+ contexts.push(specific["additionalContext"]);
366651
+ }
366652
+ }
366653
+ };
366654
+
366655
+ // packages/core/dist/src/hooks/hookPlanner.js
366656
+ var HookPlanner = class {
366657
+ hookRegistry;
366658
+ constructor(hookRegistry) {
366659
+ this.hookRegistry = hookRegistry;
366660
+ }
366661
+ /**
366662
+ * Create execution plan for a hook event
366663
+ */
366664
+ createExecutionPlan(eventName, context2) {
366665
+ const hookEntries = this.hookRegistry.getHooksForEvent(eventName);
366666
+ if (hookEntries.length === 0) {
366667
+ return null;
366668
+ }
366669
+ const matchingEntries = hookEntries.filter((entry) => this.matchesContext(entry, context2));
366670
+ if (matchingEntries.length === 0) {
366671
+ return null;
366672
+ }
366673
+ const deduplicatedEntries = this.deduplicateHooks(matchingEntries);
366674
+ const hookConfigs = deduplicatedEntries.map((entry) => entry.config);
366675
+ const sequential = deduplicatedEntries.some((entry) => entry.sequential === true);
366676
+ const plan = {
366677
+ eventName,
366678
+ hookConfigs,
366679
+ sequential
366680
+ };
366681
+ debugLogger.debug(`Created execution plan for ${eventName}: ${hookConfigs.length} hook(s) to execute ${sequential ? "sequentially" : "in parallel"}`);
366682
+ return plan;
366683
+ }
366684
+ /**
366685
+ * Check if a hook entry matches the given context
366686
+ */
366687
+ matchesContext(entry, context2) {
366688
+ if (!entry.matcher || !context2) {
366689
+ return true;
366690
+ }
366691
+ const matcher = entry.matcher.trim();
366692
+ if (matcher === "" || matcher === "*") {
366693
+ return true;
366694
+ }
366695
+ if (context2.toolName) {
366696
+ return this.matchesToolName(matcher, context2.toolName);
366697
+ }
366698
+ if (context2.trigger) {
366699
+ return this.matchesTrigger(matcher, context2.trigger);
366700
+ }
366701
+ return true;
366702
+ }
366703
+ /**
366704
+ * Match tool name against matcher pattern
366705
+ */
366706
+ matchesToolName(matcher, toolName) {
366707
+ try {
366708
+ const regex2 = new RegExp(matcher);
366709
+ return regex2.test(toolName);
366710
+ } catch {
366711
+ return matcher === toolName;
366712
+ }
366713
+ }
366714
+ /**
366715
+ * Match trigger/source against matcher pattern
366716
+ */
366717
+ matchesTrigger(matcher, trigger) {
366718
+ return matcher === trigger;
366719
+ }
366720
+ /**
366721
+ * Deduplicate identical hook configurations
366722
+ */
366723
+ deduplicateHooks(entries2) {
366724
+ const seen = /* @__PURE__ */ new Set();
366725
+ const deduplicated = [];
366726
+ for (const entry of entries2) {
366727
+ const key = this.getHookKey(entry);
366728
+ if (!seen.has(key)) {
366729
+ seen.add(key);
366730
+ deduplicated.push(entry);
366731
+ } else {
366732
+ debugLogger.debug(`Deduplicated hook: ${key}`);
366733
+ }
366734
+ }
366735
+ return deduplicated;
366736
+ }
366737
+ /**
366738
+ * Generate a unique key for a hook entry
366739
+ */
366740
+ getHookKey(entry) {
366741
+ return `command:${entry.config.command}`;
366742
+ }
366743
+ };
366744
+
366745
+ // packages/core/dist/src/hooks/hookEventHandler.js
366746
+ function isObject3(value) {
366747
+ return typeof value === "object" && value !== null;
366748
+ }
366749
+ function validateBeforeToolInput(input) {
366750
+ const toolName = input["tool_name"];
366751
+ const toolInput = input["tool_input"];
366752
+ if (typeof toolName !== "string") {
366753
+ throw new Error("Invalid input for BeforeTool hook event: tool_name must be a string");
366754
+ }
366755
+ if (!isObject3(toolInput)) {
366756
+ throw new Error("Invalid input for BeforeTool hook event: tool_input must be an object");
366757
+ }
366758
+ return { toolName, toolInput };
366759
+ }
366760
+ function validateAfterToolInput(input) {
366761
+ const toolName = input["tool_name"];
366762
+ const toolInput = input["tool_input"];
366763
+ const toolResponse = input["tool_response"];
366764
+ if (typeof toolName !== "string") {
366765
+ throw new Error("Invalid input for AfterTool hook event: tool_name must be a string");
366766
+ }
366767
+ if (!isObject3(toolInput)) {
366768
+ throw new Error("Invalid input for AfterTool hook event: tool_input must be an object");
366769
+ }
366770
+ if (!isObject3(toolResponse)) {
366771
+ throw new Error("Invalid input for AfterTool hook event: tool_response must be an object");
366772
+ }
366773
+ return { toolName, toolInput, toolResponse };
366774
+ }
366775
+ function validateBeforeAgentInput(input) {
366776
+ const prompt = input["prompt"];
366777
+ if (typeof prompt !== "string") {
366778
+ throw new Error("Invalid input for BeforeAgent hook event: prompt must be a string");
366779
+ }
366780
+ return { prompt };
366781
+ }
366782
+ function validateAfterAgentInput(input) {
366783
+ const prompt = input["prompt"];
366784
+ const promptResponse = input["prompt_response"];
366785
+ const stopHookActive = input["stop_hook_active"];
366786
+ if (typeof prompt !== "string") {
366787
+ throw new Error("Invalid input for AfterAgent hook event: prompt must be a string");
366788
+ }
366789
+ if (typeof promptResponse !== "string") {
366790
+ throw new Error("Invalid input for AfterAgent hook event: prompt_response must be a string");
366791
+ }
366792
+ return {
366793
+ prompt,
366794
+ promptResponse,
366795
+ stopHookActive: typeof stopHookActive === "boolean" ? stopHookActive : false
366796
+ };
366797
+ }
366798
+ function validateModelInput(input, eventName) {
366799
+ const llmRequest = input["llm_request"];
366800
+ if (!isObject3(llmRequest)) {
366801
+ throw new Error(`Invalid input for ${eventName} hook event: llm_request must be an object`);
366802
+ }
366803
+ return { llmRequest };
366804
+ }
366805
+ function validateAfterModelInput(input) {
366806
+ const llmRequest = input["llm_request"];
366807
+ const llmResponse = input["llm_response"];
366808
+ if (!isObject3(llmRequest)) {
366809
+ throw new Error("Invalid input for AfterModel hook event: llm_request must be an object");
366810
+ }
366811
+ if (!isObject3(llmResponse)) {
366812
+ throw new Error("Invalid input for AfterModel hook event: llm_response must be an object");
366813
+ }
366814
+ return {
366815
+ llmRequest,
366816
+ llmResponse
366817
+ };
366818
+ }
366819
+ function validateNotificationInput(input) {
366820
+ const notificationType = input["notification_type"];
366821
+ const message = input["message"];
366822
+ const details = input["details"];
366823
+ if (typeof notificationType !== "string") {
366824
+ throw new Error("Invalid input for Notification hook event: notification_type must be a string");
366825
+ }
366826
+ if (typeof message !== "string") {
366827
+ throw new Error("Invalid input for Notification hook event: message must be a string");
366828
+ }
366829
+ if (!isObject3(details)) {
366830
+ throw new Error("Invalid input for Notification hook event: details must be an object");
366831
+ }
366832
+ return {
366833
+ notificationType,
366834
+ message,
366835
+ details
366836
+ };
366837
+ }
366838
+ var HookEventHandler = class {
366839
+ config;
366840
+ hookPlanner;
366841
+ hookRunner;
366842
+ hookAggregator;
366843
+ messageBus;
366844
+ constructor(config2, logger6, hookPlanner, hookRunner, hookAggregator, messageBus) {
366845
+ this.config = config2;
366846
+ this.hookPlanner = hookPlanner;
366847
+ this.hookRunner = hookRunner;
366848
+ this.hookAggregator = hookAggregator;
366849
+ this.messageBus = messageBus;
366850
+ if (this.messageBus) {
366851
+ this.messageBus.subscribe(MessageBusType.HOOK_EXECUTION_REQUEST, (request3) => this.handleHookExecutionRequest(request3));
366852
+ }
366853
+ }
366854
+ /**
366855
+ * Fire a BeforeTool event
366856
+ * Called by handleHookExecutionRequest - executes hooks directly
366857
+ */
366858
+ async fireBeforeToolEvent(toolName, toolInput) {
366859
+ const input = {
366860
+ ...this.createBaseInput(HookEventName.BeforeTool),
366861
+ tool_name: toolName,
366862
+ tool_input: toolInput
366863
+ };
366864
+ const context2 = { toolName };
366865
+ return await this.executeHooks(HookEventName.BeforeTool, input, context2);
366866
+ }
366867
+ /**
366868
+ * Fire an AfterTool event
366869
+ * Called by handleHookExecutionRequest - executes hooks directly
366870
+ */
366871
+ async fireAfterToolEvent(toolName, toolInput, toolResponse) {
366872
+ const input = {
366873
+ ...this.createBaseInput(HookEventName.AfterTool),
366874
+ tool_name: toolName,
366875
+ tool_input: toolInput,
366876
+ tool_response: toolResponse
366877
+ };
366878
+ const context2 = { toolName };
366879
+ return await this.executeHooks(HookEventName.AfterTool, input, context2);
366880
+ }
366881
+ /**
366882
+ * Fire a BeforeAgent event
366883
+ * Called by handleHookExecutionRequest - executes hooks directly
366884
+ */
366885
+ async fireBeforeAgentEvent(prompt) {
366886
+ const input = {
366887
+ ...this.createBaseInput(HookEventName.BeforeAgent),
366888
+ prompt
366889
+ };
366890
+ return await this.executeHooks(HookEventName.BeforeAgent, input);
366891
+ }
366892
+ /**
366893
+ * Fire a Notification event
366894
+ */
366895
+ async fireNotificationEvent(type, message, details) {
366896
+ const input = {
366897
+ ...this.createBaseInput(HookEventName.Notification),
366898
+ notification_type: type,
366899
+ message,
366900
+ details
366901
+ };
366902
+ return await this.executeHooks(HookEventName.Notification, input);
366903
+ }
366904
+ /**
366905
+ * Fire an AfterAgent event
366906
+ * Called by handleHookExecutionRequest - executes hooks directly
366907
+ */
366908
+ async fireAfterAgentEvent(prompt, promptResponse, stopHookActive = false) {
366909
+ const input = {
366910
+ ...this.createBaseInput(HookEventName.AfterAgent),
366911
+ prompt,
366912
+ prompt_response: promptResponse,
366913
+ stop_hook_active: stopHookActive
366914
+ };
366915
+ return await this.executeHooks(HookEventName.AfterAgent, input);
366916
+ }
366917
+ /**
366918
+ * Fire a SessionStart event
366919
+ */
366920
+ async fireSessionStartEvent(source) {
366921
+ const input = {
366922
+ ...this.createBaseInput(HookEventName.SessionStart),
366923
+ source
366924
+ };
366925
+ const context2 = { trigger: source };
366926
+ return await this.executeHooks(HookEventName.SessionStart, input, context2);
366927
+ }
366928
+ /**
366929
+ * Fire a SessionEnd event
366930
+ */
366931
+ async fireSessionEndEvent(reason) {
366932
+ const input = {
366933
+ ...this.createBaseInput(HookEventName.SessionEnd),
366934
+ reason
366935
+ };
366936
+ const context2 = { trigger: reason };
366937
+ return await this.executeHooks(HookEventName.SessionEnd, input, context2);
366938
+ }
366939
+ /**
366940
+ * Fire a PreCompress event
366941
+ */
366942
+ async firePreCompressEvent(trigger) {
366943
+ const input = {
366944
+ ...this.createBaseInput(HookEventName.PreCompress),
366945
+ trigger
366946
+ };
366947
+ const context2 = { trigger };
366948
+ return await this.executeHooks(HookEventName.PreCompress, input, context2);
366949
+ }
366950
+ /**
366951
+ * Fire a BeforeModel event
366952
+ * Called by handleHookExecutionRequest - executes hooks directly
366953
+ */
366954
+ async fireBeforeModelEvent(llmRequest) {
366955
+ const input = {
366956
+ ...this.createBaseInput(HookEventName.BeforeModel),
366957
+ llm_request: defaultHookTranslator.toHookLLMRequest(llmRequest)
366958
+ };
366959
+ return await this.executeHooks(HookEventName.BeforeModel, input);
366960
+ }
366961
+ /**
366962
+ * Fire an AfterModel event
366963
+ * Called by handleHookExecutionRequest - executes hooks directly
366964
+ */
366965
+ async fireAfterModelEvent(llmRequest, llmResponse) {
366966
+ const input = {
366967
+ ...this.createBaseInput(HookEventName.AfterModel),
366968
+ llm_request: defaultHookTranslator.toHookLLMRequest(llmRequest),
366969
+ llm_response: defaultHookTranslator.toHookLLMResponse(llmResponse)
366970
+ };
366971
+ return await this.executeHooks(HookEventName.AfterModel, input);
366972
+ }
366973
+ /**
366974
+ * Fire a BeforeToolSelection event
366975
+ * Called by handleHookExecutionRequest - executes hooks directly
366976
+ */
366977
+ async fireBeforeToolSelectionEvent(llmRequest) {
366978
+ const input = {
366979
+ ...this.createBaseInput(HookEventName.BeforeToolSelection),
366980
+ llm_request: defaultHookTranslator.toHookLLMRequest(llmRequest)
366981
+ };
366982
+ return await this.executeHooks(HookEventName.BeforeToolSelection, input);
366983
+ }
366984
+ /**
366985
+ * Execute hooks for a specific event (direct execution without MessageBus)
366986
+ * Used as fallback when MessageBus is not available
366987
+ */
366988
+ async executeHooks(eventName, input, context2) {
366989
+ try {
366990
+ const plan = this.hookPlanner.createExecutionPlan(eventName, context2);
366991
+ if (!plan || plan.hookConfigs.length === 0) {
366992
+ return {
366993
+ success: true,
366994
+ allOutputs: [],
366995
+ errors: [],
366996
+ totalDuration: 0
366997
+ };
366998
+ }
366999
+ const results = plan.sequential ? await this.hookRunner.executeHooksSequential(plan.hookConfigs, eventName, input) : await this.hookRunner.executeHooksParallel(plan.hookConfigs, eventName, input);
367000
+ const aggregated = this.hookAggregator.aggregateResults(results, eventName);
367001
+ this.processCommonHookOutputFields(aggregated);
367002
+ this.logHookExecution(eventName, input, results, aggregated);
367003
+ return aggregated;
367004
+ } catch (error) {
367005
+ debugLogger.error(`Hook event bus error for ${eventName}: ${error}`);
367006
+ return {
367007
+ success: false,
367008
+ allOutputs: [],
367009
+ errors: [error instanceof Error ? error : new Error(String(error))],
367010
+ totalDuration: 0
367011
+ };
367012
+ }
367013
+ }
367014
+ /**
367015
+ * Create base hook input with common fields
367016
+ */
367017
+ createBaseInput(eventName) {
367018
+ return {
367019
+ session_id: this.config.getSessionId(),
367020
+ transcript_path: "",
367021
+ // TODO: Implement transcript path when supported
367022
+ cwd: this.config.getWorkingDir(),
367023
+ hook_event_name: eventName,
367024
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
367025
+ };
367026
+ }
367027
+ /**
367028
+ * Log hook execution for observability
367029
+ */
367030
+ logHookExecution(eventName, input, results, aggregated) {
367031
+ const successCount = results.filter((r3) => r3.success).length;
367032
+ const errorCount = results.length - successCount;
367033
+ if (errorCount > 0) {
367034
+ debugLogger.warn(`Hook execution for ${eventName}: ${successCount} succeeded, ${errorCount} failed, total duration: ${aggregated.totalDuration}ms`);
367035
+ } else {
367036
+ debugLogger.debug(`Hook execution for ${eventName}: ${successCount} hooks executed successfully, total duration: ${aggregated.totalDuration}ms`);
367037
+ }
367038
+ for (const result of results) {
367039
+ const hookName = this.getHookNameFromResult(result);
367040
+ const hookType = this.getHookTypeFromResult(result);
367041
+ 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);
367042
+ logHookCall(this.config, hookCallEvent);
367043
+ }
367044
+ for (const error of aggregated.errors) {
367045
+ debugLogger.error(`Hook execution error: ${error.message}`);
367046
+ }
367047
+ }
367048
+ /**
367049
+ * Process common hook output fields centrally
367050
+ */
367051
+ processCommonHookOutputFields(aggregated) {
367052
+ if (!aggregated.finalOutput) {
367053
+ return;
367054
+ }
367055
+ const systemMessage = aggregated.finalOutput.systemMessage;
367056
+ if (systemMessage && !aggregated.finalOutput.suppressOutput) {
367057
+ debugLogger.warn(`Hook system message: ${systemMessage}`);
367058
+ }
367059
+ if (aggregated.finalOutput.shouldStopExecution()) {
367060
+ const stopReason = aggregated.finalOutput.getEffectiveReason();
367061
+ debugLogger.log(`Hook requested to stop execution: ${stopReason}`);
367062
+ }
367063
+ }
367064
+ /**
367065
+ * Get hook name from execution result for telemetry
367066
+ */
367067
+ getHookNameFromResult(result) {
367068
+ return result.hookConfig.command || "unknown-command";
367069
+ }
367070
+ /**
367071
+ * Get hook type from execution result for telemetry
367072
+ */
367073
+ getHookTypeFromResult(result) {
367074
+ return result.hookConfig.type;
367075
+ }
367076
+ /**
367077
+ * Handle hook execution requests from MessageBus
367078
+ * This method routes the request to the appropriate fire*Event method
367079
+ * and publishes the response back through MessageBus
367080
+ *
367081
+ * The request input only contains event-specific fields. This method adds
367082
+ * the common base fields (session_id, cwd, etc.) before routing.
367083
+ */
367084
+ async handleHookExecutionRequest(request3) {
367085
+ try {
367086
+ const enrichedInput = {
367087
+ ...this.createBaseInput(request3.eventName),
367088
+ ...request3.input
367089
+ };
367090
+ let result;
367091
+ switch (request3.eventName) {
367092
+ case HookEventName.BeforeTool: {
367093
+ const { toolName, toolInput } = validateBeforeToolInput(enrichedInput);
367094
+ result = await this.fireBeforeToolEvent(toolName, toolInput);
367095
+ break;
367096
+ }
367097
+ case HookEventName.AfterTool: {
367098
+ const { toolName, toolInput, toolResponse } = validateAfterToolInput(enrichedInput);
367099
+ result = await this.fireAfterToolEvent(toolName, toolInput, toolResponse);
367100
+ break;
367101
+ }
367102
+ case HookEventName.BeforeAgent: {
367103
+ const { prompt } = validateBeforeAgentInput(enrichedInput);
367104
+ result = await this.fireBeforeAgentEvent(prompt);
367105
+ break;
367106
+ }
367107
+ case HookEventName.AfterAgent: {
367108
+ const { prompt, promptResponse, stopHookActive } = validateAfterAgentInput(enrichedInput);
367109
+ result = await this.fireAfterAgentEvent(prompt, promptResponse, stopHookActive);
367110
+ break;
367111
+ }
367112
+ case HookEventName.BeforeModel: {
367113
+ const { llmRequest } = validateModelInput(enrichedInput, "BeforeModel");
367114
+ const translatedRequest = defaultHookTranslator.toHookLLMRequest(llmRequest);
367115
+ enrichedInput["llm_request"] = translatedRequest;
367116
+ result = await this.fireBeforeModelEvent(llmRequest);
367117
+ break;
367118
+ }
367119
+ case HookEventName.AfterModel: {
367120
+ const { llmRequest, llmResponse } = validateAfterModelInput(enrichedInput);
367121
+ const translatedRequest = defaultHookTranslator.toHookLLMRequest(llmRequest);
367122
+ const translatedResponse = defaultHookTranslator.toHookLLMResponse(llmResponse);
367123
+ enrichedInput["llm_request"] = translatedRequest;
367124
+ enrichedInput["llm_response"] = translatedResponse;
367125
+ result = await this.fireAfterModelEvent(llmRequest, llmResponse);
367126
+ break;
367127
+ }
367128
+ case HookEventName.BeforeToolSelection: {
367129
+ const { llmRequest } = validateModelInput(enrichedInput, "BeforeToolSelection");
367130
+ const translatedRequest = defaultHookTranslator.toHookLLMRequest(llmRequest);
367131
+ enrichedInput["llm_request"] = translatedRequest;
367132
+ result = await this.fireBeforeToolSelectionEvent(llmRequest);
367133
+ break;
367134
+ }
367135
+ case HookEventName.Notification: {
367136
+ const { notificationType, message, details } = validateNotificationInput(enrichedInput);
367137
+ result = await this.fireNotificationEvent(notificationType, message, details);
367138
+ break;
367139
+ }
367140
+ default:
367141
+ throw new Error(`Unsupported hook event: ${request3.eventName}`);
367142
+ }
367143
+ if (this.messageBus) {
367144
+ this.messageBus.publish({
367145
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
367146
+ correlationId: request3.correlationId,
367147
+ success: result.success,
367148
+ output: result.finalOutput
367149
+ });
367150
+ }
367151
+ } catch (error) {
367152
+ if (this.messageBus) {
367153
+ this.messageBus.publish({
367154
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
367155
+ correlationId: request3.correlationId,
367156
+ success: false,
367157
+ error: error instanceof Error ? error : new Error(String(error))
367158
+ });
367159
+ }
367160
+ }
367161
+ }
367162
+ };
367163
+
367164
+ // packages/core/dist/src/hooks/hookSystem.js
367165
+ var import_api_logs2 = __toESM(require_src21(), 1);
367166
+ var HookSystem = class {
367167
+ hookRegistry;
367168
+ hookRunner;
367169
+ hookAggregator;
367170
+ hookPlanner;
367171
+ hookEventHandler;
367172
+ initialized = false;
367173
+ constructor(config2) {
367174
+ const logger6 = import_api_logs2.logs.getLogger(SERVICE_NAME);
367175
+ const messageBus = config2.getMessageBus();
367176
+ this.hookRegistry = new HookRegistry(config2);
367177
+ this.hookRunner = new HookRunner();
367178
+ this.hookAggregator = new HookAggregator();
367179
+ this.hookPlanner = new HookPlanner(this.hookRegistry);
367180
+ this.hookEventHandler = new HookEventHandler(config2, logger6, this.hookPlanner, this.hookRunner, this.hookAggregator, messageBus);
367181
+ }
367182
+ /**
367183
+ * Initialize the hook system
367184
+ */
367185
+ async initialize() {
367186
+ if (this.initialized) {
367187
+ return;
367188
+ }
367189
+ await this.hookRegistry.initialize();
367190
+ this.initialized = true;
367191
+ debugLogger.debug("Hook system initialized successfully");
367192
+ }
367193
+ /**
367194
+ * Get the hook event bus for firing events
367195
+ */
367196
+ getEventHandler() {
367197
+ if (!this.initialized) {
367198
+ throw new Error("Hook system not initialized");
367199
+ }
367200
+ return this.hookEventHandler;
367201
+ }
367202
+ /**
367203
+ * Get hook registry for management operations
367204
+ */
367205
+ getRegistry() {
367206
+ return this.hookRegistry;
367207
+ }
367208
+ /**
367209
+ * Enable or disable a hook
367210
+ */
367211
+ setHookEnabled(hookName, enabled) {
367212
+ this.hookRegistry.setHookEnabled(hookName, enabled);
367213
+ }
367214
+ /**
367215
+ * Get all registered hooks for display/management
367216
+ */
367217
+ getAllHooks() {
367218
+ return this.hookRegistry.getAllHooks();
367219
+ }
367220
+ /**
367221
+ * Get hook system status for debugging
367222
+ */
367223
+ getStatus() {
367224
+ const allHooks = this.initialized ? this.hookRegistry.getAllHooks() : [];
367225
+ return {
367226
+ initialized: this.initialized,
367227
+ totalHooks: allHooks.length
367228
+ };
367229
+ }
367230
+ };
367231
+
365241
367232
  // packages/core/dist/src/agents/registry.js
365242
367233
  function getModelConfigAlias(definition) {
365243
367234
  return `${definition.name}-config`;
@@ -367676,7 +369667,7 @@ async function readPackageUp(options2) {
367676
369667
  async function getPackageJson(cwd) {
367677
369668
  const result = await readPackageUp({ cwd });
367678
369669
  if (!result) {
367679
- return;
369670
+ return void 0;
367680
369671
  }
367681
369672
  return result.packageJson;
367682
369673
  }
@@ -367738,7 +369729,7 @@ async function getClientMetadata() {
367738
369729
  clientMetadataPromise = (async () => ({
367739
369730
  ideName: "IDE_UNSPECIFIED",
367740
369731
  pluginType: "GEMINI",
367741
- ideVersion: "0.19.0-nightly.20251123.dadd606c0",
369732
+ ideVersion: "0.19.0-nightly.20251125.f6d97d448",
367742
369733
  platform: getPlatform(),
367743
369734
  updateChannel: await getReleaseChannel(__dirname5)
367744
369735
  }))();
@@ -373254,6 +375245,7 @@ var Config = class {
373254
375245
  hooks;
373255
375246
  experiments;
373256
375247
  experimentsPromise;
375248
+ hookSystem;
373257
375249
  previewModelFallbackMode = false;
373258
375250
  previewModelBypassMode = false;
373259
375251
  constructor(params) {
@@ -373413,6 +375405,10 @@ var Config = class {
373413
375405
  await this.mcpClientManager.startConfiguredMcpServers(),
373414
375406
  await this.getExtensionLoader().start(this)
373415
375407
  ]);
375408
+ if (this.enableHooks) {
375409
+ this.hookSystem = new HookSystem(this);
375410
+ await this.hookSystem.initialize();
375411
+ }
373416
375412
  await this.geminiClient.initialize();
373417
375413
  }
373418
375414
  getContentGenerator() {
@@ -374016,6 +376012,12 @@ var Config = class {
374016
376012
  registry.sortTools();
374017
376013
  return registry;
374018
376014
  }
376015
+ /**
376016
+ * Get the hook system instance
376017
+ */
376018
+ getHookSystem() {
376019
+ return this.hookSystem;
376020
+ }
374019
376021
  /**
374020
376022
  * Get hooks configuration
374021
376023
  */
@@ -374207,220 +376209,8 @@ function parseAndFormatApiError(error, authType, userTier, currentModel, fallbac
374207
376209
  init_events();
374208
376210
 
374209
376211
  // 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 = {}));
376212
+ import { randomUUID as randomUUID7 } from "node:crypto";
376213
+ var sessionId = randomUUID7();
374424
376214
 
374425
376215
  // packages/core/dist/index.js
374426
376216
  init_keychain_token_storage();