@probelabs/probe-chat 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/appTracer.js +198 -0
- package/package.json +1 -1
package/appTracer.js
CHANGED
|
@@ -895,6 +895,204 @@ class AppTracer {
|
|
|
895
895
|
return span;
|
|
896
896
|
}
|
|
897
897
|
|
|
898
|
+
/**
|
|
899
|
+
* Get the current iteration span for a session
|
|
900
|
+
* @private
|
|
901
|
+
*/
|
|
902
|
+
_getCurrentIterationSpan(sessionId) {
|
|
903
|
+
// Try to find the most recent iteration span
|
|
904
|
+
for (let i = 100; i >= 0; i--) {
|
|
905
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${i}`);
|
|
906
|
+
if (span) return span;
|
|
907
|
+
}
|
|
908
|
+
// Fall back to session span
|
|
909
|
+
return this.sessionSpans.get(sessionId);
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
/**
|
|
913
|
+
* Record AI thinking/reasoning content
|
|
914
|
+
* @param {string} sessionId - Session ID
|
|
915
|
+
* @param {number} iterationNumber - Iteration number
|
|
916
|
+
* @param {string} thinkingContent - The thinking content from AI response
|
|
917
|
+
*/
|
|
918
|
+
recordThinkingContent(sessionId, iterationNumber, thinkingContent) {
|
|
919
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${iterationNumber}`) || this._getCurrentIterationSpan(sessionId);
|
|
920
|
+
if (!span || !thinkingContent) return;
|
|
921
|
+
|
|
922
|
+
span.addEvent('ai.thinking', {
|
|
923
|
+
'app.ai.thinking.content': thinkingContent.substring(0, 20000),
|
|
924
|
+
'app.ai.thinking.length': thinkingContent.length,
|
|
925
|
+
'app.ai.thinking.hash': this._hashString(thinkingContent),
|
|
926
|
+
'app.iteration': iterationNumber,
|
|
927
|
+
'app.timestamp': Date.now()
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Record tool execution result
|
|
933
|
+
* @param {string} sessionId - Session ID
|
|
934
|
+
* @param {number} iterationNumber - Iteration number
|
|
935
|
+
* @param {string} toolName - Tool name
|
|
936
|
+
* @param {string|Object} result - Tool result
|
|
937
|
+
* @param {boolean} success - Whether succeeded
|
|
938
|
+
* @param {number} durationMs - Execution duration
|
|
939
|
+
*/
|
|
940
|
+
recordToolResult(sessionId, iterationNumber, toolName, result, success, durationMs) {
|
|
941
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${iterationNumber}`) || this._getCurrentIterationSpan(sessionId);
|
|
942
|
+
if (!span) return;
|
|
943
|
+
|
|
944
|
+
const resultStr = typeof result === 'string' ? result : JSON.stringify(result || '');
|
|
945
|
+
span.addEvent('tool.result', {
|
|
946
|
+
'app.tool.name': toolName,
|
|
947
|
+
'app.tool.result': resultStr.substring(0, 20000),
|
|
948
|
+
'app.tool.result.length': resultStr.length,
|
|
949
|
+
'app.tool.result.hash': this._hashString(resultStr),
|
|
950
|
+
'app.tool.success': success,
|
|
951
|
+
'app.tool.duration_ms': durationMs,
|
|
952
|
+
'app.iteration': iterationNumber,
|
|
953
|
+
'app.timestamp': Date.now()
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Record a conversation turn (assistant response or tool result)
|
|
959
|
+
* @param {string} sessionId - Session ID
|
|
960
|
+
* @param {number} iterationNumber - Iteration number
|
|
961
|
+
* @param {string} role - The role (assistant, tool_result)
|
|
962
|
+
* @param {string} content - The turn content
|
|
963
|
+
* @param {Object} metadata - Additional metadata
|
|
964
|
+
*/
|
|
965
|
+
recordConversationTurn(sessionId, iterationNumber, role, content, metadata = {}) {
|
|
966
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${iterationNumber}`) || this._getCurrentIterationSpan(sessionId);
|
|
967
|
+
if (!span) return;
|
|
968
|
+
|
|
969
|
+
span.addEvent(`conversation.${role}`, {
|
|
970
|
+
'app.conversation.role': role,
|
|
971
|
+
'app.conversation.content': content.substring(0, 20000),
|
|
972
|
+
'app.conversation.length': content.length,
|
|
973
|
+
'app.conversation.hash': this._hashString(content),
|
|
974
|
+
'app.iteration': iterationNumber,
|
|
975
|
+
'app.timestamp': Date.now(),
|
|
976
|
+
...Object.fromEntries(
|
|
977
|
+
Object.entries(metadata).map(([k, v]) => [`app.${k}`, v])
|
|
978
|
+
)
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* Record AI tool call decision
|
|
984
|
+
* @param {string} sessionId - Session ID
|
|
985
|
+
* @param {number} iterationNumber - Iteration number
|
|
986
|
+
* @param {string} toolName - Tool name AI decided to call
|
|
987
|
+
* @param {Object} params - Tool parameters
|
|
988
|
+
*/
|
|
989
|
+
recordAIToolDecision(sessionId, iterationNumber, toolName, params) {
|
|
990
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${iterationNumber}`) || this._getCurrentIterationSpan(sessionId);
|
|
991
|
+
if (!span) return;
|
|
992
|
+
|
|
993
|
+
span.addEvent('ai.tool_decision', {
|
|
994
|
+
'app.ai.tool_decision.name': toolName,
|
|
995
|
+
'app.ai.tool_decision.params': JSON.stringify(params || {}).substring(0, 5000),
|
|
996
|
+
'app.ai.tool_decision.params_hash': this._hashString(JSON.stringify(params || {})),
|
|
997
|
+
'app.iteration': iterationNumber,
|
|
998
|
+
'app.timestamp': Date.now()
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* Record MCP tool execution start
|
|
1004
|
+
* @param {string} sessionId - Session ID
|
|
1005
|
+
* @param {number} iterationNumber - Iteration number
|
|
1006
|
+
* @param {string} toolName - MCP tool name
|
|
1007
|
+
* @param {string} serverName - MCP server name
|
|
1008
|
+
* @param {Object} params - Tool parameters
|
|
1009
|
+
*/
|
|
1010
|
+
recordMcpToolStart(sessionId, iterationNumber, toolName, serverName, params) {
|
|
1011
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${iterationNumber}`) || this._getCurrentIterationSpan(sessionId);
|
|
1012
|
+
if (!span) return;
|
|
1013
|
+
|
|
1014
|
+
span.addEvent('mcp.tool.start', {
|
|
1015
|
+
'app.mcp.tool.name': toolName,
|
|
1016
|
+
'app.mcp.tool.server': serverName || 'unknown',
|
|
1017
|
+
'app.mcp.tool.params': JSON.stringify(params || {}).substring(0, 2000),
|
|
1018
|
+
'app.iteration': iterationNumber,
|
|
1019
|
+
'app.timestamp': Date.now()
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
/**
|
|
1024
|
+
* Record MCP tool execution end
|
|
1025
|
+
* @param {string} sessionId - Session ID
|
|
1026
|
+
* @param {number} iterationNumber - Iteration number
|
|
1027
|
+
* @param {string} toolName - MCP tool name
|
|
1028
|
+
* @param {string} serverName - MCP server name
|
|
1029
|
+
* @param {string|Object} result - Tool result
|
|
1030
|
+
* @param {boolean} success - Whether succeeded
|
|
1031
|
+
* @param {number} durationMs - Execution duration
|
|
1032
|
+
* @param {string} errorMessage - Error message if failed
|
|
1033
|
+
*/
|
|
1034
|
+
recordMcpToolEnd(sessionId, iterationNumber, toolName, serverName, result, success, durationMs, errorMessage = null) {
|
|
1035
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${iterationNumber}`) || this._getCurrentIterationSpan(sessionId);
|
|
1036
|
+
if (!span) return;
|
|
1037
|
+
|
|
1038
|
+
const resultStr = typeof result === 'string' ? result : JSON.stringify(result || '');
|
|
1039
|
+
span.addEvent('mcp.tool.end', {
|
|
1040
|
+
'app.mcp.tool.name': toolName,
|
|
1041
|
+
'app.mcp.tool.server': serverName || 'unknown',
|
|
1042
|
+
'app.mcp.tool.result': resultStr.substring(0, 10000),
|
|
1043
|
+
'app.mcp.tool.result.length': resultStr.length,
|
|
1044
|
+
'app.mcp.tool.duration_ms': durationMs,
|
|
1045
|
+
'app.mcp.tool.success': success,
|
|
1046
|
+
'app.mcp.tool.error': errorMessage,
|
|
1047
|
+
'app.iteration': iterationNumber,
|
|
1048
|
+
'app.timestamp': Date.now()
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
/**
|
|
1053
|
+
* Record error classification event
|
|
1054
|
+
* @param {string} sessionId - Session ID
|
|
1055
|
+
* @param {number} iterationNumber - Iteration number
|
|
1056
|
+
* @param {string} errorType - Error type (wrapped_tool, unrecognized_tool, no_tool_call, circuit_breaker, etc.)
|
|
1057
|
+
* @param {Object} errorDetails - Error details
|
|
1058
|
+
*/
|
|
1059
|
+
recordErrorClassification(sessionId, iterationNumber, errorType, errorDetails = {}) {
|
|
1060
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${iterationNumber}`) || this._getCurrentIterationSpan(sessionId);
|
|
1061
|
+
if (!span) return;
|
|
1062
|
+
|
|
1063
|
+
span.addEvent(`error.${errorType}`, {
|
|
1064
|
+
'app.error.type': errorType,
|
|
1065
|
+
'app.error.message': errorDetails.message?.substring(0, 1000) || '',
|
|
1066
|
+
'app.error.recoverable': errorDetails.recoverable ?? true,
|
|
1067
|
+
'app.error.context': JSON.stringify(errorDetails.context || {}).substring(0, 1000),
|
|
1068
|
+
'app.iteration': iterationNumber,
|
|
1069
|
+
'app.timestamp': Date.now()
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* Record per-turn token breakdown
|
|
1075
|
+
* @param {string} sessionId - Session ID
|
|
1076
|
+
* @param {number} iterationNumber - Iteration number
|
|
1077
|
+
* @param {Object} tokenData - Token metrics
|
|
1078
|
+
*/
|
|
1079
|
+
recordTokenTurn(sessionId, iterationNumber, tokenData = {}) {
|
|
1080
|
+
const span = this.activeSpans.get(`${sessionId}_iteration_${iterationNumber}`) || this._getCurrentIterationSpan(sessionId);
|
|
1081
|
+
if (!span) return;
|
|
1082
|
+
|
|
1083
|
+
span.addEvent('tokens.turn', {
|
|
1084
|
+
'app.iteration': iterationNumber,
|
|
1085
|
+
'app.tokens.input': tokenData.inputTokens || 0,
|
|
1086
|
+
'app.tokens.output': tokenData.outputTokens || 0,
|
|
1087
|
+
'app.tokens.total': (tokenData.inputTokens || 0) + (tokenData.outputTokens || 0),
|
|
1088
|
+
'app.tokens.cache_read': tokenData.cacheReadTokens || 0,
|
|
1089
|
+
'app.tokens.cache_write': tokenData.cacheWriteTokens || 0,
|
|
1090
|
+
'app.tokens.context_used': tokenData.contextTokens || 0,
|
|
1091
|
+
'app.tokens.context_remaining': tokenData.maxContextTokens ? (tokenData.maxContextTokens - (tokenData.contextTokens || 0)) : null,
|
|
1092
|
+
'app.timestamp': Date.now()
|
|
1093
|
+
});
|
|
1094
|
+
}
|
|
1095
|
+
|
|
898
1096
|
/**
|
|
899
1097
|
* Record a generic event (used by completionPrompt and other features)
|
|
900
1098
|
* This provides compatibility with SimpleAppTracer interface
|
package/package.json
CHANGED