@llmops/sdk 0.5.3-beta.1 → 0.5.3-beta.2

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/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
- import { i as createLLMOps, n as ProviderOptions, r as TraceContext, t as LLMOpsClient } from "./index-BvYAMh37.mjs";
2
- import { t as createLLMOpsMiddleware } from "./index-CoflKbMf.mjs";
1
+ import { i as createLLMOps, n as ProviderOptions, r as TraceContext, t as LLMOpsClient } from "./index-BjzrptNm.mjs";
2
+ import { t as createLLMOpsMiddleware } from "./index-BJayNg2a.mjs";
3
+ import { a as AgentsTracingExporter, o as LLMOpsAgentsExporterConfig, s as createLLMOpsAgentsExporter } from "./agents-exporter-COsWSriQ.mjs";
3
4
 
4
5
  //#region src/lib/auth/client.d.ts
5
6
 
@@ -259,156 +260,4 @@ interface LLMOpsExporterConfig {
259
260
  */
260
261
  declare function createLLMOpsSpanExporter(config: LLMOpsExporterConfig): SpanExporter;
261
262
  //#endregion
262
- //#region src/telemetry/agents-exporter.d.ts
263
- /**
264
- * LLMOps Tracing Exporter for @openai/agents
265
- *
266
- * Implements the TracingExporter interface from @openai/agents-core, converting
267
- * the agents framework's Trace/Span format to OTLP JSON and sending it to
268
- * the LLMOps OTLP ingestion endpoint.
269
- *
270
- * No dependency on @openai/agents — types are defined inline using structural
271
- * compatibility (same pattern as the OTel exporter).
272
- *
273
- * @example
274
- * ```typescript
275
- * import { createLLMOpsAgentsExporter } from '@llmops/sdk';
276
- * import { setTraceProcessors, BatchTraceProcessor } from '@openai/agents';
277
- *
278
- * const exporter = createLLMOpsAgentsExporter({
279
- * baseURL: 'http://localhost:5177',
280
- * apiKey: process.env.LLMOPS_API_KEY!,
281
- * });
282
- *
283
- * setTraceProcessors([new BatchTraceProcessor(exporter)]);
284
- *
285
- * // All @openai/agents traces now flow to LLMOps automatically
286
- * ```
287
- */
288
- /** Matches TracingExporter from @openai/agents-core */
289
- interface AgentsTracingExporter {
290
- export(items: (AgentsTrace | AgentsSpan)[], signal?: AbortSignal): Promise<void>;
291
- }
292
- /** Matches Trace from @openai/agents-core */
293
- interface AgentsTrace {
294
- type: 'trace';
295
- traceId: string;
296
- name: string;
297
- groupId?: string | null;
298
- metadata?: Record<string, unknown>;
299
- }
300
- /** Matches SpanError from @openai/agents-core */
301
- interface AgentsSpanError {
302
- message: string;
303
- data?: Record<string, unknown>;
304
- }
305
- /** Matches Span from @openai/agents-core */
306
- interface AgentsSpan {
307
- type: 'trace.span';
308
- spanId: string;
309
- traceId: string;
310
- parentId?: string | null;
311
- startedAt?: string | null;
312
- endedAt?: string | null;
313
- error?: AgentsSpanError | null;
314
- spanData: AgentsSpanData;
315
- }
316
- type AgentSpanData = {
317
- type: 'agent';
318
- name: string;
319
- handoffs?: string[];
320
- tools?: string[];
321
- output_type?: string;
322
- };
323
- type FunctionSpanData = {
324
- type: 'function';
325
- name: string;
326
- input: string;
327
- output: string;
328
- mcp_data?: string;
329
- };
330
- type GenerationUsageData = {
331
- input_tokens?: number;
332
- output_tokens?: number;
333
- details?: Record<string, unknown> | null;
334
- [key: string]: unknown;
335
- };
336
- type GenerationSpanData = {
337
- type: 'generation';
338
- input?: Record<string, unknown>[];
339
- output?: Record<string, unknown>[];
340
- model?: string;
341
- model_config?: Record<string, unknown>;
342
- usage?: GenerationUsageData;
343
- };
344
- type ResponseSpanData = {
345
- type: 'response';
346
- response_id?: string;
347
- [key: string]: unknown;
348
- };
349
- type HandoffSpanData = {
350
- type: 'handoff';
351
- from_agent?: string;
352
- to_agent?: string;
353
- };
354
- type CustomSpanData = {
355
- type: 'custom';
356
- name: string;
357
- data: Record<string, unknown>;
358
- };
359
- type GuardrailSpanData = {
360
- type: 'guardrail';
361
- name: string;
362
- triggered: boolean;
363
- };
364
- type TranscriptionSpanData = {
365
- type: 'transcription';
366
- input: unknown;
367
- output?: string;
368
- model?: string;
369
- model_config?: Record<string, unknown>;
370
- };
371
- type SpeechSpanData = {
372
- type: 'speech';
373
- input?: string;
374
- output: unknown;
375
- model?: string;
376
- model_config?: Record<string, unknown>;
377
- };
378
- type SpeechGroupSpanData = {
379
- type: 'speech_group';
380
- input?: string;
381
- };
382
- type MCPListToolsSpanData = {
383
- type: 'mcp_tools';
384
- server?: string;
385
- result?: string[];
386
- };
387
- type AgentsSpanData = AgentSpanData | FunctionSpanData | GenerationSpanData | ResponseSpanData | HandoffSpanData | CustomSpanData | GuardrailSpanData | TranscriptionSpanData | SpeechSpanData | SpeechGroupSpanData | MCPListToolsSpanData;
388
- interface LLMOpsAgentsExporterConfig {
389
- /** LLMOps server base URL (e.g. http://localhost:5177) */
390
- baseURL: string;
391
- /** Environment secret or API key for authentication */
392
- apiKey: string;
393
- /** Custom headers to include in requests */
394
- headers?: Record<string, string>;
395
- }
396
- /**
397
- * Create a TracingExporter for @openai/agents that sends traces to LLMOps.
398
- *
399
- * Usage:
400
- * ```typescript
401
- * import { createLLMOpsAgentsExporter } from '@llmops/sdk';
402
- * import { setTraceProcessors, BatchTraceProcessor } from '@openai/agents';
403
- *
404
- * setTraceProcessors([
405
- * new BatchTraceProcessor(createLLMOpsAgentsExporter({
406
- * baseURL: 'http://localhost:5177',
407
- * apiKey: process.env.LLMOPS_API_KEY!,
408
- * }))
409
- * ]);
410
- * ```
411
- */
412
- declare function createLLMOpsAgentsExporter(config: LLMOpsAgentsExporterConfig): AgentsTracingExporter;
413
- //#endregion
414
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.mjs CHANGED
@@ -1,4 +1,5 @@
1
- import { t as createLLMOpsMiddleware } from "./express-Dz3xwxkh.mjs";
1
+ import { t as createLLMOpsMiddleware } from "./express-ClEIbLM9.mjs";
2
+ import { t as createLLMOpsAgentsExporter } from "./agents-exporter-BBBF9nsM.mjs";
2
3
  import { LLMOPS_SPAN_NAME_HEADER, LLMOPS_TRACE_ID_HEADER, LLMOPS_TRACE_NAME_HEADER } from "@llmops/core";
3
4
  import { createApp } from "@llmops/app";
4
5
 
@@ -63,11 +64,11 @@ let ExportResultCode = /* @__PURE__ */ function(ExportResultCode$1) {
63
64
  /**
64
65
  * Convert a value to OTLP attribute value format
65
66
  */
66
- function toOtlpValue$1(value) {
67
+ function toOtlpValue(value) {
67
68
  if (typeof value === "string") return { stringValue: value };
68
69
  if (typeof value === "number") return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
69
70
  if (typeof value === "boolean") return { boolValue: value };
70
- if (Array.isArray(value)) return { arrayValue: { values: value.map((v) => toOtlpValue$1(v)) } };
71
+ if (Array.isArray(value)) return { arrayValue: { values: value.map((v) => toOtlpValue(v)) } };
71
72
  if (typeof value === "object" && value !== null) try {
72
73
  return { stringValue: JSON.stringify(value) };
73
74
  } catch {
@@ -107,7 +108,7 @@ function createLLMOpsSpanExporter(config) {
107
108
  return {
108
109
  resource: { attributes: Object.entries(resourceAttrs).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
109
110
  key,
110
- value: toOtlpValue$1(value)
111
+ value: toOtlpValue(value)
111
112
  })) },
112
113
  scopeSpans: Array.from(scopeMap.entries()).map(([, scopeGroup]) => ({
113
114
  scope: {
@@ -126,14 +127,14 @@ function createLLMOpsSpanExporter(config) {
126
127
  endTimeUnixNano: hrTimeToNano(span.endTime),
127
128
  attributes: Object.entries(span.attributes).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
128
129
  key,
129
- value: toOtlpValue$1(value)
130
+ value: toOtlpValue(value)
130
131
  })),
131
132
  events: span.events.map((event) => ({
132
133
  name: event.name,
133
134
  timeUnixNano: hrTimeToNano(event.time),
134
135
  attributes: event.attributes ? Object.entries(event.attributes).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
135
136
  key,
136
- value: toOtlpValue$1(value)
137
+ value: toOtlpValue(value)
137
138
  })) : []
138
139
  })),
139
140
  status: {
@@ -171,210 +172,5 @@ function createLLMOpsSpanExporter(config) {
171
172
  };
172
173
  }
173
174
 
174
- //#endregion
175
- //#region src/telemetry/agents-exporter.ts
176
- function normalizeTraceId(id) {
177
- return id.startsWith("trace_") ? id.slice(6) : id;
178
- }
179
- function normalizeSpanId(id) {
180
- return id.startsWith("span_") ? id.slice(5) : id;
181
- }
182
- function isoToNano(iso) {
183
- if (!iso) return "0";
184
- const ms = new Date(iso).getTime();
185
- if (isNaN(ms)) return "0";
186
- return (BigInt(ms) * BigInt(1e6)).toString();
187
- }
188
- function toOtlpValue(value) {
189
- if (typeof value === "string") return { stringValue: value };
190
- if (typeof value === "number") return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
191
- if (typeof value === "boolean") return { boolValue: value };
192
- if (Array.isArray(value)) return { arrayValue: { values: value.map((v) => toOtlpValue(v)) } };
193
- if (typeof value === "object" && value !== null) try {
194
- return { stringValue: JSON.stringify(value) };
195
- } catch {
196
- return { stringValue: String(value) };
197
- }
198
- return { stringValue: String(value) };
199
- }
200
- function kv(key, value) {
201
- return {
202
- key,
203
- value: toOtlpValue(value)
204
- };
205
- }
206
- /**
207
- * Derive a human-readable span name from the span data type.
208
- */
209
- function deriveSpanName(data) {
210
- switch (data.type) {
211
- case "agent": return `Agent: ${data.name}`;
212
- case "function": return `Tool: ${data.name}`;
213
- case "generation": return data.model ? `Generation: ${data.model}` : "Generation";
214
- case "response": return "Response";
215
- case "handoff": return `Handoff: ${data.from_agent ?? "?"} → ${data.to_agent ?? "?"}`;
216
- case "guardrail": return `Guardrail: ${data.name}`;
217
- case "custom": return `Custom: ${data.name}`;
218
- case "transcription": return data.model ? `Transcription: ${data.model}` : "Transcription";
219
- case "speech": return data.model ? `Speech: ${data.model}` : "Speech";
220
- case "speech_group": return "Speech Group";
221
- case "mcp_tools": return `MCP Tools: ${data.server ?? "unknown"}`;
222
- default: return "Unknown Span";
223
- }
224
- }
225
- /**
226
- * Convert span data fields to OTLP attributes that our UI's getSpanType() recognizes.
227
- */
228
- function convertSpanDataToAttributes(data, error) {
229
- const attrs = [kv("openai.agents.span_type", data.type)];
230
- switch (data.type) {
231
- case "generation":
232
- attrs.push(kv("gen_ai.operation.name", "chat"));
233
- if (data.model) {
234
- attrs.push(kv("gen_ai.request.model", data.model));
235
- attrs.push(kv("gen_ai.system", "openai"));
236
- }
237
- if (data.usage?.input_tokens != null) attrs.push(kv("gen_ai.usage.input_tokens", data.usage.input_tokens));
238
- if (data.usage?.output_tokens != null) attrs.push(kv("gen_ai.usage.output_tokens", data.usage.output_tokens));
239
- if (data.input) attrs.push(kv("ai.prompt.messages", JSON.stringify(data.input)));
240
- if (data.output) attrs.push(kv("gen_ai.completion", JSON.stringify(data.output)));
241
- if (data.model_config) attrs.push(kv("gen_ai.request.model_config", JSON.stringify(data.model_config)));
242
- break;
243
- case "agent":
244
- attrs.push(kv("openai.agents.agent.name", data.name));
245
- if (data.tools?.length) attrs.push(kv("openai.agents.agent.tools", JSON.stringify(data.tools)));
246
- if (data.handoffs?.length) attrs.push(kv("openai.agents.agent.handoffs", JSON.stringify(data.handoffs)));
247
- if (data.output_type) attrs.push(kv("openai.agents.agent.output_type", data.output_type));
248
- break;
249
- case "function":
250
- attrs.push(kv("gen_ai.tool.name", data.name));
251
- if (data.input) attrs.push(kv("ai.prompt.messages", data.input));
252
- if (data.output) attrs.push(kv("ai.response.text", data.output));
253
- if (data.mcp_data) attrs.push(kv("openai.agents.function.mcp_data", data.mcp_data));
254
- break;
255
- case "handoff":
256
- if (data.from_agent) attrs.push(kv("openai.agents.handoff.from_agent", data.from_agent));
257
- if (data.to_agent) attrs.push(kv("openai.agents.handoff.to_agent", data.to_agent));
258
- break;
259
- case "guardrail":
260
- attrs.push(kv("llmops.guardrail.action", data.triggered ? "triggered" : "passed"));
261
- attrs.push(kv("openai.agents.guardrail.name", data.name));
262
- break;
263
- case "response":
264
- attrs.push(kv("gen_ai.operation.name", "chat"));
265
- if (data.response_id) attrs.push(kv("openai.agents.response.id", data.response_id));
266
- break;
267
- case "custom":
268
- attrs.push(kv("openai.agents.custom.name", data.name));
269
- attrs.push(kv("openai.agents.custom.data", JSON.stringify(data.data)));
270
- break;
271
- case "transcription":
272
- attrs.push(kv("gen_ai.operation.name", "transcription"));
273
- if (data.model) attrs.push(kv("gen_ai.request.model", data.model));
274
- if (data.output) attrs.push(kv("ai.response.text", data.output));
275
- break;
276
- case "speech":
277
- attrs.push(kv("gen_ai.operation.name", "speech"));
278
- if (data.model) attrs.push(kv("gen_ai.request.model", data.model));
279
- if (data.input) attrs.push(kv("ai.prompt.messages", data.input));
280
- break;
281
- case "speech_group":
282
- if (data.input) attrs.push(kv("openai.agents.speech_group.input", data.input));
283
- break;
284
- case "mcp_tools":
285
- attrs.push(kv("gen_ai.tool.name", `mcp:${data.server ?? "unknown"}`));
286
- if (data.result) attrs.push(kv("openai.agents.mcp.tools", JSON.stringify(data.result)));
287
- break;
288
- }
289
- if (error) {
290
- attrs.push(kv("error.message", error.message));
291
- if (error.data) attrs.push(kv("error.data", JSON.stringify(error.data)));
292
- }
293
- return attrs;
294
- }
295
- function buildResourceSpans(traceId, trace, spans) {
296
- const resourceAttrs = [kv("service.name", "@openai/agents")];
297
- if (trace) {
298
- resourceAttrs.push(kv("openai.agents.trace.name", trace.name));
299
- if (trace.groupId) resourceAttrs.push(kv("openai.agents.trace.group_id", trace.groupId));
300
- if (trace.metadata && Object.keys(trace.metadata).length > 0) resourceAttrs.push(kv("openai.agents.trace.metadata", JSON.stringify(trace.metadata)));
301
- }
302
- const normalizedTraceId = normalizeTraceId(traceId);
303
- return {
304
- resource: { attributes: resourceAttrs },
305
- scopeSpans: [{
306
- scope: { name: "@llmops/agents-exporter" },
307
- spans: spans.map((span) => {
308
- const isError = !!span.error;
309
- return {
310
- traceId: normalizedTraceId,
311
- spanId: normalizeSpanId(span.spanId),
312
- parentSpanId: span.parentId ? normalizeSpanId(span.parentId) : void 0,
313
- name: deriveSpanName(span.spanData),
314
- kind: 1,
315
- startTimeUnixNano: isoToNano(span.startedAt),
316
- endTimeUnixNano: isoToNano(span.endedAt),
317
- attributes: convertSpanDataToAttributes(span.spanData, span.error),
318
- events: [],
319
- status: isError ? {
320
- code: 2,
321
- message: span.error.message
322
- } : { code: 1 }
323
- };
324
- })
325
- }]
326
- };
327
- }
328
- /**
329
- * Create a TracingExporter for @openai/agents that sends traces to LLMOps.
330
- *
331
- * Usage:
332
- * ```typescript
333
- * import { createLLMOpsAgentsExporter } from '@llmops/sdk';
334
- * import { setTraceProcessors, BatchTraceProcessor } from '@openai/agents';
335
- *
336
- * setTraceProcessors([
337
- * new BatchTraceProcessor(createLLMOpsAgentsExporter({
338
- * baseURL: 'http://localhost:5177',
339
- * apiKey: process.env.LLMOPS_API_KEY!,
340
- * }))
341
- * ]);
342
- * ```
343
- */
344
- function createLLMOpsAgentsExporter(config) {
345
- const url = `${config.baseURL.replace(/\/$/, "")}/api/otlp/v1/traces`;
346
- return { async export(items, signal) {
347
- const traces = [];
348
- const spans = [];
349
- for (const item of items) if (item.type === "trace") traces.push(item);
350
- else spans.push(item);
351
- if (spans.length === 0) return;
352
- const traceMap = /* @__PURE__ */ new Map();
353
- for (const t of traces) traceMap.set(t.traceId, t);
354
- const spansByTrace = /* @__PURE__ */ new Map();
355
- for (const s of spans) {
356
- const group = spansByTrace.get(s.traceId) ?? [];
357
- group.push(s);
358
- spansByTrace.set(s.traceId, group);
359
- }
360
- const resourceSpans = [];
361
- for (const [traceId, traceSpans] of spansByTrace) {
362
- const trace = traceMap.get(traceId);
363
- resourceSpans.push(buildResourceSpans(traceId, trace, traceSpans));
364
- }
365
- if (resourceSpans.length === 0) return;
366
- await fetch(url, {
367
- method: "POST",
368
- headers: {
369
- "Content-Type": "application/json",
370
- Authorization: `Bearer ${config.apiKey}`,
371
- ...config.headers ?? {}
372
- },
373
- body: JSON.stringify({ resourceSpans }),
374
- signal
375
- });
376
- } };
377
- }
378
-
379
175
  //#endregion
380
176
  export { AuthFeatureNotAvailableError, createLLMOpsAgentsExporter, createLLMOpsMiddleware, createLLMOpsSpanExporter, createLLMOps as llmops };
package/dist/nextjs.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as LLMOpsClient } from "./index-DdwqBi1V.cjs";
1
+ import { t as LLMOpsClient } from "./index-BDb3GYHs.cjs";
2
2
 
3
3
  //#region src/lib/nextjs/index.d.ts
4
4
  declare function toNextJsHandler(client: LLMOpsClient): {
package/dist/nextjs.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as LLMOpsClient } from "./index-BvYAMh37.mjs";
1
+ import { t as LLMOpsClient } from "./index-BjzrptNm.mjs";
2
2
 
3
3
  //#region src/lib/nextjs/index.d.ts
4
4
  declare function toNextJsHandler(client: LLMOpsClient): {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmops/sdk",
3
- "version": "0.5.3-beta.1",
3
+ "version": "0.5.3-beta.2",
4
4
  "description": "An LLMOps toolkit for TypeScript applications",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -38,6 +38,16 @@
38
38
  "default": "./dist/index.cjs"
39
39
  }
40
40
  },
41
+ "./agents": {
42
+ "import": {
43
+ "types": "./dist/agents.d.mts",
44
+ "default": "./dist/agents.mjs"
45
+ },
46
+ "require": {
47
+ "types": "./dist/agents.d.cts",
48
+ "default": "./dist/agents.cjs"
49
+ }
50
+ },
41
51
  "./express": {
42
52
  "import": {
43
53
  "types": "./dist/express.d.mts",
@@ -74,8 +84,8 @@
74
84
  "access": "public"
75
85
  },
76
86
  "dependencies": {
77
- "@llmops/core": "^0.5.3-beta.1",
78
- "@llmops/app": "^0.5.3-beta.1"
87
+ "@llmops/core": "^0.5.3-beta.2",
88
+ "@llmops/app": "^0.5.3-beta.2"
79
89
  },
80
90
  "devDependencies": {
81
91
  "@types/express": "^5.0.6",