@superinterface/react 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +41 -0
- package/src/components/examples/Examples/Example/index.tsx +65 -0
- package/src/components/examples/Examples/index.tsx +85 -0
- package/src/components/messageGroups/MessagesGroupBase/AssistantAvatar.tsx +18 -0
- package/src/components/messageGroups/MessagesGroupBase/Name.tsx +24 -0
- package/src/components/messageGroups/MessagesGroupBase/index.tsx +29 -0
- package/src/components/messages/Form/Submit/index.tsx +29 -0
- package/src/components/messages/Form/index.tsx +150 -0
- package/src/components/messages/Message/TextContent/index.tsx +22 -0
- package/src/components/messages/Message/index.tsx +71 -0
- package/src/components/messages/Messages/Content/MessageGroup/Content/index.tsx +22 -0
- package/src/components/messages/Messages/Content/MessageGroup/index.tsx +47 -0
- package/src/components/messages/Messages/Content/index.tsx +26 -0
- package/src/components/messages/Messages/ProgressMessage/index.tsx +31 -0
- package/src/components/messages/Messages/index.tsx +102 -0
- package/src/components/runSteps/RunStep/ToolCalls/Starting/index.tsx +28 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/CodeInterpreter/index.tsx +17 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/Fn/Availabilities/Title.tsx +29 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/Fn/Availabilities/index.tsx +34 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/Fn/Content/index.tsx +58 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/Fn/Icon.tsx +28 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/Fn/Scores/Title.tsx +29 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/Fn/Scores/index.tsx +34 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/Fn/index.tsx +31 -0
- package/src/components/runSteps/RunStep/ToolCalls/ToolCall/index.tsx +44 -0
- package/src/components/runSteps/RunStep/ToolCalls/index.tsx +31 -0
- package/src/components/runSteps/RunStep/index.tsx +21 -0
- package/src/components/runSteps/RunSteps/index.tsx +22 -0
- package/src/components/skeletons/MessagesSkeleton/index.tsx +50 -0
- package/src/components/skeletons/RunSkeleton/index.tsx +34 -0
- package/src/components/skeletons/Skeleton/index.tsx +17 -0
- package/src/components/skeletons/StartingContentSkeleton/index.tsx +13 -0
- package/src/components/skeletons/StartingSkeleton/index.tsx +33 -0
- package/src/components/spinners/Spinner/index.tsx +17 -0
- package/src/components/textareas/TextareaBase/index.tsx +28 -0
- package/src/components/toolCalls/ToolCallBase/ToolCallTitle.tsx +17 -0
- package/src/components/toolCalls/ToolCallBase/index.tsx +34 -0
- package/src/contexts/assistants/AssistantNameContext/index.tsx +3 -0
- package/src/contexts/avatars/AssistantAvatarContext/index.tsx +14 -0
- package/src/contexts/markdown/MarkdownContext/index.ts +7 -0
- package/src/contexts/markdown/MarkdownContext/lib/components/Link.tsx +13 -0
- package/src/contexts/markdown/MarkdownContext/lib/components/ListItem.tsx +13 -0
- package/src/contexts/markdown/MarkdownContext/lib/components/OrderedList.tsx +16 -0
- package/src/contexts/markdown/MarkdownContext/lib/components/Paragraph.tsx +17 -0
- package/src/contexts/markdown/MarkdownContext/lib/components/Strong.tsx +9 -0
- package/src/contexts/markdown/MarkdownContext/lib/components/UnorderedList.tsx +16 -0
- package/src/contexts/markdown/MarkdownContext/lib/components/index.tsx +16 -0
- package/src/hooks/actions/useHandleAction/index.tsx +30 -0
- package/src/hooks/actions/useHandleAction/lib/mutationOptions/index.ts +14 -0
- package/src/hooks/actions/useHandleAction/lib/mutationOptions/mutationFn/index.ts +39 -0
- package/src/hooks/actions/useHandleAction/lib/mutationOptions/mutationFn/toolOutput/index.ts +29 -0
- package/src/hooks/actions/useHandleAction/lib/mutationOptions/onSettled.ts +22 -0
- package/src/hooks/actions/useManageActions/index.tsx +43 -0
- package/src/hooks/messageGroups/useMessageGroups/index.ts +18 -0
- package/src/hooks/messageGroups/useMessageGroups/lib/messageGroups/index.ts +37 -0
- package/src/hooks/messageGroups/useMessageGroups/lib/messageGroups/newGroup/index.ts +14 -0
- package/src/hooks/messageGroups/useMessageGroups/lib/messageGroups/newGroup/newGroupItem.ts +12 -0
- package/src/hooks/messages/useCreateMessage/index.ts +30 -0
- package/src/hooks/messages/useCreateMessage/lib/mutationOptions/index.ts +24 -0
- package/src/hooks/messages/useCreateMessage/lib/mutationOptions/mutationFn.ts +25 -0
- package/src/hooks/messages/useCreateMessage/lib/mutationOptions/onError.ts +27 -0
- package/src/hooks/messages/useCreateMessage/lib/mutationOptions/onMutate/data.ts +62 -0
- package/src/hooks/messages/useCreateMessage/lib/mutationOptions/onMutate/index.ts +25 -0
- package/src/hooks/messages/useCreateMessage/lib/mutationOptions/onSettled.ts +16 -0
- package/src/hooks/messages/useCreateMessage/lib/mutationOptions/onSuccess.ts +48 -0
- package/src/hooks/messages/useLatestMessage/index.ts +20 -0
- package/src/hooks/messages/useMessages/index.tsx +41 -0
- package/src/hooks/messages/useMessages/lib/queryOptions/index.ts +20 -0
- package/src/hooks/messages/useMessages/lib/queryOptions/queryFn/data/index.ts +32 -0
- package/src/hooks/messages/useMessages/lib/queryOptions/queryFn/data/runMessages/getLatestRun.ts +15 -0
- package/src/hooks/messages/useMessages/lib/queryOptions/queryFn/data/runMessages/index.ts +44 -0
- package/src/hooks/messages/useMessages/lib/queryOptions/queryFn/hasNextPage.ts +12 -0
- package/src/hooks/messages/useMessages/lib/queryOptions/queryFn/index.ts +32 -0
- package/src/hooks/messages/useMessages/lib/queryOptions/queryFn/messagesLimit.ts +1 -0
- package/src/hooks/messages/useMessages/lib/queryOptions/queryKey.ts +3 -0
- package/src/hooks/misc/useInfiniteScroll/index.tsx +42 -0
- package/src/hooks/misc/useThrottledEffect/index.tsx +19 -0
- package/src/hooks/runs/useCreateRun/index.ts +30 -0
- package/src/hooks/runs/useCreateRun/lib/mutationOptions/index.ts +16 -0
- package/src/hooks/runs/useCreateRun/lib/mutationOptions/mutationFn.ts +30 -0
- package/src/hooks/runs/useCreateRun/lib/mutationOptions/onSettled.ts +22 -0
- package/src/hooks/runs/useCreateRun/lib/mutationOptions/onSuccess.ts +44 -0
- package/src/hooks/runs/useIsRunActive/index.tsx +65 -0
- package/src/hooks/runs/useLatestRun/index.ts +20 -0
- package/src/hooks/runs/useManageRuns/index.tsx +55 -0
- package/src/hooks/runs/usePolling/index.tsx +39 -0
- package/src/hooks/runs/usePolling/lib/refetch.ts +20 -0
- package/src/hooks/runs/useRuns/index.tsx +27 -0
- package/src/hooks/runs/useRuns/lib/getRuns.ts +16 -0
- package/src/hooks/runs/useRuns/lib/queryOptions/index.ts +21 -0
- package/src/hooks/runs/useRuns/lib/queryOptions/queryFn.ts +22 -0
- package/src/hooks/runs/useRuns/lib/queryOptions/queryKey.ts +3 -0
- package/src/hooks/threads/useThreadLifecycles/index.tsx +41 -0
- package/src/index.ts +12 -0
- package/src/lib/ai/index.ts +15 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/messages/extendMessage.ts +25 -0
- package/src/lib/messages/order.ts +9 -0
- package/src/lib/optimistic/isOptimistic.ts +11 -0
- package/src/lib/optimistic/optimisticId.ts +5 -0
- package/src/lib/runSteps/getRunSteps/index.ts +18 -0
- package/src/lib/runs/isRunEditingMessage/index.ts +21 -0
- package/src/mutationFns.ts +3 -0
- package/src/queryFns.ts +2 -0
- package/src/queryKeys.ts +2 -0
- package/src/types/index.ts +38 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { queryKey as messagesQueryKey } from '@/hooks/messages/useMessages/lib/queryOptions/queryKey'
|
|
2
|
+
import { Args as NewMessageArgs } from '../mutationFn'
|
|
3
|
+
import { data } from './data'
|
|
4
|
+
|
|
5
|
+
type Args = {
|
|
6
|
+
queryClient: any
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const onMutate = ({
|
|
10
|
+
queryClient,
|
|
11
|
+
}: Args) => async (newMessage: NewMessageArgs) => {
|
|
12
|
+
await queryClient.cancelQueries(messagesQueryKey())
|
|
13
|
+
|
|
14
|
+
const prevMessages = queryClient.getQueryData(messagesQueryKey())
|
|
15
|
+
|
|
16
|
+
queryClient.setQueryData(
|
|
17
|
+
messagesQueryKey(),
|
|
18
|
+
data({ newMessage })
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
prevMessages,
|
|
23
|
+
newMessage,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { queryKey as messagesQueryKey } from '@/hooks/messages/useMessages/lib/queryOptions/queryKey'
|
|
2
|
+
import { Response } from './mutationFn'
|
|
3
|
+
|
|
4
|
+
type Args = {
|
|
5
|
+
queryClient: any
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const onSettled = ({
|
|
9
|
+
queryClient,
|
|
10
|
+
}: Args) => async (response: Response | undefined) => {
|
|
11
|
+
if (!response) return
|
|
12
|
+
|
|
13
|
+
await queryClient.invalidateQueries({
|
|
14
|
+
queryKey: messagesQueryKey(),
|
|
15
|
+
})
|
|
16
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { queryKey as messagesQueryKey } from '@/hooks/messages/useMessages/lib/queryOptions/queryKey'
|
|
2
|
+
import { Response } from './mutationFn'
|
|
3
|
+
|
|
4
|
+
type Args = {
|
|
5
|
+
queryClient: any
|
|
6
|
+
passedOnSuccess?: () => void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const onSuccess = ({
|
|
10
|
+
queryClient,
|
|
11
|
+
passedOnSuccess,
|
|
12
|
+
}: Args) => (response: Response) => {
|
|
13
|
+
passedOnSuccess?.()
|
|
14
|
+
|
|
15
|
+
queryClient.setQueryData(
|
|
16
|
+
messagesQueryKey(),
|
|
17
|
+
(prevData: any) => {
|
|
18
|
+
if (!prevData) {
|
|
19
|
+
return {
|
|
20
|
+
pageParams: [],
|
|
21
|
+
pages: [
|
|
22
|
+
{
|
|
23
|
+
data: [response.message],
|
|
24
|
+
hasNextPage: false,
|
|
25
|
+
lastId: response.message.id,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const [latestPage, ...pagesRest] = prevData.pages
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
...prevData,
|
|
35
|
+
pages: [
|
|
36
|
+
{
|
|
37
|
+
...latestPage,
|
|
38
|
+
data: [
|
|
39
|
+
response.message,
|
|
40
|
+
...latestPage.data,
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
...pagesRest,
|
|
44
|
+
],
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UseInfiniteQueryOptions,
|
|
3
|
+
InfiniteData,
|
|
4
|
+
} from '@tanstack/react-query'
|
|
5
|
+
import { useMemo } from 'react'
|
|
6
|
+
import { useMessages } from '@/hooks/messages/useMessages'
|
|
7
|
+
import { MessagesPage } from '@/types'
|
|
8
|
+
|
|
9
|
+
type Args = {
|
|
10
|
+
messagesQueryOptions: UseInfiniteQueryOptions<InfiniteData<MessagesPage>>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const useLatestMessage = (args: Args) => {
|
|
14
|
+
const props = useMessages(args)
|
|
15
|
+
|
|
16
|
+
return useMemo(() => ({
|
|
17
|
+
...props,
|
|
18
|
+
latestMessage: props.messages[0] || null,
|
|
19
|
+
}), [props])
|
|
20
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
useInfiniteQuery,
|
|
4
|
+
InfiniteData,
|
|
5
|
+
UseInfiniteQueryOptions,
|
|
6
|
+
} from '@tanstack/react-query'
|
|
7
|
+
import { Message, MessagesPage } from '@/types'
|
|
8
|
+
import { queryOptions as defaultQueryOptions } from './lib/queryOptions'
|
|
9
|
+
|
|
10
|
+
type Args = {
|
|
11
|
+
messagesQueryOptions: UseInfiniteQueryOptions<InfiniteData<MessagesPage>>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const messages = ({
|
|
15
|
+
props,
|
|
16
|
+
}: {
|
|
17
|
+
props: {
|
|
18
|
+
data: InfiniteData<MessagesPage> | undefined
|
|
19
|
+
},
|
|
20
|
+
}) => {
|
|
21
|
+
if (!props.data) return []
|
|
22
|
+
|
|
23
|
+
return props.data.pages.reduce<Message[]>((acc, page) => (
|
|
24
|
+
acc.concat(page.data)
|
|
25
|
+
), [])
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
export const useMessages = ({
|
|
30
|
+
messagesQueryOptions,
|
|
31
|
+
}: Args) => {
|
|
32
|
+
const props = useInfiniteQuery({
|
|
33
|
+
...defaultQueryOptions,
|
|
34
|
+
...messagesQueryOptions,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
return useMemo(() => ({
|
|
38
|
+
...props,
|
|
39
|
+
messages: messages({ props }),
|
|
40
|
+
}), [props])
|
|
41
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { MessagesPage } from '@/types'
|
|
2
|
+
// import { queryFn } from './queryFn'
|
|
3
|
+
import { queryKey } from './queryKey'
|
|
4
|
+
|
|
5
|
+
export const queryOptions = {
|
|
6
|
+
queryKey: queryKey(),
|
|
7
|
+
// queryFn: ({
|
|
8
|
+
// pageParam,
|
|
9
|
+
// }: { pageParam?: string }) => (
|
|
10
|
+
// queryFn({
|
|
11
|
+
// ...(pageParam ? { cursor: pageParam } : {}),
|
|
12
|
+
// })
|
|
13
|
+
// ),
|
|
14
|
+
initialPageParam: undefined,
|
|
15
|
+
getNextPageParam: (lastPage: MessagesPage) => {
|
|
16
|
+
if (!lastPage.hasNextPage) return null
|
|
17
|
+
|
|
18
|
+
return lastPage.lastId
|
|
19
|
+
},
|
|
20
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import OpenAI from 'openai'
|
|
2
|
+
import pMap from 'p-map'
|
|
3
|
+
import { extendMessage } from '@/lib/messages/extendMessage'
|
|
4
|
+
import { runMessages } from './runMessages'
|
|
5
|
+
|
|
6
|
+
export const data = async ({
|
|
7
|
+
messagesResponse,
|
|
8
|
+
cursor,
|
|
9
|
+
threadId,
|
|
10
|
+
}: {
|
|
11
|
+
messagesResponse: OpenAI.CursorPage<OpenAI.Beta.Threads.Messages.ThreadMessage>
|
|
12
|
+
cursor?: string
|
|
13
|
+
threadId: string
|
|
14
|
+
}) => {
|
|
15
|
+
const messages = await pMap(messagesResponse.data, (message) => (
|
|
16
|
+
extendMessage({
|
|
17
|
+
message,
|
|
18
|
+
})
|
|
19
|
+
))
|
|
20
|
+
|
|
21
|
+
if (cursor) {
|
|
22
|
+
return messages
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return [
|
|
26
|
+
...await runMessages({
|
|
27
|
+
messages,
|
|
28
|
+
threadId,
|
|
29
|
+
}),
|
|
30
|
+
...messages,
|
|
31
|
+
]
|
|
32
|
+
}
|
package/src/hooks/messages/useMessages/lib/queryOptions/queryFn/data/runMessages/getLatestRun.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { client } from '@/lib/ai'
|
|
2
|
+
|
|
3
|
+
type Args = {
|
|
4
|
+
threadId: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const getLatestRun = async ({
|
|
8
|
+
threadId,
|
|
9
|
+
}: Args) => {
|
|
10
|
+
const runsResponse = await client.beta.threads.runs.list(threadId, {
|
|
11
|
+
limit: 1,
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
return runsResponse.data[0]
|
|
15
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import OpenAI from 'openai'
|
|
2
|
+
import { Message } from '@/types'
|
|
3
|
+
import { getLatestRun } from './getLatestRun'
|
|
4
|
+
import { extendMessage } from '@/lib/messages/extendMessage'
|
|
5
|
+
import { optimisticId } from '@/lib/optimistic/optimisticId'
|
|
6
|
+
|
|
7
|
+
type Args = {
|
|
8
|
+
messages: Message[]
|
|
9
|
+
threadId: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const runMessages = async ({
|
|
13
|
+
messages,
|
|
14
|
+
threadId,
|
|
15
|
+
}: Args) => {
|
|
16
|
+
const latestRun = await getLatestRun({ threadId })
|
|
17
|
+
|
|
18
|
+
if (!latestRun) {
|
|
19
|
+
return []
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const messageFromLatestRun = messages.find(m => m.run_id === latestRun.id)
|
|
23
|
+
|
|
24
|
+
if (messageFromLatestRun) {
|
|
25
|
+
return []
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return [
|
|
29
|
+
await extendMessage({
|
|
30
|
+
message: {
|
|
31
|
+
id: optimisticId(),
|
|
32
|
+
role: 'assistant' as OpenAI.Beta.Threads.Messages.ThreadMessage['role'],
|
|
33
|
+
created_at: +new Date(),
|
|
34
|
+
object: 'thread.message' as OpenAI.Beta.Threads.Messages.ThreadMessage['object'],
|
|
35
|
+
content: [],
|
|
36
|
+
run_id: latestRun.id,
|
|
37
|
+
assistant_id: latestRun.assistant_id,
|
|
38
|
+
thread_id: latestRun.thread_id,
|
|
39
|
+
file_ids: [],
|
|
40
|
+
metadata: {},
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
]
|
|
44
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import OpenAI from 'openai'
|
|
2
|
+
import { messagesLimit } from './messagesLimit'
|
|
3
|
+
|
|
4
|
+
export const hasNextPage = ({
|
|
5
|
+
messagesResponse,
|
|
6
|
+
}: {
|
|
7
|
+
messagesResponse: OpenAI.CursorPage<OpenAI.Beta.Threads.Messages.ThreadMessage>
|
|
8
|
+
}) => {
|
|
9
|
+
if (messagesResponse.data.length < messagesLimit) return false
|
|
10
|
+
|
|
11
|
+
return messagesResponse.hasNextPage()
|
|
12
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { client } from '@/lib/ai'
|
|
3
|
+
import { MessagesPage } from '@/types'
|
|
4
|
+
import { data } from './data'
|
|
5
|
+
import { messagesLimit } from './messagesLimit'
|
|
6
|
+
import { hasNextPage } from './hasNextPage'
|
|
7
|
+
|
|
8
|
+
type Args = {
|
|
9
|
+
threadId: string
|
|
10
|
+
cursor?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const queryFn = async ({
|
|
14
|
+
threadId,
|
|
15
|
+
cursor,
|
|
16
|
+
}: Args): Promise<MessagesPage> => {
|
|
17
|
+
const messagesResponse = await client.beta.threads.messages.list(threadId, {
|
|
18
|
+
...(cursor ? { after: cursor } : {}),
|
|
19
|
+
limit: messagesLimit,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
data: await data({
|
|
24
|
+
messagesResponse,
|
|
25
|
+
cursor,
|
|
26
|
+
threadId,
|
|
27
|
+
}),
|
|
28
|
+
hasNextPage: hasNextPage({ messagesResponse }),
|
|
29
|
+
// @ts-ignore-next-line
|
|
30
|
+
lastId: messagesResponse.body.last_id,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const messagesLimit = 10
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useRef } from 'react'
|
|
2
|
+
import { useInView } from 'react-intersection-observer'
|
|
3
|
+
import { useThrottledEffect } from '@/hooks/misc/useThrottledEffect'
|
|
4
|
+
|
|
5
|
+
type Args = {
|
|
6
|
+
isFetchingNextPage: boolean
|
|
7
|
+
hasNextPage: boolean
|
|
8
|
+
fetchNextPage: () => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const useInfiniteScroll = ({
|
|
12
|
+
isFetchingNextPage,
|
|
13
|
+
hasNextPage,
|
|
14
|
+
fetchNextPage,
|
|
15
|
+
}: Args) => {
|
|
16
|
+
const containerRef = useRef(null)
|
|
17
|
+
|
|
18
|
+
const { ref: loaderRef, inView } = useInView({
|
|
19
|
+
root: containerRef.current,
|
|
20
|
+
rootMargin: '0px',
|
|
21
|
+
threshold: 0.1,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
useThrottledEffect(
|
|
25
|
+
() => {
|
|
26
|
+
if (isFetchingNextPage) return
|
|
27
|
+
if (!inView) return
|
|
28
|
+
if (!hasNextPage) return
|
|
29
|
+
|
|
30
|
+
console.log('Fetching next page')
|
|
31
|
+
fetchNextPage()
|
|
32
|
+
},
|
|
33
|
+
500,
|
|
34
|
+
[inView, isFetchingNextPage, hasNextPage, fetchNextPage]
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
containerRef,
|
|
39
|
+
loaderRef,
|
|
40
|
+
inView,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { useRef, useEffect, useCallback } from 'react'
|
|
3
|
+
|
|
4
|
+
export const useThrottledEffect = (cb: Function, delay: number, additionalDeps: any[]) => {
|
|
5
|
+
const cbRef = useRef(cb)
|
|
6
|
+
|
|
7
|
+
const throttledCb = useCallback(
|
|
8
|
+
_.throttle((...args: any[]) => cbRef.current(...args), delay, {
|
|
9
|
+
leading: true,
|
|
10
|
+
trailing: true,
|
|
11
|
+
}),
|
|
12
|
+
[delay]
|
|
13
|
+
)
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
cbRef.current = cb
|
|
16
|
+
})
|
|
17
|
+
// set additionalDeps to execute effect, when other values change (not only on delay change)
|
|
18
|
+
useEffect(throttledCb, [throttledCb, ...additionalDeps])
|
|
19
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useMutation,
|
|
3
|
+
useQueryClient,
|
|
4
|
+
UseMutationOptions,
|
|
5
|
+
} from '@tanstack/react-query'
|
|
6
|
+
import { mutationOptions } from './lib/mutationOptions'
|
|
7
|
+
import { Run } from '@/types'
|
|
8
|
+
|
|
9
|
+
type Args = {
|
|
10
|
+
createRunMutationOptions: UseMutationOptions<{ run: Run }>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const useCreateRun = ({
|
|
14
|
+
createRunMutationOptions,
|
|
15
|
+
}: Args) => {
|
|
16
|
+
const queryClient = useQueryClient()
|
|
17
|
+
|
|
18
|
+
// @ts-ignore-next-line
|
|
19
|
+
const mutationProps = useMutation({
|
|
20
|
+
...mutationOptions({
|
|
21
|
+
queryClient,
|
|
22
|
+
}),
|
|
23
|
+
...createRunMutationOptions,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
...mutationProps,
|
|
28
|
+
createRun: mutationProps.mutate,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query'
|
|
2
|
+
// import { mutationFn } from './mutationFn'
|
|
3
|
+
import { onSuccess } from './onSuccess'
|
|
4
|
+
import { onSettled } from './onSettled'
|
|
5
|
+
|
|
6
|
+
type Args = {
|
|
7
|
+
queryClient: QueryClient
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const mutationOptions = ({
|
|
11
|
+
queryClient,
|
|
12
|
+
}: Args) => ({
|
|
13
|
+
// mutationFn,
|
|
14
|
+
onSuccess: onSuccess({ queryClient }),
|
|
15
|
+
onSettled: onSettled({ queryClient }),
|
|
16
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Run } from '@/types'
|
|
2
|
+
import { client } from '@/lib/ai'
|
|
3
|
+
|
|
4
|
+
type Args = {
|
|
5
|
+
threadId: string
|
|
6
|
+
assistantId: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type Response = {
|
|
10
|
+
run: Run
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const mutationFn = async ({
|
|
14
|
+
threadId,
|
|
15
|
+
assistantId,
|
|
16
|
+
}: Args): Promise<Response> => {
|
|
17
|
+
const run = await client.beta.threads.runs.create(threadId, {
|
|
18
|
+
assistant_id: assistantId,
|
|
19
|
+
// model: 'gpt-3.5-turbo-1106',
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
// @ts-ignore-next-line
|
|
24
|
+
run,
|
|
25
|
+
}
|
|
26
|
+
// ...run,
|
|
27
|
+
// assistantConversationId,
|
|
28
|
+
// },
|
|
29
|
+
// }
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { queryKey as messagesQueryKey } from '@/hooks/messages/useMessages/lib/queryOptions/queryKey'
|
|
2
|
+
import { queryKey as runsQueryKey } from '@/hooks/runs/useRuns/lib/queryOptions/queryKey'
|
|
3
|
+
import { Response } from './mutationFn'
|
|
4
|
+
|
|
5
|
+
type Args = {
|
|
6
|
+
queryClient: any
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const onSettled = ({
|
|
10
|
+
queryClient,
|
|
11
|
+
}: Args) => (response: Response | undefined) => {
|
|
12
|
+
if (!response) {
|
|
13
|
+
throw new Error('useCreateRun onSettled: response is undefined')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
queryClient.invalidateQueries({
|
|
17
|
+
queryKey: messagesQueryKey(),
|
|
18
|
+
})
|
|
19
|
+
queryClient.invalidateQueries({
|
|
20
|
+
queryKey: runsQueryKey(),
|
|
21
|
+
})
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { queryKey as runsQueryKey } from '@/hooks/runs/useRuns/lib/queryOptions/queryKey'
|
|
2
|
+
import { Response } from './mutationFn'
|
|
3
|
+
|
|
4
|
+
type Args = {
|
|
5
|
+
queryClient: any
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const onSuccess = ({
|
|
9
|
+
queryClient,
|
|
10
|
+
}: Args) => (response: Response) => (
|
|
11
|
+
queryClient.setQueryData(
|
|
12
|
+
runsQueryKey(),
|
|
13
|
+
(prevData: any) => {
|
|
14
|
+
if (!prevData) {
|
|
15
|
+
return {
|
|
16
|
+
pageParams: [],
|
|
17
|
+
pages: [
|
|
18
|
+
{
|
|
19
|
+
data: [response.run],
|
|
20
|
+
hasNextPage: false,
|
|
21
|
+
lastId: response.run.id,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const [latestPage, ...pagesRest] = prevData.pages
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
...prevData,
|
|
31
|
+
pages: [
|
|
32
|
+
{
|
|
33
|
+
...latestPage,
|
|
34
|
+
data: [
|
|
35
|
+
response.run,
|
|
36
|
+
...latestPage.data,
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
...pagesRest,
|
|
40
|
+
],
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UseInfiniteQueryOptions,
|
|
3
|
+
InfiniteData,
|
|
4
|
+
} from '@tanstack/react-query'
|
|
5
|
+
import { useMemo } from 'react'
|
|
6
|
+
import { useIsMutating } from '@tanstack/react-query'
|
|
7
|
+
import { useLatestRun } from '@/hooks/runs/useLatestRun'
|
|
8
|
+
import { useLatestMessage } from '@/hooks/messages/useLatestMessage'
|
|
9
|
+
import { isRunEditingMessage } from '@/lib/runs/isRunEditingMessage'
|
|
10
|
+
import { MessagesPage, RunsPage } from '@/types'
|
|
11
|
+
|
|
12
|
+
type Args = {
|
|
13
|
+
messagesQueryOptions: UseInfiniteQueryOptions<InfiniteData<MessagesPage>>
|
|
14
|
+
runsQueryOptions: UseInfiniteQueryOptions<InfiniteData<RunsPage>>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const statuses = [
|
|
18
|
+
'queued',
|
|
19
|
+
// 'completed',
|
|
20
|
+
'in_progress',
|
|
21
|
+
'cancelling',
|
|
22
|
+
'requires_action',
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
const isRunActive = ({
|
|
26
|
+
latestRunProps,
|
|
27
|
+
latestMessageProps,
|
|
28
|
+
isMutating,
|
|
29
|
+
}: {
|
|
30
|
+
latestRunProps: ReturnType<typeof useLatestRun>,
|
|
31
|
+
latestMessageProps: ReturnType<typeof useLatestMessage>,
|
|
32
|
+
isMutating: number,
|
|
33
|
+
}) => {
|
|
34
|
+
// @ts-ignore-next-line
|
|
35
|
+
if (latestMessageProps.latestMessage?.metadata?.isBlocking) return false
|
|
36
|
+
if (isMutating > 0) return true
|
|
37
|
+
if (!latestRunProps.latestRun) return false
|
|
38
|
+
if (statuses.includes(latestRunProps.latestRun.status)) return true
|
|
39
|
+
|
|
40
|
+
return isRunEditingMessage({ message: latestMessageProps.latestMessage })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const useIsRunActive = ({
|
|
44
|
+
messagesQueryOptions,
|
|
45
|
+
runsQueryOptions,
|
|
46
|
+
}: Args) => {
|
|
47
|
+
const latestRunProps = useLatestRun({
|
|
48
|
+
runsQueryOptions,
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const latestMessageProps = useLatestMessage({
|
|
52
|
+
messagesQueryOptions,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const isMutating = useIsMutating()
|
|
56
|
+
|
|
57
|
+
return useMemo(() => ({
|
|
58
|
+
...latestRunProps,
|
|
59
|
+
isRunActive: isRunActive({
|
|
60
|
+
latestRunProps,
|
|
61
|
+
latestMessageProps,
|
|
62
|
+
isMutating,
|
|
63
|
+
}),
|
|
64
|
+
}), [latestRunProps, latestMessageProps, isMutating])
|
|
65
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UseInfiniteQueryOptions,
|
|
3
|
+
InfiniteData,
|
|
4
|
+
} from '@tanstack/react-query'
|
|
5
|
+
import { useMemo } from 'react'
|
|
6
|
+
import { useRuns } from '@/hooks/runs/useRuns'
|
|
7
|
+
import { RunsPage } from '@/types'
|
|
8
|
+
|
|
9
|
+
type Args = {
|
|
10
|
+
runsQueryOptions: UseInfiniteQueryOptions<InfiniteData<RunsPage>>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const useLatestRun = (args: Args) => {
|
|
14
|
+
const props = useRuns(args)
|
|
15
|
+
|
|
16
|
+
return useMemo(() => ({
|
|
17
|
+
...props,
|
|
18
|
+
latestRun: props.runs[0],
|
|
19
|
+
}), [props])
|
|
20
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UseInfiniteQueryOptions,
|
|
3
|
+
UseMutationOptions,
|
|
4
|
+
InfiniteData,
|
|
5
|
+
} from '@tanstack/react-query'
|
|
6
|
+
import { useEffect } from 'react'
|
|
7
|
+
import { useLatestMessage } from '@/hooks/messages/useLatestMessage'
|
|
8
|
+
import { useLatestRun } from '@/hooks/runs/useLatestRun'
|
|
9
|
+
import { useCreateRun } from '@/hooks/runs/useCreateRun'
|
|
10
|
+
import { isOptimistic } from '@/lib/optimistic/isOptimistic'
|
|
11
|
+
import { MessagesPage, RunsPage, Run } from '@/types'
|
|
12
|
+
|
|
13
|
+
type Args = {
|
|
14
|
+
messagesQueryOptions: UseInfiniteQueryOptions<InfiniteData<MessagesPage>>
|
|
15
|
+
runsQueryOptions: UseInfiniteQueryOptions<InfiniteData<RunsPage>>
|
|
16
|
+
createRunMutationOptions: UseMutationOptions<{ run: Run }>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const useManageRuns = ({
|
|
20
|
+
messagesQueryOptions,
|
|
21
|
+
runsQueryOptions,
|
|
22
|
+
createRunMutationOptions,
|
|
23
|
+
}: Args) => {
|
|
24
|
+
const latestRunProps = useLatestRun({
|
|
25
|
+
runsQueryOptions,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const latestMessageProps = useLatestMessage({
|
|
29
|
+
messagesQueryOptions,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const createRunProps = useCreateRun({
|
|
33
|
+
createRunMutationOptions,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (createRunProps.isPending) return
|
|
38
|
+
if (latestRunProps.isFetching) return
|
|
39
|
+
if (latestMessageProps.isFetching) return
|
|
40
|
+
|
|
41
|
+
if (!latestMessageProps.latestMessage) return
|
|
42
|
+
if (latestMessageProps.latestMessage.role !== 'user') return
|
|
43
|
+
if (isOptimistic({ id: latestMessageProps.latestMessage.id })) return
|
|
44
|
+
|
|
45
|
+
if (!latestRunProps.latestRun || (latestMessageProps.latestMessage.created_at > latestRunProps.latestRun.created_at)) {
|
|
46
|
+
createRunProps.createRun()
|
|
47
|
+
}
|
|
48
|
+
}, [
|
|
49
|
+
createRunProps,
|
|
50
|
+
latestRunProps,
|
|
51
|
+
latestMessageProps,
|
|
52
|
+
])
|
|
53
|
+
|
|
54
|
+
return null
|
|
55
|
+
}
|