1
0
Fork 0

Merge branch 'main' into fix/js-packages-deps

This commit is contained in:
Paul Jankowski 2026-08-17 14:47:39 -04:00 committed by GitHub
commit cde33cd044
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 94 additions and 6 deletions

View file

@ -0,0 +1,5 @@
---
"@docsearch/react": patch
---
Fix Ask AI conversations breaking after stopping a stream mid-tool-call. Incomplete tool parts (`input-streaming`/`input-available`) are now pruned before resending, so the dangling `tool_use` no longer causes the provider to reject every subsequent question.

View file

@ -104,7 +104,6 @@ const getAgentStudioTransport = ({
algolia: algoliaParams,
},
prepareSendMessagesRequest({ id, messages, body, ...rest }) {
// Filter out `data-*` part types since Agent Studio does not currently support them on the request
const sanitizedMessages = sanitizeMessagesForRequest(messages);
return {

View file

@ -286,6 +286,82 @@ describe('sanitizeMessagesForRequest', () => {
expect(result[1]).not.toBe(sanitizedMessage);
expect(result[1].parts).toEqual([{ type: 'text', text: 'Hi' }]);
});
it('removes an aborted tool call from the assistant message', () => {
const initialQuestion: AIMessage = {
id: 'message-1',
role: 'user',
parts: [{ type: 'text', text: 'Find installation instructions' }],
};
const assistantMessage = message('message-2', [
{ type: 'step-start' },
{
type: 'tool-algolia_search_index',
toolCallId: 'tool-1',
state: 'input-streaming',
input: undefined,
},
]);
const followUpQuestion: AIMessage = {
id: 'message-3',
role: 'user',
parts: [{ type: 'text', text: 'What are the prerequisites?' }],
};
expect(
sanitizeMessagesForRequest([
initialQuestion,
assistantMessage,
followUpQuestion,
])
).toEqual([
initialQuestion,
message('message-2', [{ type: 'step-start' }]),
followUpQuestion,
]);
});
it('keeps streamed text while removing an incomplete tool call', () => {
const result = sanitizeMessagesForRequest([
message('message-1', [
{ type: 'text', text: 'Let me look that up.' },
{
type: 'tool-searchIndex',
toolCallId: 'tool-1',
state: 'input-available',
input: { query: 'installation' },
},
]),
]);
expect(result).toEqual([
message('message-1', [{ type: 'text', text: 'Let me look that up.' }]),
]);
});
it.each([
{
state: 'output-available' as const,
output: { hits: [] },
},
{
state: 'output-error' as const,
errorText: 'Search failed',
},
])('keeps a $state tool call', (toolPart) => {
const messages = [
message('message-1', [
{
type: 'tool-searchIndex',
toolCallId: 'tool-1',
input: { query: 'installation' },
...toolPart,
},
]),
];
expect(sanitizeMessagesForRequest(messages)).toBe(messages);
});
});
describe('getAgentPromptSuggestions', () => {

View file

@ -1,4 +1,4 @@
import type { TextUIPart } from 'ai';
import { isDataUIPart, isToolOrDynamicToolUIPart, type TextUIPart } from 'ai';
import type { StoredAskAiState } from '../types';
import type {
@ -281,10 +281,18 @@ export function sanitizeMessagesForRequest(messages: AIMessage[]): AIMessage[] {
let sanitizedMessages: AIMessage[] | undefined;
messages.forEach((message, index) => {
// Filter out `data-*` part types since Agent Studio does not currently support them on the request
const parts = message.parts.filter(
(part) => !part.type.startsWith('data-')
);
// Remove parts that Agent Studio does not support during a request, including incomplete tool calls
const parts = message.parts.filter((part) => {
if (isDataUIPart(part)) {
return false;
}
if (isToolOrDynamicToolUIPart(part) && part.state.startsWith('input-')) {
return false;
}
return true;
});
if (parts.length === message.parts.length) {
sanitizedMessages?.push(message);