* Move text-block siblings off user messages that contain tool_reference. * * When a tool_result contains tool_reference, the server expands it to a * functions block. Any text siblings appended to that same user message * (auto-memory, skill reminders, etc.) create a second human-turn segment
( messages: (UserMessage | AssistantMessage)[], )
| 1931 | * finds nothing to move. |
| 1932 | */ |
| 1933 | function relocateToolReferenceSiblings( |
| 1934 | messages: (UserMessage | AssistantMessage)[], |
| 1935 | ): (UserMessage | AssistantMessage)[] { |
| 1936 | const result = [...messages] |
| 1937 | |
| 1938 | for (let i = 0; i < result.length; i++) { |
| 1939 | const msg = result[i]! |
| 1940 | if (msg.type !== 'user') continue |
| 1941 | const content = msg.message.content |
| 1942 | if (!Array.isArray(content)) continue |
| 1943 | if (!contentHasToolReference(content)) continue |
| 1944 | |
| 1945 | const textSiblings = content.filter(b => b.type === 'text') |
| 1946 | if (textSiblings.length === 0) continue |
| 1947 | |
| 1948 | // Find the next user message with tool_result but no tool_reference. |
| 1949 | // Skip tool_reference-containing targets — moving there would just |
| 1950 | // recreate the problem one position later. |
| 1951 | let targetIdx = -1 |
| 1952 | for (let j = i + 1; j < result.length; j++) { |
| 1953 | const cand = result[j]! |
| 1954 | if (cand.type !== 'user') continue |
| 1955 | const cc = cand.message.content |
| 1956 | if (!Array.isArray(cc)) continue |
| 1957 | if (!cc.some(b => b.type === 'tool_result')) continue |
| 1958 | if (contentHasToolReference(cc)) continue |
| 1959 | targetIdx = j |
| 1960 | break |
| 1961 | } |
| 1962 | |
| 1963 | if (targetIdx === -1) continue // No valid target; leave in place. |
| 1964 | |
| 1965 | // Strip text from source, append to target. |
| 1966 | result[i] = { |
| 1967 | ...msg, |
| 1968 | message: { |
| 1969 | ...msg.message, |
| 1970 | content: content.filter(b => b.type !== 'text'), |
| 1971 | }, |
| 1972 | } |
| 1973 | const target = result[targetIdx] as UserMessage |
| 1974 | result[targetIdx] = { |
| 1975 | ...target, |
| 1976 | message: { |
| 1977 | ...target.message, |
| 1978 | content: [ |
| 1979 | ...(target.message.content as ContentBlockParam[]), |
| 1980 | ...textSiblings, |
| 1981 | ], |
| 1982 | }, |
| 1983 | } |
| 1984 | } |
| 1985 | |
| 1986 | return result |
| 1987 | } |
| 1988 | |
| 1989 | export function normalizeMessagesForAPI( |
| 1990 | messages: Message[], |
no test coverage detected