@introspection-sdk/introspection-node 0.4.1 → 0.4.3
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/.turbo/turbo-check-types.log +4 -0
- package/.turbo/turbo-lint.log +5 -0
- package/dist/ai-sdk-integration.d.ts.map +1 -1
- package/dist/ai-sdk-integration.js +2 -2
- package/dist/claude-hooks.d.ts.map +1 -1
- package/dist/claude-hooks.js +3 -3
- package/dist/client.d.ts +42 -132
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +66 -365
- package/dist/client.js.map +1 -0
- package/dist/converters/claude.d.ts +5 -1
- 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/openclaw.d.ts +16 -0
- package/dist/converters/openclaw.d.ts.map +1 -0
- package/dist/converters/openclaw.js +49 -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/langchain-handler.d.ts.map +1 -1
- package/dist/langchain-handler.js +2 -2
- package/dist/mastra-exporter.d.ts.map +1 -1
- package/dist/mastra-exporter.js +2 -2
- package/dist/otel/anthropic.d.ts +62 -0
- package/dist/otel/anthropic.d.ts.map +1 -0
- package/dist/otel/anthropic.js +425 -0
- package/dist/otel/anthropic.js.map +1 -0
- package/dist/otel/claude-hooks.d.ts +346 -0
- package/dist/otel/claude-hooks.d.ts.map +1 -0
- package/dist/otel/claude-hooks.js +645 -0
- package/dist/otel/claude-hooks.js.map +1 -0
- package/dist/otel/claude-wrapper.d.ts +93 -0
- package/dist/otel/claude-wrapper.d.ts.map +1 -0
- package/dist/otel/claude-wrapper.js +155 -0
- package/dist/otel/claude-wrapper.js.map +1 -0
- package/dist/otel/gemini.d.ts +48 -0
- package/dist/otel/gemini.d.ts.map +1 -0
- package/dist/otel/gemini.js +297 -0
- package/dist/otel/gemini.js.map +1 -0
- package/dist/otel/index.d.ts +27 -0
- package/dist/otel/index.d.ts.map +1 -0
- package/dist/otel/index.js +33 -0
- package/dist/otel/index.js.map +1 -0
- package/dist/otel/langchain-handler.d.ts +112 -0
- package/dist/otel/langchain-handler.d.ts.map +1 -0
- package/dist/otel/langchain-handler.js +555 -0
- 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/otel/mastra-exporter.d.ts +87 -0
- package/dist/otel/mastra-exporter.d.ts.map +1 -0
- package/dist/otel/mastra-exporter.js +525 -0
- 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/setup.d.ts +23 -0
- package/dist/otel/setup.d.ts.map +1 -0
- package/dist/otel/setup.js +127 -0
- package/dist/otel/setup.js.map +1 -0
- package/dist/otel/span-processor.d.ts +62 -0
- package/dist/otel/span-processor.d.ts.map +1 -0
- package/dist/otel/span-processor.js +319 -0
- package/dist/otel/span-processor.js.map +1 -0
- package/dist/otel/tracing-processor.d.ts +139 -0
- package/dist/otel/tracing-processor.d.ts.map +1 -0
- package/dist/otel/tracing-processor.js +418 -0
- 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/span-processor.d.ts.map +1 -1
- package/dist/span-processor.js +3 -3
- 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/tracing-processor.d.ts.map +1 -1
- package/dist/tracing-processor.js +3 -3
- package/dist/types/genai.d.ts +165 -0
- package/dist/types/genai.d.ts.map +1 -0
- package/dist/types/genai.js +82 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +14 -0
- package/dist/utils.js.map +1 -0
- package/dist/version.js +1 -0
- package/dist/version.js.map +1 -0
- package/package.json +83 -25
- package/src/client.ts +76 -471
- package/src/converters/claude.ts +11 -1
- 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} +95 -8
- package/src/{claude-hooks.ts → otel/claude-hooks.ts} +125 -24
- package/src/{claude-wrapper.ts → otel/claude-wrapper.ts} +1 -1
- package/src/otel/gemini.ts +397 -0
- package/src/otel/index.ts +80 -0
- package/src/{langchain-handler.ts → otel/langchain-handler.ts} +56 -7
- package/src/otel/logs.ts +394 -0
- package/src/{mastra-exporter.ts → otel/mastra-exporter.ts} +86 -23
- package/src/otel/pi.ts +88 -0
- package/src/otel/setup.ts +174 -0
- package/src/{span-processor.ts → otel/span-processor.ts} +17 -10
- package/src/{tracing-processor.ts → otel/tracing-processor.ts} +100 -23
- 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 +15 -0
- package/src/ai-sdk-integration.ts +0 -689
- package/src/converters/ai-sdk.ts +0 -323
package/src/client.ts
CHANGED
|
@@ -1,513 +1,118 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Introspection Client for Node.js
|
|
3
|
-
* Provides an API for tracking events and feedback using OTLP Logs.
|
|
2
|
+
* Introspection REST Client for Node.js
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Exposes the Control Plane REST surface for managing runtimes and
|
|
5
|
+
* experiments. Calling `client.runtimes(name).run()` or
|
|
6
|
+
* `client.experiments(id).run()` returns a {@link Runner} bound to a Data
|
|
7
|
+
* Plane sandbox.
|
|
8
|
+
*
|
|
9
|
+
* This class is **REST-only** and does not depend on the OpenTelemetry
|
|
10
|
+
* SDK. For event tracking, feedback, identify, and baggage context
|
|
11
|
+
* helpers, use {@link IntrospectionLogs} from
|
|
12
|
+
* `@introspection-sdk/introspection-node/otel`.
|
|
7
13
|
*/
|
|
8
14
|
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
LoggerProvider,
|
|
12
|
-
BatchLogRecordProcessor,
|
|
13
|
-
} from "@opentelemetry/sdk-logs";
|
|
14
|
-
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-proto";
|
|
15
|
-
import {
|
|
16
|
-
resourceFromAttributes,
|
|
17
|
-
defaultResource,
|
|
18
|
-
} from "@opentelemetry/resources";
|
|
19
|
-
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
20
|
-
import { propagation, context } from "@opentelemetry/api";
|
|
15
|
+
import type { AdvancedOptions } from "@introspection-sdk/types";
|
|
21
16
|
import { logger as sdkLogger } from "./utils.js";
|
|
22
|
-
import {
|
|
17
|
+
import type { IntrospectionClientOptions } from "./types.js";
|
|
18
|
+
import { HttpClient } from "./http.js";
|
|
19
|
+
import {
|
|
20
|
+
attachRuntimes,
|
|
21
|
+
type RuntimeHandleFactory,
|
|
22
|
+
type RuntimesApi,
|
|
23
|
+
} from "./resources/runtimes.js";
|
|
23
24
|
import {
|
|
24
|
-
|
|
25
|
-
type
|
|
26
|
-
type
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
type IdentityContext,
|
|
30
|
-
} from "./types.js";
|
|
25
|
+
attachExperiments,
|
|
26
|
+
type ExperimentHandleFactory,
|
|
27
|
+
type ExperimentsApi,
|
|
28
|
+
} from "./resources/experiments.js";
|
|
29
|
+
import { attachRecipes, type RecipesApi } from "./resources/recipes.js";
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
|
-
* Introspection client
|
|
32
|
+
* Introspection REST client.
|
|
34
33
|
*
|
|
35
34
|
* @example
|
|
36
35
|
* ```typescript
|
|
37
36
|
* const client = new IntrospectionClient({
|
|
38
37
|
* token: process.env.INTROSPECTION_TOKEN,
|
|
38
|
+
* projectId: "proj_…",
|
|
39
39
|
* });
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
* client.
|
|
41
|
+
* // Open a runner from a runtime, then drive it.
|
|
42
|
+
* const runner = await client.runtimes("customer-agent").run({
|
|
43
|
+
* identity: { user_id: "u_42" },
|
|
44
|
+
* });
|
|
45
|
+
* const run = await runner.tasks.create({ prompt: "Summarize this repo" });
|
|
46
|
+
* for await (const ev of run.stream()) console.log(ev);
|
|
43
47
|
*
|
|
48
|
+
* await runner.close();
|
|
44
49
|
* await client.shutdown();
|
|
45
50
|
* ```
|
|
46
51
|
*/
|
|
47
52
|
export class IntrospectionClient {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
constructor(options: IntrospectionClientOptions = {}) {
|
|
55
|
-
const token = options.token || process.env.INTROSPECTION_TOKEN || "";
|
|
56
|
-
const serviceName =
|
|
57
|
-
options.serviceName ||
|
|
58
|
-
process.env.INTROSPECTION_SERVICE_NAME ||
|
|
59
|
-
"introspection-client";
|
|
60
|
-
const advanced = options.advanced || {};
|
|
61
|
-
const baseUrl =
|
|
62
|
-
advanced.baseUrl ||
|
|
63
|
-
process.env.INTROSPECTION_BASE_URL ||
|
|
64
|
-
"https://otel.introspection.dev";
|
|
65
|
-
|
|
66
|
-
if (!token) {
|
|
67
|
-
sdkLogger.warn(
|
|
68
|
-
"IntrospectionClient: No token provided. Events will not be sent.",
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Construct endpoint URL for logs
|
|
73
|
-
let endpoint: string;
|
|
74
|
-
if (baseUrl.endsWith("/v1/logs")) {
|
|
75
|
-
endpoint = baseUrl;
|
|
76
|
-
} else {
|
|
77
|
-
endpoint = `${baseUrl.replace(/\/$/, "")}/v1/logs`;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Build headers
|
|
81
|
-
const headers: Record<string, string> = {
|
|
82
|
-
Authorization: `Bearer ${token}`,
|
|
83
|
-
};
|
|
84
|
-
if (advanced.additionalHeaders) {
|
|
85
|
-
Object.assign(headers, advanced.additionalHeaders);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Create OTLP log exporter
|
|
89
|
-
const exporter = new OTLPLogExporter({
|
|
90
|
-
url: endpoint,
|
|
91
|
-
headers,
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Create batch processor
|
|
95
|
-
const processor = new BatchLogRecordProcessor(exporter, {
|
|
96
|
-
maxQueueSize: advanced.maxBatchSize ?? 100,
|
|
97
|
-
scheduledDelayMillis: advanced.flushInterval ?? 5000,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// Get default resource and merge with our service name
|
|
101
|
-
const baseResource = defaultResource();
|
|
102
|
-
const introspectionResource = resourceFromAttributes({
|
|
103
|
-
[ATTR_SERVICE_NAME]: serviceName,
|
|
104
|
-
});
|
|
105
|
-
const resource = baseResource.merge(introspectionResource);
|
|
106
|
-
|
|
107
|
-
// Create logger provider
|
|
108
|
-
this.loggerProvider = new LoggerProvider({
|
|
109
|
-
resource,
|
|
110
|
-
processors: [processor],
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
this.otelLogger = this.loggerProvider.getLogger(
|
|
114
|
-
"@introspection-sdk/introspection-node",
|
|
115
|
-
VERSION,
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
sdkLogger.info(
|
|
119
|
-
`IntrospectionClient initialized: service=${serviceName}, endpoint=${endpoint}`,
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** Get gen_ai context from baggage */
|
|
124
|
-
private getGenAiFromContext(): GenAiContext {
|
|
125
|
-
const baggage = propagation.getBaggage(context.active());
|
|
126
|
-
return {
|
|
127
|
-
conversationId: baggage?.getEntry("gen_ai.conversation.id")?.value,
|
|
128
|
-
previousResponseId: baggage?.getEntry(
|
|
129
|
-
"gen_ai.request.previous_response_id",
|
|
130
|
-
)?.value,
|
|
131
|
-
agentName: baggage?.getEntry("gen_ai.agent.name")?.value,
|
|
132
|
-
agentId: baggage?.getEntry("gen_ai.agent.id")?.value,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/** Get identity from baggage or client instance */
|
|
137
|
-
private getIdentityFromContext(): IdentityContext {
|
|
138
|
-
const baggage = propagation.getBaggage(context.active());
|
|
139
|
-
return {
|
|
140
|
-
userId: baggage?.getEntry("identity.user_id")?.value || this.userId,
|
|
141
|
-
anonymousId:
|
|
142
|
-
baggage?.getEntry("identity.anonymous_id")?.value || this.anonymousId,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
53
|
+
/** @internal — HTTP client pointed at the CP API with the customer key. */
|
|
54
|
+
readonly cpHttp: HttpClient;
|
|
55
|
+
/** @internal — passed through to Runner so it can build its own DP HTTP client. */
|
|
56
|
+
readonly advancedOptions: AdvancedOptions;
|
|
57
|
+
readonly projectId: string | undefined;
|
|
145
58
|
|
|
146
59
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
60
|
+
* CRUD on `/v1/runtimes` and the `(idOrName) => RuntimeHandle` factory.
|
|
61
|
+
* Call as `client.runtimes("customer-agent").run()` or
|
|
62
|
+
* `client.runtimes.list({ project_id })`.
|
|
149
63
|
*/
|
|
150
|
-
|
|
151
|
-
const hrTimeNs = process.hrtime.bigint();
|
|
152
|
-
const epochNs = BigInt(Date.now()) * BigInt(1_000_000);
|
|
153
|
-
const offsetNs = hrTimeNs - process.hrtime.bigint() + epochNs;
|
|
154
|
-
const seconds = Number(offsetNs / BigInt(1_000_000_000));
|
|
155
|
-
const nanos = Number(offsetNs % BigInt(1_000_000_000));
|
|
156
|
-
return [seconds, nanos];
|
|
157
|
-
}
|
|
64
|
+
readonly runtimes: RuntimesApi & RuntimeHandleFactory;
|
|
158
65
|
|
|
159
66
|
/**
|
|
160
|
-
*
|
|
67
|
+
* CRUD on `/v1/experiments` and the `(id) => ExperimentHandle` factory.
|
|
161
68
|
*/
|
|
162
|
-
|
|
163
|
-
eventName: string,
|
|
164
|
-
options: {
|
|
165
|
-
properties?: Record<string, unknown>;
|
|
166
|
-
traits?: Record<string, unknown>;
|
|
167
|
-
conversationId?: string;
|
|
168
|
-
previousResponseId?: string;
|
|
169
|
-
eventId?: string;
|
|
170
|
-
} = {},
|
|
171
|
-
): LogAttributes {
|
|
172
|
-
const { properties, traits, conversationId, previousResponseId, eventId } =
|
|
173
|
-
options;
|
|
174
|
-
|
|
175
|
-
// Core fields
|
|
176
|
-
const attributes: LogAttributes = {
|
|
177
|
-
"event.name": eventName,
|
|
178
|
-
"event.id": eventId || generateEventId(),
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
// Identity
|
|
182
|
-
const identity = this.getIdentityFromContext();
|
|
183
|
-
if (identity.userId) {
|
|
184
|
-
attributes["identity.user.id"] = identity.userId;
|
|
185
|
-
}
|
|
186
|
-
if (identity.anonymousId) {
|
|
187
|
-
attributes["identity.anonymous.id"] = identity.anonymousId;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Gen AI context (explicit params override baggage)
|
|
191
|
-
const genAi = this.getGenAiFromContext();
|
|
192
|
-
const finalConversationId = conversationId || genAi.conversationId;
|
|
193
|
-
const finalPreviousResponseId =
|
|
194
|
-
previousResponseId || genAi.previousResponseId;
|
|
195
|
-
|
|
196
|
-
if (finalConversationId) {
|
|
197
|
-
attributes["gen_ai.conversation.id"] = finalConversationId;
|
|
198
|
-
}
|
|
199
|
-
if (finalPreviousResponseId) {
|
|
200
|
-
attributes["gen_ai.request.previous_response_id"] =
|
|
201
|
-
finalPreviousResponseId;
|
|
202
|
-
}
|
|
203
|
-
if (genAi.agentName) {
|
|
204
|
-
attributes["gen_ai.agent.name"] = genAi.agentName;
|
|
205
|
-
}
|
|
206
|
-
if (genAi.agentId) {
|
|
207
|
-
attributes["gen_ai.agent.id"] = genAi.agentId;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Flatten properties with "properties." prefix
|
|
211
|
-
if (properties) {
|
|
212
|
-
for (const [key, value] of Object.entries(properties)) {
|
|
213
|
-
if (value != null) {
|
|
214
|
-
const attrKey = `properties.${key}`;
|
|
215
|
-
if (typeof value === "object") {
|
|
216
|
-
attributes[attrKey] = JSON.stringify(value);
|
|
217
|
-
} else if (
|
|
218
|
-
typeof value === "string" ||
|
|
219
|
-
typeof value === "number" ||
|
|
220
|
-
typeof value === "boolean"
|
|
221
|
-
) {
|
|
222
|
-
attributes[attrKey] = value;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Flatten traits with "context.traits." prefix
|
|
229
|
-
if (traits) {
|
|
230
|
-
for (const [key, value] of Object.entries(traits)) {
|
|
231
|
-
if (value != null) {
|
|
232
|
-
const attrKey = `context.traits.${key}`;
|
|
233
|
-
if (typeof value === "object") {
|
|
234
|
-
attributes[attrKey] = JSON.stringify(value);
|
|
235
|
-
} else if (
|
|
236
|
-
typeof value === "string" ||
|
|
237
|
-
typeof value === "number" ||
|
|
238
|
-
typeof value === "boolean"
|
|
239
|
-
) {
|
|
240
|
-
attributes[attrKey] = value;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return attributes;
|
|
247
|
-
}
|
|
69
|
+
readonly experiments: ExperimentsApi & ExperimentHandleFactory;
|
|
248
70
|
|
|
249
71
|
/**
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* @param properties - Arbitrary key/value pairs attached to the event.
|
|
254
|
-
* @param options - Optional overrides such as a custom `eventId`.
|
|
72
|
+
* CRUD on `/v1/recipes`. Recipes are immutable build artefacts
|
|
73
|
+
* (repository + git ref + commit sha) referenced by runtimes and
|
|
74
|
+
* experiment arms.
|
|
255
75
|
*/
|
|
256
|
-
|
|
257
|
-
eventName: string,
|
|
258
|
-
properties?: Record<string, unknown>,
|
|
259
|
-
options?: { eventId?: string },
|
|
260
|
-
): void {
|
|
261
|
-
const attributes = this.buildAttributes(eventName, {
|
|
262
|
-
properties,
|
|
263
|
-
eventId: options?.eventId,
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
this.otelLogger.emit({
|
|
267
|
-
timestamp: this.getTimestamp(),
|
|
268
|
-
context: context.active(),
|
|
269
|
-
severityNumber: SeverityNumber.INFO,
|
|
270
|
-
severityText: "INFO",
|
|
271
|
-
attributes,
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
sdkLogger.debug(`Tracked: ${eventName}`);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Track feedback on a message or response.
|
|
279
|
-
*
|
|
280
|
-
* @param name - Feedback type (e.g. `"thumbs_up"`, `"thumbs_down"`).
|
|
281
|
-
* @param options - Additional feedback context such as comments or conversation ID.
|
|
282
|
-
*/
|
|
283
|
-
feedback(name: string, options: FeedbackOptions = {}): void {
|
|
284
|
-
const { comments, conversationId, previousResponseId, eventId, ...extra } =
|
|
285
|
-
options;
|
|
286
|
-
|
|
287
|
-
const properties: Record<string, unknown> = { name, ...extra };
|
|
288
|
-
if (comments) {
|
|
289
|
-
properties.comments = comments;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const attributes = this.buildAttributes("introspection.feedback", {
|
|
293
|
-
properties,
|
|
294
|
-
conversationId: conversationId as string | undefined,
|
|
295
|
-
previousResponseId: previousResponseId as string | undefined,
|
|
296
|
-
eventId: eventId as string | undefined,
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
this.otelLogger.emit({
|
|
300
|
-
timestamp: this.getTimestamp(),
|
|
301
|
-
context: context.active(),
|
|
302
|
-
severityNumber: SeverityNumber.INFO,
|
|
303
|
-
severityText: "INFO",
|
|
304
|
-
attributes,
|
|
305
|
-
});
|
|
76
|
+
readonly recipes: RecipesApi;
|
|
306
77
|
|
|
307
|
-
|
|
308
|
-
|
|
78
|
+
constructor(options: IntrospectionClientOptions = {}) {
|
|
79
|
+
const token = options.token || process.env.INTROSPECTION_TOKEN || "";
|
|
80
|
+
const advanced = options.advanced || {};
|
|
81
|
+
this.advancedOptions = advanced;
|
|
82
|
+
this.projectId =
|
|
83
|
+
options.projectId || process.env.INTROSPECTION_PROJECT_ID || undefined;
|
|
84
|
+
const baseApiUrl =
|
|
85
|
+
advanced.baseApiUrl ||
|
|
86
|
+
process.env.INTROSPECTION_BASE_API_URL ||
|
|
87
|
+
"https://api.introspection.dev";
|
|
309
88
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
* @param traits - Key/value user properties (e.g. `{ email: "…" }`).
|
|
315
|
-
* @param anonymousId - Optional anonymous identifier to link pre-auth sessions.
|
|
316
|
-
* @param eventId - Optional custom event ID override.
|
|
317
|
-
*/
|
|
318
|
-
identify(
|
|
319
|
-
userId: string,
|
|
320
|
-
traits?: UserTraits,
|
|
321
|
-
anonymousId?: string,
|
|
322
|
-
eventId?: string,
|
|
323
|
-
): void {
|
|
324
|
-
this.userId = userId;
|
|
325
|
-
if (anonymousId) {
|
|
326
|
-
this.anonymousId = anonymousId;
|
|
327
|
-
}
|
|
328
|
-
if (traits) {
|
|
329
|
-
this.traits = { ...this.traits, ...traits };
|
|
89
|
+
if (!token) {
|
|
90
|
+
sdkLogger.warn(
|
|
91
|
+
"IntrospectionClient: No token provided. REST calls will fail.",
|
|
92
|
+
);
|
|
330
93
|
}
|
|
331
94
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
95
|
+
// CP HTTP client — talks to the customer-facing API with the customer
|
|
96
|
+
// API key. Runners get their own HttpClient instances pointed at the
|
|
97
|
+
// `deployment.endpoint` returned by `/v1/runtimes/{id}/run`.
|
|
98
|
+
this.cpHttp = new HttpClient({
|
|
99
|
+
apiUrl: baseApiUrl,
|
|
100
|
+
token,
|
|
101
|
+
additionalHeaders: advanced.additionalHeaders,
|
|
102
|
+
fetch: advanced.fetch,
|
|
340
103
|
});
|
|
341
104
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* Create an OTel context with the given baggage values set.
|
|
347
|
-
*
|
|
348
|
-
* @param values - Key/value pairs to store in OTel baggage.
|
|
349
|
-
* @returns A new context containing the baggage entries.
|
|
350
|
-
*/
|
|
351
|
-
createBaggageContext(values: Record<string, string>) {
|
|
352
|
-
const ctx = context.active();
|
|
353
|
-
let bag = propagation.getBaggage(ctx) || propagation.createBaggage();
|
|
354
|
-
|
|
355
|
-
for (const [key, value] of Object.entries(values)) {
|
|
356
|
-
bag = bag.setEntry(key, { value });
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
return propagation.setBaggage(ctx, bag);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Set multiple baggage values and run a callback within that context.
|
|
364
|
-
*
|
|
365
|
-
* @param values - Key/value pairs to store in OTel baggage.
|
|
366
|
-
* @param callback - Function to execute with the baggage context active.
|
|
367
|
-
* @returns The value returned by `callback`.
|
|
368
|
-
*/
|
|
369
|
-
async withBaggage<T>(
|
|
370
|
-
values: Record<string, string>,
|
|
371
|
-
callback: () => T | Promise<T>,
|
|
372
|
-
): Promise<T> {
|
|
373
|
-
const ctx = this.createBaggageContext(values);
|
|
374
|
-
return await context.with(ctx, callback);
|
|
375
|
-
}
|
|
105
|
+
this.runtimes = attachRuntimes(this, this.cpHttp);
|
|
106
|
+
this.experiments = attachExperiments(this, this.cpHttp);
|
|
107
|
+
this.recipes = attachRecipes(this.cpHttp);
|
|
376
108
|
|
|
377
|
-
|
|
378
|
-
* Set `gen_ai.agent.name` (and optionally `gen_ai.agent.id`) baggage and run
|
|
379
|
-
* a callback within that context.
|
|
380
|
-
*
|
|
381
|
-
* @param agentName - The agent name to propagate.
|
|
382
|
-
* @param agentId - Optional agent identifier.
|
|
383
|
-
* @param callback - Function to execute with the agent baggage active.
|
|
384
|
-
* @returns The value returned by `callback`.
|
|
385
|
-
*/
|
|
386
|
-
async withAgent<T>(
|
|
387
|
-
agentName: string,
|
|
388
|
-
agentId: string | undefined,
|
|
389
|
-
callback: () => T | Promise<T>,
|
|
390
|
-
): Promise<T> {
|
|
391
|
-
const values: Record<string, string> = { "gen_ai.agent.name": agentName };
|
|
392
|
-
if (agentId) {
|
|
393
|
-
values["gen_ai.agent.id"] = agentId;
|
|
394
|
-
}
|
|
395
|
-
return await context.with(this.createBaggageContext(values), callback);
|
|
109
|
+
sdkLogger.info(`IntrospectionClient initialized: api=${baseApiUrl}`);
|
|
396
110
|
}
|
|
397
111
|
|
|
398
|
-
/**
|
|
399
|
-
* Set conversation-related baggage (`gen_ai.conversation.id`,
|
|
400
|
-
* `gen_ai.request.previous_response_id`) and run a callback within that
|
|
401
|
-
* context.
|
|
402
|
-
*
|
|
403
|
-
* @param conversationId - The conversation identifier.
|
|
404
|
-
* @param previousResponseId - The ID of the previous response in the conversation.
|
|
405
|
-
* @param callback - Function to execute with the conversation baggage active.
|
|
406
|
-
* @returns The value returned by `callback`.
|
|
407
|
-
*/
|
|
408
|
-
async withConversation<T>(
|
|
409
|
-
conversationId: string | undefined,
|
|
410
|
-
previousResponseId: string | undefined,
|
|
411
|
-
callback: () => T | Promise<T>,
|
|
412
|
-
): Promise<T> {
|
|
413
|
-
const values: Record<string, string> = {};
|
|
414
|
-
if (conversationId) {
|
|
415
|
-
values["gen_ai.conversation.id"] = conversationId;
|
|
416
|
-
}
|
|
417
|
-
if (previousResponseId) {
|
|
418
|
-
values["gen_ai.request.previous_response_id"] = previousResponseId;
|
|
419
|
-
}
|
|
420
|
-
return await context.with(this.createBaggageContext(values), callback);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* Set the user ID on this client instance.
|
|
425
|
-
*
|
|
426
|
-
* @param userId - Unique identifier for the user.
|
|
427
|
-
*/
|
|
428
|
-
setUserId(userId: string): void {
|
|
429
|
-
this.userId = userId;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* Set the anonymous ID on this client instance.
|
|
434
|
-
*
|
|
435
|
-
* @param anonymousId - Anonymous identifier used before authentication.
|
|
436
|
-
*/
|
|
437
|
-
setAnonymousId(anonymousId: string): void {
|
|
438
|
-
this.anonymousId = anonymousId;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/**
|
|
442
|
-
* Set `identity.user_id` baggage and run a callback within that context.
|
|
443
|
-
*
|
|
444
|
-
* @param userId - The user identifier to propagate.
|
|
445
|
-
* @param callback - Function to execute with the user-ID baggage active.
|
|
446
|
-
* @returns The value returned by `callback`.
|
|
447
|
-
*/
|
|
448
|
-
async withUserId<T>(
|
|
449
|
-
userId: string,
|
|
450
|
-
callback: () => T | Promise<T>,
|
|
451
|
-
): Promise<T> {
|
|
452
|
-
return await context.with(
|
|
453
|
-
this.createBaggageContext({ "identity.user_id": userId }),
|
|
454
|
-
callback,
|
|
455
|
-
);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* Set `identity.anonymous_id` baggage and run a callback within that context.
|
|
460
|
-
*
|
|
461
|
-
* @param anonymousId - The anonymous identifier to propagate.
|
|
462
|
-
* @param callback - Function to execute with the anonymous-ID baggage active.
|
|
463
|
-
* @returns The value returned by `callback`.
|
|
464
|
-
*/
|
|
465
|
-
async withAnonymousId<T>(
|
|
466
|
-
anonymousId: string,
|
|
467
|
-
callback: () => T | Promise<T>,
|
|
468
|
-
): Promise<T> {
|
|
469
|
-
return await context.with(
|
|
470
|
-
this.createBaggageContext({ "identity.anonymous_id": anonymousId }),
|
|
471
|
-
callback,
|
|
472
|
-
);
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Get the current anonymous ID stored on this client instance.
|
|
477
|
-
*
|
|
478
|
-
* @returns The anonymous ID, or `undefined` if not set.
|
|
479
|
-
*/
|
|
480
|
-
getAnonymousId(): string | undefined {
|
|
481
|
-
return this.anonymousId;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* Reset all client-side state (user ID, anonymous ID, and traits).
|
|
486
|
-
*/
|
|
487
|
-
reset(): void {
|
|
488
|
-
this.userId = undefined;
|
|
489
|
-
this.anonymousId = undefined;
|
|
490
|
-
this.traits = {};
|
|
491
|
-
sdkLogger.debug("Client state reset");
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Flush all queued log records to the backend.
|
|
496
|
-
*
|
|
497
|
-
* @returns A promise that resolves once the flush completes.
|
|
498
|
-
*/
|
|
499
|
-
async flush(): Promise<void> {
|
|
500
|
-
await this.loggerProvider.forceFlush();
|
|
501
|
-
sdkLogger.debug("Flushed pending log records");
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Shut down the client, flushing all pending log records.
|
|
506
|
-
*
|
|
507
|
-
* @returns A promise that resolves once shutdown is complete.
|
|
508
|
-
*/
|
|
112
|
+
/** Close the underlying HTTP client. */
|
|
509
113
|
async shutdown(): Promise<void> {
|
|
510
|
-
|
|
114
|
+
// HttpClient has no persistent connections to close, but reserved
|
|
115
|
+
// for future use (e.g. agent keep-alive pools).
|
|
511
116
|
sdkLogger.debug("IntrospectionClient shutdown complete");
|
|
512
117
|
}
|
|
513
118
|
}
|
package/src/converters/claude.ts
CHANGED
|
@@ -228,6 +228,10 @@ export interface ClaudeSessionData {
|
|
|
228
228
|
toolNames?: string[];
|
|
229
229
|
/** System instructions / system prompt */
|
|
230
230
|
systemInstructions?: string;
|
|
231
|
+
/** Tokens read from the LLM prompt cache */
|
|
232
|
+
cacheReadInputTokens?: number;
|
|
233
|
+
/** Tokens written to the LLM prompt cache */
|
|
234
|
+
cacheCreationInputTokens?: number;
|
|
231
235
|
}
|
|
232
236
|
|
|
233
237
|
/**
|
|
@@ -280,6 +284,12 @@ export function convertClaudeSessionToGenAI(
|
|
|
280
284
|
if (data.outputTokens !== undefined) {
|
|
281
285
|
result.outputTokens = data.outputTokens;
|
|
282
286
|
}
|
|
287
|
+
if (data.cacheReadInputTokens !== undefined) {
|
|
288
|
+
result.cacheReadInputTokens = data.cacheReadInputTokens;
|
|
289
|
+
}
|
|
290
|
+
if (data.cacheCreationInputTokens !== undefined) {
|
|
291
|
+
result.cacheCreationInputTokens = data.cacheCreationInputTokens;
|
|
292
|
+
}
|
|
283
293
|
|
|
284
294
|
// Set response ID
|
|
285
295
|
if (data.responseId) {
|
|
@@ -318,7 +328,7 @@ export function convertClaudeSessionToGenAI(
|
|
|
318
328
|
*/
|
|
319
329
|
export function convertClaudeSessionToOtelAttributes(
|
|
320
330
|
data: ClaudeSessionData,
|
|
321
|
-
): Record<string, string | number> {
|
|
331
|
+
): Record<string, string | number | string[] | number[]> {
|
|
322
332
|
const genaiAttrs = convertClaudeSessionToGenAI(data);
|
|
323
333
|
const result = toAttributes(genaiAttrs);
|
|
324
334
|
|