langwatch 0.2.0 → 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 +78 -34
  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 -593
  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-LKD2K67J.mjs +0 -717
  99. package/dist/chunk-LKD2K67J.mjs.map +0 -1
  100. package/dist/index.d.mts +0 -1030
  101. package/dist/index.d.ts +0 -1030
  102. package/dist/index.js +0 -27310
  103. package/dist/index.js.map +0 -1
  104. package/dist/index.mjs +0 -963
  105. package/dist/index.mjs.map +0 -1
  106. package/dist/utils-Cv-rUjJ1.d.mts +0 -313
  107. package/dist/utils-Cv-rUjJ1.d.ts +0 -313
  108. package/dist/utils.d.mts +0 -2
  109. package/dist/utils.d.ts +0 -2
  110. package/dist/utils.js +0 -709
  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 -10917
  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 -96
  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 -82
  234. package/src/utils.ts +0 -205
  235. /package/src/{server/types → internal/generated/openapi}/.gitkeep +0 -0
package/dist/index.mjs DELETED
@@ -1,963 +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-LKD2K67J.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.2.0";
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 {
480
- JsonTraceSerializer
481
- } from "@opentelemetry/otlp-transformer";
482
-
483
- // node_modules/@opentelemetry/core/build/esm/ExportResult.js
484
- var ExportResultCode;
485
- (function(ExportResultCode2) {
486
- ExportResultCode2[ExportResultCode2["SUCCESS"] = 0] = "SUCCESS";
487
- ExportResultCode2[ExportResultCode2["FAILED"] = 1] = "FAILED";
488
- })(ExportResultCode || (ExportResultCode = {}));
489
-
490
- // src/LangWatchExporter.ts
491
- var LangWatchExporter = class {
492
- constructor(params = {}) {
493
- var _a, _b, _c, _d, _e, _f;
494
- this.endpoint = (_b = (_a = params.endpoint) != null ? _a : process.env.LANGWATCH_ENDPOINT) != null ? _b : "https://app.langwatch.ai";
495
- this.apiKey = (_d = (_c = params.apiKey) != null ? _c : process.env.LANGWATCH_API_KEY) != null ? _d : "";
496
- this.includeAllSpans = (_e = params.includeAllSpans) != null ? _e : false;
497
- this.debug = (_f = params.debug) != null ? _f : false;
498
- this.serializer = JsonTraceSerializer;
499
- if (!this.apiKey) {
500
- throw new Error("LANGWATCH_API_KEY is not set");
501
- }
502
- }
503
- export(allSpans, resultCallback) {
504
- const spans = allSpans.filter(
505
- (span) => this.includeAllSpans || this.isAiSdkSpan(span)
506
- );
507
- if (spans.length === 0) {
508
- resultCallback({ code: ExportResultCode.SUCCESS });
509
- return;
510
- }
511
- if (this.debug) {
512
- console.log("[LangWatchExporter] Exporting spans:", spans);
513
- }
514
- let body;
515
- try {
516
- body = this.serializer.serializeRequest(spans);
517
- } catch (error) {
518
- console.error("[LangWatchExporter] Failed to serialize spans:", error);
519
- resultCallback({ code: ExportResultCode.FAILED });
520
- return;
521
- }
522
- fetch(`${this.endpoint}/api/otel/v1/traces`, {
523
- method: "POST",
524
- headers: {
525
- "Content-Type": "application/json",
526
- Authorization: `Bearer ${this.apiKey}`
527
- },
528
- body
529
- }).then((response) => {
530
- if (!response.ok) {
531
- resultCallback({ code: ExportResultCode.FAILED });
532
- return;
533
- }
534
- resultCallback({ code: ExportResultCode.SUCCESS });
535
- }).catch((error) => {
536
- console.error("[LangWatchExporter] Failed to export spans:", error);
537
- resultCallback({
538
- code: ExportResultCode.FAILED,
539
- error: error instanceof Error ? error : new Error("Unknown error")
540
- });
541
- });
542
- }
543
- isAiSdkSpan(span) {
544
- var _a;
545
- return ((_a = span.instrumentationScope) == null ? void 0 : _a.name) === "ai";
546
- }
547
- shutdown() {
548
- return Promise.resolve();
549
- }
550
- };
551
-
552
- // src/index.ts
553
- var LangWatch = class extends EventEmitter {
554
- constructor({
555
- apiKey,
556
- endpoint = ((_a) => (_a = process.env.LANGWATCH_ENDPOINT) != null ? _a : "https://app.langwatch.ai")()
557
- } = {}) {
558
- super();
559
- const apiKey_ = apiKey != null ? apiKey : process.env.LANGWATCH_API_KEY;
560
- if (!apiKey_) {
561
- const error = new Error(
562
- "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."
563
- );
564
- this.emit("error", error);
565
- }
566
- this.apiKey = apiKey_;
567
- this.endpoint = endpoint;
568
- }
569
- getTrace({
570
- traceId,
571
- metadata
572
- } = {}) {
573
- return new LangWatchTrace({
574
- client: this,
575
- traceId: traceId != null ? traceId : `trace_${nanoid()}`,
576
- metadata
577
- });
578
- }
579
- async sendTrace(params) {
580
- const backoff = [1e3, 2e3, 4e3, 8e3, 16e3];
581
- for (const backoffTime of backoff) {
582
- try {
583
- await this._sendTrace(params);
584
- return;
585
- } catch (e) {
586
- console.warn(
587
- `[LangWatch] \u26A0\uFE0F Failed to send trace, retrying in ${backoffTime / 1e3}s`
588
- );
589
- await new Promise((resolve) => setTimeout(resolve, backoffTime));
590
- }
591
- }
592
- console.warn("[LangWatch] \u26A0\uFE0F Failed to send trace, giving up");
593
- }
594
- async _sendTrace(params) {
595
- if (params.spans.length === 0) {
596
- return;
597
- }
598
- if (!this.apiKey) {
599
- const error = new Error(
600
- "LangWatch API key is not set, LLMs traces will not be sent, go to https://langwatch.ai to set it up"
601
- );
602
- this.emit("error", error);
603
- return;
604
- }
605
- const response = await fetch(`${this.endpoint}/api/collector`, {
606
- method: "POST",
607
- headers: {
608
- "X-Auth-Token": this.apiKey,
609
- "Content-Type": "application/json"
610
- },
611
- body: JSON.stringify(params)
612
- });
613
- if (response.status === 429) {
614
- const error = new Error(
615
- "Rate limit exceeded, dropping message from being sent to LangWatch. Please check your dashboard to upgrade your plan."
616
- );
617
- this.emit("error", error);
618
- return;
619
- }
620
- if (!response.ok) {
621
- const error = new Error(
622
- `Failed to send trace, status: ${response.status}`
623
- );
624
- this.emit("error", error);
625
- throw error;
626
- }
627
- }
628
- };
629
- var LangWatchTrace = class {
630
- constructor({
631
- client,
632
- traceId,
633
- metadata
634
- }) {
635
- this.finishedSpans = {};
636
- this.evaluations = [];
637
- this.addEvaluation = ({
638
- evaluationId,
639
- span,
640
- name,
641
- type,
642
- isGuardrail,
643
- status = "processed",
644
- passed,
645
- score,
646
- label,
647
- details,
648
- error,
649
- timestamps
650
- }) => {
651
- var _a, _b;
652
- const currentEvaluationIndex = this.evaluations.findIndex(
653
- (e) => evaluationId && "evaluationId" in e && e.evaluationId === evaluationId
654
- );
655
- const currentEvaluation = currentEvaluationIndex !== -1 ? this.evaluations[currentEvaluationIndex] : void 0;
656
- const evaluationResult = __spreadValues(__spreadValues(__spreadValues(__spreadValues({
657
- status
658
- }, passed !== void 0 && { passed }), score !== void 0 && { score }), label !== void 0 && { label }), details !== void 0 && { details });
659
- let span_ = span;
660
- if (!span_) {
661
- span_ = this.startSpan({
662
- type: "evaluation"
663
- });
664
- }
665
- if (span_.type !== "evaluation") {
666
- span_ = span_.startSpan({ type: "evaluation" });
667
- }
668
- span_.update({
669
- name,
670
- output: {
671
- type: "evaluation_result",
672
- value: evaluationResult
673
- },
674
- error,
675
- timestamps: timestamps ? {
676
- startedAt: (_a = timestamps.startedAt) != null ? _a : span_.timestamps.startedAt,
677
- finishedAt: (_b = timestamps.finishedAt) != null ? _b : void 0
678
- } : void 0
679
- });
680
- span_.end();
681
- const evaluation = {
682
- evaluationId: evaluationId != null ? evaluationId : `eval_${nanoid()}`,
683
- spanId: span_.spanId,
684
- name,
685
- type,
686
- isGuardrail,
687
- status,
688
- passed,
689
- score,
690
- label,
691
- details,
692
- error: error ? captureError(error) : void 0,
693
- timestamps: timestamps != null ? timestamps : {
694
- startedAt: span_.timestamps.startedAt,
695
- finishedAt: span_.timestamps.finishedAt
696
- }
697
- };
698
- if (currentEvaluation && currentEvaluationIndex !== -1) {
699
- this.evaluations[currentEvaluationIndex] = __spreadValues(__spreadValues({}, currentEvaluation), evaluation);
700
- } else {
701
- this.evaluations.push(evaluation);
702
- }
703
- };
704
- this.client = client;
705
- this.traceId = traceId;
706
- this.metadata = __spreadProps(__spreadValues({}, metadata), {
707
- sdkVersion: version,
708
- sdkLanguage: "typescript"
709
- });
710
- }
711
- update({ metadata }) {
712
- var _a, _b, _c;
713
- this.metadata = __spreadValues(__spreadValues(__spreadValues({}, this.metadata), metadata), typeof metadata.labels !== "undefined" ? {
714
- labels: [
715
- ...(_b = (_a = this.metadata) == null ? void 0 : _a.labels) != null ? _b : [],
716
- ...(_c = metadata.labels) != null ? _c : []
717
- ]
718
- } : {});
719
- }
720
- setCurrentSpan(span) {
721
- this.currentSpan = {
722
- current: span,
723
- previous: this.currentSpan
724
- };
725
- }
726
- getCurrentSpan() {
727
- var _a;
728
- return (_a = this.currentSpan) == null ? void 0 : _a.current;
729
- }
730
- resetCurrentSpan() {
731
- var _a;
732
- this.currentSpan = (_a = this.currentSpan) == null ? void 0 : _a.previous;
733
- }
734
- startSpan(params) {
735
- const span = new LangWatchSpan(__spreadValues({
736
- trace: this
737
- }, params));
738
- this.setCurrentSpan(span);
739
- return span;
740
- }
741
- startLLMSpan(params) {
742
- const span = new LangWatchLLMSpan(__spreadValues({
743
- trace: this
744
- }, params));
745
- this.setCurrentSpan(span);
746
- return span;
747
- }
748
- startRAGSpan(params) {
749
- const span = new LangWatchRAGSpan(__spreadValues({
750
- trace: this
751
- }, params));
752
- this.setCurrentSpan(span);
753
- return span;
754
- }
755
- async evaluate(params) {
756
- return evaluate(__spreadValues({
757
- trace: this
758
- }, params));
759
- }
760
- getLangChainCallback() {
761
- if (!this.langchainCallback) {
762
- this.langchainCallback = new LangWatchCallbackHandler({ trace: this });
763
- }
764
- return this.langchainCallback;
765
- }
766
- onEnd(span) {
767
- this.finishedSpans[span.span_id] = span;
768
- this.resetCurrentSpan();
769
- this.delayedSendSpans();
770
- }
771
- delayedSendSpans() {
772
- clearTimeout(this.timeoutRef);
773
- this.timeoutRef = setTimeout(() => {
774
- void this.sendSpans();
775
- }, 1e3);
776
- }
777
- async sendSpans() {
778
- clearTimeout(this.timeoutRef);
779
- let trace = void 0;
780
- try {
781
- trace = collectorRESTParamsSchema.parse({
782
- trace_id: this.traceId,
783
- metadata: camelToSnakeCaseNested(this.metadata, "metadata"),
784
- spans: Object.values(this.finishedSpans),
785
- evaluations: camelToSnakeCaseNested(this.evaluations)
786
- });
787
- } catch (error) {
788
- if (error instanceof ZodError) {
789
- console.warn("[LangWatch] \u26A0\uFE0F Failed to parse trace");
790
- console.warn(fromZodError(error).message);
791
- }
792
- this.client.emit("error", error);
793
- }
794
- if (trace) {
795
- await this.client.sendTrace(trace);
796
- }
797
- }
798
- };
799
- var LangWatchSpan = class _LangWatchSpan {
800
- constructor({
801
- trace,
802
- spanId,
803
- parentId,
804
- type,
805
- name,
806
- input,
807
- output,
808
- error,
809
- timestamps,
810
- metrics
811
- }) {
812
- this.spanId = spanId != null ? spanId : `span_${nanoid()}`;
813
- this.parentId = parentId;
814
- this.trace = trace;
815
- this.type = type != null ? type : "span";
816
- this.name = name;
817
- this.input = input;
818
- this.output = output;
819
- this.error = error;
820
- this.timestamps = timestamps != null ? timestamps : {
821
- startedAt: Date.now()
822
- };
823
- this.metrics = metrics;
824
- }
825
- update(params) {
826
- if (Object.isFrozen(this)) {
827
- const error = new Error(
828
- `Tried to update span ${this.spanId}, but the span is already finished, discarding update`
829
- );
830
- this.trace.client.emit("error", error);
831
- return;
832
- }
833
- if (params.type) {
834
- this.type = params.type;
835
- }
836
- if ("name" in params) {
837
- this.name = params.name;
838
- }
839
- if ("input" in params) {
840
- this.input = params.input;
841
- }
842
- if ("output" in params) {
843
- this.output = params.output;
844
- }
845
- if ("error" in params) {
846
- this.error = params.error;
847
- }
848
- if (params.timestamps) {
849
- this.timestamps = params.timestamps;
850
- }
851
- if ("metrics" in params) {
852
- this.metrics = params.metrics;
853
- }
854
- }
855
- startSpan(params) {
856
- const span = new _LangWatchSpan(__spreadValues({
857
- trace: this.trace,
858
- parentId: this.spanId
859
- }, params));
860
- this.trace.setCurrentSpan(span);
861
- return span;
862
- }
863
- startLLMSpan(params) {
864
- const span = new LangWatchLLMSpan(__spreadValues({
865
- trace: this.trace,
866
- parentId: this.spanId
867
- }, params));
868
- this.trace.setCurrentSpan(span);
869
- return span;
870
- }
871
- startRAGSpan(params) {
872
- const span = new LangWatchRAGSpan(__spreadValues({
873
- trace: this.trace,
874
- parentId: this.spanId
875
- }, params));
876
- this.trace.setCurrentSpan(span);
877
- return span;
878
- }
879
- addEvaluation(params) {
880
- this.trace.addEvaluation(__spreadProps(__spreadValues({}, params), {
881
- span: this
882
- }));
883
- }
884
- async evaluate(params) {
885
- return evaluate(__spreadValues({
886
- span: this
887
- }, params));
888
- }
889
- end(params) {
890
- this.timestamps.finishedAt = Date.now();
891
- if (params) {
892
- this.update(params);
893
- }
894
- try {
895
- const finalSpan = spanSchema.parse(
896
- camelToSnakeCaseNested(__spreadValues(__spreadProps(__spreadValues({}, this), {
897
- trace: void 0,
898
- traceId: this.trace.traceId,
899
- timestamps: __spreadProps(__spreadValues({}, this.timestamps), {
900
- finishedAt: this.timestamps.finishedAt
901
- })
902
- }), this.error && { error: captureError(this.error) }))
903
- );
904
- this.trace.onEnd(finalSpan);
905
- } catch (error) {
906
- if (error instanceof ZodError) {
907
- console.warn("[LangWatch] \u26A0\uFE0F Failed to parse span");
908
- console.warn(fromZodError(error).message);
909
- }
910
- this.trace.client.emit("error", error);
911
- }
912
- }
913
- };
914
- var LangWatchLLMSpan = class extends LangWatchSpan {
915
- constructor(params) {
916
- var _a, _b;
917
- super(__spreadValues({}, params));
918
- this.type = "llm";
919
- this.model = (_a = params.model) != null ? _a : "unknown";
920
- this.params = (_b = params.params) != null ? _b : {};
921
- }
922
- update(params) {
923
- super.update(params);
924
- if (params.model) {
925
- this.model = params.model;
926
- }
927
- if (params.params) {
928
- this.params = params.params;
929
- }
930
- }
931
- end(params) {
932
- super.end(params);
933
- }
934
- };
935
- var LangWatchRAGSpan = class extends LangWatchSpan {
936
- constructor(params) {
937
- var _a;
938
- super(__spreadValues({}, params));
939
- this.type = "rag";
940
- this.contexts = (_a = params.contexts) != null ? _a : [];
941
- }
942
- update(params) {
943
- super.update(params);
944
- if (params.contexts) {
945
- this.contexts = params.contexts;
946
- }
947
- }
948
- end(params) {
949
- super.end(params);
950
- }
951
- };
952
- export {
953
- LangWatch,
954
- LangWatchExporter,
955
- LangWatchLLMSpan,
956
- LangWatchRAGSpan,
957
- LangWatchSpan,
958
- LangWatchTrace,
959
- autoconvertTypedValues,
960
- captureError,
961
- convertFromVercelAIMessages
962
- };
963
- //# sourceMappingURL=index.mjs.map