feat(stage-*,plugin-*): retriable tool call

This commit is contained in:
Neko Ayaka
2026-06-26 14:52:20 +08:00
parent 445b597041
commit 6372491e3b
37 changed files with 2148 additions and 521 deletions
@@ -14,6 +14,8 @@ import ChatActionButtons from '../Widgets/ChatActionButtons.vue'
import ChatArea from '../Widgets/ChatArea.vue'
import ChatContainer from '../Widgets/ChatContainer.vue'
import { useChatToolCallRerun } from '../../composables/useChatToolCallRerun'
const { isReady } = useDeferredMount()
const { sending } = storeToRefs(useChatOrchestratorStore())
const { messages } = storeToRefs(useChatSessionStore())
@@ -22,6 +24,7 @@ const { streamingMessage } = storeToRefs(useChatStreamStore())
const isLoading = ref(true)
const historyMessages = computed(() => messages.value as unknown as ChatHistoryItem[])
const { trackChatMessageDeleted } = useAnalytics()
const { rerunToolCall } = useChatToolCallRerun()
function handleDeleteMessage(index: number) {
const message = messages.value[index]
@@ -53,6 +56,7 @@ function handleDeleteMessage(index: number) {
h-full
variant="desktop"
@delete-message="handleDeleteMessage($event.index)"
@tool-call-rerun="rerunToolCall"
@vue:mounted="isLoading = false"
/>
</div>
@@ -28,6 +28,7 @@ import IndicatorMicVolume from '../Widgets/IndicatorMicVolume.vue'
import ActionAbout from './InteractiveArea/Actions/About.vue'
import { useTranscriptions } from '../../composables/use-transcriptions'
import { useChatToolCallRerun } from '../../composables/useChatToolCallRerun'
import { useStopSpeakingButton } from '../../composables/useStopSpeakingButton'
import { BackgroundDialogPicker } from '../Backgrounds'
@@ -41,6 +42,7 @@ const { streamingMessage } = storeToRefs(chatStream)
const { sending } = storeToRefs(chatOrchestrator)
const historyMessages = computed(() => messages.value as unknown as ChatHistoryItem[])
const { trackChatMessageDeleted, trackChatMessagesCleared } = useAnalytics()
const { rerunToolCall } = useChatToolCallRerun()
function handleDeleteMessage(index: number) {
const message = messages.value[index]
@@ -184,6 +186,7 @@ onMounted(() => {
'relative z-20',
]"
@delete-message="handleDeleteMessage($event.index)"
@tool-call-rerun="rerunToolCall"
/>
</Transition>
</KeepAlive>
@@ -0,0 +1,53 @@
import type { ChatHistoryItem } from '@proj-airi/stage-ui/types/chat'
import { errorMessageFrom } from '@moeru/std'
import { useChatSessionStore } from '@proj-airi/stage-ui/stores/chat/session-store'
import { resolveLlmTools } from '@proj-airi/stage-ui/stores/llm-tool-resolver'
import { executeToolCallRerun } from '@proj-airi/stage-ui/stores/tool-call-rerun'
export interface ChatToolCallRerunEvent {
message: ChatHistoryItem
index: number
key: string | number
toolCallId: string
toolName: string
args: string
}
export function useChatToolCallRerun() {
const chatSession = useChatSessionStore()
async function rerunToolCall(payload: ChatToolCallRerunEvent) {
const sessionId = chatSession.activeSessionId
const currentMessages = chatSession.getSessionMessages(sessionId)
try {
const nextMessages = await executeToolCallRerun({
messages: currentMessages,
payload: {
sessionId,
messageId: payload.message.id,
index: payload.index,
toolCallId: payload.toolCallId,
toolName: payload.toolName,
args: payload.args,
},
resolveTools: () => resolveLlmTools(),
})
chatSession.setSessionMessages(sessionId, nextMessages)
}
catch (error) {
chatSession.setSessionMessages(sessionId, [
...currentMessages,
{
role: 'error',
content: errorMessageFrom(error) ?? 'Failed to rerun tool call.',
},
])
}
}
return {
rerunToolCall,
}
}