@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.
package/dist/a2a-server.mjs
CHANGED
|
@@ -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
|
|
54968
|
+
function isObject4(thing) {
|
|
54969
54969
|
return Object.prototype.toString.call(thing) === "[object Object]";
|
|
54970
54970
|
}
|
|
54971
54971
|
function safeJsonParse(thing) {
|
|
54972
|
-
if (
|
|
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
|
|
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" && !
|
|
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" && !
|
|
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 =
|
|
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 =
|
|
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
|
|
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 (!
|
|
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
|
|
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
|
|
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 (
|
|
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 (
|
|
102316
|
-
if (
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
129795
|
-
|
|
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
|
|
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
|
|
133602
|
-
|
|
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
|
|
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(
|
|
140582
|
-
this._sendLogRecords(
|
|
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(
|
|
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(...
|
|
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 [
|
|
217740
|
-
if (
|
|
217741
|
-
resp[0] =
|
|
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
|
|
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 =
|
|
218889
|
-
module2.exports.spawn =
|
|
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
|
|
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 =
|
|
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 = "
|
|
307693
|
-
var CLI_VERSION = "0.19.0-nightly.
|
|
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(
|
|
308906
|
-
const data =
|
|
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(
|
|
309077
|
+
export(logs3, resultCallback) {
|
|
308964
309078
|
try {
|
|
308965
|
-
const entries2 =
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
358826
|
-
|
|
358827
|
-
|
|
358828
|
-
|
|
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(
|
|
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.
|
|
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
|
|
374211
|
-
var sessionId =
|
|
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();
|