Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 4x 515x 515x 515x 515x 515x 515x 1x 1x 1x 515x 515x 515x 515x 515x 541x 541x 541x | import { createContext, type ReactNode, useCallback, useContext, useMemo } from 'react'
import { useChatState } from '../hooks/useChatState'
import { useConversationState } from '../hooks/useConversationState'
import { type PendingInput, type PendingPermission, usePermissionState } from '../hooks/usePermissionState'
import type { MessageEntry } from '../lib/types'
import { vscode } from '../lib/vscode'
import { useRouter } from './MessageRouterContext'
interface ChatState {
messages: MessageEntry[]
setMessages: React.Dispatch<React.SetStateAction<MessageEntry[]>>
streamingText: string
streamingThinking: string
isRunning: boolean
setIsRunning: (v: boolean) => void
pendingPermission: PendingPermission | null
setPendingPermission: (v: PendingPermission | null) => void
pendingInput: PendingInput | null
setPendingInput: (v: PendingInput | null) => void
conversations: { id: string; title: string; updatedAt: number }[]
setConversations: React.Dispatch<React.SetStateAction<{ id: string; title: string; updatedAt: number }[]>>
activeConversationId: string | null
conversationSearchResults: { id: string; title: string; updatedAt: number; snippet: string }[] | null
setConversationSearchResults: (v: null) => void
handleAbort: () => void
handlePermissionRespond: (behavior: 'allow' | 'deny' | 'always') => void
handlePermissionInstruct: (instructions: string) => void
handleInputRespond: (answers: Record<string, string>) => void
}
const ChatCtx = createContext<ChatState | null>(null)
export function ChatProvider({ children }: { children: ReactNode }) {
const router = useRouter()
const chat = useChatState(router)
const permissions = usePermissionState(router, chat.setMessages)
const conversations = useConversationState(router)
const handleAbort = useCallback(() => vscode.postMessage({ type: 'abort' }), [])
const handlePermissionRespond = useCallback(
(behavior: 'allow' | 'deny' | 'always') => {
Iif (!permissions.pendingPermission) return
vscode.postMessage({
type: 'user',
subtype: 'permission',
requestId: permissions.pendingPermission.requestId,
behavior,
})
permissions.setPendingPermission(null)
},
[permissions.pendingPermission, permissions.setPendingPermission],
)
const handlePermissionInstruct = useCallback(
(instructions: string) => {
if (!permissions.pendingPermission) return
chat.setMessages((prev) => [...prev, { role: 'denied-with-instructions', instructions }])
vscode.postMessage({
type: 'user',
subtype: 'permission',
requestId: permissions.pendingPermission.requestId,
behavior: 'deny',
feedback: instructions,
})
permissions.setPendingPermission(null)
},
[permissions.pendingPermission, permissions.setPendingPermission, chat.setMessages],
)
const handleInputRespond = useCallback(
(answers: Record<string, string>) => {
if (!permissions.pendingInput) return
vscode.postMessage({
type: 'user',
subtype: 'input',
requestId: permissions.pendingInput.requestId,
answers,
})
permissions.setPendingInput(null)
},
[permissions.pendingInput, permissions.setPendingInput],
)
const value = useMemo(
() => ({
...chat,
...permissions,
...conversations,
handleAbort,
handlePermissionRespond,
handlePermissionInstruct,
handleInputRespond,
}),
[
chat,
permissions,
conversations,
handleAbort,
handlePermissionRespond,
handlePermissionInstruct,
handleInputRespond,
],
)
return <ChatCtx.Provider value={value}>{children}</ChatCtx.Provider>
}
export function useChat(): ChatState {
const ctx = useContext(ChatCtx)
Iif (!ctx) throw new Error('useChat must be used within ChatProvider')
return ctx
}
|