fix(conversation): track token usage and message count in conversation entity
Problem: - Token usage was recorded to token_usage table but not to conversation entity - Message count was not being incremented - Dashboard showed 0 tokens for all conversations Solution: - Add inputTokens/outputTokens fields to StreamChunk interface - Return token usage in 'end' chunk from ClaudeAgentServiceV2 - Capture token usage in conversation.service.ts sendMessage - Call conversation.addTokens() and incrementMessageCount() after each exchange - Consolidate conversation updates into single repo.update() call Files changed: - claude-agent-v2.service.ts: Add token fields to StreamChunk, return in 'end' - conversation.service.ts: Track tokens and message counts properly Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
931055b51f
commit
ae99b78579
|
|
@ -158,6 +158,8 @@ export class ConversationService {
|
|||
let fullResponse = '';
|
||||
const toolCalls: Array<{ name: string; input: unknown; result: unknown }> = [];
|
||||
let updatedState: ConversationContext['consultingState'] | undefined;
|
||||
let inputTokens = 0;
|
||||
let outputTokens = 0;
|
||||
|
||||
// Stream response from Claude (with attachments for multimodal support)
|
||||
for await (const chunk of this.claudeAgentService.sendMessage(
|
||||
|
|
@ -181,6 +183,10 @@ export class ConversationService {
|
|||
} else if (chunk.type === 'state_update' && chunk.newState) {
|
||||
// V2: Capture updated consulting state
|
||||
updatedState = chunk.newState;
|
||||
} else if (chunk.type === 'end') {
|
||||
// Capture token usage from end chunk
|
||||
inputTokens = chunk.inputTokens || 0;
|
||||
outputTokens = chunk.outputTokens || 0;
|
||||
}
|
||||
|
||||
yield chunk;
|
||||
|
|
@ -191,7 +197,6 @@ export class ConversationService {
|
|||
// Convert state to JSON-compatible format for database storage
|
||||
const stateForDb = JSON.parse(JSON.stringify(updatedState));
|
||||
conversation.updateConsultingState(stateForDb);
|
||||
await this.conversationRepo.update(conversation);
|
||||
}
|
||||
|
||||
// Save assistant response
|
||||
|
|
@ -205,12 +210,20 @@ export class ConversationService {
|
|||
});
|
||||
await this.messageRepo.save(assistantMessage);
|
||||
|
||||
// Update conversation statistics
|
||||
conversation.incrementMessageCount('user');
|
||||
conversation.incrementMessageCount('assistant');
|
||||
conversation.addTokens(inputTokens, outputTokens);
|
||||
|
||||
// Update conversation title if first message
|
||||
if (conversation.messageCount === 0) {
|
||||
if (conversation.messageCount === 2) {
|
||||
// Now 2 after incrementing (user + assistant)
|
||||
const title = await this.generateTitle(params.content);
|
||||
conversation.title = title;
|
||||
await this.conversationRepo.update(conversation);
|
||||
}
|
||||
|
||||
// Save all updates to conversation
|
||||
await this.conversationRepo.update(conversation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ export interface StreamChunk {
|
|||
// V2新增
|
||||
stageName?: string;
|
||||
newState?: ConsultingState;
|
||||
// Token usage (returned with 'end' chunk)
|
||||
inputTokens?: number;
|
||||
outputTokens?: number;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
|
|
@ -342,7 +345,7 @@ export class ClaudeAgentServiceV2 implements OnModuleInit {
|
|||
|
||||
// 7.6 返回更新后的状态
|
||||
yield { type: 'state_update', newState: state };
|
||||
yield { type: 'end' };
|
||||
yield { type: 'end', inputTokens: totalInputTokens, outputTokens: totalOutputTokens };
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -403,7 +406,7 @@ export class ClaudeAgentServiceV2 implements OnModuleInit {
|
|||
}
|
||||
|
||||
console.error('[ClaudeAgentV2] Tool loop exceeded maximum iterations');
|
||||
yield { type: 'end' };
|
||||
yield { type: 'end', inputTokens: totalInputTokens, outputTokens: totalOutputTokens };
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue