@nexuscore/nexus-ai-sdk 0.1.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.
- package/dist/index.cjs +201 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +179 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
NexusAISDK: () => NexusAISDK
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/wrap.ts
|
|
28
|
+
function wrap(ai, context = null) {
|
|
29
|
+
const withTelemetry = (options) => ({
|
|
30
|
+
...options,
|
|
31
|
+
experimental_telemetry: { isEnabled: true, metadata: context }
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
generateText: (options) => ai.generateText(withTelemetry(options)),
|
|
35
|
+
streamText: (options) => ai.streamText(withTelemetry(options)),
|
|
36
|
+
generateObject: (options) => ai.generateObject(withTelemetry(options)),
|
|
37
|
+
streamObject: (options) => ai.streamObject(withTelemetry(options)),
|
|
38
|
+
embed: (options) => ai.embed(withTelemetry(options)),
|
|
39
|
+
embedMany: (options) => ai.embedMany(withTelemetry(options))
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/traces_db.ts
|
|
44
|
+
var import_serverless = require("@neondatabase/serverless");
|
|
45
|
+
var import_neon_http = require("drizzle-orm/neon-http");
|
|
46
|
+
var import_pg_core = require("drizzle-orm/pg-core");
|
|
47
|
+
var import_drizzle_zod = require("drizzle-zod");
|
|
48
|
+
var db = (0, import_neon_http.drizzle)((0, import_serverless.neon)("postgresql://neondb_owner:npg_MLsCg7kA4BzV@ep-late-morning-ahnpf6h2-pooler.c-3.us-east-1.aws.neon.tech/neondb?sslmode=require&channel_binding=require"));
|
|
49
|
+
var agentLogs = (0, import_pg_core.pgTable)("agent_logs", {
|
|
50
|
+
runId: (0, import_pg_core.text)("run_id").notNull().primaryKey(),
|
|
51
|
+
userId: (0, import_pg_core.uuid)("user_id").notNull(),
|
|
52
|
+
traceId: (0, import_pg_core.text)("trace_id").notNull(),
|
|
53
|
+
parentRunId: (0, import_pg_core.text)("parent_run_id"),
|
|
54
|
+
eventType: (0, import_pg_core.text)("event_type"),
|
|
55
|
+
name: (0, import_pg_core.text)("name"),
|
|
56
|
+
input: (0, import_pg_core.json)("input"),
|
|
57
|
+
output: (0, import_pg_core.json)("output"),
|
|
58
|
+
error: (0, import_pg_core.text)("error"),
|
|
59
|
+
agentType: (0, import_pg_core.text)("agent_type").default("ai"),
|
|
60
|
+
spanMetadata: (0, import_pg_core.text)("span_metadata")
|
|
61
|
+
});
|
|
62
|
+
var insertTraceSchema = (0, import_drizzle_zod.createInsertSchema)(agentLogs);
|
|
63
|
+
async function insertTrace(trace) {
|
|
64
|
+
try {
|
|
65
|
+
await db.insert(agentLogs).values(trace);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/export_store.ts
|
|
72
|
+
var NexusExporter = class {
|
|
73
|
+
batch = [];
|
|
74
|
+
writeKey;
|
|
75
|
+
devMode;
|
|
76
|
+
API_URL = "https://nexus-agent-api-fast-endpoint-production.up.railway.app/catch_route_manual";
|
|
77
|
+
constructor({ writeKey, devMode }) {
|
|
78
|
+
this.writeKey = writeKey;
|
|
79
|
+
this.devMode = devMode;
|
|
80
|
+
}
|
|
81
|
+
triggerAnalysis(trace_id) {
|
|
82
|
+
if (!this.devMode) {
|
|
83
|
+
try {
|
|
84
|
+
const params = new URLSearchParams({
|
|
85
|
+
user_id: this.writeKey,
|
|
86
|
+
trace_id
|
|
87
|
+
}).toString();
|
|
88
|
+
fetch(`${this.API_URL}?${params}`, {
|
|
89
|
+
method: "POST"
|
|
90
|
+
});
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error("Error triggering analysis", error);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// OTEL calls this automatically when a span completes
|
|
97
|
+
export(spans, resultCallback) {
|
|
98
|
+
for (const span of spans) {
|
|
99
|
+
const attrs = span.attributes;
|
|
100
|
+
const name = span.name;
|
|
101
|
+
let input = null;
|
|
102
|
+
let output = null;
|
|
103
|
+
switch (name) {
|
|
104
|
+
// Tool execution
|
|
105
|
+
case "ai.toolCall":
|
|
106
|
+
input = attrs["ai.toolCall.args"] ?? null;
|
|
107
|
+
output = attrs["ai.toolCall.result"] ?? null;
|
|
108
|
+
break;
|
|
109
|
+
// Model calls (inner spans)
|
|
110
|
+
case "ai.generateText.doGenerate":
|
|
111
|
+
case "ai.streamText.doStream":
|
|
112
|
+
case "ai.generateObject.doGenerate":
|
|
113
|
+
case "ai.streamObject.doStream":
|
|
114
|
+
input = attrs["ai.prompt.messages"] ?? null;
|
|
115
|
+
output = attrs["ai.response.text"] ?? null;
|
|
116
|
+
break;
|
|
117
|
+
// Embedding calls (inner spans)
|
|
118
|
+
case "ai.embed.doEmbed":
|
|
119
|
+
case "ai.embedMany.doEmbed":
|
|
120
|
+
input = attrs["ai.values"] ?? null;
|
|
121
|
+
output = attrs["ai.embeddings"] ?? null;
|
|
122
|
+
break;
|
|
123
|
+
// Root spans
|
|
124
|
+
case "ai.generateText":
|
|
125
|
+
case "ai.streamText":
|
|
126
|
+
case "ai.generateObject":
|
|
127
|
+
case "ai.streamObject":
|
|
128
|
+
input = attrs["ai.prompt"] ?? null;
|
|
129
|
+
output = attrs["ai.response.text"] ?? null;
|
|
130
|
+
break;
|
|
131
|
+
case "ai.embed":
|
|
132
|
+
case "ai.embedMany":
|
|
133
|
+
input = attrs["ai.values"] ?? null;
|
|
134
|
+
output = attrs["ai.embeddings"] ?? null;
|
|
135
|
+
break;
|
|
136
|
+
default:
|
|
137
|
+
input = attrs["ai.prompt"] ?? attrs["ai.prompt.messages"] ?? null;
|
|
138
|
+
output = attrs["ai.response.text"] ?? null;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
const [dSec, dNano] = span._duration ?? [0, 0];
|
|
142
|
+
const duration_s = dSec + dNano / 1e9;
|
|
143
|
+
const parts = [`${duration_s}s`];
|
|
144
|
+
if (attrs["ai.usage.promptTokens"] != null) {
|
|
145
|
+
parts.push(`in: ${attrs["ai.usage.promptTokens"]} tokens`);
|
|
146
|
+
}
|
|
147
|
+
if (attrs["ai.usage.completionTokens"] != null) {
|
|
148
|
+
parts.push(`out: ${attrs["ai.usage.completionTokens"]} tokens`);
|
|
149
|
+
}
|
|
150
|
+
this.batch.push({
|
|
151
|
+
runId: span.spanContext().spanId,
|
|
152
|
+
userId: this.writeKey,
|
|
153
|
+
traceId: span.spanContext().traceId,
|
|
154
|
+
parentRunId: span.parentSpanContext?.spanId ?? null,
|
|
155
|
+
eventType: name,
|
|
156
|
+
name,
|
|
157
|
+
input: input ? JSON.parse(input) : null,
|
|
158
|
+
output: output ? JSON.parse(output) : null,
|
|
159
|
+
error: null,
|
|
160
|
+
agentType: "vercel",
|
|
161
|
+
spanMetadata: parts.join(", ")
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
resultCallback({ code: 0 });
|
|
165
|
+
}
|
|
166
|
+
// POST to nexus
|
|
167
|
+
async flush() {
|
|
168
|
+
await insertTrace(this.batch);
|
|
169
|
+
if (this.batch.length > 0) {
|
|
170
|
+
let trace_id = this.batch[0].traceId;
|
|
171
|
+
this.triggerAnalysis(trace_id);
|
|
172
|
+
}
|
|
173
|
+
this.batch = [];
|
|
174
|
+
}
|
|
175
|
+
// OTEL calls this on shutdown
|
|
176
|
+
async shutdown() {
|
|
177
|
+
await this.flush();
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// src/index.ts
|
|
182
|
+
var import_sdk_node = require("@opentelemetry/sdk-node");
|
|
183
|
+
var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
|
|
184
|
+
function NexusAISDK(api_key) {
|
|
185
|
+
const exporter = new NexusExporter({ writeKey: api_key, devMode: false });
|
|
186
|
+
const sdk = new import_sdk_node.NodeSDK({
|
|
187
|
+
spanProcessors: [
|
|
188
|
+
new import_sdk_trace_base.SimpleSpanProcessor(exporter)
|
|
189
|
+
]
|
|
190
|
+
});
|
|
191
|
+
sdk.start();
|
|
192
|
+
return {
|
|
193
|
+
wrap,
|
|
194
|
+
flush: () => exporter.flush()
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
198
|
+
0 && (module.exports = {
|
|
199
|
+
NexusAISDK
|
|
200
|
+
});
|
|
201
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/wrap.ts","../src/traces_db.ts","../src/export_store.ts"],"sourcesContent":["import { wrap } from \"./wrap\";\nimport { NexusExporter } from \"./export_store\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { SimpleSpanProcessor } from \"@opentelemetry/sdk-trace-base\"\n\nexport function NexusAISDK(api_key: string){\n const exporter = new NexusExporter({ writeKey: api_key, devMode: false });\n\n const sdk = new NodeSDK({\n spanProcessors: [\n new SimpleSpanProcessor(exporter)\n ]\n })\n \n sdk.start()\n\n return {\n wrap,\n flush: () => exporter.flush()\n }\n}","\nexport function wrap(ai:any, context:any=null){\n const withTelemetry = (options:any) => ({\n ...options,\n experimental_telemetry: {isEnabled: true, metadata: context}\n });\n\n return {\n generateText: (options:any) => ai.generateText(withTelemetry(options)),\n streamText: (options:any) => ai.streamText(withTelemetry(options)),\n generateObject: (options:any) => ai.generateObject(withTelemetry(options)),\n streamObject: (options:any) => ai.streamObject(withTelemetry(options)),\n embed: (options:any) => ai.embed(withTelemetry(options)),\n embedMany: (options:any) => ai.embedMany(withTelemetry(options)),\n }\n}","import { neon } from '@neondatabase/serverless';\nimport { drizzle } from 'drizzle-orm/neon-http';\nimport {\n pgTable,\n text,\n json,\n uuid,\n} from 'drizzle-orm/pg-core';\nimport { and, eq } from 'drizzle-orm';\nimport { createInsertSchema } from 'drizzle-zod';\n\n// export const db = drizzle(neon(process.env.POSTGRES_URL!));\n\nexport const db = drizzle(neon(\"postgresql://neondb_owner:npg_MLsCg7kA4BzV@ep-late-morning-ahnpf6h2-pooler.c-3.us-east-1.aws.neon.tech/neondb?sslmode=require&channel_binding=require\"));\n\nexport const agentLogs = pgTable('agent_logs', {\n runId: text('run_id').notNull().primaryKey(),\n userId: uuid('user_id').notNull(),\n traceId: text('trace_id').notNull(),\n parentRunId: text('parent_run_id'),\n eventType: text('event_type'),\n name: text('name'),\n input: json('input'),\n output: json('output'),\n error: text('error'),\n agentType: text('agent_type').default('ai'),\n spanMetadata: text('span_metadata'),\n});\n\nexport type SelectTrace = typeof agentLogs.$inferSelect;\n// Note: insertTraceSchema is exported but not used - it's just a schema definition for validation, no database writes\nexport const insertTraceSchema = createInsertSchema(agentLogs);\n\n// Get all unique traces for a user\n// READ-ONLY: Only performs SELECT queries, does not modify database\n// export async function getTraces(userId: string): Promise<SelectTrace[]> {\n// try {\n// // Get distinct trace_ids for the user\n// const distinctTraces = await db\n// .selectDistinct({ traceId: agentLogs.traceId })\n// .from(agentLogs)\n// .where(eq(agentLogs.userId, userId));\n\n// // For each trace_id, get the first run (or a representative run)\n// const traces = await Promise.all(\n// distinctTraces.map(async ({ traceId }) => {\n// const firstRun = await db\n// .select()\n// .from(agentLogs)\n// .where(\n// and(\n// eq(agentLogs.userId, userId),\n// eq(agentLogs.traceId, traceId)\n// )\n// )\n// .limit(1);\n// return firstRun[0];\n// })\n// );\n\n// return traces.filter(Boolean) as SelectTrace[];\n// } catch (error: any) {\n// // Handle case where database schema doesn't match (column doesn't exist)\n// if (error?.code === '42703' || error?.message?.includes('does not exist') || error?.message?.includes('trace_id')) {\n// console.warn('Database schema mismatch: agent_logs table does not have the expected columns. Please ensure the table has run_id, user_id, trace_id, and other required columns.');\n// return [];\n// }\n// // Re-throw other errors\n// throw error;\n// }\n// }\n\n// // Get all spans (runs) for a specific trace_id\n// // READ-ONLY: Only performs SELECT queries, does not modify database\n// export async function getSpansByTraceId(\n// traceId: string,\n// userId: string\n// ): Promise<SelectTrace[]> {\n// try {\n// return await db\n// .select()\n// .from(agentLogs)\n// .where(\n// and(\n// eq(agentLogs.userId, userId),\n// eq(agentLogs.traceId, traceId)\n// )\n// )\n// .orderBy(agentLogs.runId);\n// } catch (error: any) {\n// // Handle case where database schema doesn't match\n// if (error?.code === '42703' || error?.message?.includes('does not exist') || error?.message?.includes('trace_id')) {\n// console.warn('Database schema mismatch: agent_logs table does not have the expected columns.');\n// return [];\n// }\n// throw error;\n// }\n// }\n\n// // Get a single trace/span by run_id\n// // READ-ONLY: Only performs SELECT queries, does not modify database\n// export async function getTraceByRunId(\n// runId: string,\n// userId: string\n// ): Promise<SelectTrace | null> {\n// try {\n// const result = await db\n// .select()\n// .from(agentLogs)\n// .where(\n// and(\n// eq(agentLogs.runId, runId),\n// eq(agentLogs.userId, userId)\n// )\n// )\n// .limit(1);\n \n// return result[0] || null;\n// } catch (error: any) {\n// // Handle case where database schema doesn't match\n// if (error?.code === '42703' || error?.message?.includes('does not exist') || error?.message?.includes('trace_id') || error?.message?.includes('run_id')) {\n// console.warn('Database schema mismatch: agent_logs table does not have the expected columns.');\n// return null;\n// }\n// throw error;\n// }\n// }\n\nexport async function insertTrace(trace: SelectTrace[]) {\n try {\n await db.insert(agentLogs).values(trace);\n } catch (error: any) {\n throw error;\n }\n}\n","import { SpanExporter } from \"@opentelemetry/sdk-trace-base\";\nimport { insertTrace, SelectTrace } from \"./traces_db\";\nexport class NexusExporter implements SpanExporter {\n private batch:SelectTrace[] = []\n private writeKey: string\n private devMode: boolean\n\n private API_URL: string = \"https://nexus-agent-api-fast-endpoint-production.up.railway.app/catch_route_manual\"\n\n constructor({ writeKey, devMode }: { writeKey: string, devMode: boolean }) {\n this.writeKey = writeKey\n this.devMode = devMode\n }\n \n private triggerAnalysis(trace_id: string) {\n if (!this.devMode){\n try {\n const params = new URLSearchParams({\n user_id: this.writeKey,\n trace_id: trace_id\n }).toString();\n fetch(`${this.API_URL}?${params}`, {\n method: \"POST\"\n })\n } catch (error) {\n console.error(\"Error triggering analysis\", error)\n }\n }\n }\n // OTEL calls this automatically when a span completes\n export(spans: any, resultCallback: any) {\n for (const span of spans) {\n const attrs = span.attributes;\n const name = span.name;\n\n let input: string | null = null;\n let output: string | null = null;\n\n switch (name) {\n // Tool execution\n case 'ai.toolCall':\n input = attrs[\"ai.toolCall.args\"] ?? null;\n output = attrs[\"ai.toolCall.result\"] ?? null;\n break;\n\n // Model calls (inner spans)\n case 'ai.generateText.doGenerate':\n case 'ai.streamText.doStream':\n case 'ai.generateObject.doGenerate':\n case 'ai.streamObject.doStream':\n input = attrs[\"ai.prompt.messages\"] ?? null;\n output = attrs[\"ai.response.text\"] ?? null;\n break;\n\n // Embedding calls (inner spans)\n case 'ai.embed.doEmbed':\n case 'ai.embedMany.doEmbed':\n input = attrs[\"ai.values\"] ?? null;\n output = attrs[\"ai.embeddings\"] ?? null;\n break;\n\n // Root spans\n case 'ai.generateText':\n case 'ai.streamText':\n case 'ai.generateObject':\n case 'ai.streamObject':\n input = attrs[\"ai.prompt\"] ?? null;\n output = attrs[\"ai.response.text\"] ?? null;\n break;\n\n case 'ai.embed':\n case 'ai.embedMany':\n input = attrs[\"ai.values\"] ?? null;\n output = attrs[\"ai.embeddings\"] ?? null;\n break;\n\n default:\n input = attrs[\"ai.prompt\"] ?? attrs[\"ai.prompt.messages\"] ?? null;\n output = attrs[\"ai.response.text\"] ?? null;\n break;\n }\n\n // Build metadata string\n const [dSec, dNano] = span._duration ?? [0, 0];\n const duration_s = dSec + dNano / 1_000_000_000;\n const parts: string[] = [`${duration_s}s`];\n\n if (attrs[\"ai.usage.promptTokens\"] != null) {\n parts.push(`in: ${attrs[\"ai.usage.promptTokens\"]} tokens`);\n }\n if (attrs[\"ai.usage.completionTokens\"] != null) {\n parts.push(`out: ${attrs[\"ai.usage.completionTokens\"]} tokens`);\n }\n\n this.batch.push({\n runId: span.spanContext().spanId,\n userId: this.writeKey,\n traceId: span.spanContext().traceId,\n parentRunId: span.parentSpanContext?.spanId ?? null,\n eventType: name,\n name: name,\n input: input ? JSON.parse(input) : null,\n output: output ? JSON.parse(output) : null,\n error: null,\n agentType: \"vercel\",\n spanMetadata: parts.join(\", \"),\n });\n }\n resultCallback({ code: 0 })\n }\n\n // POST to nexus\n async flush() {\n \n await insertTrace(this.batch);\n\n if (this.batch.length > 0){\n let trace_id = this.batch[0].traceId\n this.triggerAnalysis(trace_id)\n }\n\n this.batch = []\n }\n \n // OTEL calls this on shutdown\n async shutdown() {\n await this.flush()\n }\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCO,SAAS,KAAK,IAAQ,UAAY,MAAK;AAC1C,QAAM,gBAAgB,CAAC,aAAiB;AAAA,IACpC,GAAG;AAAA,IACH,wBAAwB,EAAC,WAAW,MAAM,UAAU,QAAO;AAAA,EAC/D;AAEA,SAAO;AAAA,IACH,cAAc,CAAC,YAAgB,GAAG,aAAa,cAAc,OAAO,CAAC;AAAA,IACrE,YAAY,CAAC,YAAgB,GAAG,WAAW,cAAc,OAAO,CAAC;AAAA,IACjE,gBAAgB,CAAC,YAAgB,GAAG,eAAe,cAAc,OAAO,CAAC;AAAA,IACzE,cAAc,CAAC,YAAgB,GAAG,aAAa,cAAc,OAAO,CAAC;AAAA,IACrE,OAAO,CAAC,YAAgB,GAAG,MAAM,cAAc,OAAO,CAAC;AAAA,IACvD,WAAW,CAAC,YAAgB,GAAG,UAAU,cAAc,OAAO,CAAC;AAAA,EACnE;AACJ;;;ACfA,wBAAqB;AACrB,uBAAwB;AACxB,qBAKO;AAEP,yBAAmC;AAI5B,IAAM,SAAK,8BAAQ,wBAAK,uJAAuJ,CAAC;AAEhL,IAAM,gBAAY,wBAAQ,cAAc;AAAA,EAC7C,WAAO,qBAAK,QAAQ,EAAE,QAAQ,EAAE,WAAW;AAAA,EAC3C,YAAQ,qBAAK,SAAS,EAAE,QAAQ;AAAA,EAChC,aAAS,qBAAK,UAAU,EAAE,QAAQ;AAAA,EAClC,iBAAa,qBAAK,eAAe;AAAA,EACjC,eAAW,qBAAK,YAAY;AAAA,EAC5B,UAAM,qBAAK,MAAM;AAAA,EACjB,WAAO,qBAAK,OAAO;AAAA,EACnB,YAAQ,qBAAK,QAAQ;AAAA,EACrB,WAAO,qBAAK,OAAO;AAAA,EACnB,eAAW,qBAAK,YAAY,EAAE,QAAQ,IAAI;AAAA,EAC1C,kBAAc,qBAAK,eAAe;AACpC,CAAC;AAIM,IAAM,wBAAoB,uCAAmB,SAAS;AAiG7D,eAAsB,YAAY,OAAsB;AACtD,MAAI;AACF,UAAM,GAAG,OAAO,SAAS,EAAE,OAAO,KAAK;AAAA,EACzC,SAAS,OAAY;AACnB,UAAM;AAAA,EACR;AACF;;;ACpIO,IAAM,gBAAN,MAA4C;AAAA,EACvC,QAAsB,CAAC;AAAA,EACvB;AAAA,EACA;AAAA,EAEA,UAAkB;AAAA,EAE1B,YAAY,EAAE,UAAU,QAAQ,GAA2C;AACzE,SAAK,WAAW;AAChB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,gBAAgB,UAAkB;AACtC,QAAI,CAAC,KAAK,SAAQ;AACd,UAAI;AACA,cAAM,SAAS,IAAI,gBAAgB;AAAA,UAC/B,SAAS,KAAK;AAAA,UACd;AAAA,QACJ,CAAC,EAAE,SAAS;AACZ,cAAM,GAAG,KAAK,OAAO,IAAI,MAAM,IAAI;AAAA,UAC/B,QAAQ;AAAA,QACZ,CAAC;AAAA,MACL,SAAS,OAAO;AACZ,gBAAQ,MAAM,6BAA6B,KAAK;AAAA,MACpD;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA,EAEA,OAAO,OAAY,gBAAqB;AACtC,eAAW,QAAQ,OAAO;AACxB,YAAM,QAAQ,KAAK;AACnB,YAAM,OAAO,KAAK;AAElB,UAAI,QAAuB;AAC3B,UAAI,SAAwB;AAE5B,cAAQ,MAAM;AAAA;AAAA,QAEZ,KAAK;AACH,kBAAQ,MAAM,kBAAkB,KAAK;AACrC,mBAAS,MAAM,oBAAoB,KAAK;AACxC;AAAA;AAAA,QAGF,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AACH,kBAAQ,MAAM,oBAAoB,KAAK;AACvC,mBAAS,MAAM,kBAAkB,KAAK;AACtC;AAAA;AAAA,QAGF,KAAK;AAAA,QACL,KAAK;AACH,kBAAQ,MAAM,WAAW,KAAK;AAC9B,mBAAS,MAAM,eAAe,KAAK;AACnC;AAAA;AAAA,QAGF,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AACH,kBAAQ,MAAM,WAAW,KAAK;AAC9B,mBAAS,MAAM,kBAAkB,KAAK;AACtC;AAAA,QAEF,KAAK;AAAA,QACL,KAAK;AACH,kBAAQ,MAAM,WAAW,KAAK;AAC9B,mBAAS,MAAM,eAAe,KAAK;AACnC;AAAA,QAEF;AACE,kBAAQ,MAAM,WAAW,KAAK,MAAM,oBAAoB,KAAK;AAC7D,mBAAS,MAAM,kBAAkB,KAAK;AACtC;AAAA,MACJ;AAGA,YAAM,CAAC,MAAM,KAAK,IAAI,KAAK,aAAa,CAAC,GAAG,CAAC;AAC7C,YAAM,aAAa,OAAO,QAAQ;AAClC,YAAM,QAAkB,CAAC,GAAG,UAAU,GAAG;AAEzC,UAAI,MAAM,uBAAuB,KAAK,MAAM;AAC1C,cAAM,KAAK,OAAO,MAAM,uBAAuB,CAAC,SAAS;AAAA,MAC3D;AACA,UAAI,MAAM,2BAA2B,KAAK,MAAM;AAC9C,cAAM,KAAK,QAAQ,MAAM,2BAA2B,CAAC,SAAS;AAAA,MAChE;AAEA,WAAK,MAAM,KAAK;AAAA,QACd,OAAO,KAAK,YAAY,EAAE;AAAA,QAC1B,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK,YAAY,EAAE;AAAA,QAC5B,aAAa,KAAK,mBAAmB,UAAU;AAAA,QAC/C,WAAW;AAAA,QACX;AAAA,QACA,OAAO,QAAQ,KAAK,MAAM,KAAK,IAAI;AAAA,QACnC,QAAQ,SAAS,KAAK,MAAM,MAAM,IAAI;AAAA,QACtC,OAAO;AAAA,QACP,WAAW;AAAA,QACX,cAAc,MAAM,KAAK,IAAI;AAAA,MAC/B,CAAC;AAAA,IACH;AACA,mBAAe,EAAE,MAAM,EAAE,CAAC;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,QAAQ;AAEZ,UAAM,YAAY,KAAK,KAAK;AAE5B,QAAI,KAAK,MAAM,SAAS,GAAE;AACxB,UAAI,WAAW,KAAK,MAAM,CAAC,EAAE;AAC7B,WAAK,gBAAgB,QAAQ;AAAA,IAC/B;AAEA,SAAK,QAAQ,CAAC;AAAA,EAChB;AAAA;AAAA,EAGA,MAAM,WAAW;AACf,UAAM,KAAK,MAAM;AAAA,EACnB;AACJ;;;AH9HA,sBAAwB;AACxB,4BAAoC;AAE7B,SAAS,WAAW,SAAgB;AACvC,QAAM,WAAW,IAAI,cAAc,EAAE,UAAU,SAAS,SAAS,MAAM,CAAC;AAExE,QAAM,MAAM,IAAI,wBAAQ;AAAA,IACpB,gBAAgB;AAAA,MACd,IAAI,0CAAoB,QAAQ;AAAA,IAClC;AAAA,EACJ,CAAC;AAED,MAAI,MAAM;AAEV,SAAO;AAAA,IACH;AAAA,IACA,OAAO,MAAM,SAAS,MAAM;AAAA,EAChC;AACJ;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare function wrap(ai: any, context?: any): {
|
|
2
|
+
generateText: (options: any) => any;
|
|
3
|
+
streamText: (options: any) => any;
|
|
4
|
+
generateObject: (options: any) => any;
|
|
5
|
+
streamObject: (options: any) => any;
|
|
6
|
+
embed: (options: any) => any;
|
|
7
|
+
embedMany: (options: any) => any;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
declare function NexusAISDK(api_key: string): {
|
|
11
|
+
wrap: typeof wrap;
|
|
12
|
+
flush: () => Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { NexusAISDK };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare function wrap(ai: any, context?: any): {
|
|
2
|
+
generateText: (options: any) => any;
|
|
3
|
+
streamText: (options: any) => any;
|
|
4
|
+
generateObject: (options: any) => any;
|
|
5
|
+
streamObject: (options: any) => any;
|
|
6
|
+
embed: (options: any) => any;
|
|
7
|
+
embedMany: (options: any) => any;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
declare function NexusAISDK(api_key: string): {
|
|
11
|
+
wrap: typeof wrap;
|
|
12
|
+
flush: () => Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { NexusAISDK };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// src/wrap.ts
|
|
2
|
+
function wrap(ai, context = null) {
|
|
3
|
+
const withTelemetry = (options) => ({
|
|
4
|
+
...options,
|
|
5
|
+
experimental_telemetry: { isEnabled: true, metadata: context }
|
|
6
|
+
});
|
|
7
|
+
return {
|
|
8
|
+
generateText: (options) => ai.generateText(withTelemetry(options)),
|
|
9
|
+
streamText: (options) => ai.streamText(withTelemetry(options)),
|
|
10
|
+
generateObject: (options) => ai.generateObject(withTelemetry(options)),
|
|
11
|
+
streamObject: (options) => ai.streamObject(withTelemetry(options)),
|
|
12
|
+
embed: (options) => ai.embed(withTelemetry(options)),
|
|
13
|
+
embedMany: (options) => ai.embedMany(withTelemetry(options))
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/traces_db.ts
|
|
18
|
+
import { neon } from "@neondatabase/serverless";
|
|
19
|
+
import { drizzle } from "drizzle-orm/neon-http";
|
|
20
|
+
import {
|
|
21
|
+
pgTable,
|
|
22
|
+
text,
|
|
23
|
+
json,
|
|
24
|
+
uuid
|
|
25
|
+
} from "drizzle-orm/pg-core";
|
|
26
|
+
import { createInsertSchema } from "drizzle-zod";
|
|
27
|
+
var db = drizzle(neon("postgresql://neondb_owner:npg_MLsCg7kA4BzV@ep-late-morning-ahnpf6h2-pooler.c-3.us-east-1.aws.neon.tech/neondb?sslmode=require&channel_binding=require"));
|
|
28
|
+
var agentLogs = pgTable("agent_logs", {
|
|
29
|
+
runId: text("run_id").notNull().primaryKey(),
|
|
30
|
+
userId: uuid("user_id").notNull(),
|
|
31
|
+
traceId: text("trace_id").notNull(),
|
|
32
|
+
parentRunId: text("parent_run_id"),
|
|
33
|
+
eventType: text("event_type"),
|
|
34
|
+
name: text("name"),
|
|
35
|
+
input: json("input"),
|
|
36
|
+
output: json("output"),
|
|
37
|
+
error: text("error"),
|
|
38
|
+
agentType: text("agent_type").default("ai"),
|
|
39
|
+
spanMetadata: text("span_metadata")
|
|
40
|
+
});
|
|
41
|
+
var insertTraceSchema = createInsertSchema(agentLogs);
|
|
42
|
+
async function insertTrace(trace) {
|
|
43
|
+
try {
|
|
44
|
+
await db.insert(agentLogs).values(trace);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/export_store.ts
|
|
51
|
+
var NexusExporter = class {
|
|
52
|
+
batch = [];
|
|
53
|
+
writeKey;
|
|
54
|
+
devMode;
|
|
55
|
+
API_URL = "https://nexus-agent-api-fast-endpoint-production.up.railway.app/catch_route_manual";
|
|
56
|
+
constructor({ writeKey, devMode }) {
|
|
57
|
+
this.writeKey = writeKey;
|
|
58
|
+
this.devMode = devMode;
|
|
59
|
+
}
|
|
60
|
+
triggerAnalysis(trace_id) {
|
|
61
|
+
if (!this.devMode) {
|
|
62
|
+
try {
|
|
63
|
+
const params = new URLSearchParams({
|
|
64
|
+
user_id: this.writeKey,
|
|
65
|
+
trace_id
|
|
66
|
+
}).toString();
|
|
67
|
+
fetch(`${this.API_URL}?${params}`, {
|
|
68
|
+
method: "POST"
|
|
69
|
+
});
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error("Error triggering analysis", error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// OTEL calls this automatically when a span completes
|
|
76
|
+
export(spans, resultCallback) {
|
|
77
|
+
for (const span of spans) {
|
|
78
|
+
const attrs = span.attributes;
|
|
79
|
+
const name = span.name;
|
|
80
|
+
let input = null;
|
|
81
|
+
let output = null;
|
|
82
|
+
switch (name) {
|
|
83
|
+
// Tool execution
|
|
84
|
+
case "ai.toolCall":
|
|
85
|
+
input = attrs["ai.toolCall.args"] ?? null;
|
|
86
|
+
output = attrs["ai.toolCall.result"] ?? null;
|
|
87
|
+
break;
|
|
88
|
+
// Model calls (inner spans)
|
|
89
|
+
case "ai.generateText.doGenerate":
|
|
90
|
+
case "ai.streamText.doStream":
|
|
91
|
+
case "ai.generateObject.doGenerate":
|
|
92
|
+
case "ai.streamObject.doStream":
|
|
93
|
+
input = attrs["ai.prompt.messages"] ?? null;
|
|
94
|
+
output = attrs["ai.response.text"] ?? null;
|
|
95
|
+
break;
|
|
96
|
+
// Embedding calls (inner spans)
|
|
97
|
+
case "ai.embed.doEmbed":
|
|
98
|
+
case "ai.embedMany.doEmbed":
|
|
99
|
+
input = attrs["ai.values"] ?? null;
|
|
100
|
+
output = attrs["ai.embeddings"] ?? null;
|
|
101
|
+
break;
|
|
102
|
+
// Root spans
|
|
103
|
+
case "ai.generateText":
|
|
104
|
+
case "ai.streamText":
|
|
105
|
+
case "ai.generateObject":
|
|
106
|
+
case "ai.streamObject":
|
|
107
|
+
input = attrs["ai.prompt"] ?? null;
|
|
108
|
+
output = attrs["ai.response.text"] ?? null;
|
|
109
|
+
break;
|
|
110
|
+
case "ai.embed":
|
|
111
|
+
case "ai.embedMany":
|
|
112
|
+
input = attrs["ai.values"] ?? null;
|
|
113
|
+
output = attrs["ai.embeddings"] ?? null;
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
input = attrs["ai.prompt"] ?? attrs["ai.prompt.messages"] ?? null;
|
|
117
|
+
output = attrs["ai.response.text"] ?? null;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
const [dSec, dNano] = span._duration ?? [0, 0];
|
|
121
|
+
const duration_s = dSec + dNano / 1e9;
|
|
122
|
+
const parts = [`${duration_s}s`];
|
|
123
|
+
if (attrs["ai.usage.promptTokens"] != null) {
|
|
124
|
+
parts.push(`in: ${attrs["ai.usage.promptTokens"]} tokens`);
|
|
125
|
+
}
|
|
126
|
+
if (attrs["ai.usage.completionTokens"] != null) {
|
|
127
|
+
parts.push(`out: ${attrs["ai.usage.completionTokens"]} tokens`);
|
|
128
|
+
}
|
|
129
|
+
this.batch.push({
|
|
130
|
+
runId: span.spanContext().spanId,
|
|
131
|
+
userId: this.writeKey,
|
|
132
|
+
traceId: span.spanContext().traceId,
|
|
133
|
+
parentRunId: span.parentSpanContext?.spanId ?? null,
|
|
134
|
+
eventType: name,
|
|
135
|
+
name,
|
|
136
|
+
input: input ? JSON.parse(input) : null,
|
|
137
|
+
output: output ? JSON.parse(output) : null,
|
|
138
|
+
error: null,
|
|
139
|
+
agentType: "vercel",
|
|
140
|
+
spanMetadata: parts.join(", ")
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
resultCallback({ code: 0 });
|
|
144
|
+
}
|
|
145
|
+
// POST to nexus
|
|
146
|
+
async flush() {
|
|
147
|
+
await insertTrace(this.batch);
|
|
148
|
+
if (this.batch.length > 0) {
|
|
149
|
+
let trace_id = this.batch[0].traceId;
|
|
150
|
+
this.triggerAnalysis(trace_id);
|
|
151
|
+
}
|
|
152
|
+
this.batch = [];
|
|
153
|
+
}
|
|
154
|
+
// OTEL calls this on shutdown
|
|
155
|
+
async shutdown() {
|
|
156
|
+
await this.flush();
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// src/index.ts
|
|
161
|
+
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
162
|
+
import { SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
163
|
+
function NexusAISDK(api_key) {
|
|
164
|
+
const exporter = new NexusExporter({ writeKey: api_key, devMode: false });
|
|
165
|
+
const sdk = new NodeSDK({
|
|
166
|
+
spanProcessors: [
|
|
167
|
+
new SimpleSpanProcessor(exporter)
|
|
168
|
+
]
|
|
169
|
+
});
|
|
170
|
+
sdk.start();
|
|
171
|
+
return {
|
|
172
|
+
wrap,
|
|
173
|
+
flush: () => exporter.flush()
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
export {
|
|
177
|
+
NexusAISDK
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wrap.ts","../src/traces_db.ts","../src/export_store.ts","../src/index.ts"],"sourcesContent":["\nexport function wrap(ai:any, context:any=null){\n const withTelemetry = (options:any) => ({\n ...options,\n experimental_telemetry: {isEnabled: true, metadata: context}\n });\n\n return {\n generateText: (options:any) => ai.generateText(withTelemetry(options)),\n streamText: (options:any) => ai.streamText(withTelemetry(options)),\n generateObject: (options:any) => ai.generateObject(withTelemetry(options)),\n streamObject: (options:any) => ai.streamObject(withTelemetry(options)),\n embed: (options:any) => ai.embed(withTelemetry(options)),\n embedMany: (options:any) => ai.embedMany(withTelemetry(options)),\n }\n}","import { neon } from '@neondatabase/serverless';\nimport { drizzle } from 'drizzle-orm/neon-http';\nimport {\n pgTable,\n text,\n json,\n uuid,\n} from 'drizzle-orm/pg-core';\nimport { and, eq } from 'drizzle-orm';\nimport { createInsertSchema } from 'drizzle-zod';\n\n// export const db = drizzle(neon(process.env.POSTGRES_URL!));\n\nexport const db = drizzle(neon(\"postgresql://neondb_owner:npg_MLsCg7kA4BzV@ep-late-morning-ahnpf6h2-pooler.c-3.us-east-1.aws.neon.tech/neondb?sslmode=require&channel_binding=require\"));\n\nexport const agentLogs = pgTable('agent_logs', {\n runId: text('run_id').notNull().primaryKey(),\n userId: uuid('user_id').notNull(),\n traceId: text('trace_id').notNull(),\n parentRunId: text('parent_run_id'),\n eventType: text('event_type'),\n name: text('name'),\n input: json('input'),\n output: json('output'),\n error: text('error'),\n agentType: text('agent_type').default('ai'),\n spanMetadata: text('span_metadata'),\n});\n\nexport type SelectTrace = typeof agentLogs.$inferSelect;\n// Note: insertTraceSchema is exported but not used - it's just a schema definition for validation, no database writes\nexport const insertTraceSchema = createInsertSchema(agentLogs);\n\n// Get all unique traces for a user\n// READ-ONLY: Only performs SELECT queries, does not modify database\n// export async function getTraces(userId: string): Promise<SelectTrace[]> {\n// try {\n// // Get distinct trace_ids for the user\n// const distinctTraces = await db\n// .selectDistinct({ traceId: agentLogs.traceId })\n// .from(agentLogs)\n// .where(eq(agentLogs.userId, userId));\n\n// // For each trace_id, get the first run (or a representative run)\n// const traces = await Promise.all(\n// distinctTraces.map(async ({ traceId }) => {\n// const firstRun = await db\n// .select()\n// .from(agentLogs)\n// .where(\n// and(\n// eq(agentLogs.userId, userId),\n// eq(agentLogs.traceId, traceId)\n// )\n// )\n// .limit(1);\n// return firstRun[0];\n// })\n// );\n\n// return traces.filter(Boolean) as SelectTrace[];\n// } catch (error: any) {\n// // Handle case where database schema doesn't match (column doesn't exist)\n// if (error?.code === '42703' || error?.message?.includes('does not exist') || error?.message?.includes('trace_id')) {\n// console.warn('Database schema mismatch: agent_logs table does not have the expected columns. Please ensure the table has run_id, user_id, trace_id, and other required columns.');\n// return [];\n// }\n// // Re-throw other errors\n// throw error;\n// }\n// }\n\n// // Get all spans (runs) for a specific trace_id\n// // READ-ONLY: Only performs SELECT queries, does not modify database\n// export async function getSpansByTraceId(\n// traceId: string,\n// userId: string\n// ): Promise<SelectTrace[]> {\n// try {\n// return await db\n// .select()\n// .from(agentLogs)\n// .where(\n// and(\n// eq(agentLogs.userId, userId),\n// eq(agentLogs.traceId, traceId)\n// )\n// )\n// .orderBy(agentLogs.runId);\n// } catch (error: any) {\n// // Handle case where database schema doesn't match\n// if (error?.code === '42703' || error?.message?.includes('does not exist') || error?.message?.includes('trace_id')) {\n// console.warn('Database schema mismatch: agent_logs table does not have the expected columns.');\n// return [];\n// }\n// throw error;\n// }\n// }\n\n// // Get a single trace/span by run_id\n// // READ-ONLY: Only performs SELECT queries, does not modify database\n// export async function getTraceByRunId(\n// runId: string,\n// userId: string\n// ): Promise<SelectTrace | null> {\n// try {\n// const result = await db\n// .select()\n// .from(agentLogs)\n// .where(\n// and(\n// eq(agentLogs.runId, runId),\n// eq(agentLogs.userId, userId)\n// )\n// )\n// .limit(1);\n \n// return result[0] || null;\n// } catch (error: any) {\n// // Handle case where database schema doesn't match\n// if (error?.code === '42703' || error?.message?.includes('does not exist') || error?.message?.includes('trace_id') || error?.message?.includes('run_id')) {\n// console.warn('Database schema mismatch: agent_logs table does not have the expected columns.');\n// return null;\n// }\n// throw error;\n// }\n// }\n\nexport async function insertTrace(trace: SelectTrace[]) {\n try {\n await db.insert(agentLogs).values(trace);\n } catch (error: any) {\n throw error;\n }\n}\n","import { SpanExporter } from \"@opentelemetry/sdk-trace-base\";\nimport { insertTrace, SelectTrace } from \"./traces_db\";\nexport class NexusExporter implements SpanExporter {\n private batch:SelectTrace[] = []\n private writeKey: string\n private devMode: boolean\n\n private API_URL: string = \"https://nexus-agent-api-fast-endpoint-production.up.railway.app/catch_route_manual\"\n\n constructor({ writeKey, devMode }: { writeKey: string, devMode: boolean }) {\n this.writeKey = writeKey\n this.devMode = devMode\n }\n \n private triggerAnalysis(trace_id: string) {\n if (!this.devMode){\n try {\n const params = new URLSearchParams({\n user_id: this.writeKey,\n trace_id: trace_id\n }).toString();\n fetch(`${this.API_URL}?${params}`, {\n method: \"POST\"\n })\n } catch (error) {\n console.error(\"Error triggering analysis\", error)\n }\n }\n }\n // OTEL calls this automatically when a span completes\n export(spans: any, resultCallback: any) {\n for (const span of spans) {\n const attrs = span.attributes;\n const name = span.name;\n\n let input: string | null = null;\n let output: string | null = null;\n\n switch (name) {\n // Tool execution\n case 'ai.toolCall':\n input = attrs[\"ai.toolCall.args\"] ?? null;\n output = attrs[\"ai.toolCall.result\"] ?? null;\n break;\n\n // Model calls (inner spans)\n case 'ai.generateText.doGenerate':\n case 'ai.streamText.doStream':\n case 'ai.generateObject.doGenerate':\n case 'ai.streamObject.doStream':\n input = attrs[\"ai.prompt.messages\"] ?? null;\n output = attrs[\"ai.response.text\"] ?? null;\n break;\n\n // Embedding calls (inner spans)\n case 'ai.embed.doEmbed':\n case 'ai.embedMany.doEmbed':\n input = attrs[\"ai.values\"] ?? null;\n output = attrs[\"ai.embeddings\"] ?? null;\n break;\n\n // Root spans\n case 'ai.generateText':\n case 'ai.streamText':\n case 'ai.generateObject':\n case 'ai.streamObject':\n input = attrs[\"ai.prompt\"] ?? null;\n output = attrs[\"ai.response.text\"] ?? null;\n break;\n\n case 'ai.embed':\n case 'ai.embedMany':\n input = attrs[\"ai.values\"] ?? null;\n output = attrs[\"ai.embeddings\"] ?? null;\n break;\n\n default:\n input = attrs[\"ai.prompt\"] ?? attrs[\"ai.prompt.messages\"] ?? null;\n output = attrs[\"ai.response.text\"] ?? null;\n break;\n }\n\n // Build metadata string\n const [dSec, dNano] = span._duration ?? [0, 0];\n const duration_s = dSec + dNano / 1_000_000_000;\n const parts: string[] = [`${duration_s}s`];\n\n if (attrs[\"ai.usage.promptTokens\"] != null) {\n parts.push(`in: ${attrs[\"ai.usage.promptTokens\"]} tokens`);\n }\n if (attrs[\"ai.usage.completionTokens\"] != null) {\n parts.push(`out: ${attrs[\"ai.usage.completionTokens\"]} tokens`);\n }\n\n this.batch.push({\n runId: span.spanContext().spanId,\n userId: this.writeKey,\n traceId: span.spanContext().traceId,\n parentRunId: span.parentSpanContext?.spanId ?? null,\n eventType: name,\n name: name,\n input: input ? JSON.parse(input) : null,\n output: output ? JSON.parse(output) : null,\n error: null,\n agentType: \"vercel\",\n spanMetadata: parts.join(\", \"),\n });\n }\n resultCallback({ code: 0 })\n }\n\n // POST to nexus\n async flush() {\n \n await insertTrace(this.batch);\n\n if (this.batch.length > 0){\n let trace_id = this.batch[0].traceId\n this.triggerAnalysis(trace_id)\n }\n\n this.batch = []\n }\n \n // OTEL calls this on shutdown\n async shutdown() {\n await this.flush()\n }\n}","import { wrap } from \"./wrap\";\nimport { NexusExporter } from \"./export_store\";\nimport { NodeSDK } from \"@opentelemetry/sdk-node\";\nimport { SimpleSpanProcessor } from \"@opentelemetry/sdk-trace-base\"\n\nexport function NexusAISDK(api_key: string){\n const exporter = new NexusExporter({ writeKey: api_key, devMode: false });\n\n const sdk = new NodeSDK({\n spanProcessors: [\n new SimpleSpanProcessor(exporter)\n ]\n })\n \n sdk.start()\n\n return {\n wrap,\n flush: () => exporter.flush()\n }\n}"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nexuscore/nexus-ai-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Nexus AI SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@neondatabase/serverless": "^0.10.0",
|
|
34
|
+
"@opentelemetry/sdk-node": "^0.212.0",
|
|
35
|
+
"@opentelemetry/sdk-trace-base": "^2.5.1",
|
|
36
|
+
"drizzle-orm": "^0.44.0",
|
|
37
|
+
"drizzle-zod": "^0.7.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"ai": "^6.0.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"ai": {
|
|
44
|
+
"optional": false
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"tsup": "^8.4.0",
|
|
49
|
+
"typescript": "^5.7.0"
|
|
50
|
+
}
|
|
51
|
+
}
|