@probelabs/probe 0.6.0-rc224 → 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-rc224-x86_64-pc-windows-msvc.zip → 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 +408 -8
- package/build/agent/mcp/xmlBridge.js +10 -7
- package/build/agent/simpleTelemetry.js +198 -0
- package/build/agent/tools.js +8 -5
- package/cjs/agent/ProbeAgent.cjs +231 -8
- package/cjs/agent/simpleTelemetry.cjs +177 -0
- package/cjs/index.cjs +408 -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/bin/binaries/probe-v0.6.0-rc224-aarch64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc224-aarch64-unknown-linux-musl.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc224-x86_64-apple-darwin.tar.gz +0 -0
- package/bin/binaries/probe-v0.6.0-rc224-x86_64-unknown-linux-musl.tar.gz +0 -0
package/build/agent/index.js
CHANGED
|
@@ -12713,6 +12713,183 @@ var init_simpleTelemetry = __esm({
|
|
|
12713
12713
|
console.log("[Attributes]", attributes);
|
|
12714
12714
|
}
|
|
12715
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
|
+
}
|
|
12716
12893
|
async withSpan(spanName, fn, attributes = {}) {
|
|
12717
12894
|
if (!this.isEnabled()) {
|
|
12718
12895
|
return fn();
|
|
@@ -20419,11 +20596,12 @@ function createTools(configOptions) {
|
|
|
20419
20596
|
return tools2;
|
|
20420
20597
|
}
|
|
20421
20598
|
function parseXmlToolCallWithThinking(xmlString, validTools) {
|
|
20422
|
-
const { cleanedXmlString, recoveryResult } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
20599
|
+
const { cleanedXmlString, recoveryResult, thinkingContent } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
20423
20600
|
if (recoveryResult) {
|
|
20424
|
-
return recoveryResult;
|
|
20601
|
+
return { ...recoveryResult, thinkingContent };
|
|
20425
20602
|
}
|
|
20426
|
-
|
|
20603
|
+
const toolCall = parseXmlToolCall(cleanedXmlString, validTools);
|
|
20604
|
+
return toolCall ? { ...toolCall, thinkingContent } : null;
|
|
20427
20605
|
}
|
|
20428
20606
|
var implementToolDefinition, listFilesToolDefinition, searchFilesToolDefinition, listSkillsToolDefinition, useSkillToolDefinition, readImageToolDefinition;
|
|
20429
20607
|
var init_tools2 = __esm({
|
|
@@ -59717,25 +59895,27 @@ function parseXmlMcpToolCall(xmlString, mcpToolNames = []) {
|
|
|
59717
59895
|
function parseHybridXmlToolCall(xmlString, nativeTools = [], mcpBridge = null) {
|
|
59718
59896
|
const nativeResult = parseNativeXmlToolWithThinking(xmlString, nativeTools);
|
|
59719
59897
|
if (nativeResult) {
|
|
59720
|
-
|
|
59898
|
+
const { thinkingContent, ...rest } = nativeResult;
|
|
59899
|
+
return { ...rest, type: "native", thinkingContent };
|
|
59721
59900
|
}
|
|
59722
59901
|
if (mcpBridge) {
|
|
59723
59902
|
const mcpResult = parseXmlMcpToolCall(xmlString, mcpBridge.getToolNames());
|
|
59724
59903
|
if (mcpResult) {
|
|
59725
|
-
|
|
59904
|
+
const { thinkingContent } = processXmlWithThinkingAndRecovery(xmlString, []);
|
|
59905
|
+
return { ...mcpResult, type: "mcp", thinkingContent };
|
|
59726
59906
|
}
|
|
59727
59907
|
}
|
|
59728
59908
|
return null;
|
|
59729
59909
|
}
|
|
59730
59910
|
function parseNativeXmlToolWithThinking(xmlString, validTools) {
|
|
59731
|
-
const { cleanedXmlString, recoveryResult } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
59911
|
+
const { cleanedXmlString, recoveryResult, thinkingContent } = processXmlWithThinkingAndRecovery(xmlString, validTools);
|
|
59732
59912
|
if (recoveryResult) {
|
|
59733
|
-
return recoveryResult;
|
|
59913
|
+
return { ...recoveryResult, thinkingContent };
|
|
59734
59914
|
}
|
|
59735
59915
|
for (const toolName of validTools) {
|
|
59736
59916
|
const result = parseNativeXmlTool(cleanedXmlString, toolName);
|
|
59737
59917
|
if (result) {
|
|
59738
|
-
return result;
|
|
59918
|
+
return { ...result, thinkingContent };
|
|
59739
59919
|
}
|
|
59740
59920
|
}
|
|
59741
59921
|
return null;
|
|
@@ -70197,6 +70377,181 @@ var init_ProbeAgent = __esm({
|
|
|
70197
70377
|
_filterMcpTools(mcpToolNames) {
|
|
70198
70378
|
return mcpToolNames.filter((toolName) => this._isMcpToolAllowed(toolName));
|
|
70199
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
|
+
}
|
|
70200
70555
|
/**
|
|
70201
70556
|
* Initialize the agent asynchronously (must be called after constructor)
|
|
70202
70557
|
* This method initializes MCP and merges MCP tools into the tool list, and loads history from storage
|
|
@@ -72151,8 +72506,12 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72151
72506
|
}
|
|
72152
72507
|
const nativeTools = validTools;
|
|
72153
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
|
+
}
|
|
72154
72512
|
if (parsedTool) {
|
|
72155
72513
|
const { toolName, params } = parsedTool;
|
|
72514
|
+
this._recordToolDecisionTelemetry(toolName, params, assistantResponseContent.length, currentIteration);
|
|
72156
72515
|
if (this.debug) console.log(`[DEBUG] Parsed tool call: ${toolName} with params:`, params);
|
|
72157
72516
|
if (toolName === "attempt_completion") {
|
|
72158
72517
|
completionAttempted = true;
|
|
@@ -72229,6 +72588,8 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72229
72588
|
} else {
|
|
72230
72589
|
const { type } = parsedTool;
|
|
72231
72590
|
if (type === "mcp" && this.mcpBridge && this.mcpBridge.isMcpTool(toolName)) {
|
|
72591
|
+
const mcpStartTime = Date.now();
|
|
72592
|
+
this._recordMcpToolTelemetry("start", toolName, params, currentIteration);
|
|
72232
72593
|
try {
|
|
72233
72594
|
if (this.debug) {
|
|
72234
72595
|
console.error(`
|
|
@@ -72258,6 +72619,13 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72258
72619
|
} catch (truncateError) {
|
|
72259
72620
|
console.error(`[WARN] Tool output truncation failed: ${truncateError.message}`);
|
|
72260
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
|
+
});
|
|
72261
72629
|
if (this.debug) {
|
|
72262
72630
|
const preview = toolResultContent.length > 500 ? toolResultContent.substring(0, 500) + "..." : toolResultContent;
|
|
72263
72631
|
console.error(`[DEBUG] ========================================`);
|
|
@@ -72271,6 +72639,13 @@ You are working with a repository located at: ${searchDirectory}
|
|
|
72271
72639
|
${toolResultContent}
|
|
72272
72640
|
</tool_result>` });
|
|
72273
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
|
+
});
|
|
72274
72649
|
console.error(`Error executing MCP tool ${toolName}:`, error);
|
|
72275
72650
|
if (this.debug) {
|
|
72276
72651
|
console.error(`[DEBUG] ========================================`);
|
|
@@ -72362,6 +72737,7 @@ ${errorXml}
|
|
|
72362
72737
|
return await this.toolImplementations[toolName].execute(toolParams);
|
|
72363
72738
|
};
|
|
72364
72739
|
let toolResult;
|
|
72740
|
+
const toolStartTime = Date.now();
|
|
72365
72741
|
try {
|
|
72366
72742
|
if (this.tracer) {
|
|
72367
72743
|
toolResult = await this.tracer.withSpan("tool.call", executeToolCall, {
|
|
@@ -72372,6 +72748,8 @@ ${errorXml}
|
|
|
72372
72748
|
} else {
|
|
72373
72749
|
toolResult = await executeToolCall();
|
|
72374
72750
|
}
|
|
72751
|
+
const toolDurationMs = Date.now() - toolStartTime;
|
|
72752
|
+
this._recordToolResultTelemetry(toolName, toolResult, true, toolDurationMs, currentIteration);
|
|
72375
72753
|
if (this.debug) {
|
|
72376
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";
|
|
72377
72755
|
console.error(`[DEBUG] ========================================`);
|
|
@@ -72428,6 +72806,20 @@ ${toolResultContent}
|
|
|
72428
72806
|
role: "user",
|
|
72429
72807
|
content: toolResultMessage
|
|
72430
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
|
+
}
|
|
72431
72823
|
if (this.debug) {
|
|
72432
72824
|
console.log(`[DEBUG] Tool ${toolName} executed successfully. Result length: ${typeof toolResult === "string" ? toolResult.length : JSON.stringify(toolResult).length}`);
|
|
72433
72825
|
}
|
|
@@ -72498,6 +72890,7 @@ ${errorXml}
|
|
|
72498
72890
|
if (this.debug) {
|
|
72499
72891
|
console.log(`[DEBUG] Detected wrapped tool '${wrappedToolName}' in assistant response - wrong XML format.`);
|
|
72500
72892
|
}
|
|
72893
|
+
this._recordErrorTelemetry("wrapped_tool", "Tool call wrapped in markdown", { toolName: wrappedToolName }, currentIteration);
|
|
72501
72894
|
const toolError = new ParameterError(
|
|
72502
72895
|
`Tool '${wrappedToolName}' found but in WRONG FORMAT - do not wrap tools in other XML tags.`,
|
|
72503
72896
|
{
|
|
@@ -72523,6 +72916,7 @@ ${formatErrorForAI(toolError)}
|
|
|
72523
72916
|
if (this.debug) {
|
|
72524
72917
|
console.log(`[DEBUG] Detected unrecognized tool '${unrecognizedTool}' in assistant response.`);
|
|
72525
72918
|
}
|
|
72919
|
+
this._recordErrorTelemetry("unrecognized_tool", `Unknown tool: ${unrecognizedTool}`, { toolName: unrecognizedTool, validTools }, currentIteration);
|
|
72526
72920
|
const toolError = new ParameterError(`Tool '${unrecognizedTool}' is not available in this context.`, {
|
|
72527
72921
|
suggestion: `Available tools: ${validTools.join(", ")}. Please use one of these tools instead.`
|
|
72528
72922
|
});
|
|
@@ -72530,6 +72924,7 @@ ${formatErrorForAI(toolError)}
|
|
|
72530
72924
|
${formatErrorForAI(toolError)}
|
|
72531
72925
|
</tool_result>`;
|
|
72532
72926
|
} else {
|
|
72927
|
+
this._recordErrorTelemetry("no_tool_call", "AI response did not contain tool call", { responsePreview: assistantResponseContent.substring(0, 500) }, currentIteration);
|
|
72533
72928
|
if (currentIteration >= maxIterations) {
|
|
72534
72929
|
let cleanedResponse = assistantResponseContent;
|
|
72535
72930
|
cleanedResponse = cleanedResponse.replace(/<thinking>[\s\S]*?<\/thinking>/gi, "").trim();
|
|
@@ -72605,6 +73000,7 @@ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant messa
|
|
|
72605
73000
|
sameFormatErrorCount++;
|
|
72606
73001
|
if (sameFormatErrorCount >= MAX_REPEATED_FORMAT_ERRORS) {
|
|
72607
73002
|
const errorDesc = isWrapped ? "wrapped tool format" : unrecognizedTool;
|
|
73003
|
+
this._recordErrorTelemetry("circuit_breaker", "Format error limit exceeded", { formatErrorCount: sameFormatErrorCount, errorCategory }, currentIteration);
|
|
72608
73004
|
console.error(`[ERROR] Format error category '${errorCategory}' repeated ${sameFormatErrorCount} times. Breaking loop early to prevent infinite iteration.`);
|
|
72609
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.`;
|
|
72610
73006
|
break;
|
|
@@ -72618,6 +73014,10 @@ Note: <attempt_complete></attempt_complete> reuses your PREVIOUS assistant messa
|
|
|
72618
73014
|
sameFormatErrorCount = 0;
|
|
72619
73015
|
}
|
|
72620
73016
|
}
|
|
73017
|
+
this._recordIterationTelemetry("end", currentIteration, {
|
|
73018
|
+
"iteration.completed": completionAttempted,
|
|
73019
|
+
"iteration.message_count": currentMessages.length
|
|
73020
|
+
});
|
|
72621
73021
|
if (currentMessages.length > MAX_HISTORY_MESSAGES) {
|
|
72622
73022
|
const messagesBefore = currentMessages.length;
|
|
72623
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
|
|