fix: resolve ClaudeModule DI crash + historical QR code display bug

1. ClaudeModule missing ConversationORM in TypeOrmModule.forFeature —
   ImmigrationToolsService now depends on ConversationORMRepository
   (added in query_user_profile), but ClaudeModule only had TokenUsageORM.
   Fix: add ConversationORM to ClaudeModule's TypeORM imports.

2. Historical messages show "支付创建失败" for payment QR codes —
   toolCall.result is stored as JSON string in DB metadata JSONB.
   Live streaming (useChat.ts) parses it correctly, but REST API
   load (chatStore.ts → MessageBubble.tsx) does not.
   Fix: normalize toolCall.result in ToolCallResult component —
   JSON.parse if string, pass through if already object.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-07 12:24:15 -08:00
parent 43d4102e1f
commit 2a8a15fcb6
2 changed files with 12 additions and 2 deletions

View File

@ -7,6 +7,7 @@ import { ImmigrationToolsService } from './tools/immigration-tools.service';
import { TokenUsageService } from './token-usage.service';
import { StrategyEngineService } from './strategy/strategy-engine.service';
import { TokenUsageORM } from '../database/postgres/entities/token-usage.orm';
import { ConversationORM } from '../database/postgres/entities/conversation.orm';
import { KnowledgeModule } from '../knowledge/knowledge.module';
import { AgentsModule } from '../agents/agents.module';
@ -16,7 +17,7 @@ import { AgentsModule } from '../agents/agents.module';
ConfigModule,
KnowledgeModule,
AgentsModule,
TypeOrmModule.forFeature([TokenUsageORM]),
TypeOrmModule.forFeature([TokenUsageORM, ConversationORM]),
],
providers: [
ClaudeAgentService,

View File

@ -188,10 +188,19 @@ function AttachmentPreview({
}
function ToolCallResult({
toolCall,
toolCall: rawToolCall,
}: {
toolCall: { name: string; result: unknown };
}) {
// Normalize: historical messages store toolCall.result as JSON string in DB
// Live streaming already parses it, but REST API load does not
const toolCall = {
...rawToolCall,
result: typeof rawToolCall.result === 'string'
? (() => { try { return JSON.parse(rawToolCall.result as string); } catch { return rawToolCall.result; } })()
: rawToolCall.result,
};
if (toolCall.name === 'generate_payment') {
const result = toolCall.result as {
success?: boolean;