@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,28 @@
|
|
|
1
|
+
import { forwardRef } from 'react'
|
|
2
|
+
import TextareaAutosize from 'react-textarea-autosize'
|
|
3
|
+
|
|
4
|
+
const UPSCALE_RATIO = 16 / 14
|
|
5
|
+
|
|
6
|
+
type Props = React.ComponentProps<typeof TextareaAutosize>
|
|
7
|
+
|
|
8
|
+
export const TextareaBase = forwardRef(function TextareaBase(props: Props, ref) {
|
|
9
|
+
return (
|
|
10
|
+
<TextareaAutosize
|
|
11
|
+
// @ts-ignore-next-line
|
|
12
|
+
ref={ref}
|
|
13
|
+
className="textarea-base"
|
|
14
|
+
style={{
|
|
15
|
+
resize: 'none',
|
|
16
|
+
fontSize: `${14 * UPSCALE_RATIO}px`,
|
|
17
|
+
lineHeight: `${24 * UPSCALE_RATIO}px`,
|
|
18
|
+
transform: `scale(${1 / UPSCALE_RATIO})`,
|
|
19
|
+
margin: `0 ${(-100 * UPSCALE_RATIO + 100) / 2}%`,
|
|
20
|
+
width: `${100 * UPSCALE_RATIO}%`,
|
|
21
|
+
maxWidth: `${100 * UPSCALE_RATIO}%`,
|
|
22
|
+
flexGrow: 1,
|
|
23
|
+
display: 'flex',
|
|
24
|
+
}}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
)
|
|
28
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { forwardRef } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Flex,
|
|
4
|
+
Button,
|
|
5
|
+
PopoverTrigger
|
|
6
|
+
} from '@radix-ui/themes'
|
|
7
|
+
|
|
8
|
+
type Args = {
|
|
9
|
+
children: React.ReactNode
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ToolCallBase = forwardRef(function ToolCallBase({
|
|
13
|
+
children,
|
|
14
|
+
}: Args, ref) {
|
|
15
|
+
return (
|
|
16
|
+
<Flex
|
|
17
|
+
py="1"
|
|
18
|
+
ml="-2"
|
|
19
|
+
>
|
|
20
|
+
<PopoverTrigger>
|
|
21
|
+
<Button
|
|
22
|
+
size="1"
|
|
23
|
+
color="gold"
|
|
24
|
+
variant="outline"
|
|
25
|
+
style={{
|
|
26
|
+
boxShadow: 'none',
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
</Button>
|
|
31
|
+
</PopoverTrigger>
|
|
32
|
+
</Flex>
|
|
33
|
+
)
|
|
34
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createContext } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Avatar,
|
|
4
|
+
} from '@radix-ui/themes'
|
|
5
|
+
import {
|
|
6
|
+
LightningBoltIcon,
|
|
7
|
+
} from '@radix-ui/react-icons'
|
|
8
|
+
|
|
9
|
+
export const AssistantAvatarContext = createContext(
|
|
10
|
+
<Avatar
|
|
11
|
+
fallback={<LightningBoltIcon />}
|
|
12
|
+
size="1"
|
|
13
|
+
/>
|
|
14
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Box,
|
|
3
|
+
Text,
|
|
4
|
+
} from '@radix-ui/themes'
|
|
5
|
+
|
|
6
|
+
export const Paragraph = ({ children }: JSX.IntrinsicElements['p']) => (
|
|
7
|
+
<Box
|
|
8
|
+
pb="3"
|
|
9
|
+
>
|
|
10
|
+
<Text
|
|
11
|
+
size="3"
|
|
12
|
+
className="whitespace-pre-line break-words"
|
|
13
|
+
>
|
|
14
|
+
{children}
|
|
15
|
+
</Text>
|
|
16
|
+
</Box>
|
|
17
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Components } from 'react-markdown'
|
|
2
|
+
import { Paragraph } from './Paragraph'
|
|
3
|
+
import { Link } from './Link'
|
|
4
|
+
import { UnorderedList } from './UnorderedList'
|
|
5
|
+
import { OrderedList } from './OrderedList'
|
|
6
|
+
import { ListItem } from './ListItem'
|
|
7
|
+
import { Strong } from './Strong'
|
|
8
|
+
|
|
9
|
+
export const components: Components = {
|
|
10
|
+
p: Paragraph,
|
|
11
|
+
a: Link,
|
|
12
|
+
strong: Strong,
|
|
13
|
+
ul: UnorderedList,
|
|
14
|
+
ol: OrderedList,
|
|
15
|
+
li: ListItem,
|
|
16
|
+
}
|
|
@@ -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
|
+
handleActionMutationOptions: UseMutationOptions<{ run: Run }>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const useHandleAction = ({
|
|
14
|
+
handleActionMutationOptions,
|
|
15
|
+
}: Args) => {
|
|
16
|
+
const queryClient = useQueryClient()
|
|
17
|
+
|
|
18
|
+
// @ts-ignore-next-line
|
|
19
|
+
const mutationProps = useMutation({
|
|
20
|
+
...mutationOptions({
|
|
21
|
+
queryClient,
|
|
22
|
+
}),
|
|
23
|
+
...handleActionMutationOptions,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
...mutationProps,
|
|
28
|
+
handleAction: mutationProps.mutate,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query'
|
|
2
|
+
// import { mutationFn } from './mutationFn'
|
|
3
|
+
import { onSettled } from './onSettled'
|
|
4
|
+
|
|
5
|
+
type Args = {
|
|
6
|
+
queryClient: QueryClient
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const mutationOptions = ({
|
|
10
|
+
queryClient,
|
|
11
|
+
}: Args) => ({
|
|
12
|
+
// mutationFn,
|
|
13
|
+
onSettled: onSettled({ queryClient }),
|
|
14
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Run, Functions } from '@/types'
|
|
2
|
+
import pMap from 'p-map'
|
|
3
|
+
import { client } from '@/lib/ai'
|
|
4
|
+
import { toolOutput } from './toolOutput'
|
|
5
|
+
|
|
6
|
+
type Args = {
|
|
7
|
+
latestRun: Run
|
|
8
|
+
functions?: Functions
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type Response = {
|
|
12
|
+
run: Run
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const mutationFn = async ({
|
|
16
|
+
latestRun,
|
|
17
|
+
functions = {},
|
|
18
|
+
}: Args): Promise<Response> => {
|
|
19
|
+
if (!latestRun.required_action) {
|
|
20
|
+
throw new Error('No required_action for run ${latestRun.id} with status ${latestRun.status}')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
console.log('handleActions', { latestRun })
|
|
24
|
+
|
|
25
|
+
const toolCalls = latestRun.required_action.submit_tool_outputs.tool_calls
|
|
26
|
+
|
|
27
|
+
const run = await client.beta.threads.runs.submitToolOutputs(
|
|
28
|
+
latestRun.thread_id,
|
|
29
|
+
latestRun.id,
|
|
30
|
+
{
|
|
31
|
+
tool_outputs: await pMap(toolCalls, (toolCall) => toolOutput({ toolCall, latestRun, functions })),
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
// @ts-ignore-next-line
|
|
37
|
+
run,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import OpenAI from 'openai'
|
|
2
|
+
import { Functions } from '@/types'
|
|
3
|
+
|
|
4
|
+
type Args = {
|
|
5
|
+
toolCall: OpenAI.Beta.Threads.Runs.RequiredActionFunctionToolCall
|
|
6
|
+
latestRun: OpenAI.Beta.Threads.Runs.Run
|
|
7
|
+
functions: Functions
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const toolOutput = async ({
|
|
11
|
+
toolCall,
|
|
12
|
+
latestRun,
|
|
13
|
+
functions,
|
|
14
|
+
}: Args) => {
|
|
15
|
+
const fn = functions[toolCall.function.name]
|
|
16
|
+
|
|
17
|
+
if (!fn) {
|
|
18
|
+
console.log({ toolCall })
|
|
19
|
+
throw new Error(`No function for ${toolCall.function.name}`)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
tool_call_id: toolCall.id,
|
|
24
|
+
output: await fn({
|
|
25
|
+
toolCall,
|
|
26
|
+
latestRun,
|
|
27
|
+
}),
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -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('useHandleAction onSettled: response is undefined')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
queryClient.invalidateQueries({
|
|
17
|
+
queryKey: messagesQueryKey(),
|
|
18
|
+
})
|
|
19
|
+
queryClient.invalidateQueries({
|
|
20
|
+
queryKey: runsQueryKey(),
|
|
21
|
+
})
|
|
22
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UseInfiniteQueryOptions,
|
|
3
|
+
InfiniteData,
|
|
4
|
+
UseMutationOptions,
|
|
5
|
+
} from '@tanstack/react-query'
|
|
6
|
+
import { useEffect } from 'react'
|
|
7
|
+
import { useLatestRun } from '@/hooks/runs/useLatestRun'
|
|
8
|
+
import { useHandleAction } from '@/hooks/actions/useHandleAction'
|
|
9
|
+
import { RunsPage, Run } from '@/types'
|
|
10
|
+
|
|
11
|
+
type Args = {
|
|
12
|
+
runsQueryOptions: UseInfiniteQueryOptions<InfiniteData<RunsPage>>
|
|
13
|
+
handleActionMutationOptions: UseMutationOptions<{ run: Run }>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const useManageActions = ({
|
|
17
|
+
runsQueryOptions,
|
|
18
|
+
handleActionMutationOptions,
|
|
19
|
+
}: Args) => {
|
|
20
|
+
const latestRunProps = useLatestRun({
|
|
21
|
+
runsQueryOptions,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const handleActionProps = useHandleAction({
|
|
25
|
+
handleActionMutationOptions,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (handleActionProps.isPending) return
|
|
30
|
+
if (latestRunProps.isFetching) return
|
|
31
|
+
if (!latestRunProps.latestRun) return
|
|
32
|
+
if (latestRunProps.latestRun.status !== 'requires_action') return
|
|
33
|
+
|
|
34
|
+
console.log('requires action', {
|
|
35
|
+
latestRunProps,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// @ts-ignore-next-line
|
|
39
|
+
handleActionProps.handleAction({ latestRun: latestRunProps.latestRun })
|
|
40
|
+
}, [handleActionProps, latestRunProps])
|
|
41
|
+
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
import { messageGroups as getMessageGroups } from './lib/messageGroups'
|
|
3
|
+
import { Message } from '@/types'
|
|
4
|
+
|
|
5
|
+
type Args = {
|
|
6
|
+
messages: Message[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const useMessageGroups = ({
|
|
10
|
+
messages,
|
|
11
|
+
}: Args) => (
|
|
12
|
+
useMemo(
|
|
13
|
+
() => ({
|
|
14
|
+
messageGroups: getMessageGroups({ messages }),
|
|
15
|
+
}),
|
|
16
|
+
[messages]
|
|
17
|
+
)
|
|
18
|
+
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { last } from 'radash'
|
|
3
|
+
import { Message, MessageGroup } from '@/types'
|
|
4
|
+
import { order } from '@/lib/messages/order'
|
|
5
|
+
import { newGroup } from './newGroup'
|
|
6
|
+
|
|
7
|
+
type Args = {
|
|
8
|
+
messages: Message[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const messageGroups = ({
|
|
12
|
+
messages,
|
|
13
|
+
}: Args) =>
|
|
14
|
+
_.reduce(
|
|
15
|
+
order({ messages }),
|
|
16
|
+
(groups: MessageGroup[], message: Message) => {
|
|
17
|
+
const group = last(groups)
|
|
18
|
+
|
|
19
|
+
if (!group) return newGroup({ groups, message })
|
|
20
|
+
|
|
21
|
+
if (group.role !== message.role) {
|
|
22
|
+
return newGroup({
|
|
23
|
+
groups,
|
|
24
|
+
message,
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return [
|
|
29
|
+
..._.dropRight(groups),
|
|
30
|
+
{
|
|
31
|
+
...group,
|
|
32
|
+
messages: [...group.messages, message],
|
|
33
|
+
},
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
[]
|
|
37
|
+
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Message, MessageGroup } from '@/types'
|
|
2
|
+
import { newGroupItem } from './newGroupItem'
|
|
3
|
+
|
|
4
|
+
type Args = {
|
|
5
|
+
groups: MessageGroup[]
|
|
6
|
+
message: Message
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const newGroup = ({ groups, message }: Args) => [
|
|
10
|
+
...groups,
|
|
11
|
+
newGroupItem({
|
|
12
|
+
message,
|
|
13
|
+
}),
|
|
14
|
+
]
|
|
@@ -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 { Message } from '@/types'
|
|
8
|
+
|
|
9
|
+
type Args = {
|
|
10
|
+
createMessageMutationOptions: UseMutationOptions<{ message: Message }>
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const useCreateMessage = ({
|
|
14
|
+
createMessageMutationOptions,
|
|
15
|
+
}: Args) => {
|
|
16
|
+
const queryClient = useQueryClient()
|
|
17
|
+
|
|
18
|
+
// @ts-ignore-next-line
|
|
19
|
+
const mutationProps = useMutation({
|
|
20
|
+
...mutationOptions({
|
|
21
|
+
queryClient,
|
|
22
|
+
}),
|
|
23
|
+
...createMessageMutationOptions,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
...mutationProps,
|
|
28
|
+
createMessage: mutationProps.mutateAsync,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query'
|
|
2
|
+
// import { mutationFn } from './mutationFn'
|
|
3
|
+
import { onMutate } from './onMutate'
|
|
4
|
+
import { onError } from './onError'
|
|
5
|
+
import { onSettled } from './onSettled'
|
|
6
|
+
|
|
7
|
+
type Args = {
|
|
8
|
+
queryClient: QueryClient
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const mutationOptions = ({
|
|
12
|
+
queryClient,
|
|
13
|
+
}: Args) => ({
|
|
14
|
+
// mutationFn,
|
|
15
|
+
onMutate: onMutate({
|
|
16
|
+
queryClient,
|
|
17
|
+
}),
|
|
18
|
+
onError: onError({
|
|
19
|
+
queryClient,
|
|
20
|
+
}),
|
|
21
|
+
onSettled: onSettled({
|
|
22
|
+
queryClient,
|
|
23
|
+
}),
|
|
24
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { client } from '@/lib/ai'
|
|
2
|
+
import { Message } from '@/types'
|
|
3
|
+
import { extendMessage } from '@/lib/messages/extendMessage'
|
|
4
|
+
|
|
5
|
+
export type Args = {
|
|
6
|
+
content: string
|
|
7
|
+
threadId: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type Response = {
|
|
11
|
+
message: Message
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const mutationFn = async ({ content, threadId }: Args): Promise<Response> => {
|
|
15
|
+
const message = await client.beta.threads.messages.create(threadId, {
|
|
16
|
+
content: content,
|
|
17
|
+
role: 'user',
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
message: await extendMessage({
|
|
22
|
+
message,
|
|
23
|
+
}),
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { queryKey as messagesQueryKey } from '@/hooks/messages/useMessages/lib/queryOptions/queryKey'
|
|
2
|
+
import { Args as NewMessageArgs } from './mutationFn'
|
|
3
|
+
|
|
4
|
+
type Args = {
|
|
5
|
+
queryClient: any
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
type Context = {
|
|
9
|
+
prevMessages: any
|
|
10
|
+
} | undefined
|
|
11
|
+
|
|
12
|
+
export const onError = ({
|
|
13
|
+
queryClient,
|
|
14
|
+
}: Args) => async (
|
|
15
|
+
_error: any,
|
|
16
|
+
newMessage: NewMessageArgs,
|
|
17
|
+
context: Context
|
|
18
|
+
) => {
|
|
19
|
+
if (!context) {
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
queryClient.setQueryData(
|
|
24
|
+
messagesQueryKey(),
|
|
25
|
+
context.prevMessages,
|
|
26
|
+
)
|
|
27
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import OpenAI from 'openai'
|
|
2
|
+
import { optimisticId } from '@/lib/optimistic/optimisticId'
|
|
3
|
+
import { Args as NewMessageArgs } from '../mutationFn'
|
|
4
|
+
|
|
5
|
+
type Args = {
|
|
6
|
+
newMessage: NewMessageArgs
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const data = ({
|
|
10
|
+
newMessage,
|
|
11
|
+
}: Args) => (prevData: any) => {
|
|
12
|
+
const message = {
|
|
13
|
+
id: optimisticId(),
|
|
14
|
+
role: 'user' as OpenAI.Beta.Threads.Messages.ThreadMessage['role'],
|
|
15
|
+
created_at: +new Date(),
|
|
16
|
+
object: 'thread.message' as OpenAI.Beta.Threads.Messages.ThreadMessage['object'],
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: {
|
|
21
|
+
annotations: [],
|
|
22
|
+
value: newMessage.content,
|
|
23
|
+
},
|
|
24
|
+
} as OpenAI.Beta.Threads.Messages.MessageContentText,
|
|
25
|
+
],
|
|
26
|
+
run_id: null,
|
|
27
|
+
assistant_id: null,
|
|
28
|
+
thread_id: null,
|
|
29
|
+
file_ids: [],
|
|
30
|
+
metadata: {},
|
|
31
|
+
runSteps: [],
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!prevData) {
|
|
35
|
+
return {
|
|
36
|
+
pageParams: [],
|
|
37
|
+
pages: [
|
|
38
|
+
{
|
|
39
|
+
data: [message],
|
|
40
|
+
hasNextPage: false,
|
|
41
|
+
lastId: message.id,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const [latestPage, ...pagesRest] = prevData.pages
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
...prevData,
|
|
51
|
+
pages: [
|
|
52
|
+
{
|
|
53
|
+
...latestPage,
|
|
54
|
+
data: [
|
|
55
|
+
message,
|
|
56
|
+
...latestPage.data,
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
...pagesRest,
|
|
60
|
+
],
|
|
61
|
+
}
|
|
62
|
+
}
|