langwatch 0.0.2 → 0.0.3
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/{chunk-GOA2HL4A.mjs → chunk-AP23NJ57.mjs} +29 -2
- package/dist/{chunk-GOA2HL4A.mjs.map → chunk-AP23NJ57.mjs.map} +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +44 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19 -14
- package/dist/index.mjs.map +1 -1
- package/dist/{utils-s3gGR6vj.d.mts → utils-Dg5eWsAz.d.mts} +4 -2
- package/dist/{utils-s3gGR6vj.d.ts → utils-Dg5eWsAz.d.ts} +4 -2
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +28 -0
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +3 -1
- package/example/package-lock.json +2 -2
- package/package.json +2 -2
- package/src/index.test.ts +41 -0
- package/src/index.ts +19 -13
- package/src/types.ts +2 -1
- package/src/utils.ts +45 -0
package/src/index.ts
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
type RAGSpan,
|
|
25
25
|
type SpanInputOutput,
|
|
26
26
|
} from "./types";
|
|
27
|
-
import { convertFromVercelAIMessages } from "./utils";
|
|
27
|
+
import { captureError, convertFromVercelAIMessages } from "./utils";
|
|
28
28
|
|
|
29
29
|
export type {
|
|
30
30
|
BaseSpan,
|
|
@@ -39,7 +39,7 @@ export type {
|
|
|
39
39
|
SpanInputOutput,
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
export { convertFromVercelAIMessages };
|
|
42
|
+
export { convertFromVercelAIMessages, captureError };
|
|
43
43
|
|
|
44
44
|
export class LangWatch extends EventEmitter {
|
|
45
45
|
apiKey: string | undefined;
|
|
@@ -55,9 +55,10 @@ export class LangWatch extends EventEmitter {
|
|
|
55
55
|
super();
|
|
56
56
|
const apiKey_ = apiKey ?? process.env.LANGWATCH_API_KEY;
|
|
57
57
|
if (!apiKey_) {
|
|
58
|
-
|
|
59
|
-
"
|
|
58
|
+
const error = new Error(
|
|
59
|
+
"LangWatch API key is not set, please set the LANGWATCH_API_KEY environment variable or pass it in the constructor. Traces will not be captured."
|
|
60
60
|
);
|
|
61
|
+
this.emit("error", error);
|
|
61
62
|
}
|
|
62
63
|
this.apiKey = apiKey_;
|
|
63
64
|
this.endpoint = endpoint;
|
|
@@ -99,10 +100,9 @@ export class LangWatch extends EventEmitter {
|
|
|
99
100
|
|
|
100
101
|
if (!this.apiKey) {
|
|
101
102
|
const error = new Error(
|
|
102
|
-
"
|
|
103
|
+
"LangWatch API key is not set, LLMs traces will not be sent, go to https://langwatch.ai to set it up"
|
|
103
104
|
);
|
|
104
105
|
this.emit("error", error);
|
|
105
|
-
console.warn(error.message);
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -117,15 +117,14 @@ export class LangWatch extends EventEmitter {
|
|
|
117
117
|
|
|
118
118
|
if (response.status === 429) {
|
|
119
119
|
const error = new Error(
|
|
120
|
-
"
|
|
120
|
+
"Rate limit exceeded, dropping message from being sent to LangWatch. Please check your dashboard to upgrade your plan."
|
|
121
121
|
);
|
|
122
122
|
this.emit("error", error);
|
|
123
|
-
console.warn(error.message);
|
|
124
123
|
return;
|
|
125
124
|
}
|
|
126
125
|
if (!response.ok) {
|
|
127
126
|
const error = new Error(
|
|
128
|
-
`
|
|
127
|
+
`Failed to send trace, status: ${response.status}`
|
|
129
128
|
);
|
|
130
129
|
this.emit("error", error);
|
|
131
130
|
throw error;
|
|
@@ -214,8 +213,6 @@ export class LangWatchTrace {
|
|
|
214
213
|
if (error instanceof ZodError) {
|
|
215
214
|
console.warn("[LangWatch] ⚠️ Failed to parse trace");
|
|
216
215
|
console.warn(fromZodError(error).message);
|
|
217
|
-
} else {
|
|
218
|
-
console.warn(error);
|
|
219
216
|
}
|
|
220
217
|
this.client.emit("error", error);
|
|
221
218
|
}
|
|
@@ -266,6 +263,14 @@ export class LangWatchSpan implements PendingBaseSpan {
|
|
|
266
263
|
}
|
|
267
264
|
|
|
268
265
|
update(params: Partial<Omit<PendingBaseSpan, "spanId" | "parentId">>) {
|
|
266
|
+
if (Object.isFrozen(this)) {
|
|
267
|
+
const error = new Error(
|
|
268
|
+
`Tried to update span ${this.spanId}, but the span is already finished, discarding update`
|
|
269
|
+
);
|
|
270
|
+
this.trace.client.emit("error", error);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
269
274
|
if (params.type) {
|
|
270
275
|
this.type = params.type;
|
|
271
276
|
}
|
|
@@ -322,6 +327,8 @@ export class LangWatchSpan implements PendingBaseSpan {
|
|
|
322
327
|
this.update(params);
|
|
323
328
|
}
|
|
324
329
|
|
|
330
|
+
Object.freeze(this);
|
|
331
|
+
|
|
325
332
|
try {
|
|
326
333
|
const finalSpan = spanSchema.parse(
|
|
327
334
|
camelToSnakeCaseNested({
|
|
@@ -332,6 +339,7 @@ export class LangWatchSpan implements PendingBaseSpan {
|
|
|
332
339
|
...this.timestamps,
|
|
333
340
|
finishedAt: this.timestamps.finishedAt,
|
|
334
341
|
},
|
|
342
|
+
...(this.error && { error: captureError(this.error) }),
|
|
335
343
|
}) as ServerSpan
|
|
336
344
|
);
|
|
337
345
|
this.trace.onEnd(finalSpan);
|
|
@@ -339,8 +347,6 @@ export class LangWatchSpan implements PendingBaseSpan {
|
|
|
339
347
|
if (error instanceof ZodError) {
|
|
340
348
|
console.warn("[LangWatch] ⚠️ Failed to parse span");
|
|
341
349
|
console.warn(fromZodError(error).message);
|
|
342
|
-
} else {
|
|
343
|
-
console.warn(error);
|
|
344
350
|
}
|
|
345
351
|
this.trace.client.emit("error", error);
|
|
346
352
|
}
|
package/src/types.ts
CHANGED
|
@@ -41,9 +41,10 @@ export type SpanInputOutput =
|
|
|
41
41
|
| (TypedValueChatMessages & { type: ChatMessage });
|
|
42
42
|
|
|
43
43
|
export type ConvertServerSpan<T extends ServerBaseSpan> =
|
|
44
|
-
SnakeToCamelCaseNested<Omit<T, "input" | "outputs">> & {
|
|
44
|
+
SnakeToCamelCaseNested<Omit<T, "input" | "outputs" | "error">> & {
|
|
45
45
|
input?: SpanInputOutput | null;
|
|
46
46
|
outputs: SpanInputOutput[];
|
|
47
|
+
error?: T["error"] | NonNullable<unknown>;
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
export type PendingSpan<T extends BaseSpan> = Omit<
|
package/src/utils.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { convertUint8ArrayToBase64 } from "@ai-sdk/provider-utils";
|
|
2
2
|
import { type ImagePart, type CoreMessage } from "ai";
|
|
3
3
|
import { type ChatMessage } from "./types";
|
|
4
|
+
import { type ErrorCapture } from "./server/types/tracer";
|
|
4
5
|
|
|
5
6
|
const convertImageToUrl = (
|
|
6
7
|
image: ImagePart["image"],
|
|
@@ -132,3 +133,47 @@ export function convertFromVercelAIMessages(
|
|
|
132
133
|
|
|
133
134
|
return lwMessages;
|
|
134
135
|
}
|
|
136
|
+
|
|
137
|
+
export const captureError = (error: unknown): ErrorCapture => {
|
|
138
|
+
if (
|
|
139
|
+
error &&
|
|
140
|
+
typeof error === "object" &&
|
|
141
|
+
"has_error" in error &&
|
|
142
|
+
"message" in error &&
|
|
143
|
+
"stacktrace" in error
|
|
144
|
+
) {
|
|
145
|
+
return error as ErrorCapture;
|
|
146
|
+
} else if (error instanceof Error) {
|
|
147
|
+
return {
|
|
148
|
+
has_error: true,
|
|
149
|
+
message: error.message,
|
|
150
|
+
stacktrace: error.stack ? error.stack.split("\n") : [],
|
|
151
|
+
};
|
|
152
|
+
} else if (typeof error === "object" && error !== null) {
|
|
153
|
+
const err = error as { message: unknown; stack: unknown };
|
|
154
|
+
const message =
|
|
155
|
+
typeof err.message === "string"
|
|
156
|
+
? err.message
|
|
157
|
+
: "An unknown error occurred";
|
|
158
|
+
const stacktrace =
|
|
159
|
+
typeof err.stack === "string"
|
|
160
|
+
? err.stack.split("\n")
|
|
161
|
+
: Array.isArray(err.stack) &&
|
|
162
|
+
err.stack.length > 0 &&
|
|
163
|
+
typeof err.stack[0] === "string"
|
|
164
|
+
? err.stack
|
|
165
|
+
: ["No stack trace available"];
|
|
166
|
+
return {
|
|
167
|
+
has_error: true,
|
|
168
|
+
message,
|
|
169
|
+
stacktrace,
|
|
170
|
+
};
|
|
171
|
+
} else {
|
|
172
|
+
// Handle primitives and other types that are not an error object
|
|
173
|
+
return {
|
|
174
|
+
has_error: true,
|
|
175
|
+
message: String(error),
|
|
176
|
+
stacktrace: [],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
};
|