@introspection-sdk/introspection-node 0.4.2 → 0.4.4
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/client.d.ts +42 -132
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +67 -366
- package/dist/client.js.map +1 -0
- package/dist/converters/claude.d.ts +4 -0
- package/dist/converters/claude.d.ts.map +1 -1
- package/dist/converters/claude.js +7 -0
- package/dist/converters/claude.js.map +1 -0
- package/dist/converters/gemini.d.ts +90 -0
- package/dist/converters/gemini.d.ts.map +1 -0
- package/dist/converters/gemini.js +171 -0
- package/dist/converters/gemini.js.map +1 -0
- package/dist/converters/index.d.ts +1 -1
- package/dist/converters/index.d.ts.map +1 -1
- package/dist/converters/index.js +2 -1
- package/dist/converters/index.js.map +1 -0
- package/dist/converters/openai.js +1 -0
- package/dist/converters/openai.js.map +1 -0
- package/dist/converters/openinference.js +1 -0
- package/dist/converters/openinference.js.map +1 -0
- package/dist/converters/vercel.d.ts.map +1 -1
- package/dist/converters/vercel.js +31 -3
- package/dist/converters/vercel.js.map +1 -0
- package/dist/http.d.ts +36 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +145 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +24 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -32
- package/dist/index.js.map +1 -0
- package/dist/{anthropic.d.ts → otel/anthropic.d.ts} +23 -13
- package/dist/otel/anthropic.d.ts.map +1 -0
- package/dist/{anthropic.js → otel/anthropic.js} +132 -40
- package/dist/otel/anthropic.js.map +1 -0
- package/dist/{claude-hooks.d.ts → otel/claude-hooks.d.ts} +19 -1
- package/dist/otel/claude-hooks.d.ts.map +1 -0
- package/dist/{claude-hooks.js → otel/claude-hooks.js} +94 -20
- package/dist/otel/claude-hooks.js.map +1 -0
- package/dist/otel/claude-wrapper.d.ts.map +1 -0
- package/dist/{claude-wrapper.js → otel/claude-wrapper.js} +2 -1
- package/dist/otel/claude-wrapper.js.map +1 -0
- package/dist/otel/gemini.d.ts +56 -0
- package/dist/otel/gemini.d.ts.map +1 -0
- package/dist/otel/gemini.js +348 -0
- package/dist/otel/gemini.js.map +1 -0
- package/dist/otel/index.d.ts +32 -0
- package/dist/otel/index.d.ts.map +1 -0
- package/dist/otel/index.js +41 -0
- package/dist/otel/index.js.map +1 -0
- 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/{langchain-handler.d.ts → otel/langchain-handler.d.ts} +10 -1
- package/dist/otel/langchain-handler.d.ts.map +1 -0
- package/dist/{langchain-handler.js → otel/langchain-handler.js} +43 -6
- package/dist/otel/langchain-handler.js.map +1 -0
- package/dist/otel/logs.d.ts +82 -0
- package/dist/otel/logs.d.ts.map +1 -0
- package/dist/otel/logs.js +271 -0
- package/dist/otel/logs.js.map +1 -0
- package/dist/{mastra-exporter.d.ts → otel/mastra-exporter.d.ts} +3 -1
- package/dist/otel/mastra-exporter.d.ts.map +1 -0
- package/dist/{mastra-exporter.js → otel/mastra-exporter.js} +71 -17
- package/dist/otel/mastra-exporter.js.map +1 -0
- package/dist/otel/pi.d.ts +59 -0
- package/dist/otel/pi.d.ts.map +1 -0
- package/dist/otel/pi.js +67 -0
- package/dist/otel/pi.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 +52 -0
- package/dist/otel/setup.d.ts.map +1 -0
- package/dist/otel/setup.js +146 -0
- package/dist/otel/setup.js.map +1 -0
- package/dist/{span-processor.d.ts → otel/span-processor.d.ts} +1 -1
- package/dist/otel/span-processor.d.ts.map +1 -0
- package/dist/{span-processor.js → otel/span-processor.js} +11 -5
- package/dist/otel/span-processor.js.map +1 -0
- package/dist/{tracing-processor.d.ts → otel/tracing-processor.d.ts} +4 -1
- package/dist/otel/tracing-processor.d.ts.map +1 -0
- package/dist/{tracing-processor.js → otel/tracing-processor.js} +64 -14
- package/dist/otel/tracing-processor.js.map +1 -0
- package/dist/resources/experiments.d.ts +31 -0
- package/dist/resources/experiments.d.ts.map +1 -0
- package/dist/resources/experiments.js +133 -0
- package/dist/resources/experiments.js.map +1 -0
- package/dist/resources/recipes.d.ts +22 -0
- package/dist/resources/recipes.d.ts.map +1 -0
- package/dist/resources/recipes.js +61 -0
- package/dist/resources/recipes.js.map +1 -0
- package/dist/resources/runtimes.d.ts +76 -0
- package/dist/resources/runtimes.d.ts.map +1 -0
- package/dist/resources/runtimes.js +179 -0
- package/dist/resources/runtimes.js.map +1 -0
- package/dist/runner-resources/files.d.ts +35 -0
- package/dist/runner-resources/files.d.ts.map +1 -0
- package/dist/runner-resources/files.js +131 -0
- package/dist/runner-resources/files.js.map +1 -0
- package/dist/runner-resources/tasks.d.ts +39 -0
- package/dist/runner-resources/tasks.d.ts.map +1 -0
- package/dist/runner-resources/tasks.js +129 -0
- package/dist/runner-resources/tasks.js.map +1 -0
- package/dist/runner.d.ts +80 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +159 -0
- package/dist/runner.js.map +1 -0
- package/dist/streaming.d.ts +8 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +67 -0
- package/dist/streaming.js.map +1 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +13 -4
- package/dist/utils.js.map +1 -0
- package/dist/version.js +1 -0
- package/dist/version.js.map +1 -0
- package/package.json +91 -22
- package/src/client.ts +76 -473
- package/src/converters/claude.ts +10 -0
- package/src/converters/gemini.ts +243 -0
- package/src/converters/index.ts +13 -7
- package/src/converters/vercel.ts +41 -3
- package/src/http.ts +163 -0
- package/src/index.ts +110 -75
- package/src/{anthropic.ts → otel/anthropic.ts} +206 -54
- package/src/{claude-hooks.ts → otel/claude-hooks.ts} +119 -20
- package/src/{claude-wrapper.ts → otel/claude-wrapper.ts} +1 -1
- package/src/otel/gemini.ts +491 -0
- package/src/otel/index.ts +121 -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/{langchain-handler.ts → otel/langchain-handler.ts} +53 -6
- package/src/otel/logs.ts +394 -0
- package/src/{mastra-exporter.ts → otel/mastra-exporter.ts} +83 -22
- package/src/otel/pi.ts +88 -0
- package/src/otel/register.ts +50 -0
- package/src/otel/setup.ts +215 -0
- package/src/{span-processor.ts → otel/span-processor.ts} +11 -6
- package/src/{tracing-processor.ts → otel/tracing-processor.ts} +94 -19
- package/src/resources/experiments.ts +170 -0
- package/src/resources/recipes.ts +73 -0
- package/src/resources/runtimes.ts +231 -0
- package/src/runner-resources/files.ts +163 -0
- package/src/runner-resources/tasks.ts +156 -0
- package/src/runner.ts +194 -0
- package/src/streaming.ts +57 -0
- package/src/utils.ts +12 -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.map +0 -1
- package/dist/claude-hooks.d.ts.map +0 -1
- package/dist/claude-wrapper.d.ts.map +0 -1
- 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/langchain-handler.d.ts.map +0 -1
- package/dist/mastra-exporter.d.ts.map +0 -1
- package/dist/span-processor.d.ts.map +0 -1
- package/dist/tracing-processor.d.ts.map +0 -1
- package/src/ai-sdk-integration.ts +0 -691
- package/src/converters/ai-sdk.ts +0 -323
- /package/dist/{claude-wrapper.d.ts → otel/claude-wrapper.d.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -1,36 +1,18 @@
|
|
|
1
|
-
import { IntrospectionSpanProcessor } from "./span-processor.js";
|
|
2
|
-
import type { IntrospectionSpanProcessorOptions } from "./span-processor.js";
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Provided as the default export for convenient use with logfire's
|
|
8
|
-
* `additionalSpanProcessors` option.
|
|
2
|
+
* Root entry point — REST-only surface.
|
|
9
3
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
4
|
+
* Exports `IntrospectionClient` (REST), Runner / RuntimeHandle /
|
|
5
|
+
* ExperimentHandle, REST wire types, and HTTP helpers. None of these
|
|
6
|
+
* touch the OpenTelemetry SDK.
|
|
12
7
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* import introspectionSpanProcessor from "@introspection-sdk/introspection-node";
|
|
16
|
-
*
|
|
17
|
-
* logfire.configure({ additionalSpanProcessors: [introspectionSpanProcessor()] });
|
|
18
|
-
* ```
|
|
8
|
+
* For the OTel surface (logs, span processors, instrumentors) import
|
|
9
|
+
* from `@introspection-sdk/introspection-node/otel`.
|
|
19
10
|
*/
|
|
20
|
-
export default function introspectionSpanProcessor(
|
|
21
|
-
options?: IntrospectionSpanProcessorOptions,
|
|
22
|
-
): IntrospectionSpanProcessor {
|
|
23
|
-
return new IntrospectionSpanProcessor(options);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Span processor exports (for OpenTelemetry integration)
|
|
27
|
-
export { IntrospectionSpanProcessor } from "./span-processor.js";
|
|
28
|
-
export type { IntrospectionSpanProcessorOptions } from "./span-processor.js";
|
|
29
11
|
|
|
30
|
-
//
|
|
12
|
+
// REST client.
|
|
31
13
|
export { IntrospectionClient } from "./client.js";
|
|
32
14
|
|
|
33
|
-
//
|
|
15
|
+
// Configuration / event types shared with the OTel surface.
|
|
34
16
|
export type {
|
|
35
17
|
AdvancedOptions,
|
|
36
18
|
IntrospectionClientOptions,
|
|
@@ -38,40 +20,98 @@ export type {
|
|
|
38
20
|
UserTraits,
|
|
39
21
|
} from "./types.js";
|
|
40
22
|
|
|
41
|
-
//
|
|
42
|
-
export {
|
|
43
|
-
export type {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
} from "./
|
|
23
|
+
// Runner-bound REST namespaces (runner.tasks, runner.files) + HTTP/SSE.
|
|
24
|
+
export { TasksApi, TaskRunsApi, RunHandle } from "./runner-resources/tasks.js";
|
|
25
|
+
export type { StartParams } from "./runner-resources/tasks.js";
|
|
26
|
+
export { FilesApi, FileVersionsApi } from "./runner-resources/files.js";
|
|
27
|
+
export type { FileUploadBody } from "./runner-resources/files.js";
|
|
28
|
+
export { HttpClient } from "./http.js";
|
|
29
|
+
export type { ResolvedApiConfig } from "./http.js";
|
|
30
|
+
export { parseSse } from "./streaming.js";
|
|
47
31
|
|
|
48
|
-
//
|
|
49
|
-
export {
|
|
50
|
-
export type {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
} from "./
|
|
32
|
+
// Runner + CP resources.
|
|
33
|
+
export { Runner } from "./runner.js";
|
|
34
|
+
export type { RunnerSource } from "./runner.js";
|
|
35
|
+
export {
|
|
36
|
+
RuntimesApi,
|
|
37
|
+
RuntimeHandle,
|
|
38
|
+
attachRuntimes,
|
|
39
|
+
isUuid,
|
|
40
|
+
} from "./resources/runtimes.js";
|
|
41
|
+
export type { RuntimeHandleFactory } from "./resources/runtimes.js";
|
|
42
|
+
export {
|
|
43
|
+
ExperimentsApi,
|
|
44
|
+
ExperimentHandle,
|
|
45
|
+
attachExperiments,
|
|
46
|
+
} from "./resources/experiments.js";
|
|
47
|
+
export type { ExperimentHandleFactory } from "./resources/experiments.js";
|
|
48
|
+
export { RecipesApi, attachRecipes } from "./resources/recipes.js";
|
|
65
49
|
|
|
66
|
-
//
|
|
67
|
-
export { withIntrospection } from "./claude-wrapper.js";
|
|
50
|
+
// REST API wire types
|
|
68
51
|
export type {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
52
|
+
Paginated,
|
|
53
|
+
ListParams,
|
|
54
|
+
Task,
|
|
55
|
+
TaskCreateParams,
|
|
56
|
+
TaskUpdateParams,
|
|
57
|
+
TaskListParams,
|
|
58
|
+
TaskMode,
|
|
59
|
+
TaskStatus,
|
|
60
|
+
TaskPrompt,
|
|
61
|
+
TaskRun,
|
|
62
|
+
TaskRunCreateParams,
|
|
63
|
+
TaskRunResponse,
|
|
64
|
+
TaskCreateResponse,
|
|
65
|
+
TaskCancelResponse,
|
|
66
|
+
AgentInfo,
|
|
67
|
+
File,
|
|
68
|
+
FileType,
|
|
69
|
+
FileListParams,
|
|
70
|
+
FileUpdateParams,
|
|
71
|
+
FileCreateTextParams,
|
|
72
|
+
SseEvent,
|
|
73
|
+
Runtime,
|
|
74
|
+
RuntimeCreate,
|
|
75
|
+
RuntimeUpdate,
|
|
76
|
+
RuntimeListParams,
|
|
77
|
+
Experiment,
|
|
78
|
+
ExperimentCreate,
|
|
79
|
+
ExperimentUpdate,
|
|
80
|
+
ExperimentListParams,
|
|
81
|
+
ExperimentStatus,
|
|
82
|
+
ExperimentEndParams,
|
|
83
|
+
Arm,
|
|
84
|
+
Recipe,
|
|
85
|
+
RecipeCreate,
|
|
86
|
+
RecipeUpdate,
|
|
87
|
+
RecipeListParams,
|
|
88
|
+
RunnerSpec,
|
|
89
|
+
RunnerDeployment,
|
|
90
|
+
RunnerContext,
|
|
91
|
+
RunnerRecipeSummary,
|
|
92
|
+
RunnerIdentity,
|
|
93
|
+
RunRequest,
|
|
94
|
+
RunCaller,
|
|
95
|
+
RunCallerLibrary,
|
|
96
|
+
RunCallerPage,
|
|
97
|
+
RunIdentityInput,
|
|
98
|
+
} from "@introspection-sdk/types";
|
|
99
|
+
export {
|
|
100
|
+
IntrospectionAPIError,
|
|
101
|
+
AuthenticationError,
|
|
102
|
+
InsufficientScopeError,
|
|
103
|
+
RunnerExpiredError,
|
|
104
|
+
NotFoundError,
|
|
105
|
+
ConflictError,
|
|
106
|
+
ValidationError,
|
|
107
|
+
RateLimitError,
|
|
108
|
+
SandboxUnavailableError,
|
|
109
|
+
StreamError,
|
|
110
|
+
NetworkError,
|
|
111
|
+
apiErrorFromResponse,
|
|
112
|
+
} from "@introspection-sdk/types";
|
|
73
113
|
|
|
74
|
-
// GenAI types
|
|
114
|
+
// GenAI types (shared, no OTel SDK imports).
|
|
75
115
|
export type {
|
|
76
116
|
GenAiAttributes,
|
|
77
117
|
InputMessage,
|
|
@@ -85,7 +125,7 @@ export type {
|
|
|
85
125
|
} from "@introspection-sdk/types";
|
|
86
126
|
export { toAttributes } from "@introspection-sdk/types";
|
|
87
127
|
|
|
88
|
-
// OpenAI converter exports
|
|
128
|
+
// OpenAI converter exports (pure functions, no OTel SDK imports).
|
|
89
129
|
export {
|
|
90
130
|
convertResponsesInputsToSemconv,
|
|
91
131
|
convertResponsesOutputsToSemconv,
|
|
@@ -100,22 +140,17 @@ export type {
|
|
|
100
140
|
Response as OpenAIResponse,
|
|
101
141
|
} from "./converters/openai.js";
|
|
102
142
|
|
|
103
|
-
//
|
|
104
|
-
export { IntrospectionAISDKIntegration } from "./ai-sdk-integration.js";
|
|
105
|
-
export type {
|
|
106
|
-
IntrospectionAISDKIntegrationOptions,
|
|
107
|
-
AISDKIntegrationAdvancedOptions,
|
|
108
|
-
} from "./ai-sdk-integration.js";
|
|
109
|
-
|
|
110
|
-
// OpenInference converter exports
|
|
111
|
-
export {
|
|
112
|
-
addOpenInferenceAttributes,
|
|
113
|
-
OpenInferenceSpanExporter,
|
|
114
|
-
} from "./converters/openinference.js";
|
|
115
|
-
|
|
116
|
-
// Anthropic instrumentor exports
|
|
143
|
+
// Gemini converters (pure functions, no OTel SDK imports).
|
|
117
144
|
export {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
145
|
+
convertGeminiContentsToInputMessages,
|
|
146
|
+
convertGeminiCandidatesToOutputMessages,
|
|
147
|
+
convertGeminiSystemInstructionToSemconv,
|
|
148
|
+
convertGeminiToolsToToolDefinitions,
|
|
149
|
+
} from "./converters/gemini.js";
|
|
150
|
+
export type {
|
|
151
|
+
GeminiCandidate,
|
|
152
|
+
GeminiContent,
|
|
153
|
+
GeminiFunctionDeclaration,
|
|
154
|
+
GeminiPart,
|
|
155
|
+
GeminiTool,
|
|
156
|
+
} from "./converters/gemini.js";
|
|
@@ -24,7 +24,13 @@ import type {
|
|
|
24
24
|
ReasoningPart,
|
|
25
25
|
} from "@introspection-sdk/types";
|
|
26
26
|
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
trace,
|
|
29
|
+
context as otelContext,
|
|
30
|
+
propagation,
|
|
31
|
+
SpanKind,
|
|
32
|
+
SpanStatusCode,
|
|
33
|
+
} from "@opentelemetry/api";
|
|
28
34
|
import type { Tracer, Span } from "@opentelemetry/api";
|
|
29
35
|
import type { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
|
|
30
36
|
|
|
@@ -154,7 +160,11 @@ function serializeMessages(msgs: InputMessage[] | OutputMessage[]): string {
|
|
|
154
160
|
);
|
|
155
161
|
}
|
|
156
162
|
|
|
157
|
-
function startSpan(
|
|
163
|
+
function startSpan(
|
|
164
|
+
tracer: Tracer,
|
|
165
|
+
model: string,
|
|
166
|
+
conversationId?: string,
|
|
167
|
+
): { span: Span; token: null } {
|
|
158
168
|
const span = tracer.startSpan("chat", {
|
|
159
169
|
kind: SpanKind.CLIENT,
|
|
160
170
|
attributes: {
|
|
@@ -163,6 +173,9 @@ function startSpan(tracer: Tracer, model: string): { span: Span; token: null } {
|
|
|
163
173
|
"gen_ai.operation.name": "chat",
|
|
164
174
|
"gen_ai.request.model": model,
|
|
165
175
|
"openinference.span.kind": "LLM",
|
|
176
|
+
...(conversationId
|
|
177
|
+
? { "gen_ai.conversation.id": conversationId }
|
|
178
|
+
: undefined),
|
|
166
179
|
},
|
|
167
180
|
});
|
|
168
181
|
return { span, token: null };
|
|
@@ -177,10 +190,26 @@ function setRequestAttrs(span: Span, kwargs: Record<string, unknown>): void {
|
|
|
177
190
|
|
|
178
191
|
const system = kwargs.system;
|
|
179
192
|
if (system) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
193
|
+
let sysVal: string;
|
|
194
|
+
if (typeof system === "string") {
|
|
195
|
+
sysVal = JSON.stringify([{ type: "text", content: system }]);
|
|
196
|
+
} else if (Array.isArray(system)) {
|
|
197
|
+
// Anthropic block format: [{type:"text", text:"...", cache_control:{...}}]
|
|
198
|
+
// Normalize to gen_ai format: [{type:"text", content:"..."}]
|
|
199
|
+
sysVal = JSON.stringify(
|
|
200
|
+
(system as Array<Record<string, unknown>>).map((block) => ({
|
|
201
|
+
type: "text",
|
|
202
|
+
content:
|
|
203
|
+
typeof block.text === "string"
|
|
204
|
+
? block.text
|
|
205
|
+
: typeof block.content === "string"
|
|
206
|
+
? block.content
|
|
207
|
+
: "",
|
|
208
|
+
})),
|
|
209
|
+
);
|
|
210
|
+
} else {
|
|
211
|
+
sysVal = JSON.stringify(system);
|
|
212
|
+
}
|
|
184
213
|
span.setAttribute("gen_ai.system_instructions", sysVal);
|
|
185
214
|
}
|
|
186
215
|
|
|
@@ -219,6 +248,16 @@ function setResponseAttrs(span: Span, response: Record<string, unknown>): void {
|
|
|
219
248
|
span.setAttribute("gen_ai.usage.input_tokens", usage.input_tokens);
|
|
220
249
|
if (usage.output_tokens != null)
|
|
221
250
|
span.setAttribute("gen_ai.usage.output_tokens", usage.output_tokens);
|
|
251
|
+
if (usage.cache_read_input_tokens != null)
|
|
252
|
+
span.setAttribute(
|
|
253
|
+
"gen_ai.usage.cache_read.input_tokens",
|
|
254
|
+
usage.cache_read_input_tokens,
|
|
255
|
+
);
|
|
256
|
+
if (usage.cache_creation_input_tokens != null)
|
|
257
|
+
span.setAttribute(
|
|
258
|
+
"gen_ai.usage.cache_creation.input_tokens",
|
|
259
|
+
usage.cache_creation_input_tokens,
|
|
260
|
+
);
|
|
222
261
|
}
|
|
223
262
|
|
|
224
263
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -245,6 +284,8 @@ class TracedStream {
|
|
|
245
284
|
private responseModel: string | null = null;
|
|
246
285
|
private inputTokens = 0;
|
|
247
286
|
private outputTokens = 0;
|
|
287
|
+
private cacheReadInputTokens = 0;
|
|
288
|
+
private cacheCreationInputTokens = 0;
|
|
248
289
|
private finalized = false;
|
|
249
290
|
|
|
250
291
|
constructor(inner: AsyncIterable<StreamEvent>, span: Span) {
|
|
@@ -268,7 +309,11 @@ class TracedStream {
|
|
|
268
309
|
this.responseId = (event.message.id as string) || null;
|
|
269
310
|
this.responseModel = (event.message.model as string) || null;
|
|
270
311
|
const usage = event.message.usage as Record<string, number> | undefined;
|
|
271
|
-
if (usage)
|
|
312
|
+
if (usage) {
|
|
313
|
+
this.inputTokens = usage.input_tokens || 0;
|
|
314
|
+
this.cacheReadInputTokens = usage.cache_read_input_tokens || 0;
|
|
315
|
+
this.cacheCreationInputTokens = usage.cache_creation_input_tokens || 0;
|
|
316
|
+
}
|
|
272
317
|
} else if (event.type === "content_block_start" && event.content_block) {
|
|
273
318
|
const bt = (event.content_block.type as string) || "";
|
|
274
319
|
this.currentBlock = { type: bt };
|
|
@@ -328,6 +373,16 @@ class TracedStream {
|
|
|
328
373
|
this.span.setAttribute("gen_ai.usage.input_tokens", this.inputTokens);
|
|
329
374
|
if (this.outputTokens)
|
|
330
375
|
this.span.setAttribute("gen_ai.usage.output_tokens", this.outputTokens);
|
|
376
|
+
if (this.cacheReadInputTokens)
|
|
377
|
+
this.span.setAttribute(
|
|
378
|
+
"gen_ai.usage.cache_read.input_tokens",
|
|
379
|
+
this.cacheReadInputTokens,
|
|
380
|
+
);
|
|
381
|
+
if (this.cacheCreationInputTokens)
|
|
382
|
+
this.span.setAttribute(
|
|
383
|
+
"gen_ai.usage.cache_creation.input_tokens",
|
|
384
|
+
this.cacheCreationInputTokens,
|
|
385
|
+
);
|
|
331
386
|
this.span.setStatus({ code: SpanStatusCode.OK });
|
|
332
387
|
this.span.end();
|
|
333
388
|
}
|
|
@@ -345,8 +400,13 @@ export async function tracedMessagesCreate(
|
|
|
345
400
|
tracer: Tracer,
|
|
346
401
|
client: { messages: { create: (...args: unknown[]) => Promise<unknown> } },
|
|
347
402
|
kwargs: Record<string, unknown>,
|
|
403
|
+
conversationId?: string,
|
|
348
404
|
): Promise<unknown> {
|
|
349
|
-
const { span } = startSpan(
|
|
405
|
+
const { span } = startSpan(
|
|
406
|
+
tracer,
|
|
407
|
+
(kwargs.model as string) || "unknown",
|
|
408
|
+
conversationId,
|
|
409
|
+
);
|
|
350
410
|
try {
|
|
351
411
|
setRequestAttrs(span, kwargs);
|
|
352
412
|
const response = (await client.messages.create(kwargs)) as Record<
|
|
@@ -378,16 +438,106 @@ export async function tracedMessagesCreate(
|
|
|
378
438
|
* Captures all content blocks including thinking (extended thinking) with
|
|
379
439
|
* signatures. Supports both non-streaming and streaming calls.
|
|
380
440
|
*/
|
|
441
|
+
/**
|
|
442
|
+
* Build the traced replacement for `messages.create`.
|
|
443
|
+
*
|
|
444
|
+
* Shared by {@link AnthropicInstrumentor.instrument} (patches a single client
|
|
445
|
+
* instance) and {@link AnthropicInstrumentor.instrumentClass} (patches
|
|
446
|
+
* `Anthropic.Messages.prototype.create` so every client is auto-traced). The
|
|
447
|
+
* returned function preserves the call-site `this`, so it works whether it is
|
|
448
|
+
* assigned to an instance property or onto the class prototype.
|
|
449
|
+
*/
|
|
450
|
+
function buildTracedCreate(
|
|
451
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
452
|
+
origCreate: (...args: any[]) => any,
|
|
453
|
+
tracer: Tracer,
|
|
454
|
+
defaultConversationId: string,
|
|
455
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
456
|
+
): (...args: any[]) => any {
|
|
457
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
458
|
+
return function tracedCreate(this: unknown, ...args: any[]) {
|
|
459
|
+
const kwargs = args[0] as Record<string, unknown>;
|
|
460
|
+
const isStream = kwargs?.stream === true;
|
|
461
|
+
|
|
462
|
+
// Baggage on the active context overrides the conversation ID bound at
|
|
463
|
+
// instrument() time, so callers can wrap a request in
|
|
464
|
+
// IntrospectionClient.withConversation() to scope a single call to a
|
|
465
|
+
// distinct conversation without re-instrumenting the client.
|
|
466
|
+
const baggage = propagation.getBaggage(otelContext.active());
|
|
467
|
+
const baggageConvId = baggage?.getEntry("gen_ai.conversation.id")?.value;
|
|
468
|
+
const baggageAgentName = baggage?.getEntry("gen_ai.agent.name")?.value;
|
|
469
|
+
const baggageAgentId = baggage?.getEntry("gen_ai.agent.id")?.value;
|
|
470
|
+
|
|
471
|
+
const { span } = startSpan(
|
|
472
|
+
tracer,
|
|
473
|
+
(kwargs?.model as string) || "unknown",
|
|
474
|
+
baggageConvId ?? defaultConversationId,
|
|
475
|
+
);
|
|
476
|
+
if (baggageAgentName) {
|
|
477
|
+
span.setAttribute("gen_ai.agent.name", baggageAgentName);
|
|
478
|
+
}
|
|
479
|
+
if (baggageAgentId) {
|
|
480
|
+
span.setAttribute("gen_ai.agent.id", baggageAgentId);
|
|
481
|
+
}
|
|
482
|
+
setRequestAttrs(span, kwargs || {});
|
|
483
|
+
|
|
484
|
+
if (isStream) {
|
|
485
|
+
const streamPromise = origCreate.apply(this, args) as Promise<
|
|
486
|
+
AsyncIterable<StreamEvent>
|
|
487
|
+
>;
|
|
488
|
+
return streamPromise.then(
|
|
489
|
+
(stream: AsyncIterable<StreamEvent>) => new TracedStream(stream, span),
|
|
490
|
+
(err: Error) => {
|
|
491
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
492
|
+
span.end();
|
|
493
|
+
throw err;
|
|
494
|
+
},
|
|
495
|
+
);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const resultPromise = origCreate.apply(this, args) as Promise<
|
|
499
|
+
Record<string, unknown>
|
|
500
|
+
>;
|
|
501
|
+
return resultPromise.then(
|
|
502
|
+
(response: Record<string, unknown>) => {
|
|
503
|
+
setResponseAttrs(span, response);
|
|
504
|
+
span.end();
|
|
505
|
+
return response;
|
|
506
|
+
},
|
|
507
|
+
(err: Error) => {
|
|
508
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
509
|
+
span.end();
|
|
510
|
+
throw err;
|
|
511
|
+
},
|
|
512
|
+
);
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Marker placed on a patched `Messages.prototype.create` so repeated
|
|
518
|
+
* `instrumentClass()` calls (e.g. a second `introspection.init()`) are no-ops.
|
|
519
|
+
*/
|
|
520
|
+
const PATCHED = Symbol.for("introspection.anthropic.patched");
|
|
521
|
+
|
|
381
522
|
export class AnthropicInstrumentor {
|
|
382
523
|
private tracer: Tracer | null = null;
|
|
383
524
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
384
525
|
private patchedClients: Array<{ client: any; originalCreate: any }> = [];
|
|
526
|
+
private protoRestores: Array<() => void> = [];
|
|
527
|
+
private conversationId: string | undefined;
|
|
385
528
|
|
|
386
529
|
instrument(opts: {
|
|
387
530
|
tracerProvider?: BasicTracerProvider;
|
|
388
531
|
/** The Anthropic client instance to instrument. */
|
|
389
532
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
390
533
|
client: any;
|
|
534
|
+
/**
|
|
535
|
+
* Conversation ID shared across all spans produced by this instrumentor.
|
|
536
|
+
* Enables the Introspection processor to reliably link multi-turn API calls
|
|
537
|
+
* into a single conversation without relying on history-hash matching.
|
|
538
|
+
* Defaults to a random UUID generated at instrument() time.
|
|
539
|
+
*/
|
|
540
|
+
conversationId?: string;
|
|
391
541
|
}): void {
|
|
392
542
|
const { client } = opts;
|
|
393
543
|
if (!client?.messages?.create) {
|
|
@@ -396,6 +546,8 @@ export class AnthropicInstrumentor {
|
|
|
396
546
|
);
|
|
397
547
|
}
|
|
398
548
|
|
|
549
|
+
this.conversationId = opts.conversationId ?? crypto.randomUUID();
|
|
550
|
+
|
|
399
551
|
const provider = opts.tracerProvider ?? trace.getTracerProvider();
|
|
400
552
|
this.tracer = (provider as BasicTracerProvider).getTracer(
|
|
401
553
|
"introspection-anthropic",
|
|
@@ -403,56 +555,54 @@ export class AnthropicInstrumentor {
|
|
|
403
555
|
|
|
404
556
|
const origCreate = client.messages.create.bind(client.messages);
|
|
405
557
|
this.patchedClients.push({ client, originalCreate: origCreate });
|
|
406
|
-
const tracer = this.tracer!;
|
|
407
558
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
559
|
+
client.messages.create = buildTracedCreate(
|
|
560
|
+
origCreate,
|
|
561
|
+
this.tracer,
|
|
562
|
+
this.conversationId,
|
|
563
|
+
);
|
|
564
|
+
}
|
|
412
565
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
566
|
+
/**
|
|
567
|
+
* Patch `Anthropic.Messages.prototype.create` so **every** client constructed
|
|
568
|
+
* from the given module is traced — the one-liner path used by
|
|
569
|
+
* `introspection.init()`. Idempotent: a second call is a no-op.
|
|
570
|
+
*
|
|
571
|
+
* @param opts.anthropic The `@anthropic-ai/sdk` module's default export
|
|
572
|
+
* (the `Anthropic` class). Its `.Messages.prototype.create` is patched.
|
|
573
|
+
*/
|
|
574
|
+
instrumentClass(opts: {
|
|
575
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
576
|
+
anthropic: any;
|
|
577
|
+
tracerProvider?: BasicTracerProvider;
|
|
578
|
+
conversationId?: string;
|
|
579
|
+
}): void {
|
|
580
|
+
const Messages = opts.anthropic?.Messages;
|
|
581
|
+
const proto = Messages?.prototype;
|
|
582
|
+
if (typeof proto?.create !== "function") {
|
|
583
|
+
throw new Error(
|
|
584
|
+
"Invalid Anthropic module — expected `Anthropic.Messages.prototype.create`",
|
|
416
585
|
);
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if (isStream) {
|
|
420
|
-
const streamPromise = origCreate(...args) as Promise<
|
|
421
|
-
AsyncIterable<StreamEvent>
|
|
422
|
-
>;
|
|
423
|
-
return streamPromise.then(
|
|
424
|
-
(stream: AsyncIterable<StreamEvent>) =>
|
|
425
|
-
new TracedStream(stream, span),
|
|
426
|
-
(err: Error) => {
|
|
427
|
-
span.setStatus({
|
|
428
|
-
code: SpanStatusCode.ERROR,
|
|
429
|
-
message: String(err),
|
|
430
|
-
});
|
|
431
|
-
span.end();
|
|
432
|
-
throw err;
|
|
433
|
-
},
|
|
434
|
-
);
|
|
435
|
-
}
|
|
586
|
+
}
|
|
587
|
+
if (proto.create[PATCHED]) return;
|
|
436
588
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
);
|
|
455
|
-
};
|
|
589
|
+
this.conversationId = opts.conversationId ?? crypto.randomUUID();
|
|
590
|
+
const provider = opts.tracerProvider ?? trace.getTracerProvider();
|
|
591
|
+
this.tracer = (provider as BasicTracerProvider).getTracer(
|
|
592
|
+
"introspection-anthropic",
|
|
593
|
+
);
|
|
594
|
+
|
|
595
|
+
const origCreate = proto.create;
|
|
596
|
+
const patched = buildTracedCreate(
|
|
597
|
+
origCreate,
|
|
598
|
+
this.tracer,
|
|
599
|
+
this.conversationId,
|
|
600
|
+
) as ((...args: unknown[]) => unknown) & { [PATCHED]?: boolean };
|
|
601
|
+
patched[PATCHED] = true;
|
|
602
|
+
proto.create = patched;
|
|
603
|
+
this.protoRestores.push(() => {
|
|
604
|
+
proto.create = origCreate;
|
|
605
|
+
});
|
|
456
606
|
}
|
|
457
607
|
|
|
458
608
|
uninstrument(): void {
|
|
@@ -460,6 +610,8 @@ export class AnthropicInstrumentor {
|
|
|
460
610
|
client.messages.create = originalCreate;
|
|
461
611
|
}
|
|
462
612
|
this.patchedClients = [];
|
|
613
|
+
for (const restore of this.protoRestores) restore();
|
|
614
|
+
this.protoRestores = [];
|
|
463
615
|
this.tracer = null;
|
|
464
616
|
}
|
|
465
617
|
}
|