@llmops/sdk 0.5.4 → 0.6.0

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.
@@ -0,0 +1,155 @@
1
+ //#region src/telemetry/agents-exporter.d.ts
2
+ /**
3
+ * LLMOps Tracing Exporter for @openai/agents
4
+ *
5
+ * Implements the TracingExporter interface from @openai/agents-core, converting
6
+ * the agents framework's Trace/Span format to OTLP JSON and sending it to
7
+ * the LLMOps OTLP ingestion endpoint.
8
+ *
9
+ * No dependency on @openai/agents — types are defined inline using structural
10
+ * compatibility (same pattern as the OTel exporter).
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { createLLMOpsAgentsExporter } from '@llmops/sdk';
15
+ * import { setTraceProcessors, BatchTraceProcessor } from '@openai/agents';
16
+ *
17
+ * const exporter = createLLMOpsAgentsExporter({
18
+ * baseURL: 'http://localhost:5177',
19
+ * apiKey: process.env.LLMOPS_API_KEY!,
20
+ * });
21
+ *
22
+ * setTraceProcessors([new BatchTraceProcessor(exporter)]);
23
+ *
24
+ * // All @openai/agents traces now flow to LLMOps automatically
25
+ * ```
26
+ */
27
+ /** Matches TracingExporter from @openai/agents-core */
28
+ interface AgentsTracingExporter {
29
+ export(items: (AgentsTrace | AgentsSpan)[], signal?: AbortSignal): Promise<void>;
30
+ }
31
+ /** Matches Trace from @openai/agents-core */
32
+ interface AgentsTrace {
33
+ type: 'trace';
34
+ traceId: string;
35
+ name: string;
36
+ groupId?: string | null;
37
+ metadata?: Record<string, unknown>;
38
+ }
39
+ /** Matches SpanError from @openai/agents-core */
40
+ interface AgentsSpanError {
41
+ message: string;
42
+ data?: Record<string, unknown>;
43
+ }
44
+ /** Matches Span from @openai/agents-core */
45
+ interface AgentsSpan {
46
+ type: 'trace.span';
47
+ spanId: string;
48
+ traceId: string;
49
+ parentId?: string | null;
50
+ startedAt?: string | null;
51
+ endedAt?: string | null;
52
+ error?: AgentsSpanError | null;
53
+ spanData: AgentsSpanData;
54
+ }
55
+ type AgentSpanData = {
56
+ type: 'agent';
57
+ name: string;
58
+ handoffs?: string[];
59
+ tools?: string[];
60
+ output_type?: string;
61
+ };
62
+ type FunctionSpanData = {
63
+ type: 'function';
64
+ name: string;
65
+ input: string;
66
+ output: string;
67
+ mcp_data?: string;
68
+ };
69
+ type GenerationUsageData = {
70
+ input_tokens?: number;
71
+ output_tokens?: number;
72
+ details?: Record<string, unknown> | null;
73
+ [key: string]: unknown;
74
+ };
75
+ type GenerationSpanData = {
76
+ type: 'generation';
77
+ input?: Record<string, unknown>[];
78
+ output?: Record<string, unknown>[];
79
+ model?: string;
80
+ model_config?: Record<string, unknown>;
81
+ usage?: GenerationUsageData;
82
+ };
83
+ type ResponseSpanData = {
84
+ type: 'response';
85
+ response_id?: string;
86
+ [key: string]: unknown;
87
+ };
88
+ type HandoffSpanData = {
89
+ type: 'handoff';
90
+ from_agent?: string;
91
+ to_agent?: string;
92
+ };
93
+ type CustomSpanData = {
94
+ type: 'custom';
95
+ name: string;
96
+ data: Record<string, unknown>;
97
+ };
98
+ type GuardrailSpanData = {
99
+ type: 'guardrail';
100
+ name: string;
101
+ triggered: boolean;
102
+ };
103
+ type TranscriptionSpanData = {
104
+ type: 'transcription';
105
+ input: unknown;
106
+ output?: string;
107
+ model?: string;
108
+ model_config?: Record<string, unknown>;
109
+ };
110
+ type SpeechSpanData = {
111
+ type: 'speech';
112
+ input?: string;
113
+ output: unknown;
114
+ model?: string;
115
+ model_config?: Record<string, unknown>;
116
+ };
117
+ type SpeechGroupSpanData = {
118
+ type: 'speech_group';
119
+ input?: string;
120
+ };
121
+ type MCPListToolsSpanData = {
122
+ type: 'mcp_tools';
123
+ server?: string;
124
+ result?: string[];
125
+ };
126
+ type AgentsSpanData = AgentSpanData | FunctionSpanData | GenerationSpanData | ResponseSpanData | HandoffSpanData | CustomSpanData | GuardrailSpanData | TranscriptionSpanData | SpeechSpanData | SpeechGroupSpanData | MCPListToolsSpanData;
127
+ interface LLMOpsAgentsExporterConfig {
128
+ /** LLMOps server base URL (e.g. http://localhost:5177) */
129
+ baseURL: string;
130
+ /** Environment secret or API key for authentication */
131
+ apiKey: string;
132
+ /** Custom headers to include in requests */
133
+ headers?: Record<string, string>;
134
+ /** Custom fetch implementation (used internally by client.agentsExporter()) */
135
+ fetch?: typeof globalThis.fetch;
136
+ }
137
+ /**
138
+ * Create a TracingExporter for @openai/agents that sends traces to LLMOps.
139
+ *
140
+ * Usage:
141
+ * ```typescript
142
+ * import { createLLMOpsAgentsExporter } from '@llmops/sdk';
143
+ * import { setTraceProcessors, BatchTraceProcessor } from '@openai/agents';
144
+ *
145
+ * setTraceProcessors([
146
+ * new BatchTraceProcessor(createLLMOpsAgentsExporter({
147
+ * baseURL: 'http://localhost:5177',
148
+ * apiKey: process.env.LLMOPS_API_KEY!,
149
+ * }))
150
+ * ]);
151
+ * ```
152
+ */
153
+ declare function createLLMOpsAgentsExporter(config: LLMOpsAgentsExporterConfig): AgentsTracingExporter;
154
+ //#endregion
155
+ export { AgentsTracingExporter as a, AgentsTrace as i, AgentsSpanData as n, LLMOpsAgentsExporterConfig as o, AgentsSpanError as r, createLLMOpsAgentsExporter as s, AgentsSpan as t };
@@ -0,0 +1,3 @@
1
+ const require_agents_exporter = require('./agents-exporter-Ct3l12qS.cjs');
2
+
3
+ exports.createLLMOpsAgentsExporter = require_agents_exporter.createLLMOpsAgentsExporter;
@@ -0,0 +1,2 @@
1
+ import { a as AgentsTracingExporter, i as AgentsTrace, n as AgentsSpanData, o as LLMOpsAgentsExporterConfig, r as AgentsSpanError, s as createLLMOpsAgentsExporter, t as AgentsSpan } from "./agents-exporter-DvECkYQd.cjs";
2
+ export { AgentsSpan, AgentsSpanData, AgentsSpanError, AgentsTrace, AgentsTracingExporter, LLMOpsAgentsExporterConfig, createLLMOpsAgentsExporter };
@@ -0,0 +1,2 @@
1
+ import { a as AgentsTracingExporter, i as AgentsTrace, n as AgentsSpanData, o as LLMOpsAgentsExporterConfig, r as AgentsSpanError, s as createLLMOpsAgentsExporter, t as AgentsSpan } from "./agents-exporter-DIoxRgjd.mjs";
2
+ export { AgentsSpan, AgentsSpanData, AgentsSpanError, AgentsTrace, AgentsTracingExporter, LLMOpsAgentsExporterConfig, createLLMOpsAgentsExporter };
@@ -0,0 +1,3 @@
1
+ import { t as createLLMOpsAgentsExporter } from "./agents-exporter-BorGCb93.mjs";
2
+
3
+ export { createLLMOpsAgentsExporter };
@@ -1,3 +1,4 @@
1
- import "./index-De3QdpKX.cjs";
2
- import { t as createLLMOpsMiddleware } from "./index-CHeoSGK0.cjs";
1
+ import "./agents-exporter-DvECkYQd.cjs";
2
+ import "./index-D49MVTAo.cjs";
3
+ import { t as createLLMOpsMiddleware } from "./index-DVTO0Hbl.cjs";
3
4
  export { createLLMOpsMiddleware };
@@ -1,3 +1,4 @@
1
- import "./index-BkLZoEW_.mjs";
2
- import { t as createLLMOpsMiddleware } from "./index-bdFT7Yxj.mjs";
1
+ import "./agents-exporter-DIoxRgjd.mjs";
2
+ import "./index-CelQx4B3.mjs";
3
+ import { t as createLLMOpsMiddleware } from "./index-CmC2x4dU.mjs";
3
4
  export { createLLMOpsMiddleware };
package/dist/express.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { t as createLLMOpsMiddleware } from "./express-Dz3xwxkh.mjs";
1
+ import { t as createLLMOpsMiddleware } from "./express-ClEIbLM9.mjs";
2
2
 
3
3
  export { createLLMOpsMiddleware };
package/dist/hono.d.cts CHANGED
@@ -1,4 +1,5 @@
1
- import { t as LLMOpsClient } from "./index-De3QdpKX.cjs";
1
+ import "./agents-exporter-DvECkYQd.cjs";
2
+ import { t as LLMOpsClient } from "./index-D49MVTAo.cjs";
2
3
  import { MiddlewareHandler } from "hono";
3
4
 
4
5
  //#region src/lib/hono/index.d.ts
package/dist/hono.d.mts CHANGED
@@ -1,4 +1,5 @@
1
- import { t as LLMOpsClient } from "./index-BkLZoEW_.mjs";
1
+ import "./agents-exporter-DIoxRgjd.mjs";
2
+ import { t as LLMOpsClient } from "./index-CelQx4B3.mjs";
2
3
  import { MiddlewareHandler } from "hono";
3
4
 
4
5
  //#region src/lib/hono/index.d.ts
@@ -0,0 +1,26 @@
1
+ import { a as AgentsTracingExporter } from "./agents-exporter-DIoxRgjd.mjs";
2
+ import { LLMOpsConfig, ValidatedLLMOpsConfig } from "@llmops/core";
3
+
4
+ //#region src/client/index.d.ts
5
+ type ProviderConfig = {
6
+ baseURL: string;
7
+ apiKey: string;
8
+ fetch: typeof globalThis.fetch;
9
+ };
10
+ type TraceContext = {
11
+ traceId?: string;
12
+ spanName?: string;
13
+ traceName?: string;
14
+ };
15
+ type ProviderOptions = {
16
+ traceContext?: () => TraceContext | null;
17
+ };
18
+ type LLMOpsClient = {
19
+ handler: (request: Request) => Promise<Response>;
20
+ config: ValidatedLLMOpsConfig;
21
+ provider: (options?: ProviderOptions) => ProviderConfig;
22
+ agentsExporter: () => AgentsTracingExporter;
23
+ };
24
+ declare const createLLMOps: (config?: LLMOpsConfig) => LLMOpsClient;
25
+ //#endregion
26
+ export { createLLMOps as i, ProviderOptions as n, TraceContext as r, LLMOpsClient as t };
@@ -1,4 +1,4 @@
1
- import { t as LLMOpsClient } from "./index-BkLZoEW_.mjs";
1
+ import { t as LLMOpsClient } from "./index-CelQx4B3.mjs";
2
2
  import { NextFunction, Request, Response } from "express";
3
3
 
4
4
  //#region src/lib/express/index.d.ts
@@ -0,0 +1,26 @@
1
+ import { a as AgentsTracingExporter } from "./agents-exporter-DvECkYQd.cjs";
2
+ import { LLMOpsConfig, ValidatedLLMOpsConfig } from "@llmops/core";
3
+
4
+ //#region src/client/index.d.ts
5
+ type ProviderConfig = {
6
+ baseURL: string;
7
+ apiKey: string;
8
+ fetch: typeof globalThis.fetch;
9
+ };
10
+ type TraceContext = {
11
+ traceId?: string;
12
+ spanName?: string;
13
+ traceName?: string;
14
+ };
15
+ type ProviderOptions = {
16
+ traceContext?: () => TraceContext | null;
17
+ };
18
+ type LLMOpsClient = {
19
+ handler: (request: Request) => Promise<Response>;
20
+ config: ValidatedLLMOpsConfig;
21
+ provider: (options?: ProviderOptions) => ProviderConfig;
22
+ agentsExporter: () => AgentsTracingExporter;
23
+ };
24
+ declare const createLLMOps: (config?: LLMOpsConfig) => LLMOpsClient;
25
+ //#endregion
26
+ export { createLLMOps as i, ProviderOptions as n, TraceContext as r, LLMOpsClient as t };
@@ -1,4 +1,4 @@
1
- import { t as LLMOpsClient } from "./index-De3QdpKX.cjs";
1
+ import { t as LLMOpsClient } from "./index-D49MVTAo.cjs";
2
2
  import { NextFunction, Request, Response } from "express";
3
3
 
4
4
  //#region src/lib/express/index.d.ts
package/dist/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  const require_express = require('./express-B-wbCza5.cjs');
2
- require("@llmops/core");
2
+ const require_agents_exporter = require('./agents-exporter-Ct3l12qS.cjs');
3
+ let __llmops_core = require("@llmops/core");
3
4
  let __llmops_app = require("@llmops/app");
4
5
 
5
6
  //#region src/lib/auth/client.ts
@@ -19,24 +20,166 @@ const createLLMOps = (config) => {
19
20
  const { app, config: validatedConfig } = (0, __llmops_app.createApp)(config);
20
21
  const handler = async (req) => app.fetch(req, void 0, void 0);
21
22
  const basePath = validatedConfig.basePath;
22
- const internalFetch = (input, init) => {
23
- const request = new Request(input, init);
24
- const url = new URL(request.url);
25
- if (basePath && basePath !== "/" && url.pathname.startsWith(basePath)) url.pathname = url.pathname.slice(basePath.length) || "/";
26
- return handler(new Request(url.toString(), request));
23
+ const createInternalFetch = (getTraceContext) => {
24
+ return (input, init) => {
25
+ const request = new Request(input, init);
26
+ const url = new URL(request.url);
27
+ if (basePath && basePath !== "/" && url.pathname.startsWith(basePath)) url.pathname = url.pathname.slice(basePath.length) || "/";
28
+ if (getTraceContext) {
29
+ const ctx = getTraceContext();
30
+ if (ctx) {
31
+ const headers = new Headers(request.headers);
32
+ if (ctx.traceId) headers.set(__llmops_core.LLMOPS_TRACE_ID_HEADER, ctx.traceId);
33
+ if (ctx.traceName) headers.set(__llmops_core.LLMOPS_TRACE_NAME_HEADER, ctx.traceName);
34
+ if (ctx.spanName) headers.set(__llmops_core.LLMOPS_SPAN_NAME_HEADER, ctx.spanName);
35
+ return handler(new Request(url.toString(), {
36
+ method: request.method,
37
+ headers,
38
+ body: request.body,
39
+ duplex: "half"
40
+ }));
41
+ }
42
+ }
43
+ return handler(new Request(url.toString(), request));
44
+ };
27
45
  };
28
46
  return {
29
47
  handler,
30
48
  config: Object.freeze(validatedConfig),
31
- provider: () => ({
49
+ provider: (options) => ({
32
50
  baseURL: `http://localhost${basePath}/api/genai/v1`,
33
51
  apiKey: "llmops",
34
- fetch: internalFetch
52
+ fetch: createInternalFetch(options?.traceContext)
53
+ }),
54
+ agentsExporter: () => require_agents_exporter.createLLMOpsAgentsExporter({
55
+ baseURL: `http://localhost${basePath}`,
56
+ apiKey: "llmops",
57
+ fetch: createInternalFetch()
35
58
  })
36
59
  };
37
60
  };
38
61
 
62
+ //#endregion
63
+ //#region src/telemetry/exporter.ts
64
+ let ExportResultCode = /* @__PURE__ */ function(ExportResultCode$1) {
65
+ ExportResultCode$1[ExportResultCode$1["SUCCESS"] = 0] = "SUCCESS";
66
+ ExportResultCode$1[ExportResultCode$1["FAILED"] = 1] = "FAILED";
67
+ return ExportResultCode$1;
68
+ }({});
69
+ /**
70
+ * Convert a value to OTLP attribute value format
71
+ */
72
+ function toOtlpValue(value) {
73
+ if (typeof value === "string") return { stringValue: value };
74
+ if (typeof value === "number") return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
75
+ if (typeof value === "boolean") return { boolValue: value };
76
+ if (Array.isArray(value)) return { arrayValue: { values: value.map((v) => toOtlpValue(v)) } };
77
+ if (typeof value === "object" && value !== null) try {
78
+ return { stringValue: JSON.stringify(value) };
79
+ } catch {
80
+ return { stringValue: String(value) };
81
+ }
82
+ return { stringValue: String(value) };
83
+ }
84
+ /**
85
+ * Convert HrTime [seconds, nanoseconds] to nanosecond string
86
+ */
87
+ function hrTimeToNano(hrTime) {
88
+ return (BigInt(hrTime[0]) * BigInt(1e9) + BigInt(hrTime[1])).toString();
89
+ }
90
+ /**
91
+ * Create an OTel SpanExporter that sends spans to an LLMOps server.
92
+ */
93
+ function createLLMOpsSpanExporter(config) {
94
+ const url = `${config.baseURL.replace(/\/$/, "")}/api/otlp/v1/traces`;
95
+ return {
96
+ export(spans, resultCallback) {
97
+ const resourceMap = /* @__PURE__ */ new Map();
98
+ for (const span of spans) {
99
+ const resourceKey = JSON.stringify(span.resource.attributes);
100
+ const group = resourceMap.get(resourceKey) ?? [];
101
+ group.push(span);
102
+ resourceMap.set(resourceKey, group);
103
+ }
104
+ const body = { resourceSpans: Array.from(resourceMap.entries()).map(([resourceKey, group]) => {
105
+ const resourceAttrs = JSON.parse(resourceKey);
106
+ const scopeMap = /* @__PURE__ */ new Map();
107
+ for (const span of group) {
108
+ const scopeKey = `${span.instrumentationLibrary.name}:${span.instrumentationLibrary.version ?? ""}`;
109
+ const scopeGroup = scopeMap.get(scopeKey) ?? [];
110
+ scopeGroup.push(span);
111
+ scopeMap.set(scopeKey, scopeGroup);
112
+ }
113
+ return {
114
+ resource: { attributes: Object.entries(resourceAttrs).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
115
+ key,
116
+ value: toOtlpValue(value)
117
+ })) },
118
+ scopeSpans: Array.from(scopeMap.entries()).map(([, scopeGroup]) => ({
119
+ scope: {
120
+ name: scopeGroup[0].instrumentationLibrary.name,
121
+ version: scopeGroup[0].instrumentationLibrary.version ?? void 0
122
+ },
123
+ spans: scopeGroup.map((span) => {
124
+ const ctx = span.spanContext();
125
+ return {
126
+ traceId: ctx.traceId,
127
+ spanId: ctx.spanId,
128
+ parentSpanId: span.parentSpanId || void 0,
129
+ name: span.name,
130
+ kind: span.kind,
131
+ startTimeUnixNano: hrTimeToNano(span.startTime),
132
+ endTimeUnixNano: hrTimeToNano(span.endTime),
133
+ attributes: Object.entries(span.attributes).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
134
+ key,
135
+ value: toOtlpValue(value)
136
+ })),
137
+ events: span.events.map((event) => ({
138
+ name: event.name,
139
+ timeUnixNano: hrTimeToNano(event.time),
140
+ attributes: event.attributes ? Object.entries(event.attributes).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
141
+ key,
142
+ value: toOtlpValue(value)
143
+ })) : []
144
+ })),
145
+ status: {
146
+ code: span.status.code,
147
+ message: span.status.message ?? void 0
148
+ }
149
+ };
150
+ })
151
+ }))
152
+ };
153
+ }) };
154
+ fetch(url, {
155
+ method: "POST",
156
+ headers: {
157
+ "Content-Type": "application/json",
158
+ Authorization: `Bearer ${config.apiKey}`,
159
+ ...config.headers ?? {}
160
+ },
161
+ body: JSON.stringify(body)
162
+ }).then((res) => {
163
+ if (res.ok) resultCallback({ code: ExportResultCode.SUCCESS });
164
+ else resultCallback({
165
+ code: ExportResultCode.FAILED,
166
+ error: /* @__PURE__ */ new Error(`OTLP export failed: ${res.status}`)
167
+ });
168
+ }).catch((error) => {
169
+ resultCallback({
170
+ code: ExportResultCode.FAILED,
171
+ error: error instanceof Error ? error : new Error(String(error))
172
+ });
173
+ });
174
+ },
175
+ async shutdown() {},
176
+ async forceFlush() {}
177
+ };
178
+ }
179
+
39
180
  //#endregion
40
181
  exports.AuthFeatureNotAvailableError = AuthFeatureNotAvailableError;
182
+ exports.createLLMOpsAgentsExporter = require_agents_exporter.createLLMOpsAgentsExporter;
41
183
  exports.createLLMOpsMiddleware = require_express.createLLMOpsMiddleware;
184
+ exports.createLLMOpsSpanExporter = createLLMOpsSpanExporter;
42
185
  exports.llmops = createLLMOps;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
- import { n as createLLMOps, t as LLMOpsClient } from "./index-De3QdpKX.cjs";
2
- import { t as createLLMOpsMiddleware } from "./index-CHeoSGK0.cjs";
1
+ import { a as AgentsTracingExporter, o as LLMOpsAgentsExporterConfig, s as createLLMOpsAgentsExporter } from "./agents-exporter-DvECkYQd.cjs";
2
+ import { i as createLLMOps, n as ProviderOptions, r as TraceContext, t as LLMOpsClient } from "./index-D49MVTAo.cjs";
3
+ import { t as createLLMOpsMiddleware } from "./index-DVTO0Hbl.cjs";
3
4
 
4
5
  //#region src/lib/auth/client.d.ts
5
6
 
@@ -170,4 +171,93 @@ declare class AuthFeatureNotAvailableError extends Error {
170
171
  constructor(feature: string, authType: string);
171
172
  }
172
173
  //#endregion
173
- export { AuthClient, AuthFeatureNotAvailableError, type LLMOpsClient, PaginatedResponse, PaginationOptions, Permission, Session, User, createLLMOpsMiddleware, createLLMOps as llmops };
174
+ //#region src/telemetry/exporter.d.ts
175
+ /**
176
+ * LLMOps OTLP Span Exporter
177
+ *
178
+ * A lightweight OTel SpanExporter that sends spans to the LLMOps server's
179
+ * OTLP ingestion endpoint. Compatible with OpenTelemetry SDK.
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * import { createLLMOpsSpanExporter } from '@llmops/sdk/telemetry';
184
+ * import { NodeTracerProvider, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
185
+ *
186
+ * const provider = new NodeTracerProvider();
187
+ * provider.addSpanProcessor(
188
+ * new SimpleSpanProcessor(createLLMOpsSpanExporter({
189
+ * baseURL: process.env.LLMOPS_URL,
190
+ * apiKey: process.env.LLMOPS_API_KEY,
191
+ * }))
192
+ * );
193
+ * provider.register();
194
+ *
195
+ * // Now Vercel AI SDK spans automatically flow to LLMOps
196
+ * const result = await generateText({
197
+ * model: openai('gpt-4o'),
198
+ * prompt: 'Hello',
199
+ * experimental_telemetry: { isEnabled: true },
200
+ * });
201
+ * ```
202
+ */
203
+ /**
204
+ * Minimal OTel SpanExporter interface
205
+ * We don't depend on @opentelemetry/sdk-trace-base — just implement the interface
206
+ */
207
+ interface SpanExporter {
208
+ export(spans: ReadonlyArray<ReadableSpan>, resultCallback: (result: ExportResult) => void): void;
209
+ shutdown(): Promise<void>;
210
+ forceFlush?(): Promise<void>;
211
+ }
212
+ /** Subset of OTel ReadableSpan we consume */
213
+ interface ReadableSpan {
214
+ readonly spanContext: () => {
215
+ traceId: string;
216
+ spanId: string;
217
+ traceFlags: number;
218
+ };
219
+ readonly parentSpanId?: string;
220
+ readonly name: string;
221
+ readonly kind: number;
222
+ readonly startTime: [number, number];
223
+ readonly endTime: [number, number];
224
+ readonly status: {
225
+ code: number;
226
+ message?: string;
227
+ };
228
+ readonly attributes: Record<string, unknown>;
229
+ readonly events: ReadonlyArray<{
230
+ name: string;
231
+ time: [number, number];
232
+ attributes?: Record<string, unknown>;
233
+ }>;
234
+ readonly resource: {
235
+ attributes: Record<string, unknown>;
236
+ };
237
+ readonly instrumentationLibrary: {
238
+ name: string;
239
+ version?: string;
240
+ };
241
+ }
242
+ interface ExportResult {
243
+ code: ExportResultCode;
244
+ error?: Error;
245
+ }
246
+ declare enum ExportResultCode {
247
+ SUCCESS = 0,
248
+ FAILED = 1,
249
+ }
250
+ interface LLMOpsExporterConfig {
251
+ /** LLMOps server base URL (e.g. http://localhost:3000) */
252
+ baseURL: string;
253
+ /** Environment secret or API key for authentication */
254
+ apiKey: string;
255
+ /** Custom headers to include in requests */
256
+ headers?: Record<string, string>;
257
+ }
258
+ /**
259
+ * Create an OTel SpanExporter that sends spans to an LLMOps server.
260
+ */
261
+ declare function createLLMOpsSpanExporter(config: LLMOpsExporterConfig): SpanExporter;
262
+ //#endregion
263
+ export { type AgentsTracingExporter, AuthClient, AuthFeatureNotAvailableError, type LLMOpsAgentsExporterConfig, type LLMOpsClient, type LLMOpsExporterConfig, PaginatedResponse, PaginationOptions, Permission, type ProviderOptions, Session, type SpanExporter, type TraceContext, User, createLLMOpsAgentsExporter, createLLMOpsMiddleware, createLLMOpsSpanExporter, createLLMOps as llmops };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
- import { n as createLLMOps, t as LLMOpsClient } from "./index-BkLZoEW_.mjs";
2
- import { t as createLLMOpsMiddleware } from "./index-bdFT7Yxj.mjs";
1
+ import { a as AgentsTracingExporter, o as LLMOpsAgentsExporterConfig, s as createLLMOpsAgentsExporter } from "./agents-exporter-DIoxRgjd.mjs";
2
+ import { i as createLLMOps, n as ProviderOptions, r as TraceContext, t as LLMOpsClient } from "./index-CelQx4B3.mjs";
3
+ import { t as createLLMOpsMiddleware } from "./index-CmC2x4dU.mjs";
3
4
 
4
5
  //#region src/lib/auth/client.d.ts
5
6
 
@@ -170,4 +171,93 @@ declare class AuthFeatureNotAvailableError extends Error {
170
171
  constructor(feature: string, authType: string);
171
172
  }
172
173
  //#endregion
173
- export { AuthClient, AuthFeatureNotAvailableError, type LLMOpsClient, PaginatedResponse, PaginationOptions, Permission, Session, User, createLLMOpsMiddleware, createLLMOps as llmops };
174
+ //#region src/telemetry/exporter.d.ts
175
+ /**
176
+ * LLMOps OTLP Span Exporter
177
+ *
178
+ * A lightweight OTel SpanExporter that sends spans to the LLMOps server's
179
+ * OTLP ingestion endpoint. Compatible with OpenTelemetry SDK.
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * import { createLLMOpsSpanExporter } from '@llmops/sdk/telemetry';
184
+ * import { NodeTracerProvider, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-node';
185
+ *
186
+ * const provider = new NodeTracerProvider();
187
+ * provider.addSpanProcessor(
188
+ * new SimpleSpanProcessor(createLLMOpsSpanExporter({
189
+ * baseURL: process.env.LLMOPS_URL,
190
+ * apiKey: process.env.LLMOPS_API_KEY,
191
+ * }))
192
+ * );
193
+ * provider.register();
194
+ *
195
+ * // Now Vercel AI SDK spans automatically flow to LLMOps
196
+ * const result = await generateText({
197
+ * model: openai('gpt-4o'),
198
+ * prompt: 'Hello',
199
+ * experimental_telemetry: { isEnabled: true },
200
+ * });
201
+ * ```
202
+ */
203
+ /**
204
+ * Minimal OTel SpanExporter interface
205
+ * We don't depend on @opentelemetry/sdk-trace-base — just implement the interface
206
+ */
207
+ interface SpanExporter {
208
+ export(spans: ReadonlyArray<ReadableSpan>, resultCallback: (result: ExportResult) => void): void;
209
+ shutdown(): Promise<void>;
210
+ forceFlush?(): Promise<void>;
211
+ }
212
+ /** Subset of OTel ReadableSpan we consume */
213
+ interface ReadableSpan {
214
+ readonly spanContext: () => {
215
+ traceId: string;
216
+ spanId: string;
217
+ traceFlags: number;
218
+ };
219
+ readonly parentSpanId?: string;
220
+ readonly name: string;
221
+ readonly kind: number;
222
+ readonly startTime: [number, number];
223
+ readonly endTime: [number, number];
224
+ readonly status: {
225
+ code: number;
226
+ message?: string;
227
+ };
228
+ readonly attributes: Record<string, unknown>;
229
+ readonly events: ReadonlyArray<{
230
+ name: string;
231
+ time: [number, number];
232
+ attributes?: Record<string, unknown>;
233
+ }>;
234
+ readonly resource: {
235
+ attributes: Record<string, unknown>;
236
+ };
237
+ readonly instrumentationLibrary: {
238
+ name: string;
239
+ version?: string;
240
+ };
241
+ }
242
+ interface ExportResult {
243
+ code: ExportResultCode;
244
+ error?: Error;
245
+ }
246
+ declare enum ExportResultCode {
247
+ SUCCESS = 0,
248
+ FAILED = 1,
249
+ }
250
+ interface LLMOpsExporterConfig {
251
+ /** LLMOps server base URL (e.g. http://localhost:3000) */
252
+ baseURL: string;
253
+ /** Environment secret or API key for authentication */
254
+ apiKey: string;
255
+ /** Custom headers to include in requests */
256
+ headers?: Record<string, string>;
257
+ }
258
+ /**
259
+ * Create an OTel SpanExporter that sends spans to an LLMOps server.
260
+ */
261
+ declare function createLLMOpsSpanExporter(config: LLMOpsExporterConfig): SpanExporter;
262
+ //#endregion
263
+ export { type AgentsTracingExporter, AuthClient, AuthFeatureNotAvailableError, type LLMOpsAgentsExporterConfig, type LLMOpsClient, type LLMOpsExporterConfig, PaginatedResponse, PaginationOptions, Permission, type ProviderOptions, Session, type SpanExporter, type TraceContext, User, createLLMOpsAgentsExporter, createLLMOpsMiddleware, createLLMOpsSpanExporter, createLLMOps as llmops };