neatlogs 1.0.6 → 1.0.8
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/azure-openai.cjs +344 -0
- package/dist/azure-openai.cjs.map +1 -0
- package/dist/azure-openai.d.ts +30 -0
- package/dist/azure-openai.mjs +318 -0
- package/dist/azure-openai.mjs.map +1 -0
- package/dist/bedrock.cjs +540 -0
- package/dist/bedrock.cjs.map +1 -0
- package/dist/bedrock.d.ts +29 -0
- package/dist/bedrock.mjs +514 -0
- package/dist/bedrock.mjs.map +1 -0
- package/dist/browser.cjs +121 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.ts +143 -0
- package/dist/browser.mjs +96 -0
- package/dist/browser.mjs.map +1 -0
- package/dist/claude-agent-sdk.cjs +406 -0
- package/dist/claude-agent-sdk.cjs.map +1 -0
- package/dist/claude-agent-sdk.d.ts +49 -0
- package/dist/claude-agent-sdk.mjs +381 -0
- package/dist/claude-agent-sdk.mjs.map +1 -0
- package/dist/index.cjs +3219 -1129
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.mjs +3210 -1131
- package/dist/index.mjs.map +1 -1
- package/dist/langchain.cjs +9 -9
- package/dist/langchain.cjs.map +1 -1
- package/dist/langchain.mjs +9 -9
- package/dist/langchain.mjs.map +1 -1
- package/dist/mastra-wrap.cjs +25 -25
- package/dist/mastra-wrap.cjs.map +1 -1
- package/dist/mastra-wrap.mjs +25 -25
- package/dist/mastra-wrap.mjs.map +1 -1
- package/dist/openai-agents.cjs +6 -6
- package/dist/openai-agents.cjs.map +1 -1
- package/dist/openai-agents.mjs +6 -6
- package/dist/openai-agents.mjs.map +1 -1
- package/dist/opencode-plugin.cjs +5879 -0
- package/dist/opencode-plugin.cjs.map +1 -0
- package/dist/opencode-plugin.d.ts +38 -0
- package/dist/opencode-plugin.mjs +5854 -0
- package/dist/opencode-plugin.mjs.map +1 -0
- package/dist/openrouter-agent.cjs +273 -0
- package/dist/openrouter-agent.cjs.map +1 -0
- package/dist/openrouter-agent.d.ts +34 -0
- package/dist/openrouter-agent.mjs +247 -0
- package/dist/openrouter-agent.mjs.map +1 -0
- package/dist/pi-agent.cjs +10 -10
- package/dist/pi-agent.cjs.map +1 -1
- package/dist/pi-agent.mjs +10 -10
- package/dist/pi-agent.mjs.map +1 -1
- package/dist/vertex-ai.cjs +424 -0
- package/dist/vertex-ai.cjs.map +1 -0
- package/dist/vertex-ai.d.ts +39 -0
- package/dist/vertex-ai.mjs +397 -0
- package/dist/vertex-ai.mjs.map +1 -0
- package/package.json +76 -1
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
// src/vertex-ai.ts
|
|
2
|
+
import { trace, context as otelContext, SpanStatusCode } from "@opentelemetry/api";
|
|
3
|
+
var TRACER_NAME = "neatlogs.vertex_ai";
|
|
4
|
+
var PROVIDER = "vertex_ai";
|
|
5
|
+
var SYSTEM = "vertexai";
|
|
6
|
+
function wrapVertexAI(client) {
|
|
7
|
+
return wrapNamespace(client, []);
|
|
8
|
+
}
|
|
9
|
+
function traceTool(name, fn) {
|
|
10
|
+
return async function tracedTool(args) {
|
|
11
|
+
const tracer = trace.getTracer(TRACER_NAME);
|
|
12
|
+
return tracer.startActiveSpan(
|
|
13
|
+
`tool.${name}`,
|
|
14
|
+
{
|
|
15
|
+
attributes: {
|
|
16
|
+
"neatlogs.span.kind": "TOOL",
|
|
17
|
+
"neatlogs.tool.name": name,
|
|
18
|
+
"input.value": safeStringify(args)
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
otelContext.active(),
|
|
22
|
+
async (span) => {
|
|
23
|
+
try {
|
|
24
|
+
const result = await fn(args);
|
|
25
|
+
span.setAttribute("output.value", safeStringify(result));
|
|
26
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
27
|
+
return result;
|
|
28
|
+
} catch (err) {
|
|
29
|
+
recordError(span, err);
|
|
30
|
+
throw err;
|
|
31
|
+
} finally {
|
|
32
|
+
span.end();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function wrapNamespace(target, path) {
|
|
39
|
+
return new Proxy(target, {
|
|
40
|
+
get(obj, prop, receiver) {
|
|
41
|
+
const value = Reflect.get(obj, prop, receiver);
|
|
42
|
+
if (typeof prop === "symbol" || String(prop).startsWith("_")) return value;
|
|
43
|
+
const currentPath = [...path, String(prop)];
|
|
44
|
+
const pathStr = currentPath.join(".");
|
|
45
|
+
if (pathStr === "models.generateContent" && typeof value === "function") {
|
|
46
|
+
return tracedGenerateContent(value.bind(obj), false);
|
|
47
|
+
}
|
|
48
|
+
if (pathStr === "models.generateContentStream" && typeof value === "function") {
|
|
49
|
+
return tracedGenerateContent(value.bind(obj), true);
|
|
50
|
+
}
|
|
51
|
+
if (pathStr === "models.embedContent" && typeof value === "function") {
|
|
52
|
+
return tracedEmbedContent(value.bind(obj));
|
|
53
|
+
}
|
|
54
|
+
if (pathStr === "models.countTokens" && typeof value === "function") {
|
|
55
|
+
return tracedCountTokens(value.bind(obj));
|
|
56
|
+
}
|
|
57
|
+
if (value && typeof value === "object" && !Array.isArray(value) && isNamespace(currentPath)) {
|
|
58
|
+
return wrapNamespace(value, currentPath);
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function isNamespace(path) {
|
|
65
|
+
if (path.length > 2) return false;
|
|
66
|
+
return ["models", "chats"].includes(path[path.length - 1]);
|
|
67
|
+
}
|
|
68
|
+
function wrapVertexAIChat(chat) {
|
|
69
|
+
const c = chat;
|
|
70
|
+
if (!c || c._neatlogsVertexPatched) return chat;
|
|
71
|
+
if (typeof c.sendMessage === "function") {
|
|
72
|
+
const orig = c.sendMessage.bind(c);
|
|
73
|
+
c.sendMessage = (params, ...rest) => tracedChatSend(orig, c, params, rest, false);
|
|
74
|
+
}
|
|
75
|
+
if (typeof c.sendMessageStream === "function") {
|
|
76
|
+
const orig = c.sendMessageStream.bind(c);
|
|
77
|
+
c.sendMessageStream = (params, ...rest) => tracedChatSend(orig, c, params, rest, true);
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
Object.defineProperty(c, "_neatlogsVertexPatched", { value: true, enumerable: false, configurable: true });
|
|
81
|
+
} catch {
|
|
82
|
+
c._neatlogsVertexPatched = true;
|
|
83
|
+
}
|
|
84
|
+
return chat;
|
|
85
|
+
}
|
|
86
|
+
function tracedChatSend(original, chat, params, rest, isStream) {
|
|
87
|
+
const tracer = trace.getTracer(TRACER_NAME);
|
|
88
|
+
const model = chat?.model ?? chat?.modelVersion ?? "";
|
|
89
|
+
const span = tracer.startSpan("vertex_ai.chat.send_message", {
|
|
90
|
+
attributes: {
|
|
91
|
+
"neatlogs.span.kind": "LLM",
|
|
92
|
+
"neatlogs.llm.provider": PROVIDER,
|
|
93
|
+
"neatlogs.llm.system": SYSTEM,
|
|
94
|
+
"neatlogs.llm.model_name": model,
|
|
95
|
+
"neatlogs.llm.is_streaming": isStream
|
|
96
|
+
}
|
|
97
|
+
}, otelContext.active());
|
|
98
|
+
const message = params?.message ?? params;
|
|
99
|
+
span.setAttribute("neatlogs.llm.input_messages.0.role", "user");
|
|
100
|
+
span.setAttribute(
|
|
101
|
+
"neatlogs.llm.input_messages.0.content",
|
|
102
|
+
typeof message === "string" ? message : safeStringify(message)
|
|
103
|
+
);
|
|
104
|
+
const ctx = trace.setSpan(otelContext.active(), span);
|
|
105
|
+
const result = otelContext.with(ctx, () => original(params, ...rest));
|
|
106
|
+
return Promise.resolve(result).then(
|
|
107
|
+
(response) => {
|
|
108
|
+
if (isStream) return wrapStream(response, span);
|
|
109
|
+
finalizeResponse(span, response);
|
|
110
|
+
return response;
|
|
111
|
+
},
|
|
112
|
+
(err) => {
|
|
113
|
+
recordError(span, err);
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
function tracedEmbedContent(original) {
|
|
119
|
+
return function(opts, ...rest) {
|
|
120
|
+
const tracer = trace.getTracer(TRACER_NAME);
|
|
121
|
+
const span = tracer.startSpan("vertex_ai.models.embed_content", {
|
|
122
|
+
attributes: {
|
|
123
|
+
"neatlogs.span.kind": "EMBEDDING",
|
|
124
|
+
"neatlogs.llm.provider": PROVIDER,
|
|
125
|
+
"neatlogs.embedding.model_name": opts?.model ?? "",
|
|
126
|
+
"neatlogs.embedding.text": safeStringify(opts?.contents ?? "")
|
|
127
|
+
}
|
|
128
|
+
}, otelContext.active());
|
|
129
|
+
const ctx = trace.setSpan(otelContext.active(), span);
|
|
130
|
+
const result = otelContext.with(ctx, () => original(opts, ...rest));
|
|
131
|
+
return Promise.resolve(result).then(
|
|
132
|
+
(response) => {
|
|
133
|
+
const embeddings = response?.embeddings;
|
|
134
|
+
if (Array.isArray(embeddings)) {
|
|
135
|
+
span.setAttribute("neatlogs.embedding.count", embeddings.length);
|
|
136
|
+
const vals = embeddings[0]?.values;
|
|
137
|
+
if (Array.isArray(vals)) span.setAttribute("neatlogs.embedding.dimensions", vals.length);
|
|
138
|
+
}
|
|
139
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
140
|
+
span.end();
|
|
141
|
+
return response;
|
|
142
|
+
},
|
|
143
|
+
(err) => {
|
|
144
|
+
recordError(span, err);
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function tracedCountTokens(original) {
|
|
151
|
+
return function(opts, ...rest) {
|
|
152
|
+
const tracer = trace.getTracer(TRACER_NAME);
|
|
153
|
+
const span = tracer.startSpan("vertex_ai.models.count_tokens", {
|
|
154
|
+
attributes: {
|
|
155
|
+
"neatlogs.span.kind": "LLM",
|
|
156
|
+
"neatlogs.llm.provider": PROVIDER,
|
|
157
|
+
"neatlogs.llm.task": "count_tokens",
|
|
158
|
+
"neatlogs.llm.model_name": opts?.model ?? ""
|
|
159
|
+
}
|
|
160
|
+
}, otelContext.active());
|
|
161
|
+
const ctx = trace.setSpan(otelContext.active(), span);
|
|
162
|
+
const result = otelContext.with(ctx, () => original(opts, ...rest));
|
|
163
|
+
return Promise.resolve(result).then(
|
|
164
|
+
(response) => {
|
|
165
|
+
if (response?.totalTokens != null) span.setAttribute("neatlogs.llm.token_count.prompt", response.totalTokens);
|
|
166
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
167
|
+
span.end();
|
|
168
|
+
return response;
|
|
169
|
+
},
|
|
170
|
+
(err) => {
|
|
171
|
+
recordError(span, err);
|
|
172
|
+
throw err;
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function tracedGenerateContent(original, isStream) {
|
|
178
|
+
return function(opts, ...rest) {
|
|
179
|
+
const tracer = trace.getTracer(TRACER_NAME);
|
|
180
|
+
const model = opts?.model ?? "";
|
|
181
|
+
const span = tracer.startSpan("vertex_ai.models.generate_content", {
|
|
182
|
+
attributes: {
|
|
183
|
+
"neatlogs.span.kind": "LLM",
|
|
184
|
+
"neatlogs.llm.provider": PROVIDER,
|
|
185
|
+
"neatlogs.llm.system": SYSTEM,
|
|
186
|
+
"neatlogs.llm.model_name": model,
|
|
187
|
+
"neatlogs.llm.is_streaming": isStream
|
|
188
|
+
}
|
|
189
|
+
}, otelContext.active());
|
|
190
|
+
setInputAttributes(span, opts);
|
|
191
|
+
const ctx = trace.setSpan(otelContext.active(), span);
|
|
192
|
+
const result = otelContext.with(ctx, () => original(opts, ...rest));
|
|
193
|
+
return Promise.resolve(result).then(
|
|
194
|
+
(response) => {
|
|
195
|
+
if (isStream) {
|
|
196
|
+
return wrapStream(response, span);
|
|
197
|
+
}
|
|
198
|
+
finalizeResponse(span, response);
|
|
199
|
+
return response;
|
|
200
|
+
},
|
|
201
|
+
(err) => {
|
|
202
|
+
recordError(span, err);
|
|
203
|
+
throw err;
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function setInputAttributes(span, opts) {
|
|
209
|
+
let idx = 0;
|
|
210
|
+
const config = opts?.config;
|
|
211
|
+
const systemInstruction = config?.systemInstruction ?? config?.system_instruction;
|
|
212
|
+
if (systemInstruction) {
|
|
213
|
+
span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, "system");
|
|
214
|
+
span.setAttribute(
|
|
215
|
+
`neatlogs.llm.input_messages.${idx}.content`,
|
|
216
|
+
typeof systemInstruction === "string" ? systemInstruction : safeStringify(systemInstruction)
|
|
217
|
+
);
|
|
218
|
+
idx++;
|
|
219
|
+
}
|
|
220
|
+
const contents = opts?.contents;
|
|
221
|
+
if (typeof contents === "string") {
|
|
222
|
+
span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, "user");
|
|
223
|
+
span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, contents);
|
|
224
|
+
} else if (Array.isArray(contents)) {
|
|
225
|
+
for (const item of contents) {
|
|
226
|
+
if (typeof item === "string") {
|
|
227
|
+
span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, "user");
|
|
228
|
+
span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, item);
|
|
229
|
+
idx++;
|
|
230
|
+
} else if (item && typeof item === "object") {
|
|
231
|
+
const role = item.role ?? "user";
|
|
232
|
+
span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, role);
|
|
233
|
+
const parts = item.parts ?? [];
|
|
234
|
+
const textParts = [];
|
|
235
|
+
for (const part of parts) {
|
|
236
|
+
if (typeof part === "string") textParts.push(part);
|
|
237
|
+
else if (part?.text) textParts.push(part.text);
|
|
238
|
+
}
|
|
239
|
+
span.setAttribute(
|
|
240
|
+
`neatlogs.llm.input_messages.${idx}.content`,
|
|
241
|
+
textParts.length ? textParts.join("\n") : safeStringify(parts)
|
|
242
|
+
);
|
|
243
|
+
idx++;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
} else if (contents) {
|
|
247
|
+
span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, "user");
|
|
248
|
+
span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, safeStringify(contents));
|
|
249
|
+
}
|
|
250
|
+
const tools = config?.tools;
|
|
251
|
+
if (Array.isArray(tools)) {
|
|
252
|
+
let t = 0;
|
|
253
|
+
for (const tool of tools) {
|
|
254
|
+
const decls = tool?.functionDeclarations ?? tool?.function_declarations ?? [];
|
|
255
|
+
for (const fn of decls) {
|
|
256
|
+
span.setAttribute(`neatlogs.llm.tools.${t}.name`, fn?.name ?? "");
|
|
257
|
+
if (fn?.description) span.setAttribute(`neatlogs.llm.tools.${t}.description`, fn.description);
|
|
258
|
+
if (fn?.parameters) span.setAttribute(`neatlogs.llm.tools.${t}.input_schema`, safeStringify(fn.parameters));
|
|
259
|
+
t++;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (config) {
|
|
264
|
+
if (config.temperature != null) span.setAttribute("neatlogs.llm.temperature", config.temperature);
|
|
265
|
+
if (config.topP != null) span.setAttribute("neatlogs.llm.top_p", config.topP);
|
|
266
|
+
if (config.topK != null) span.setAttribute("neatlogs.llm.top_k", config.topK);
|
|
267
|
+
const maxTokens = config.maxOutputTokens ?? config.max_output_tokens;
|
|
268
|
+
if (maxTokens != null) span.setAttribute("neatlogs.llm.max_tokens", maxTokens);
|
|
269
|
+
const params = {};
|
|
270
|
+
if (config.temperature != null) params.temperature = config.temperature;
|
|
271
|
+
if (config.topP != null) params.top_p = config.topP;
|
|
272
|
+
if (config.topK != null) params.top_k = config.topK;
|
|
273
|
+
if (maxTokens != null) params.max_tokens = maxTokens;
|
|
274
|
+
if (config.frequencyPenalty != null) params.frequency_penalty = config.frequencyPenalty;
|
|
275
|
+
if (config.presencePenalty != null) params.presence_penalty = config.presencePenalty;
|
|
276
|
+
if (Object.keys(params).length > 0) {
|
|
277
|
+
span.setAttribute("neatlogs.llm.invocation_parameters", JSON.stringify(params));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
function wrapStream(stream, span) {
|
|
282
|
+
const chunks = [];
|
|
283
|
+
const originalAsyncIterator = stream?.[Symbol.asyncIterator]?.bind(stream);
|
|
284
|
+
if (!originalAsyncIterator) {
|
|
285
|
+
finalizeStreamChunks(span, chunks);
|
|
286
|
+
return stream;
|
|
287
|
+
}
|
|
288
|
+
const wrapped = Object.create(Object.getPrototypeOf(stream));
|
|
289
|
+
Object.assign(wrapped, stream);
|
|
290
|
+
wrapped[Symbol.asyncIterator] = function() {
|
|
291
|
+
const iterator = originalAsyncIterator();
|
|
292
|
+
return {
|
|
293
|
+
async next() {
|
|
294
|
+
try {
|
|
295
|
+
const result = await iterator.next();
|
|
296
|
+
if (result.done) {
|
|
297
|
+
finalizeStreamChunks(span, chunks);
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
300
|
+
chunks.push(result.value);
|
|
301
|
+
return result;
|
|
302
|
+
} catch (err) {
|
|
303
|
+
recordError(span, err);
|
|
304
|
+
throw err;
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
async return(value) {
|
|
308
|
+
finalizeStreamChunks(span, chunks);
|
|
309
|
+
return iterator.return?.(value) ?? { done: true, value: void 0 };
|
|
310
|
+
},
|
|
311
|
+
async throw(err) {
|
|
312
|
+
recordError(span, err);
|
|
313
|
+
return iterator.throw?.(err) ?? { done: true, value: void 0 };
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
return wrapped;
|
|
318
|
+
}
|
|
319
|
+
function finalizeStreamChunks(span, chunks) {
|
|
320
|
+
const textParts = [];
|
|
321
|
+
let finishReason = "";
|
|
322
|
+
let usage = null;
|
|
323
|
+
for (const chunk of chunks) {
|
|
324
|
+
for (const candidate of chunk?.candidates ?? []) {
|
|
325
|
+
for (const part of candidate?.content?.parts ?? []) {
|
|
326
|
+
if (part?.text && !part?.thought) textParts.push(part.text);
|
|
327
|
+
}
|
|
328
|
+
if (candidate?.finishReason) finishReason = candidate.finishReason;
|
|
329
|
+
}
|
|
330
|
+
if (chunk?.usageMetadata) usage = chunk.usageMetadata;
|
|
331
|
+
}
|
|
332
|
+
const fullText = textParts.join("");
|
|
333
|
+
if (fullText) {
|
|
334
|
+
span.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
335
|
+
span.setAttribute("neatlogs.llm.output_messages.0.content", fullText);
|
|
336
|
+
}
|
|
337
|
+
if (finishReason) span.setAttribute("neatlogs.llm.finish_reason", String(finishReason));
|
|
338
|
+
setUsage(span, usage);
|
|
339
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
340
|
+
span.end();
|
|
341
|
+
}
|
|
342
|
+
function finalizeResponse(span, response) {
|
|
343
|
+
const textParts = [];
|
|
344
|
+
let toolIdx = 0;
|
|
345
|
+
for (const candidate of response?.candidates ?? []) {
|
|
346
|
+
for (const part of candidate?.content?.parts ?? []) {
|
|
347
|
+
if (part?.text && !part?.thought) {
|
|
348
|
+
textParts.push(part.text);
|
|
349
|
+
} else if (part?.thought && part?.text) {
|
|
350
|
+
span.setAttribute("neatlogs.llm.output_messages.0.thinking", part.text);
|
|
351
|
+
} else if (part?.functionCall) {
|
|
352
|
+
const fc = part.functionCall;
|
|
353
|
+
span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.name`, fc?.name ?? "");
|
|
354
|
+
span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.arguments`, safeStringify(fc?.args ?? {}));
|
|
355
|
+
toolIdx++;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (candidate?.finishReason) span.setAttribute("neatlogs.llm.finish_reason", String(candidate.finishReason));
|
|
359
|
+
}
|
|
360
|
+
if (textParts.length) {
|
|
361
|
+
span.setAttribute("neatlogs.llm.output_messages.0.role", "assistant");
|
|
362
|
+
span.setAttribute("neatlogs.llm.output_messages.0.content", textParts.join(""));
|
|
363
|
+
}
|
|
364
|
+
setUsage(span, response?.usageMetadata);
|
|
365
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
366
|
+
span.end();
|
|
367
|
+
}
|
|
368
|
+
function setUsage(span, usage) {
|
|
369
|
+
if (!usage) return;
|
|
370
|
+
if (usage.promptTokenCount != null) span.setAttribute("neatlogs.llm.token_count.prompt", usage.promptTokenCount);
|
|
371
|
+
if (usage.candidatesTokenCount != null) span.setAttribute("neatlogs.llm.token_count.completion", usage.candidatesTokenCount);
|
|
372
|
+
if (usage.totalTokenCount != null) span.setAttribute("neatlogs.llm.token_count.total", usage.totalTokenCount);
|
|
373
|
+
if (usage.cachedContentTokenCount != null) span.setAttribute("neatlogs.llm.token_count.cache_read", usage.cachedContentTokenCount);
|
|
374
|
+
if (usage.thoughtsTokenCount != null) span.setAttribute("neatlogs.llm.token_count.reasoning", usage.thoughtsTokenCount);
|
|
375
|
+
}
|
|
376
|
+
function safeStringify(value) {
|
|
377
|
+
try {
|
|
378
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
379
|
+
} catch {
|
|
380
|
+
return "";
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
function recordError(span, err) {
|
|
384
|
+
if (err instanceof Error) {
|
|
385
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
|
|
386
|
+
span.recordException(err);
|
|
387
|
+
} else {
|
|
388
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
389
|
+
}
|
|
390
|
+
span.end();
|
|
391
|
+
}
|
|
392
|
+
export {
|
|
393
|
+
traceTool,
|
|
394
|
+
wrapVertexAI,
|
|
395
|
+
wrapVertexAIChat
|
|
396
|
+
};
|
|
397
|
+
//# sourceMappingURL=vertex-ai.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vertex-ai.ts"],"sourcesContent":["/**\n * Neatlogs Vertex AI wrapper — ES6 Proxy-based.\n *\n * Vertex AI is accessed through the same `@google/genai` SDK as Gemini, but in\n * Vertex mode (`new GoogleGenAI({ vertexai: true, project, location })`). This\n * wrapper traces those clients with provider `vertex_ai` so Vertex traffic is\n * distinguished from Google AI Studio (Gemini) traffic.\n *\n * Usage:\n * import { wrapVertexAI } from 'neatlogs/vertex-ai';\n * import { GoogleGenAI } from '@google/genai';\n * const client = wrapVertexAI(new GoogleGenAI({ vertexai: true, project: 'p', location: 'us-central1' }));\n * const res = await client.models.generateContent({ model: 'gemini-2.0-flash', contents: 'Hello' });\n *\n * Intercepts:\n * - client.models.generateContent() — non-streaming\n * - client.models.generateContentStream() — streaming (async iterable)\n * - client.models.embedContent() — embeddings\n * - client.models.countTokens() — token counting\n * - chat.sendMessage() / sendMessageStream() — chat sessions\n */\n\nimport { trace, context as otelContext, SpanStatusCode, type Span } from '@opentelemetry/api';\n\nconst TRACER_NAME = 'neatlogs.vertex_ai';\nconst PROVIDER = 'vertex_ai';\nconst SYSTEM = 'vertexai';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport function wrapVertexAI<T extends object>(client: T): T {\n return wrapNamespace(client, []) as T;\n}\n\n/**\n * Wrap a tool/function implementation to emit TOOL spans when executed.\n *\n * Usage:\n * const getWeather = traceTool('get_weather', async (args: { city: string }) => {\n * return `Weather in ${args.city}: sunny`;\n * });\n */\nexport function traceTool<TArgs = any, TResult = any>(\n name: string,\n fn: (args: TArgs) => TResult | Promise<TResult>,\n): (args: TArgs) => Promise<TResult> {\n return async function tracedTool(args: TArgs): Promise<TResult> {\n const tracer = trace.getTracer(TRACER_NAME);\n return tracer.startActiveSpan(\n `tool.${name}`,\n {\n attributes: {\n 'neatlogs.span.kind': 'TOOL',\n 'neatlogs.tool.name': name,\n 'input.value': safeStringify(args),\n },\n },\n otelContext.active(),\n async (span) => {\n try {\n const result = await fn(args);\n span.setAttribute('output.value', safeStringify(result));\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n } finally {\n span.end();\n }\n },\n );\n };\n}\n\n// ---------------------------------------------------------------------------\n// Proxy wrapping\n// ---------------------------------------------------------------------------\n\nfunction wrapNamespace(target: any, path: string[]): any {\n return new Proxy(target, {\n get(obj, prop, receiver) {\n const value = Reflect.get(obj, prop, receiver);\n if (typeof prop === 'symbol' || String(prop).startsWith('_')) return value;\n\n const currentPath = [...path, String(prop)];\n const pathStr = currentPath.join('.');\n\n if (pathStr === 'models.generateContent' && typeof value === 'function') {\n return tracedGenerateContent(value.bind(obj), false);\n }\n if (pathStr === 'models.generateContentStream' && typeof value === 'function') {\n return tracedGenerateContent(value.bind(obj), true);\n }\n if (pathStr === 'models.embedContent' && typeof value === 'function') {\n return tracedEmbedContent(value.bind(obj));\n }\n if (pathStr === 'models.countTokens' && typeof value === 'function') {\n return tracedCountTokens(value.bind(obj));\n }\n\n if (value && typeof value === 'object' && !Array.isArray(value) && isNamespace(currentPath)) {\n return wrapNamespace(value, currentPath);\n }\n\n return value;\n },\n });\n}\n\nfunction isNamespace(path: string[]): boolean {\n if (path.length > 2) return false;\n return ['models', 'chats'].includes(path[path.length - 1]);\n}\n\n/**\n * Wrap a chat session returned by `client.chats.create(...)`. The `@google/genai`\n * Chat object exposes `sendMessage` / `sendMessageStream`; wrap them so each turn\n * emits an LLM span. Returns the same chat instance.\n */\nexport function wrapVertexAIChat<T extends object>(chat: T): T {\n const c = chat as any;\n if (!c || c._neatlogsVertexPatched) return chat;\n\n if (typeof c.sendMessage === 'function') {\n const orig = c.sendMessage.bind(c);\n c.sendMessage = (params: any, ...rest: any[]) => tracedChatSend(orig, c, params, rest, false);\n }\n if (typeof c.sendMessageStream === 'function') {\n const orig = c.sendMessageStream.bind(c);\n c.sendMessageStream = (params: any, ...rest: any[]) => tracedChatSend(orig, c, params, rest, true);\n }\n\n try {\n Object.defineProperty(c, '_neatlogsVertexPatched', { value: true, enumerable: false, configurable: true });\n } catch {\n c._neatlogsVertexPatched = true;\n }\n return chat;\n}\n\nfunction tracedChatSend(\n original: (...a: any[]) => any,\n chat: any,\n params: any,\n rest: any[],\n isStream: boolean,\n): any {\n const tracer = trace.getTracer(TRACER_NAME);\n const model = chat?.model ?? chat?.modelVersion ?? '';\n const span = tracer.startSpan('vertex_ai.chat.send_message', {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.system': SYSTEM,\n 'neatlogs.llm.model_name': model,\n 'neatlogs.llm.is_streaming': isStream,\n },\n }, otelContext.active());\n\n // The chat sendMessage param shape is { message } (string or Part[]).\n const message = params?.message ?? params;\n span.setAttribute('neatlogs.llm.input_messages.0.role', 'user');\n span.setAttribute(\n 'neatlogs.llm.input_messages.0.content',\n (typeof message === 'string' ? message : safeStringify(message)),\n );\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const result = otelContext.with(ctx, () => original(params, ...rest));\n\n return Promise.resolve(result).then(\n (response: any) => {\n if (isStream) return wrapStream(response, span);\n finalizeResponse(span, response);\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n}\n\nfunction tracedEmbedContent(original: (...a: any[]) => any) {\n return function (opts: any, ...rest: any[]): any {\n const tracer = trace.getTracer(TRACER_NAME);\n const span = tracer.startSpan('vertex_ai.models.embed_content', {\n attributes: {\n 'neatlogs.span.kind': 'EMBEDDING',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.embedding.model_name': opts?.model ?? '',\n 'neatlogs.embedding.text': safeStringify(opts?.contents ?? ''),\n },\n }, otelContext.active());\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const result = otelContext.with(ctx, () => original(opts, ...rest));\n\n return Promise.resolve(result).then(\n (response: any) => {\n const embeddings = response?.embeddings;\n if (Array.isArray(embeddings)) {\n span.setAttribute('neatlogs.embedding.count', embeddings.length);\n const vals = embeddings[0]?.values;\n if (Array.isArray(vals)) span.setAttribute('neatlogs.embedding.dimensions', vals.length);\n }\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n };\n}\n\nfunction tracedCountTokens(original: (...a: any[]) => any) {\n return function (opts: any, ...rest: any[]): any {\n const tracer = trace.getTracer(TRACER_NAME);\n const span = tracer.startSpan('vertex_ai.models.count_tokens', {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.task': 'count_tokens',\n 'neatlogs.llm.model_name': opts?.model ?? '',\n },\n }, otelContext.active());\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const result = otelContext.with(ctx, () => original(opts, ...rest));\n\n return Promise.resolve(result).then(\n (response: any) => {\n if (response?.totalTokens != null) span.setAttribute('neatlogs.llm.token_count.prompt', response.totalTokens);\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n };\n}\n\n// ---------------------------------------------------------------------------\n// generateContent / generateContentStream\n// ---------------------------------------------------------------------------\n\nfunction tracedGenerateContent(original: (...args: any[]) => any, isStream: boolean) {\n return function (opts: any, ...rest: any[]): any {\n const tracer = trace.getTracer(TRACER_NAME);\n const model = opts?.model ?? '';\n\n const span = tracer.startSpan('vertex_ai.models.generate_content', {\n attributes: {\n 'neatlogs.span.kind': 'LLM',\n 'neatlogs.llm.provider': PROVIDER,\n 'neatlogs.llm.system': SYSTEM,\n 'neatlogs.llm.model_name': model,\n 'neatlogs.llm.is_streaming': isStream,\n },\n }, otelContext.active());\n\n setInputAttributes(span, opts);\n\n const ctx = trace.setSpan(otelContext.active(), span);\n const result = otelContext.with(ctx, () => original(opts, ...rest));\n\n return Promise.resolve(result).then(\n (response: any) => {\n if (isStream) {\n return wrapStream(response, span);\n }\n finalizeResponse(span, response);\n return response;\n },\n (err: any) => {\n recordError(span, err);\n throw err;\n },\n );\n };\n}\n\nfunction setInputAttributes(span: Span, opts: any): void {\n let idx = 0;\n\n const config = opts?.config;\n const systemInstruction = config?.systemInstruction ?? config?.system_instruction;\n if (systemInstruction) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'system');\n span.setAttribute(\n `neatlogs.llm.input_messages.${idx}.content`,\n typeof systemInstruction === 'string' ? systemInstruction : safeStringify(systemInstruction),\n );\n idx++;\n }\n\n const contents = opts?.contents;\n if (typeof contents === 'string') {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, contents);\n } else if (Array.isArray(contents)) {\n for (const item of contents) {\n if (typeof item === 'string') {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, item);\n idx++;\n } else if (item && typeof item === 'object') {\n const role = item.role ?? 'user';\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, role);\n const parts = item.parts ?? [];\n const textParts: string[] = [];\n for (const part of parts) {\n if (typeof part === 'string') textParts.push(part);\n else if (part?.text) textParts.push(part.text);\n }\n span.setAttribute(\n `neatlogs.llm.input_messages.${idx}.content`,\n textParts.length ? textParts.join('\\n') : safeStringify(parts),\n );\n idx++;\n }\n }\n } else if (contents) {\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.role`, 'user');\n span.setAttribute(`neatlogs.llm.input_messages.${idx}.content`, safeStringify(contents));\n }\n\n // Tools (function declarations)\n const tools = config?.tools;\n if (Array.isArray(tools)) {\n let t = 0;\n for (const tool of tools) {\n const decls = tool?.functionDeclarations ?? tool?.function_declarations ?? [];\n for (const fn of decls) {\n span.setAttribute(`neatlogs.llm.tools.${t}.name`, fn?.name ?? '');\n if (fn?.description) span.setAttribute(`neatlogs.llm.tools.${t}.description`, fn.description);\n if (fn?.parameters) span.setAttribute(`neatlogs.llm.tools.${t}.input_schema`, safeStringify(fn.parameters));\n t++;\n }\n }\n }\n\n // Invocation params\n if (config) {\n if (config.temperature != null) span.setAttribute('neatlogs.llm.temperature', config.temperature);\n if (config.topP != null) span.setAttribute('neatlogs.llm.top_p', config.topP);\n if (config.topK != null) span.setAttribute('neatlogs.llm.top_k', config.topK);\n const maxTokens = config.maxOutputTokens ?? config.max_output_tokens;\n if (maxTokens != null) span.setAttribute('neatlogs.llm.max_tokens', maxTokens);\n\n // Blob the backend reads for metadata.model_settings (the UI source).\n const params: Record<string, any> = {};\n if (config.temperature != null) params.temperature = config.temperature;\n if (config.topP != null) params.top_p = config.topP;\n if (config.topK != null) params.top_k = config.topK;\n if (maxTokens != null) params.max_tokens = maxTokens;\n if (config.frequencyPenalty != null) params.frequency_penalty = config.frequencyPenalty;\n if (config.presencePenalty != null) params.presence_penalty = config.presencePenalty;\n if (Object.keys(params).length > 0) {\n span.setAttribute('neatlogs.llm.invocation_parameters', JSON.stringify(params));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Streaming support — @google/genai stream is an async iterable of chunks\n// ---------------------------------------------------------------------------\n\nfunction wrapStream(stream: any, span: Span): any {\n const chunks: any[] = [];\n const originalAsyncIterator = stream?.[Symbol.asyncIterator]?.bind(stream);\n\n if (!originalAsyncIterator) {\n finalizeStreamChunks(span, chunks);\n return stream;\n }\n\n const wrapped = Object.create(Object.getPrototypeOf(stream));\n Object.assign(wrapped, stream);\n\n wrapped[Symbol.asyncIterator] = function () {\n const iterator = originalAsyncIterator();\n return {\n async next(): Promise<IteratorResult<any>> {\n try {\n const result = await iterator.next();\n if (result.done) {\n finalizeStreamChunks(span, chunks);\n return result;\n }\n chunks.push(result.value);\n return result;\n } catch (err) {\n recordError(span, err);\n throw err;\n }\n },\n async return(value?: any): Promise<IteratorResult<any>> {\n finalizeStreamChunks(span, chunks);\n return iterator.return?.(value) ?? { done: true, value: undefined };\n },\n async throw(err?: any): Promise<IteratorResult<any>> {\n recordError(span, err);\n return iterator.throw?.(err) ?? { done: true, value: undefined };\n },\n };\n };\n\n return wrapped;\n}\n\nfunction finalizeStreamChunks(span: Span, chunks: any[]): void {\n const textParts: string[] = [];\n let finishReason = '';\n let usage: any = null;\n\n for (const chunk of chunks) {\n for (const candidate of chunk?.candidates ?? []) {\n for (const part of candidate?.content?.parts ?? []) {\n if (part?.text && !part?.thought) textParts.push(part.text);\n }\n if (candidate?.finishReason) finishReason = candidate.finishReason;\n }\n if (chunk?.usageMetadata) usage = chunk.usageMetadata;\n }\n\n const fullText = textParts.join('');\n if (fullText) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', fullText);\n }\n if (finishReason) span.setAttribute('neatlogs.llm.finish_reason', String(finishReason));\n setUsage(span, usage);\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\n// ---------------------------------------------------------------------------\n// Non-streaming response finalization\n// ---------------------------------------------------------------------------\n\nfunction finalizeResponse(span: Span, response: any): void {\n const textParts: string[] = [];\n let toolIdx = 0;\n\n for (const candidate of response?.candidates ?? []) {\n for (const part of candidate?.content?.parts ?? []) {\n if (part?.text && !part?.thought) {\n textParts.push(part.text);\n } else if (part?.thought && part?.text) {\n span.setAttribute('neatlogs.llm.output_messages.0.thinking', part.text);\n } else if (part?.functionCall) {\n const fc = part.functionCall;\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.name`, fc?.name ?? '');\n span.setAttribute(`neatlogs.llm.tool_calls.${toolIdx}.arguments`, safeStringify(fc?.args ?? {}));\n toolIdx++;\n }\n }\n if (candidate?.finishReason) span.setAttribute('neatlogs.llm.finish_reason', String(candidate.finishReason));\n }\n\n if (textParts.length) {\n span.setAttribute('neatlogs.llm.output_messages.0.role', 'assistant');\n span.setAttribute('neatlogs.llm.output_messages.0.content', textParts.join(''));\n }\n\n setUsage(span, response?.usageMetadata);\n\n span.setStatus({ code: SpanStatusCode.OK });\n span.end();\n}\n\nfunction setUsage(span: Span, usage: any): void {\n if (!usage) return;\n if (usage.promptTokenCount != null) span.setAttribute('neatlogs.llm.token_count.prompt', usage.promptTokenCount);\n if (usage.candidatesTokenCount != null) span.setAttribute('neatlogs.llm.token_count.completion', usage.candidatesTokenCount);\n if (usage.totalTokenCount != null) span.setAttribute('neatlogs.llm.token_count.total', usage.totalTokenCount);\n if (usage.cachedContentTokenCount != null) span.setAttribute('neatlogs.llm.token_count.cache_read', usage.cachedContentTokenCount);\n if (usage.thoughtsTokenCount != null) span.setAttribute('neatlogs.llm.token_count.reasoning', usage.thoughtsTokenCount);\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nfunction safeStringify(value: unknown): string {\n try {\n return typeof value === 'string' ? value : JSON.stringify(value);\n } catch {\n return '';\n }\n}\n\nfunction recordError(span: Span, err: unknown): void {\n if (err instanceof Error) {\n span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });\n span.recordException(err);\n } else {\n span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });\n }\n span.end();\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neatlogs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "AI agent debugging, collaboration, and trace observability. Built for teams using CrewAI, OpenAI, and more.",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -46,6 +46,66 @@
|
|
|
46
46
|
"default": "./dist/anthropic.cjs"
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
|
+
"./azure-openai": {
|
|
50
|
+
"import": {
|
|
51
|
+
"types": "./dist/azure-openai.d.ts",
|
|
52
|
+
"default": "./dist/azure-openai.mjs"
|
|
53
|
+
},
|
|
54
|
+
"require": {
|
|
55
|
+
"types": "./dist/azure-openai.d.ts",
|
|
56
|
+
"default": "./dist/azure-openai.cjs"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"./vertex-ai": {
|
|
60
|
+
"import": {
|
|
61
|
+
"types": "./dist/vertex-ai.d.ts",
|
|
62
|
+
"default": "./dist/vertex-ai.mjs"
|
|
63
|
+
},
|
|
64
|
+
"require": {
|
|
65
|
+
"types": "./dist/vertex-ai.d.ts",
|
|
66
|
+
"default": "./dist/vertex-ai.cjs"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"./bedrock": {
|
|
70
|
+
"import": {
|
|
71
|
+
"types": "./dist/bedrock.d.ts",
|
|
72
|
+
"default": "./dist/bedrock.mjs"
|
|
73
|
+
},
|
|
74
|
+
"require": {
|
|
75
|
+
"types": "./dist/bedrock.d.ts",
|
|
76
|
+
"default": "./dist/bedrock.cjs"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"./claude-agent-sdk": {
|
|
80
|
+
"import": {
|
|
81
|
+
"types": "./dist/claude-agent-sdk.d.ts",
|
|
82
|
+
"default": "./dist/claude-agent-sdk.mjs"
|
|
83
|
+
},
|
|
84
|
+
"require": {
|
|
85
|
+
"types": "./dist/claude-agent-sdk.d.ts",
|
|
86
|
+
"default": "./dist/claude-agent-sdk.cjs"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"./openrouter-agent": {
|
|
90
|
+
"import": {
|
|
91
|
+
"types": "./dist/openrouter-agent.d.ts",
|
|
92
|
+
"default": "./dist/openrouter-agent.mjs"
|
|
93
|
+
},
|
|
94
|
+
"require": {
|
|
95
|
+
"types": "./dist/openrouter-agent.d.ts",
|
|
96
|
+
"default": "./dist/openrouter-agent.cjs"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"./opencode": {
|
|
100
|
+
"import": {
|
|
101
|
+
"types": "./dist/opencode-plugin.d.ts",
|
|
102
|
+
"default": "./dist/opencode-plugin.mjs"
|
|
103
|
+
},
|
|
104
|
+
"require": {
|
|
105
|
+
"types": "./dist/opencode-plugin.d.ts",
|
|
106
|
+
"default": "./dist/opencode-plugin.cjs"
|
|
107
|
+
}
|
|
108
|
+
},
|
|
49
109
|
"./langchain": {
|
|
50
110
|
"import": {
|
|
51
111
|
"types": "./dist/langchain.d.ts",
|
|
@@ -95,6 +155,16 @@
|
|
|
95
155
|
"types": "./dist/pi-agent.d.ts",
|
|
96
156
|
"default": "./dist/pi-agent.cjs"
|
|
97
157
|
}
|
|
158
|
+
},
|
|
159
|
+
"./browser": {
|
|
160
|
+
"import": {
|
|
161
|
+
"types": "./dist/browser.d.ts",
|
|
162
|
+
"default": "./dist/browser.mjs"
|
|
163
|
+
},
|
|
164
|
+
"require": {
|
|
165
|
+
"types": "./dist/browser.d.ts",
|
|
166
|
+
"default": "./dist/browser.cjs"
|
|
167
|
+
}
|
|
98
168
|
}
|
|
99
169
|
},
|
|
100
170
|
"files": [
|
|
@@ -118,6 +188,10 @@
|
|
|
118
188
|
"example:langgraph": "tsx examples/langgraph_multiagent/main.ts",
|
|
119
189
|
"example:marketing": "tsx examples/marketing_strategy_demo/main.ts",
|
|
120
190
|
"example:reasoning": "tsx examples/reasoning_model_workflow/main.ts",
|
|
191
|
+
"example:azure-openai": "tsx examples/sdk_examples/azure_openai_basic/main.ts",
|
|
192
|
+
"example:vertex-ai": "tsx examples/sdk_examples/vertex_ai_basic/main.ts",
|
|
193
|
+
"example:bedrock": "tsx examples/sdk_examples/bedrock_basic/main.ts",
|
|
194
|
+
"example:openrouter": "tsx examples/sdk_examples/openrouter_agent_basic/main.ts",
|
|
121
195
|
"test:examples:original7": "node scripts/run-original7-examples.mjs",
|
|
122
196
|
"verify:logs": "node scripts/verify-original7-logs.mjs"
|
|
123
197
|
},
|
|
@@ -163,6 +237,7 @@
|
|
|
163
237
|
"@langchain/google-genai": "^0.2.18",
|
|
164
238
|
"@langchain/langgraph": "^0.3.12",
|
|
165
239
|
"@langchain/openai": "^0.6.17",
|
|
240
|
+
"@openrouter/agent": "^0.7.1",
|
|
166
241
|
"@types/node": "^20.0.0",
|
|
167
242
|
"ai": "^6.0.190",
|
|
168
243
|
"dotenv": "^17.4.2",
|