diff --git a/src/main/services/agents/services/SessionMessageService.ts b/src/main/services/agents/services/SessionMessageService.ts index dd0d0ebbbe..ddfb59f4a8 100644 --- a/src/main/services/agents/services/SessionMessageService.ts +++ b/src/main/services/agents/services/SessionMessageService.ts @@ -83,28 +83,6 @@ class TextStreamAccumulator { break } } - - toModelMessage(role: ModelMessage['role'] = 'assistant'): ModelMessage { - const content = this.totalText || this.textBuffer || '' - - const toolInvocations = Array.from(this.toolCalls.entries()).map(([toolCallId, info]) => ({ - toolCallId, - toolName: info.toolName, - args: info.input, - result: this.toolResults.get(toolCallId) - })) - - const message: Record = { - role, - content - } - - if (toolInvocations.length > 0) { - message.toolInvocations = toolInvocations - } - - return message as ModelMessage - } } export class SessionMessageService extends BaseService { @@ -175,7 +153,6 @@ export class SessionMessageService extends BaseService { abortController: AbortController ): Promise { const agentSessionId = await this.getLastAgentSessionId(session.id) - let newAgentSessionId = '' logger.debug('Session Message stream message data:', { message: req, session_id: agentSessionId }) if (session.agent_type !== 'claude-code') { @@ -222,10 +199,6 @@ export class SessionMessageService extends BaseService { return } - if (chunk.type === 'start' && chunk.messageId) { - newAgentSessionId = chunk.messageId - } - accumulator.add(chunk) controller.enqueue(chunk) break diff --git a/src/main/services/agents/services/claudecode/transform.ts b/src/main/services/agents/services/claudecode/transform.ts index 34ce05172a..8cc33fcdcc 100644 --- a/src/main/services/agents/services/claudecode/transform.ts +++ b/src/main/services/agents/services/claudecode/transform.ts @@ -70,23 +70,18 @@ function generateTextChunks(id: string, text: string, message: SDKMessage): Agen return [ { type: 'text-start', - id, - providerMetadata + id }, { type: 'text-delta', id, - text, - providerMetadata + text }, { type: 'text-end', id, providerMetadata: { - ...providerMetadata, - text: { - value: text - } + ...providerMetadata } } ] @@ -119,17 +114,22 @@ function handleUserOrAssistantMessage(message: Extract): AgentStreamPart[] { const chunks: AgentStreamPart[] = [] const event = message.event - const blockKey = `${message.uuid ?? message.session_id ?? 'session'}:${event.index}` + const blockKey = `${message.uuid ?? message.session_id ?? 'session'}:${event.type}` switch (event.type) { case 'message_start': @@ -255,15 +255,13 @@ function handleStreamEvent(message: Extract): chunks.push({ type: 'start' }) + chunks.push({ + type: 'raw', + rawValue: { + type: 'init', + session_id: message.session_id, + slash_commands: message.slash_commands, + tools: message.tools, + raw: message + } + }) } } - return [] + return chunks } // Handle result messages (completion with usage stats) @@ -295,14 +303,9 @@ function handleResultMessage(message: Extract): let usage: LanguageModelV2Usage | undefined if ('usage' in message) { usage = { - inputTokens: - (message.usage.cache_creation_input_tokens ?? 0) + - (message.usage.cache_read_input_tokens ?? 0) + - (message.usage.input_tokens ?? 0), + inputTokens: message.usage.input_tokens ?? 0, outputTokens: message.usage.output_tokens ?? 0, totalTokens: - (message.usage.cache_creation_input_tokens ?? 0) + - (message.usage.cache_read_input_tokens ?? 0) + (message.usage.input_tokens ?? 0) + (message.usage.output_tokens ?? 0) } @@ -330,25 +333,3 @@ function handleResultMessage(message: Extract): } return chunks } - -// Convenience function to transform a stream of SDKMessages -export function* transformSDKMessageStream(sdkMessages: SDKMessage[]): Generator { - for (const sdkMessage of sdkMessages) { - const chunks = transformSDKMessageToStreamParts(sdkMessage) - for (const chunk of chunks) { - yield chunk - } - } -} - -// Async version for async iterables -export async function* transformSDKMessageStreamAsync( - sdkMessages: AsyncIterable -): AsyncGenerator { - for await (const sdkMessage of sdkMessages) { - const chunks = transformSDKMessageToStreamParts(sdkMessage) - for (const chunk of chunks) { - yield chunk - } - } -} diff --git a/src/renderer/src/aiCore/chunk/AiSdkToChunkAdapter.ts b/src/renderer/src/aiCore/chunk/AiSdkToChunkAdapter.ts index d8a3bcca72..e2aa5063a5 100644 --- a/src/renderer/src/aiCore/chunk/AiSdkToChunkAdapter.ts +++ b/src/renderer/src/aiCore/chunk/AiSdkToChunkAdapter.ts @@ -111,13 +111,10 @@ export class AiSdkToChunkAdapter { chunk: TextStreamPart, final: { text: string; reasoningContent: string; webSearchResults: AISDKWebSearchResult[]; reasoningId: string } ) { - const sessionId = - (chunk.providerMetadata as any)?.anthropic?.session_id ?? - (chunk.providerMetadata as any)?.anthropic?.sessionId ?? - (chunk.providerMetadata as any)?.raw?.session_id - - if (typeof sessionId === 'string' && sessionId) { - this.onSessionUpdate?.(sessionId) + // @ts-ignore + if (chunk.type === 'raw' && chunk.rawValue.type === 'init' && chunk.rawValue.session_id) { + // @ts-ignore + this.onSessionUpdate?.(chunk.rawValue.session_id) } logger.silly(`AI SDK chunk type: ${chunk.type}`, chunk) diff --git a/src/renderer/src/types/newMessage.ts b/src/renderer/src/types/newMessage.ts index 74e2b8266a..08654457e4 100644 --- a/src/renderer/src/types/newMessage.ts +++ b/src/renderer/src/types/newMessage.ts @@ -1,3 +1,4 @@ +import type {ProviderMetadata} from "ai"; import type { CompletionUsage } from 'openai/resources' import type { @@ -203,6 +204,10 @@ export type Message = { // 跟踪Id traceId?: string + + // raw data + // TODO: add this providerMetadata to MessageBlock to save raw provider data for each block + providerMetadata?: ProviderMetadata } export interface Response {