@probelabs/probe 0.6.0-rc299 → 0.6.0-rc300
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/bin/binaries/{probe-v0.6.0-rc299-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc300-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc299-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc300-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc299-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc300-x86_64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc299-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc300-x86_64-pc-windows-msvc.zip} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc299-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc300-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/ProbeAgent.js +8 -3
- package/build/agent/simpleTelemetry.js +25 -3
- package/build/tools/vercel.js +7 -0
- package/cjs/agent/ProbeAgent.cjs +181 -159
- package/cjs/agent/simpleTelemetry.cjs +19 -3
- package/cjs/index.cjs +926 -898
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +8 -3
- package/src/agent/simpleTelemetry.js +25 -3
- package/src/tools/vercel.js +7 -0
package/cjs/index.cjs
CHANGED
|
@@ -25877,229 +25877,805 @@ var init_tokenCounter = __esm({
|
|
|
25877
25877
|
}
|
|
25878
25878
|
});
|
|
25879
25879
|
|
|
25880
|
-
// src/agent/
|
|
25881
|
-
|
|
25882
|
-
|
|
25883
|
-
|
|
25884
|
-
|
|
25885
|
-
|
|
25886
|
-
|
|
25887
|
-
|
|
25888
|
-
|
|
25889
|
-
|
|
25890
|
-
|
|
25891
|
-
|
|
25892
|
-
|
|
25893
|
-
|
|
25894
|
-
|
|
25895
|
-
|
|
25896
|
-
|
|
25897
|
-
|
|
25898
|
-
|
|
25899
|
-
|
|
25900
|
-
|
|
25901
|
-
|
|
25902
|
-
|
|
25903
|
-
|
|
25904
|
-
|
|
25905
|
-
|
|
25906
|
-
|
|
25907
|
-
|
|
25908
|
-
|
|
25909
|
-
|
|
25880
|
+
// src/agent/otelLogBridge.js
|
|
25881
|
+
function getOtelApi() {
|
|
25882
|
+
if (otelApiAttempted) return otelApi;
|
|
25883
|
+
otelApiAttempted = true;
|
|
25884
|
+
try {
|
|
25885
|
+
otelApi = (function(name15) {
|
|
25886
|
+
return _require(name15);
|
|
25887
|
+
})("@opentelemetry/api");
|
|
25888
|
+
} catch {
|
|
25889
|
+
}
|
|
25890
|
+
return otelApi;
|
|
25891
|
+
}
|
|
25892
|
+
function getOtelLogger() {
|
|
25893
|
+
if (otelLoggerAttempted) return otelLogger;
|
|
25894
|
+
otelLoggerAttempted = true;
|
|
25895
|
+
try {
|
|
25896
|
+
const { logs } = (function(name15) {
|
|
25897
|
+
return _require(name15);
|
|
25898
|
+
})("@opentelemetry/api-logs");
|
|
25899
|
+
otelLogger = logs.getLogger("probe-agent");
|
|
25900
|
+
} catch {
|
|
25901
|
+
}
|
|
25902
|
+
return otelLogger;
|
|
25903
|
+
}
|
|
25904
|
+
function getTraceSuffix() {
|
|
25905
|
+
try {
|
|
25906
|
+
const api2 = getOtelApi();
|
|
25907
|
+
if (!api2) return "";
|
|
25908
|
+
const span = api2.trace.getSpan(api2.context.active());
|
|
25909
|
+
const ctx = span?.spanContext?.();
|
|
25910
|
+
if (!ctx?.traceId) return "";
|
|
25911
|
+
return ` [trace_id=${ctx.traceId} span_id=${ctx.spanId}]`;
|
|
25912
|
+
} catch {
|
|
25913
|
+
return "";
|
|
25914
|
+
}
|
|
25915
|
+
}
|
|
25916
|
+
function emitOtelLog(msg, level) {
|
|
25917
|
+
try {
|
|
25918
|
+
const logger = getOtelLogger();
|
|
25919
|
+
if (!logger) return;
|
|
25920
|
+
const api2 = getOtelApi();
|
|
25921
|
+
let traceId, spanId;
|
|
25922
|
+
if (api2) {
|
|
25923
|
+
const span = api2.trace.getSpan(api2.context.active());
|
|
25924
|
+
const ctx = span?.spanContext?.();
|
|
25925
|
+
if (ctx?.traceId) {
|
|
25926
|
+
traceId = ctx.traceId;
|
|
25927
|
+
spanId = ctx.spanId;
|
|
25910
25928
|
}
|
|
25911
|
-
|
|
25912
|
-
|
|
25913
|
-
|
|
25914
|
-
|
|
25915
|
-
|
|
25916
|
-
|
|
25917
|
-
|
|
25929
|
+
}
|
|
25930
|
+
logger.emit({
|
|
25931
|
+
severityNumber: OTEL_SEVERITY[level] || 9,
|
|
25932
|
+
severityText: level.toUpperCase(),
|
|
25933
|
+
body: msg,
|
|
25934
|
+
attributes: {
|
|
25935
|
+
"probe.logger": true,
|
|
25936
|
+
...traceId ? { trace_id: traceId, span_id: spanId } : {}
|
|
25918
25937
|
}
|
|
25919
|
-
|
|
25920
|
-
|
|
25921
|
-
|
|
25922
|
-
|
|
25923
|
-
|
|
25924
|
-
|
|
25938
|
+
});
|
|
25939
|
+
} catch {
|
|
25940
|
+
}
|
|
25941
|
+
}
|
|
25942
|
+
function patchConsole() {
|
|
25943
|
+
if (patched) return;
|
|
25944
|
+
const methods = ["log", "info", "warn", "error"];
|
|
25945
|
+
const c = globalThis.console;
|
|
25946
|
+
for (const m of methods) {
|
|
25947
|
+
const orig = c[m].bind(c);
|
|
25948
|
+
originals[m] = orig;
|
|
25949
|
+
c[m] = (...args) => {
|
|
25950
|
+
const msgParts = args.map(
|
|
25951
|
+
(a) => typeof a === "string" ? a : a instanceof Error ? a.message : JSON.stringify(a)
|
|
25952
|
+
);
|
|
25953
|
+
const msg = msgParts.join(" ");
|
|
25954
|
+
emitOtelLog(msg, m === "log" ? "log" : m);
|
|
25955
|
+
const suffix = getTraceSuffix();
|
|
25956
|
+
if (suffix) {
|
|
25957
|
+
if (typeof args[0] === "string") {
|
|
25958
|
+
args[0] = args[0] + suffix;
|
|
25959
|
+
} else {
|
|
25960
|
+
args.push(suffix);
|
|
25961
|
+
}
|
|
25925
25962
|
}
|
|
25963
|
+
return orig(...args);
|
|
25964
|
+
};
|
|
25965
|
+
}
|
|
25966
|
+
patched = true;
|
|
25967
|
+
}
|
|
25968
|
+
var import_module, _require, OTEL_SEVERITY, patched, originals, otelApi, otelApiAttempted, otelLogger, otelLoggerAttempted;
|
|
25969
|
+
var init_otelLogBridge = __esm({
|
|
25970
|
+
"src/agent/otelLogBridge.js"() {
|
|
25971
|
+
"use strict";
|
|
25972
|
+
import_module = require("module");
|
|
25973
|
+
_require = (0, import_module.createRequire)("file:///");
|
|
25974
|
+
OTEL_SEVERITY = {
|
|
25975
|
+
log: 9,
|
|
25976
|
+
// INFO
|
|
25977
|
+
info: 9,
|
|
25978
|
+
// INFO
|
|
25979
|
+
warn: 13,
|
|
25980
|
+
// WARN
|
|
25981
|
+
error: 17,
|
|
25982
|
+
// ERROR
|
|
25983
|
+
debug: 5
|
|
25984
|
+
// DEBUG
|
|
25926
25985
|
};
|
|
25986
|
+
patched = false;
|
|
25987
|
+
originals = {};
|
|
25988
|
+
otelApi = null;
|
|
25989
|
+
otelApiAttempted = false;
|
|
25990
|
+
otelLogger = null;
|
|
25991
|
+
otelLoggerAttempted = false;
|
|
25927
25992
|
}
|
|
25928
25993
|
});
|
|
25929
25994
|
|
|
25930
|
-
// src/agent/
|
|
25931
|
-
|
|
25932
|
-
|
|
25933
|
-
|
|
25995
|
+
// src/agent/simpleTelemetry.js
|
|
25996
|
+
function truncateForSpan(text, maxLen = 4096) {
|
|
25997
|
+
if (!text || text.length <= maxLen) return text || "";
|
|
25998
|
+
const half = Math.floor((maxLen - 40) / 2);
|
|
25999
|
+
const omitted = text.length - half * 2;
|
|
26000
|
+
return text.substring(0, half) + `
|
|
26001
|
+
... [${omitted} chars omitted] ...
|
|
26002
|
+
` + text.substring(text.length - half);
|
|
26003
|
+
}
|
|
26004
|
+
function initializeSimpleTelemetryFromOptions(options) {
|
|
26005
|
+
const telemetry = new SimpleTelemetry({
|
|
26006
|
+
serviceName: "probe-agent",
|
|
26007
|
+
enableFile: options.traceFile !== void 0,
|
|
26008
|
+
enableConsole: options.traceConsole,
|
|
26009
|
+
filePath: options.traceFile || "./traces.jsonl"
|
|
26010
|
+
});
|
|
26011
|
+
patchConsole();
|
|
26012
|
+
return telemetry;
|
|
26013
|
+
}
|
|
26014
|
+
var import_fs4, import_path5, SimpleTelemetry, SimpleAppTracer;
|
|
26015
|
+
var init_simpleTelemetry = __esm({
|
|
26016
|
+
"src/agent/simpleTelemetry.js"() {
|
|
25934
26017
|
"use strict";
|
|
25935
|
-
|
|
25936
|
-
|
|
25937
|
-
|
|
25938
|
-
|
|
25939
|
-
|
|
26018
|
+
import_fs4 = require("fs");
|
|
26019
|
+
import_path5 = require("path");
|
|
26020
|
+
init_otelLogBridge();
|
|
26021
|
+
SimpleTelemetry = class {
|
|
26022
|
+
constructor(options = {}) {
|
|
26023
|
+
this.serviceName = options.serviceName || "probe-agent";
|
|
26024
|
+
this.enableFile = options.enableFile || false;
|
|
26025
|
+
this.enableConsole = options.enableConsole || false;
|
|
26026
|
+
this.filePath = options.filePath || "./traces.jsonl";
|
|
26027
|
+
this.stream = null;
|
|
26028
|
+
if (this.enableFile) {
|
|
26029
|
+
this.initializeFileExporter();
|
|
26030
|
+
}
|
|
25940
26031
|
}
|
|
25941
|
-
|
|
25942
|
-
|
|
25943
|
-
|
|
26032
|
+
initializeFileExporter() {
|
|
26033
|
+
try {
|
|
26034
|
+
const dir = (0, import_path5.dirname)(this.filePath);
|
|
26035
|
+
if (!(0, import_fs4.existsSync)(dir)) {
|
|
26036
|
+
(0, import_fs4.mkdirSync)(dir, { recursive: true });
|
|
26037
|
+
}
|
|
26038
|
+
this.stream = (0, import_fs4.createWriteStream)(this.filePath, { flags: "a" });
|
|
26039
|
+
this.stream.on("error", (error40) => {
|
|
26040
|
+
console.error(`[SimpleTelemetry] Stream error: ${error40.message}`);
|
|
26041
|
+
});
|
|
26042
|
+
console.log(`[SimpleTelemetry] File exporter initialized: ${this.filePath}`);
|
|
26043
|
+
} catch (error40) {
|
|
26044
|
+
console.error(`[SimpleTelemetry] Failed to initialize file exporter: ${error40.message}`);
|
|
26045
|
+
}
|
|
25944
26046
|
}
|
|
25945
|
-
|
|
25946
|
-
|
|
25947
|
-
this.
|
|
25948
|
-
|
|
25949
|
-
|
|
25950
|
-
|
|
25951
|
-
|
|
26047
|
+
createSpan(name15, attributes = {}) {
|
|
26048
|
+
const span = {
|
|
26049
|
+
traceId: this.generateTraceId(),
|
|
26050
|
+
spanId: this.generateSpanId(),
|
|
26051
|
+
name: name15,
|
|
26052
|
+
startTime: Date.now(),
|
|
26053
|
+
attributes: { ...attributes, service: this.serviceName },
|
|
26054
|
+
events: [],
|
|
26055
|
+
status: "OK"
|
|
26056
|
+
};
|
|
26057
|
+
return {
|
|
26058
|
+
...span,
|
|
26059
|
+
addEvent: (eventName, eventAttributes = {}) => {
|
|
26060
|
+
span.events.push({
|
|
26061
|
+
name: eventName,
|
|
26062
|
+
time: Date.now(),
|
|
26063
|
+
attributes: eventAttributes
|
|
26064
|
+
});
|
|
26065
|
+
},
|
|
26066
|
+
setAttributes: (attrs) => {
|
|
26067
|
+
Object.assign(span.attributes, attrs);
|
|
26068
|
+
},
|
|
26069
|
+
setStatus: (status) => {
|
|
26070
|
+
span.status = status;
|
|
26071
|
+
},
|
|
26072
|
+
end: () => {
|
|
26073
|
+
span.endTime = Date.now();
|
|
26074
|
+
span.duration = span.endTime - span.startTime;
|
|
26075
|
+
this.exportSpan(span);
|
|
26076
|
+
}
|
|
26077
|
+
};
|
|
26078
|
+
}
|
|
26079
|
+
exportSpan(span) {
|
|
26080
|
+
const spanData = {
|
|
26081
|
+
...span,
|
|
26082
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
26083
|
+
};
|
|
26084
|
+
if (this.enableConsole) {
|
|
26085
|
+
console.log("[Trace]", JSON.stringify(spanData, null, 2));
|
|
26086
|
+
}
|
|
26087
|
+
if (this.enableFile && this.stream) {
|
|
26088
|
+
this.stream.write(JSON.stringify(spanData) + "\n");
|
|
26089
|
+
}
|
|
26090
|
+
}
|
|
26091
|
+
generateTraceId() {
|
|
26092
|
+
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
|
26093
|
+
}
|
|
26094
|
+
generateSpanId() {
|
|
26095
|
+
return Math.random().toString(36).substring(2, 10);
|
|
26096
|
+
}
|
|
26097
|
+
async flush() {
|
|
26098
|
+
if (this.stream) {
|
|
26099
|
+
return new Promise((resolve9) => {
|
|
26100
|
+
this.stream.once("drain", resolve9);
|
|
26101
|
+
if (!this.stream.writableNeedDrain) {
|
|
26102
|
+
resolve9();
|
|
25952
26103
|
}
|
|
25953
26104
|
});
|
|
25954
26105
|
}
|
|
25955
|
-
const session = this.sessions.get(sessionId);
|
|
25956
|
-
session.messages.push(message);
|
|
25957
|
-
session.metadata.lastActivity = (/* @__PURE__ */ new Date()).toISOString();
|
|
25958
26106
|
}
|
|
25959
|
-
async
|
|
25960
|
-
this.
|
|
26107
|
+
async shutdown() {
|
|
26108
|
+
if (this.stream) {
|
|
26109
|
+
return new Promise((resolve9) => {
|
|
26110
|
+
this.stream.end(() => {
|
|
26111
|
+
console.log(`[SimpleTelemetry] File stream closed: ${this.filePath}`);
|
|
26112
|
+
resolve9();
|
|
26113
|
+
});
|
|
26114
|
+
});
|
|
26115
|
+
}
|
|
25961
26116
|
}
|
|
25962
|
-
|
|
25963
|
-
|
|
25964
|
-
|
|
26117
|
+
};
|
|
26118
|
+
SimpleAppTracer = class {
|
|
26119
|
+
constructor(telemetry, sessionId = null) {
|
|
26120
|
+
this.telemetry = telemetry;
|
|
26121
|
+
this.sessionId = sessionId || this.generateSessionId();
|
|
25965
26122
|
}
|
|
25966
|
-
|
|
25967
|
-
|
|
25968
|
-
|
|
25969
|
-
|
|
26123
|
+
generateSessionId() {
|
|
26124
|
+
return Math.random().toString(36).substring(2, 15);
|
|
26125
|
+
}
|
|
26126
|
+
isEnabled() {
|
|
26127
|
+
return this.telemetry !== null;
|
|
26128
|
+
}
|
|
26129
|
+
createSessionSpan(attributes = {}) {
|
|
26130
|
+
if (!this.isEnabled()) return null;
|
|
26131
|
+
return this.telemetry.createSpan("agent.session", {
|
|
26132
|
+
"session.id": this.sessionId,
|
|
26133
|
+
...attributes
|
|
26134
|
+
});
|
|
26135
|
+
}
|
|
26136
|
+
createAISpan(modelName, provider, attributes = {}) {
|
|
26137
|
+
if (!this.isEnabled()) return null;
|
|
26138
|
+
return this.telemetry.createSpan("ai.request", {
|
|
26139
|
+
"ai.model": modelName,
|
|
26140
|
+
"ai.provider": provider,
|
|
26141
|
+
"session.id": this.sessionId,
|
|
26142
|
+
...attributes
|
|
26143
|
+
});
|
|
26144
|
+
}
|
|
26145
|
+
createToolSpan(toolName, attributes = {}) {
|
|
26146
|
+
if (!this.isEnabled()) return null;
|
|
26147
|
+
return this.telemetry.createSpan("tool.call", {
|
|
26148
|
+
"tool.name": toolName,
|
|
26149
|
+
"session.id": this.sessionId,
|
|
26150
|
+
...attributes
|
|
26151
|
+
});
|
|
26152
|
+
}
|
|
26153
|
+
addEvent(name15, attributes = {}) {
|
|
26154
|
+
if (this.telemetry && this.telemetry.enableConsole) {
|
|
26155
|
+
console.log("[Event]", name15, attributes);
|
|
25970
26156
|
}
|
|
25971
26157
|
}
|
|
25972
|
-
|
|
25973
|
-
|
|
25974
|
-
|
|
25975
|
-
|
|
25976
|
-
|
|
25977
|
-
|
|
25978
|
-
|
|
25979
|
-
|
|
25980
|
-
|
|
25981
|
-
|
|
25982
|
-
constructor() {
|
|
25983
|
-
this.hooks = /* @__PURE__ */ new Map();
|
|
26158
|
+
/**
|
|
26159
|
+
* Record a generic event (used by completionPrompt and other features)
|
|
26160
|
+
*/
|
|
26161
|
+
// visor-disable: SimpleAppTracer uses this.sessionId because it's a per-session instance. AppTracer extracts from attributes because it's a singleton managing multiple sessions. Different architectures require different approaches.
|
|
26162
|
+
recordEvent(name15, attributes = {}) {
|
|
26163
|
+
if (!this.isEnabled()) return;
|
|
26164
|
+
this.addEvent(name15, {
|
|
26165
|
+
"session.id": this.sessionId,
|
|
26166
|
+
...attributes
|
|
26167
|
+
});
|
|
25984
26168
|
}
|
|
25985
26169
|
/**
|
|
25986
|
-
*
|
|
25987
|
-
* @param {string} hookName - Name of the hook
|
|
25988
|
-
* @param {Function} callback - Callback function
|
|
25989
|
-
* @returns {Function} Unregister function
|
|
26170
|
+
* Record delegation events
|
|
25990
26171
|
*/
|
|
25991
|
-
|
|
25992
|
-
if (!this.
|
|
25993
|
-
|
|
25994
|
-
|
|
25995
|
-
|
|
25996
|
-
|
|
26172
|
+
recordDelegationEvent(eventType, data2 = {}) {
|
|
26173
|
+
if (!this.isEnabled()) return;
|
|
26174
|
+
this.addEvent(`delegation.${eventType}`, {
|
|
26175
|
+
"session.id": this.sessionId,
|
|
26176
|
+
...data2
|
|
26177
|
+
});
|
|
25997
26178
|
}
|
|
25998
26179
|
/**
|
|
25999
|
-
*
|
|
26000
|
-
* @param {string} hookName - Name of the hook
|
|
26001
|
-
* @param {Function} callback - Callback function
|
|
26002
|
-
* @returns {Function} Unregister function
|
|
26180
|
+
* Record JSON validation events
|
|
26003
26181
|
*/
|
|
26004
|
-
|
|
26005
|
-
|
|
26006
|
-
|
|
26007
|
-
|
|
26008
|
-
|
|
26009
|
-
|
|
26182
|
+
recordJsonValidationEvent(eventType, data2 = {}) {
|
|
26183
|
+
if (!this.isEnabled()) return;
|
|
26184
|
+
this.addEvent(`json_validation.${eventType}`, {
|
|
26185
|
+
"session.id": this.sessionId,
|
|
26186
|
+
...data2
|
|
26187
|
+
});
|
|
26010
26188
|
}
|
|
26011
26189
|
/**
|
|
26012
|
-
*
|
|
26013
|
-
* @param {string} hookName - Name of the hook
|
|
26014
|
-
* @param {Function} callback - Callback function
|
|
26190
|
+
* Record Mermaid validation events
|
|
26015
26191
|
*/
|
|
26016
|
-
|
|
26017
|
-
|
|
26018
|
-
|
|
26019
|
-
|
|
26020
|
-
|
|
26192
|
+
recordMermaidValidationEvent(eventType, data2 = {}) {
|
|
26193
|
+
if (!this.isEnabled()) return;
|
|
26194
|
+
this.addEvent(`mermaid_validation.${eventType}`, {
|
|
26195
|
+
"session.id": this.sessionId,
|
|
26196
|
+
...data2
|
|
26197
|
+
});
|
|
26021
26198
|
}
|
|
26022
26199
|
/**
|
|
26023
|
-
*
|
|
26024
|
-
* @param {string} hookName - Name of the hook
|
|
26025
|
-
* @param {any} data - Data to pass to callbacks
|
|
26026
|
-
* @returns {Promise<void>}
|
|
26200
|
+
* Record task management events
|
|
26027
26201
|
*/
|
|
26028
|
-
|
|
26029
|
-
|
|
26030
|
-
|
|
26031
|
-
|
|
26032
|
-
|
|
26033
|
-
return Promise.resolve(callback(data2));
|
|
26034
|
-
} catch (error40) {
|
|
26035
|
-
return Promise.reject(error40);
|
|
26036
|
-
}
|
|
26202
|
+
recordTaskEvent(eventType, data2 = {}) {
|
|
26203
|
+
if (!this.isEnabled()) return;
|
|
26204
|
+
this.addEvent(`task.${eventType}`, {
|
|
26205
|
+
"session.id": this.sessionId,
|
|
26206
|
+
...data2
|
|
26037
26207
|
});
|
|
26038
|
-
|
|
26039
|
-
|
|
26040
|
-
|
|
26041
|
-
|
|
26042
|
-
|
|
26208
|
+
}
|
|
26209
|
+
/**
|
|
26210
|
+
* Record MCP (Model Context Protocol) events
|
|
26211
|
+
* Tracks server connections, tool discovery, method filtering, and tool execution
|
|
26212
|
+
*/
|
|
26213
|
+
recordMcpEvent(eventType, data2 = {}) {
|
|
26214
|
+
if (!this.isEnabled()) return;
|
|
26215
|
+
this.addEvent(`mcp.${eventType}`, {
|
|
26216
|
+
"session.id": this.sessionId,
|
|
26217
|
+
...data2
|
|
26043
26218
|
});
|
|
26044
26219
|
}
|
|
26045
26220
|
/**
|
|
26046
|
-
*
|
|
26047
|
-
*
|
|
26221
|
+
* Record bash tool events
|
|
26222
|
+
* Tracks command permission checks, allowed/denied commands, and execution
|
|
26048
26223
|
*/
|
|
26049
|
-
|
|
26050
|
-
if (
|
|
26051
|
-
|
|
26052
|
-
|
|
26053
|
-
|
|
26224
|
+
recordBashEvent(eventType, data2 = {}) {
|
|
26225
|
+
if (!this.isEnabled()) return;
|
|
26226
|
+
this.addEvent(`bash.${eventType}`, {
|
|
26227
|
+
"session.id": this.sessionId,
|
|
26228
|
+
...data2
|
|
26229
|
+
});
|
|
26230
|
+
}
|
|
26231
|
+
setAttributes(attributes) {
|
|
26232
|
+
if (this.telemetry && this.telemetry.enableConsole) {
|
|
26233
|
+
console.log("[Attributes]", attributes);
|
|
26054
26234
|
}
|
|
26055
26235
|
}
|
|
26056
26236
|
/**
|
|
26057
|
-
*
|
|
26058
|
-
* @
|
|
26237
|
+
* Hash content for deduplication/comparison purposes
|
|
26238
|
+
* @param {string} content - The content to hash
|
|
26239
|
+
* @returns {string} - Hex string hash
|
|
26059
26240
|
*/
|
|
26060
|
-
|
|
26061
|
-
|
|
26241
|
+
hashContent(content) {
|
|
26242
|
+
let hash2 = 0;
|
|
26243
|
+
const len = Math.min(content.length, 1e3);
|
|
26244
|
+
for (let i = 0; i < len; i++) {
|
|
26245
|
+
hash2 = (hash2 << 5) - hash2 + content.charCodeAt(i);
|
|
26246
|
+
hash2 |= 0;
|
|
26247
|
+
}
|
|
26248
|
+
return hash2.toString(16);
|
|
26062
26249
|
}
|
|
26063
26250
|
/**
|
|
26064
|
-
*
|
|
26065
|
-
* @param {string}
|
|
26066
|
-
* @
|
|
26251
|
+
* Record a conversation turn (assistant response or tool result)
|
|
26252
|
+
* @param {string} role - The role (assistant, tool_result)
|
|
26253
|
+
* @param {string} content - The turn content
|
|
26254
|
+
* @param {Object} metadata - Additional metadata
|
|
26067
26255
|
*/
|
|
26068
|
-
|
|
26069
|
-
|
|
26070
|
-
|
|
26256
|
+
recordConversationTurn(role, content, metadata = {}) {
|
|
26257
|
+
if (!this.isEnabled()) return;
|
|
26258
|
+
this.addEvent(`conversation.turn.${role}`, {
|
|
26259
|
+
"session.id": this.sessionId,
|
|
26260
|
+
"conversation.role": role,
|
|
26261
|
+
"conversation.content": content.substring(0, 1e4),
|
|
26262
|
+
"conversation.content.length": content.length,
|
|
26263
|
+
"conversation.content.hash": this.hashContent(content),
|
|
26264
|
+
...metadata
|
|
26265
|
+
});
|
|
26071
26266
|
}
|
|
26072
|
-
|
|
26073
|
-
|
|
26074
|
-
|
|
26075
|
-
|
|
26076
|
-
|
|
26077
|
-
|
|
26078
|
-
|
|
26079
|
-
|
|
26080
|
-
|
|
26081
|
-
|
|
26082
|
-
|
|
26083
|
-
|
|
26084
|
-
|
|
26085
|
-
|
|
26086
|
-
|
|
26087
|
-
|
|
26088
|
-
|
|
26089
|
-
|
|
26090
|
-
|
|
26091
|
-
|
|
26092
|
-
|
|
26093
|
-
|
|
26094
|
-
|
|
26095
|
-
|
|
26096
|
-
|
|
26097
|
-
|
|
26098
|
-
|
|
26099
|
-
|
|
26100
|
-
|
|
26101
|
-
|
|
26102
|
-
|
|
26267
|
+
/**
|
|
26268
|
+
* Record error events with classification
|
|
26269
|
+
* @param {string} errorType - The type of error (wrapped_tool, unrecognized_tool, no_tool_call, circuit_breaker, etc.)
|
|
26270
|
+
* @param {Object} errorDetails - Error details including message, stack, context
|
|
26271
|
+
*/
|
|
26272
|
+
recordErrorEvent(errorType, errorDetails = {}) {
|
|
26273
|
+
if (!this.isEnabled()) return;
|
|
26274
|
+
this.addEvent(`error.${errorType}`, {
|
|
26275
|
+
"session.id": this.sessionId,
|
|
26276
|
+
"error.type": errorType,
|
|
26277
|
+
"error.message": errorDetails.message?.substring(0, 1e3) || null,
|
|
26278
|
+
"error.stack": errorDetails.stack?.substring(0, 2e3) || null,
|
|
26279
|
+
"error.recoverable": errorDetails.recoverable ?? true,
|
|
26280
|
+
"error.context": JSON.stringify(errorDetails.context || {}).substring(0, 1e3),
|
|
26281
|
+
...Object.fromEntries(
|
|
26282
|
+
Object.entries(errorDetails).filter(([k]) => !["message", "stack", "context", "recoverable"].includes(k)).map(([k, v]) => [`error.${k}`, v])
|
|
26283
|
+
)
|
|
26284
|
+
});
|
|
26285
|
+
}
|
|
26286
|
+
/**
|
|
26287
|
+
* Record AI thinking/reasoning content
|
|
26288
|
+
* @param {string} thinkingContent - The thinking content from AI response
|
|
26289
|
+
* @param {Object} metadata - Additional metadata
|
|
26290
|
+
*/
|
|
26291
|
+
recordThinkingContent(thinkingContent, metadata = {}) {
|
|
26292
|
+
if (!this.isEnabled() || !thinkingContent) return;
|
|
26293
|
+
this.addEvent("ai.thinking", {
|
|
26294
|
+
"session.id": this.sessionId,
|
|
26295
|
+
"ai.thinking.content": thinkingContent.substring(0, 5e4),
|
|
26296
|
+
"ai.thinking.length": thinkingContent.length,
|
|
26297
|
+
"ai.thinking.hash": this.hashContent(thinkingContent),
|
|
26298
|
+
...metadata
|
|
26299
|
+
});
|
|
26300
|
+
}
|
|
26301
|
+
/**
|
|
26302
|
+
* Record AI tool call decision
|
|
26303
|
+
* @param {string} toolName - The tool name AI decided to call
|
|
26304
|
+
* @param {Object} params - The parameters AI provided
|
|
26305
|
+
* @param {Object} metadata - Additional metadata
|
|
26306
|
+
*/
|
|
26307
|
+
recordToolDecision(toolName, params, metadata = {}) {
|
|
26308
|
+
if (!this.isEnabled()) return;
|
|
26309
|
+
this.addEvent("ai.tool_decision", {
|
|
26310
|
+
"session.id": this.sessionId,
|
|
26311
|
+
"ai.tool_decision.name": toolName,
|
|
26312
|
+
"ai.tool_decision.params": JSON.stringify(params || {}).substring(0, 2e3),
|
|
26313
|
+
...metadata
|
|
26314
|
+
});
|
|
26315
|
+
}
|
|
26316
|
+
/**
|
|
26317
|
+
* Record tool result after execution
|
|
26318
|
+
* @param {string} toolName - The tool that was executed
|
|
26319
|
+
* @param {string|Object} result - The tool result
|
|
26320
|
+
* @param {boolean} success - Whether the tool succeeded
|
|
26321
|
+
* @param {number} durationMs - Execution duration in milliseconds
|
|
26322
|
+
* @param {Object} metadata - Additional metadata
|
|
26323
|
+
*/
|
|
26324
|
+
recordToolResult(toolName, result, success2, durationMs, metadata = {}) {
|
|
26325
|
+
if (!this.isEnabled()) return;
|
|
26326
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
26327
|
+
this.addEvent("tool.result", {
|
|
26328
|
+
"session.id": this.sessionId,
|
|
26329
|
+
"tool.name": toolName,
|
|
26330
|
+
"tool.result": resultStr.substring(0, 1e4),
|
|
26331
|
+
"tool.result.length": resultStr.length,
|
|
26332
|
+
"tool.result.hash": this.hashContent(resultStr),
|
|
26333
|
+
"tool.duration_ms": durationMs,
|
|
26334
|
+
"tool.success": success2,
|
|
26335
|
+
...metadata
|
|
26336
|
+
});
|
|
26337
|
+
}
|
|
26338
|
+
/**
|
|
26339
|
+
* Record MCP tool execution start
|
|
26340
|
+
* @param {string} toolName - MCP tool name
|
|
26341
|
+
* @param {string} serverName - MCP server name
|
|
26342
|
+
* @param {Object} params - Tool parameters
|
|
26343
|
+
* @param {Object} metadata - Additional metadata
|
|
26344
|
+
*/
|
|
26345
|
+
recordMcpToolStart(toolName, serverName, params, metadata = {}) {
|
|
26346
|
+
if (!this.isEnabled()) return;
|
|
26347
|
+
this.addEvent("mcp.tool.start", {
|
|
26348
|
+
"session.id": this.sessionId,
|
|
26349
|
+
"mcp.tool.name": toolName,
|
|
26350
|
+
"mcp.tool.server": serverName || "unknown",
|
|
26351
|
+
"mcp.tool.params": JSON.stringify(params || {}).substring(0, 2e3),
|
|
26352
|
+
...metadata
|
|
26353
|
+
});
|
|
26354
|
+
}
|
|
26355
|
+
/**
|
|
26356
|
+
* Record MCP tool execution end
|
|
26357
|
+
* @param {string} toolName - MCP tool name
|
|
26358
|
+
* @param {string} serverName - MCP server name
|
|
26359
|
+
* @param {string|Object} result - Tool result
|
|
26360
|
+
* @param {boolean} success - Whether succeeded
|
|
26361
|
+
* @param {number} durationMs - Execution duration
|
|
26362
|
+
* @param {string} errorMessage - Error message if failed
|
|
26363
|
+
* @param {Object} metadata - Additional metadata
|
|
26364
|
+
*/
|
|
26365
|
+
recordMcpToolEnd(toolName, serverName, result, success2, durationMs, errorMessage = null, metadata = {}) {
|
|
26366
|
+
if (!this.isEnabled()) return;
|
|
26367
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result || "");
|
|
26368
|
+
this.addEvent("mcp.tool.end", {
|
|
26369
|
+
"session.id": this.sessionId,
|
|
26370
|
+
"mcp.tool.name": toolName,
|
|
26371
|
+
"mcp.tool.server": serverName || "unknown",
|
|
26372
|
+
"mcp.tool.result": resultStr.substring(0, 1e4),
|
|
26373
|
+
"mcp.tool.result.length": resultStr.length,
|
|
26374
|
+
"mcp.tool.duration_ms": durationMs,
|
|
26375
|
+
"mcp.tool.success": success2,
|
|
26376
|
+
"mcp.tool.error": errorMessage,
|
|
26377
|
+
...metadata
|
|
26378
|
+
});
|
|
26379
|
+
}
|
|
26380
|
+
/**
|
|
26381
|
+
* Record iteration lifecycle event
|
|
26382
|
+
* @param {string} eventType - start or end
|
|
26383
|
+
* @param {number} iteration - Iteration number
|
|
26384
|
+
* @param {Object} data - Additional data
|
|
26385
|
+
*/
|
|
26386
|
+
recordIterationEvent(eventType, iteration, data2 = {}) {
|
|
26387
|
+
if (!this.isEnabled()) return;
|
|
26388
|
+
this.addEvent(`iteration.${eventType}`, {
|
|
26389
|
+
"session.id": this.sessionId,
|
|
26390
|
+
"iteration": iteration,
|
|
26391
|
+
...data2
|
|
26392
|
+
});
|
|
26393
|
+
}
|
|
26394
|
+
/**
|
|
26395
|
+
* Record per-turn token breakdown
|
|
26396
|
+
* @param {number} iteration - Iteration number
|
|
26397
|
+
* @param {Object} tokenData - Token metrics
|
|
26398
|
+
*/
|
|
26399
|
+
recordTokenTurn(iteration, tokenData = {}) {
|
|
26400
|
+
if (!this.isEnabled()) return;
|
|
26401
|
+
this.addEvent("tokens.turn", {
|
|
26402
|
+
"session.id": this.sessionId,
|
|
26403
|
+
"iteration": iteration,
|
|
26404
|
+
"tokens.input": tokenData.inputTokens || 0,
|
|
26405
|
+
"tokens.output": tokenData.outputTokens || 0,
|
|
26406
|
+
"tokens.total": (tokenData.inputTokens || 0) + (tokenData.outputTokens || 0),
|
|
26407
|
+
"tokens.cache_read": tokenData.cacheReadTokens || 0,
|
|
26408
|
+
"tokens.cache_write": tokenData.cacheWriteTokens || 0,
|
|
26409
|
+
"tokens.context_used": tokenData.contextTokens || 0,
|
|
26410
|
+
"tokens.context_remaining": tokenData.maxContextTokens ? tokenData.maxContextTokens - (tokenData.contextTokens || 0) : null
|
|
26411
|
+
});
|
|
26412
|
+
}
|
|
26413
|
+
async withSpan(spanName, fn, attributes = {}, onResult = null) {
|
|
26414
|
+
if (!this.isEnabled()) {
|
|
26415
|
+
return fn();
|
|
26416
|
+
}
|
|
26417
|
+
const span = this.telemetry.createSpan(spanName, {
|
|
26418
|
+
"session.id": this.sessionId,
|
|
26419
|
+
...attributes
|
|
26420
|
+
});
|
|
26421
|
+
try {
|
|
26422
|
+
const result = await fn();
|
|
26423
|
+
span.setStatus("OK");
|
|
26424
|
+
if (onResult) {
|
|
26425
|
+
try {
|
|
26426
|
+
onResult(span, result);
|
|
26427
|
+
} catch (_) {
|
|
26428
|
+
}
|
|
26429
|
+
}
|
|
26430
|
+
return result;
|
|
26431
|
+
} catch (error40) {
|
|
26432
|
+
span.setStatus("ERROR");
|
|
26433
|
+
span.addEvent("exception", {
|
|
26434
|
+
"exception.message": error40.message,
|
|
26435
|
+
"exception.stack": error40.stack
|
|
26436
|
+
});
|
|
26437
|
+
throw error40;
|
|
26438
|
+
} finally {
|
|
26439
|
+
span.end();
|
|
26440
|
+
}
|
|
26441
|
+
}
|
|
26442
|
+
async flush() {
|
|
26443
|
+
if (this.telemetry) {
|
|
26444
|
+
await this.telemetry.flush();
|
|
26445
|
+
}
|
|
26446
|
+
}
|
|
26447
|
+
async shutdown() {
|
|
26448
|
+
if (this.telemetry) {
|
|
26449
|
+
await this.telemetry.shutdown();
|
|
26450
|
+
}
|
|
26451
|
+
}
|
|
26452
|
+
};
|
|
26453
|
+
}
|
|
26454
|
+
});
|
|
26455
|
+
|
|
26456
|
+
// src/agent/storage/StorageAdapter.js
|
|
26457
|
+
var StorageAdapter;
|
|
26458
|
+
var init_StorageAdapter = __esm({
|
|
26459
|
+
"src/agent/storage/StorageAdapter.js"() {
|
|
26460
|
+
"use strict";
|
|
26461
|
+
StorageAdapter = class {
|
|
26462
|
+
/**
|
|
26463
|
+
* Load conversation history for a session
|
|
26464
|
+
* @param {string} sessionId - Session identifier
|
|
26465
|
+
* @returns {Promise<Array<Object>>} Array of message objects with {role, content, ...}
|
|
26466
|
+
*/
|
|
26467
|
+
async loadHistory(sessionId) {
|
|
26468
|
+
throw new Error("StorageAdapter.loadHistory() must be implemented by subclass");
|
|
26469
|
+
}
|
|
26470
|
+
/**
|
|
26471
|
+
* Save a message to storage
|
|
26472
|
+
* @param {string} sessionId - Session identifier
|
|
26473
|
+
* @param {Object} message - Message object { role, content, ... }
|
|
26474
|
+
* @returns {Promise<void>}
|
|
26475
|
+
*/
|
|
26476
|
+
async saveMessage(sessionId, message) {
|
|
26477
|
+
throw new Error("StorageAdapter.saveMessage() must be implemented by subclass");
|
|
26478
|
+
}
|
|
26479
|
+
/**
|
|
26480
|
+
* Clear history for a session
|
|
26481
|
+
* @param {string} sessionId - Session identifier
|
|
26482
|
+
* @returns {Promise<void>}
|
|
26483
|
+
*/
|
|
26484
|
+
async clearHistory(sessionId) {
|
|
26485
|
+
throw new Error("StorageAdapter.clearHistory() must be implemented by subclass");
|
|
26486
|
+
}
|
|
26487
|
+
/**
|
|
26488
|
+
* Get session metadata (optional)
|
|
26489
|
+
* @param {string} sessionId - Session identifier
|
|
26490
|
+
* @returns {Promise<Object|null>} Session metadata or null
|
|
26491
|
+
*/
|
|
26492
|
+
async getSessionMetadata(sessionId) {
|
|
26493
|
+
return null;
|
|
26494
|
+
}
|
|
26495
|
+
/**
|
|
26496
|
+
* Update session activity timestamp (optional)
|
|
26497
|
+
* @param {string} sessionId - Session identifier
|
|
26498
|
+
* @returns {Promise<void>}
|
|
26499
|
+
*/
|
|
26500
|
+
async updateSessionActivity(sessionId) {
|
|
26501
|
+
}
|
|
26502
|
+
};
|
|
26503
|
+
}
|
|
26504
|
+
});
|
|
26505
|
+
|
|
26506
|
+
// src/agent/storage/InMemoryStorageAdapter.js
|
|
26507
|
+
var InMemoryStorageAdapter;
|
|
26508
|
+
var init_InMemoryStorageAdapter = __esm({
|
|
26509
|
+
"src/agent/storage/InMemoryStorageAdapter.js"() {
|
|
26510
|
+
"use strict";
|
|
26511
|
+
init_StorageAdapter();
|
|
26512
|
+
InMemoryStorageAdapter = class extends StorageAdapter {
|
|
26513
|
+
constructor() {
|
|
26514
|
+
super();
|
|
26515
|
+
this.sessions = /* @__PURE__ */ new Map();
|
|
26516
|
+
}
|
|
26517
|
+
async loadHistory(sessionId) {
|
|
26518
|
+
const session = this.sessions.get(sessionId);
|
|
26519
|
+
return session ? session.messages : [];
|
|
26520
|
+
}
|
|
26521
|
+
async saveMessage(sessionId, message) {
|
|
26522
|
+
if (!this.sessions.has(sessionId)) {
|
|
26523
|
+
this.sessions.set(sessionId, {
|
|
26524
|
+
messages: [],
|
|
26525
|
+
metadata: {
|
|
26526
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26527
|
+
lastActivity: (/* @__PURE__ */ new Date()).toISOString()
|
|
26528
|
+
}
|
|
26529
|
+
});
|
|
26530
|
+
}
|
|
26531
|
+
const session = this.sessions.get(sessionId);
|
|
26532
|
+
session.messages.push(message);
|
|
26533
|
+
session.metadata.lastActivity = (/* @__PURE__ */ new Date()).toISOString();
|
|
26534
|
+
}
|
|
26535
|
+
async clearHistory(sessionId) {
|
|
26536
|
+
this.sessions.delete(sessionId);
|
|
26537
|
+
}
|
|
26538
|
+
async getSessionMetadata(sessionId) {
|
|
26539
|
+
const session = this.sessions.get(sessionId);
|
|
26540
|
+
return session ? session.metadata : null;
|
|
26541
|
+
}
|
|
26542
|
+
async updateSessionActivity(sessionId) {
|
|
26543
|
+
const session = this.sessions.get(sessionId);
|
|
26544
|
+
if (session) {
|
|
26545
|
+
session.metadata.lastActivity = (/* @__PURE__ */ new Date()).toISOString();
|
|
26546
|
+
}
|
|
26547
|
+
}
|
|
26548
|
+
};
|
|
26549
|
+
}
|
|
26550
|
+
});
|
|
26551
|
+
|
|
26552
|
+
// src/agent/hooks/HookManager.js
|
|
26553
|
+
var HookManager, HOOK_TYPES;
|
|
26554
|
+
var init_HookManager = __esm({
|
|
26555
|
+
"src/agent/hooks/HookManager.js"() {
|
|
26556
|
+
"use strict";
|
|
26557
|
+
HookManager = class {
|
|
26558
|
+
constructor() {
|
|
26559
|
+
this.hooks = /* @__PURE__ */ new Map();
|
|
26560
|
+
}
|
|
26561
|
+
/**
|
|
26562
|
+
* Register a hook callback
|
|
26563
|
+
* @param {string} hookName - Name of the hook
|
|
26564
|
+
* @param {Function} callback - Callback function
|
|
26565
|
+
* @returns {Function} Unregister function
|
|
26566
|
+
*/
|
|
26567
|
+
on(hookName, callback) {
|
|
26568
|
+
if (!this.hooks.has(hookName)) {
|
|
26569
|
+
this.hooks.set(hookName, /* @__PURE__ */ new Set());
|
|
26570
|
+
}
|
|
26571
|
+
this.hooks.get(hookName).add(callback);
|
|
26572
|
+
return () => this.off(hookName, callback);
|
|
26573
|
+
}
|
|
26574
|
+
/**
|
|
26575
|
+
* Register a one-time hook callback
|
|
26576
|
+
* @param {string} hookName - Name of the hook
|
|
26577
|
+
* @param {Function} callback - Callback function
|
|
26578
|
+
* @returns {Function} Unregister function
|
|
26579
|
+
*/
|
|
26580
|
+
once(hookName, callback) {
|
|
26581
|
+
const wrappedCallback = async (data2) => {
|
|
26582
|
+
this.off(hookName, wrappedCallback);
|
|
26583
|
+
await callback(data2);
|
|
26584
|
+
};
|
|
26585
|
+
return this.on(hookName, wrappedCallback);
|
|
26586
|
+
}
|
|
26587
|
+
/**
|
|
26588
|
+
* Unregister a hook callback
|
|
26589
|
+
* @param {string} hookName - Name of the hook
|
|
26590
|
+
* @param {Function} callback - Callback function
|
|
26591
|
+
*/
|
|
26592
|
+
off(hookName, callback) {
|
|
26593
|
+
const callbacks = this.hooks.get(hookName);
|
|
26594
|
+
if (callbacks) {
|
|
26595
|
+
callbacks.delete(callback);
|
|
26596
|
+
}
|
|
26597
|
+
}
|
|
26598
|
+
/**
|
|
26599
|
+
* Emit a hook event
|
|
26600
|
+
* @param {string} hookName - Name of the hook
|
|
26601
|
+
* @param {any} data - Data to pass to callbacks
|
|
26602
|
+
* @returns {Promise<void>}
|
|
26603
|
+
*/
|
|
26604
|
+
async emit(hookName, data2) {
|
|
26605
|
+
const callbacks = this.hooks.get(hookName);
|
|
26606
|
+
if (!callbacks || callbacks.size === 0) return;
|
|
26607
|
+
const promises = Array.from(callbacks).map((callback) => {
|
|
26608
|
+
try {
|
|
26609
|
+
return Promise.resolve(callback(data2));
|
|
26610
|
+
} catch (error40) {
|
|
26611
|
+
return Promise.reject(error40);
|
|
26612
|
+
}
|
|
26613
|
+
});
|
|
26614
|
+
const results = await Promise.allSettled(promises);
|
|
26615
|
+
results.forEach((result, index) => {
|
|
26616
|
+
if (result.status === "rejected") {
|
|
26617
|
+
console.error(`[HookManager] Error in hook "${hookName}" (callback ${index + 1}):`, result.reason);
|
|
26618
|
+
}
|
|
26619
|
+
});
|
|
26620
|
+
}
|
|
26621
|
+
/**
|
|
26622
|
+
* Clear all hooks or hooks for a specific event
|
|
26623
|
+
* @param {string} [hookName] - Optional hook name to clear
|
|
26624
|
+
*/
|
|
26625
|
+
clear(hookName) {
|
|
26626
|
+
if (hookName) {
|
|
26627
|
+
this.hooks.delete(hookName);
|
|
26628
|
+
} else {
|
|
26629
|
+
this.hooks.clear();
|
|
26630
|
+
}
|
|
26631
|
+
}
|
|
26632
|
+
/**
|
|
26633
|
+
* Get list of registered hook names
|
|
26634
|
+
* @returns {string[]} Array of hook names
|
|
26635
|
+
*/
|
|
26636
|
+
getHookNames() {
|
|
26637
|
+
return Array.from(this.hooks.keys());
|
|
26638
|
+
}
|
|
26639
|
+
/**
|
|
26640
|
+
* Get number of callbacks for a hook
|
|
26641
|
+
* @param {string} hookName - Name of the hook
|
|
26642
|
+
* @returns {number} Number of callbacks
|
|
26643
|
+
*/
|
|
26644
|
+
getCallbackCount(hookName) {
|
|
26645
|
+
const callbacks = this.hooks.get(hookName);
|
|
26646
|
+
return callbacks ? callbacks.size : 0;
|
|
26647
|
+
}
|
|
26648
|
+
};
|
|
26649
|
+
HOOK_TYPES = {
|
|
26650
|
+
// Lifecycle hooks
|
|
26651
|
+
AGENT_INITIALIZED: "agent:initialized",
|
|
26652
|
+
AGENT_CLEANUP: "agent:cleanup",
|
|
26653
|
+
// Message hooks
|
|
26654
|
+
MESSAGE_USER: "message:user",
|
|
26655
|
+
MESSAGE_ASSISTANT: "message:assistant",
|
|
26656
|
+
MESSAGE_SYSTEM: "message:system",
|
|
26657
|
+
// Tool execution hooks
|
|
26658
|
+
TOOL_START: "tool:start",
|
|
26659
|
+
TOOL_END: "tool:end",
|
|
26660
|
+
TOOL_ERROR: "tool:error",
|
|
26661
|
+
// AI streaming hooks
|
|
26662
|
+
AI_STREAM_START: "ai:stream:start",
|
|
26663
|
+
AI_STREAM_DELTA: "ai:stream:delta",
|
|
26664
|
+
AI_STREAM_END: "ai:stream:end",
|
|
26665
|
+
// Storage hooks
|
|
26666
|
+
STORAGE_LOAD: "storage:load",
|
|
26667
|
+
STORAGE_SAVE: "storage:save",
|
|
26668
|
+
STORAGE_CLEAR: "storage:clear",
|
|
26669
|
+
// Iteration hooks
|
|
26670
|
+
ITERATION_START: "iteration:start",
|
|
26671
|
+
ITERATION_END: "iteration:end"
|
|
26672
|
+
};
|
|
26673
|
+
}
|
|
26674
|
+
});
|
|
26675
|
+
|
|
26676
|
+
// src/agent/imageConfig.js
|
|
26677
|
+
function isFormatSupportedByProvider(extension, provider) {
|
|
26678
|
+
if (!extension || typeof extension !== "string") {
|
|
26103
26679
|
return false;
|
|
26104
26680
|
}
|
|
26105
26681
|
if (extension.includes("/") || extension.includes("\\") || extension.includes("..")) {
|
|
@@ -27105,8 +27681,8 @@ function parseAndResolvePaths(pathStr, cwd) {
|
|
|
27105
27681
|
if (/["']/.test(pathStr)) {
|
|
27106
27682
|
const paths2 = splitQuotedString(pathStr);
|
|
27107
27683
|
return paths2.map((p) => {
|
|
27108
|
-
if ((0,
|
|
27109
|
-
return cwd ? (0,
|
|
27684
|
+
if ((0, import_path6.isAbsolute)(p)) return p;
|
|
27685
|
+
return cwd ? (0, import_path6.resolve)(cwd, p) : p;
|
|
27110
27686
|
});
|
|
27111
27687
|
}
|
|
27112
27688
|
let paths = pathStr.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
@@ -27118,8 +27694,8 @@ function parseAndResolvePaths(pathStr, cwd) {
|
|
|
27118
27694
|
return allLookLikePaths ? parts : [p];
|
|
27119
27695
|
});
|
|
27120
27696
|
return paths.map((p) => {
|
|
27121
|
-
if ((0,
|
|
27122
|
-
return cwd ? (0,
|
|
27697
|
+
if ((0, import_path6.isAbsolute)(p)) return p;
|
|
27698
|
+
return cwd ? (0, import_path6.resolve)(cwd, p) : p;
|
|
27123
27699
|
});
|
|
27124
27700
|
}
|
|
27125
27701
|
function resolveTargetPath(target, cwd) {
|
|
@@ -27137,17 +27713,17 @@ function resolveTargetPath(target, cwd) {
|
|
|
27137
27713
|
filePart = target;
|
|
27138
27714
|
suffix = "";
|
|
27139
27715
|
}
|
|
27140
|
-
if (!(0,
|
|
27141
|
-
filePart = (0,
|
|
27716
|
+
if (!(0, import_path6.isAbsolute)(filePart) && cwd) {
|
|
27717
|
+
filePart = (0, import_path6.resolve)(cwd, filePart);
|
|
27142
27718
|
}
|
|
27143
27719
|
return filePart + suffix;
|
|
27144
27720
|
}
|
|
27145
|
-
var
|
|
27721
|
+
var import_path6, searchSchema, searchAllSchema, querySchema, extractSchema, delegateSchema, listSkillsSchema, useSkillSchema, listFilesSchema, searchFilesSchema, readImageSchema, bashSchema, analyzeAllSchema, executePlanSchema, cleanupExecutePlanSchema, searchDescription, searchDelegateDescription, queryDescription, extractDescription, delegateDescription, bashDescription, analyzeAllDescription;
|
|
27146
27722
|
var init_common = __esm({
|
|
27147
27723
|
"src/tools/common.js"() {
|
|
27148
27724
|
"use strict";
|
|
27149
27725
|
init_zod();
|
|
27150
|
-
|
|
27726
|
+
import_path6 = require("path");
|
|
27151
27727
|
searchSchema = external_exports2.object({
|
|
27152
27728
|
query: external_exports2.string().describe("Search query \u2014 natural language questions or Elasticsearch-style keywords both work. For keywords: use quotes for exact phrases, AND/OR for boolean logic, - for negation. Probe handles stemming and camelCase/snake_case splitting automatically, so do NOT try case or style variations of the same keyword."),
|
|
27153
27729
|
path: external_exports2.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
|
|
@@ -27310,7 +27886,7 @@ var init_symbolEdit = __esm({
|
|
|
27310
27886
|
// src/tools/fileTracker.js
|
|
27311
27887
|
function normalizePath(filePath) {
|
|
27312
27888
|
if (!filePath) return filePath;
|
|
27313
|
-
return (0,
|
|
27889
|
+
return (0, import_path7.resolve)(filePath);
|
|
27314
27890
|
}
|
|
27315
27891
|
function computeContentHash(content) {
|
|
27316
27892
|
const normalized = (content || "").split("\n").map((l) => l.trimEnd()).join("\n");
|
|
@@ -27350,12 +27926,12 @@ function parseFilePathsFromOutput(output) {
|
|
|
27350
27926
|
}
|
|
27351
27927
|
return paths;
|
|
27352
27928
|
}
|
|
27353
|
-
var import_crypto2,
|
|
27929
|
+
var import_crypto2, import_path7, FileTracker;
|
|
27354
27930
|
var init_fileTracker = __esm({
|
|
27355
27931
|
"src/tools/fileTracker.js"() {
|
|
27356
27932
|
"use strict";
|
|
27357
27933
|
import_crypto2 = require("crypto");
|
|
27358
|
-
|
|
27934
|
+
import_path7 = require("path");
|
|
27359
27935
|
init_symbolEdit();
|
|
27360
27936
|
FileTracker = class {
|
|
27361
27937
|
/**
|
|
@@ -27456,7 +28032,7 @@ var init_fileTracker = __esm({
|
|
|
27456
28032
|
const symbolPromises = [];
|
|
27457
28033
|
for (const target of targets) {
|
|
27458
28034
|
const filePath = extractFilePath(target);
|
|
27459
|
-
const resolved = (0,
|
|
28035
|
+
const resolved = (0, import_path7.isAbsolute)(filePath) ? filePath : (0, import_path7.resolve)(cwd, filePath);
|
|
27460
28036
|
if (!seenPaths.has(resolved)) {
|
|
27461
28037
|
seenPaths.add(resolved);
|
|
27462
28038
|
this.markFileSeen(resolved);
|
|
@@ -27496,7 +28072,7 @@ var init_fileTracker = __esm({
|
|
|
27496
28072
|
async trackFilesFromOutput(output, cwd) {
|
|
27497
28073
|
const paths = parseFilePathsFromOutput(output);
|
|
27498
28074
|
for (const filePath of paths) {
|
|
27499
|
-
const resolved = (0,
|
|
28075
|
+
const resolved = (0, import_path7.isAbsolute)(filePath) ? filePath : (0, import_path7.resolve)(cwd, filePath);
|
|
27500
28076
|
this.markFileSeen(resolved);
|
|
27501
28077
|
}
|
|
27502
28078
|
}
|
|
@@ -31643,22 +32219,22 @@ var init_esm3 = __esm({
|
|
|
31643
32219
|
});
|
|
31644
32220
|
|
|
31645
32221
|
// node_modules/path-scurry/dist/esm/index.js
|
|
31646
|
-
var import_node_path, import_node_url,
|
|
32222
|
+
var import_node_path, import_node_url, import_fs5, actualFS, import_promises, realpathSync2, defaultFS, fsFromOption, uncDriveRegexp, uncToDrive, eitherSep, UNKNOWN, IFIFO, IFCHR, IFDIR, IFBLK, IFREG, IFLNK, IFSOCK, IFMT, IFMT_UNKNOWN, READDIR_CALLED, LSTAT_CALLED, ENOTDIR, ENOENT, ENOREADLINK, ENOREALPATH, ENOCHILD, TYPEMASK, entToType, normalizeCache, normalize2, normalizeNocaseCache, normalizeNocase, ResolveCache, ChildrenCache, setAsCwd, PathBase, PathWin32, PathPosix, PathScurryBase, PathScurryWin32, PathScurryPosix, PathScurryDarwin, Path, PathScurry;
|
|
31647
32223
|
var init_esm4 = __esm({
|
|
31648
32224
|
"node_modules/path-scurry/dist/esm/index.js"() {
|
|
31649
32225
|
init_esm2();
|
|
31650
32226
|
import_node_path = require("node:path");
|
|
31651
32227
|
import_node_url = require("node:url");
|
|
31652
|
-
|
|
32228
|
+
import_fs5 = require("fs");
|
|
31653
32229
|
actualFS = __toESM(require("node:fs"), 1);
|
|
31654
32230
|
import_promises = require("node:fs/promises");
|
|
31655
32231
|
init_esm3();
|
|
31656
|
-
realpathSync2 =
|
|
32232
|
+
realpathSync2 = import_fs5.realpathSync.native;
|
|
31657
32233
|
defaultFS = {
|
|
31658
|
-
lstatSync:
|
|
31659
|
-
readdir:
|
|
31660
|
-
readdirSync:
|
|
31661
|
-
readlinkSync:
|
|
32234
|
+
lstatSync: import_fs5.lstatSync,
|
|
32235
|
+
readdir: import_fs5.readdir,
|
|
32236
|
+
readdirSync: import_fs5.readdirSync,
|
|
32237
|
+
readlinkSync: import_fs5.readlinkSync,
|
|
31662
32238
|
realpathSync: realpathSync2,
|
|
31663
32239
|
promises: {
|
|
31664
32240
|
lstat: import_promises.lstat,
|
|
@@ -34595,7 +35171,7 @@ function createWrappedTools(baseTools) {
|
|
|
34595
35171
|
}
|
|
34596
35172
|
return wrappedTools;
|
|
34597
35173
|
}
|
|
34598
|
-
var import_child_process6, import_util13, import_crypto3, import_events,
|
|
35174
|
+
var import_child_process6, import_util13, import_crypto3, import_events, import_fs6, import_fs7, import_path8, toolCallEmitter, activeToolExecutions, wrapToolWithEmitter, listFilesTool, searchFilesTool, listFilesToolInstance, searchFilesToolInstance;
|
|
34599
35175
|
var init_probeTool = __esm({
|
|
34600
35176
|
"src/agent/probeTool.js"() {
|
|
34601
35177
|
"use strict";
|
|
@@ -34604,9 +35180,9 @@ var init_probeTool = __esm({
|
|
|
34604
35180
|
import_util13 = require("util");
|
|
34605
35181
|
import_crypto3 = require("crypto");
|
|
34606
35182
|
import_events = require("events");
|
|
34607
|
-
|
|
34608
|
-
|
|
34609
|
-
|
|
35183
|
+
import_fs6 = __toESM(require("fs"), 1);
|
|
35184
|
+
import_fs7 = require("fs");
|
|
35185
|
+
import_path8 = __toESM(require("path"), 1);
|
|
34610
35186
|
init_esm5();
|
|
34611
35187
|
init_symlink_utils();
|
|
34612
35188
|
toolCallEmitter = new import_events.EventEmitter();
|
|
@@ -34695,17 +35271,17 @@ var init_probeTool = __esm({
|
|
|
34695
35271
|
execute: async (params) => {
|
|
34696
35272
|
const { directory = ".", workingDirectory } = params;
|
|
34697
35273
|
const baseCwd = workingDirectory || process.cwd();
|
|
34698
|
-
const secureBaseDir =
|
|
35274
|
+
const secureBaseDir = import_path8.default.resolve(baseCwd);
|
|
34699
35275
|
const isDependencyPath = directory.startsWith("/dep/") || directory.startsWith("go:") || directory.startsWith("js:") || directory.startsWith("rust:");
|
|
34700
35276
|
let targetDir;
|
|
34701
|
-
if (
|
|
34702
|
-
targetDir =
|
|
34703
|
-
if (!isDependencyPath && !targetDir.startsWith(secureBaseDir +
|
|
35277
|
+
if (import_path8.default.isAbsolute(directory)) {
|
|
35278
|
+
targetDir = import_path8.default.resolve(directory);
|
|
35279
|
+
if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path8.default.sep) && targetDir !== secureBaseDir) {
|
|
34704
35280
|
throw new Error(`Path traversal attempt detected. Cannot access directory outside workspace: ${directory}`);
|
|
34705
35281
|
}
|
|
34706
35282
|
} else {
|
|
34707
|
-
targetDir =
|
|
34708
|
-
if (!isDependencyPath && !targetDir.startsWith(secureBaseDir +
|
|
35283
|
+
targetDir = import_path8.default.resolve(secureBaseDir, directory);
|
|
35284
|
+
if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path8.default.sep) && targetDir !== secureBaseDir) {
|
|
34709
35285
|
throw new Error(`Path traversal attempt detected. Access denied: ${directory}`);
|
|
34710
35286
|
}
|
|
34711
35287
|
}
|
|
@@ -34714,7 +35290,7 @@ var init_probeTool = __esm({
|
|
|
34714
35290
|
console.log(`[DEBUG] Listing files in directory: ${targetDir}`);
|
|
34715
35291
|
}
|
|
34716
35292
|
try {
|
|
34717
|
-
const files = await
|
|
35293
|
+
const files = await import_fs7.promises.readdir(targetDir, { withFileTypes: true });
|
|
34718
35294
|
const formatSize = (size) => {
|
|
34719
35295
|
if (size < 1024) return `${size}B`;
|
|
34720
35296
|
if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)}K`;
|
|
@@ -34722,7 +35298,7 @@ var init_probeTool = __esm({
|
|
|
34722
35298
|
return `${(size / (1024 * 1024 * 1024)).toFixed(1)}G`;
|
|
34723
35299
|
};
|
|
34724
35300
|
const entries = await Promise.all(files.map(async (file2) => {
|
|
34725
|
-
const fullPath =
|
|
35301
|
+
const fullPath = import_path8.default.join(targetDir, file2.name);
|
|
34726
35302
|
const entryType = await getEntryType(file2, fullPath);
|
|
34727
35303
|
return {
|
|
34728
35304
|
name: file2.name,
|
|
@@ -34759,17 +35335,17 @@ var init_probeTool = __esm({
|
|
|
34759
35335
|
throw new Error("Pattern is required for file search");
|
|
34760
35336
|
}
|
|
34761
35337
|
const baseCwd = workingDirectory || process.cwd();
|
|
34762
|
-
const secureBaseDir =
|
|
35338
|
+
const secureBaseDir = import_path8.default.resolve(baseCwd);
|
|
34763
35339
|
const isDependencyPath = directory.startsWith("/dep/") || directory.startsWith("go:") || directory.startsWith("js:") || directory.startsWith("rust:");
|
|
34764
35340
|
let targetDir;
|
|
34765
|
-
if (
|
|
34766
|
-
targetDir =
|
|
34767
|
-
if (!isDependencyPath && !targetDir.startsWith(secureBaseDir +
|
|
35341
|
+
if (import_path8.default.isAbsolute(directory)) {
|
|
35342
|
+
targetDir = import_path8.default.resolve(directory);
|
|
35343
|
+
if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path8.default.sep) && targetDir !== secureBaseDir) {
|
|
34768
35344
|
throw new Error(`Path traversal attempt detected. Cannot access directory outside workspace: ${directory}`);
|
|
34769
35345
|
}
|
|
34770
35346
|
} else {
|
|
34771
|
-
targetDir =
|
|
34772
|
-
if (!isDependencyPath && !targetDir.startsWith(secureBaseDir +
|
|
35347
|
+
targetDir = import_path8.default.resolve(secureBaseDir, directory);
|
|
35348
|
+
if (!isDependencyPath && !targetDir.startsWith(secureBaseDir + import_path8.default.sep) && targetDir !== secureBaseDir) {
|
|
34773
35349
|
throw new Error(`Path traversal attempt detected. Access denied: ${directory}`);
|
|
34774
35350
|
}
|
|
34775
35351
|
}
|
|
@@ -73424,11 +74000,11 @@ function loadMCPConfigurationFromPath(configPath) {
|
|
|
73424
74000
|
if (!configPath) {
|
|
73425
74001
|
throw new Error("Config path is required");
|
|
73426
74002
|
}
|
|
73427
|
-
if (!(0,
|
|
74003
|
+
if (!(0, import_fs8.existsSync)(configPath)) {
|
|
73428
74004
|
throw new Error(`MCP configuration file not found: ${configPath}`);
|
|
73429
74005
|
}
|
|
73430
74006
|
try {
|
|
73431
|
-
const content = (0,
|
|
74007
|
+
const content = (0, import_fs8.readFileSync)(configPath, "utf8");
|
|
73432
74008
|
const config2 = JSON.parse(content);
|
|
73433
74009
|
if (process.env.DEBUG === "1" || process.env.DEBUG_MCP === "1") {
|
|
73434
74010
|
console.error(`[MCP DEBUG] Loaded configuration from: ${configPath}`);
|
|
@@ -73443,19 +74019,19 @@ function loadMCPConfiguration() {
|
|
|
73443
74019
|
// Environment variable path
|
|
73444
74020
|
process.env.MCP_CONFIG_PATH,
|
|
73445
74021
|
// Local project paths
|
|
73446
|
-
(0,
|
|
73447
|
-
(0,
|
|
74022
|
+
(0, import_path9.join)(process.cwd(), ".mcp", "config.json"),
|
|
74023
|
+
(0, import_path9.join)(process.cwd(), "mcp.config.json"),
|
|
73448
74024
|
// Home directory paths
|
|
73449
|
-
(0,
|
|
73450
|
-
(0,
|
|
74025
|
+
(0, import_path9.join)((0, import_os3.homedir)(), ".config", "probe", "mcp.json"),
|
|
74026
|
+
(0, import_path9.join)((0, import_os3.homedir)(), ".mcp", "config.json"),
|
|
73451
74027
|
// Claude-style config location
|
|
73452
|
-
(0,
|
|
74028
|
+
(0, import_path9.join)((0, import_os3.homedir)(), "Library", "Application Support", "Claude", "mcp_config.json")
|
|
73453
74029
|
].filter(Boolean);
|
|
73454
74030
|
let config2 = null;
|
|
73455
74031
|
for (const configPath of configPaths) {
|
|
73456
|
-
if ((0,
|
|
74032
|
+
if ((0, import_fs8.existsSync)(configPath)) {
|
|
73457
74033
|
try {
|
|
73458
|
-
const content = (0,
|
|
74034
|
+
const content = (0, import_fs8.readFileSync)(configPath, "utf8");
|
|
73459
74035
|
config2 = JSON.parse(content);
|
|
73460
74036
|
if (process.env.DEBUG === "1" || process.env.DEBUG_MCP === "1") {
|
|
73461
74037
|
console.error(`[MCP DEBUG] Loaded configuration from: ${configPath}`);
|
|
@@ -73576,16 +74152,16 @@ function parseEnabledServers(config2) {
|
|
|
73576
74152
|
}
|
|
73577
74153
|
return servers;
|
|
73578
74154
|
}
|
|
73579
|
-
var
|
|
74155
|
+
var import_fs8, import_path9, import_os3, import_url4, __filename4, __dirname4, DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_CONFIG;
|
|
73580
74156
|
var init_config = __esm({
|
|
73581
74157
|
"src/agent/mcp/config.js"() {
|
|
73582
74158
|
"use strict";
|
|
73583
|
-
|
|
73584
|
-
|
|
74159
|
+
import_fs8 = require("fs");
|
|
74160
|
+
import_path9 = require("path");
|
|
73585
74161
|
import_os3 = require("os");
|
|
73586
74162
|
import_url4 = require("url");
|
|
73587
74163
|
__filename4 = (0, import_url4.fileURLToPath)("file:///");
|
|
73588
|
-
__dirname4 = (0,
|
|
74164
|
+
__dirname4 = (0, import_path9.dirname)(__filename4);
|
|
73589
74165
|
DEFAULT_TIMEOUT = 3e4;
|
|
73590
74166
|
MAX_TIMEOUT = (() => {
|
|
73591
74167
|
if (process.env.MCP_MAX_TIMEOUT) {
|
|
@@ -73599,7 +74175,7 @@ var init_config = __esm({
|
|
|
73599
74175
|
// Example probe server configuration
|
|
73600
74176
|
"probe-local": {
|
|
73601
74177
|
command: "node",
|
|
73602
|
-
args: [(0,
|
|
74178
|
+
args: [(0, import_path9.join)(__dirname4, "../../../examples/chat/mcpServer.js")],
|
|
73603
74179
|
transport: "stdio",
|
|
73604
74180
|
enabled: false
|
|
73605
74181
|
},
|
|
@@ -81749,17 +82325,17 @@ async function parseSkillFile(skillFilePath, directoryName) {
|
|
|
81749
82325
|
description,
|
|
81750
82326
|
skillFilePath,
|
|
81751
82327
|
directoryName,
|
|
81752
|
-
sourceDir: (0,
|
|
82328
|
+
sourceDir: (0, import_path10.dirname)(skillFilePath)
|
|
81753
82329
|
},
|
|
81754
82330
|
error: null
|
|
81755
82331
|
};
|
|
81756
82332
|
}
|
|
81757
|
-
var import_promises2,
|
|
82333
|
+
var import_promises2, import_path10, import_yaml, SKILL_NAME_REGEX, MAX_SKILL_NAME_LENGTH, MAX_DESCRIPTION_CHARS;
|
|
81758
82334
|
var init_parser7 = __esm({
|
|
81759
82335
|
"src/agent/skills/parser.js"() {
|
|
81760
82336
|
"use strict";
|
|
81761
82337
|
import_promises2 = require("fs/promises");
|
|
81762
|
-
|
|
82338
|
+
import_path10 = require("path");
|
|
81763
82339
|
import_yaml = __toESM(require_dist(), 1);
|
|
81764
82340
|
SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
81765
82341
|
MAX_SKILL_NAME_LENGTH = 64;
|
|
@@ -81769,12 +82345,12 @@ var init_parser7 = __esm({
|
|
|
81769
82345
|
|
|
81770
82346
|
// src/agent/skills/registry.js
|
|
81771
82347
|
function isPathInside(basePath, targetPath) {
|
|
81772
|
-
const base2 = (0,
|
|
81773
|
-
const target = (0,
|
|
81774
|
-
const rel = (0,
|
|
82348
|
+
const base2 = (0, import_path11.resolve)(basePath);
|
|
82349
|
+
const target = (0, import_path11.resolve)(targetPath);
|
|
82350
|
+
const rel = (0, import_path11.relative)(base2, target);
|
|
81775
82351
|
if (rel === "") return true;
|
|
81776
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
81777
|
-
if ((0,
|
|
82352
|
+
if (rel === ".." || rel.startsWith(`..${import_path11.sep}`)) return false;
|
|
82353
|
+
if ((0, import_path11.isAbsolute)(rel)) return false;
|
|
81778
82354
|
return true;
|
|
81779
82355
|
}
|
|
81780
82356
|
function isSafeEntryName(name15) {
|
|
@@ -81782,19 +82358,19 @@ function isSafeEntryName(name15) {
|
|
|
81782
82358
|
if (name15.includes("\0")) return false;
|
|
81783
82359
|
return !name15.includes("/") && !name15.includes("\\");
|
|
81784
82360
|
}
|
|
81785
|
-
var
|
|
82361
|
+
var import_fs9, import_promises3, import_path11, DEFAULT_SKILL_DIRS, SKILL_FILE_NAME, SkillRegistry;
|
|
81786
82362
|
var init_registry = __esm({
|
|
81787
82363
|
"src/agent/skills/registry.js"() {
|
|
81788
82364
|
"use strict";
|
|
81789
|
-
|
|
82365
|
+
import_fs9 = require("fs");
|
|
81790
82366
|
import_promises3 = require("fs/promises");
|
|
81791
|
-
|
|
82367
|
+
import_path11 = require("path");
|
|
81792
82368
|
init_parser7();
|
|
81793
82369
|
DEFAULT_SKILL_DIRS = [".claude/skills", ".codex/skills", "skills", ".skills"];
|
|
81794
82370
|
SKILL_FILE_NAME = "SKILL.md";
|
|
81795
82371
|
SkillRegistry = class {
|
|
81796
82372
|
constructor({ repoRoot, skillDirs = DEFAULT_SKILL_DIRS, debug = false } = {}) {
|
|
81797
|
-
this.repoRoot = repoRoot ? (0,
|
|
82373
|
+
this.repoRoot = repoRoot ? (0, import_path11.resolve)(repoRoot) : process.cwd();
|
|
81798
82374
|
this.repoRootReal = null;
|
|
81799
82375
|
this.skillDirs = Array.isArray(skillDirs) && skillDirs.length > 0 ? skillDirs : DEFAULT_SKILL_DIRS;
|
|
81800
82376
|
this.debug = debug;
|
|
@@ -81848,8 +82424,8 @@ var init_registry = __esm({
|
|
|
81848
82424
|
}
|
|
81849
82425
|
}
|
|
81850
82426
|
async _resolveSkillDir(skillDir) {
|
|
81851
|
-
const resolved = (0,
|
|
81852
|
-
const repoRoot = this.repoRootReal || (0,
|
|
82427
|
+
const resolved = (0, import_path11.isAbsolute)(skillDir) ? (0, import_path11.resolve)(skillDir) : (0, import_path11.resolve)(this.repoRoot, skillDir);
|
|
82428
|
+
const repoRoot = this.repoRootReal || (0, import_path11.resolve)(this.repoRoot);
|
|
81853
82429
|
const resolvedReal = await this._resolveRealPath(resolved);
|
|
81854
82430
|
if (!resolvedReal) return null;
|
|
81855
82431
|
if (!isPathInside(repoRoot, resolvedReal)) {
|
|
@@ -81861,7 +82437,7 @@ var init_registry = __esm({
|
|
|
81861
82437
|
return resolvedReal;
|
|
81862
82438
|
}
|
|
81863
82439
|
async _scanSkillDir(dirPath) {
|
|
81864
|
-
if (!(0,
|
|
82440
|
+
if (!(0, import_fs9.existsSync)(dirPath)) return [];
|
|
81865
82441
|
let entries;
|
|
81866
82442
|
try {
|
|
81867
82443
|
entries = await (0, import_promises3.readdir)(dirPath, { withFileTypes: true });
|
|
@@ -81880,8 +82456,8 @@ var init_registry = __esm({
|
|
|
81880
82456
|
}
|
|
81881
82457
|
continue;
|
|
81882
82458
|
}
|
|
81883
|
-
const skillFolder = (0,
|
|
81884
|
-
const skillFilePath = (0,
|
|
82459
|
+
const skillFolder = (0, import_path11.join)(dirPath, entry.name);
|
|
82460
|
+
const skillFilePath = (0, import_path11.join)(skillFolder, SKILL_FILE_NAME);
|
|
81885
82461
|
let skillStat;
|
|
81886
82462
|
try {
|
|
81887
82463
|
skillStat = await (0, import_promises3.lstat)(skillFilePath);
|
|
@@ -81901,7 +82477,7 @@ var init_registry = __esm({
|
|
|
81901
82477
|
}
|
|
81902
82478
|
continue;
|
|
81903
82479
|
}
|
|
81904
|
-
if (!(0,
|
|
82480
|
+
if (!(0, import_fs9.existsSync)(skillFilePath)) continue;
|
|
81905
82481
|
const { skill, error: error40 } = await parseSkillFile(skillFilePath, entry.name);
|
|
81906
82482
|
if (!skill) {
|
|
81907
82483
|
if (error40) {
|
|
@@ -82826,9 +83402,9 @@ async function truncateIfNeeded(content, tokenCounter, sessionId, maxTokens) {
|
|
|
82826
83402
|
let tempFilePath = null;
|
|
82827
83403
|
let fileError = null;
|
|
82828
83404
|
try {
|
|
82829
|
-
const tempDir = (0,
|
|
83405
|
+
const tempDir = (0, import_path12.join)((0, import_os4.tmpdir)(), "probe-output");
|
|
82830
83406
|
await (0, import_promises4.mkdir)(tempDir, { recursive: true });
|
|
82831
|
-
tempFilePath = (0,
|
|
83407
|
+
tempFilePath = (0, import_path12.join)(tempDir, `tool-output-${sessionId || "unknown"}-${(0, import_crypto4.randomUUID)()}.txt`);
|
|
82832
83408
|
await (0, import_promises4.writeFile)(tempFilePath, content, "utf8");
|
|
82833
83409
|
} catch (err) {
|
|
82834
83410
|
fileError = err.message || "Unknown file system error";
|
|
@@ -82876,13 +83452,13 @@ ${truncatedBody}
|
|
|
82876
83452
|
error: fileError || void 0
|
|
82877
83453
|
};
|
|
82878
83454
|
}
|
|
82879
|
-
var import_promises4, import_os4,
|
|
83455
|
+
var import_promises4, import_os4, import_path12, import_crypto4, DEFAULT_MAX_OUTPUT_TOKENS, CHARS_PER_TOKEN, TAIL_TOKENS, MIN_LIMIT_FOR_TAIL;
|
|
82880
83456
|
var init_outputTruncator = __esm({
|
|
82881
83457
|
"src/agent/outputTruncator.js"() {
|
|
82882
83458
|
"use strict";
|
|
82883
83459
|
import_promises4 = require("fs/promises");
|
|
82884
83460
|
import_os4 = require("os");
|
|
82885
|
-
|
|
83461
|
+
import_path12 = require("path");
|
|
82886
83462
|
import_crypto4 = require("crypto");
|
|
82887
83463
|
DEFAULT_MAX_OUTPUT_TOKENS = 2e4;
|
|
82888
83464
|
CHARS_PER_TOKEN = 4;
|
|
@@ -94220,8 +94796,8 @@ async function executeBashCommand(command, options = {}) {
|
|
|
94220
94796
|
} = options;
|
|
94221
94797
|
let cwd = workingDirectory;
|
|
94222
94798
|
try {
|
|
94223
|
-
cwd = (0,
|
|
94224
|
-
if (!(0,
|
|
94799
|
+
cwd = (0, import_path13.resolve)(cwd);
|
|
94800
|
+
if (!(0, import_fs10.existsSync)(cwd)) {
|
|
94225
94801
|
throw new Error(`Working directory does not exist: ${cwd}`);
|
|
94226
94802
|
}
|
|
94227
94803
|
} catch (error40) {
|
|
@@ -94477,7 +95053,7 @@ function validateExecutionOptions(options = {}) {
|
|
|
94477
95053
|
if (options.workingDirectory) {
|
|
94478
95054
|
if (typeof options.workingDirectory !== "string") {
|
|
94479
95055
|
errors.push("workingDirectory must be a string");
|
|
94480
|
-
} else if (!(0,
|
|
95056
|
+
} else if (!(0, import_fs10.existsSync)(options.workingDirectory)) {
|
|
94481
95057
|
errors.push(`workingDirectory does not exist: ${options.workingDirectory}`);
|
|
94482
95058
|
}
|
|
94483
95059
|
}
|
|
@@ -94490,24 +95066,24 @@ function validateExecutionOptions(options = {}) {
|
|
|
94490
95066
|
warnings
|
|
94491
95067
|
};
|
|
94492
95068
|
}
|
|
94493
|
-
var import_child_process7,
|
|
95069
|
+
var import_child_process7, import_path13, import_fs10;
|
|
94494
95070
|
var init_bashExecutor = __esm({
|
|
94495
95071
|
"src/agent/bashExecutor.js"() {
|
|
94496
95072
|
"use strict";
|
|
94497
95073
|
import_child_process7 = require("child_process");
|
|
94498
|
-
|
|
94499
|
-
|
|
95074
|
+
import_path13 = require("path");
|
|
95075
|
+
import_fs10 = require("fs");
|
|
94500
95076
|
init_bashCommandUtils();
|
|
94501
95077
|
}
|
|
94502
95078
|
});
|
|
94503
95079
|
|
|
94504
95080
|
// src/tools/bash.js
|
|
94505
|
-
var import_ai,
|
|
95081
|
+
var import_ai, import_path14, bashTool;
|
|
94506
95082
|
var init_bash = __esm({
|
|
94507
95083
|
"src/tools/bash.js"() {
|
|
94508
95084
|
"use strict";
|
|
94509
95085
|
import_ai = require("ai");
|
|
94510
|
-
|
|
95086
|
+
import_path14 = require("path");
|
|
94511
95087
|
init_bashPermissions();
|
|
94512
95088
|
init_bashExecutor();
|
|
94513
95089
|
init_path_validation();
|
|
@@ -94624,12 +95200,12 @@ For code exploration, try these safe alternatives:
|
|
|
94624
95200
|
- npm list, pip list for package information`;
|
|
94625
95201
|
}
|
|
94626
95202
|
const defaultDir = getDefaultWorkingDirectory();
|
|
94627
|
-
const workingDir = workingDirectory ? (0,
|
|
95203
|
+
const workingDir = workingDirectory ? (0, import_path14.isAbsolute)(workingDirectory) ? (0, import_path14.resolve)(workingDirectory) : (0, import_path14.resolve)(defaultDir, workingDirectory) : defaultDir;
|
|
94628
95204
|
if (allowedFolders && allowedFolders.length > 0) {
|
|
94629
95205
|
const resolvedWorkingDir = safeRealpath(workingDir);
|
|
94630
95206
|
const isAllowed = allowedFolders.some((folder) => {
|
|
94631
95207
|
const resolvedFolder = safeRealpath(folder);
|
|
94632
|
-
return resolvedWorkingDir === resolvedFolder || resolvedWorkingDir.startsWith(resolvedFolder +
|
|
95208
|
+
return resolvedWorkingDir === resolvedFolder || resolvedWorkingDir.startsWith(resolvedFolder + import_path14.sep);
|
|
94633
95209
|
});
|
|
94634
95210
|
if (!isAllowed) {
|
|
94635
95211
|
const relativeDir = toRelativePath(workingDir, workspaceRoot);
|
|
@@ -95943,12 +96519,12 @@ async function createEnhancedClaudeCLIEngine(options = {}) {
|
|
|
95943
96519
|
console.log("[DEBUG] Built-in MCP server started");
|
|
95944
96520
|
console.log("[DEBUG] MCP URL:", `http://${host}:${port}/mcp`);
|
|
95945
96521
|
}
|
|
95946
|
-
mcpConfigPath =
|
|
96522
|
+
mcpConfigPath = import_path15.default.join(import_os5.default.tmpdir(), `probe-mcp-${session.id}.json`);
|
|
95947
96523
|
const mcpConfig = {
|
|
95948
96524
|
mcpServers: {
|
|
95949
96525
|
probe: {
|
|
95950
96526
|
command: "node",
|
|
95951
|
-
args: [
|
|
96527
|
+
args: [import_path15.default.join(process.cwd(), "mcp-probe-server.js")],
|
|
95952
96528
|
env: {
|
|
95953
96529
|
PROBE_WORKSPACE: process.cwd(),
|
|
95954
96530
|
DEBUG: debug ? "true" : "false"
|
|
@@ -96373,14 +96949,14 @@ function combinePrompts(systemPrompt, customPrompt, agent) {
|
|
|
96373
96949
|
}
|
|
96374
96950
|
return systemPrompt || "";
|
|
96375
96951
|
}
|
|
96376
|
-
var import_child_process8, import_crypto6, import_promises5,
|
|
96952
|
+
var import_child_process8, import_crypto6, import_promises5, import_path15, import_os5, import_events3;
|
|
96377
96953
|
var init_enhanced_claude_code = __esm({
|
|
96378
96954
|
"src/agent/engines/enhanced-claude-code.js"() {
|
|
96379
96955
|
"use strict";
|
|
96380
96956
|
import_child_process8 = require("child_process");
|
|
96381
96957
|
import_crypto6 = require("crypto");
|
|
96382
96958
|
import_promises5 = __toESM(require("fs/promises"), 1);
|
|
96383
|
-
|
|
96959
|
+
import_path15 = __toESM(require("path"), 1);
|
|
96384
96960
|
import_os5 = __toESM(require("os"), 1);
|
|
96385
96961
|
import_events3 = require("events");
|
|
96386
96962
|
init_built_in_server();
|
|
@@ -96751,7 +97327,7 @@ function debugLogToolResults(toolResults) {
|
|
|
96751
97327
|
console.log(`[DEBUG] tool: ${tr.toolName} | args: ${debugTruncate(argsStr)} | result: ${debugTruncate(resultStr)}`);
|
|
96752
97328
|
}
|
|
96753
97329
|
}
|
|
96754
|
-
var import_dotenv, import_anthropic2, import_openai2, import_google2, import_ai4, import_crypto8, import_events4,
|
|
97330
|
+
var import_dotenv, import_anthropic2, import_openai2, import_google2, import_ai4, import_crypto8, import_events4, import_fs11, import_promises6, import_path16, ENGINE_ACTIVITY_TIMEOUT_DEFAULT, ENGINE_ACTIVITY_TIMEOUT_MIN, ENGINE_ACTIVITY_TIMEOUT_MAX, MAX_TOOL_ITERATIONS, MAX_HISTORY_MESSAGES, MAX_IMAGE_FILE_SIZE, ProbeAgent;
|
|
96755
97331
|
var init_ProbeAgent = __esm({
|
|
96756
97332
|
"src/agent/ProbeAgent.js"() {
|
|
96757
97333
|
"use strict";
|
|
@@ -96763,10 +97339,11 @@ var init_ProbeAgent = __esm({
|
|
|
96763
97339
|
import_ai4 = require("ai");
|
|
96764
97340
|
import_crypto8 = require("crypto");
|
|
96765
97341
|
import_events4 = require("events");
|
|
96766
|
-
|
|
97342
|
+
import_fs11 = require("fs");
|
|
96767
97343
|
import_promises6 = require("fs/promises");
|
|
96768
|
-
|
|
97344
|
+
import_path16 = require("path");
|
|
96769
97345
|
init_tokenCounter();
|
|
97346
|
+
init_simpleTelemetry();
|
|
96770
97347
|
init_InMemoryStorageAdapter();
|
|
96771
97348
|
init_HookManager();
|
|
96772
97349
|
init_imageConfig();
|
|
@@ -97430,7 +98007,7 @@ var init_ProbeAgent = __esm({
|
|
|
97430
98007
|
if (!imagePath) {
|
|
97431
98008
|
throw new Error("Image path is required");
|
|
97432
98009
|
}
|
|
97433
|
-
const filename = (0,
|
|
98010
|
+
const filename = (0, import_path16.basename)(imagePath);
|
|
97434
98011
|
const extension = filename.toLowerCase().split(".").pop();
|
|
97435
98012
|
if (!extension || !SUPPORTED_IMAGE_EXTENSIONS.includes(extension)) {
|
|
97436
98013
|
throw new Error(`Invalid or unsupported image extension: ${extension}. Supported formats: ${SUPPORTED_IMAGE_EXTENSIONS.join(", ")}`);
|
|
@@ -98170,10 +98747,10 @@ var init_ProbeAgent = __esm({
|
|
|
98170
98747
|
execute: async (params) => {
|
|
98171
98748
|
let resolvedWorkingDirectory = this.workspaceRoot || this.cwd || this.allowedFolders && this.allowedFolders[0] || process.cwd();
|
|
98172
98749
|
if (params.workingDirectory) {
|
|
98173
|
-
const requestedDir = safeRealpath((0,
|
|
98750
|
+
const requestedDir = safeRealpath((0, import_path16.isAbsolute)(params.workingDirectory) ? (0, import_path16.resolve)(params.workingDirectory) : (0, import_path16.resolve)(resolvedWorkingDirectory, params.workingDirectory));
|
|
98174
98751
|
const isWithinAllowed = !this.allowedFolders || this.allowedFolders.length === 0 || this.allowedFolders.some((folder) => {
|
|
98175
98752
|
const resolvedFolder = safeRealpath(folder);
|
|
98176
|
-
return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder +
|
|
98753
|
+
return requestedDir === resolvedFolder || requestedDir.startsWith(resolvedFolder + import_path16.sep);
|
|
98177
98754
|
});
|
|
98178
98755
|
if (isWithinAllowed) {
|
|
98179
98756
|
resolvedWorkingDirectory = requestedDir;
|
|
@@ -98262,7 +98839,7 @@ var init_ProbeAgent = __esm({
|
|
|
98262
98839
|
});
|
|
98263
98840
|
let toolResultContent = typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
98264
98841
|
if (this.workspaceRoot && toolResultContent) {
|
|
98265
|
-
const wsPrefix = this.workspaceRoot.endsWith(
|
|
98842
|
+
const wsPrefix = this.workspaceRoot.endsWith(import_path16.sep) ? this.workspaceRoot : this.workspaceRoot + import_path16.sep;
|
|
98266
98843
|
toolResultContent = toolResultContent.split(wsPrefix).join("");
|
|
98267
98844
|
}
|
|
98268
98845
|
const { cleanedContent, extractedBlocks } = extractRawOutputBlocks(toolResultContent);
|
|
@@ -98632,7 +99209,7 @@ var init_ProbeAgent = __esm({
|
|
|
98632
99209
|
let resolvedPath = imagePath;
|
|
98633
99210
|
if (!imagePath.includes("/") && !imagePath.includes("\\")) {
|
|
98634
99211
|
for (const dir of listFilesDirectories) {
|
|
98635
|
-
const potentialPath = (0,
|
|
99212
|
+
const potentialPath = (0, import_path16.resolve)(dir, imagePath);
|
|
98636
99213
|
const loaded = await this.loadImageIfValid(potentialPath);
|
|
98637
99214
|
if (loaded) {
|
|
98638
99215
|
if (this.debug) {
|
|
@@ -98657,7 +99234,7 @@ var init_ProbeAgent = __esm({
|
|
|
98657
99234
|
let match2;
|
|
98658
99235
|
while ((match2 = fileHeaderPattern.exec(content)) !== null) {
|
|
98659
99236
|
const filePath = match2[1].trim();
|
|
98660
|
-
const dir = (0,
|
|
99237
|
+
const dir = (0, import_path16.dirname)(filePath);
|
|
98661
99238
|
if (dir && dir !== ".") {
|
|
98662
99239
|
directories.push(dir);
|
|
98663
99240
|
if (this.debug) {
|
|
@@ -98702,17 +99279,17 @@ var init_ProbeAgent = __esm({
|
|
|
98702
99279
|
const allowedDirs = this.allowedFolders && this.allowedFolders.length > 0 ? this.allowedFolders : [process.cwd()];
|
|
98703
99280
|
let absolutePath;
|
|
98704
99281
|
let isPathAllowed2 = false;
|
|
98705
|
-
if ((0,
|
|
98706
|
-
absolutePath = safeRealpath((0,
|
|
99282
|
+
if ((0, import_path16.isAbsolute)(imagePath)) {
|
|
99283
|
+
absolutePath = safeRealpath((0, import_path16.resolve)(imagePath));
|
|
98707
99284
|
isPathAllowed2 = allowedDirs.some((dir) => {
|
|
98708
99285
|
const resolvedDir = safeRealpath(dir);
|
|
98709
|
-
return absolutePath === resolvedDir || absolutePath.startsWith(resolvedDir +
|
|
99286
|
+
return absolutePath === resolvedDir || absolutePath.startsWith(resolvedDir + import_path16.sep);
|
|
98710
99287
|
});
|
|
98711
99288
|
} else {
|
|
98712
99289
|
for (const dir of allowedDirs) {
|
|
98713
99290
|
const resolvedDir = safeRealpath(dir);
|
|
98714
|
-
const resolvedPath = safeRealpath((0,
|
|
98715
|
-
if (resolvedPath === resolvedDir || resolvedPath.startsWith(resolvedDir +
|
|
99291
|
+
const resolvedPath = safeRealpath((0, import_path16.resolve)(dir, imagePath));
|
|
99292
|
+
if (resolvedPath === resolvedDir || resolvedPath.startsWith(resolvedDir + import_path16.sep)) {
|
|
98716
99293
|
absolutePath = resolvedPath;
|
|
98717
99294
|
isPathAllowed2 = true;
|
|
98718
99295
|
break;
|
|
@@ -98900,8 +99477,8 @@ var init_ProbeAgent = __esm({
|
|
|
98900
99477
|
const hasConfiguredName = !!configuredName;
|
|
98901
99478
|
let guidanceCandidates = [];
|
|
98902
99479
|
if (hasConfiguredName) {
|
|
98903
|
-
const targetName = (0,
|
|
98904
|
-
if (configuredName !== targetName || configuredName.includes("/") || configuredName.includes("\\") || configuredName.includes("..") || (0,
|
|
99480
|
+
const targetName = (0, import_path16.basename)(configuredName);
|
|
99481
|
+
if (configuredName !== targetName || configuredName.includes("/") || configuredName.includes("\\") || configuredName.includes("..") || (0, import_path16.isAbsolute)(configuredName)) {
|
|
98905
99482
|
console.warn(`[WARN] Invalid architectureFileName (must be a simple filename): ${configuredName}`);
|
|
98906
99483
|
} else if (targetName) {
|
|
98907
99484
|
const targetLower = targetName.toLowerCase();
|
|
@@ -98914,7 +99491,7 @@ var init_ProbeAgent = __esm({
|
|
|
98914
99491
|
} else {
|
|
98915
99492
|
guidanceCandidates = ["agents.md", "claude.md"];
|
|
98916
99493
|
}
|
|
98917
|
-
if (!(0,
|
|
99494
|
+
if (!(0, import_fs11.existsSync)(rootDirectory)) {
|
|
98918
99495
|
this._architectureContextLoaded = true;
|
|
98919
99496
|
return null;
|
|
98920
99497
|
}
|
|
@@ -98968,7 +99545,7 @@ var init_ProbeAgent = __esm({
|
|
|
98968
99545
|
pushEntry(architectureMatch);
|
|
98969
99546
|
const contexts = [];
|
|
98970
99547
|
for (const entry of uniqueEntries) {
|
|
98971
|
-
const filePath = (0,
|
|
99548
|
+
const filePath = (0, import_path16.resolve)(rootDirectory, entry.name);
|
|
98972
99549
|
try {
|
|
98973
99550
|
const content = await (0, import_promises6.readFile)(filePath, "utf8");
|
|
98974
99551
|
let kind = "other";
|
|
@@ -99033,10 +99610,10 @@ ${this.architectureContext.content}
|
|
|
99033
99610
|
}
|
|
99034
99611
|
_getSkillsRepoRoot() {
|
|
99035
99612
|
if (this.workspaceRoot) {
|
|
99036
|
-
return (0,
|
|
99613
|
+
return (0, import_path16.resolve)(this.workspaceRoot);
|
|
99037
99614
|
}
|
|
99038
99615
|
if (this.allowedFolders && this.allowedFolders.length > 0) {
|
|
99039
|
-
return (0,
|
|
99616
|
+
return (0, import_path16.resolve)(this.allowedFolders[0]);
|
|
99040
99617
|
}
|
|
99041
99618
|
return process.cwd();
|
|
99042
99619
|
}
|
|
@@ -100105,7 +100682,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
100105
100682
|
};
|
|
100106
100683
|
let aiResult;
|
|
100107
100684
|
if (this.tracer) {
|
|
100108
|
-
const inputPreview = message
|
|
100685
|
+
const inputPreview = truncateForSpan(message, 4096);
|
|
100109
100686
|
aiResult = await this.tracer.withSpan("ai.request", executeAIRequest, {
|
|
100110
100687
|
"ai.model": this.model,
|
|
100111
100688
|
"ai.provider": this.clientApiProvider || "auto",
|
|
@@ -100115,6 +100692,12 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
100115
100692
|
"max_tokens": maxResponseTokens,
|
|
100116
100693
|
"temperature": 0.3,
|
|
100117
100694
|
"message_count": currentMessages.length
|
|
100695
|
+
}, (span, result) => {
|
|
100696
|
+
const text = result?.finalText || "";
|
|
100697
|
+
span.setAttributes({
|
|
100698
|
+
"ai.output": truncateForSpan(text),
|
|
100699
|
+
"ai.output_length": text.length
|
|
100700
|
+
});
|
|
100118
100701
|
});
|
|
100119
100702
|
} else {
|
|
100120
100703
|
aiResult = await executeAIRequest();
|
|
@@ -102451,7 +103034,7 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
|
|
|
102451
103034
|
"Remember: if your search returned relevant results, use nextPage=true to check for more before outputting."
|
|
102452
103035
|
].join("\n");
|
|
102453
103036
|
}
|
|
102454
|
-
var import_ai5,
|
|
103037
|
+
var import_ai5, import_fs12, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool;
|
|
102455
103038
|
var init_vercel = __esm({
|
|
102456
103039
|
"src/tools/vercel.js"() {
|
|
102457
103040
|
"use strict";
|
|
@@ -102462,9 +103045,10 @@ var init_vercel = __esm({
|
|
|
102462
103045
|
init_delegate();
|
|
102463
103046
|
init_analyzeAll();
|
|
102464
103047
|
init_common();
|
|
102465
|
-
|
|
103048
|
+
import_fs12 = require("fs");
|
|
102466
103049
|
init_error_types();
|
|
102467
103050
|
init_hashline();
|
|
103051
|
+
init_simpleTelemetry();
|
|
102468
103052
|
CODE_SEARCH_SCHEMA = {
|
|
102469
103053
|
type: "object",
|
|
102470
103054
|
properties: {
|
|
@@ -102630,6 +103214,12 @@ var init_vercel = __esm({
|
|
|
102630
103214
|
const delegateResult = options.tracer?.withSpan ? await options.tracer.withSpan("search.delegate", runDelegation, {
|
|
102631
103215
|
"search.query": searchQuery,
|
|
102632
103216
|
"search.path": searchPath
|
|
103217
|
+
}, (span, result) => {
|
|
103218
|
+
const text = typeof result === "string" ? result : "";
|
|
103219
|
+
span.setAttributes({
|
|
103220
|
+
"search.delegate.output": truncateForSpan(text),
|
|
103221
|
+
"search.delegate.output_length": text.length
|
|
103222
|
+
});
|
|
102633
103223
|
}) : await runDelegation();
|
|
102634
103224
|
const targets = parseDelegatedTargets(delegateResult);
|
|
102635
103225
|
if (!targets.length) {
|
|
@@ -102649,7 +103239,7 @@ var init_vercel = __esm({
|
|
|
102649
103239
|
const validatedTargets = [];
|
|
102650
103240
|
for (const target of resolvedTargets) {
|
|
102651
103241
|
const { filePart, suffix } = splitTargetSuffix(target);
|
|
102652
|
-
if ((0,
|
|
103242
|
+
if ((0, import_fs12.existsSync)(filePart)) {
|
|
102653
103243
|
validatedTargets.push(target);
|
|
102654
103244
|
continue;
|
|
102655
103245
|
}
|
|
@@ -102658,7 +103248,7 @@ var init_vercel = __esm({
|
|
|
102658
103248
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
102659
103249
|
if (parts[i] === parts[i + 1]) {
|
|
102660
103250
|
const candidate = "/" + [...parts.slice(0, i), ...parts.slice(i + 1)].join("/");
|
|
102661
|
-
if ((0,
|
|
103251
|
+
if ((0, import_fs12.existsSync)(candidate)) {
|
|
102662
103252
|
validatedTargets.push(candidate + suffix);
|
|
102663
103253
|
if (debug) console.error(`[search-delegate] Fixed doubled path segment: ${filePart} \u2192 ${candidate}`);
|
|
102664
103254
|
fixed = true;
|
|
@@ -102671,7 +103261,7 @@ var init_vercel = __esm({
|
|
|
102671
103261
|
if (altBase === delegateBase) continue;
|
|
102672
103262
|
const altResolved = resolveTargetPath(target, altBase);
|
|
102673
103263
|
const { filePart: altFile } = splitTargetSuffix(altResolved);
|
|
102674
|
-
if ((0,
|
|
103264
|
+
if ((0, import_fs12.existsSync)(altFile)) {
|
|
102675
103265
|
validatedTargets.push(altResolved);
|
|
102676
103266
|
if (debug) console.error(`[search-delegate] Resolved with alt base: ${filePart} \u2192 ${altFile}`);
|
|
102677
103267
|
fixed = true;
|
|
@@ -102796,13 +103386,13 @@ var init_vercel = __esm({
|
|
|
102796
103386
|
const { join: pathJoin, sep: pathSep } = await import("path");
|
|
102797
103387
|
extractFiles = extractFiles.map((target) => {
|
|
102798
103388
|
const { filePart, suffix } = splitTargetSuffix(target);
|
|
102799
|
-
if ((0,
|
|
103389
|
+
if ((0, import_fs12.existsSync)(filePart)) return target;
|
|
102800
103390
|
const cwdPrefix = effectiveCwd.endsWith(pathSep) ? effectiveCwd : effectiveCwd + pathSep;
|
|
102801
103391
|
const relativePart = filePart.startsWith(cwdPrefix) ? filePart.slice(cwdPrefix.length) : null;
|
|
102802
103392
|
if (relativePart) {
|
|
102803
103393
|
for (const folder of options.allowedFolders) {
|
|
102804
103394
|
const candidate = pathJoin(folder, relativePart);
|
|
102805
|
-
if ((0,
|
|
103395
|
+
if ((0, import_fs12.existsSync)(candidate)) {
|
|
102806
103396
|
if (debug) console.error(`[extract] Auto-fixed path: ${filePart} \u2192 ${candidate}`);
|
|
102807
103397
|
return candidate + suffix;
|
|
102808
103398
|
}
|
|
@@ -102815,7 +103405,7 @@ var init_vercel = __esm({
|
|
|
102815
103405
|
if (filePart.startsWith(wsParent)) {
|
|
102816
103406
|
const tail = filePart.slice(wsParent.length);
|
|
102817
103407
|
const candidate = pathJoin(folderPrefix, tail);
|
|
102818
|
-
if (candidate !== filePart && (0,
|
|
103408
|
+
if (candidate !== filePart && (0, import_fs12.existsSync)(candidate)) {
|
|
102819
103409
|
if (debug) console.error(`[extract] Auto-fixed path via workspace: ${filePart} \u2192 ${candidate}`);
|
|
102820
103410
|
return candidate + suffix;
|
|
102821
103411
|
}
|
|
@@ -103309,12 +103899,12 @@ function isPathAllowed(filePath, allowedFolders) {
|
|
|
103309
103899
|
if (!allowedFolders || allowedFolders.length === 0) {
|
|
103310
103900
|
const resolvedPath2 = safeRealpath(filePath);
|
|
103311
103901
|
const cwd = safeRealpath(process.cwd());
|
|
103312
|
-
return resolvedPath2 === cwd || resolvedPath2.startsWith(cwd +
|
|
103902
|
+
return resolvedPath2 === cwd || resolvedPath2.startsWith(cwd + import_path17.sep);
|
|
103313
103903
|
}
|
|
103314
103904
|
const resolvedPath = safeRealpath(filePath);
|
|
103315
103905
|
return allowedFolders.some((folder) => {
|
|
103316
103906
|
const allowedPath = safeRealpath(folder);
|
|
103317
|
-
return resolvedPath === allowedPath || resolvedPath.startsWith(allowedPath +
|
|
103907
|
+
return resolvedPath === allowedPath || resolvedPath.startsWith(allowedPath + import_path17.sep);
|
|
103318
103908
|
});
|
|
103319
103909
|
}
|
|
103320
103910
|
function parseFileToolOptions(options = {}) {
|
|
@@ -103354,7 +103944,7 @@ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualif
|
|
|
103354
103944
|
return `Error editing ${file_path}: Symbol "${symbol17}" has changed since you last read it. Use the extract tool with targets="${file_path}#${symbol17}" to re-read the current content, then retry.`;
|
|
103355
103945
|
}
|
|
103356
103946
|
}
|
|
103357
|
-
const content = await
|
|
103947
|
+
const content = await import_fs13.promises.readFile(resolvedPath, "utf-8");
|
|
103358
103948
|
const lines = content.split("\n");
|
|
103359
103949
|
if (position) {
|
|
103360
103950
|
const refIndent = detectBaseIndent(symbolInfo.code);
|
|
@@ -103365,7 +103955,7 @@ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualif
|
|
|
103365
103955
|
} else {
|
|
103366
103956
|
lines.splice(symbolInfo.startLine - 1, 0, ...newLines, "");
|
|
103367
103957
|
}
|
|
103368
|
-
await
|
|
103958
|
+
await import_fs13.promises.writeFile(resolvedPath, lines.join("\n"), "utf-8");
|
|
103369
103959
|
if (fileTracker) {
|
|
103370
103960
|
const updated = await findSymbol(resolvedPath, symbol17, cwd || process.cwd());
|
|
103371
103961
|
if (updated) {
|
|
@@ -103383,7 +103973,7 @@ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualif
|
|
|
103383
103973
|
const reindented = reindent(new_string, originalIndent);
|
|
103384
103974
|
const newLines = reindented.split("\n");
|
|
103385
103975
|
lines.splice(symbolInfo.startLine - 1, symbolInfo.endLine - symbolInfo.startLine + 1, ...newLines);
|
|
103386
|
-
await
|
|
103976
|
+
await import_fs13.promises.writeFile(resolvedPath, lines.join("\n"), "utf-8");
|
|
103387
103977
|
if (fileTracker) {
|
|
103388
103978
|
const updated = await findSymbol(resolvedPath, symbol17, cwd || process.cwd());
|
|
103389
103979
|
if (updated) {
|
|
@@ -103438,7 +104028,7 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
103438
104028
|
if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
|
|
103439
104029
|
return 'Error editing file: Invalid position - must be "before" or "after". Use position="before" to insert before the line, or position="after" to insert after it.';
|
|
103440
104030
|
}
|
|
103441
|
-
const content = await
|
|
104031
|
+
const content = await import_fs13.promises.readFile(resolvedPath, "utf-8");
|
|
103442
104032
|
const fileLines = content.split("\n");
|
|
103443
104033
|
if (startLine > fileLines.length) {
|
|
103444
104034
|
return `Error editing file: Line ${startLine} is beyond file length (${fileLines.length} lines). Use 'extract' to read the current file content.`;
|
|
@@ -103467,20 +104057,20 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
103467
104057
|
const newLines = cleaned === "" ? [] : cleaned.split("\n");
|
|
103468
104058
|
if (position === "after") {
|
|
103469
104059
|
fileLines.splice(startLine, 0, ...newLines);
|
|
103470
|
-
await
|
|
104060
|
+
await import_fs13.promises.writeFile(resolvedPath, fileLines.join("\n"), "utf-8");
|
|
103471
104061
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103472
104062
|
const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted after line ${startLine}`;
|
|
103473
104063
|
return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine, action, modifications);
|
|
103474
104064
|
} else if (position === "before") {
|
|
103475
104065
|
fileLines.splice(startLine - 1, 0, ...newLines);
|
|
103476
|
-
await
|
|
104066
|
+
await import_fs13.promises.writeFile(resolvedPath, fileLines.join("\n"), "utf-8");
|
|
103477
104067
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103478
104068
|
const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted before line ${startLine}`;
|
|
103479
104069
|
return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
103480
104070
|
} else {
|
|
103481
104071
|
const replacedCount = endLine - startLine + 1;
|
|
103482
104072
|
fileLines.splice(startLine - 1, replacedCount, ...newLines);
|
|
103483
|
-
await
|
|
104073
|
+
await import_fs13.promises.writeFile(resolvedPath, fileLines.join("\n"), "utf-8");
|
|
103484
104074
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103485
104075
|
let action;
|
|
103486
104076
|
if (newLines.length === 0) {
|
|
@@ -103493,14 +104083,14 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
103493
104083
|
return buildLineEditResponse(file_path, startLine, endLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
103494
104084
|
}
|
|
103495
104085
|
}
|
|
103496
|
-
var import_ai6,
|
|
104086
|
+
var import_ai6, import_fs13, import_path17, import_fs14, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
103497
104087
|
var init_edit = __esm({
|
|
103498
104088
|
"src/tools/edit.js"() {
|
|
103499
104089
|
"use strict";
|
|
103500
104090
|
import_ai6 = require("ai");
|
|
103501
|
-
import_fs12 = require("fs");
|
|
103502
|
-
import_path16 = require("path");
|
|
103503
104091
|
import_fs13 = require("fs");
|
|
104092
|
+
import_path17 = require("path");
|
|
104093
|
+
import_fs14 = require("fs");
|
|
103504
104094
|
init_path_validation();
|
|
103505
104095
|
init_fuzzyMatch();
|
|
103506
104096
|
init_symbolEdit();
|
|
@@ -103576,7 +104166,7 @@ Parameters:
|
|
|
103576
104166
|
return `Error editing file: Invalid new_string - must be a string. Provide the replacement content as a string value (empty string "" is valid for deletions).`;
|
|
103577
104167
|
}
|
|
103578
104168
|
const effectiveCwd = workingDirectory || cwd || process.cwd();
|
|
103579
|
-
const resolvedPath = (0,
|
|
104169
|
+
const resolvedPath = (0, import_path17.isAbsolute)(file_path) ? file_path : (0, import_path17.resolve)(effectiveCwd, file_path);
|
|
103580
104170
|
if (debug) {
|
|
103581
104171
|
console.error(`[Edit] Attempting to edit file: ${resolvedPath}`);
|
|
103582
104172
|
}
|
|
@@ -103584,7 +104174,7 @@ Parameters:
|
|
|
103584
104174
|
const relativePath = toRelativePath(resolvedPath, workspaceRoot);
|
|
103585
104175
|
return `Error editing file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
|
|
103586
104176
|
}
|
|
103587
|
-
if (!(0,
|
|
104177
|
+
if (!(0, import_fs14.existsSync)(resolvedPath)) {
|
|
103588
104178
|
return `Error editing file: File not found - ${file_path}. Verify the path is correct and the file exists. Use 'search' to find files by name, or 'create' to make a new file.`;
|
|
103589
104179
|
}
|
|
103590
104180
|
if (options.fileTracker && !options.fileTracker.isFileSeen(resolvedPath)) {
|
|
@@ -103612,7 +104202,7 @@ Parameters:
|
|
|
103612
104202
|
Use the extract tool with targets="${displayPath}" to re-read the file, then retry.`;
|
|
103613
104203
|
}
|
|
103614
104204
|
}
|
|
103615
|
-
const content = await
|
|
104205
|
+
const content = await import_fs13.promises.readFile(resolvedPath, "utf-8");
|
|
103616
104206
|
let matchTarget = old_string;
|
|
103617
104207
|
let matchStrategy = "exact";
|
|
103618
104208
|
if (!content.includes(old_string)) {
|
|
@@ -103644,7 +104234,7 @@ Use the extract tool with targets="${displayPath}" to re-read the file, then ret
|
|
|
103644
104234
|
if (newContent === content) {
|
|
103645
104235
|
return `Error editing file: No changes made - the replacement result is identical to the original. Verify that old_string and new_string are actually different. If fuzzy matching was used, the matched text may already equal new_string.`;
|
|
103646
104236
|
}
|
|
103647
|
-
await
|
|
104237
|
+
await import_fs13.promises.writeFile(resolvedPath, newContent, "utf-8");
|
|
103648
104238
|
if (options.fileTracker) {
|
|
103649
104239
|
await options.fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103650
104240
|
options.fileTracker.recordTextEdit(resolvedPath);
|
|
@@ -103707,7 +104297,7 @@ Important:
|
|
|
103707
104297
|
return `Error creating file: Invalid content - must be a string. Provide the file content as a string value (empty string "" is valid for an empty file).`;
|
|
103708
104298
|
}
|
|
103709
104299
|
const effectiveCwd = workingDirectory || cwd || process.cwd();
|
|
103710
|
-
const resolvedPath = (0,
|
|
104300
|
+
const resolvedPath = (0, import_path17.isAbsolute)(file_path) ? file_path : (0, import_path17.resolve)(effectiveCwd, file_path);
|
|
103711
104301
|
if (debug) {
|
|
103712
104302
|
console.error(`[Create] Attempting to create file: ${resolvedPath}`);
|
|
103713
104303
|
}
|
|
@@ -103715,13 +104305,13 @@ Important:
|
|
|
103715
104305
|
const relativePath = toRelativePath(resolvedPath, workspaceRoot);
|
|
103716
104306
|
return `Error creating file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
|
|
103717
104307
|
}
|
|
103718
|
-
if ((0,
|
|
104308
|
+
if ((0, import_fs14.existsSync)(resolvedPath) && !overwrite) {
|
|
103719
104309
|
return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
|
|
103720
104310
|
}
|
|
103721
|
-
const existed = (0,
|
|
103722
|
-
const dir = (0,
|
|
103723
|
-
await
|
|
103724
|
-
await
|
|
104311
|
+
const existed = (0, import_fs14.existsSync)(resolvedPath);
|
|
104312
|
+
const dir = (0, import_path17.dirname)(resolvedPath);
|
|
104313
|
+
await import_fs13.promises.mkdir(dir, { recursive: true });
|
|
104314
|
+
await import_fs13.promises.writeFile(resolvedPath, content, "utf-8");
|
|
103725
104315
|
if (options.fileTracker) await options.fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103726
104316
|
const action = existed && overwrite ? "overwrote" : "created";
|
|
103727
104317
|
const bytes = Buffer.byteLength(content, "utf-8");
|
|
@@ -104362,10 +104952,10 @@ async function listFilesByLevel(options) {
|
|
|
104362
104952
|
maxFiles = 100,
|
|
104363
104953
|
respectGitignore = true
|
|
104364
104954
|
} = options;
|
|
104365
|
-
if (!
|
|
104955
|
+
if (!import_fs15.default.existsSync(directory)) {
|
|
104366
104956
|
throw new Error(`Directory does not exist: ${directory}`);
|
|
104367
104957
|
}
|
|
104368
|
-
const gitDirExists =
|
|
104958
|
+
const gitDirExists = import_fs15.default.existsSync(import_path18.default.join(directory, ".git"));
|
|
104369
104959
|
if (gitDirExists && respectGitignore) {
|
|
104370
104960
|
try {
|
|
104371
104961
|
return await listFilesUsingGit(directory, maxFiles);
|
|
@@ -104380,8 +104970,8 @@ async function listFilesUsingGit(directory, maxFiles) {
|
|
|
104380
104970
|
const { stdout } = await execAsync3("git ls-files", { cwd: directory });
|
|
104381
104971
|
const files = stdout.split("\n").filter(Boolean);
|
|
104382
104972
|
const sortedFiles = files.sort((a, b) => {
|
|
104383
|
-
const depthA = a.split(
|
|
104384
|
-
const depthB = b.split(
|
|
104973
|
+
const depthA = a.split(import_path18.default.sep).length;
|
|
104974
|
+
const depthB = b.split(import_path18.default.sep).length;
|
|
104385
104975
|
return depthA - depthB;
|
|
104386
104976
|
});
|
|
104387
104977
|
return sortedFiles.slice(0, maxFiles);
|
|
@@ -104396,25 +104986,25 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
|
|
|
104396
104986
|
while (queue.length > 0 && result.length < maxFiles) {
|
|
104397
104987
|
const { dir, level } = queue.shift();
|
|
104398
104988
|
try {
|
|
104399
|
-
const entries =
|
|
104989
|
+
const entries = import_fs15.default.readdirSync(dir, { withFileTypes: true });
|
|
104400
104990
|
const files = entries.filter((entry) => {
|
|
104401
|
-
const fullPath =
|
|
104991
|
+
const fullPath = import_path18.default.join(dir, entry.name);
|
|
104402
104992
|
return getEntryTypeSync(entry, fullPath).isFile;
|
|
104403
104993
|
});
|
|
104404
104994
|
for (const file2 of files) {
|
|
104405
104995
|
if (result.length >= maxFiles) break;
|
|
104406
|
-
const filePath =
|
|
104407
|
-
const relativePath =
|
|
104996
|
+
const filePath = import_path18.default.join(dir, file2.name);
|
|
104997
|
+
const relativePath = import_path18.default.relative(directory, filePath);
|
|
104408
104998
|
if (shouldIgnore(relativePath, ignorePatterns)) continue;
|
|
104409
104999
|
result.push(relativePath);
|
|
104410
105000
|
}
|
|
104411
105001
|
const dirs = entries.filter((entry) => {
|
|
104412
|
-
const fullPath =
|
|
105002
|
+
const fullPath = import_path18.default.join(dir, entry.name);
|
|
104413
105003
|
return getEntryTypeSync(entry, fullPath).isDirectory;
|
|
104414
105004
|
});
|
|
104415
105005
|
for (const subdir of dirs) {
|
|
104416
|
-
const subdirPath =
|
|
104417
|
-
const relativeSubdirPath =
|
|
105006
|
+
const subdirPath = import_path18.default.join(dir, subdir.name);
|
|
105007
|
+
const relativeSubdirPath = import_path18.default.relative(directory, subdirPath);
|
|
104418
105008
|
if (shouldIgnore(relativeSubdirPath, ignorePatterns)) continue;
|
|
104419
105009
|
if (subdir.name === "node_modules" || subdir.name === ".git") continue;
|
|
104420
105010
|
queue.push({ dir: subdirPath, level: level + 1 });
|
|
@@ -104426,12 +105016,12 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
|
|
|
104426
105016
|
return result;
|
|
104427
105017
|
}
|
|
104428
105018
|
function loadGitignorePatterns(directory) {
|
|
104429
|
-
const gitignorePath =
|
|
104430
|
-
if (!
|
|
105019
|
+
const gitignorePath = import_path18.default.join(directory, ".gitignore");
|
|
105020
|
+
if (!import_fs15.default.existsSync(gitignorePath)) {
|
|
104431
105021
|
return [];
|
|
104432
105022
|
}
|
|
104433
105023
|
try {
|
|
104434
|
-
const content =
|
|
105024
|
+
const content = import_fs15.default.readFileSync(gitignorePath, "utf8");
|
|
104435
105025
|
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
104436
105026
|
} catch (error40) {
|
|
104437
105027
|
console.error(`Warning: Could not read .gitignore: ${error40.message}`);
|
|
@@ -104449,12 +105039,12 @@ function shouldIgnore(filePath, ignorePatterns) {
|
|
|
104449
105039
|
}
|
|
104450
105040
|
return false;
|
|
104451
105041
|
}
|
|
104452
|
-
var
|
|
105042
|
+
var import_fs15, import_path18, import_util14, import_child_process10, execAsync3;
|
|
104453
105043
|
var init_file_lister = __esm({
|
|
104454
105044
|
"src/utils/file-lister.js"() {
|
|
104455
105045
|
"use strict";
|
|
104456
|
-
|
|
104457
|
-
|
|
105046
|
+
import_fs15 = __toESM(require("fs"), 1);
|
|
105047
|
+
import_path18 = __toESM(require("path"), 1);
|
|
104458
105048
|
import_util14 = require("util");
|
|
104459
105049
|
import_child_process10 = require("child_process");
|
|
104460
105050
|
init_symlink_utils();
|
|
@@ -104462,568 +105052,6 @@ var init_file_lister = __esm({
|
|
|
104462
105052
|
}
|
|
104463
105053
|
});
|
|
104464
105054
|
|
|
104465
|
-
// src/agent/otelLogBridge.js
|
|
104466
|
-
function getOtelApi() {
|
|
104467
|
-
if (otelApiAttempted) return otelApi;
|
|
104468
|
-
otelApiAttempted = true;
|
|
104469
|
-
try {
|
|
104470
|
-
otelApi = (function(name15) {
|
|
104471
|
-
return _require(name15);
|
|
104472
|
-
})("@opentelemetry/api");
|
|
104473
|
-
} catch {
|
|
104474
|
-
}
|
|
104475
|
-
return otelApi;
|
|
104476
|
-
}
|
|
104477
|
-
function getOtelLogger() {
|
|
104478
|
-
if (otelLoggerAttempted) return otelLogger;
|
|
104479
|
-
otelLoggerAttempted = true;
|
|
104480
|
-
try {
|
|
104481
|
-
const { logs } = (function(name15) {
|
|
104482
|
-
return _require(name15);
|
|
104483
|
-
})("@opentelemetry/api-logs");
|
|
104484
|
-
otelLogger = logs.getLogger("probe-agent");
|
|
104485
|
-
} catch {
|
|
104486
|
-
}
|
|
104487
|
-
return otelLogger;
|
|
104488
|
-
}
|
|
104489
|
-
function getTraceSuffix() {
|
|
104490
|
-
try {
|
|
104491
|
-
const api2 = getOtelApi();
|
|
104492
|
-
if (!api2) return "";
|
|
104493
|
-
const span = api2.trace.getSpan(api2.context.active());
|
|
104494
|
-
const ctx = span?.spanContext?.();
|
|
104495
|
-
if (!ctx?.traceId) return "";
|
|
104496
|
-
return ` [trace_id=${ctx.traceId} span_id=${ctx.spanId}]`;
|
|
104497
|
-
} catch {
|
|
104498
|
-
return "";
|
|
104499
|
-
}
|
|
104500
|
-
}
|
|
104501
|
-
function emitOtelLog(msg, level) {
|
|
104502
|
-
try {
|
|
104503
|
-
const logger = getOtelLogger();
|
|
104504
|
-
if (!logger) return;
|
|
104505
|
-
const api2 = getOtelApi();
|
|
104506
|
-
let traceId, spanId;
|
|
104507
|
-
if (api2) {
|
|
104508
|
-
const span = api2.trace.getSpan(api2.context.active());
|
|
104509
|
-
const ctx = span?.spanContext?.();
|
|
104510
|
-
if (ctx?.traceId) {
|
|
104511
|
-
traceId = ctx.traceId;
|
|
104512
|
-
spanId = ctx.spanId;
|
|
104513
|
-
}
|
|
104514
|
-
}
|
|
104515
|
-
logger.emit({
|
|
104516
|
-
severityNumber: OTEL_SEVERITY[level] || 9,
|
|
104517
|
-
severityText: level.toUpperCase(),
|
|
104518
|
-
body: msg,
|
|
104519
|
-
attributes: {
|
|
104520
|
-
"probe.logger": true,
|
|
104521
|
-
...traceId ? { trace_id: traceId, span_id: spanId } : {}
|
|
104522
|
-
}
|
|
104523
|
-
});
|
|
104524
|
-
} catch {
|
|
104525
|
-
}
|
|
104526
|
-
}
|
|
104527
|
-
function patchConsole() {
|
|
104528
|
-
if (patched) return;
|
|
104529
|
-
const methods = ["log", "info", "warn", "error"];
|
|
104530
|
-
const c = globalThis.console;
|
|
104531
|
-
for (const m of methods) {
|
|
104532
|
-
const orig = c[m].bind(c);
|
|
104533
|
-
originals[m] = orig;
|
|
104534
|
-
c[m] = (...args) => {
|
|
104535
|
-
const msgParts = args.map(
|
|
104536
|
-
(a) => typeof a === "string" ? a : a instanceof Error ? a.message : JSON.stringify(a)
|
|
104537
|
-
);
|
|
104538
|
-
const msg = msgParts.join(" ");
|
|
104539
|
-
emitOtelLog(msg, m === "log" ? "log" : m);
|
|
104540
|
-
const suffix = getTraceSuffix();
|
|
104541
|
-
if (suffix) {
|
|
104542
|
-
if (typeof args[0] === "string") {
|
|
104543
|
-
args[0] = args[0] + suffix;
|
|
104544
|
-
} else {
|
|
104545
|
-
args.push(suffix);
|
|
104546
|
-
}
|
|
104547
|
-
}
|
|
104548
|
-
return orig(...args);
|
|
104549
|
-
};
|
|
104550
|
-
}
|
|
104551
|
-
patched = true;
|
|
104552
|
-
}
|
|
104553
|
-
var import_module, _require, OTEL_SEVERITY, patched, originals, otelApi, otelApiAttempted, otelLogger, otelLoggerAttempted;
|
|
104554
|
-
var init_otelLogBridge = __esm({
|
|
104555
|
-
"src/agent/otelLogBridge.js"() {
|
|
104556
|
-
"use strict";
|
|
104557
|
-
import_module = require("module");
|
|
104558
|
-
_require = (0, import_module.createRequire)("file:///");
|
|
104559
|
-
OTEL_SEVERITY = {
|
|
104560
|
-
log: 9,
|
|
104561
|
-
// INFO
|
|
104562
|
-
info: 9,
|
|
104563
|
-
// INFO
|
|
104564
|
-
warn: 13,
|
|
104565
|
-
// WARN
|
|
104566
|
-
error: 17,
|
|
104567
|
-
// ERROR
|
|
104568
|
-
debug: 5
|
|
104569
|
-
// DEBUG
|
|
104570
|
-
};
|
|
104571
|
-
patched = false;
|
|
104572
|
-
originals = {};
|
|
104573
|
-
otelApi = null;
|
|
104574
|
-
otelApiAttempted = false;
|
|
104575
|
-
otelLogger = null;
|
|
104576
|
-
otelLoggerAttempted = false;
|
|
104577
|
-
}
|
|
104578
|
-
});
|
|
104579
|
-
|
|
104580
|
-
// src/agent/simpleTelemetry.js
|
|
104581
|
-
function initializeSimpleTelemetryFromOptions(options) {
|
|
104582
|
-
const telemetry = new SimpleTelemetry({
|
|
104583
|
-
serviceName: "probe-agent",
|
|
104584
|
-
enableFile: options.traceFile !== void 0,
|
|
104585
|
-
enableConsole: options.traceConsole,
|
|
104586
|
-
filePath: options.traceFile || "./traces.jsonl"
|
|
104587
|
-
});
|
|
104588
|
-
patchConsole();
|
|
104589
|
-
return telemetry;
|
|
104590
|
-
}
|
|
104591
|
-
var import_fs15, import_path18, SimpleTelemetry, SimpleAppTracer;
|
|
104592
|
-
var init_simpleTelemetry = __esm({
|
|
104593
|
-
"src/agent/simpleTelemetry.js"() {
|
|
104594
|
-
"use strict";
|
|
104595
|
-
import_fs15 = require("fs");
|
|
104596
|
-
import_path18 = require("path");
|
|
104597
|
-
init_otelLogBridge();
|
|
104598
|
-
SimpleTelemetry = class {
|
|
104599
|
-
constructor(options = {}) {
|
|
104600
|
-
this.serviceName = options.serviceName || "probe-agent";
|
|
104601
|
-
this.enableFile = options.enableFile || false;
|
|
104602
|
-
this.enableConsole = options.enableConsole || false;
|
|
104603
|
-
this.filePath = options.filePath || "./traces.jsonl";
|
|
104604
|
-
this.stream = null;
|
|
104605
|
-
if (this.enableFile) {
|
|
104606
|
-
this.initializeFileExporter();
|
|
104607
|
-
}
|
|
104608
|
-
}
|
|
104609
|
-
initializeFileExporter() {
|
|
104610
|
-
try {
|
|
104611
|
-
const dir = (0, import_path18.dirname)(this.filePath);
|
|
104612
|
-
if (!(0, import_fs15.existsSync)(dir)) {
|
|
104613
|
-
(0, import_fs15.mkdirSync)(dir, { recursive: true });
|
|
104614
|
-
}
|
|
104615
|
-
this.stream = (0, import_fs15.createWriteStream)(this.filePath, { flags: "a" });
|
|
104616
|
-
this.stream.on("error", (error40) => {
|
|
104617
|
-
console.error(`[SimpleTelemetry] Stream error: ${error40.message}`);
|
|
104618
|
-
});
|
|
104619
|
-
console.log(`[SimpleTelemetry] File exporter initialized: ${this.filePath}`);
|
|
104620
|
-
} catch (error40) {
|
|
104621
|
-
console.error(`[SimpleTelemetry] Failed to initialize file exporter: ${error40.message}`);
|
|
104622
|
-
}
|
|
104623
|
-
}
|
|
104624
|
-
createSpan(name15, attributes = {}) {
|
|
104625
|
-
const span = {
|
|
104626
|
-
traceId: this.generateTraceId(),
|
|
104627
|
-
spanId: this.generateSpanId(),
|
|
104628
|
-
name: name15,
|
|
104629
|
-
startTime: Date.now(),
|
|
104630
|
-
attributes: { ...attributes, service: this.serviceName },
|
|
104631
|
-
events: [],
|
|
104632
|
-
status: "OK"
|
|
104633
|
-
};
|
|
104634
|
-
return {
|
|
104635
|
-
...span,
|
|
104636
|
-
addEvent: (eventName, eventAttributes = {}) => {
|
|
104637
|
-
span.events.push({
|
|
104638
|
-
name: eventName,
|
|
104639
|
-
time: Date.now(),
|
|
104640
|
-
attributes: eventAttributes
|
|
104641
|
-
});
|
|
104642
|
-
},
|
|
104643
|
-
setAttributes: (attrs) => {
|
|
104644
|
-
Object.assign(span.attributes, attrs);
|
|
104645
|
-
},
|
|
104646
|
-
setStatus: (status) => {
|
|
104647
|
-
span.status = status;
|
|
104648
|
-
},
|
|
104649
|
-
end: () => {
|
|
104650
|
-
span.endTime = Date.now();
|
|
104651
|
-
span.duration = span.endTime - span.startTime;
|
|
104652
|
-
this.exportSpan(span);
|
|
104653
|
-
}
|
|
104654
|
-
};
|
|
104655
|
-
}
|
|
104656
|
-
exportSpan(span) {
|
|
104657
|
-
const spanData = {
|
|
104658
|
-
...span,
|
|
104659
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
104660
|
-
};
|
|
104661
|
-
if (this.enableConsole) {
|
|
104662
|
-
console.log("[Trace]", JSON.stringify(spanData, null, 2));
|
|
104663
|
-
}
|
|
104664
|
-
if (this.enableFile && this.stream) {
|
|
104665
|
-
this.stream.write(JSON.stringify(spanData) + "\n");
|
|
104666
|
-
}
|
|
104667
|
-
}
|
|
104668
|
-
generateTraceId() {
|
|
104669
|
-
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
|
|
104670
|
-
}
|
|
104671
|
-
generateSpanId() {
|
|
104672
|
-
return Math.random().toString(36).substring(2, 10);
|
|
104673
|
-
}
|
|
104674
|
-
async flush() {
|
|
104675
|
-
if (this.stream) {
|
|
104676
|
-
return new Promise((resolve9) => {
|
|
104677
|
-
this.stream.once("drain", resolve9);
|
|
104678
|
-
if (!this.stream.writableNeedDrain) {
|
|
104679
|
-
resolve9();
|
|
104680
|
-
}
|
|
104681
|
-
});
|
|
104682
|
-
}
|
|
104683
|
-
}
|
|
104684
|
-
async shutdown() {
|
|
104685
|
-
if (this.stream) {
|
|
104686
|
-
return new Promise((resolve9) => {
|
|
104687
|
-
this.stream.end(() => {
|
|
104688
|
-
console.log(`[SimpleTelemetry] File stream closed: ${this.filePath}`);
|
|
104689
|
-
resolve9();
|
|
104690
|
-
});
|
|
104691
|
-
});
|
|
104692
|
-
}
|
|
104693
|
-
}
|
|
104694
|
-
};
|
|
104695
|
-
SimpleAppTracer = class {
|
|
104696
|
-
constructor(telemetry, sessionId = null) {
|
|
104697
|
-
this.telemetry = telemetry;
|
|
104698
|
-
this.sessionId = sessionId || this.generateSessionId();
|
|
104699
|
-
}
|
|
104700
|
-
generateSessionId() {
|
|
104701
|
-
return Math.random().toString(36).substring(2, 15);
|
|
104702
|
-
}
|
|
104703
|
-
isEnabled() {
|
|
104704
|
-
return this.telemetry !== null;
|
|
104705
|
-
}
|
|
104706
|
-
createSessionSpan(attributes = {}) {
|
|
104707
|
-
if (!this.isEnabled()) return null;
|
|
104708
|
-
return this.telemetry.createSpan("agent.session", {
|
|
104709
|
-
"session.id": this.sessionId,
|
|
104710
|
-
...attributes
|
|
104711
|
-
});
|
|
104712
|
-
}
|
|
104713
|
-
createAISpan(modelName, provider, attributes = {}) {
|
|
104714
|
-
if (!this.isEnabled()) return null;
|
|
104715
|
-
return this.telemetry.createSpan("ai.request", {
|
|
104716
|
-
"ai.model": modelName,
|
|
104717
|
-
"ai.provider": provider,
|
|
104718
|
-
"session.id": this.sessionId,
|
|
104719
|
-
...attributes
|
|
104720
|
-
});
|
|
104721
|
-
}
|
|
104722
|
-
createToolSpan(toolName, attributes = {}) {
|
|
104723
|
-
if (!this.isEnabled()) return null;
|
|
104724
|
-
return this.telemetry.createSpan("tool.call", {
|
|
104725
|
-
"tool.name": toolName,
|
|
104726
|
-
"session.id": this.sessionId,
|
|
104727
|
-
...attributes
|
|
104728
|
-
});
|
|
104729
|
-
}
|
|
104730
|
-
addEvent(name15, attributes = {}) {
|
|
104731
|
-
if (this.telemetry && this.telemetry.enableConsole) {
|
|
104732
|
-
console.log("[Event]", name15, attributes);
|
|
104733
|
-
}
|
|
104734
|
-
}
|
|
104735
|
-
/**
|
|
104736
|
-
* Record a generic event (used by completionPrompt and other features)
|
|
104737
|
-
*/
|
|
104738
|
-
// visor-disable: SimpleAppTracer uses this.sessionId because it's a per-session instance. AppTracer extracts from attributes because it's a singleton managing multiple sessions. Different architectures require different approaches.
|
|
104739
|
-
recordEvent(name15, attributes = {}) {
|
|
104740
|
-
if (!this.isEnabled()) return;
|
|
104741
|
-
this.addEvent(name15, {
|
|
104742
|
-
"session.id": this.sessionId,
|
|
104743
|
-
...attributes
|
|
104744
|
-
});
|
|
104745
|
-
}
|
|
104746
|
-
/**
|
|
104747
|
-
* Record delegation events
|
|
104748
|
-
*/
|
|
104749
|
-
recordDelegationEvent(eventType, data2 = {}) {
|
|
104750
|
-
if (!this.isEnabled()) return;
|
|
104751
|
-
this.addEvent(`delegation.${eventType}`, {
|
|
104752
|
-
"session.id": this.sessionId,
|
|
104753
|
-
...data2
|
|
104754
|
-
});
|
|
104755
|
-
}
|
|
104756
|
-
/**
|
|
104757
|
-
* Record JSON validation events
|
|
104758
|
-
*/
|
|
104759
|
-
recordJsonValidationEvent(eventType, data2 = {}) {
|
|
104760
|
-
if (!this.isEnabled()) return;
|
|
104761
|
-
this.addEvent(`json_validation.${eventType}`, {
|
|
104762
|
-
"session.id": this.sessionId,
|
|
104763
|
-
...data2
|
|
104764
|
-
});
|
|
104765
|
-
}
|
|
104766
|
-
/**
|
|
104767
|
-
* Record Mermaid validation events
|
|
104768
|
-
*/
|
|
104769
|
-
recordMermaidValidationEvent(eventType, data2 = {}) {
|
|
104770
|
-
if (!this.isEnabled()) return;
|
|
104771
|
-
this.addEvent(`mermaid_validation.${eventType}`, {
|
|
104772
|
-
"session.id": this.sessionId,
|
|
104773
|
-
...data2
|
|
104774
|
-
});
|
|
104775
|
-
}
|
|
104776
|
-
/**
|
|
104777
|
-
* Record task management events
|
|
104778
|
-
*/
|
|
104779
|
-
recordTaskEvent(eventType, data2 = {}) {
|
|
104780
|
-
if (!this.isEnabled()) return;
|
|
104781
|
-
this.addEvent(`task.${eventType}`, {
|
|
104782
|
-
"session.id": this.sessionId,
|
|
104783
|
-
...data2
|
|
104784
|
-
});
|
|
104785
|
-
}
|
|
104786
|
-
/**
|
|
104787
|
-
* Record MCP (Model Context Protocol) events
|
|
104788
|
-
* Tracks server connections, tool discovery, method filtering, and tool execution
|
|
104789
|
-
*/
|
|
104790
|
-
recordMcpEvent(eventType, data2 = {}) {
|
|
104791
|
-
if (!this.isEnabled()) return;
|
|
104792
|
-
this.addEvent(`mcp.${eventType}`, {
|
|
104793
|
-
"session.id": this.sessionId,
|
|
104794
|
-
...data2
|
|
104795
|
-
});
|
|
104796
|
-
}
|
|
104797
|
-
/**
|
|
104798
|
-
* Record bash tool events
|
|
104799
|
-
* Tracks command permission checks, allowed/denied commands, and execution
|
|
104800
|
-
*/
|
|
104801
|
-
recordBashEvent(eventType, data2 = {}) {
|
|
104802
|
-
if (!this.isEnabled()) return;
|
|
104803
|
-
this.addEvent(`bash.${eventType}`, {
|
|
104804
|
-
"session.id": this.sessionId,
|
|
104805
|
-
...data2
|
|
104806
|
-
});
|
|
104807
|
-
}
|
|
104808
|
-
setAttributes(attributes) {
|
|
104809
|
-
if (this.telemetry && this.telemetry.enableConsole) {
|
|
104810
|
-
console.log("[Attributes]", attributes);
|
|
104811
|
-
}
|
|
104812
|
-
}
|
|
104813
|
-
/**
|
|
104814
|
-
* Hash content for deduplication/comparison purposes
|
|
104815
|
-
* @param {string} content - The content to hash
|
|
104816
|
-
* @returns {string} - Hex string hash
|
|
104817
|
-
*/
|
|
104818
|
-
hashContent(content) {
|
|
104819
|
-
let hash2 = 0;
|
|
104820
|
-
const len = Math.min(content.length, 1e3);
|
|
104821
|
-
for (let i = 0; i < len; i++) {
|
|
104822
|
-
hash2 = (hash2 << 5) - hash2 + content.charCodeAt(i);
|
|
104823
|
-
hash2 |= 0;
|
|
104824
|
-
}
|
|
104825
|
-
return hash2.toString(16);
|
|
104826
|
-
}
|
|
104827
|
-
/**
|
|
104828
|
-
* Record a conversation turn (assistant response or tool result)
|
|
104829
|
-
* @param {string} role - The role (assistant, tool_result)
|
|
104830
|
-
* @param {string} content - The turn content
|
|
104831
|
-
* @param {Object} metadata - Additional metadata
|
|
104832
|
-
*/
|
|
104833
|
-
recordConversationTurn(role, content, metadata = {}) {
|
|
104834
|
-
if (!this.isEnabled()) return;
|
|
104835
|
-
this.addEvent(`conversation.turn.${role}`, {
|
|
104836
|
-
"session.id": this.sessionId,
|
|
104837
|
-
"conversation.role": role,
|
|
104838
|
-
"conversation.content": content.substring(0, 1e4),
|
|
104839
|
-
"conversation.content.length": content.length,
|
|
104840
|
-
"conversation.content.hash": this.hashContent(content),
|
|
104841
|
-
...metadata
|
|
104842
|
-
});
|
|
104843
|
-
}
|
|
104844
|
-
/**
|
|
104845
|
-
* Record error events with classification
|
|
104846
|
-
* @param {string} errorType - The type of error (wrapped_tool, unrecognized_tool, no_tool_call, circuit_breaker, etc.)
|
|
104847
|
-
* @param {Object} errorDetails - Error details including message, stack, context
|
|
104848
|
-
*/
|
|
104849
|
-
recordErrorEvent(errorType, errorDetails = {}) {
|
|
104850
|
-
if (!this.isEnabled()) return;
|
|
104851
|
-
this.addEvent(`error.${errorType}`, {
|
|
104852
|
-
"session.id": this.sessionId,
|
|
104853
|
-
"error.type": errorType,
|
|
104854
|
-
"error.message": errorDetails.message?.substring(0, 1e3) || null,
|
|
104855
|
-
"error.stack": errorDetails.stack?.substring(0, 2e3) || null,
|
|
104856
|
-
"error.recoverable": errorDetails.recoverable ?? true,
|
|
104857
|
-
"error.context": JSON.stringify(errorDetails.context || {}).substring(0, 1e3),
|
|
104858
|
-
...Object.fromEntries(
|
|
104859
|
-
Object.entries(errorDetails).filter(([k]) => !["message", "stack", "context", "recoverable"].includes(k)).map(([k, v]) => [`error.${k}`, v])
|
|
104860
|
-
)
|
|
104861
|
-
});
|
|
104862
|
-
}
|
|
104863
|
-
/**
|
|
104864
|
-
* Record AI thinking/reasoning content
|
|
104865
|
-
* @param {string} thinkingContent - The thinking content from AI response
|
|
104866
|
-
* @param {Object} metadata - Additional metadata
|
|
104867
|
-
*/
|
|
104868
|
-
recordThinkingContent(thinkingContent, metadata = {}) {
|
|
104869
|
-
if (!this.isEnabled() || !thinkingContent) return;
|
|
104870
|
-
this.addEvent("ai.thinking", {
|
|
104871
|
-
"session.id": this.sessionId,
|
|
104872
|
-
"ai.thinking.content": thinkingContent.substring(0, 5e4),
|
|
104873
|
-
"ai.thinking.length": thinkingContent.length,
|
|
104874
|
-
"ai.thinking.hash": this.hashContent(thinkingContent),
|
|
104875
|
-
...metadata
|
|
104876
|
-
});
|
|
104877
|
-
}
|
|
104878
|
-
/**
|
|
104879
|
-
* Record AI tool call decision
|
|
104880
|
-
* @param {string} toolName - The tool name AI decided to call
|
|
104881
|
-
* @param {Object} params - The parameters AI provided
|
|
104882
|
-
* @param {Object} metadata - Additional metadata
|
|
104883
|
-
*/
|
|
104884
|
-
recordToolDecision(toolName, params, metadata = {}) {
|
|
104885
|
-
if (!this.isEnabled()) return;
|
|
104886
|
-
this.addEvent("ai.tool_decision", {
|
|
104887
|
-
"session.id": this.sessionId,
|
|
104888
|
-
"ai.tool_decision.name": toolName,
|
|
104889
|
-
"ai.tool_decision.params": JSON.stringify(params || {}).substring(0, 2e3),
|
|
104890
|
-
...metadata
|
|
104891
|
-
});
|
|
104892
|
-
}
|
|
104893
|
-
/**
|
|
104894
|
-
* Record tool result after execution
|
|
104895
|
-
* @param {string} toolName - The tool that was executed
|
|
104896
|
-
* @param {string|Object} result - The tool result
|
|
104897
|
-
* @param {boolean} success - Whether the tool succeeded
|
|
104898
|
-
* @param {number} durationMs - Execution duration in milliseconds
|
|
104899
|
-
* @param {Object} metadata - Additional metadata
|
|
104900
|
-
*/
|
|
104901
|
-
recordToolResult(toolName, result, success2, durationMs, metadata = {}) {
|
|
104902
|
-
if (!this.isEnabled()) return;
|
|
104903
|
-
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
104904
|
-
this.addEvent("tool.result", {
|
|
104905
|
-
"session.id": this.sessionId,
|
|
104906
|
-
"tool.name": toolName,
|
|
104907
|
-
"tool.result": resultStr.substring(0, 1e4),
|
|
104908
|
-
"tool.result.length": resultStr.length,
|
|
104909
|
-
"tool.result.hash": this.hashContent(resultStr),
|
|
104910
|
-
"tool.duration_ms": durationMs,
|
|
104911
|
-
"tool.success": success2,
|
|
104912
|
-
...metadata
|
|
104913
|
-
});
|
|
104914
|
-
}
|
|
104915
|
-
/**
|
|
104916
|
-
* Record MCP tool execution start
|
|
104917
|
-
* @param {string} toolName - MCP tool name
|
|
104918
|
-
* @param {string} serverName - MCP server name
|
|
104919
|
-
* @param {Object} params - Tool parameters
|
|
104920
|
-
* @param {Object} metadata - Additional metadata
|
|
104921
|
-
*/
|
|
104922
|
-
recordMcpToolStart(toolName, serverName, params, metadata = {}) {
|
|
104923
|
-
if (!this.isEnabled()) return;
|
|
104924
|
-
this.addEvent("mcp.tool.start", {
|
|
104925
|
-
"session.id": this.sessionId,
|
|
104926
|
-
"mcp.tool.name": toolName,
|
|
104927
|
-
"mcp.tool.server": serverName || "unknown",
|
|
104928
|
-
"mcp.tool.params": JSON.stringify(params || {}).substring(0, 2e3),
|
|
104929
|
-
...metadata
|
|
104930
|
-
});
|
|
104931
|
-
}
|
|
104932
|
-
/**
|
|
104933
|
-
* Record MCP tool execution end
|
|
104934
|
-
* @param {string} toolName - MCP tool name
|
|
104935
|
-
* @param {string} serverName - MCP server name
|
|
104936
|
-
* @param {string|Object} result - Tool result
|
|
104937
|
-
* @param {boolean} success - Whether succeeded
|
|
104938
|
-
* @param {number} durationMs - Execution duration
|
|
104939
|
-
* @param {string} errorMessage - Error message if failed
|
|
104940
|
-
* @param {Object} metadata - Additional metadata
|
|
104941
|
-
*/
|
|
104942
|
-
recordMcpToolEnd(toolName, serverName, result, success2, durationMs, errorMessage = null, metadata = {}) {
|
|
104943
|
-
if (!this.isEnabled()) return;
|
|
104944
|
-
const resultStr = typeof result === "string" ? result : JSON.stringify(result || "");
|
|
104945
|
-
this.addEvent("mcp.tool.end", {
|
|
104946
|
-
"session.id": this.sessionId,
|
|
104947
|
-
"mcp.tool.name": toolName,
|
|
104948
|
-
"mcp.tool.server": serverName || "unknown",
|
|
104949
|
-
"mcp.tool.result": resultStr.substring(0, 1e4),
|
|
104950
|
-
"mcp.tool.result.length": resultStr.length,
|
|
104951
|
-
"mcp.tool.duration_ms": durationMs,
|
|
104952
|
-
"mcp.tool.success": success2,
|
|
104953
|
-
"mcp.tool.error": errorMessage,
|
|
104954
|
-
...metadata
|
|
104955
|
-
});
|
|
104956
|
-
}
|
|
104957
|
-
/**
|
|
104958
|
-
* Record iteration lifecycle event
|
|
104959
|
-
* @param {string} eventType - start or end
|
|
104960
|
-
* @param {number} iteration - Iteration number
|
|
104961
|
-
* @param {Object} data - Additional data
|
|
104962
|
-
*/
|
|
104963
|
-
recordIterationEvent(eventType, iteration, data2 = {}) {
|
|
104964
|
-
if (!this.isEnabled()) return;
|
|
104965
|
-
this.addEvent(`iteration.${eventType}`, {
|
|
104966
|
-
"session.id": this.sessionId,
|
|
104967
|
-
"iteration": iteration,
|
|
104968
|
-
...data2
|
|
104969
|
-
});
|
|
104970
|
-
}
|
|
104971
|
-
/**
|
|
104972
|
-
* Record per-turn token breakdown
|
|
104973
|
-
* @param {number} iteration - Iteration number
|
|
104974
|
-
* @param {Object} tokenData - Token metrics
|
|
104975
|
-
*/
|
|
104976
|
-
recordTokenTurn(iteration, tokenData = {}) {
|
|
104977
|
-
if (!this.isEnabled()) return;
|
|
104978
|
-
this.addEvent("tokens.turn", {
|
|
104979
|
-
"session.id": this.sessionId,
|
|
104980
|
-
"iteration": iteration,
|
|
104981
|
-
"tokens.input": tokenData.inputTokens || 0,
|
|
104982
|
-
"tokens.output": tokenData.outputTokens || 0,
|
|
104983
|
-
"tokens.total": (tokenData.inputTokens || 0) + (tokenData.outputTokens || 0),
|
|
104984
|
-
"tokens.cache_read": tokenData.cacheReadTokens || 0,
|
|
104985
|
-
"tokens.cache_write": tokenData.cacheWriteTokens || 0,
|
|
104986
|
-
"tokens.context_used": tokenData.contextTokens || 0,
|
|
104987
|
-
"tokens.context_remaining": tokenData.maxContextTokens ? tokenData.maxContextTokens - (tokenData.contextTokens || 0) : null
|
|
104988
|
-
});
|
|
104989
|
-
}
|
|
104990
|
-
async withSpan(spanName, fn, attributes = {}) {
|
|
104991
|
-
if (!this.isEnabled()) {
|
|
104992
|
-
return fn();
|
|
104993
|
-
}
|
|
104994
|
-
const span = this.telemetry.createSpan(spanName, {
|
|
104995
|
-
"session.id": this.sessionId,
|
|
104996
|
-
...attributes
|
|
104997
|
-
});
|
|
104998
|
-
try {
|
|
104999
|
-
const result = await fn();
|
|
105000
|
-
span.setStatus("OK");
|
|
105001
|
-
return result;
|
|
105002
|
-
} catch (error40) {
|
|
105003
|
-
span.setStatus("ERROR");
|
|
105004
|
-
span.addEvent("exception", {
|
|
105005
|
-
"exception.message": error40.message,
|
|
105006
|
-
"exception.stack": error40.stack
|
|
105007
|
-
});
|
|
105008
|
-
throw error40;
|
|
105009
|
-
} finally {
|
|
105010
|
-
span.end();
|
|
105011
|
-
}
|
|
105012
|
-
}
|
|
105013
|
-
async flush() {
|
|
105014
|
-
if (this.telemetry) {
|
|
105015
|
-
await this.telemetry.flush();
|
|
105016
|
-
}
|
|
105017
|
-
}
|
|
105018
|
-
async shutdown() {
|
|
105019
|
-
if (this.telemetry) {
|
|
105020
|
-
await this.telemetry.shutdown();
|
|
105021
|
-
}
|
|
105022
|
-
}
|
|
105023
|
-
};
|
|
105024
|
-
}
|
|
105025
|
-
});
|
|
105026
|
-
|
|
105027
105055
|
// src/agent/storage/index.js
|
|
105028
105056
|
var init_storage = __esm({
|
|
105029
105057
|
"src/agent/storage/index.js"() {
|