@probelabs/probe 0.6.0-rc299 → 0.6.0-rc301
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-rc301-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-rc301-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-rc301-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-rc301-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-rc301-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/ProbeAgent.js +16 -3
- package/build/agent/simpleTelemetry.js +25 -3
- package/build/tools/vercel.js +10 -1
- package/cjs/agent/ProbeAgent.cjs +187 -159
- package/cjs/agent/simpleTelemetry.cjs +19 -3
- package/cjs/index.cjs +932 -898
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +16 -3
- package/src/agent/simpleTelemetry.js +25 -3
- package/src/tools/vercel.js +10 -1
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();
|
|
@@ -100138,6 +100721,9 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
100138
100721
|
} else if (aiResult.finalText) {
|
|
100139
100722
|
finalResult = aiResult.finalText;
|
|
100140
100723
|
}
|
|
100724
|
+
if (finalResult === null || finalResult === void 0) {
|
|
100725
|
+
finalResult = "";
|
|
100726
|
+
}
|
|
100141
100727
|
if (gracefulTimeoutState.triggered) {
|
|
100142
100728
|
const timeoutNotice = "**Note: This response was generated under a time constraint. The research may be incomplete, and some planned searches or analysis steps were not completed.**\n\n";
|
|
100143
100729
|
if (!finalResult || finalResult === DEFAULT_MAX_ITER_MSG || finalResult.startsWith("I was unable to complete your request after")) {
|
|
@@ -102451,7 +103037,7 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
|
|
|
102451
103037
|
"Remember: if your search returned relevant results, use nextPage=true to check for more before outputting."
|
|
102452
103038
|
].join("\n");
|
|
102453
103039
|
}
|
|
102454
|
-
var import_ai5,
|
|
103040
|
+
var import_ai5, import_fs12, CODE_SEARCH_SCHEMA, searchTool, queryTool, extractTool, delegateTool, analyzeAllTool;
|
|
102455
103041
|
var init_vercel = __esm({
|
|
102456
103042
|
"src/tools/vercel.js"() {
|
|
102457
103043
|
"use strict";
|
|
@@ -102462,9 +103048,10 @@ var init_vercel = __esm({
|
|
|
102462
103048
|
init_delegate();
|
|
102463
103049
|
init_analyzeAll();
|
|
102464
103050
|
init_common();
|
|
102465
|
-
|
|
103051
|
+
import_fs12 = require("fs");
|
|
102466
103052
|
init_error_types();
|
|
102467
103053
|
init_hashline();
|
|
103054
|
+
init_simpleTelemetry();
|
|
102468
103055
|
CODE_SEARCH_SCHEMA = {
|
|
102469
103056
|
type: "object",
|
|
102470
103057
|
properties: {
|
|
@@ -102620,6 +103207,7 @@ var init_vercel = __esm({
|
|
|
102620
103207
|
tracer: options.tracer || null,
|
|
102621
103208
|
enableBash: false,
|
|
102622
103209
|
bashConfig: null,
|
|
103210
|
+
allowEdit: options.allowEdit || false,
|
|
102623
103211
|
architectureFileName: options.architectureFileName || null,
|
|
102624
103212
|
promptType: "code-searcher",
|
|
102625
103213
|
allowedTools: ["search", "extract", "listFiles"],
|
|
@@ -102630,6 +103218,12 @@ var init_vercel = __esm({
|
|
|
102630
103218
|
const delegateResult = options.tracer?.withSpan ? await options.tracer.withSpan("search.delegate", runDelegation, {
|
|
102631
103219
|
"search.query": searchQuery,
|
|
102632
103220
|
"search.path": searchPath
|
|
103221
|
+
}, (span, result) => {
|
|
103222
|
+
const text = typeof result === "string" ? result : "";
|
|
103223
|
+
span.setAttributes({
|
|
103224
|
+
"search.delegate.output": truncateForSpan(text),
|
|
103225
|
+
"search.delegate.output_length": text.length
|
|
103226
|
+
});
|
|
102633
103227
|
}) : await runDelegation();
|
|
102634
103228
|
const targets = parseDelegatedTargets(delegateResult);
|
|
102635
103229
|
if (!targets.length) {
|
|
@@ -102649,7 +103243,7 @@ var init_vercel = __esm({
|
|
|
102649
103243
|
const validatedTargets = [];
|
|
102650
103244
|
for (const target of resolvedTargets) {
|
|
102651
103245
|
const { filePart, suffix } = splitTargetSuffix(target);
|
|
102652
|
-
if ((0,
|
|
103246
|
+
if ((0, import_fs12.existsSync)(filePart)) {
|
|
102653
103247
|
validatedTargets.push(target);
|
|
102654
103248
|
continue;
|
|
102655
103249
|
}
|
|
@@ -102658,7 +103252,7 @@ var init_vercel = __esm({
|
|
|
102658
103252
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
102659
103253
|
if (parts[i] === parts[i + 1]) {
|
|
102660
103254
|
const candidate = "/" + [...parts.slice(0, i), ...parts.slice(i + 1)].join("/");
|
|
102661
|
-
if ((0,
|
|
103255
|
+
if ((0, import_fs12.existsSync)(candidate)) {
|
|
102662
103256
|
validatedTargets.push(candidate + suffix);
|
|
102663
103257
|
if (debug) console.error(`[search-delegate] Fixed doubled path segment: ${filePart} \u2192 ${candidate}`);
|
|
102664
103258
|
fixed = true;
|
|
@@ -102671,7 +103265,7 @@ var init_vercel = __esm({
|
|
|
102671
103265
|
if (altBase === delegateBase) continue;
|
|
102672
103266
|
const altResolved = resolveTargetPath(target, altBase);
|
|
102673
103267
|
const { filePart: altFile } = splitTargetSuffix(altResolved);
|
|
102674
|
-
if ((0,
|
|
103268
|
+
if ((0, import_fs12.existsSync)(altFile)) {
|
|
102675
103269
|
validatedTargets.push(altResolved);
|
|
102676
103270
|
if (debug) console.error(`[search-delegate] Resolved with alt base: ${filePart} \u2192 ${altFile}`);
|
|
102677
103271
|
fixed = true;
|
|
@@ -102796,13 +103390,13 @@ var init_vercel = __esm({
|
|
|
102796
103390
|
const { join: pathJoin, sep: pathSep } = await import("path");
|
|
102797
103391
|
extractFiles = extractFiles.map((target) => {
|
|
102798
103392
|
const { filePart, suffix } = splitTargetSuffix(target);
|
|
102799
|
-
if ((0,
|
|
103393
|
+
if ((0, import_fs12.existsSync)(filePart)) return target;
|
|
102800
103394
|
const cwdPrefix = effectiveCwd.endsWith(pathSep) ? effectiveCwd : effectiveCwd + pathSep;
|
|
102801
103395
|
const relativePart = filePart.startsWith(cwdPrefix) ? filePart.slice(cwdPrefix.length) : null;
|
|
102802
103396
|
if (relativePart) {
|
|
102803
103397
|
for (const folder of options.allowedFolders) {
|
|
102804
103398
|
const candidate = pathJoin(folder, relativePart);
|
|
102805
|
-
if ((0,
|
|
103399
|
+
if ((0, import_fs12.existsSync)(candidate)) {
|
|
102806
103400
|
if (debug) console.error(`[extract] Auto-fixed path: ${filePart} \u2192 ${candidate}`);
|
|
102807
103401
|
return candidate + suffix;
|
|
102808
103402
|
}
|
|
@@ -102815,7 +103409,7 @@ var init_vercel = __esm({
|
|
|
102815
103409
|
if (filePart.startsWith(wsParent)) {
|
|
102816
103410
|
const tail = filePart.slice(wsParent.length);
|
|
102817
103411
|
const candidate = pathJoin(folderPrefix, tail);
|
|
102818
|
-
if (candidate !== filePart && (0,
|
|
103412
|
+
if (candidate !== filePart && (0, import_fs12.existsSync)(candidate)) {
|
|
102819
103413
|
if (debug) console.error(`[extract] Auto-fixed path via workspace: ${filePart} \u2192 ${candidate}`);
|
|
102820
103414
|
return candidate + suffix;
|
|
102821
103415
|
}
|
|
@@ -102874,6 +103468,7 @@ var init_vercel = __esm({
|
|
|
102874
103468
|
workspaceRoot,
|
|
102875
103469
|
enableBash = false,
|
|
102876
103470
|
bashConfig,
|
|
103471
|
+
allowEdit = false,
|
|
102877
103472
|
architectureFileName,
|
|
102878
103473
|
enableMcp = false,
|
|
102879
103474
|
mcpConfig = null,
|
|
@@ -102968,6 +103563,7 @@ var init_vercel = __esm({
|
|
|
102968
103563
|
model,
|
|
102969
103564
|
tracer,
|
|
102970
103565
|
enableBash,
|
|
103566
|
+
allowEdit,
|
|
102971
103567
|
bashConfig,
|
|
102972
103568
|
architectureFileName,
|
|
102973
103569
|
searchDelegate,
|
|
@@ -103309,12 +103905,12 @@ function isPathAllowed(filePath, allowedFolders) {
|
|
|
103309
103905
|
if (!allowedFolders || allowedFolders.length === 0) {
|
|
103310
103906
|
const resolvedPath2 = safeRealpath(filePath);
|
|
103311
103907
|
const cwd = safeRealpath(process.cwd());
|
|
103312
|
-
return resolvedPath2 === cwd || resolvedPath2.startsWith(cwd +
|
|
103908
|
+
return resolvedPath2 === cwd || resolvedPath2.startsWith(cwd + import_path17.sep);
|
|
103313
103909
|
}
|
|
103314
103910
|
const resolvedPath = safeRealpath(filePath);
|
|
103315
103911
|
return allowedFolders.some((folder) => {
|
|
103316
103912
|
const allowedPath = safeRealpath(folder);
|
|
103317
|
-
return resolvedPath === allowedPath || resolvedPath.startsWith(allowedPath +
|
|
103913
|
+
return resolvedPath === allowedPath || resolvedPath.startsWith(allowedPath + import_path17.sep);
|
|
103318
103914
|
});
|
|
103319
103915
|
}
|
|
103320
103916
|
function parseFileToolOptions(options = {}) {
|
|
@@ -103354,7 +103950,7 @@ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualif
|
|
|
103354
103950
|
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
103951
|
}
|
|
103356
103952
|
}
|
|
103357
|
-
const content = await
|
|
103953
|
+
const content = await import_fs13.promises.readFile(resolvedPath, "utf-8");
|
|
103358
103954
|
const lines = content.split("\n");
|
|
103359
103955
|
if (position) {
|
|
103360
103956
|
const refIndent = detectBaseIndent(symbolInfo.code);
|
|
@@ -103365,7 +103961,7 @@ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualif
|
|
|
103365
103961
|
} else {
|
|
103366
103962
|
lines.splice(symbolInfo.startLine - 1, 0, ...newLines, "");
|
|
103367
103963
|
}
|
|
103368
|
-
await
|
|
103964
|
+
await import_fs13.promises.writeFile(resolvedPath, lines.join("\n"), "utf-8");
|
|
103369
103965
|
if (fileTracker) {
|
|
103370
103966
|
const updated = await findSymbol(resolvedPath, symbol17, cwd || process.cwd());
|
|
103371
103967
|
if (updated) {
|
|
@@ -103383,7 +103979,7 @@ Example: <edit><file_path>${file_path}</file_path><symbol>${allMatches[0].qualif
|
|
|
103383
103979
|
const reindented = reindent(new_string, originalIndent);
|
|
103384
103980
|
const newLines = reindented.split("\n");
|
|
103385
103981
|
lines.splice(symbolInfo.startLine - 1, symbolInfo.endLine - symbolInfo.startLine + 1, ...newLines);
|
|
103386
|
-
await
|
|
103982
|
+
await import_fs13.promises.writeFile(resolvedPath, lines.join("\n"), "utf-8");
|
|
103387
103983
|
if (fileTracker) {
|
|
103388
103984
|
const updated = await findSymbol(resolvedPath, symbol17, cwd || process.cwd());
|
|
103389
103985
|
if (updated) {
|
|
@@ -103438,7 +104034,7 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
103438
104034
|
if (position !== void 0 && position !== null && position !== "before" && position !== "after") {
|
|
103439
104035
|
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
104036
|
}
|
|
103441
|
-
const content = await
|
|
104037
|
+
const content = await import_fs13.promises.readFile(resolvedPath, "utf-8");
|
|
103442
104038
|
const fileLines = content.split("\n");
|
|
103443
104039
|
if (startLine > fileLines.length) {
|
|
103444
104040
|
return `Error editing file: Line ${startLine} is beyond file length (${fileLines.length} lines). Use 'extract' to read the current file content.`;
|
|
@@ -103467,20 +104063,20 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
103467
104063
|
const newLines = cleaned === "" ? [] : cleaned.split("\n");
|
|
103468
104064
|
if (position === "after") {
|
|
103469
104065
|
fileLines.splice(startLine, 0, ...newLines);
|
|
103470
|
-
await
|
|
104066
|
+
await import_fs13.promises.writeFile(resolvedPath, fileLines.join("\n"), "utf-8");
|
|
103471
104067
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103472
104068
|
const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted after line ${startLine}`;
|
|
103473
104069
|
return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine, action, modifications);
|
|
103474
104070
|
} else if (position === "before") {
|
|
103475
104071
|
fileLines.splice(startLine - 1, 0, ...newLines);
|
|
103476
|
-
await
|
|
104072
|
+
await import_fs13.promises.writeFile(resolvedPath, fileLines.join("\n"), "utf-8");
|
|
103477
104073
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103478
104074
|
const action = `${newLines.length} line${newLines.length !== 1 ? "s" : ""} inserted before line ${startLine}`;
|
|
103479
104075
|
return buildLineEditResponse(file_path, startLine, startLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
103480
104076
|
} else {
|
|
103481
104077
|
const replacedCount = endLine - startLine + 1;
|
|
103482
104078
|
fileLines.splice(startLine - 1, replacedCount, ...newLines);
|
|
103483
|
-
await
|
|
104079
|
+
await import_fs13.promises.writeFile(resolvedPath, fileLines.join("\n"), "utf-8");
|
|
103484
104080
|
if (fileTracker) await fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103485
104081
|
let action;
|
|
103486
104082
|
if (newLines.length === 0) {
|
|
@@ -103493,14 +104089,14 @@ async function handleLineEdit({ resolvedPath, file_path, start_line, end_line, n
|
|
|
103493
104089
|
return buildLineEditResponse(file_path, startLine, endLine, newLines.length, fileLines, startLine - 1, action, modifications);
|
|
103494
104090
|
}
|
|
103495
104091
|
}
|
|
103496
|
-
var import_ai6,
|
|
104092
|
+
var import_ai6, import_fs13, import_path17, import_fs14, editTool, createTool, multiEditTool, editSchema, createSchema, multiEditSchema, editDescription, createDescription, multiEditDescription, editToolDefinition, createToolDefinition, multiEditToolDefinition;
|
|
103497
104093
|
var init_edit = __esm({
|
|
103498
104094
|
"src/tools/edit.js"() {
|
|
103499
104095
|
"use strict";
|
|
103500
104096
|
import_ai6 = require("ai");
|
|
103501
|
-
import_fs12 = require("fs");
|
|
103502
|
-
import_path16 = require("path");
|
|
103503
104097
|
import_fs13 = require("fs");
|
|
104098
|
+
import_path17 = require("path");
|
|
104099
|
+
import_fs14 = require("fs");
|
|
103504
104100
|
init_path_validation();
|
|
103505
104101
|
init_fuzzyMatch();
|
|
103506
104102
|
init_symbolEdit();
|
|
@@ -103576,7 +104172,7 @@ Parameters:
|
|
|
103576
104172
|
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
104173
|
}
|
|
103578
104174
|
const effectiveCwd = workingDirectory || cwd || process.cwd();
|
|
103579
|
-
const resolvedPath = (0,
|
|
104175
|
+
const resolvedPath = (0, import_path17.isAbsolute)(file_path) ? file_path : (0, import_path17.resolve)(effectiveCwd, file_path);
|
|
103580
104176
|
if (debug) {
|
|
103581
104177
|
console.error(`[Edit] Attempting to edit file: ${resolvedPath}`);
|
|
103582
104178
|
}
|
|
@@ -103584,7 +104180,7 @@ Parameters:
|
|
|
103584
104180
|
const relativePath = toRelativePath(resolvedPath, workspaceRoot);
|
|
103585
104181
|
return `Error editing file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
|
|
103586
104182
|
}
|
|
103587
|
-
if (!(0,
|
|
104183
|
+
if (!(0, import_fs14.existsSync)(resolvedPath)) {
|
|
103588
104184
|
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
104185
|
}
|
|
103590
104186
|
if (options.fileTracker && !options.fileTracker.isFileSeen(resolvedPath)) {
|
|
@@ -103612,7 +104208,7 @@ Parameters:
|
|
|
103612
104208
|
Use the extract tool with targets="${displayPath}" to re-read the file, then retry.`;
|
|
103613
104209
|
}
|
|
103614
104210
|
}
|
|
103615
|
-
const content = await
|
|
104211
|
+
const content = await import_fs13.promises.readFile(resolvedPath, "utf-8");
|
|
103616
104212
|
let matchTarget = old_string;
|
|
103617
104213
|
let matchStrategy = "exact";
|
|
103618
104214
|
if (!content.includes(old_string)) {
|
|
@@ -103644,7 +104240,7 @@ Use the extract tool with targets="${displayPath}" to re-read the file, then ret
|
|
|
103644
104240
|
if (newContent === content) {
|
|
103645
104241
|
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
104242
|
}
|
|
103647
|
-
await
|
|
104243
|
+
await import_fs13.promises.writeFile(resolvedPath, newContent, "utf-8");
|
|
103648
104244
|
if (options.fileTracker) {
|
|
103649
104245
|
await options.fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103650
104246
|
options.fileTracker.recordTextEdit(resolvedPath);
|
|
@@ -103707,7 +104303,7 @@ Important:
|
|
|
103707
104303
|
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
104304
|
}
|
|
103709
104305
|
const effectiveCwd = workingDirectory || cwd || process.cwd();
|
|
103710
|
-
const resolvedPath = (0,
|
|
104306
|
+
const resolvedPath = (0, import_path17.isAbsolute)(file_path) ? file_path : (0, import_path17.resolve)(effectiveCwd, file_path);
|
|
103711
104307
|
if (debug) {
|
|
103712
104308
|
console.error(`[Create] Attempting to create file: ${resolvedPath}`);
|
|
103713
104309
|
}
|
|
@@ -103715,13 +104311,13 @@ Important:
|
|
|
103715
104311
|
const relativePath = toRelativePath(resolvedPath, workspaceRoot);
|
|
103716
104312
|
return `Error creating file: Permission denied - ${relativePath} is outside allowed directories. Use a file path within the project workspace.`;
|
|
103717
104313
|
}
|
|
103718
|
-
if ((0,
|
|
104314
|
+
if ((0, import_fs14.existsSync)(resolvedPath) && !overwrite) {
|
|
103719
104315
|
return `Error creating file: File already exists - ${file_path}. Use overwrite: true to replace it.`;
|
|
103720
104316
|
}
|
|
103721
|
-
const existed = (0,
|
|
103722
|
-
const dir = (0,
|
|
103723
|
-
await
|
|
103724
|
-
await
|
|
104317
|
+
const existed = (0, import_fs14.existsSync)(resolvedPath);
|
|
104318
|
+
const dir = (0, import_path17.dirname)(resolvedPath);
|
|
104319
|
+
await import_fs13.promises.mkdir(dir, { recursive: true });
|
|
104320
|
+
await import_fs13.promises.writeFile(resolvedPath, content, "utf-8");
|
|
103725
104321
|
if (options.fileTracker) await options.fileTracker.trackFileAfterWrite(resolvedPath);
|
|
103726
104322
|
const action = existed && overwrite ? "overwrote" : "created";
|
|
103727
104323
|
const bytes = Buffer.byteLength(content, "utf-8");
|
|
@@ -104362,10 +104958,10 @@ async function listFilesByLevel(options) {
|
|
|
104362
104958
|
maxFiles = 100,
|
|
104363
104959
|
respectGitignore = true
|
|
104364
104960
|
} = options;
|
|
104365
|
-
if (!
|
|
104961
|
+
if (!import_fs15.default.existsSync(directory)) {
|
|
104366
104962
|
throw new Error(`Directory does not exist: ${directory}`);
|
|
104367
104963
|
}
|
|
104368
|
-
const gitDirExists =
|
|
104964
|
+
const gitDirExists = import_fs15.default.existsSync(import_path18.default.join(directory, ".git"));
|
|
104369
104965
|
if (gitDirExists && respectGitignore) {
|
|
104370
104966
|
try {
|
|
104371
104967
|
return await listFilesUsingGit(directory, maxFiles);
|
|
@@ -104380,8 +104976,8 @@ async function listFilesUsingGit(directory, maxFiles) {
|
|
|
104380
104976
|
const { stdout } = await execAsync3("git ls-files", { cwd: directory });
|
|
104381
104977
|
const files = stdout.split("\n").filter(Boolean);
|
|
104382
104978
|
const sortedFiles = files.sort((a, b) => {
|
|
104383
|
-
const depthA = a.split(
|
|
104384
|
-
const depthB = b.split(
|
|
104979
|
+
const depthA = a.split(import_path18.default.sep).length;
|
|
104980
|
+
const depthB = b.split(import_path18.default.sep).length;
|
|
104385
104981
|
return depthA - depthB;
|
|
104386
104982
|
});
|
|
104387
104983
|
return sortedFiles.slice(0, maxFiles);
|
|
@@ -104396,25 +104992,25 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
|
|
|
104396
104992
|
while (queue.length > 0 && result.length < maxFiles) {
|
|
104397
104993
|
const { dir, level } = queue.shift();
|
|
104398
104994
|
try {
|
|
104399
|
-
const entries =
|
|
104995
|
+
const entries = import_fs15.default.readdirSync(dir, { withFileTypes: true });
|
|
104400
104996
|
const files = entries.filter((entry) => {
|
|
104401
|
-
const fullPath =
|
|
104997
|
+
const fullPath = import_path18.default.join(dir, entry.name);
|
|
104402
104998
|
return getEntryTypeSync(entry, fullPath).isFile;
|
|
104403
104999
|
});
|
|
104404
105000
|
for (const file2 of files) {
|
|
104405
105001
|
if (result.length >= maxFiles) break;
|
|
104406
|
-
const filePath =
|
|
104407
|
-
const relativePath =
|
|
105002
|
+
const filePath = import_path18.default.join(dir, file2.name);
|
|
105003
|
+
const relativePath = import_path18.default.relative(directory, filePath);
|
|
104408
105004
|
if (shouldIgnore(relativePath, ignorePatterns)) continue;
|
|
104409
105005
|
result.push(relativePath);
|
|
104410
105006
|
}
|
|
104411
105007
|
const dirs = entries.filter((entry) => {
|
|
104412
|
-
const fullPath =
|
|
105008
|
+
const fullPath = import_path18.default.join(dir, entry.name);
|
|
104413
105009
|
return getEntryTypeSync(entry, fullPath).isDirectory;
|
|
104414
105010
|
});
|
|
104415
105011
|
for (const subdir of dirs) {
|
|
104416
|
-
const subdirPath =
|
|
104417
|
-
const relativeSubdirPath =
|
|
105012
|
+
const subdirPath = import_path18.default.join(dir, subdir.name);
|
|
105013
|
+
const relativeSubdirPath = import_path18.default.relative(directory, subdirPath);
|
|
104418
105014
|
if (shouldIgnore(relativeSubdirPath, ignorePatterns)) continue;
|
|
104419
105015
|
if (subdir.name === "node_modules" || subdir.name === ".git") continue;
|
|
104420
105016
|
queue.push({ dir: subdirPath, level: level + 1 });
|
|
@@ -104426,12 +105022,12 @@ async function listFilesByLevelManually(directory, maxFiles, respectGitignore) {
|
|
|
104426
105022
|
return result;
|
|
104427
105023
|
}
|
|
104428
105024
|
function loadGitignorePatterns(directory) {
|
|
104429
|
-
const gitignorePath =
|
|
104430
|
-
if (!
|
|
105025
|
+
const gitignorePath = import_path18.default.join(directory, ".gitignore");
|
|
105026
|
+
if (!import_fs15.default.existsSync(gitignorePath)) {
|
|
104431
105027
|
return [];
|
|
104432
105028
|
}
|
|
104433
105029
|
try {
|
|
104434
|
-
const content =
|
|
105030
|
+
const content = import_fs15.default.readFileSync(gitignorePath, "utf8");
|
|
104435
105031
|
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
104436
105032
|
} catch (error40) {
|
|
104437
105033
|
console.error(`Warning: Could not read .gitignore: ${error40.message}`);
|
|
@@ -104449,12 +105045,12 @@ function shouldIgnore(filePath, ignorePatterns) {
|
|
|
104449
105045
|
}
|
|
104450
105046
|
return false;
|
|
104451
105047
|
}
|
|
104452
|
-
var
|
|
105048
|
+
var import_fs15, import_path18, import_util14, import_child_process10, execAsync3;
|
|
104453
105049
|
var init_file_lister = __esm({
|
|
104454
105050
|
"src/utils/file-lister.js"() {
|
|
104455
105051
|
"use strict";
|
|
104456
|
-
|
|
104457
|
-
|
|
105052
|
+
import_fs15 = __toESM(require("fs"), 1);
|
|
105053
|
+
import_path18 = __toESM(require("path"), 1);
|
|
104458
105054
|
import_util14 = require("util");
|
|
104459
105055
|
import_child_process10 = require("child_process");
|
|
104460
105056
|
init_symlink_utils();
|
|
@@ -104462,568 +105058,6 @@ var init_file_lister = __esm({
|
|
|
104462
105058
|
}
|
|
104463
105059
|
});
|
|
104464
105060
|
|
|
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
105061
|
// src/agent/storage/index.js
|
|
105028
105062
|
var init_storage = __esm({
|
|
105029
105063
|
"src/agent/storage/index.js"() {
|