({
messages,
systemPrompt,
thinkingConfig,
tools,
signal,
options,
}: {
messages: Message[]
systemPrompt: SystemPrompt
thinkingConfig: ThinkingConfig
tools: Tools
signal: AbortSignal
options: Options
})
| 730 | } |
| 731 | |
| 732 | export async function queryModelWithoutStreaming({ |
| 733 | messages, |
| 734 | systemPrompt, |
| 735 | thinkingConfig, |
| 736 | tools, |
| 737 | signal, |
| 738 | options, |
| 739 | }: { |
| 740 | messages: Message[] |
| 741 | systemPrompt: SystemPrompt |
| 742 | thinkingConfig: ThinkingConfig |
| 743 | tools: Tools |
| 744 | signal: AbortSignal |
| 745 | options: Options |
| 746 | }): Promise<AssistantMessage> { |
| 747 | // Store the assistant message but continue consuming the generator to ensure |
| 748 | // logAPISuccessAndDuration gets called (which happens after all yields) |
| 749 | let assistantMessage: AssistantMessage | undefined |
| 750 | for await (const message of withStreamingVCR(messages, async function* () { |
| 751 | yield* queryModel( |
| 752 | messages, |
| 753 | systemPrompt, |
| 754 | thinkingConfig, |
| 755 | tools, |
| 756 | signal, |
| 757 | options, |
| 758 | ) |
| 759 | })) { |
| 760 | if (message.type === 'assistant') { |
| 761 | assistantMessage = message as AssistantMessage |
| 762 | } |
| 763 | } |
| 764 | if (!assistantMessage) { |
| 765 | // If the signal was aborted, throw APIUserAbortError instead of a generic error |
| 766 | // This allows callers to handle abort scenarios gracefully |
| 767 | if (signal.aborted) { |
| 768 | throw new APIUserAbortError() |
| 769 | } |
| 770 | throw new Error('No assistant message found') |
| 771 | } |
| 772 | return assistantMessage |
| 773 | } |
| 774 | |
| 775 | export async function* queryModelWithStreaming({ |
| 776 | messages, |
no test coverage detected