@introspection-sdk/introspection-node 0.4.3 → 0.4.5
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/.turbo/turbo-build.log +1 -1
- package/dist/otel/anthropic.d.ts +14 -12
- package/dist/otel/anthropic.d.ts.map +1 -1
- package/dist/otel/anthropic.js +89 -47
- package/dist/otel/anthropic.js.map +1 -1
- package/dist/otel/gemini.d.ts +15 -7
- package/dist/otel/gemini.d.ts.map +1 -1
- package/dist/otel/gemini.js +88 -37
- package/dist/otel/gemini.js.map +1 -1
- package/dist/otel/index.d.ts +5 -0
- package/dist/otel/index.d.ts.map +1 -1
- package/dist/otel/index.js +8 -0
- package/dist/otel/index.js.map +1 -1
- package/dist/otel/init.d.ts +126 -0
- package/dist/otel/init.d.ts.map +1 -0
- package/dist/otel/init.js +259 -0
- package/dist/otel/init.js.map +1 -0
- package/dist/otel/integrations/anthropic.d.ts +10 -0
- package/dist/otel/integrations/anthropic.d.ts.map +1 -0
- package/dist/otel/integrations/anthropic.js +22 -0
- package/dist/otel/integrations/anthropic.js.map +1 -0
- package/dist/otel/integrations/base.d.ts +83 -0
- package/dist/otel/integrations/base.d.ts.map +1 -0
- package/dist/otel/integrations/base.js +23 -0
- package/dist/otel/integrations/base.js.map +1 -0
- package/dist/otel/integrations/claude-agent.d.ts +13 -0
- package/dist/otel/integrations/claude-agent.d.ts.map +1 -0
- package/dist/otel/integrations/claude-agent.js +27 -0
- package/dist/otel/integrations/claude-agent.js.map +1 -0
- package/dist/otel/integrations/gemini.d.ts +11 -0
- package/dist/otel/integrations/gemini.d.ts.map +1 -0
- package/dist/otel/integrations/gemini.js +21 -0
- package/dist/otel/integrations/gemini.js.map +1 -0
- package/dist/otel/integrations/index.d.ts +39 -0
- package/dist/otel/integrations/index.d.ts.map +1 -0
- package/dist/otel/integrations/index.js +131 -0
- package/dist/otel/integrations/index.js.map +1 -0
- package/dist/otel/integrations/langchain.d.ts +16 -0
- package/dist/otel/integrations/langchain.d.ts.map +1 -0
- package/dist/otel/integrations/langchain.js +41 -0
- package/dist/otel/integrations/langchain.js.map +1 -0
- package/dist/otel/integrations/mastra.d.ts +14 -0
- package/dist/otel/integrations/mastra.d.ts.map +1 -0
- package/dist/otel/integrations/mastra.js +27 -0
- package/dist/otel/integrations/mastra.js.map +1 -0
- package/dist/otel/integrations/openai-agents.d.ts +11 -0
- package/dist/otel/integrations/openai-agents.d.ts.map +1 -0
- package/dist/otel/integrations/openai-agents.js +25 -0
- package/dist/otel/integrations/openai-agents.js.map +1 -0
- package/dist/otel/integrations/pi.d.ts +12 -0
- package/dist/otel/integrations/pi.d.ts.map +1 -0
- package/dist/otel/integrations/pi.js +20 -0
- package/dist/otel/integrations/pi.js.map +1 -0
- package/dist/otel/integrations/vercel.d.ts +15 -0
- package/dist/otel/integrations/vercel.d.ts.map +1 -0
- package/dist/otel/integrations/vercel.js +20 -0
- package/dist/otel/integrations/vercel.js.map +1 -0
- package/dist/otel/register.d.ts +8 -0
- package/dist/otel/register.d.ts.map +1 -0
- package/dist/otel/register.js +48 -0
- package/dist/otel/register.js.map +1 -0
- package/dist/otel/setup.d.ts +29 -0
- package/dist/otel/setup.d.ts.map +1 -1
- package/dist/otel/setup.js +22 -3
- package/dist/otel/setup.js.map +1 -1
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +12 -4
- package/dist/utils.js.map +1 -1
- package/package.json +17 -5
- package/src/otel/anthropic.ts +128 -63
- package/src/otel/gemini.ts +139 -45
- package/src/otel/index.ts +41 -0
- package/src/otel/init.ts +411 -0
- package/src/otel/integrations/anthropic.ts +26 -0
- package/src/otel/integrations/base.ts +95 -0
- package/src/otel/integrations/claude-agent.ts +32 -0
- package/src/otel/integrations/gemini.ts +25 -0
- package/src/otel/integrations/index.ts +151 -0
- package/src/otel/integrations/langchain.ts +45 -0
- package/src/otel/integrations/mastra.ts +30 -0
- package/src/otel/integrations/openai-agents.ts +31 -0
- package/src/otel/integrations/pi.ts +24 -0
- package/src/otel/integrations/vercel.ts +24 -0
- package/src/otel/register.ts +50 -0
- package/src/otel/setup.ts +44 -3
- package/src/utils.ts +12 -5
- package/.turbo/turbo-check-types.log +0 -4
- package/.turbo/turbo-lint.log +0 -5
- package/dist/ai-sdk-integration.d.ts +0 -123
- package/dist/ai-sdk-integration.d.ts.map +0 -1
- package/dist/ai-sdk-integration.js +0 -475
- package/dist/anthropic.d.ts +0 -54
- package/dist/anthropic.d.ts.map +0 -1
- package/dist/anthropic.js +0 -375
- package/dist/claude-hooks.d.ts +0 -328
- package/dist/claude-hooks.d.ts.map +0 -1
- package/dist/claude-hooks.js +0 -571
- package/dist/claude-wrapper.d.ts +0 -93
- package/dist/claude-wrapper.d.ts.map +0 -1
- package/dist/claude-wrapper.js +0 -154
- package/dist/converters/ai-sdk.d.ts +0 -65
- package/dist/converters/ai-sdk.d.ts.map +0 -1
- package/dist/converters/ai-sdk.js +0 -261
- package/dist/converters/openclaw.d.ts +0 -16
- package/dist/converters/openclaw.d.ts.map +0 -1
- package/dist/converters/openclaw.js +0 -49
- package/dist/langchain-handler.d.ts +0 -103
- package/dist/langchain-handler.d.ts.map +0 -1
- package/dist/langchain-handler.js +0 -518
- package/dist/mastra-exporter.d.ts +0 -85
- package/dist/mastra-exporter.d.ts.map +0 -1
- package/dist/mastra-exporter.js +0 -471
- package/dist/span-processor.d.ts +0 -62
- package/dist/span-processor.d.ts.map +0 -1
- package/dist/span-processor.js +0 -313
- package/dist/tracing-processor.d.ts +0 -136
- package/dist/tracing-processor.d.ts.map +0 -1
- package/dist/tracing-processor.js +0 -368
- package/dist/types/genai.d.ts +0 -165
- package/dist/types/genai.d.ts.map +0 -1
- package/dist/types/genai.js +0 -82
|
@@ -1,475 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AI SDK TelemetryIntegration for Introspection.
|
|
3
|
-
*
|
|
4
|
-
* Implements the Vercel AI SDK's TelemetryIntegration interface to capture
|
|
5
|
-
* LLM interactions and export them as OpenTelemetry spans with gen_ai.*
|
|
6
|
-
* semantic convention attributes to the Introspection backend.
|
|
7
|
-
*
|
|
8
|
-
* Similar to IntrospectionTracingProcessor for OpenAI Agents SDK and
|
|
9
|
-
* IntrospectionClaudeHooks for Claude Agent SDK.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* import { IntrospectionAISDKIntegration } from "@introspection-sdk/introspection-node";
|
|
14
|
-
* import { generateText } from "ai";
|
|
15
|
-
* import { openai } from "@ai-sdk/openai";
|
|
16
|
-
*
|
|
17
|
-
* const introspection = new IntrospectionAISDKIntegration({
|
|
18
|
-
* token: "sk-intro-...",
|
|
19
|
-
* serviceName: "my-app",
|
|
20
|
-
* });
|
|
21
|
-
*
|
|
22
|
-
* const { text } = await generateText({
|
|
23
|
-
* model: openai("gpt-4o"),
|
|
24
|
-
* prompt: "Hello!",
|
|
25
|
-
* experimental_telemetry: {
|
|
26
|
-
* isEnabled: true,
|
|
27
|
-
* integrations: [introspection],
|
|
28
|
-
* },
|
|
29
|
-
* });
|
|
30
|
-
*
|
|
31
|
-
* await introspection.shutdown();
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
import { context as otelContext, trace as otelTrace, } from "@opentelemetry/api";
|
|
35
|
-
import { BasicTracerProvider, BatchSpanProcessor, SimpleSpanProcessor, } from "@opentelemetry/sdk-trace-base";
|
|
36
|
-
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
|
|
37
|
-
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
38
|
-
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
39
|
-
import { randomUUID } from "crypto";
|
|
40
|
-
import { convertMessagesToInputMessages, extractSystemInstructions, buildOutputMessages, convertToolsToToolDefinitions, } from "./converters/ai-sdk.js";
|
|
41
|
-
import { logger, withOtlpHttpsProxy } from "./utils.js";
|
|
42
|
-
import { VERSION } from "./version.js";
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
|
-
// Integration class
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
|
-
/**
|
|
47
|
-
* AI SDK {@link TelemetryIntegration} that captures LLM interactions and
|
|
48
|
-
* exports them as OpenTelemetry spans with `gen_ai.*` semantic convention
|
|
49
|
-
* attributes to the Introspection backend.
|
|
50
|
-
*
|
|
51
|
-
* Creates its own {@link BasicTracerProvider} — no external OTel setup required.
|
|
52
|
-
* Each generation (generateText/streamText call) produces:
|
|
53
|
-
* - A root span grouping the entire operation
|
|
54
|
-
* - Step spans (one per LLM call) with full gen_ai attributes
|
|
55
|
-
* - Tool call spans nested under their parent step
|
|
56
|
-
*/
|
|
57
|
-
export class IntrospectionAISDKIntegration {
|
|
58
|
-
_tracerProvider;
|
|
59
|
-
_tracer;
|
|
60
|
-
_generation = null;
|
|
61
|
-
constructor(options = {}) {
|
|
62
|
-
const advanced = options.advanced;
|
|
63
|
-
const serviceName = options.serviceName || process.env.INTROSPECTION_SERVICE_NAME;
|
|
64
|
-
const resource = serviceName
|
|
65
|
-
? resourceFromAttributes({ [ATTR_SERVICE_NAME]: serviceName })
|
|
66
|
-
: undefined;
|
|
67
|
-
// Production mode — requires a token
|
|
68
|
-
if (!advanced?.spanExporter) {
|
|
69
|
-
const token = options.token || process.env.INTROSPECTION_TOKEN;
|
|
70
|
-
if (!token) {
|
|
71
|
-
throw new Error("INTROSPECTION_TOKEN is required");
|
|
72
|
-
}
|
|
73
|
-
const baseUrl = options.baseUrl ||
|
|
74
|
-
process.env.INTROSPECTION_BASE_URL ||
|
|
75
|
-
"https://otel.introspection.dev";
|
|
76
|
-
const headers = {
|
|
77
|
-
"User-Agent": `introspection-sdk/${VERSION}`,
|
|
78
|
-
Authorization: `Bearer ${token}`,
|
|
79
|
-
...options.additionalHeaders,
|
|
80
|
-
};
|
|
81
|
-
const endpoint = baseUrl.endsWith("/v1/traces")
|
|
82
|
-
? baseUrl
|
|
83
|
-
: `${baseUrl.replace(/\/$/, "")}/v1/traces`;
|
|
84
|
-
logger.info(`IntrospectionAISDKIntegration initialized: endpoint=${endpoint}`);
|
|
85
|
-
const spanExporter = new OTLPTraceExporter(withOtlpHttpsProxy({ url: endpoint, headers }));
|
|
86
|
-
// Use SimpleSpanProcessor for sequential export (dev/staging tokens)
|
|
87
|
-
const effectiveBatchSize = advanced?.maxExportBatchSize ??
|
|
88
|
-
(token.startsWith("intro_dev") || token.startsWith("intro_staging")
|
|
89
|
-
? 1
|
|
90
|
-
: undefined);
|
|
91
|
-
const useSimple = advanced?.useSimpleSpanProcessor || effectiveBatchSize === 1;
|
|
92
|
-
const scheduledDelayMillis = advanced?.scheduledDelayMillis ?? 1000;
|
|
93
|
-
const spanProcessor = useSimple
|
|
94
|
-
? new SimpleSpanProcessor(spanExporter)
|
|
95
|
-
: new BatchSpanProcessor(spanExporter, {
|
|
96
|
-
scheduledDelayMillis,
|
|
97
|
-
...(effectiveBatchSize
|
|
98
|
-
? { maxExportBatchSize: effectiveBatchSize }
|
|
99
|
-
: {}),
|
|
100
|
-
});
|
|
101
|
-
this._tracerProvider = new BasicTracerProvider({
|
|
102
|
-
resource,
|
|
103
|
-
idGenerator: advanced?.idGenerator,
|
|
104
|
-
spanProcessors: [spanProcessor],
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
// Testing mode — use provided exporter
|
|
109
|
-
logger.info(`IntrospectionAISDKIntegration initialized in test mode with custom exporter`);
|
|
110
|
-
const spanProcessor = advanced.useSimpleSpanProcessor
|
|
111
|
-
? new SimpleSpanProcessor(advanced.spanExporter)
|
|
112
|
-
: new BatchSpanProcessor(advanced.spanExporter, {
|
|
113
|
-
scheduledDelayMillis: 100,
|
|
114
|
-
});
|
|
115
|
-
this._tracerProvider = new BasicTracerProvider({
|
|
116
|
-
resource,
|
|
117
|
-
idGenerator: advanced.idGenerator,
|
|
118
|
-
spanProcessors: [spanProcessor],
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
this._tracer = this._tracerProvider.getTracer("ai-sdk", VERSION);
|
|
122
|
-
}
|
|
123
|
-
// -------------------------------------------------------------------------
|
|
124
|
-
// TelemetryIntegration lifecycle methods
|
|
125
|
-
//
|
|
126
|
-
// Defined as arrow functions to preserve `this` binding when the AI SDK
|
|
127
|
-
// calls them as plain function references.
|
|
128
|
-
//
|
|
129
|
-
// Event parameters use `unknown` for TypeScript compatibility with the
|
|
130
|
-
// AI SDK's TelemetryIntegration interface (avoids index signature mismatch).
|
|
131
|
-
// -------------------------------------------------------------------------
|
|
132
|
-
/**
|
|
133
|
-
* Called when a generation operation begins (before any LLM calls).
|
|
134
|
-
* Creates a root span to group all steps in this generation.
|
|
135
|
-
*/
|
|
136
|
-
onStart = (event) => {
|
|
137
|
-
try {
|
|
138
|
-
const e = event;
|
|
139
|
-
// End any lingering previous generation (safety net)
|
|
140
|
-
if (this._generation) {
|
|
141
|
-
this._endGeneration();
|
|
142
|
-
}
|
|
143
|
-
const model = e.model;
|
|
144
|
-
const functionId = e.functionId;
|
|
145
|
-
const metadata = e.metadata;
|
|
146
|
-
const name = functionId || "ai-sdk-generation";
|
|
147
|
-
// Conversation ID: metadata > auto-generate
|
|
148
|
-
const metadataConvId = metadata?.["gen_ai.conversation.id"];
|
|
149
|
-
const conversationId = metadataConvId || `intro_conv_${randomUUID().replace(/-/g, "")}`;
|
|
150
|
-
const rootSpan = this._tracer.startSpan(name);
|
|
151
|
-
rootSpan.setAttribute("gen_ai.conversation.id", conversationId);
|
|
152
|
-
if (functionId) {
|
|
153
|
-
rootSpan.setAttribute("gen_ai.agent.name", functionId);
|
|
154
|
-
}
|
|
155
|
-
if (model?.provider) {
|
|
156
|
-
rootSpan.setAttribute("gen_ai.system", model.provider);
|
|
157
|
-
}
|
|
158
|
-
// Pass through all telemetry metadata as span attributes
|
|
159
|
-
if (metadata) {
|
|
160
|
-
for (const [key, value] of Object.entries(metadata)) {
|
|
161
|
-
if (value !== undefined && value !== null) {
|
|
162
|
-
rootSpan.setAttribute(`ai.telemetry.metadata.${key}`, typeof value === "string" ? value : JSON.stringify(value));
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
this._generation = {
|
|
167
|
-
rootSpan,
|
|
168
|
-
conversationId,
|
|
169
|
-
system: e.system,
|
|
170
|
-
metadata,
|
|
171
|
-
stepSpans: new Map(),
|
|
172
|
-
stepMessages: new Map(),
|
|
173
|
-
toolCallSpans: new Map(),
|
|
174
|
-
};
|
|
175
|
-
logger.debug(`Generation started: ${name} (${conversationId})`);
|
|
176
|
-
}
|
|
177
|
-
catch (error) {
|
|
178
|
-
logger.error(`onStart error: ${error instanceof Error ? error.message : String(error)}`);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
/**
|
|
182
|
-
* Called when a step (individual LLM call) begins.
|
|
183
|
-
* Creates a child span under the root span and captures input messages.
|
|
184
|
-
*/
|
|
185
|
-
onStepStart = (event) => {
|
|
186
|
-
try {
|
|
187
|
-
const e = event;
|
|
188
|
-
const gen = this._generation;
|
|
189
|
-
if (!gen)
|
|
190
|
-
return;
|
|
191
|
-
const stepNumber = e.stepNumber ?? 0;
|
|
192
|
-
const model = e.model;
|
|
193
|
-
const messages = e.messages || [];
|
|
194
|
-
const system = e.system ?? gen.system;
|
|
195
|
-
const tools = e.tools;
|
|
196
|
-
const functionId = e.functionId;
|
|
197
|
-
// Create step span as child of root
|
|
198
|
-
const parentCtx = otelTrace.setSpan(otelContext.active(), gen.rootSpan);
|
|
199
|
-
const spanName = model?.modelId
|
|
200
|
-
? `chat ${model.modelId}`
|
|
201
|
-
: `step-${stepNumber}`;
|
|
202
|
-
const stepSpan = this._tracer.startSpan(spanName, {}, parentCtx);
|
|
203
|
-
gen.stepSpans.set(stepNumber, stepSpan);
|
|
204
|
-
// Capture input messages for use in onStepFinish
|
|
205
|
-
const inputMessages = convertMessagesToInputMessages(messages);
|
|
206
|
-
gen.stepMessages.set(stepNumber, inputMessages);
|
|
207
|
-
// Set input-side attributes immediately
|
|
208
|
-
stepSpan.setAttribute("gen_ai.operation.name", "chat");
|
|
209
|
-
stepSpan.setAttribute("gen_ai.conversation.id", gen.conversationId);
|
|
210
|
-
if (model?.provider) {
|
|
211
|
-
stepSpan.setAttribute("gen_ai.system", model.provider);
|
|
212
|
-
}
|
|
213
|
-
if (model?.modelId) {
|
|
214
|
-
stepSpan.setAttribute("gen_ai.request.model", model.modelId);
|
|
215
|
-
}
|
|
216
|
-
// System instructions
|
|
217
|
-
const sysInstructions = extractSystemInstructions(system, messages);
|
|
218
|
-
if (sysInstructions) {
|
|
219
|
-
stepSpan.setAttribute("gen_ai.system_instructions", JSON.stringify(sysInstructions));
|
|
220
|
-
}
|
|
221
|
-
// Tool definitions
|
|
222
|
-
const toolDefs = convertToolsToToolDefinitions(tools);
|
|
223
|
-
if (toolDefs) {
|
|
224
|
-
stepSpan.setAttribute("gen_ai.tool.definitions", JSON.stringify(toolDefs));
|
|
225
|
-
}
|
|
226
|
-
// Agent name from functionId
|
|
227
|
-
if (functionId) {
|
|
228
|
-
stepSpan.setAttribute("gen_ai.agent.name", functionId);
|
|
229
|
-
}
|
|
230
|
-
// Pass through telemetry metadata to step spans
|
|
231
|
-
if (gen.metadata) {
|
|
232
|
-
for (const [key, value] of Object.entries(gen.metadata)) {
|
|
233
|
-
if (value !== undefined && value !== null) {
|
|
234
|
-
stepSpan.setAttribute(`ai.telemetry.metadata.${key}`, typeof value === "string" ? value : JSON.stringify(value));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
logger.debug(`Step ${stepNumber} started: ${spanName}`);
|
|
239
|
-
}
|
|
240
|
-
catch (error) {
|
|
241
|
-
logger.error(`onStepStart error: ${error instanceof Error ? error.message : String(error)}`);
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
/**
|
|
245
|
-
* Called when a tool execution begins.
|
|
246
|
-
* Creates a child span under the current step span.
|
|
247
|
-
*/
|
|
248
|
-
onToolCallStart = (event) => {
|
|
249
|
-
try {
|
|
250
|
-
const e = event;
|
|
251
|
-
const gen = this._generation;
|
|
252
|
-
if (!gen)
|
|
253
|
-
return;
|
|
254
|
-
const toolCall = e.toolCall;
|
|
255
|
-
if (!toolCall)
|
|
256
|
-
return;
|
|
257
|
-
const stepNumber = e.stepNumber ?? 0;
|
|
258
|
-
const parentSpan = gen.stepSpans.get(stepNumber) || gen.rootSpan;
|
|
259
|
-
const parentCtx = otelTrace.setSpan(otelContext.active(), parentSpan);
|
|
260
|
-
const toolName = toolCall.toolName || "unknown-tool";
|
|
261
|
-
const toolSpan = this._tracer.startSpan(toolName, {}, parentCtx);
|
|
262
|
-
toolSpan.setAttribute("gen_ai.tool.name", toolName);
|
|
263
|
-
toolSpan.setAttribute("openinference.span.kind", "TOOL");
|
|
264
|
-
if (toolCall.input !== undefined) {
|
|
265
|
-
toolSpan.setAttribute("gen_ai.tool.input", typeof toolCall.input === "string"
|
|
266
|
-
? toolCall.input
|
|
267
|
-
: JSON.stringify(toolCall.input));
|
|
268
|
-
}
|
|
269
|
-
// Propagate conversation ID
|
|
270
|
-
toolSpan.setAttribute("gen_ai.conversation.id", gen.conversationId);
|
|
271
|
-
const toolCallId = toolCall.toolCallId || `tool-${stepNumber}-${toolName}`;
|
|
272
|
-
gen.toolCallSpans.set(toolCallId, toolSpan);
|
|
273
|
-
logger.debug(`Tool call started: ${toolName} (${toolCallId})`);
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
logger.error(`onToolCallStart error: ${error instanceof Error ? error.message : String(error)}`);
|
|
277
|
-
}
|
|
278
|
-
};
|
|
279
|
-
/**
|
|
280
|
-
* Called when a tool execution completes.
|
|
281
|
-
* Sets output/error attributes and ends the tool span.
|
|
282
|
-
*/
|
|
283
|
-
onToolCallFinish = (event) => {
|
|
284
|
-
try {
|
|
285
|
-
const e = event;
|
|
286
|
-
const gen = this._generation;
|
|
287
|
-
if (!gen)
|
|
288
|
-
return;
|
|
289
|
-
const toolCall = e.toolCall;
|
|
290
|
-
if (!toolCall)
|
|
291
|
-
return;
|
|
292
|
-
const stepNumber = e.stepNumber ?? 0;
|
|
293
|
-
const toolCallId = toolCall.toolCallId ||
|
|
294
|
-
`tool-${stepNumber}-${toolCall.toolName || "unknown"}`;
|
|
295
|
-
const toolSpan = gen.toolCallSpans.get(toolCallId);
|
|
296
|
-
if (!toolSpan)
|
|
297
|
-
return;
|
|
298
|
-
gen.toolCallSpans.delete(toolCallId);
|
|
299
|
-
const success = e.success;
|
|
300
|
-
if (success && e.output !== undefined) {
|
|
301
|
-
toolSpan.setAttribute("gen_ai.tool.output", typeof e.output === "string" ? e.output : JSON.stringify(e.output));
|
|
302
|
-
}
|
|
303
|
-
else if (!success && e.error !== undefined) {
|
|
304
|
-
toolSpan.setAttribute("gen_ai.tool.error", typeof e.error === "string"
|
|
305
|
-
? e.error
|
|
306
|
-
: e.error instanceof Error
|
|
307
|
-
? e.error.message
|
|
308
|
-
: JSON.stringify(e.error));
|
|
309
|
-
}
|
|
310
|
-
if (typeof e.durationMs === "number") {
|
|
311
|
-
toolSpan.setAttribute("gen_ai.tool.duration_ms", e.durationMs);
|
|
312
|
-
}
|
|
313
|
-
toolSpan.end();
|
|
314
|
-
logger.debug(`Tool call finished: ${toolCall.toolName} (${toolCallId})`);
|
|
315
|
-
}
|
|
316
|
-
catch (error) {
|
|
317
|
-
logger.error(`onToolCallFinish error: ${error instanceof Error ? error.message : String(error)}`);
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
/**
|
|
321
|
-
* Called when a step (LLM call) completes.
|
|
322
|
-
* Sets gen_ai attributes (input/output messages, usage, model) and ends
|
|
323
|
-
* the step span.
|
|
324
|
-
*/
|
|
325
|
-
onStepFinish = (event) => {
|
|
326
|
-
try {
|
|
327
|
-
const e = event;
|
|
328
|
-
const gen = this._generation;
|
|
329
|
-
if (!gen)
|
|
330
|
-
return;
|
|
331
|
-
const stepNumber = e.stepNumber ?? 0;
|
|
332
|
-
const stepSpan = gen.stepSpans.get(stepNumber);
|
|
333
|
-
if (!stepSpan) {
|
|
334
|
-
logger.debug(`No step span found for step ${stepNumber}`);
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
gen.stepSpans.delete(stepNumber);
|
|
338
|
-
// Input messages (captured in onStepStart)
|
|
339
|
-
const inputMessages = gen.stepMessages.get(stepNumber);
|
|
340
|
-
gen.stepMessages.delete(stepNumber);
|
|
341
|
-
if (inputMessages && inputMessages.length > 0) {
|
|
342
|
-
stepSpan.setAttribute("gen_ai.input.messages", JSON.stringify(inputMessages));
|
|
343
|
-
}
|
|
344
|
-
// Output messages
|
|
345
|
-
const outputMessages = buildOutputMessages({
|
|
346
|
-
text: e.text,
|
|
347
|
-
reasoningText: e.reasoningText,
|
|
348
|
-
reasoning: e.reasoning,
|
|
349
|
-
toolCalls: e.toolCalls,
|
|
350
|
-
finishReason: e.finishReason,
|
|
351
|
-
});
|
|
352
|
-
if (outputMessages.length > 0) {
|
|
353
|
-
stepSpan.setAttribute("gen_ai.output.messages", JSON.stringify(outputMessages));
|
|
354
|
-
}
|
|
355
|
-
// Token usage
|
|
356
|
-
const usage = e.usage;
|
|
357
|
-
if (usage) {
|
|
358
|
-
if (usage.inputTokens !== undefined) {
|
|
359
|
-
stepSpan.setAttribute("gen_ai.usage.input_tokens", usage.inputTokens);
|
|
360
|
-
}
|
|
361
|
-
if (usage.outputTokens !== undefined) {
|
|
362
|
-
stepSpan.setAttribute("gen_ai.usage.output_tokens", usage.outputTokens);
|
|
363
|
-
}
|
|
364
|
-
if (usage.inputTokenDetails?.cacheReadTokens !== undefined) {
|
|
365
|
-
stepSpan.setAttribute("gen_ai.usage.cache_read.input_tokens", usage.inputTokenDetails.cacheReadTokens);
|
|
366
|
-
}
|
|
367
|
-
if (usage.inputTokenDetails?.cacheWriteTokens !== undefined) {
|
|
368
|
-
stepSpan.setAttribute("gen_ai.usage.cache_creation.input_tokens", usage.inputTokenDetails.cacheWriteTokens);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
// Response metadata
|
|
372
|
-
const response = e.response;
|
|
373
|
-
if (response?.id) {
|
|
374
|
-
stepSpan.setAttribute("gen_ai.response.id", response.id);
|
|
375
|
-
}
|
|
376
|
-
if (response?.modelId) {
|
|
377
|
-
stepSpan.setAttribute("gen_ai.response.model", response.modelId);
|
|
378
|
-
}
|
|
379
|
-
// Finish reason
|
|
380
|
-
const finishReason = e.finishReason;
|
|
381
|
-
if (finishReason) {
|
|
382
|
-
stepSpan.setAttribute("gen_ai.response.finish_reasons", [finishReason]);
|
|
383
|
-
}
|
|
384
|
-
// Model info (reinforces what was set in onStepStart)
|
|
385
|
-
const model = e.model;
|
|
386
|
-
if (model?.provider) {
|
|
387
|
-
stepSpan.setAttribute("gen_ai.system", model.provider);
|
|
388
|
-
}
|
|
389
|
-
if (model?.modelId) {
|
|
390
|
-
stepSpan.setAttribute("gen_ai.request.model", model.modelId);
|
|
391
|
-
}
|
|
392
|
-
stepSpan.setAttribute("openinference.span.kind", "LLM");
|
|
393
|
-
stepSpan.end();
|
|
394
|
-
logger.debug(`Step ${stepNumber} finished`);
|
|
395
|
-
}
|
|
396
|
-
catch (error) {
|
|
397
|
-
logger.error(`onStepFinish error: ${error instanceof Error ? error.message : String(error)}`);
|
|
398
|
-
}
|
|
399
|
-
};
|
|
400
|
-
/**
|
|
401
|
-
* Called when the entire generation completes (all steps finished).
|
|
402
|
-
* Sets total usage on the root span and ends it.
|
|
403
|
-
*/
|
|
404
|
-
onFinish = (event) => {
|
|
405
|
-
try {
|
|
406
|
-
const e = event;
|
|
407
|
-
const gen = this._generation;
|
|
408
|
-
if (!gen)
|
|
409
|
-
return;
|
|
410
|
-
// End any orphaned tool call spans
|
|
411
|
-
for (const [id, span] of gen.toolCallSpans) {
|
|
412
|
-
span.end();
|
|
413
|
-
logger.debug(`Ending orphaned tool call span: ${id}`);
|
|
414
|
-
}
|
|
415
|
-
gen.toolCallSpans.clear();
|
|
416
|
-
// End any orphaned step spans
|
|
417
|
-
for (const [stepNumber, span] of gen.stepSpans) {
|
|
418
|
-
span.end();
|
|
419
|
-
logger.debug(`Ending orphaned step span: ${stepNumber}`);
|
|
420
|
-
}
|
|
421
|
-
gen.stepSpans.clear();
|
|
422
|
-
// Total usage on root span
|
|
423
|
-
const totalUsage = e.totalUsage;
|
|
424
|
-
if (totalUsage) {
|
|
425
|
-
if (totalUsage.inputTokens !== undefined) {
|
|
426
|
-
gen.rootSpan.setAttribute("gen_ai.usage.input_tokens", totalUsage.inputTokens);
|
|
427
|
-
}
|
|
428
|
-
if (totalUsage.outputTokens !== undefined) {
|
|
429
|
-
gen.rootSpan.setAttribute("gen_ai.usage.output_tokens", totalUsage.outputTokens);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
gen.rootSpan.end();
|
|
433
|
-
this._generation = null;
|
|
434
|
-
logger.debug("Generation finished");
|
|
435
|
-
}
|
|
436
|
-
catch (error) {
|
|
437
|
-
logger.error(`onFinish error: ${error instanceof Error ? error.message : String(error)}`);
|
|
438
|
-
}
|
|
439
|
-
};
|
|
440
|
-
// -------------------------------------------------------------------------
|
|
441
|
-
// Lifecycle methods
|
|
442
|
-
// -------------------------------------------------------------------------
|
|
443
|
-
/**
|
|
444
|
-
* Shut down the tracer provider, flushing all pending spans.
|
|
445
|
-
*
|
|
446
|
-
* @returns A promise that resolves once shutdown is complete.
|
|
447
|
-
*/
|
|
448
|
-
async shutdown() {
|
|
449
|
-
this._endGeneration();
|
|
450
|
-
await this._tracerProvider.shutdown();
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
|
-
* Force-flush any buffered spans to the Introspection backend.
|
|
454
|
-
*
|
|
455
|
-
* @returns A promise that resolves once the flush completes.
|
|
456
|
-
*/
|
|
457
|
-
async forceFlush() {
|
|
458
|
-
await this._tracerProvider.forceFlush();
|
|
459
|
-
}
|
|
460
|
-
// -------------------------------------------------------------------------
|
|
461
|
-
// Internal helpers
|
|
462
|
-
// -------------------------------------------------------------------------
|
|
463
|
-
/** Cleanly end any active generation, closing all open spans. */
|
|
464
|
-
_endGeneration() {
|
|
465
|
-
const gen = this._generation;
|
|
466
|
-
if (!gen)
|
|
467
|
-
return;
|
|
468
|
-
for (const span of gen.toolCallSpans.values())
|
|
469
|
-
span.end();
|
|
470
|
-
for (const span of gen.stepSpans.values())
|
|
471
|
-
span.end();
|
|
472
|
-
gen.rootSpan.end();
|
|
473
|
-
this._generation = null;
|
|
474
|
-
}
|
|
475
|
-
}
|
package/dist/anthropic.d.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lightweight Anthropic instrumentor for Introspection SDK.
|
|
3
|
-
*
|
|
4
|
-
* Captures the full Anthropic response including thinking blocks (extended
|
|
5
|
-
* thinking) with signatures, which third-party instrumentors drop.
|
|
6
|
-
*
|
|
7
|
-
* Supports both non-streaming (`messages.create`) and streaming
|
|
8
|
-
* (`messages.create({ stream: true })`) calls.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* import { AnthropicInstrumentor } from "@introspection-sdk/introspection-node";
|
|
13
|
-
*
|
|
14
|
-
* const instrumentor = new AnthropicInstrumentor();
|
|
15
|
-
* instrumentor.instrument({ tracerProvider: provider });
|
|
16
|
-
* // All client.messages.create calls are now traced
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
import type { Tracer } from "@opentelemetry/api";
|
|
20
|
-
import type { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
|
|
21
|
-
/** Sentinel value for redacted thinking blocks — content was encrypted by safety systems. */
|
|
22
|
-
export declare const REDACTED_THINKING_CONTENT = "[redacted]";
|
|
23
|
-
/**
|
|
24
|
-
* Traced wrapper around `client.messages.create(kwargs)`.
|
|
25
|
-
* Creates a gen_ai span with full Anthropic response including thinking blocks.
|
|
26
|
-
*/
|
|
27
|
-
export declare function tracedMessagesCreate(tracer: Tracer, client: {
|
|
28
|
-
messages: {
|
|
29
|
-
create: (...args: unknown[]) => Promise<unknown>;
|
|
30
|
-
};
|
|
31
|
-
}, kwargs: Record<string, unknown>): Promise<unknown>;
|
|
32
|
-
/**
|
|
33
|
-
* Auto-instrumentor that patches `Anthropic.messages.create` to add tracing.
|
|
34
|
-
*
|
|
35
|
-
* Captures all content blocks including thinking (extended thinking) with
|
|
36
|
-
* signatures. Supports both non-streaming and streaming calls.
|
|
37
|
-
*/
|
|
38
|
-
/**
|
|
39
|
-
* Auto-instrumentor that wraps an Anthropic client instance to add tracing.
|
|
40
|
-
*
|
|
41
|
-
* Captures all content blocks including thinking (extended thinking) with
|
|
42
|
-
* signatures. Supports both non-streaming and streaming calls.
|
|
43
|
-
*/
|
|
44
|
-
export declare class AnthropicInstrumentor {
|
|
45
|
-
private tracer;
|
|
46
|
-
private patchedClients;
|
|
47
|
-
instrument(opts: {
|
|
48
|
-
tracerProvider?: BasicTracerProvider;
|
|
49
|
-
/** The Anthropic client instance to instrument. */
|
|
50
|
-
client: any;
|
|
51
|
-
}): void;
|
|
52
|
-
uninstrument(): void;
|
|
53
|
-
}
|
|
54
|
-
//# sourceMappingURL=anthropic.d.ts.map
|
package/dist/anthropic.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../src/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAUH,OAAO,KAAK,EAAE,MAAM,EAAQ,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAMzE,6FAA6F;AAC7F,eAAO,MAAM,yBAAyB,eAAe,CAAC;AAgTtD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE;IAAE,QAAQ,EAAE;QAAE,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAA;CAAE,EAC1E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAED;;;;;GAKG;AACH;;;;;GAKG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAuB;IAErC,OAAO,CAAC,cAAc,CAAmD;IAEzE,UAAU,CAAC,IAAI,EAAE;QACf,cAAc,CAAC,EAAE,mBAAmB,CAAC;QACrC,mDAAmD;QAEnD,MAAM,EAAE,GAAG,CAAC;KACb,GAAG,IAAI;IAmER,YAAY,IAAI,IAAI;CAOrB"}
|