langwatch 0.0.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 (132) hide show
  1. package/.eslintrc.cjs +37 -0
  2. package/README.md +3 -0
  3. package/dist/chunk-GOA2HL4A.mjs +269 -0
  4. package/dist/chunk-GOA2HL4A.mjs.map +1 -0
  5. package/dist/index.d.mts +82 -0
  6. package/dist/index.d.ts +82 -0
  7. package/dist/index.js +940 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/index.mjs +666 -0
  10. package/dist/index.mjs.map +1 -0
  11. package/dist/utils-s3gGR6vj.d.mts +209 -0
  12. package/dist/utils-s3gGR6vj.d.ts +209 -0
  13. package/dist/utils.d.mts +3 -0
  14. package/dist/utils.d.ts +3 -0
  15. package/dist/utils.js +263 -0
  16. package/dist/utils.js.map +1 -0
  17. package/dist/utils.mjs +7 -0
  18. package/dist/utils.mjs.map +1 -0
  19. package/example/.env.example +12 -0
  20. package/example/.eslintrc.json +26 -0
  21. package/example/LICENSE +13 -0
  22. package/example/README.md +10 -0
  23. package/example/app/(chat)/chat/[id]/page.tsx +60 -0
  24. package/example/app/(chat)/layout.tsx +14 -0
  25. package/example/app/(chat)/page.tsx +22 -0
  26. package/example/app/actions.ts +156 -0
  27. package/example/app/globals.css +76 -0
  28. package/example/app/layout.tsx +64 -0
  29. package/example/app/login/actions.ts +71 -0
  30. package/example/app/login/page.tsx +18 -0
  31. package/example/app/new/page.tsx +5 -0
  32. package/example/app/opengraph-image.png +0 -0
  33. package/example/app/share/[id]/page.tsx +58 -0
  34. package/example/app/signup/actions.ts +111 -0
  35. package/example/app/signup/page.tsx +18 -0
  36. package/example/app/twitter-image.png +0 -0
  37. package/example/auth.config.ts +42 -0
  38. package/example/auth.ts +45 -0
  39. package/example/components/button-scroll-to-bottom.tsx +36 -0
  40. package/example/components/chat-history.tsx +49 -0
  41. package/example/components/chat-list.tsx +52 -0
  42. package/example/components/chat-message-actions.tsx +40 -0
  43. package/example/components/chat-message.tsx +80 -0
  44. package/example/components/chat-panel.tsx +139 -0
  45. package/example/components/chat-share-dialog.tsx +95 -0
  46. package/example/components/chat.tsx +84 -0
  47. package/example/components/clear-history.tsx +75 -0
  48. package/example/components/empty-screen.tsx +38 -0
  49. package/example/components/external-link.tsx +29 -0
  50. package/example/components/footer.tsx +19 -0
  51. package/example/components/header.tsx +80 -0
  52. package/example/components/login-button.tsx +42 -0
  53. package/example/components/login-form.tsx +97 -0
  54. package/example/components/markdown.tsx +9 -0
  55. package/example/components/prompt-form.tsx +115 -0
  56. package/example/components/providers.tsx +17 -0
  57. package/example/components/sidebar-actions.tsx +125 -0
  58. package/example/components/sidebar-desktop.tsx +19 -0
  59. package/example/components/sidebar-footer.tsx +16 -0
  60. package/example/components/sidebar-item.tsx +124 -0
  61. package/example/components/sidebar-items.tsx +42 -0
  62. package/example/components/sidebar-list.tsx +38 -0
  63. package/example/components/sidebar-mobile.tsx +31 -0
  64. package/example/components/sidebar-toggle.tsx +24 -0
  65. package/example/components/sidebar.tsx +21 -0
  66. package/example/components/signup-form.tsx +95 -0
  67. package/example/components/stocks/events-skeleton.tsx +31 -0
  68. package/example/components/stocks/events.tsx +30 -0
  69. package/example/components/stocks/index.tsx +36 -0
  70. package/example/components/stocks/message.tsx +134 -0
  71. package/example/components/stocks/spinner.tsx +16 -0
  72. package/example/components/stocks/stock-purchase.tsx +146 -0
  73. package/example/components/stocks/stock-skeleton.tsx +22 -0
  74. package/example/components/stocks/stock.tsx +210 -0
  75. package/example/components/stocks/stocks-skeleton.tsx +9 -0
  76. package/example/components/stocks/stocks.tsx +67 -0
  77. package/example/components/tailwind-indicator.tsx +14 -0
  78. package/example/components/theme-toggle.tsx +31 -0
  79. package/example/components/ui/alert-dialog.tsx +141 -0
  80. package/example/components/ui/badge.tsx +36 -0
  81. package/example/components/ui/button.tsx +57 -0
  82. package/example/components/ui/codeblock.tsx +148 -0
  83. package/example/components/ui/dialog.tsx +122 -0
  84. package/example/components/ui/dropdown-menu.tsx +205 -0
  85. package/example/components/ui/icons.tsx +507 -0
  86. package/example/components/ui/input.tsx +25 -0
  87. package/example/components/ui/label.tsx +26 -0
  88. package/example/components/ui/select.tsx +164 -0
  89. package/example/components/ui/separator.tsx +31 -0
  90. package/example/components/ui/sheet.tsx +140 -0
  91. package/example/components/ui/sonner.tsx +31 -0
  92. package/example/components/ui/switch.tsx +29 -0
  93. package/example/components/ui/textarea.tsx +24 -0
  94. package/example/components/ui/tooltip.tsx +30 -0
  95. package/example/components/user-menu.tsx +53 -0
  96. package/example/components.json +17 -0
  97. package/example/lib/chat/actions.tsx +606 -0
  98. package/example/lib/hooks/use-copy-to-clipboard.tsx +33 -0
  99. package/example/lib/hooks/use-enter-submit.tsx +23 -0
  100. package/example/lib/hooks/use-local-storage.ts +24 -0
  101. package/example/lib/hooks/use-scroll-anchor.tsx +86 -0
  102. package/example/lib/hooks/use-sidebar.tsx +60 -0
  103. package/example/lib/hooks/use-streamable-text.ts +25 -0
  104. package/example/lib/types.ts +41 -0
  105. package/example/lib/utils.ts +89 -0
  106. package/example/middleware.ts +8 -0
  107. package/example/next-env.d.ts +5 -0
  108. package/example/next.config.js +13 -0
  109. package/example/package-lock.json +9249 -0
  110. package/example/package.json +77 -0
  111. package/example/pnpm-lock.yaml +5712 -0
  112. package/example/postcss.config.js +6 -0
  113. package/example/prettier.config.cjs +34 -0
  114. package/example/public/apple-touch-icon.png +0 -0
  115. package/example/public/favicon-16x16.png +0 -0
  116. package/example/public/favicon.ico +0 -0
  117. package/example/public/next.svg +1 -0
  118. package/example/public/thirteen.svg +1 -0
  119. package/example/public/vercel.svg +1 -0
  120. package/example/tailwind.config.ts +81 -0
  121. package/example/tsconfig.json +35 -0
  122. package/package.json +45 -0
  123. package/src/helpers.ts +64 -0
  124. package/src/index.test.ts +255 -0
  125. package/src/index.ts +397 -0
  126. package/src/server/types/.gitkeep +0 -0
  127. package/src/types.ts +69 -0
  128. package/src/utils.ts +134 -0
  129. package/ts-to-zod.config.js +18 -0
  130. package/tsconfig.json +32 -0
  131. package/tsup.config.ts +10 -0
  132. package/vitest.config.ts +8 -0
@@ -0,0 +1,86 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react'
2
+
3
+ export const useScrollAnchor = () => {
4
+ const messagesRef = useRef<HTMLDivElement>(null)
5
+ const scrollRef = useRef<HTMLDivElement>(null)
6
+ const visibilityRef = useRef<HTMLDivElement>(null)
7
+
8
+ const [isAtBottom, setIsAtBottom] = useState(true)
9
+ const [isVisible, setIsVisible] = useState(false)
10
+
11
+ const scrollToBottom = useCallback(() => {
12
+ if (messagesRef.current) {
13
+ messagesRef.current.scrollIntoView({
14
+ block: 'end',
15
+ behavior: 'smooth'
16
+ })
17
+ }
18
+ }, [])
19
+
20
+ useEffect(() => {
21
+ if (messagesRef.current) {
22
+ if (isAtBottom && !isVisible) {
23
+ messagesRef.current.scrollIntoView({
24
+ block: 'end'
25
+ })
26
+ }
27
+ }
28
+ }, [isAtBottom, isVisible])
29
+
30
+ useEffect(() => {
31
+ const { current } = scrollRef
32
+
33
+ if (current) {
34
+ const handleScroll = (event: Event) => {
35
+ const target = event.target as HTMLDivElement
36
+ const offset = 25
37
+ const isAtBottom =
38
+ target.scrollTop + target.clientHeight >= target.scrollHeight - offset
39
+
40
+ setIsAtBottom(isAtBottom)
41
+ }
42
+
43
+ current.addEventListener('scroll', handleScroll, {
44
+ passive: true
45
+ })
46
+
47
+ return () => {
48
+ current.removeEventListener('scroll', handleScroll)
49
+ }
50
+ }
51
+ }, [])
52
+
53
+ useEffect(() => {
54
+ if (visibilityRef.current) {
55
+ let observer = new IntersectionObserver(
56
+ entries => {
57
+ entries.forEach(entry => {
58
+ if (entry.isIntersecting) {
59
+ setIsVisible(true)
60
+ } else {
61
+ setIsVisible(false)
62
+ }
63
+ })
64
+ },
65
+ {
66
+ rootMargin: '0px 0px -150px 0px'
67
+ }
68
+ )
69
+
70
+ observer.observe(visibilityRef.current)
71
+
72
+ return () => {
73
+ observer.disconnect()
74
+ }
75
+ }
76
+ })
77
+
78
+ return {
79
+ messagesRef,
80
+ scrollRef,
81
+ visibilityRef,
82
+ scrollToBottom,
83
+ isAtBottom,
84
+ isVisible
85
+ }
86
+ }
@@ -0,0 +1,60 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+
5
+ const LOCAL_STORAGE_KEY = 'sidebar'
6
+
7
+ interface SidebarContext {
8
+ isSidebarOpen: boolean
9
+ toggleSidebar: () => void
10
+ isLoading: boolean
11
+ }
12
+
13
+ const SidebarContext = React.createContext<SidebarContext | undefined>(
14
+ undefined
15
+ )
16
+
17
+ export function useSidebar() {
18
+ const context = React.useContext(SidebarContext)
19
+ if (!context) {
20
+ throw new Error('useSidebarContext must be used within a SidebarProvider')
21
+ }
22
+ return context
23
+ }
24
+
25
+ interface SidebarProviderProps {
26
+ children: React.ReactNode
27
+ }
28
+
29
+ export function SidebarProvider({ children }: SidebarProviderProps) {
30
+ const [isSidebarOpen, setSidebarOpen] = React.useState(true)
31
+ const [isLoading, setLoading] = React.useState(true)
32
+
33
+ React.useEffect(() => {
34
+ const value = localStorage.getItem(LOCAL_STORAGE_KEY)
35
+ if (value) {
36
+ setSidebarOpen(JSON.parse(value))
37
+ }
38
+ setLoading(false)
39
+ }, [])
40
+
41
+ const toggleSidebar = () => {
42
+ setSidebarOpen(value => {
43
+ const newState = !value
44
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(newState))
45
+ return newState
46
+ })
47
+ }
48
+
49
+ if (isLoading) {
50
+ return null
51
+ }
52
+
53
+ return (
54
+ <SidebarContext.Provider
55
+ value={{ isSidebarOpen, toggleSidebar, isLoading }}
56
+ >
57
+ {children}
58
+ </SidebarContext.Provider>
59
+ )
60
+ }
@@ -0,0 +1,25 @@
1
+ import { StreamableValue, readStreamableValue } from 'ai/rsc'
2
+ import { useEffect, useState } from 'react'
3
+
4
+ export const useStreamableText = (
5
+ content: string | StreamableValue<string>
6
+ ) => {
7
+ const [rawContent, setRawContent] = useState(
8
+ typeof content === 'string' ? content : ''
9
+ )
10
+
11
+ useEffect(() => {
12
+ ;(async () => {
13
+ if (typeof content === 'object') {
14
+ let value = ''
15
+ for await (const delta of readStreamableValue(content)) {
16
+ if (typeof delta === 'string') {
17
+ setRawContent((value = value + delta))
18
+ }
19
+ }
20
+ }
21
+ })()
22
+ }, [content])
23
+
24
+ return rawContent
25
+ }
@@ -0,0 +1,41 @@
1
+ import { CoreMessage } from 'ai'
2
+
3
+ export type Message = CoreMessage & {
4
+ id: string
5
+ }
6
+
7
+ export interface Chat extends Record<string, any> {
8
+ id: string
9
+ title: string
10
+ createdAt: Date
11
+ userId: string
12
+ path: string
13
+ messages: Message[]
14
+ sharePath?: string
15
+ }
16
+
17
+ export type ServerActionResult<Result> = Promise<
18
+ | Result
19
+ | {
20
+ error: string
21
+ }
22
+ >
23
+
24
+ export interface Session {
25
+ user: {
26
+ id: string
27
+ email: string
28
+ }
29
+ }
30
+
31
+ export interface AuthResult {
32
+ type: string
33
+ message: string
34
+ }
35
+
36
+ export interface User extends Record<string, any> {
37
+ id: string
38
+ email: string
39
+ password: string
40
+ salt: string
41
+ }
@@ -0,0 +1,89 @@
1
+ import { clsx, type ClassValue } from 'clsx'
2
+ import { customAlphabet } from 'nanoid'
3
+ import { twMerge } from 'tailwind-merge'
4
+
5
+ export function cn(...inputs: ClassValue[]) {
6
+ return twMerge(clsx(inputs))
7
+ }
8
+
9
+ export const nanoid = customAlphabet(
10
+ '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
11
+ 7
12
+ ) // 7-character random string
13
+
14
+ export async function fetcher<JSON = any>(
15
+ input: RequestInfo,
16
+ init?: RequestInit
17
+ ): Promise<JSON> {
18
+ const res = await fetch(input, init)
19
+
20
+ if (!res.ok) {
21
+ const json = await res.json()
22
+ if (json.error) {
23
+ const error = new Error(json.error) as Error & {
24
+ status: number
25
+ }
26
+ error.status = res.status
27
+ throw error
28
+ } else {
29
+ throw new Error('An unexpected error occurred')
30
+ }
31
+ }
32
+
33
+ return res.json()
34
+ }
35
+
36
+ export function formatDate(input: string | number | Date): string {
37
+ const date = new Date(input)
38
+ return date.toLocaleDateString('en-US', {
39
+ month: 'long',
40
+ day: 'numeric',
41
+ year: 'numeric'
42
+ })
43
+ }
44
+
45
+ export const formatNumber = (value: number) =>
46
+ new Intl.NumberFormat('en-US', {
47
+ style: 'currency',
48
+ currency: 'USD'
49
+ }).format(value)
50
+
51
+ export const runAsyncFnWithoutBlocking = (
52
+ fn: (...args: any) => Promise<any>
53
+ ) => {
54
+ fn()
55
+ }
56
+
57
+ export const sleep = (ms: number) =>
58
+ new Promise(resolve => setTimeout(resolve, ms))
59
+
60
+ export const getStringFromBuffer = (buffer: ArrayBuffer) =>
61
+ Array.from(new Uint8Array(buffer))
62
+ .map(b => b.toString(16).padStart(2, '0'))
63
+ .join('')
64
+
65
+ export enum ResultCode {
66
+ InvalidCredentials = 'INVALID_CREDENTIALS',
67
+ InvalidSubmission = 'INVALID_SUBMISSION',
68
+ UserAlreadyExists = 'USER_ALREADY_EXISTS',
69
+ UnknownError = 'UNKNOWN_ERROR',
70
+ UserCreated = 'USER_CREATED',
71
+ UserLoggedIn = 'USER_LOGGED_IN'
72
+ }
73
+
74
+ export const getMessageFromCode = (resultCode: string) => {
75
+ switch (resultCode) {
76
+ case ResultCode.InvalidCredentials:
77
+ return 'Invalid credentials!'
78
+ case ResultCode.InvalidSubmission:
79
+ return 'Invalid submission, please try again!'
80
+ case ResultCode.UserAlreadyExists:
81
+ return 'User already exists, please log in!'
82
+ case ResultCode.UserCreated:
83
+ return 'User created, welcome!'
84
+ case ResultCode.UnknownError:
85
+ return 'Something went wrong, please try again!'
86
+ case ResultCode.UserLoggedIn:
87
+ return 'Logged in!'
88
+ }
89
+ }
@@ -0,0 +1,8 @@
1
+ import NextAuth from 'next-auth'
2
+ import { authConfig } from './auth.config'
3
+
4
+ export default NextAuth(authConfig).auth
5
+
6
+ export const config = {
7
+ matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)']
8
+ }
@@ -0,0 +1,5 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/basic-features/typescript for more information.
@@ -0,0 +1,13 @@
1
+ /** @type {import('next').NextConfig} */
2
+ module.exports = {
3
+ images: {
4
+ remotePatterns: [
5
+ {
6
+ protocol: 'https',
7
+ hostname: 'avatars.githubusercontent.com',
8
+ port: '',
9
+ pathname: '**'
10
+ }
11
+ ]
12
+ }
13
+ }