langwatch 0.2.0 → 0.3.0-prerelease.2

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 (229) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +268 -1
  3. package/dist/chunk-4BZATFKJ.mjs +181 -0
  4. package/dist/chunk-4BZATFKJ.mjs.map +1 -0
  5. package/dist/chunk-CSC3CMIT.mjs +118 -0
  6. package/dist/chunk-CSC3CMIT.mjs.map +1 -0
  7. package/dist/chunk-F63YKTXA.mjs +47 -0
  8. package/dist/chunk-F63YKTXA.mjs.map +1 -0
  9. package/dist/chunk-G3AUABT7.js +4 -0
  10. package/dist/chunk-G3AUABT7.js.map +1 -0
  11. package/dist/chunk-HPC6Z7J4.js +118 -0
  12. package/dist/chunk-HPC6Z7J4.js.map +1 -0
  13. package/dist/chunk-KGDAENGD.js +50 -0
  14. package/dist/chunk-KGDAENGD.js.map +1 -0
  15. package/dist/chunk-LD74LVRU.js +47 -0
  16. package/dist/chunk-LD74LVRU.js.map +1 -0
  17. package/dist/chunk-OM7VY3XT.mjs +4 -0
  18. package/dist/chunk-PCQVQ7SB.js +45 -0
  19. package/dist/chunk-PCQVQ7SB.js.map +1 -0
  20. package/dist/chunk-PMBEK6YE.mjs +424 -0
  21. package/dist/chunk-PMBEK6YE.mjs.map +1 -0
  22. package/dist/chunk-PR3JDWC3.mjs +50 -0
  23. package/dist/chunk-PR3JDWC3.mjs.map +1 -0
  24. package/dist/chunk-PTJ6AAI7.js +360 -0
  25. package/dist/chunk-PTJ6AAI7.js.map +1 -0
  26. package/dist/chunk-QEWDG5QE.mjs +45 -0
  27. package/dist/chunk-QEWDG5QE.mjs.map +1 -0
  28. package/dist/chunk-REUCVT7A.mjs +39 -0
  29. package/dist/chunk-REUCVT7A.mjs.map +1 -0
  30. package/dist/chunk-SVJ7SCGB.js +424 -0
  31. package/dist/chunk-SVJ7SCGB.js.map +1 -0
  32. package/dist/chunk-VJSOCNPA.js +181 -0
  33. package/dist/chunk-VJSOCNPA.js.map +1 -0
  34. package/dist/chunk-WM2GRSRW.js +39 -0
  35. package/dist/chunk-WM2GRSRW.js.map +1 -0
  36. package/dist/chunk-Z5J5UI5E.mjs +360 -0
  37. package/dist/chunk-Z5J5UI5E.mjs.map +1 -0
  38. package/dist/client-B2HqIKg6.d.ts +51 -0
  39. package/dist/client-XyCqclCi.d.mts +51 -0
  40. package/dist/client-browser.d.mts +8 -0
  41. package/dist/client-browser.d.ts +8 -0
  42. package/dist/client-browser.js +83 -0
  43. package/dist/client-browser.js.map +1 -0
  44. package/dist/client-browser.mjs +83 -0
  45. package/dist/client-browser.mjs.map +1 -0
  46. package/dist/client-node.d.mts +8 -0
  47. package/dist/client-node.d.ts +8 -0
  48. package/dist/client-node.js +90 -0
  49. package/dist/client-node.js.map +1 -0
  50. package/dist/client-node.mjs +90 -0
  51. package/dist/client-node.mjs.map +1 -0
  52. package/dist/evaluation/index.d.mts +897 -0
  53. package/dist/evaluation/index.d.ts +897 -0
  54. package/dist/evaluation/index.js +13 -0
  55. package/dist/evaluation/index.js.map +1 -0
  56. package/dist/evaluation/index.mjs +13 -0
  57. package/dist/evaluation/index.mjs.map +1 -0
  58. package/dist/filterable-batch-span-processor-zO5kcjBY.d.mts +64 -0
  59. package/dist/filterable-batch-span-processor-zO5kcjBY.d.ts +64 -0
  60. package/dist/index.d.mts +45 -1027
  61. package/dist/index.d.ts +45 -1027
  62. package/dist/index.js +11 -27291
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +23 -956
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/observability/index.d.mts +260 -0
  67. package/dist/observability/index.d.ts +260 -0
  68. package/dist/observability/index.js +20 -0
  69. package/dist/observability/index.js.map +1 -0
  70. package/dist/observability/index.mjs +20 -0
  71. package/dist/observability/index.mjs.map +1 -0
  72. package/dist/observability/instrumentation/langchain/index.d.mts +40 -0
  73. package/dist/observability/instrumentation/langchain/index.d.ts +40 -0
  74. package/dist/observability/instrumentation/langchain/index.js +666 -0
  75. package/dist/observability/instrumentation/langchain/index.js.map +1 -0
  76. package/dist/observability/instrumentation/langchain/index.mjs +666 -0
  77. package/dist/observability/instrumentation/langchain/index.mjs.map +1 -0
  78. package/dist/prompt/index.d.mts +10 -0
  79. package/dist/prompt/index.d.ts +10 -0
  80. package/dist/prompt/index.js +18 -0
  81. package/dist/prompt/index.js.map +1 -0
  82. package/dist/prompt/index.mjs +18 -0
  83. package/dist/prompt/index.mjs.map +1 -0
  84. package/dist/prompt-BXJWdbQp.d.mts +1967 -0
  85. package/dist/prompt-BXJWdbQp.d.ts +1967 -0
  86. package/dist/record-evaluation-CmxMXa-3.d.mts +25 -0
  87. package/dist/record-evaluation-CmxMXa-3.d.ts +25 -0
  88. package/dist/trace-D-bZOuqb.d.mts +622 -0
  89. package/dist/trace-G2312klE.d.ts +622 -0
  90. package/package.json +86 -37
  91. package/.eslintrc.cjs +0 -37
  92. package/copy-types.sh +0 -17
  93. package/dist/chunk-LKD2K67J.mjs +0 -717
  94. package/dist/chunk-LKD2K67J.mjs.map +0 -1
  95. package/dist/utils-Cv-rUjJ1.d.mts +0 -313
  96. package/dist/utils-Cv-rUjJ1.d.ts +0 -313
  97. package/dist/utils.d.mts +0 -2
  98. package/dist/utils.d.ts +0 -2
  99. package/dist/utils.js +0 -709
  100. package/dist/utils.js.map +0 -1
  101. package/dist/utils.mjs +0 -11
  102. package/example/.env.example +0 -12
  103. package/example/.eslintrc.json +0 -26
  104. package/example/LICENSE +0 -13
  105. package/example/README.md +0 -12
  106. package/example/app/(chat)/chat/[id]/page.tsx +0 -60
  107. package/example/app/(chat)/layout.tsx +0 -14
  108. package/example/app/(chat)/page.tsx +0 -27
  109. package/example/app/actions.ts +0 -156
  110. package/example/app/globals.css +0 -76
  111. package/example/app/guardrails/page.tsx +0 -26
  112. package/example/app/langchain/page.tsx +0 -27
  113. package/example/app/langchain-rag/page.tsx +0 -28
  114. package/example/app/late-update/page.tsx +0 -27
  115. package/example/app/layout.tsx +0 -64
  116. package/example/app/login/actions.ts +0 -71
  117. package/example/app/login/page.tsx +0 -18
  118. package/example/app/manual/page.tsx +0 -27
  119. package/example/app/new/page.tsx +0 -5
  120. package/example/app/opengraph-image.png +0 -0
  121. package/example/app/share/[id]/page.tsx +0 -58
  122. package/example/app/signup/actions.ts +0 -111
  123. package/example/app/signup/page.tsx +0 -18
  124. package/example/app/twitter-image.png +0 -0
  125. package/example/auth.config.ts +0 -42
  126. package/example/auth.ts +0 -45
  127. package/example/components/button-scroll-to-bottom.tsx +0 -36
  128. package/example/components/chat-history.tsx +0 -49
  129. package/example/components/chat-list.tsx +0 -52
  130. package/example/components/chat-message-actions.tsx +0 -40
  131. package/example/components/chat-message.tsx +0 -80
  132. package/example/components/chat-panel.tsx +0 -139
  133. package/example/components/chat-share-dialog.tsx +0 -95
  134. package/example/components/chat.tsx +0 -84
  135. package/example/components/clear-history.tsx +0 -75
  136. package/example/components/empty-screen.tsx +0 -38
  137. package/example/components/external-link.tsx +0 -29
  138. package/example/components/footer.tsx +0 -19
  139. package/example/components/header.tsx +0 -114
  140. package/example/components/login-button.tsx +0 -42
  141. package/example/components/login-form.tsx +0 -97
  142. package/example/components/markdown.tsx +0 -9
  143. package/example/components/prompt-form.tsx +0 -115
  144. package/example/components/providers.tsx +0 -17
  145. package/example/components/sidebar-actions.tsx +0 -125
  146. package/example/components/sidebar-desktop.tsx +0 -19
  147. package/example/components/sidebar-footer.tsx +0 -16
  148. package/example/components/sidebar-item.tsx +0 -124
  149. package/example/components/sidebar-items.tsx +0 -42
  150. package/example/components/sidebar-list.tsx +0 -38
  151. package/example/components/sidebar-mobile.tsx +0 -31
  152. package/example/components/sidebar-toggle.tsx +0 -24
  153. package/example/components/sidebar.tsx +0 -21
  154. package/example/components/signup-form.tsx +0 -95
  155. package/example/components/stocks/events-skeleton.tsx +0 -31
  156. package/example/components/stocks/events.tsx +0 -30
  157. package/example/components/stocks/index.tsx +0 -36
  158. package/example/components/stocks/message.tsx +0 -134
  159. package/example/components/stocks/spinner.tsx +0 -16
  160. package/example/components/stocks/stock-purchase.tsx +0 -146
  161. package/example/components/stocks/stock-skeleton.tsx +0 -22
  162. package/example/components/stocks/stock.tsx +0 -210
  163. package/example/components/stocks/stocks-skeleton.tsx +0 -9
  164. package/example/components/stocks/stocks.tsx +0 -67
  165. package/example/components/tailwind-indicator.tsx +0 -14
  166. package/example/components/theme-toggle.tsx +0 -31
  167. package/example/components/ui/alert-dialog.tsx +0 -141
  168. package/example/components/ui/badge.tsx +0 -36
  169. package/example/components/ui/button.tsx +0 -57
  170. package/example/components/ui/codeblock.tsx +0 -148
  171. package/example/components/ui/dialog.tsx +0 -122
  172. package/example/components/ui/dropdown-menu.tsx +0 -205
  173. package/example/components/ui/icons.tsx +0 -507
  174. package/example/components/ui/input.tsx +0 -25
  175. package/example/components/ui/label.tsx +0 -26
  176. package/example/components/ui/select.tsx +0 -164
  177. package/example/components/ui/separator.tsx +0 -31
  178. package/example/components/ui/sheet.tsx +0 -140
  179. package/example/components/ui/sonner.tsx +0 -31
  180. package/example/components/ui/switch.tsx +0 -29
  181. package/example/components/ui/textarea.tsx +0 -24
  182. package/example/components/ui/tooltip.tsx +0 -30
  183. package/example/components/user-menu.tsx +0 -53
  184. package/example/components.json +0 -17
  185. package/example/instrumentation.ts +0 -11
  186. package/example/lib/chat/guardrails.tsx +0 -181
  187. package/example/lib/chat/langchain-rag.tsx +0 -191
  188. package/example/lib/chat/langchain.tsx +0 -112
  189. package/example/lib/chat/late-update.tsx +0 -208
  190. package/example/lib/chat/manual.tsx +0 -605
  191. package/example/lib/chat/vercel-ai.tsx +0 -576
  192. package/example/lib/hooks/use-copy-to-clipboard.tsx +0 -33
  193. package/example/lib/hooks/use-enter-submit.tsx +0 -23
  194. package/example/lib/hooks/use-local-storage.ts +0 -24
  195. package/example/lib/hooks/use-scroll-anchor.tsx +0 -86
  196. package/example/lib/hooks/use-sidebar.tsx +0 -60
  197. package/example/lib/hooks/use-streamable-text.ts +0 -25
  198. package/example/lib/types.ts +0 -41
  199. package/example/lib/utils.ts +0 -89
  200. package/example/middleware.ts +0 -8
  201. package/example/next-env.d.ts +0 -5
  202. package/example/next.config.js +0 -16
  203. package/example/package-lock.json +0 -10917
  204. package/example/package.json +0 -84
  205. package/example/pnpm-lock.yaml +0 -5712
  206. package/example/postcss.config.js +0 -6
  207. package/example/prettier.config.cjs +0 -34
  208. package/example/public/apple-touch-icon.png +0 -0
  209. package/example/public/favicon-16x16.png +0 -0
  210. package/example/public/favicon.ico +0 -0
  211. package/example/public/next.svg +0 -1
  212. package/example/public/thirteen.svg +0 -1
  213. package/example/public/vercel.svg +0 -1
  214. package/example/tailwind.config.ts +0 -81
  215. package/example/tsconfig.json +0 -35
  216. package/src/LangWatchExporter.ts +0 -96
  217. package/src/evaluations.ts +0 -219
  218. package/src/index.test.ts +0 -402
  219. package/src/index.ts +0 -596
  220. package/src/langchain.ts +0 -557
  221. package/src/server/types/.gitkeep +0 -0
  222. package/src/typeUtils.ts +0 -89
  223. package/src/types.ts +0 -82
  224. package/src/utils.ts +0 -205
  225. package/ts-to-zod.config.js +0 -24
  226. package/tsconfig.json +0 -32
  227. package/tsup.config.ts +0 -10
  228. package/vitest.config.ts +0 -8
  229. /package/dist/{utils.mjs.map → chunk-OM7VY3XT.mjs.map} +0 -0
@@ -1,605 +0,0 @@
1
- import 'server-only'
2
-
3
- import {
4
- createAI,
5
- createStreamableUI,
6
- getMutableAIState,
7
- getAIState,
8
- streamUI,
9
- createStreamableValue
10
- } from 'ai/rsc'
11
- import { openai } from '@ai-sdk/openai'
12
-
13
- import {
14
- spinner,
15
- BotCard,
16
- BotMessage,
17
- SystemMessage,
18
- Stock,
19
- Purchase
20
- } from '@/components/stocks'
21
-
22
- import { z } from 'zod'
23
- import { EventsSkeleton } from '@/components/stocks/events-skeleton'
24
- import { Events } from '@/components/stocks/events'
25
- import { StocksSkeleton } from '@/components/stocks/stocks-skeleton'
26
- import { Stocks } from '@/components/stocks/stocks'
27
- import { StockSkeleton } from '@/components/stocks/stock-skeleton'
28
- import {
29
- formatNumber,
30
- runAsyncFnWithoutBlocking,
31
- sleep,
32
- nanoid
33
- } from '@/lib/utils'
34
- import { saveChat } from '@/app/actions'
35
- import { SpinnerMessage, UserMessage } from '@/components/stocks/message'
36
- import { Chat, Message } from '@/lib/types'
37
- import { auth } from '@/auth'
38
- import { LangWatch, convertFromVercelAIMessages } from 'langwatch'
39
- import { generateText } from 'ai'
40
-
41
- async function confirmPurchase(symbol: string, price: number, amount: number) {
42
- 'use server'
43
-
44
- const aiState = getMutableAIState<typeof ManualTracing>()
45
-
46
- const purchasing = createStreamableUI(
47
- <div className="inline-flex items-start gap-1 md:items-center">
48
- {spinner}
49
- <p className="mb-2">
50
- Purchasing {amount} ${symbol}...
51
- </p>
52
- </div>
53
- )
54
-
55
- const systemMessage = createStreamableUI(null)
56
-
57
- runAsyncFnWithoutBlocking(async () => {
58
- await sleep(1000)
59
-
60
- purchasing.update(
61
- <div className="inline-flex items-start gap-1 md:items-center">
62
- {spinner}
63
- <p className="mb-2">
64
- Purchasing {amount} ${symbol}... working on it...
65
- </p>
66
- </div>
67
- )
68
-
69
- await sleep(1000)
70
-
71
- purchasing.done(
72
- <div>
73
- <p className="mb-2">
74
- You have successfully purchased {amount} ${symbol}. Total cost:{' '}
75
- {formatNumber(amount * price)}
76
- </p>
77
- </div>
78
- )
79
-
80
- systemMessage.done(
81
- <SystemMessage>
82
- You have purchased {amount} shares of {symbol} at ${price}. Total cost ={' '}
83
- {formatNumber(amount * price)}.
84
- </SystemMessage>
85
- )
86
-
87
- aiState.done({
88
- ...aiState.get(),
89
- messages: [
90
- ...aiState.get().messages,
91
- {
92
- id: nanoid(),
93
- role: 'system',
94
- content: `[User has purchased ${amount} shares of ${symbol} at ${price}. Total cost = ${
95
- amount * price
96
- }]`
97
- }
98
- ]
99
- })
100
- })
101
-
102
- return {
103
- purchasingUI: purchasing.value,
104
- newMessage: {
105
- id: nanoid(),
106
- display: systemMessage.value
107
- }
108
- }
109
- }
110
-
111
- async function submitUserMessage(content: string) {
112
- 'use server'
113
-
114
- const langwatch = new LangWatch()
115
- langwatch.on('error', e => {
116
- console.log('Error from LangWatch:', e)
117
- })
118
-
119
- const trace = langwatch.getTrace()
120
-
121
- const aiState = getMutableAIState<typeof ManualTracing>()
122
-
123
- aiState.update({
124
- ...aiState.get(),
125
- messages: [
126
- ...aiState.get().messages,
127
- {
128
- id: nanoid(),
129
- role: 'user',
130
- content
131
- }
132
- ]
133
- })
134
-
135
- const system = `\
136
- You are a stock trading conversation bot and you can help users buy stocks, step by step.
137
- You and the user can discuss stock prices and the user can adjust the amount of stocks they want to buy, or place an order, in the UI.
138
-
139
- Messages inside [] means that it's a UI element or a user event. For example:
140
- - "[Price of AAPL = 100]" means that an interface of the stock price of AAPL is shown to the user.
141
- - "[User has changed the amount of AAPL to 10]" means that the user has changed the amount of AAPL to 10 in the UI.
142
-
143
- If the user requests purchasing a stock, call \`show_stock_purchase_ui\` to show the purchase UI.
144
- If the user just wants the price, call \`show_stock_price\` to show the price.
145
- If you want to show trending stocks, call \`list_stocks\`.
146
- If you want to show events, call \`get_events\`.
147
- If the user wants to sell stock, or complete another impossible task, respond that you are a demo and cannot do that.
148
-
149
- Besides that, you can also chat with users and do some calculations if needed.`
150
-
151
- const span = trace.startLLMSpan({
152
- model: 'gpt-4o-mini',
153
- input: {
154
- type: 'chat_messages',
155
- value: [
156
- {
157
- role: 'system',
158
- content: system
159
- },
160
- ...convertFromVercelAIMessages(aiState.get().messages)
161
- ]
162
- }
163
- })
164
-
165
- const onFinish = (output: Message[]) => {
166
- aiState.done({
167
- ...aiState.get(),
168
- messages: [...aiState.get().messages, ...output]
169
- })
170
-
171
- span.end({
172
- output: {
173
- type: 'chat_messages',
174
- value: convertFromVercelAIMessages(output)
175
- }
176
- })
177
- }
178
-
179
- let textStream: undefined | ReturnType<typeof createStreamableValue<string>>
180
- let textNode: undefined | React.ReactNode
181
-
182
- const result = await streamUI({
183
- model: openai('gpt-4o-mini'),
184
- initial: <SpinnerMessage />,
185
- system,
186
- messages: [
187
- ...aiState.get().messages.map((message: any) => ({
188
- role: message.role,
189
- content: message.content,
190
- name: message.name
191
- }))
192
- ],
193
- text: ({ content, done, delta }) => {
194
- if (!textStream) {
195
- textStream = createStreamableValue('')
196
- textNode = <BotMessage content={textStream.value} />
197
- }
198
-
199
- if (done) {
200
- textStream.done()
201
-
202
- onFinish([
203
- {
204
- id: nanoid(),
205
- role: 'assistant',
206
- content
207
- }
208
- ])
209
- } else {
210
- textStream.update(delta)
211
- }
212
-
213
- return textNode
214
- },
215
- tools: {
216
- listStocks: {
217
- description: 'List three imaginary stocks that are trending.',
218
- parameters: z.object({
219
- stocks: z.array(
220
- z.object({
221
- symbol: z.string().describe('The symbol of the stock'),
222
- price: z.number().describe('The price of the stock'),
223
- delta: z.number().describe('The change in price of the stock')
224
- })
225
- )
226
- }),
227
- generate: async function* ({ stocks }) {
228
- yield (
229
- <BotCard>
230
- <StocksSkeleton />
231
- </BotCard>
232
- )
233
-
234
- await sleep(1000)
235
-
236
- const toolCallId = nanoid()
237
-
238
- onFinish([
239
- {
240
- id: nanoid(),
241
- role: 'assistant',
242
- content: [
243
- {
244
- type: 'tool-call',
245
- toolName: 'listStocks',
246
- toolCallId,
247
- args: { stocks }
248
- }
249
- ]
250
- },
251
- {
252
- id: nanoid(),
253
- role: 'tool',
254
- content: [
255
- {
256
- type: 'tool-result',
257
- toolName: 'listStocks',
258
- toolCallId,
259
- result: stocks
260
- }
261
- ]
262
- }
263
- ])
264
-
265
- return (
266
- <BotCard>
267
- <Stocks props={stocks} />
268
- </BotCard>
269
- )
270
- }
271
- },
272
- showStockPrice: {
273
- description:
274
- 'Get the current stock price of a given stock or currency. Use this to show the price to the user.',
275
- parameters: z.object({
276
- symbol: z
277
- .string()
278
- .describe(
279
- 'The name or symbol of the stock or currency. e.g. DOGE/AAPL/USD.'
280
- ),
281
- price: z.number().describe('The price of the stock.'),
282
- delta: z.number().describe('The change in price of the stock')
283
- }),
284
- generate: async function* ({ symbol, price, delta }) {
285
- yield (
286
- <BotCard>
287
- <StockSkeleton />
288
- </BotCard>
289
- )
290
-
291
- await sleep(1000)
292
-
293
- const toolCallId = nanoid()
294
-
295
- onFinish([
296
- {
297
- id: nanoid(),
298
- role: 'assistant',
299
- content: [
300
- {
301
- type: 'tool-call',
302
- toolName: 'showStockPrice',
303
- toolCallId,
304
- args: { symbol, price, delta }
305
- }
306
- ]
307
- },
308
- {
309
- id: nanoid(),
310
- role: 'tool',
311
- content: [
312
- {
313
- type: 'tool-result',
314
- toolName: 'showStockPrice',
315
- toolCallId,
316
- result: { symbol, price, delta }
317
- }
318
- ]
319
- }
320
- ])
321
-
322
- return (
323
- <BotCard>
324
- <Stock props={{ symbol, price, delta }} />
325
- </BotCard>
326
- )
327
- }
328
- },
329
- showStockPurchase: {
330
- description:
331
- 'Show price and the UI to purchase a stock or currency. Use this if the user wants to purchase a stock or currency.',
332
- parameters: z.object({
333
- symbol: z
334
- .string()
335
- .describe(
336
- 'The name or symbol of the stock or currency. e.g. DOGE/AAPL/USD.'
337
- ),
338
- price: z.number().describe('The price of the stock.'),
339
- numberOfShares: z
340
- .number()
341
- .describe(
342
- 'The **number of shares** for a stock or currency to purchase. Can be optional if the user did not specify it.'
343
- )
344
- }),
345
- generate: async function* ({ symbol, price, numberOfShares = 100 }) {
346
- const toolCallId = nanoid()
347
-
348
- if (numberOfShares <= 0 || numberOfShares > 1000) {
349
- onFinish([
350
- {
351
- id: nanoid(),
352
- role: 'assistant',
353
- content: [
354
- {
355
- type: 'tool-call',
356
- toolName: 'showStockPurchase',
357
- toolCallId,
358
- args: { symbol, price, numberOfShares }
359
- }
360
- ]
361
- },
362
- {
363
- id: nanoid(),
364
- role: 'tool',
365
- content: [
366
- {
367
- type: 'tool-result',
368
- toolName: 'showStockPurchase',
369
- toolCallId,
370
- result: {
371
- symbol,
372
- price,
373
- numberOfShares,
374
- status: 'expired'
375
- }
376
- }
377
- ]
378
- },
379
- {
380
- id: nanoid(),
381
- role: 'system',
382
- content: `[User has selected an invalid amount]`
383
- }
384
- ])
385
-
386
- return <BotMessage content={'Invalid amount'} />
387
- } else {
388
- onFinish([
389
- {
390
- id: nanoid(),
391
- role: 'assistant',
392
- content: [
393
- {
394
- type: 'tool-call',
395
- toolName: 'showStockPurchase',
396
- toolCallId,
397
- args: { symbol, price, numberOfShares }
398
- }
399
- ]
400
- },
401
- {
402
- id: nanoid(),
403
- role: 'tool',
404
- content: [
405
- {
406
- type: 'tool-result',
407
- toolName: 'showStockPurchase',
408
- toolCallId,
409
- result: {
410
- symbol,
411
- price,
412
- numberOfShares
413
- }
414
- }
415
- ]
416
- }
417
- ])
418
-
419
- return (
420
- <BotCard>
421
- <Purchase
422
- props={{
423
- numberOfShares,
424
- symbol,
425
- price: +price,
426
- status: 'requires_action'
427
- }}
428
- />
429
- </BotCard>
430
- )
431
- }
432
- }
433
- },
434
- getEvents: {
435
- description:
436
- 'List funny imaginary events between user highlighted dates that describe stock activity.',
437
- parameters: z.object({
438
- events: z.array(
439
- z.object({
440
- date: z
441
- .string()
442
- .describe('The date of the event, in ISO-8601 format'),
443
- headline: z.string().describe('The headline of the event'),
444
- description: z.string().describe('The description of the event')
445
- })
446
- )
447
- }),
448
- generate: async function* ({ events }) {
449
- yield (
450
- <BotCard>
451
- <EventsSkeleton />
452
- </BotCard>
453
- )
454
-
455
- await sleep(1000)
456
-
457
- const toolCallId = nanoid()
458
-
459
- onFinish([
460
- {
461
- id: nanoid(),
462
- role: 'assistant',
463
- content: [
464
- {
465
- type: 'tool-call',
466
- toolName: 'getEvents',
467
- toolCallId,
468
- args: { events }
469
- }
470
- ]
471
- },
472
- {
473
- id: nanoid(),
474
- role: 'tool',
475
- content: [
476
- {
477
- type: 'tool-result',
478
- toolName: 'getEvents',
479
- toolCallId,
480
- result: events
481
- }
482
- ]
483
- }
484
- ])
485
-
486
- return (
487
- <BotCard>
488
- <Events props={events} />
489
- </BotCard>
490
- )
491
- }
492
- }
493
- }
494
- })
495
-
496
- return {
497
- id: nanoid(),
498
- display: result.value
499
- }
500
- }
501
-
502
- export type AIState = {
503
- chatId: string
504
- messages: Message[]
505
- }
506
-
507
- export type UIState = {
508
- id: string
509
- display: React.ReactNode
510
- }[]
511
-
512
- export const ManualTracing = createAI<AIState, UIState>({
513
- actions: {
514
- submitUserMessage,
515
- confirmPurchase
516
- },
517
- initialUIState: [],
518
- initialAIState: { chatId: nanoid(), messages: [] },
519
- onGetUIState: async () => {
520
- 'use server'
521
-
522
- const session = await auth()
523
-
524
- if (session && session.user) {
525
- const aiState = getAIState()
526
-
527
- if (aiState) {
528
- // @ts-ignore
529
- const uiState = getUIStateFromAIState(aiState)
530
- return uiState
531
- }
532
- } else {
533
- return
534
- }
535
- },
536
- onSetAIState: async ({ state }) => {
537
- 'use server'
538
-
539
- const session = await auth()
540
-
541
- if (session && session.user) {
542
- const { chatId, messages } = state
543
-
544
- const createdAt = new Date()
545
- const userId = session.user.id as string
546
- const path = `/chat/${chatId}`
547
-
548
- const firstMessageContent = messages[0].content as string
549
- const title = firstMessageContent.substring(0, 100)
550
-
551
- const chat: Chat = {
552
- id: chatId,
553
- title,
554
- userId,
555
- createdAt,
556
- messages,
557
- path
558
- }
559
-
560
- await saveChat(chat)
561
- } else {
562
- return
563
- }
564
- }
565
- })
566
-
567
- export const getUIStateFromAIState = (aiState: Chat) => {
568
- return aiState.messages
569
- .filter(message => message.role !== 'system')
570
- .map((message, index) => ({
571
- id: `${aiState.chatId}-${index}`,
572
- display:
573
- message.role === 'tool' ? (
574
- message.content.map(tool => {
575
- return tool.toolName === 'listStocks' ? (
576
- <BotCard>
577
- {/* TODO: Infer types based on the tool result*/}
578
- {/* @ts-expect-error */}
579
- <Stocks props={tool.result} />
580
- </BotCard>
581
- ) : tool.toolName === 'showStockPrice' ? (
582
- <BotCard>
583
- {/* @ts-expect-error */}
584
- <Stock props={tool.result} />
585
- </BotCard>
586
- ) : tool.toolName === 'showStockPurchase' ? (
587
- <BotCard>
588
- {/* @ts-expect-error */}
589
- <Purchase props={tool.result} />
590
- </BotCard>
591
- ) : tool.toolName === 'getEvents' ? (
592
- <BotCard>
593
- {/* @ts-expect-error */}
594
- <Events props={tool.result} />
595
- </BotCard>
596
- ) : null
597
- })
598
- ) : message.role === 'user' ? (
599
- <UserMessage>{message.content as string}</UserMessage>
600
- ) : message.role === 'assistant' &&
601
- typeof message.content === 'string' ? (
602
- <BotMessage content={message.content} />
603
- ) : null
604
- }))
605
- }