mirror of https://github.com/buster-so/buster.git
sequential thinking tie off the request.
This commit is contained in:
parent
4c042a34fa
commit
95b67529ad
|
@ -343,4 +343,51 @@ describe('extract-values-search-step integration', () => {
|
|||
expect(Array.isArray(result.values)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not create valuesMessage with empty content when search returns no results', async () => {
|
||||
const messages: ModelMessage[] = [
|
||||
{ role: 'user', content: 'Show me sales for Red Bull' },
|
||||
];
|
||||
|
||||
// Test with a dataSourceId that would trigger search but return empty results
|
||||
const params = {
|
||||
messages,
|
||||
dataSourceId: 'test-datasource-id',
|
||||
};
|
||||
|
||||
const result = await runExtractValuesAndSearchStep(params);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.values).toBeDefined();
|
||||
|
||||
// If valuesMessage exists, it should have non-empty content
|
||||
if (result.valuesMessage) {
|
||||
expect(result.valuesMessage.content).toBeTruthy();
|
||||
expect(typeof result.valuesMessage.content).toBe('string');
|
||||
expect((result.valuesMessage.content as string).length).toBeGreaterThan(0);
|
||||
}
|
||||
});
|
||||
|
||||
it('should not create valuesMessage when extracted values exist but search results are empty', async () => {
|
||||
const messages: ModelMessage[] = [
|
||||
{ role: 'user', content: 'Show me Nike and Adidas products' },
|
||||
];
|
||||
|
||||
const params = {
|
||||
messages,
|
||||
dataSourceId: 'test-datasource-id',
|
||||
};
|
||||
|
||||
const result = await runExtractValuesAndSearchStep(params);
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result.values).toBeDefined();
|
||||
|
||||
// Verify that if we have values but no search results, valuesMessage is undefined
|
||||
// This prevents empty string messages from being created
|
||||
if (result.values.length > 0 && result.valuesMessage) {
|
||||
expect(result.valuesMessage.content).toBeTruthy();
|
||||
expect((result.valuesMessage.content as string).trim()).not.toBe('');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -185,7 +185,7 @@ export async function runExtractValuesAndSearchStep(
|
|||
return {
|
||||
values: extractedValues,
|
||||
valuesMessage:
|
||||
extractedValues.length > 0
|
||||
extractedValues.length > 0 && storedValuesResult.searchResults
|
||||
? {
|
||||
role: 'user',
|
||||
content: storedValuesResult.searchResults,
|
||||
|
|
|
@ -12,14 +12,14 @@ import type { SequentialThinkingState } from '../sequential-thinking-tool';
|
|||
*/
|
||||
export function createSequentialThinkingReasoningMessage(
|
||||
sequentialThinkingState: SequentialThinkingState,
|
||||
toolCallId?: string,
|
||||
toolCallId: string,
|
||||
status: ChatMessageReasoning_status = 'loading'
|
||||
): ChatMessageReasoningMessage_Text | null {
|
||||
): ChatMessageReasoningMessage_Text {
|
||||
// Use entry_id from state or fallback to provided toolCallId
|
||||
const id = toolCallId;
|
||||
|
||||
if (!id) {
|
||||
return null;
|
||||
throw new Error('Tool call ID is required');
|
||||
}
|
||||
|
||||
// Determine title based on status
|
||||
|
@ -49,11 +49,11 @@ export function createSequentialThinkingReasoningMessage(
|
|||
export function createSequentialThinkingRawLlmMessageEntry(
|
||||
sequentialThinkingState: SequentialThinkingState,
|
||||
toolCallId?: string
|
||||
): ModelMessage | null {
|
||||
): ModelMessage {
|
||||
const id = toolCallId;
|
||||
|
||||
if (!id) {
|
||||
return null;
|
||||
throw new Error('Tool call ID is required');
|
||||
}
|
||||
|
||||
// Build the input object with available state
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { updateMessageEntries } from '@buster/database';
|
||||
import { type UpdateMessageEntriesParams, updateMessageEntries } from '@buster/database';
|
||||
import { wrapTraced } from 'braintrust';
|
||||
import { normalizeEscapedText } from '../../../utils/streaming/escape-normalizer';
|
||||
import { createRawToolResultEntry } from '../../shared/create-raw-llm-tool-result-entry';
|
||||
|
@ -16,24 +16,42 @@ import {
|
|||
|
||||
// Process sequential thinking execution
|
||||
async function processSequentialThinking(
|
||||
toolCallId: string,
|
||||
messageId: string
|
||||
state: SequentialThinkingState,
|
||||
context: SequentialThinkingContext
|
||||
): Promise<SequentialThinkingOutput> {
|
||||
const output: SequentialThinkingOutput = {
|
||||
success: true,
|
||||
};
|
||||
|
||||
const entries: UpdateMessageEntriesParams = {
|
||||
messageId: context.messageId,
|
||||
reasoningMessages: [],
|
||||
rawLlmMessages: [],
|
||||
};
|
||||
|
||||
const reasoningEntry = createSequentialThinkingReasoningMessage(
|
||||
state,
|
||||
context.messageId,
|
||||
'completed'
|
||||
);
|
||||
const rawLlmMessage = createSequentialThinkingRawLlmMessageEntry(state, context.messageId);
|
||||
|
||||
const rawToolResultEntry = createRawToolResultEntry(
|
||||
toolCallId,
|
||||
context.messageId,
|
||||
SEQUENTIAL_THINKING_TOOL_NAME,
|
||||
output
|
||||
);
|
||||
|
||||
if (reasoningEntry) {
|
||||
entries.reasoningMessages = [reasoningEntry];
|
||||
}
|
||||
|
||||
if (rawLlmMessage) {
|
||||
entries.rawLlmMessages = [rawLlmMessage, rawToolResultEntry];
|
||||
}
|
||||
|
||||
try {
|
||||
await updateMessageEntries({
|
||||
messageId,
|
||||
rawLlmMessages: [rawToolResultEntry],
|
||||
});
|
||||
await updateMessageEntries(entries);
|
||||
} catch (error) {
|
||||
console.error('[sequential-thinking] Error updating message entries:', error);
|
||||
}
|
||||
|
@ -54,7 +72,7 @@ export function createSequentialThinkingExecute(
|
|||
throw new Error('Tool call ID is required');
|
||||
}
|
||||
|
||||
return await processSequentialThinking(state.toolCallId, context.messageId);
|
||||
return await processSequentialThinking(state, context);
|
||||
},
|
||||
{ name: SEQUENTIAL_THINKING_TOOL_NAME }
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue