@probelabs/probe 0.6.0-rc223 → 0.6.0-rc225
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-rc225-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc225-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc225-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc225-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc225-x86_64-unknown-linux-musl.tar.gz +0 -0
- package/build/agent/ProbeAgent.js +279 -3
- package/build/agent/index.js +421 -8
- package/build/agent/mcp/xmlBridge.js +10 -7
- package/build/agent/simpleTelemetry.js +198 -0
- package/build/agent/tools.js +8 -5
- package/build/delegate.js +17 -0
- package/cjs/agent/ProbeAgent.cjs +244 -8
- package/cjs/agent/simpleTelemetry.cjs +177 -0
- package/cjs/index.cjs +421 -8
- package/package.json +1 -1
- package/src/agent/ProbeAgent.js +279 -3
- package/src/agent/mcp/xmlBridge.js +10 -7
- package/src/agent/simpleTelemetry.js +198 -0
- package/src/agent/tools.js +8 -5
- package/src/delegate.js +17 -0
- package/bin/binaries/probe-v0.6.0-rc223-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc223-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc223-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc223-x86_64-pc-windows-msvc.zip +0 -0
- package/bin/binaries/probe-v0.6.0-rc223-x86_64-unknown-linux-musl.tar.gz +0 -0
package/build/agent/index.js
CHANGED
|
@@ -3776,6 +3776,19 @@ async function delegate({
|
|
|
3776
3776
|
if (!task || typeof task !== "string") {
|
|
3777
3777
|
throw new Error("Task parameter is required and must be a string");
|
|
3778
3778
|
}
|
|
3779
|
+
const hasExplicitTimeout = Object.prototype.hasOwnProperty.call(arguments?.[0] ?? {}, "timeout");
|
|
3780
|
+
if (!hasExplicitTimeout) {
|
|
3781
|
+
const envTimeoutMs = parseInt(process.env.DELEGATION_TIMEOUT_MS || "", 10);
|
|
3782
|
+
const envTimeoutSeconds = parseInt(
|
|
3783
|
+
process.env.DELEGATION_TIMEOUT_SECONDS || process.env.DELEGATION_TIMEOUT || "",
|
|
3784
|
+
10
|
|
3785
|
+
);
|
|
3786
|
+
if (!Number.isNaN(envTimeoutMs) && envTimeoutMs > 0) {
|
|
3787
|
+
timeout = Math.max(1, Math.ceil(envTimeoutMs / 1e3));
|
|
3788
|
+
} else if (!Number.isNaN(envTimeoutSeconds) && envTimeoutSeconds > 0) {
|
|
3789
|
+
timeout = Math.max(1, envTimeoutSeconds);
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3779
3792
|
const manager = delegationManager || defaultDelegationManager;
|
|
3780
3793
|
const sessionId = randomUUID();
|
|
3781
3794
|
const startTime = Date.now();
|
|
@@ -12700,6 +12713,183 @@ var init_simpleTelemetry = __esm({
|
|
|
12700
12713
|
console.log("[Attributes]", attributes);
|
|
12701
12714
|
}
|
|
12702
12715
|
}
|
|
12716
|
+
/**
|
|
12717
|
+
* Hash content for deduplication/comparison purposes
|
|
12718
|
+
* @param {string} content - The content to hash
|
|
12719
|
+
* @returns {string} - Hex string hash
|
|
12720
|
+
*/
|
|
12721
|
+
hashContent(content) {
|
|
12722
|
+
let hash = 0;
|
|
12723
|
+
const len = Math.min(content.length, 1e3);
|
|
12724
|
+
for (let i = 0; i < len; i++) {
|
|
12725
|
+
hash = (hash << 5) - hash + content.charCodeAt(i);
|
|
12726
|
+
hash |= 0;
|
|
12727
|
+
}
|
|
12728
|
+
return hash.toString(16);
|
|
12729
|
+
}
|
|
12730
|
+
/**
|
|
12731
|
+
* Record a conversation turn (assistant response or tool result)
|
|
12732
|
+
* @param {string} role - The role (assistant, tool_result)
|
|
12733
|
+
* @param {string} content - The turn content
|
|
12734
|
+
* @param {Object} metadata - Additional metadata
|
|
12735
|
+
*/
|
|
12736
|
+
recordConversationTurn(role, content, metadata = {}) {
|
|
12737
|
+
if (!this.isEnabled()) return;
|
|
12738
|
+
this.addEvent(`conversation.turn.${role}`, {
|
|
12739
|
+
"session.id": this.sessionId,
|
|
12740
|
+
"conversation.role": role,
|
|
12741
|
+
"conversation.content": content.substring(0, 1e4),
|
|
12742
|
+
"conversation.content.length": content.length,
|
|
12743
|
+
"conversation.content.hash": this.hashContent(content),
|
|
12744
|
+
...metadata
|
|
12745
|
+
});
|
|
12746
|
+
}
|
|
12747
|
+
/**
|
|
12748
|
+
* Record error events with classification
|
|
12749
|
+
* @param {string} errorType - The type of error (wrapped_tool, unrecognized_tool, no_tool_call, circuit_breaker, etc.)
|
|
12750
|
+
* @param {Object} errorDetails - Error details including message, stack, context
|
|
12751
|
+
*/
|
|
12752
|
+
recordErrorEvent(errorType, errorDetails = {}) {
|
|
12753
|
+
if (!this.isEnabled()) return;
|
|
12754
|
+
this.addEvent(`error.${errorType}`, {
|
|
12755
|
+
"session.id": this.sessionId,
|
|
12756
|
+
"error.type": errorType,
|
|
12757
|
+
"error.message": errorDetails.message?.substring(0, 1e3) || null,
|
|
12758
|
+
"error.stack": errorDetails.stack?.substring(0, 2e3) || null,
|
|
12759
|
+
"error.recoverable": errorDetails.recoverable ?? true,
|
|
12760
|
+
"error.context": JSON.stringify(errorDetails.context || {}).substring(0, 1e3),
|
|
12761
|
+
...Object.fromEntries(
|
|
12762
|
+
Object.entries(errorDetails).filter(([k]) => !["message", "stack", "context", "recoverable"].includes(k)).map(([k, v]) => [`error.${k}`, v])
|
|
12763
|
+
)
|
|
12764
|
+
});
|
|
12765
|
+
}
|
|
12766
|
+
/**
|
|
12767
|
+
* Record AI thinking/reasoning content
|
|
12768
|
+
* @param {string} thinkingContent - The thinking content from AI response
|
|
12769
|
+
* @param {Object} metadata - Additional metadata
|
|
12770
|
+
*/
|
|
12771
|
+
recordThinkingContent(thinkingContent, metadata = {}) {
|
|
12772
|
+
if (!this.isEnabled() || !thinkingContent) return;
|
|
12773
|
+
this.addEvent("ai.thinking", {
|
|
12774
|
+
"session.id": this.sessionId,
|
|
12775
|
+
"ai.thinking.content": thinkingContent.substring(0, 5e4),
|
|
12776
|
+
"ai.thinking.length": thinkingContent.length,
|
|
12777
|
+
"ai.thinking.hash": this.hashContent(thinkingContent),
|
|
12778
|
+
...metadata
|
|
12779
|
+
});
|
|
12780
|
+
}
|
|
12781
|
+
/**
|
|
12782
|
+
* Record AI tool call decision
|
|
12783
|
+
* @param {string} toolName - The tool name AI decided to call
|
|
12784
|
+
* @param {Object} params - The parameters AI provided
|
|
12785
|
+
* @param {Object} metadata - Additional metadata
|
|
12786
|
+
*/
|
|
12787
|
+
recordToolDecision(toolName, params, metadata = {}) {
|
|
12788
|
+
if (!this.isEnabled()) return;
|
|
12789
|
+
this.addEvent("ai.tool_decision", {
|
|
12790
|
+
"session.id": this.sessionId,
|
|
12791
|
+
"ai.tool_decision.name": toolName,
|
|
12792
|
+
"ai.tool_decision.params": JSON.stringify(params || {}).substring(0, 2e3),
|
|
12793
|
+
...metadata
|
|
12794
|
+
});
|
|
12795
|
+
}
|
|
12796
|
+
/**
|
|
12797
|
+
* Record tool result after execution
|
|
12798
|
+
* @param {string} toolName - The tool that was executed
|
|
12799
|
+
* @param {string|Object} result - The tool result
|
|
12800
|
+
* @param {boolean} success - Whether the tool succeeded
|
|
12801
|
+
* @param {number} durationMs - Execution duration in milliseconds
|
|
12802
|
+
* @param {Object} metadata - Additional metadata
|
|
12803
|
+
*/
|
|
12804
|
+
recordToolResult(toolName, result, success, durationMs, metadata = {}) {
|
|
12805
|
+
if (!this.isEnabled()) return;
|
|
12806
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result);
|
|
12807
|
+
this.addEvent("tool.result", {
|
|
12808
|
+
"session.id": this.sessionId,
|
|
12809
|
+
"tool.name": toolName,
|
|
12810
|
+
"tool.result": resultStr.substring(0, 1e4),
|
|
12811
|
+
"tool.result.length": resultStr.length,
|
|
12812
|
+
"tool.result.hash": this.hashContent(resultStr),
|
|
12813
|
+
"tool.duration_ms": durationMs,
|
|
12814
|
+
"tool.success": success,
|
|
12815
|
+
...metadata
|
|
12816
|
+
});
|
|
12817
|
+
}
|
|
12818
|
+
/**
|
|
12819
|
+
* Record MCP tool execution start
|
|
12820
|
+
* @param {string} toolName - MCP tool name
|
|
12821
|
+
* @param {string} serverName - MCP server name
|
|
12822
|
+
* @param {Object} params - Tool parameters
|
|
12823
|
+
* @param {Object} metadata - Additional metadata
|
|
12824
|
+
*/
|
|
12825
|
+
recordMcpToolStart(toolName, serverName, params, metadata = {}) {
|
|
12826
|
+
if (!this.isEnabled()) return;
|
|
12827
|
+
this.addEvent("mcp.tool.start", {
|
|
12828
|
+
"session.id": this.sessionId,
|
|
12829
|
+
"mcp.tool.name": toolName,
|
|
12830
|
+
"mcp.tool.server": serverName || "unknown",
|
|
12831
|
+
"mcp.tool.params": JSON.stringify(params || {}).substring(0, 2e3),
|
|
12832
|
+
...metadata
|
|
12833
|
+
});
|
|
12834
|
+
}
|
|
12835
|
+
/**
|
|
12836
|
+
* Record MCP tool execution end
|
|
12837
|
+
* @param {string} toolName - MCP tool name
|
|
12838
|
+
* @param {string} serverName - MCP server name
|
|
12839
|
+
* @param {string|Object} result - Tool result
|
|
12840
|
+
* @param {boolean} success - Whether succeeded
|
|
12841
|
+
* @param {number} durationMs - Execution duration
|
|
12842
|
+
* @param {string} errorMessage - Error message if failed
|
|
12843
|
+
* @param {Object} metadata - Additional metadata
|
|
12844
|
+
*/
|
|
12845
|
+
recordMcpToolEnd(toolName, serverName, result, success, durationMs, errorMessage = null, metadata = {}) {
|
|
12846
|
+
if (!this.isEnabled()) return;
|
|
12847
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result || "");
|
|
12848
|
+
this.addEvent("mcp.tool.end", {
|
|
12849
|
+
"session.id": this.sessionId,
|
|
12850
|
+
"mcp.tool.name": toolName,
|
|
12851
|
+
"mcp.tool.server": serverName || "unknown",
|
|
12852
|
+
"mcp.tool.result": resultStr.substring(0, 1e4),
|
|
12853
|
+
"mcp.tool.result.length": resultStr.length,
|
|
12854
|
+
"mcp.tool.duration_ms": durationMs,
|
|
12855
|
+
"mcp.tool.success": success,
|
|
12856
|
+
"mcp.tool.error": errorMessage,
|
|
12857
|
+
...metadata
|
|
12858
|
+
});
|
|
12859
|
+
}
|
|
12860
|
+
/**
|
|
12861
|
+
* Record iteration lifecycle event
|
|
12862
|
+
* @param {string} eventType - start or end
|
|
12863
|
+
* @param {number} iteration - Iteration number
|
|
12864
|
+
* @param {Object} data - Additional data
|
|
12865
|
+
*/
|
|
12866
|
+
recordIterationEvent(eventType, iteration, data = {}) {
|
|
12867
|
+
if (!this.isEnabled()) return;
|
|
12868
|
+
this.addEvent(`iteration.${eventType}`, {
|
|
12869
|
+
"session.id": this.sessionId,
|
|
12870
|
+
"iteration": iteration,
|
|
12871
|
+
...data
|
|
12872
|
+
});
|
|
12873
|
+
}
|
|
12874
|
+
/**
|
|
12875
|
+
* Record per-turn token breakdown
|
|
12876
|
+
* @param {number} iteration - Iteration number
|
|
12877
|
+
* @param {Object} tokenData - Token metrics
|
|
12878
|
+
*/
|
|
12879
|
+
recordTokenTurn(iteration, tokenData = {}) {
|
|
12880
|
+
if (!this.isEnabled()) return;
|
|
12881
|
+
this.addEvent("tokens.turn", {
|
|
12882
|
+
"session.id": this.sessionId,
|
|
12883
|
+
"iteration": iteration,
|
|
12884
|
+
"tokens.input": tokenData.inputTokens || 0,
|
|
12885
|
+
"tokens.output": tokenData.outputTokens || 0,
|
|
12886
|
+
"tokens.total": (tokenData.inputTokens || 0) + (tokenData.outputTokens || 0),
|
|
12887
|
+
"tokens.cache_read": tokenData.cacheReadTokens || 0,
|
|
12888
|
+
"tokens.cache_write": tokenData.cacheWriteTokens || 0,
|
|
12889
|
+
"tokens.context_used": tokenData.contextTokens || 0,
|
|
12890
|
+
"tokens.context_remaining": tokenData.maxContextTokens ? tokenData.maxContextTokens - (tokenData.contextTokens || 0) : null
|
|
12891
|
+
});
|
|
12892
|
+
}
|
|
12703
12893
|
async withSpan(spanName, fn, attributes = {}) {
|
|
12704
12894
|
if (!this.isEnabled()) {
|
|
12705
12895
|
return fn();
|
|
@@ -20406,11 +20596,12 @@ function createTools(configOptions) {
|
|
|
20406
20596
|
return tools2;
|
|
20407
20597
|
}
|
|
20408
20598
|
function parseXmlToolCallWithThinking(xmlString, validTools) {
|
|
20409
|
-
const { cleanedXmlString, recoveryResult } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
20599
|
+
const { cleanedXmlString, recoveryResult, thinkingContent } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
20410
20600
|
if (recoveryResult) {
|
|
20411
|
-
return recoveryResult;
|
|
20601
|
+
return { ...recoveryResult, thinkingContent };
|
|
20412
20602
|
}
|
|
20413
|
-
|
|
20603
|
+
const toolCall = parseXmlToolCall(cleanedXmlString, validTools);
|
|
20604
|
+
return toolCall ? { ...toolCall, thinkingContent } : null;
|
|
20414
20605
|
}
|
|
20415
20606
|
var implementToolDefinition, listFilesToolDefinition, searchFilesToolDefinition, listSkillsToolDefinition, useSkillToolDefinition, readImageToolDefinition;
|
|
20416
20607
|
var init_tools2 = __esm({
|
|
@@ -59704,25 +59895,27 @@ function parseXmlMcpToolCall(xmlString, mcpToolNames = []) {
|
|
|
59704
59895
|
function parseHybridXmlToolCall(xmlString, nativeTools = [], mcpBridge = null) {
|
|
59705
59896
|
const nativeResult = parseNativeXmlToolWithThinking(xmlString, nativeTools);
|
|
59706
59897
|
if (nativeResult) {
|
|
59707
|
-
|
|
59898
|
+
const { thinkingContent, ...rest } = nativeResult;
|
|
59899
|
+
return { ...rest, type: "native", thinkingContent };
|
|
59708
59900
|
}
|
|
59709
59901
|
if (mcpBridge) {
|
|
59710
59902
|
const mcpResult = parseXmlMcpToolCall(xmlString, mcpBridge.getToolNames());
|
|
59711
59903
|
if (mcpResult) {
|
|
59712
|
-
|
|
59904
|
+
const { thinkingContent } = processXmlWithThinkingAndRecovery(xmlString, []);
|
|
59905
|
+
return { ...mcpResult, type: "mcp", thinkingContent };
|
|
59713
59906
|
}
|
|
59714
59907
|
}
|
|
59715
59908
|
return null;
|
|
59716
59909
|
}
|
|
59717
59910
|
function parseNativeXmlToolWithThinking(xmlString, validTools) {
|
|
59718
|
-
const { cleanedXmlString, recoveryResult } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
59911
|
+
const { cleanedXmlString, recoveryResult, thinkingContent } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
59719
59912
|
if (recoveryResult) {
|
|
59720
|
-
return recoveryResult;
|
|
59913
|
+
return { ...recoveryResult, thinkingContent };
|
|
59721
59914
|
}
|
|
59722
59915
|
for (const toolName of validTools) {
|
|
59723
59916
|
const result = parseNativeXmlTool(cleanedXmlString, toolName);
|
|
59724
59917
|
if (result) {
|
|
59725
|
-
return result;
|
|
59918
|
+
return { ...result, thinkingContent };
|
|
59726
59919
|
}
|
|
59727
59920
|
}
|
|
59728
59921
|
return null;
|
|
@@ -70184,6 +70377,181 @@ var init_ProbeAgent = __esm({
|
|
|
70184
70377
|
_filterMcpTools(mcpToolNames) {
|
|
70185
70378
|
return mcpToolNames.filter((toolName) => this._isMcpToolAllowed(toolName));
|
|
70186
70379
|
}
|
|
70380
|
+
/**
|
|
70381
|
+
* Check if tracer is AppTracer (expects sessionId as first param) vs SimpleAppTracer
|
|
70382
|
+
* @returns {boolean} - True if tracer is AppTracer style (requires sessionId)
|
|
70383
|
+
* @private
|
|
70384
|
+
*/
|
|
70385
|
+
_isAppTracerStyle() {
|
|
70386
|
+
return this.tracer && typeof this.tracer.sessionSpans !== "undefined";
|
|
70387
|
+
}
|
|
70388
|
+
/**
|
|
70389
|
+
* Record an error classification event for telemetry
|
|
70390
|
+
* Provides unified error recording across all error types
|
|
70391
|
+
* @param {string} errorType - Error type (wrapped_tool, unrecognized_tool, no_tool_call, circuit_breaker)
|
|
70392
|
+
* @param {string} message - Error message
|
|
70393
|
+
* @param {Object} context - Additional context data
|
|
70394
|
+
* @param {number} iteration - Current iteration number
|
|
70395
|
+
* @private
|
|
70396
|
+
*/
|
|
70397
|
+
_recordErrorTelemetry(errorType, message, context, iteration) {
|
|
70398
|
+
if (!this.tracer) return;
|
|
70399
|
+
if (this._isAppTracerStyle() && typeof this.tracer.recordErrorClassification === "function") {
|
|
70400
|
+
this.tracer.recordErrorClassification(this.sessionId, iteration, errorType, {
|
|
70401
|
+
message,
|
|
70402
|
+
context
|
|
70403
|
+
});
|
|
70404
|
+
} else if (typeof this.tracer.recordErrorEvent === "function") {
|
|
70405
|
+
this.tracer.recordErrorEvent(errorType, {
|
|
70406
|
+
message,
|
|
70407
|
+
context: { ...context, iteration }
|
|
70408
|
+
});
|
|
70409
|
+
} else {
|
|
70410
|
+
this.tracer.addEvent(`error.${errorType}`, {
|
|
70411
|
+
"error.type": errorType,
|
|
70412
|
+
"error.message": message,
|
|
70413
|
+
"error.recoverable": errorType !== "circuit_breaker",
|
|
70414
|
+
"error.context": JSON.stringify(context).substring(0, 1e3),
|
|
70415
|
+
"iteration": iteration
|
|
70416
|
+
});
|
|
70417
|
+
}
|
|
70418
|
+
}
|
|
70419
|
+
/**
|
|
70420
|
+
* Record AI thinking content for telemetry
|
|
70421
|
+
* @param {string} thinkingContent - The thinking content
|
|
70422
|
+
* @param {number} iteration - Current iteration number
|
|
70423
|
+
* @private
|
|
70424
|
+
*/
|
|
70425
|
+
_recordThinkingTelemetry(thinkingContent, iteration) {
|
|
70426
|
+
if (!this.tracer || !thinkingContent) return;
|
|
70427
|
+
if (this._isAppTracerStyle() && typeof this.tracer.recordThinkingContent === "function") {
|
|
70428
|
+
this.tracer.recordThinkingContent(this.sessionId, iteration, thinkingContent);
|
|
70429
|
+
} else if (typeof this.tracer.recordThinkingContent === "function") {
|
|
70430
|
+
this.tracer.recordThinkingContent(thinkingContent, { iteration });
|
|
70431
|
+
} else {
|
|
70432
|
+
this.tracer.addEvent("ai.thinking", {
|
|
70433
|
+
"ai.thinking.content": thinkingContent.substring(0, 5e4),
|
|
70434
|
+
"ai.thinking.length": thinkingContent.length,
|
|
70435
|
+
"iteration": iteration
|
|
70436
|
+
});
|
|
70437
|
+
}
|
|
70438
|
+
}
|
|
70439
|
+
/**
|
|
70440
|
+
* Record AI tool decision for telemetry
|
|
70441
|
+
* @param {string} toolName - The tool name
|
|
70442
|
+
* @param {Object} params - Tool parameters
|
|
70443
|
+
* @param {number} responseLength - Length of AI response
|
|
70444
|
+
* @param {number} iteration - Current iteration number
|
|
70445
|
+
* @private
|
|
70446
|
+
*/
|
|
70447
|
+
_recordToolDecisionTelemetry(toolName, params, responseLength, iteration) {
|
|
70448
|
+
if (!this.tracer) return;
|
|
70449
|
+
if (this._isAppTracerStyle() && typeof this.tracer.recordAIToolDecision === "function") {
|
|
70450
|
+
this.tracer.recordAIToolDecision(this.sessionId, iteration, toolName, params);
|
|
70451
|
+
} else if (typeof this.tracer.recordToolDecision === "function") {
|
|
70452
|
+
this.tracer.recordToolDecision(toolName, params, {
|
|
70453
|
+
iteration,
|
|
70454
|
+
"ai.tool_decision.raw_response_length": responseLength
|
|
70455
|
+
});
|
|
70456
|
+
} else {
|
|
70457
|
+
this.tracer.addEvent("ai.tool_decision", {
|
|
70458
|
+
"ai.tool_decision.name": toolName,
|
|
70459
|
+
"ai.tool_decision.params": JSON.stringify(params || {}).substring(0, 2e3),
|
|
70460
|
+
"ai.tool_decision.raw_response_length": responseLength,
|
|
70461
|
+
"iteration": iteration
|
|
70462
|
+
});
|
|
70463
|
+
}
|
|
70464
|
+
}
|
|
70465
|
+
/**
|
|
70466
|
+
* Record tool result for telemetry
|
|
70467
|
+
* @param {string} toolName - The tool name
|
|
70468
|
+
* @param {string|Object} result - Tool result
|
|
70469
|
+
* @param {boolean} success - Whether tool succeeded
|
|
70470
|
+
* @param {number} durationMs - Execution duration in milliseconds
|
|
70471
|
+
* @param {number} iteration - Current iteration number
|
|
70472
|
+
* @private
|
|
70473
|
+
*/
|
|
70474
|
+
_recordToolResultTelemetry(toolName, result, success, durationMs, iteration) {
|
|
70475
|
+
if (!this.tracer) return;
|
|
70476
|
+
if (this._isAppTracerStyle() && typeof this.tracer.recordToolResult === "function") {
|
|
70477
|
+
this.tracer.recordToolResult(this.sessionId, iteration, toolName, result, success, durationMs);
|
|
70478
|
+
} else if (typeof this.tracer.recordToolResult === "function") {
|
|
70479
|
+
this.tracer.recordToolResult(toolName, result, success, durationMs, { iteration });
|
|
70480
|
+
} else {
|
|
70481
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result || "");
|
|
70482
|
+
this.tracer.addEvent("tool.result", {
|
|
70483
|
+
"tool.name": toolName,
|
|
70484
|
+
"tool.result": resultStr.substring(0, 1e4),
|
|
70485
|
+
"tool.result.length": resultStr.length,
|
|
70486
|
+
"tool.duration_ms": durationMs,
|
|
70487
|
+
"tool.success": success,
|
|
70488
|
+
"iteration": iteration
|
|
70489
|
+
});
|
|
70490
|
+
}
|
|
70491
|
+
}
|
|
70492
|
+
/**
|
|
70493
|
+
* Record MCP tool lifecycle event for telemetry
|
|
70494
|
+
* @param {string} phase - 'start' or 'end'
|
|
70495
|
+
* @param {string} toolName - MCP tool name
|
|
70496
|
+
* @param {Object} params - Tool parameters (for start) or null (for end)
|
|
70497
|
+
* @param {number} iteration - Current iteration number
|
|
70498
|
+
* @param {Object} [endData] - Additional data for end phase (result, success, durationMs, error)
|
|
70499
|
+
* @private
|
|
70500
|
+
*/
|
|
70501
|
+
_recordMcpToolTelemetry(phase, toolName, params, iteration, endData = null) {
|
|
70502
|
+
if (!this.tracer) return;
|
|
70503
|
+
if (phase === "start") {
|
|
70504
|
+
if (this._isAppTracerStyle() && typeof this.tracer.recordMcpToolStart === "function") {
|
|
70505
|
+
this.tracer.recordMcpToolStart(this.sessionId, iteration, toolName, "mcp", params);
|
|
70506
|
+
} else if (typeof this.tracer.recordMcpToolStart === "function") {
|
|
70507
|
+
this.tracer.recordMcpToolStart(toolName, "mcp", params, { iteration });
|
|
70508
|
+
} else {
|
|
70509
|
+
this.tracer.addEvent("mcp.tool.start", {
|
|
70510
|
+
"mcp.tool.name": toolName,
|
|
70511
|
+
"mcp.tool.server": "mcp",
|
|
70512
|
+
"mcp.tool.params": JSON.stringify(params || {}).substring(0, 2e3),
|
|
70513
|
+
"iteration": iteration
|
|
70514
|
+
});
|
|
70515
|
+
}
|
|
70516
|
+
} else if (phase === "end" && endData) {
|
|
70517
|
+
const { result, success, durationMs, error } = endData;
|
|
70518
|
+
if (this._isAppTracerStyle() && typeof this.tracer.recordMcpToolEnd === "function") {
|
|
70519
|
+
this.tracer.recordMcpToolEnd(this.sessionId, iteration, toolName, "mcp", result, success, durationMs, error);
|
|
70520
|
+
} else if (typeof this.tracer.recordMcpToolEnd === "function") {
|
|
70521
|
+
this.tracer.recordMcpToolEnd(toolName, "mcp", result, success, durationMs, error, { iteration });
|
|
70522
|
+
} else {
|
|
70523
|
+
const resultStr = typeof result === "string" ? result : JSON.stringify(result || "");
|
|
70524
|
+
this.tracer.addEvent("mcp.tool.end", {
|
|
70525
|
+
"mcp.tool.name": toolName,
|
|
70526
|
+
"mcp.tool.server": "mcp",
|
|
70527
|
+
"mcp.tool.result": resultStr.substring(0, 1e4),
|
|
70528
|
+
"mcp.tool.result.length": resultStr.length,
|
|
70529
|
+
"mcp.tool.duration_ms": durationMs,
|
|
70530
|
+
"mcp.tool.success": success,
|
|
70531
|
+
"mcp.tool.error": error,
|
|
70532
|
+
"iteration": iteration
|
|
70533
|
+
});
|
|
70534
|
+
}
|
|
70535
|
+
}
|
|
70536
|
+
}
|
|
70537
|
+
/**
|
|
70538
|
+
* Record iteration lifecycle event for telemetry
|
|
70539
|
+
* @param {string} phase - 'end' (start is already handled elsewhere)
|
|
70540
|
+
* @param {number} iteration - Current iteration number
|
|
70541
|
+
* @param {Object} data - Additional iteration data
|
|
70542
|
+
* @private
|
|
70543
|
+
*/
|
|
70544
|
+
_recordIterationTelemetry(phase, iteration, data = {}) {
|
|
70545
|
+
if (!this.tracer) return;
|
|
70546
|
+
if (typeof this.tracer.recordIterationEvent === "function") {
|
|
70547
|
+
this.tracer.recordIterationEvent(phase, iteration, data);
|
|
70548
|
+
} else {
|
|
70549
|
+
this.tracer.addEvent(`iteration.${phase}`, {
|
|
70550
|
+
"iteration": iteration,
|
|
70551
|
+
...data
|
|
70552
|
+
});
|
|
70553
|
+
}
|
|
70554
|
+
}
|
|
70187
70555
|
/**
|
|
70188
70556
|
* Initialize the agent asynchronously (must be called after constructor)
|
|
70189
70557
|
* This method initializes MCP and merges MCP tools into the tool list, and loads history from storage
|
|
@@ -72138,8 +72506,12 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72138
72506
|
}
|
|
72139
72507
|
const nativeTools = validTools;
|
|
72140
72508
|
const parsedTool = this.mcpBridge && !options._disableTools ? parseHybridXmlToolCall(assistantResponseContent, nativeTools, this.mcpBridge) : parseXmlToolCallWithThinking(assistantResponseContent, validTools);
|
|
72509
|
+
if (parsedTool?.thinkingContent) {
|
|
72510
|
+
this._recordThinkingTelemetry(parsedTool.thinkingContent, currentIteration);
|
|
72511
|
+
}
|
|
72141
72512
|
if (parsedTool) {
|
|
72142
72513
|
const { toolName, params } = parsedTool;
|
|
72514
|
+
this._recordToolDecisionTelemetry(toolName, params, assistantResponseContent.length, currentIteration);
|
|
72143
72515
|
if (this.debug) console.log(`[DEBUG] Parsed tool call: ${toolName} with params:`, params);
|
|
72144
72516
|
if (toolName === "attempt_completion") {
|
|
72145
72517
|
completionAttempted = true;
|
|
@@ -72216,6 +72588,8 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72216
72588
|
} else {
|
|
72217
72589
|
const { type } = parsedTool;
|
|
72218
72590
|
if (type === "mcp" && this.mcpBridge && this.mcpBridge.isMcpTool(toolName)) {
|
|
72591
|
+
const mcpStartTime = Date.now();
|
|
72592
|
+
this._recordMcpToolTelemetry("start", toolName, params, currentIteration);
|
|
72219
72593
|
try {
|
|
72220
72594
|
if (this.debug) {
|
|
72221
72595
|
console.error(`
|
|
@@ -72245,6 +72619,13 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72245
72619
|
} catch (truncateError) {
|
|
72246
72620
|
console.error(`[WARN] Tool output truncation failed: ${truncateError.message}`);
|
|
72247
72621
|
}
|
|
72622
|
+
const mcpDurationMs = Date.now() - mcpStartTime;
|
|
72623
|
+
this._recordMcpToolTelemetry("end", toolName, null, currentIteration, {
|
|
72624
|
+
result: toolResultContent,
|
|
72625
|
+
success: true,
|
|
72626
|
+
durationMs: mcpDurationMs,
|
|
72627
|
+
error: null
|
|
72628
|
+
});
|
|
72248
72629
|
if (this.debug) {
|
|
72249
72630
|
const preview = toolResultContent.length > 500 ? toolResultContent.substring(0, 500) + "..." : toolResultContent;
|
|
72250
72631
|
console.error(`[DEBUG] ========================================`);
|
|
@@ -72258,6 +72639,13 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72258
72639
|
${toolResultContent}
|
|
72259
72640
|
</tool_result>` });
|
|
72260
72641
|
} catch (error) {
|
|
72642
|
+
const mcpDurationMs = Date.now() - mcpStartTime;
|
|
72643
|
+
this._recordMcpToolTelemetry("end", toolName, null, currentIteration, {
|
|
72644
|
+
result: null,
|
|
72645
|
+
success: false,
|
|
72646
|
+
durationMs: mcpDurationMs,
|
|
72647
|
+
error: error.message
|
|
72648
|
+
});
|
|
72261
72649
|
console.error(`Error executing MCP tool ${toolName}:`, error);
|
|
72262
72650
|
if (this.debug) {
|
|
72263
72651
|
console.error(`[DEBUG] ========================================`);
|
|
@@ -72349,6 +72737,7 @@ ${errorXml}
|
|
|
72349
72737
|
return await this.toolImplementations[toolName].execute(toolParams);
|
|
72350
72738
|
};
|
|
72351
72739
|
let toolResult;
|
|
72740
|
+
const toolStartTime = Date.now();
|
|
72352
72741
|
try {
|
|
72353
72742
|
if (this.tracer) {
|
|
72354
72743
|
toolResult = await this.tracer.withSpan("tool.call", executeToolCall, {
|
|
@@ -72359,6 +72748,8 @@ ${errorXml}
|
|
|
72359
72748
|
} else {
|
|
72360
72749
|
toolResult = await executeToolCall();
|
|
72361
72750
|
}
|
|
72751
|
+
const toolDurationMs = Date.now() - toolStartTime;
|
|
72752
|
+
this._recordToolResultTelemetry(toolName, toolResult, true, toolDurationMs, currentIteration);
|
|
72362
72753
|
if (this.debug) {
|
|
72363
72754
|
const resultPreview = typeof toolResult === "string" ? toolResult.length > 500 ? toolResult.substring(0, 500) + "..." : toolResult : toolResult ? JSON.stringify(toolResult, null, 2).substring(0, 500) + "..." : "No Result";
|
|
72364
72755
|
console.error(`[DEBUG] ========================================`);
|
|
@@ -72415,6 +72806,20 @@ ${toolResultContent}
|
|
|
72415
72806
|
role: "user",
|
|
72416
72807
|
content: toolResultMessage
|
|
72417
72808
|
});
|
|
72809
|
+
if (this.tracer) {
|
|
72810
|
+
if (typeof this.tracer.recordConversationTurn === "function") {
|
|
72811
|
+
this.tracer.recordConversationTurn("assistant", assistantResponseContent, {
|
|
72812
|
+
iteration: currentIteration,
|
|
72813
|
+
has_tool_call: true,
|
|
72814
|
+
tool_name: toolName
|
|
72815
|
+
});
|
|
72816
|
+
this.tracer.recordConversationTurn("tool_result", toolResultContent, {
|
|
72817
|
+
iteration: currentIteration,
|
|
72818
|
+
tool_name: toolName,
|
|
72819
|
+
tool_success: true
|
|
72820
|
+
});
|
|
72821
|
+
}
|
|
72822
|
+
}
|
|
72418
72823
|
if (this.debug) {
|
|
72419
72824
|
console.log(`[DEBUG] Tool ${toolName} executed successfully. Result length: ${typeof toolResult === "string" ? toolResult.length : JSON.stringify(toolResult).length}`);
|
|
72420
72825
|
}
|
|
@@ -72485,6 +72890,7 @@ ${errorXml}
|
|
|
72485
72890
|
if (this.debug) {
|
|
72486
72891
|
console.log(`[DEBUG] Detected wrapped tool '${wrappedToolName}' in assistant response - wrong XML format.`);
|
|
72487
72892
|
}
|
|
72893
|
+
this._recordErrorTelemetry("wrapped_tool", "Tool call wrapped in markdown", { toolName: wrappedToolName }, currentIteration);
|
|
72488
72894
|
const toolError = new ParameterError(
|
|
72489
72895
|
`Tool '${wrappedToolName}' found but in WRONG FORMAT - do not wrap tools in other XML tags.`,
|
|
72490
72896
|
{
|
|
@@ -72510,6 +72916,7 @@ ${formatErrorForAI(toolError)}
|
|
|
72510
72916
|
if (this.debug) {
|
|
72511
72917
|
console.log(`[DEBUG] Detected unrecognized tool '${unrecognizedTool}' in assistant response.`);
|
|
72512
72918
|
}
|
|
72919
|
+
this._recordErrorTelemetry("unrecognized_tool", `Unknown tool: ${unrecognizedTool}`, { toolName: unrecognizedTool, validTools }, currentIteration);
|
|
72513
72920
|
const toolError = new ParameterError(`Tool '${unrecognizedTool}' is not available in this context.`, {
|
|
72514
72921
|
suggestion: `Available tools: ${validTools.join(", ")}. Please use one of these tools instead.`
|
|
72515
72922
|
});
|
|
@@ -72517,6 +72924,7 @@ ${formatErrorForAI(toolError)}
|
|
|
72517
72924
|
${formatErrorForAI(toolError)}
|
|
72518
72925
|
</tool_result>`;
|
|
72519
72926
|
} else {
|
|
72927
|
+
this._recordErrorTelemetry("no_tool_call", "AI response did not contain tool call", { responsePreview: assistantResponseContent.substring(0, 500) }, currentIteration);
|
|
72520
72928
|
if (currentIteration >= maxIterations) {
|
|
72521
72929
|
let cleanedResponse = assistantResponseContent;
|
|
72522
72930
|
cleanedResponse = cleanedResponse.replace(/<thinking>[\s\S]*?<\/thinking>/gi, "").trim();
|
|
@@ -72592,6 +73000,7 @@ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant messa
|
|
|
72592
73000
|
sameFormatErrorCount++;
|
|
72593
73001
|
if (sameFormatErrorCount >= MAX_REPEATED_FORMAT_ERRORS) {
|
|
72594
73002
|
const errorDesc = isWrapped ? "wrapped tool format" : unrecognizedTool;
|
|
73003
|
+
this._recordErrorTelemetry("circuit_breaker", "Format error limit exceeded", { formatErrorCount: sameFormatErrorCount, errorCategory }, currentIteration);
|
|
72595
73004
|
console.error(`[ERROR] Format error category '${errorCategory}' repeated ${sameFormatErrorCount} times. Breaking loop early to prevent infinite iteration.`);
|
|
72596
73005
|
finalResult = `Error: Unable to complete request. The AI model repeatedly used incorrect tool call format (${errorDesc}). Please try rephrasing your question or using a different model.`;
|
|
72597
73006
|
break;
|
|
@@ -72605,6 +73014,10 @@ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant messa
|
|
|
72605
73014
|
sameFormatErrorCount = 0;
|
|
72606
73015
|
}
|
|
72607
73016
|
}
|
|
73017
|
+
this._recordIterationTelemetry("end", currentIteration, {
|
|
73018
|
+
"iteration.completed": completionAttempted,
|
|
73019
|
+
"iteration.message_count": currentMessages.length
|
|
73020
|
+
});
|
|
72608
73021
|
if (currentMessages.length > MAX_HISTORY_MESSAGES) {
|
|
72609
73022
|
const messagesBefore = currentMessages.length;
|
|
72610
73023
|
const systemMsg = currentMessages[0];
|
|
@@ -321,14 +321,17 @@ export function parseHybridXmlToolCall(xmlString, nativeTools = [], mcpBridge =
|
|
|
321
321
|
// This includes thinking tag removal and attempt_complete recovery logic
|
|
322
322
|
const nativeResult = parseNativeXmlToolWithThinking(xmlString, nativeTools);
|
|
323
323
|
if (nativeResult) {
|
|
324
|
-
|
|
324
|
+
const { thinkingContent, ...rest } = nativeResult;
|
|
325
|
+
return { ...rest, type: 'native', thinkingContent };
|
|
325
326
|
}
|
|
326
327
|
|
|
327
328
|
// Then try MCP tools if bridge is available
|
|
328
329
|
if (mcpBridge) {
|
|
329
330
|
const mcpResult = parseXmlMcpToolCall(xmlString, mcpBridge.getToolNames());
|
|
330
331
|
if (mcpResult) {
|
|
331
|
-
|
|
332
|
+
// Extract thinking content for MCP tools as well
|
|
333
|
+
const { thinkingContent } = processXmlWithThinkingAndRecovery(xmlString, []);
|
|
334
|
+
return { ...mcpResult, type: 'mcp', thinkingContent };
|
|
332
335
|
}
|
|
333
336
|
}
|
|
334
337
|
|
|
@@ -344,18 +347,18 @@ export function parseHybridXmlToolCall(xmlString, nativeTools = [], mcpBridge =
|
|
|
344
347
|
*/
|
|
345
348
|
function parseNativeXmlToolWithThinking(xmlString, validTools) {
|
|
346
349
|
// Use the shared processing logic
|
|
347
|
-
const { cleanedXmlString, recoveryResult } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
348
|
-
|
|
349
|
-
// If recovery found an attempt_complete pattern, return it
|
|
350
|
+
const { cleanedXmlString, recoveryResult, thinkingContent } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
351
|
+
|
|
352
|
+
// If recovery found an attempt_complete pattern, return it with thinking content
|
|
350
353
|
if (recoveryResult) {
|
|
351
|
-
return recoveryResult;
|
|
354
|
+
return { ...recoveryResult, thinkingContent };
|
|
352
355
|
}
|
|
353
356
|
|
|
354
357
|
// Use the original parseNativeXmlTool function to parse the cleaned XML string
|
|
355
358
|
for (const toolName of validTools) {
|
|
356
359
|
const result = parseNativeXmlTool(cleanedXmlString, toolName);
|
|
357
360
|
if (result) {
|
|
358
|
-
return result;
|
|
361
|
+
return { ...result, thinkingContent };
|
|
359
362
|
}
|
|
360
363
|
}
|
|
361
364
|
|