mirror of https://github.com/buster-so/buster.git
final tweak
This commit is contained in:
parent
7b9afdbb2f
commit
9bdfe81cd5
|
@ -67,10 +67,24 @@ export function convertCoreMessageToModelMessage(message: unknown): ModelMessage
|
|||
case 'tool':
|
||||
// Tool messages are always arrays of ToolResultPart
|
||||
if (Array.isArray(content)) {
|
||||
// Convert and flatten nested results
|
||||
const convertedContent = [];
|
||||
for (const part of content) {
|
||||
const converted = convertToolResultPart(part);
|
||||
if (converted !== null) {
|
||||
if (Array.isArray(converted)) {
|
||||
// Flatten nested arrays (from wrapper tool results)
|
||||
convertedContent.push(...converted);
|
||||
} else {
|
||||
convertedContent.push(converted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
role: 'tool',
|
||||
// biome-ignore lint/suspicious/noExplicitAny: necessary for v4 to v5 conversion
|
||||
content: content.map(convertToolResultPart) as any,
|
||||
content: convertedContent as any,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -134,7 +148,7 @@ function convertContentPart(part: unknown): unknown {
|
|||
/**
|
||||
* Convert tool result parts from v4 to v5 format
|
||||
*/
|
||||
function convertToolResultPart(part: unknown): unknown {
|
||||
function convertToolResultPart(part: unknown): unknown | unknown[] | null {
|
||||
if (!part || typeof part !== 'object') {
|
||||
return part;
|
||||
}
|
||||
|
@ -145,10 +159,54 @@ function convertToolResultPart(part: unknown): unknown {
|
|||
return part;
|
||||
}
|
||||
|
||||
// Check if this is a wrapper with empty toolCallId/toolName and nested results
|
||||
if (
|
||||
'toolCallId' in p &&
|
||||
(p.toolCallId === '' || !p.toolCallId) &&
|
||||
'toolName' in p &&
|
||||
(p.toolName === '' || !p.toolName) &&
|
||||
'result' in p &&
|
||||
Array.isArray(p.result)
|
||||
) {
|
||||
// This is a wrapper - extract and convert the nested tool results
|
||||
const nestedResults = [];
|
||||
for (const nestedItem of p.result) {
|
||||
if (
|
||||
nestedItem &&
|
||||
typeof nestedItem === 'object' &&
|
||||
'type' in nestedItem &&
|
||||
nestedItem.type === 'tool-result'
|
||||
) {
|
||||
const converted = convertToolResultPart(nestedItem);
|
||||
if (converted !== null) {
|
||||
if (Array.isArray(converted)) {
|
||||
nestedResults.push(...converted);
|
||||
} else {
|
||||
nestedResults.push(converted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the array of nested results to be flattened
|
||||
return nestedResults.length > 0 ? nestedResults : null;
|
||||
}
|
||||
|
||||
// Convert result → output with proper structure
|
||||
if ('result' in p && !('output' in p)) {
|
||||
const { result, experimental_content, isError, ...rest } = p;
|
||||
|
||||
// Ensure toolCallId exists and is valid
|
||||
// If it's missing or invalid, skip this result
|
||||
if (!rest.toolCallId || typeof rest.toolCallId !== 'string' || rest.toolCallId.trim() === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if toolCallId matches the required pattern
|
||||
const validPattern = /^[a-zA-Z0-9_-]+$/;
|
||||
if (!validPattern.test(rest.toolCallId as string)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert result to structured output format
|
||||
let output: { type: string; value: unknown };
|
||||
if (isError) {
|
||||
|
@ -167,12 +225,6 @@ function convertToolResultPart(part: unknown): unknown {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure toolCallId exists and is valid
|
||||
// If it's missing or invalid, preserve the original part
|
||||
if (!rest.toolCallId || typeof rest.toolCallId !== 'string') {
|
||||
return part;
|
||||
}
|
||||
|
||||
return {
|
||||
...rest,
|
||||
output,
|
||||
|
|
|
@ -67,9 +67,23 @@ export function convertCoreToModel(messages: unknown): ModelMessage[] {
|
|||
case 'tool':
|
||||
// Tool messages: convert result to structured output
|
||||
if (Array.isArray(content)) {
|
||||
// Convert and flatten nested results
|
||||
const convertedContent = [];
|
||||
for (const part of content) {
|
||||
const converted = convertToolResultPart(part);
|
||||
if (converted !== null) {
|
||||
if (Array.isArray(converted)) {
|
||||
// Flatten nested arrays (from wrapper tool results)
|
||||
convertedContent.push(...converted);
|
||||
} else {
|
||||
convertedContent.push(converted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...msg,
|
||||
content: content.map(convertToolResultPart),
|
||||
content: convertedContent,
|
||||
} as ModelMessage;
|
||||
}
|
||||
return { role: 'tool', content: [] } as ModelMessage;
|
||||
|
@ -133,7 +147,7 @@ function convertContentPart(part: unknown): unknown {
|
|||
/**
|
||||
* Convert tool result parts from v4 to v5 format
|
||||
*/
|
||||
function convertToolResultPart(part: unknown): unknown {
|
||||
function convertToolResultPart(part: unknown): unknown | unknown[] | null {
|
||||
if (!part || typeof part !== 'object') {
|
||||
return part;
|
||||
}
|
||||
|
@ -144,10 +158,64 @@ function convertToolResultPart(part: unknown): unknown {
|
|||
return part;
|
||||
}
|
||||
|
||||
// Convert result → structured output
|
||||
// Check if this is a wrapper with empty toolCallId/toolName and nested results
|
||||
if (
|
||||
'toolCallId' in p &&
|
||||
(p.toolCallId === '' || !p.toolCallId) &&
|
||||
'toolName' in p &&
|
||||
(p.toolName === '' || !p.toolName) &&
|
||||
'result' in p &&
|
||||
Array.isArray(p.result)
|
||||
) {
|
||||
// This is a wrapper - extract and convert the nested tool results
|
||||
const nestedResults = [];
|
||||
for (const nestedItem of p.result) {
|
||||
if (
|
||||
nestedItem &&
|
||||
typeof nestedItem === 'object' &&
|
||||
'type' in nestedItem &&
|
||||
nestedItem.type === 'tool-result'
|
||||
) {
|
||||
const converted = convertToolResultPart(nestedItem);
|
||||
if (converted !== null) {
|
||||
if (Array.isArray(converted)) {
|
||||
nestedResults.push(...converted);
|
||||
} else {
|
||||
nestedResults.push(converted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the array of nested results to be flattened
|
||||
return nestedResults.length > 0 ? nestedResults : null;
|
||||
}
|
||||
|
||||
// Only convert if we have 'result' field but not 'output' (v4 format)
|
||||
if ('result' in p && !('output' in p)) {
|
||||
const { result, experimental_content, isError, ...rest } = p;
|
||||
|
||||
// Validate toolCallId exists and matches Anthropic's pattern
|
||||
const toolCallId = rest.toolCallId;
|
||||
if (!toolCallId || typeof toolCallId !== 'string' || toolCallId.trim() === '') {
|
||||
console.warn('[chatConversationHistory] Skipping tool-result with invalid toolCallId:', {
|
||||
toolCallId,
|
||||
toolName: rest.toolName,
|
||||
});
|
||||
// Skip this tool result entirely if toolCallId is invalid
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if toolCallId matches the required pattern
|
||||
const validPattern = /^[a-zA-Z0-9_-]+$/;
|
||||
if (!validPattern.test(toolCallId)) {
|
||||
console.warn('[chatConversationHistory] Tool-result has invalid toolCallId format:', {
|
||||
toolCallId,
|
||||
toolName: rest.toolName,
|
||||
});
|
||||
// Skip this tool result if the ID doesn't match the pattern
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert to v5's structured output format
|
||||
let output: { type: string; value: unknown };
|
||||
if (isError) {
|
||||
|
@ -166,18 +234,13 @@ function convertToolResultPart(part: unknown): unknown {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure toolCallId exists and is valid
|
||||
// If it's missing or invalid, preserve the original part
|
||||
if (!rest.toolCallId || typeof rest.toolCallId !== 'string') {
|
||||
return part;
|
||||
}
|
||||
|
||||
return {
|
||||
...rest,
|
||||
output,
|
||||
};
|
||||
}
|
||||
|
||||
// Already in v5 format or doesn't need conversion
|
||||
return part;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue