@llmops/sdk 0.5.2 → 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.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { t as createLLMOpsMiddleware } from "./express-Dz3xwxkh.mjs";
2
- import "@llmops/core";
1
+ import { t as createLLMOpsMiddleware } from "./express-ClEIbLM9.mjs";
2
+ import { t as createLLMOpsAgentsExporter } from "./agents-exporter-BBBF9nsM.mjs";
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
 
5
6
  //#region src/lib/auth/client.ts
@@ -19,22 +20,157 @@ const createLLMOps = (config) => {
19
20
  const { app, config: validatedConfig } = 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_TRACE_ID_HEADER, ctx.traceId);
33
+ if (ctx.traceName) headers.set(LLMOPS_TRACE_NAME_HEADER, ctx.traceName);
34
+ if (ctx.spanName) headers.set(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)
35
53
  })
36
54
  };
37
55
  };
38
56
 
39
57
  //#endregion
40
- export { AuthFeatureNotAvailableError, createLLMOpsMiddleware, createLLMOps as llmops };
58
+ //#region src/telemetry/exporter.ts
59
+ let ExportResultCode = /* @__PURE__ */ function(ExportResultCode$1) {
60
+ ExportResultCode$1[ExportResultCode$1["SUCCESS"] = 0] = "SUCCESS";
61
+ ExportResultCode$1[ExportResultCode$1["FAILED"] = 1] = "FAILED";
62
+ return ExportResultCode$1;
63
+ }({});
64
+ /**
65
+ * Convert a value to OTLP attribute value format
66
+ */
67
+ function toOtlpValue(value) {
68
+ if (typeof value === "string") return { stringValue: value };
69
+ if (typeof value === "number") return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
70
+ if (typeof value === "boolean") return { boolValue: value };
71
+ if (Array.isArray(value)) return { arrayValue: { values: value.map((v) => toOtlpValue(v)) } };
72
+ if (typeof value === "object" && value !== null) try {
73
+ return { stringValue: JSON.stringify(value) };
74
+ } catch {
75
+ return { stringValue: String(value) };
76
+ }
77
+ return { stringValue: String(value) };
78
+ }
79
+ /**
80
+ * Convert HrTime [seconds, nanoseconds] to nanosecond string
81
+ */
82
+ function hrTimeToNano(hrTime) {
83
+ return (BigInt(hrTime[0]) * BigInt(1e9) + BigInt(hrTime[1])).toString();
84
+ }
85
+ /**
86
+ * Create an OTel SpanExporter that sends spans to an LLMOps server.
87
+ */
88
+ function createLLMOpsSpanExporter(config) {
89
+ const url = `${config.baseURL.replace(/\/$/, "")}/api/otlp/v1/traces`;
90
+ return {
91
+ export(spans, resultCallback) {
92
+ const resourceMap = /* @__PURE__ */ new Map();
93
+ for (const span of spans) {
94
+ const resourceKey = JSON.stringify(span.resource.attributes);
95
+ const group = resourceMap.get(resourceKey) ?? [];
96
+ group.push(span);
97
+ resourceMap.set(resourceKey, group);
98
+ }
99
+ const body = { resourceSpans: Array.from(resourceMap.entries()).map(([resourceKey, group]) => {
100
+ const resourceAttrs = JSON.parse(resourceKey);
101
+ const scopeMap = /* @__PURE__ */ new Map();
102
+ for (const span of group) {
103
+ const scopeKey = `${span.instrumentationLibrary.name}:${span.instrumentationLibrary.version ?? ""}`;
104
+ const scopeGroup = scopeMap.get(scopeKey) ?? [];
105
+ scopeGroup.push(span);
106
+ scopeMap.set(scopeKey, scopeGroup);
107
+ }
108
+ return {
109
+ resource: { attributes: Object.entries(resourceAttrs).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
110
+ key,
111
+ value: toOtlpValue(value)
112
+ })) },
113
+ scopeSpans: Array.from(scopeMap.entries()).map(([, scopeGroup]) => ({
114
+ scope: {
115
+ name: scopeGroup[0].instrumentationLibrary.name,
116
+ version: scopeGroup[0].instrumentationLibrary.version ?? void 0
117
+ },
118
+ spans: scopeGroup.map((span) => {
119
+ const ctx = span.spanContext();
120
+ return {
121
+ traceId: ctx.traceId,
122
+ spanId: ctx.spanId,
123
+ parentSpanId: span.parentSpanId || void 0,
124
+ name: span.name,
125
+ kind: span.kind,
126
+ startTimeUnixNano: hrTimeToNano(span.startTime),
127
+ endTimeUnixNano: hrTimeToNano(span.endTime),
128
+ attributes: Object.entries(span.attributes).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
129
+ key,
130
+ value: toOtlpValue(value)
131
+ })),
132
+ events: span.events.map((event) => ({
133
+ name: event.name,
134
+ timeUnixNano: hrTimeToNano(event.time),
135
+ attributes: event.attributes ? Object.entries(event.attributes).filter(([, v]) => v !== void 0 && v !== null).map(([key, value]) => ({
136
+ key,
137
+ value: toOtlpValue(value)
138
+ })) : []
139
+ })),
140
+ status: {
141
+ code: span.status.code,
142
+ message: span.status.message ?? void 0
143
+ }
144
+ };
145
+ })
146
+ }))
147
+ };
148
+ }) };
149
+ fetch(url, {
150
+ method: "POST",
151
+ headers: {
152
+ "Content-Type": "application/json",
153
+ Authorization: `Bearer ${config.apiKey}`,
154
+ ...config.headers ?? {}
155
+ },
156
+ body: JSON.stringify(body)
157
+ }).then((res) => {
158
+ if (res.ok) resultCallback({ code: ExportResultCode.SUCCESS });
159
+ else resultCallback({
160
+ code: ExportResultCode.FAILED,
161
+ error: /* @__PURE__ */ new Error(`OTLP export failed: ${res.status}`)
162
+ });
163
+ }).catch((error) => {
164
+ resultCallback({
165
+ code: ExportResultCode.FAILED,
166
+ error: error instanceof Error ? error : new Error(String(error))
167
+ });
168
+ });
169
+ },
170
+ async shutdown() {},
171
+ async forceFlush() {}
172
+ };
173
+ }
174
+
175
+ //#endregion
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-De3QdpKX.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-BkLZoEW_.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.2",
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.2",
78
- "@llmops/app": "^0.5.2"
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",