Skip to content

Commit d19add2

Browse files
committed
fix: ?? OpenAI Langfuse ????
1 parent ecb5339 commit d19add2

2 files changed

Lines changed: 27 additions & 25 deletions

File tree

src/services/api/openai/index.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {
55
StreamEvent,
66
SystemAPIErrorMessage,
77
AssistantMessage,
8+
UserMessage,
89
} from '../../../types/message.js'
910
import type { AgentId } from '../../../types/ids.js'
1011
import type { Tools } from '../../../Tool.js'
@@ -56,11 +57,11 @@ import {
5657
* ToolSearchTool to load their full schemas.
5758
*/
5859
function prependDeferredToolListIfNeeded(
59-
messages: Message[],
60+
messages: (AssistantMessage | UserMessage)[],
6061
tools: Tools,
6162
deferredToolNames: Set<string>,
6263
useToolSearch: boolean,
63-
): Message[] {
64+
): (AssistantMessage | UserMessage)[] {
6465
if (!useToolSearch || isDeferredToolsDeltaEnabled()) return messages
6566

6667
const deferredToolList = tools
@@ -80,6 +81,10 @@ function prependDeferredToolListIfNeeded(
8081
]
8182
}
8283

84+
function isOpenAIConvertibleMessage(msg: Message): msg is AssistantMessage | UserMessage {
85+
return msg.type === 'assistant' || msg.type === 'user'
86+
}
87+
8388
/**
8489
* Assemble the final AssistantMessage (and optional max_tokens error) from
8590
* accumulated stream state. Extracted to avoid duplication between the
@@ -212,8 +217,9 @@ export async function* queryModelOpenAI(
212217

213218
// 8. Convert messages and tools to OpenAI format
214219
const enableThinking = isOpenAIThinkingEnabled(openaiModel)
220+
const openAIConvertibleMessages = messagesForAPI.filter(isOpenAIConvertibleMessage)
215221
const messagesWithDeferredToolList = prependDeferredToolListIfNeeded(
216-
messagesForAPI,
222+
openAIConvertibleMessages,
217223
tools,
218224
deferredToolNames,
219225
useToolSearch,
@@ -240,7 +246,7 @@ export async function* queryModelOpenAI(
240246
)
241247
}
242248

243-
// 10. Compute max_tokens required by most OpenAI-compatible endpoints.
249+
// 10. Compute max_tokens ??required by most OpenAI-compatible endpoints.
244250
// Without this the server uses a tiny default, and when
245251
// thinking is enabled the thinking phase consumes the entire budget
246252
// leaving no tokens for the final response.
@@ -432,4 +438,4 @@ export async function* queryModelOpenAI(
432438
error: (error instanceof Error ? error : new Error(String(error))) as unknown as SDKAssistantMessageError,
433439
})
434440
}
435-
}
441+
}

src/services/langfuse/convert.ts

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
* input: { role, content }[] where content is string or structured parts
66
* output: { role: 'assistant', content: string | part[] }
77
*
8-
* Key conversions from Anthropic OpenAI format:
9-
* - tool_use blocks tool_calls[] at message level
10-
* - tool_result blocks separate { role: 'tool' } messages
8+
* Key conversions from Anthropic ??OpenAI format:
9+
* - tool_use blocks ??tool_calls[] at message level
10+
* - tool_result blocks ??separate { role: 'tool' } messages
1111
*/
1212

13-
import type { Message, AssistantMessage, UserMessage } from 'src/types/message.js'
13+
import type { AssistantMessage } from 'src/types/message.js'
1414

1515
type LangfuseContentPart =
1616
| { type: 'text'; text: string }
@@ -42,11 +42,6 @@ function isLangfuseRole(value: unknown): value is LangfuseChatMessage['role'] {
4242
}
4343
}
4444

45-
type LangfuseInputMessage =
46-
| UserMessage
47-
| AssistantMessage
48-
| LangfuseChatMessage
49-
5045
function isRecord(value: unknown): value is Record<string, unknown> {
5146
return value !== null && typeof value === 'object' && !Array.isArray(value)
5247
}
@@ -175,15 +170,15 @@ function collapseContent(parts: LangfuseContentPart[]): string | LangfuseContent
175170
return parts
176171
}
177172

178-
function toRole(msg: Message): 'user' | 'assistant' | 'system' {
173+
function toRoleFromWrappedMessage(msg: Record<string, unknown>): 'user' | 'assistant' | 'system' {
179174
if (msg.type === 'assistant') return 'assistant'
180175
if (msg.type === 'system') return 'system'
181176
return 'user'
182177
}
183178

184-
/** Convert internal or OpenAI-style messages Langfuse input format */
179+
/** Convert internal or OpenAI-style messages ??Langfuse input format */
185180
export function convertMessagesToLangfuse(
186-
messages: LangfuseInputMessage[],
181+
messages: readonly unknown[],
187182
systemPrompt?: readonly string[],
188183
): LangfuseChatMessage[] {
189184
const result: LangfuseChatMessage[] = []
@@ -193,11 +188,12 @@ export function convertMessagesToLangfuse(
193188
}
194189
}
195190
for (const msg of messages) {
196-
const isWrappedMessage = 'message' in msg
197-
const inner = isWrappedMessage ? msg.message : msg
198-
if (!inner) continue
191+
if (!isRecord(msg)) continue
192+
const wrappedMessage = msg.message
193+
const isWrappedMessage = isRecord(wrappedMessage)
194+
const inner = isWrappedMessage ? wrappedMessage : msg
199195
const role =
200-
isLangfuseRole(inner.role) ? inner.role : isWrappedMessage ? toRole(msg) : 'user'
196+
isLangfuseRole(inner.role) ? inner.role : isWrappedMessage ? toRoleFromWrappedMessage(msg) : 'user'
201197
const rawContent = inner.content
202198
if (typeof rawContent === 'string' || !Array.isArray(rawContent)) {
203199
const toolCalls = getToolCalls(inner.tool_calls)
@@ -213,7 +209,7 @@ export function convertMessagesToLangfuse(
213209
}
214210

215211
if (role === 'assistant') {
216-
// Extract tool_use tool_calls at message level
212+
// Extract tool_use ??tool_calls at message level
217213
const { tool_calls, rest } = extractToolCalls(rawContent)
218214
const allToolCalls = mergeToolCalls(
219215
tool_calls,
@@ -230,7 +226,7 @@ export function convertMessagesToLangfuse(
230226
...(allToolCalls.length > 0 && { tool_calls: allToolCalls }),
231227
})
232228
} else {
233-
// User messages: extract tool_result separate tool messages
229+
// User messages: extract tool_result ??separate tool messages
234230
const { toolMessages, rest } = extractToolResults(rawContent)
235231
const parts = rest
236232
.filter((b): b is Record<string, unknown> => b != null && typeof b === 'object')
@@ -271,7 +267,7 @@ export function convertToolsToLangfuse(tools: unknown[]): unknown[] {
271267
})
272268
}
273269

274-
/** Convert AssistantMessage[] (newMessages) Langfuse output format (last assistant turn) */
270+
/** Convert AssistantMessage[] (newMessages) ??Langfuse output format (last assistant turn) */
275271
export function convertOutputToLangfuse(
276272
messages: AssistantMessage[],
277273
): LangfuseChatMessage | LangfuseChatMessage[] | null {
@@ -296,4 +292,4 @@ export function convertOutputToLangfuse(
296292

297293
if (messages.length === 1) return convert(messages[0]!)
298294
return messages.map(convert)
299-
}
295+
}

0 commit comments

Comments
 (0)