langwatch 0.1.7 → 0.3.0-prerelease.1

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.
Files changed (235) hide show
  1. package/.editorconfig +16 -0
  2. package/LICENSE +7 -0
  3. package/README.md +268 -1
  4. package/copy-types.sh +19 -8
  5. package/examples/langchain/.env.example +2 -0
  6. package/examples/langchain/README.md +42 -0
  7. package/examples/langchain/package-lock.json +2930 -0
  8. package/examples/langchain/package.json +27 -0
  9. package/examples/langchain/src/cli-markdown.d.ts +137 -0
  10. package/examples/langchain/src/index.ts +109 -0
  11. package/examples/langchain/tsconfig.json +25 -0
  12. package/examples/langgraph/.env.example +2 -0
  13. package/examples/langgraph/README.md +42 -0
  14. package/examples/langgraph/package-lock.json +3031 -0
  15. package/examples/langgraph/package.json +28 -0
  16. package/examples/langgraph/src/cli-markdown.d.ts +137 -0
  17. package/examples/langgraph/src/index.ts +196 -0
  18. package/examples/langgraph/tsconfig.json +25 -0
  19. package/examples/mastra/.env.example +2 -0
  20. package/examples/mastra/README.md +57 -0
  21. package/examples/mastra/package-lock.json +5296 -0
  22. package/examples/mastra/package.json +32 -0
  23. package/examples/mastra/src/cli-markdown.d.ts +137 -0
  24. package/examples/mastra/src/index.ts +120 -0
  25. package/examples/mastra/src/mastra/agents/weather-agent.ts +30 -0
  26. package/examples/mastra/src/mastra/index.ts +21 -0
  27. package/examples/mastra/src/mastra/tools/weather-tool.ts +102 -0
  28. package/examples/mastra/tsconfig.json +25 -0
  29. package/examples/vercel-ai/.env.example +2 -0
  30. package/examples/vercel-ai/README.md +38 -0
  31. package/examples/vercel-ai/package-lock.json +2571 -0
  32. package/examples/vercel-ai/package.json +27 -0
  33. package/examples/vercel-ai/src/cli-markdown.d.ts +137 -0
  34. package/examples/vercel-ai/src/index.ts +110 -0
  35. package/examples/vercel-ai/src/instrumentation.ts +9 -0
  36. package/examples/vercel-ai/tsconfig.json +25 -0
  37. package/package.json +80 -33
  38. package/src/__tests__/client-browser.test.ts +92 -0
  39. package/src/__tests__/client-node.test.ts +76 -0
  40. package/src/__tests__/client.test.ts +71 -0
  41. package/src/__tests__/integration/client-browser.test.ts +46 -0
  42. package/src/__tests__/integration/client-node.test.ts +46 -0
  43. package/src/client-browser.ts +70 -0
  44. package/src/client-node.ts +82 -0
  45. package/src/client-shared.ts +72 -0
  46. package/src/client.ts +119 -0
  47. package/src/evaluation/__tests__/record-evaluation.test.ts +112 -0
  48. package/src/evaluation/__tests__/run-evaluation.test.ts +171 -0
  49. package/src/evaluation/index.ts +2 -0
  50. package/src/evaluation/record-evaluation.ts +101 -0
  51. package/src/evaluation/run-evaluation.ts +133 -0
  52. package/src/evaluation/tracer.ts +3 -0
  53. package/src/evaluation/types.ts +23 -0
  54. package/src/index.ts +10 -591
  55. package/src/internal/api/__tests__/errors.test.ts +98 -0
  56. package/src/internal/api/client.ts +30 -0
  57. package/src/internal/api/errors.ts +32 -0
  58. package/src/internal/generated/types/.gitkeep +0 -0
  59. package/src/observability/__tests__/integration/base.test.ts +74 -0
  60. package/src/observability/__tests__/integration/browser-setup-ordering.test.ts +60 -0
  61. package/src/observability/__tests__/integration/complex-nested-spans.test.ts +29 -0
  62. package/src/observability/__tests__/integration/error-handling.test.ts +24 -0
  63. package/src/observability/__tests__/integration/langwatch-disabled-otel.test.ts +24 -0
  64. package/src/observability/__tests__/integration/langwatch-first-then-vercel.test.ts +24 -0
  65. package/src/observability/__tests__/integration/multiple-setup-attempts.test.ts +27 -0
  66. package/src/observability/__tests__/integration/otel-ordering.test.ts +27 -0
  67. package/src/observability/__tests__/integration/vercel-configurations.test.ts +20 -0
  68. package/src/observability/__tests__/integration/vercel-first-then-langwatch.test.ts +27 -0
  69. package/src/observability/__tests__/span.test.ts +214 -0
  70. package/src/observability/__tests__/trace.test.ts +180 -0
  71. package/src/observability/exporters/index.ts +1 -0
  72. package/src/observability/exporters/langwatch-exporter.ts +53 -0
  73. package/src/observability/index.ts +4 -0
  74. package/src/observability/instrumentation/langchain/__tests__/integration/langchain-chatbot.test.ts +112 -0
  75. package/src/observability/instrumentation/langchain/__tests__/langchain.test.ts +284 -0
  76. package/src/observability/instrumentation/langchain/index.ts +624 -0
  77. package/src/observability/processors/__tests__/filterable-batch-span-exporter.test.ts +98 -0
  78. package/src/observability/processors/filterable-batch-span-processor.ts +99 -0
  79. package/src/observability/processors/index.ts +1 -0
  80. package/src/observability/semconv/attributes.ts +185 -0
  81. package/src/observability/semconv/events.ts +42 -0
  82. package/src/observability/semconv/index.ts +16 -0
  83. package/src/observability/semconv/values.ts +159 -0
  84. package/src/observability/span.ts +728 -0
  85. package/src/observability/trace.ts +301 -0
  86. package/src/prompt/__tests__/prompt.test.ts +139 -0
  87. package/src/prompt/get-prompt-version.ts +49 -0
  88. package/src/prompt/get-prompt.ts +44 -0
  89. package/src/prompt/index.ts +3 -0
  90. package/src/prompt/prompt.ts +133 -0
  91. package/src/prompt/service.ts +221 -0
  92. package/src/prompt/tracer.ts +3 -0
  93. package/src/prompt/types.ts +0 -0
  94. package/ts-to-zod.config.js +11 -0
  95. package/tsconfig.json +3 -9
  96. package/tsup.config.ts +11 -1
  97. package/vitest.config.ts +1 -0
  98. package/dist/chunk-FWBCQQYZ.mjs +0 -711
  99. package/dist/chunk-FWBCQQYZ.mjs.map +0 -1
  100. package/dist/index.d.mts +0 -1010
  101. package/dist/index.d.ts +0 -1010
  102. package/dist/index.js +0 -27294
  103. package/dist/index.js.map +0 -1
  104. package/dist/index.mjs +0 -959
  105. package/dist/index.mjs.map +0 -1
  106. package/dist/utils-B0pgWcps.d.mts +0 -303
  107. package/dist/utils-B0pgWcps.d.ts +0 -303
  108. package/dist/utils.d.mts +0 -2
  109. package/dist/utils.d.ts +0 -2
  110. package/dist/utils.js +0 -703
  111. package/dist/utils.js.map +0 -1
  112. package/dist/utils.mjs +0 -11
  113. package/dist/utils.mjs.map +0 -1
  114. package/example/.env.example +0 -12
  115. package/example/.eslintrc.json +0 -26
  116. package/example/LICENSE +0 -13
  117. package/example/README.md +0 -12
  118. package/example/app/(chat)/chat/[id]/page.tsx +0 -60
  119. package/example/app/(chat)/layout.tsx +0 -14
  120. package/example/app/(chat)/page.tsx +0 -27
  121. package/example/app/actions.ts +0 -156
  122. package/example/app/globals.css +0 -76
  123. package/example/app/guardrails/page.tsx +0 -26
  124. package/example/app/langchain/page.tsx +0 -27
  125. package/example/app/langchain-rag/page.tsx +0 -28
  126. package/example/app/late-update/page.tsx +0 -27
  127. package/example/app/layout.tsx +0 -64
  128. package/example/app/login/actions.ts +0 -71
  129. package/example/app/login/page.tsx +0 -18
  130. package/example/app/manual/page.tsx +0 -27
  131. package/example/app/new/page.tsx +0 -5
  132. package/example/app/opengraph-image.png +0 -0
  133. package/example/app/share/[id]/page.tsx +0 -58
  134. package/example/app/signup/actions.ts +0 -111
  135. package/example/app/signup/page.tsx +0 -18
  136. package/example/app/twitter-image.png +0 -0
  137. package/example/auth.config.ts +0 -42
  138. package/example/auth.ts +0 -45
  139. package/example/components/button-scroll-to-bottom.tsx +0 -36
  140. package/example/components/chat-history.tsx +0 -49
  141. package/example/components/chat-list.tsx +0 -52
  142. package/example/components/chat-message-actions.tsx +0 -40
  143. package/example/components/chat-message.tsx +0 -80
  144. package/example/components/chat-panel.tsx +0 -139
  145. package/example/components/chat-share-dialog.tsx +0 -95
  146. package/example/components/chat.tsx +0 -84
  147. package/example/components/clear-history.tsx +0 -75
  148. package/example/components/empty-screen.tsx +0 -38
  149. package/example/components/external-link.tsx +0 -29
  150. package/example/components/footer.tsx +0 -19
  151. package/example/components/header.tsx +0 -114
  152. package/example/components/login-button.tsx +0 -42
  153. package/example/components/login-form.tsx +0 -97
  154. package/example/components/markdown.tsx +0 -9
  155. package/example/components/prompt-form.tsx +0 -115
  156. package/example/components/providers.tsx +0 -17
  157. package/example/components/sidebar-actions.tsx +0 -125
  158. package/example/components/sidebar-desktop.tsx +0 -19
  159. package/example/components/sidebar-footer.tsx +0 -16
  160. package/example/components/sidebar-item.tsx +0 -124
  161. package/example/components/sidebar-items.tsx +0 -42
  162. package/example/components/sidebar-list.tsx +0 -38
  163. package/example/components/sidebar-mobile.tsx +0 -31
  164. package/example/components/sidebar-toggle.tsx +0 -24
  165. package/example/components/sidebar.tsx +0 -21
  166. package/example/components/signup-form.tsx +0 -95
  167. package/example/components/stocks/events-skeleton.tsx +0 -31
  168. package/example/components/stocks/events.tsx +0 -30
  169. package/example/components/stocks/index.tsx +0 -36
  170. package/example/components/stocks/message.tsx +0 -134
  171. package/example/components/stocks/spinner.tsx +0 -16
  172. package/example/components/stocks/stock-purchase.tsx +0 -146
  173. package/example/components/stocks/stock-skeleton.tsx +0 -22
  174. package/example/components/stocks/stock.tsx +0 -210
  175. package/example/components/stocks/stocks-skeleton.tsx +0 -9
  176. package/example/components/stocks/stocks.tsx +0 -67
  177. package/example/components/tailwind-indicator.tsx +0 -14
  178. package/example/components/theme-toggle.tsx +0 -31
  179. package/example/components/ui/alert-dialog.tsx +0 -141
  180. package/example/components/ui/badge.tsx +0 -36
  181. package/example/components/ui/button.tsx +0 -57
  182. package/example/components/ui/codeblock.tsx +0 -148
  183. package/example/components/ui/dialog.tsx +0 -122
  184. package/example/components/ui/dropdown-menu.tsx +0 -205
  185. package/example/components/ui/icons.tsx +0 -507
  186. package/example/components/ui/input.tsx +0 -25
  187. package/example/components/ui/label.tsx +0 -26
  188. package/example/components/ui/select.tsx +0 -164
  189. package/example/components/ui/separator.tsx +0 -31
  190. package/example/components/ui/sheet.tsx +0 -140
  191. package/example/components/ui/sonner.tsx +0 -31
  192. package/example/components/ui/switch.tsx +0 -29
  193. package/example/components/ui/textarea.tsx +0 -24
  194. package/example/components/ui/tooltip.tsx +0 -30
  195. package/example/components/user-menu.tsx +0 -53
  196. package/example/components.json +0 -17
  197. package/example/instrumentation.ts +0 -11
  198. package/example/lib/chat/guardrails.tsx +0 -181
  199. package/example/lib/chat/langchain-rag.tsx +0 -191
  200. package/example/lib/chat/langchain.tsx +0 -112
  201. package/example/lib/chat/late-update.tsx +0 -208
  202. package/example/lib/chat/manual.tsx +0 -605
  203. package/example/lib/chat/vercel-ai.tsx +0 -576
  204. package/example/lib/hooks/use-copy-to-clipboard.tsx +0 -33
  205. package/example/lib/hooks/use-enter-submit.tsx +0 -23
  206. package/example/lib/hooks/use-local-storage.ts +0 -24
  207. package/example/lib/hooks/use-scroll-anchor.tsx +0 -86
  208. package/example/lib/hooks/use-sidebar.tsx +0 -60
  209. package/example/lib/hooks/use-streamable-text.ts +0 -25
  210. package/example/lib/types.ts +0 -41
  211. package/example/lib/utils.ts +0 -89
  212. package/example/middleware.ts +0 -8
  213. package/example/next-env.d.ts +0 -5
  214. package/example/next.config.js +0 -16
  215. package/example/package-lock.json +0 -9990
  216. package/example/package.json +0 -84
  217. package/example/pnpm-lock.yaml +0 -5712
  218. package/example/postcss.config.js +0 -6
  219. package/example/prettier.config.cjs +0 -34
  220. package/example/public/apple-touch-icon.png +0 -0
  221. package/example/public/favicon-16x16.png +0 -0
  222. package/example/public/favicon.ico +0 -0
  223. package/example/public/next.svg +0 -1
  224. package/example/public/thirteen.svg +0 -1
  225. package/example/public/vercel.svg +0 -1
  226. package/example/tailwind.config.ts +0 -81
  227. package/example/tsconfig.json +0 -35
  228. package/src/LangWatchExporter.ts +0 -91
  229. package/src/evaluations.ts +0 -219
  230. package/src/index.test.ts +0 -402
  231. package/src/langchain.ts +0 -557
  232. package/src/typeUtils.ts +0 -89
  233. package/src/types.ts +0 -79
  234. package/src/utils.ts +0 -205
  235. /package/src/{server/types → internal/generated/openapi}/.gitkeep +0 -0
package/dist/index.mjs DELETED
@@ -1,959 +0,0 @@
1
- import {
2
- __spreadProps,
3
- __spreadValues,
4
- autoconvertTypedValues,
5
- captureError,
6
- collectorRESTParamsSchema,
7
- convertFromVercelAIMessages,
8
- reservedSpanParamsSchema,
9
- reservedTraceMetadataSchema,
10
- spanSchema
11
- } from "./chunk-FWBCQQYZ.mjs";
12
-
13
- // src/index.ts
14
- import EventEmitter from "eventemitter3";
15
- import { nanoid } from "nanoid";
16
- import { ZodError } from "zod";
17
- import { fromZodError } from "zod-validation-error";
18
-
19
- // package.json
20
- var version = "0.1.7";
21
-
22
- // src/evaluations.ts
23
- var evaluate = async (params) => {
24
- const slug = "slug" in params ? params.slug : params.evaluator;
25
- const span = optionalCreateSpan({
26
- trace: params.trace,
27
- span: params.span,
28
- name: params.name ? params.name : slug,
29
- type: params.asGuardrail ? "guardrail" : "evaluation"
30
- });
31
- try {
32
- const requestParams = prepareData(__spreadProps(__spreadValues({}, params), {
33
- slug,
34
- traceId: span == null ? void 0 : span.trace.traceId,
35
- spanId: span == null ? void 0 : span.spanId,
36
- span
37
- }));
38
- const response = await fetch(requestParams.url, {
39
- method: "POST",
40
- headers: requestParams.headers,
41
- body: JSON.stringify(requestParams.json)
42
- });
43
- if (!response.ok) {
44
- throw new Error(`HTTP error! status: ${response.status}`);
45
- }
46
- const result = await response.json();
47
- return handleResponse(result, span, params.asGuardrail);
48
- } catch (e) {
49
- return handleException(e, span, params.asGuardrail);
50
- }
51
- };
52
- var optionalCreateSpan = ({
53
- trace,
54
- span,
55
- name,
56
- type
57
- }) => {
58
- if (span) {
59
- return span.startSpan({ name, type });
60
- } else if (trace) {
61
- return trace.startSpan({ name, type });
62
- }
63
- return void 0;
64
- };
65
- var prepareData = (params) => {
66
- var _a;
67
- const data = {};
68
- if (params.input) data.input = params.input;
69
- if (params.output) data.output = params.output;
70
- if (params.expectedOutput) data.expected_output = params.expectedOutput;
71
- if (params.contexts && params.contexts.length > 0)
72
- data.contexts = params.contexts;
73
- if (params.conversation && params.conversation.length > 0)
74
- data.conversation = params.conversation;
75
- if (params.span) {
76
- params.span.update({
77
- input: { type: "json", value: data },
78
- params: params.settings
79
- });
80
- }
81
- return {
82
- url: `${process.env.LANGWATCH_ENDPOINT}/api/evaluations/${params.slug}/evaluate`,
83
- json: {
84
- trace_id: params.traceId,
85
- span_id: params.spanId,
86
- name: params.name,
87
- data,
88
- settings: params.settings,
89
- as_guardrail: params.asGuardrail
90
- },
91
- headers: {
92
- "X-Auth-Token": (_a = process.env.LANGWATCH_API_KEY) != null ? _a : "",
93
- "Content-Type": "application/json"
94
- }
95
- };
96
- };
97
- var handleResponse = (response, span, asGuardrail = false) => {
98
- var _a;
99
- if (response.status === "error") {
100
- response.details = (_a = response.details) != null ? _a : "";
101
- }
102
- for (const key of Object.keys(response)) {
103
- if (response[key] === null || response[key] === void 0) {
104
- delete response[key];
105
- }
106
- }
107
- if (span) {
108
- const output = asGuardrail ? {
109
- type: "guardrail_result",
110
- value: response
111
- } : {
112
- type: "evaluation_result",
113
- value: response
114
- };
115
- span.update({ output });
116
- if (response.cost) {
117
- span.update({
118
- metrics: {
119
- cost: response.cost.amount
120
- }
121
- });
122
- }
123
- span.end();
124
- }
125
- return response;
126
- };
127
- var handleException = (e, span, asGuardrail = false) => {
128
- const response = {
129
- status: "error",
130
- details: e.toString()
131
- };
132
- if (asGuardrail) {
133
- response.passed = true;
134
- }
135
- return handleResponse(response, span, asGuardrail);
136
- };
137
-
138
- // src/langchain.ts
139
- import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
140
- import {
141
- AIMessage,
142
- AIMessageChunk,
143
- FunctionMessage,
144
- FunctionMessageChunk,
145
- HumanMessage,
146
- HumanMessageChunk,
147
- SystemMessage,
148
- SystemMessageChunk,
149
- ToolMessage,
150
- ToolMessageChunk,
151
- mapChatMessagesToStoredMessages
152
- } from "@langchain/core/messages";
153
- import { stringify } from "javascript-stringify";
154
- var LangWatchCallbackHandler = class extends BaseCallbackHandler {
155
- constructor({ trace }) {
156
- super();
157
- this.name = "LangWatchCallbackHandler";
158
- this.spans = {};
159
- this.trace = trace;
160
- }
161
- async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, _tags, metadata, name) {
162
- this.spans[runId] = this.buildLLMSpan({
163
- llm,
164
- runId,
165
- parentRunId,
166
- input: {
167
- type: "json",
168
- value: prompts
169
- },
170
- extraParams,
171
- metadata,
172
- name
173
- });
174
- }
175
- buildLLMSpan({
176
- llm,
177
- runId,
178
- parentRunId,
179
- input,
180
- extraParams,
181
- metadata,
182
- name
183
- }) {
184
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
185
- try {
186
- const parent = this.getParent(parentRunId);
187
- const vendor = (_b = metadata == null ? void 0 : metadata.ls_provider) != null ? _b : (_a = llm.id.at(-2)) == null ? void 0 : _a.toString();
188
- const model = (_e = (_d = metadata == null ? void 0 : metadata.ls_model_name) != null ? _d : (_c = llm.kwargs) == null ? void 0 : _c.model) != null ? _e : "unknown";
189
- const span = parent.startLLMSpan({
190
- spanId: runId,
191
- name: name != null ? name : (_f = llm.id.at(-1)) == null ? void 0 : _f.toString(),
192
- input,
193
- model: [vendor, model].filter((x) => x).join("/"),
194
- params: __spreadValues({
195
- temperature: (_g = extraParams == null ? void 0 : extraParams.invocation_params) == null ? void 0 : _g.temperature
196
- }, ((_h = extraParams == null ? void 0 : extraParams.invocation_params) == null ? void 0 : _h.functions) ? { functions: (_i = extraParams == null ? void 0 : extraParams.invocation_params) == null ? void 0 : _i.functions } : {})
197
- });
198
- return span;
199
- } catch (e) {
200
- this.trace.client.emit("error", e);
201
- throw e;
202
- }
203
- }
204
- async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, name) {
205
- this.spans[runId] = this.buildLLMSpan({
206
- name,
207
- llm,
208
- runId,
209
- parentRunId,
210
- input: {
211
- type: "chat_messages",
212
- value: messages.flatMap(convertFromLangChainMessages)
213
- },
214
- extraParams,
215
- metadata
216
- });
217
- }
218
- async handleNewToken(_token, runId) {
219
- const span = this.spans[runId];
220
- if (runId && span && !span.timestamps.firstTokenAt) {
221
- span.update({
222
- timestamps: __spreadProps(__spreadValues({}, span.timestamps), { firstTokenAt: Date.now() })
223
- });
224
- }
225
- }
226
- async handleLLMEnd(response, runId, _parentRunId) {
227
- try {
228
- const span = this.spans[runId];
229
- if (!span) {
230
- return;
231
- }
232
- const outputs = [];
233
- for (const generation of response.generations) {
234
- for (const generation_ of generation) {
235
- if ("message" in generation_) {
236
- outputs.push({
237
- type: "chat_messages",
238
- value: convertFromLangChainMessages([
239
- generation_.message
240
- ])
241
- });
242
- } else if ("text" in generation_) {
243
- outputs.push({
244
- type: "text",
245
- value: generation_.text
246
- });
247
- } else {
248
- outputs.push({
249
- type: "text",
250
- value: JSON.stringify(generation_)
251
- });
252
- }
253
- }
254
- }
255
- const output = outputs.length === 1 ? outputs[0] : { type: "list", value: outputs };
256
- span.end({
257
- output
258
- // ...(metrics ? { metrics } : {}),
259
- });
260
- } catch (e) {
261
- this.trace.client.emit("error", e);
262
- throw e;
263
- }
264
- }
265
- async handleLLMError(err, runId, _parentRunId) {
266
- this.errorSpan({ runId, error: err });
267
- }
268
- async handleChainStart(chain, inputs, runId, parentRunId, _tags, _metadata, _runType, name) {
269
- this.spans[runId] = this.buildSpan({
270
- type: "chain",
271
- serialized: chain,
272
- runId,
273
- parentRunId,
274
- input: inputs,
275
- name
276
- });
277
- }
278
- async handleChainEnd(output, runId, _parentRunId) {
279
- this.endSpan({
280
- runId,
281
- output
282
- });
283
- }
284
- async handleChainError(err, runId, _parentRunId, _tags, _kwargs) {
285
- this.errorSpan({ runId, error: err });
286
- }
287
- async handleToolStart(tool, input, runId, parentRunId, _tags, _metadata, name) {
288
- this.spans[runId] = this.buildSpan({
289
- type: "tool",
290
- serialized: tool,
291
- runId,
292
- parentRunId,
293
- input,
294
- name
295
- });
296
- }
297
- async handleToolEnd(output, runId, _parentRunId) {
298
- this.endSpan({ runId, output });
299
- }
300
- async handleToolError(err, runId, _parentRunId, _tags) {
301
- this.errorSpan({ runId, error: err });
302
- }
303
- async handleRetrieverStart(retriever, query, runId, parentRunId, _tags, _metadata, name) {
304
- var _a, _b;
305
- try {
306
- const parent = this.getParent(parentRunId);
307
- this.spans[runId] = parent.startRAGSpan({
308
- spanId: runId,
309
- name: (_b = name != null ? name : retriever.name) != null ? _b : (_a = retriever.id.at(-1)) == null ? void 0 : _a.toString(),
310
- input: this.autoconvertTypedValues(query)
311
- });
312
- } catch (e) {
313
- this.trace.client.emit("error", e);
314
- throw e;
315
- }
316
- }
317
- async handleRetrieverEnd(documents, runId, _parentRunId, _tags) {
318
- try {
319
- const contexts = documents.map((doc) => __spreadValues({
320
- content: doc.pageContent
321
- }, doc.metadata.source ? { documentId: doc.metadata.source } : {}));
322
- const span = this.spans[runId];
323
- if (!span) {
324
- return;
325
- }
326
- span.end({
327
- contexts,
328
- output: this.autoconvertTypedValues(documents)
329
- });
330
- } catch (e) {
331
- this.trace.client.emit("error", e);
332
- throw e;
333
- }
334
- }
335
- async handleRetrieverError(err, runId, _parentRunId, _tags) {
336
- this.errorSpan({ runId, error: err });
337
- }
338
- async handleAgentAction(_action, runId, _parentRunId, _tags) {
339
- const span = this.spans[runId];
340
- if (!span) {
341
- return;
342
- }
343
- span.update({
344
- type: "agent"
345
- });
346
- }
347
- async handleAgentEnd(action, runId, _parentRunId, _tags) {
348
- this.endSpan({
349
- runId,
350
- output: action.returnValues
351
- });
352
- }
353
- buildSpan({
354
- type,
355
- serialized,
356
- runId,
357
- parentRunId,
358
- input,
359
- name
360
- }) {
361
- var _a, _b;
362
- try {
363
- const parent = this.getParent(parentRunId);
364
- const span = parent.startSpan({
365
- spanId: runId,
366
- type,
367
- name: (_b = name != null ? name : serialized.name) != null ? _b : (_a = serialized.id.at(-1)) == null ? void 0 : _a.toString(),
368
- input: this.autoconvertTypedValues(input)
369
- });
370
- return span;
371
- } catch (e) {
372
- this.trace.client.emit("error", e);
373
- throw e;
374
- }
375
- }
376
- endSpan({ runId, output }) {
377
- try {
378
- const span = this.spans[runId];
379
- if (!span) {
380
- return;
381
- }
382
- span.end({
383
- output: this.autoconvertTypedValues(output)
384
- });
385
- } catch (e) {
386
- this.trace.client.emit("error", e);
387
- throw e;
388
- }
389
- }
390
- errorSpan({ runId, error }) {
391
- const span = this.spans[runId];
392
- if (!span) {
393
- return;
394
- }
395
- span.end({
396
- error
397
- });
398
- }
399
- autoconvertTypedValues(value) {
400
- var _a;
401
- if (!value || typeof value === "object" && Object.keys(value).length === 0) {
402
- return void 0;
403
- }
404
- if (typeof value === "string") {
405
- return { type: "text", value };
406
- }
407
- try {
408
- JSON.stringify(value);
409
- return { type: "json", value };
410
- } catch (e) {
411
- return { type: "text", value: (_a = stringify(value)) != null ? _a : value.toString() };
412
- }
413
- }
414
- getParent(parentRunId) {
415
- var _a, _b;
416
- return (_b = parentRunId ? this.spans[parentRunId] : this.spans[(_a = Object.keys(this.spans).at(-1)) != null ? _a : ""]) != null ? _b : this.trace;
417
- }
418
- };
419
- var convertFromLangChainMessages = (messages) => {
420
- const chatMessages = [];
421
- for (const message of messages) {
422
- chatMessages.push(convertFromLangChainMessage(message));
423
- }
424
- return chatMessages;
425
- };
426
- var convertFromLangChainMessage = (message) => {
427
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
428
- let role = "user";
429
- const message_ = message.lc_serializable ? mapChatMessagesToStoredMessages([message])[0] : message;
430
- if (message_ instanceof HumanMessage || message_ instanceof HumanMessageChunk || ((_a = message_.id) == null ? void 0 : _a.at(-1)) === "HumanMessage" || ((_b = message_.id) == null ? void 0 : _b.at(-1)) === "HumanMessageChunk" || message_.type === "human") {
431
- role = "user";
432
- } else if (message instanceof AIMessage || message instanceof AIMessageChunk || ((_c = message.id) == null ? void 0 : _c.at(-1)) === "AIMessage" || ((_d = message.id) == null ? void 0 : _d.at(-1)) === "AIMessageChunk" || message_.type === "ai") {
433
- role = "assistant";
434
- } else if (message instanceof SystemMessage || message instanceof SystemMessageChunk || ((_e = message.id) == null ? void 0 : _e.at(-1)) === "SystemMessage" || ((_f = message.id) == null ? void 0 : _f.at(-1)) === "SystemMessageChunk" || message_.type === "system") {
435
- role = "system";
436
- } else if (message instanceof FunctionMessage || message instanceof FunctionMessageChunk || ((_g = message.id) == null ? void 0 : _g.at(-1)) === "FunctionMessage" || ((_h = message.id) == null ? void 0 : _h.at(-1)) === "FunctionMessageChunk" || message_.type === "function") {
437
- role = "function";
438
- } else if (message instanceof ToolMessage || message instanceof ToolMessageChunk || ((_i = message.id) == null ? void 0 : _i.at(-1)) === "ToolMessage" || ((_j = message.id) == null ? void 0 : _j.at(-1)) === "ToolMessageChunk" || message_.type === "tool") {
439
- role = "tool";
440
- }
441
- const content = typeof message.content === "string" ? message.content : message.content.map(
442
- (content2) => content2.type === "text" ? { type: "text", text: content2.text } : content2.type == "image_url" ? { type: "image_url", image_url: content2.image_url } : { type: "text", text: JSON.stringify(content2) }
443
- );
444
- const functionCall = message.additional_kwargs;
445
- return __spreadValues({
446
- role,
447
- content
448
- }, functionCall && typeof functionCall === "object" && Object.keys(functionCall).length > 0 ? { function_call: functionCall } : {});
449
- };
450
-
451
- // src/typeUtils.ts
452
- function camelToSnakeCase(str) {
453
- return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
454
- }
455
- function camelToSnakeCaseNested(obj, parentKey) {
456
- if (Array.isArray(obj)) {
457
- return obj.map(
458
- (item) => camelToSnakeCaseNested(item, parentKey)
459
- );
460
- } else if (typeof obj === "object" && obj !== null) {
461
- const newObj = {};
462
- for (const key in obj) {
463
- if (obj.hasOwnProperty(key)) {
464
- const newKey = camelToSnakeCase(key);
465
- if (parentKey === "metadata" && !Object.keys(reservedTraceMetadataSchema.shape).includes(newKey) || parentKey === "params" && !Object.keys(reservedSpanParamsSchema.shape).includes(newKey) || parentKey === "input" && ["json", "raw", "list"].includes(newObj.type) && newKey === "value" || parentKey === "output" && ["json", "raw", "list"].includes(newObj.type) && newKey === "value" || parentKey === "contexts" && newKey === "content") {
466
- newObj[key] = obj[key];
467
- } else {
468
- newObj[newKey] = camelToSnakeCaseNested(obj[key], newKey);
469
- }
470
- }
471
- }
472
- return newObj;
473
- } else {
474
- return obj;
475
- }
476
- }
477
-
478
- // src/LangWatchExporter.ts
479
- import { createExportTraceServiceRequest } from "@opentelemetry/otlp-transformer";
480
-
481
- // node_modules/@opentelemetry/core/build/esm/ExportResult.js
482
- var ExportResultCode;
483
- (function(ExportResultCode2) {
484
- ExportResultCode2[ExportResultCode2["SUCCESS"] = 0] = "SUCCESS";
485
- ExportResultCode2[ExportResultCode2["FAILED"] = 1] = "FAILED";
486
- })(ExportResultCode || (ExportResultCode = {}));
487
-
488
- // src/LangWatchExporter.ts
489
- var LangWatchExporter = class {
490
- constructor(params = {}) {
491
- var _a, _b, _c, _d, _e, _f;
492
- this.endpoint = (_b = (_a = params.endpoint) != null ? _a : process.env.LANGWATCH_ENDPOINT) != null ? _b : "https://app.langwatch.ai";
493
- this.apiKey = (_d = (_c = params.apiKey) != null ? _c : process.env.LANGWATCH_API_KEY) != null ? _d : "";
494
- this.includeAllSpans = (_e = params.includeAllSpans) != null ? _e : false;
495
- this.debug = (_f = params.debug) != null ? _f : false;
496
- if (!this.apiKey) {
497
- throw new Error("LANGWATCH_API_KEY is not set");
498
- }
499
- }
500
- export(allSpans, resultCallback) {
501
- const spans = allSpans.filter(
502
- (span) => this.includeAllSpans || this.isAiSdkSpan(span)
503
- );
504
- if (spans.length === 0) {
505
- resultCallback({ code: ExportResultCode.SUCCESS });
506
- return;
507
- }
508
- if (this.debug) {
509
- console.log("[LangWatchExporter] Exporting spans:", spans);
510
- }
511
- let body;
512
- try {
513
- body = JSON.stringify(createExportTraceServiceRequest(spans));
514
- } catch (error) {
515
- console.error("[LangWatchExporter] Failed to serialize spans:", error);
516
- resultCallback({ code: ExportResultCode.FAILED });
517
- return;
518
- }
519
- fetch(`${this.endpoint}/api/otel/v1/traces`, {
520
- method: "POST",
521
- headers: {
522
- "Content-Type": "application/json",
523
- Authorization: `Bearer ${this.apiKey}`
524
- },
525
- body
526
- }).then((response) => {
527
- if (!response.ok) {
528
- resultCallback({ code: ExportResultCode.FAILED });
529
- return;
530
- }
531
- resultCallback({ code: ExportResultCode.SUCCESS });
532
- }).catch((error) => {
533
- console.error("[LangWatchExporter] Failed to export spans:", error);
534
- resultCallback({
535
- code: ExportResultCode.FAILED,
536
- error: error instanceof Error ? error : new Error("Unknown error")
537
- });
538
- });
539
- }
540
- isAiSdkSpan(span) {
541
- return span.instrumentationLibrary.name === "ai";
542
- }
543
- shutdown() {
544
- return Promise.resolve();
545
- }
546
- };
547
-
548
- // src/index.ts
549
- var LangWatch = class extends EventEmitter {
550
- constructor({
551
- apiKey,
552
- endpoint = ((_a) => (_a = process.env.LANGWATCH_ENDPOINT) != null ? _a : "https://app.langwatch.ai")()
553
- } = {}) {
554
- super();
555
- const apiKey_ = apiKey != null ? apiKey : process.env.LANGWATCH_API_KEY;
556
- if (!apiKey_) {
557
- const error = new Error(
558
- "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."
559
- );
560
- this.emit("error", error);
561
- }
562
- this.apiKey = apiKey_;
563
- this.endpoint = endpoint;
564
- }
565
- getTrace({
566
- traceId,
567
- metadata
568
- } = {}) {
569
- return new LangWatchTrace({
570
- client: this,
571
- traceId: traceId != null ? traceId : `trace_${nanoid()}`,
572
- metadata
573
- });
574
- }
575
- async sendTrace(params) {
576
- const backoff = [1e3, 2e3, 4e3, 8e3, 16e3];
577
- for (const backoffTime of backoff) {
578
- try {
579
- await this._sendTrace(params);
580
- return;
581
- } catch (e) {
582
- console.warn(
583
- `[LangWatch] \u26A0\uFE0F Failed to send trace, retrying in ${backoffTime / 1e3}s`
584
- );
585
- await new Promise((resolve) => setTimeout(resolve, backoffTime));
586
- }
587
- }
588
- console.warn("[LangWatch] \u26A0\uFE0F Failed to send trace, giving up");
589
- }
590
- async _sendTrace(params) {
591
- if (params.spans.length === 0) {
592
- return;
593
- }
594
- if (!this.apiKey) {
595
- const error = new Error(
596
- "LangWatch API key is not set, LLMs traces will not be sent, go to https://langwatch.ai to set it up"
597
- );
598
- this.emit("error", error);
599
- return;
600
- }
601
- const response = await fetch(`${this.endpoint}/api/collector`, {
602
- method: "POST",
603
- headers: {
604
- "X-Auth-Token": this.apiKey,
605
- "Content-Type": "application/json"
606
- },
607
- body: JSON.stringify(params)
608
- });
609
- if (response.status === 429) {
610
- const error = new Error(
611
- "Rate limit exceeded, dropping message from being sent to LangWatch. Please check your dashboard to upgrade your plan."
612
- );
613
- this.emit("error", error);
614
- return;
615
- }
616
- if (!response.ok) {
617
- const error = new Error(
618
- `Failed to send trace, status: ${response.status}`
619
- );
620
- this.emit("error", error);
621
- throw error;
622
- }
623
- }
624
- };
625
- var LangWatchTrace = class {
626
- constructor({
627
- client,
628
- traceId,
629
- metadata
630
- }) {
631
- this.finishedSpans = {};
632
- this.evaluations = [];
633
- this.addEvaluation = ({
634
- evaluationId,
635
- span,
636
- name,
637
- type,
638
- isGuardrail,
639
- status = "processed",
640
- passed,
641
- score,
642
- label,
643
- details,
644
- error,
645
- timestamps
646
- }) => {
647
- var _a, _b;
648
- const currentEvaluationIndex = this.evaluations.findIndex(
649
- (e) => evaluationId && "evaluationId" in e && e.evaluationId === evaluationId
650
- );
651
- const currentEvaluation = currentEvaluationIndex !== -1 ? this.evaluations[currentEvaluationIndex] : void 0;
652
- const evaluationResult = __spreadValues(__spreadValues(__spreadValues(__spreadValues({
653
- status
654
- }, passed !== void 0 && { passed }), score !== void 0 && { score }), label !== void 0 && { label }), details !== void 0 && { details });
655
- let span_ = span;
656
- if (!span_) {
657
- span_ = this.startSpan({
658
- type: "evaluation"
659
- });
660
- }
661
- if (span_.type !== "evaluation") {
662
- span_ = span_.startSpan({ type: "evaluation" });
663
- }
664
- span_.update({
665
- name,
666
- output: {
667
- type: "evaluation_result",
668
- value: evaluationResult
669
- },
670
- error,
671
- timestamps: timestamps ? {
672
- startedAt: (_a = timestamps.startedAt) != null ? _a : span_.timestamps.startedAt,
673
- finishedAt: (_b = timestamps.finishedAt) != null ? _b : void 0
674
- } : void 0
675
- });
676
- span_.end();
677
- const evaluation = {
678
- evaluationId: evaluationId != null ? evaluationId : `eval_${nanoid()}`,
679
- spanId: span_.spanId,
680
- name,
681
- type,
682
- isGuardrail,
683
- status,
684
- passed,
685
- score,
686
- label,
687
- details,
688
- error: error ? captureError(error) : void 0,
689
- timestamps: timestamps != null ? timestamps : {
690
- startedAt: span_.timestamps.startedAt,
691
- finishedAt: span_.timestamps.finishedAt
692
- }
693
- };
694
- if (currentEvaluation && currentEvaluationIndex !== -1) {
695
- this.evaluations[currentEvaluationIndex] = __spreadValues(__spreadValues({}, currentEvaluation), evaluation);
696
- } else {
697
- this.evaluations.push(evaluation);
698
- }
699
- };
700
- this.client = client;
701
- this.traceId = traceId;
702
- this.metadata = __spreadProps(__spreadValues({}, metadata), {
703
- sdkVersion: version,
704
- sdkLanguage: "typescript"
705
- });
706
- }
707
- update({ metadata }) {
708
- var _a, _b, _c;
709
- this.metadata = __spreadValues(__spreadValues(__spreadValues({}, this.metadata), metadata), typeof metadata.labels !== "undefined" ? {
710
- labels: [
711
- ...(_b = (_a = this.metadata) == null ? void 0 : _a.labels) != null ? _b : [],
712
- ...(_c = metadata.labels) != null ? _c : []
713
- ]
714
- } : {});
715
- }
716
- setCurrentSpan(span) {
717
- this.currentSpan = {
718
- current: span,
719
- previous: this.currentSpan
720
- };
721
- }
722
- getCurrentSpan() {
723
- var _a;
724
- return (_a = this.currentSpan) == null ? void 0 : _a.current;
725
- }
726
- resetCurrentSpan() {
727
- var _a;
728
- this.currentSpan = (_a = this.currentSpan) == null ? void 0 : _a.previous;
729
- }
730
- startSpan(params) {
731
- const span = new LangWatchSpan(__spreadValues({
732
- trace: this
733
- }, params));
734
- this.setCurrentSpan(span);
735
- return span;
736
- }
737
- startLLMSpan(params) {
738
- const span = new LangWatchLLMSpan(__spreadValues({
739
- trace: this
740
- }, params));
741
- this.setCurrentSpan(span);
742
- return span;
743
- }
744
- startRAGSpan(params) {
745
- const span = new LangWatchRAGSpan(__spreadValues({
746
- trace: this
747
- }, params));
748
- this.setCurrentSpan(span);
749
- return span;
750
- }
751
- async evaluate(params) {
752
- return evaluate(__spreadValues({
753
- trace: this
754
- }, params));
755
- }
756
- getLangChainCallback() {
757
- if (!this.langchainCallback) {
758
- this.langchainCallback = new LangWatchCallbackHandler({ trace: this });
759
- }
760
- return this.langchainCallback;
761
- }
762
- onEnd(span) {
763
- this.finishedSpans[span.span_id] = span;
764
- this.resetCurrentSpan();
765
- this.delayedSendSpans();
766
- }
767
- delayedSendSpans() {
768
- clearTimeout(this.timeoutRef);
769
- this.timeoutRef = setTimeout(() => {
770
- void this.sendSpans();
771
- }, 1e3);
772
- }
773
- async sendSpans() {
774
- clearTimeout(this.timeoutRef);
775
- let trace = void 0;
776
- try {
777
- trace = collectorRESTParamsSchema.parse({
778
- trace_id: this.traceId,
779
- metadata: camelToSnakeCaseNested(this.metadata, "metadata"),
780
- spans: Object.values(this.finishedSpans),
781
- evaluations: camelToSnakeCaseNested(this.evaluations)
782
- });
783
- } catch (error) {
784
- if (error instanceof ZodError) {
785
- console.warn("[LangWatch] \u26A0\uFE0F Failed to parse trace");
786
- console.warn(fromZodError(error).message);
787
- }
788
- this.client.emit("error", error);
789
- }
790
- if (trace) {
791
- await this.client.sendTrace(trace);
792
- }
793
- }
794
- };
795
- var LangWatchSpan = class _LangWatchSpan {
796
- constructor({
797
- trace,
798
- spanId,
799
- parentId,
800
- type,
801
- name,
802
- input,
803
- output,
804
- error,
805
- timestamps,
806
- metrics
807
- }) {
808
- this.spanId = spanId != null ? spanId : `span_${nanoid()}`;
809
- this.parentId = parentId;
810
- this.trace = trace;
811
- this.type = type != null ? type : "span";
812
- this.name = name;
813
- this.input = input;
814
- this.output = output;
815
- this.error = error;
816
- this.timestamps = timestamps != null ? timestamps : {
817
- startedAt: Date.now()
818
- };
819
- this.metrics = metrics;
820
- }
821
- update(params) {
822
- if (Object.isFrozen(this)) {
823
- const error = new Error(
824
- `Tried to update span ${this.spanId}, but the span is already finished, discarding update`
825
- );
826
- this.trace.client.emit("error", error);
827
- return;
828
- }
829
- if (params.type) {
830
- this.type = params.type;
831
- }
832
- if ("name" in params) {
833
- this.name = params.name;
834
- }
835
- if ("input" in params) {
836
- this.input = params.input;
837
- }
838
- if ("output" in params) {
839
- this.output = params.output;
840
- }
841
- if ("error" in params) {
842
- this.error = params.error;
843
- }
844
- if (params.timestamps) {
845
- this.timestamps = params.timestamps;
846
- }
847
- if ("metrics" in params) {
848
- this.metrics = params.metrics;
849
- }
850
- }
851
- startSpan(params) {
852
- const span = new _LangWatchSpan(__spreadValues({
853
- trace: this.trace,
854
- parentId: this.spanId
855
- }, params));
856
- this.trace.setCurrentSpan(span);
857
- return span;
858
- }
859
- startLLMSpan(params) {
860
- const span = new LangWatchLLMSpan(__spreadValues({
861
- trace: this.trace,
862
- parentId: this.spanId
863
- }, params));
864
- this.trace.setCurrentSpan(span);
865
- return span;
866
- }
867
- startRAGSpan(params) {
868
- const span = new LangWatchRAGSpan(__spreadValues({
869
- trace: this.trace,
870
- parentId: this.spanId
871
- }, params));
872
- this.trace.setCurrentSpan(span);
873
- return span;
874
- }
875
- addEvaluation(params) {
876
- this.trace.addEvaluation(__spreadProps(__spreadValues({}, params), {
877
- span: this
878
- }));
879
- }
880
- async evaluate(params) {
881
- return evaluate(__spreadValues({
882
- span: this
883
- }, params));
884
- }
885
- end(params) {
886
- this.timestamps.finishedAt = Date.now();
887
- if (params) {
888
- this.update(params);
889
- }
890
- try {
891
- const finalSpan = spanSchema.parse(
892
- camelToSnakeCaseNested(__spreadValues(__spreadProps(__spreadValues({}, this), {
893
- trace: void 0,
894
- traceId: this.trace.traceId,
895
- timestamps: __spreadProps(__spreadValues({}, this.timestamps), {
896
- finishedAt: this.timestamps.finishedAt
897
- })
898
- }), this.error && { error: captureError(this.error) }))
899
- );
900
- this.trace.onEnd(finalSpan);
901
- } catch (error) {
902
- if (error instanceof ZodError) {
903
- console.warn("[LangWatch] \u26A0\uFE0F Failed to parse span");
904
- console.warn(fromZodError(error).message);
905
- }
906
- this.trace.client.emit("error", error);
907
- }
908
- }
909
- };
910
- var LangWatchLLMSpan = class extends LangWatchSpan {
911
- constructor(params) {
912
- var _a, _b;
913
- super(__spreadValues({}, params));
914
- this.type = "llm";
915
- this.model = (_a = params.model) != null ? _a : "unknown";
916
- this.params = (_b = params.params) != null ? _b : {};
917
- }
918
- update(params) {
919
- super.update(params);
920
- if (params.model) {
921
- this.model = params.model;
922
- }
923
- if (params.params) {
924
- this.params = params.params;
925
- }
926
- }
927
- end(params) {
928
- super.end(params);
929
- }
930
- };
931
- var LangWatchRAGSpan = class extends LangWatchSpan {
932
- constructor(params) {
933
- var _a;
934
- super(__spreadValues({}, params));
935
- this.type = "rag";
936
- this.contexts = (_a = params.contexts) != null ? _a : [];
937
- }
938
- update(params) {
939
- super.update(params);
940
- if (params.contexts) {
941
- this.contexts = params.contexts;
942
- }
943
- }
944
- end(params) {
945
- super.end(params);
946
- }
947
- };
948
- export {
949
- LangWatch,
950
- LangWatchExporter,
951
- LangWatchLLMSpan,
952
- LangWatchRAGSpan,
953
- LangWatchSpan,
954
- LangWatchTrace,
955
- autoconvertTypedValues,
956
- captureError,
957
- convertFromVercelAIMessages
958
- };
959
- //# sourceMappingURL=index.mjs.map