diff --git a/packages/services/conversation-service/package.json b/packages/services/conversation-service/package.json index 77f5daf..a63a294 100644 --- a/packages/services/conversation-service/package.json +++ b/packages/services/conversation-service/package.json @@ -29,6 +29,7 @@ "@nestjs/websockets": "^10.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", + "dotenv": "^16.3.0", "ioredis": "^5.3.0", "kafkajs": "^2.2.4", "pg": "^8.11.0", @@ -45,7 +46,6 @@ "@types/node": "^20.10.0", "@types/socket.io": "^3.0.2", "@types/uuid": "^9.0.0", - "dotenv": "^16.3.0", "jest": "^29.7.0", "ts-jest": "^29.1.0", "ts-node": "^10.9.0", diff --git a/packages/services/conversation-service/src/conversation/conversation.service.ts b/packages/services/conversation-service/src/conversation/conversation.service.ts index 021c6e4..170c639 100644 --- a/packages/services/conversation-service/src/conversation/conversation.service.ts +++ b/packages/services/conversation-service/src/conversation/conversation.service.ts @@ -11,10 +11,10 @@ import { MessageType, } from '../domain/entities/message.entity'; import { - ClaudeAgentService, + ClaudeAgentServiceV2, ConversationContext, StreamChunk, -} from '../infrastructure/claude/claude-agent.service'; +} from '../infrastructure/claude/claude-agent-v2.service'; export interface CreateConversationDto { userId: string; @@ -45,7 +45,7 @@ export class ConversationService { private conversationRepo: Repository, @InjectRepository(MessageEntity) private messageRepo: Repository, - private claudeAgentService: ClaudeAgentService, + private claudeAgentService: ClaudeAgentServiceV2, ) {} /** @@ -134,7 +134,7 @@ export class ConversationService { take: 20, // Last 20 messages for context }); - // Build context with support for multimodal messages + // Build context with support for multimodal messages and consulting state (V2) const context: ConversationContext = { userId: dto.userId, conversationId: dto.conversationId, @@ -149,11 +149,15 @@ export class ConversationService { } return msg; }), + // V2: Pass consulting state from conversation (cast through unknown for JSON/Date compatibility) + consultingState: conversation.consultingState as unknown as ConversationContext['consultingState'], + deviceInfo: conversation.deviceInfo, }; // Collect full response for saving let fullResponse = ''; const toolCalls: Array<{ name: string; input: unknown; result: unknown }> = []; + let updatedState: ConversationContext['consultingState'] | undefined; // Stream response from Claude (with attachments for multimodal support) for await (const chunk of this.claudeAgentService.sendMessage( @@ -174,11 +178,27 @@ export class ConversationService { if (lastToolCall) { lastToolCall.result = chunk.toolResult; } + } else if (chunk.type === 'state_update' && chunk.newState) { + // V2: Capture updated consulting state + updatedState = chunk.newState; } yield chunk; } + // V2: Save updated consulting state to conversation + if (updatedState) { + // Convert state to JSON-compatible format for database storage + const stateForDb = JSON.parse(JSON.stringify(updatedState)); + await this.conversationRepo.update(conversation.id, { + consultingState: stateForDb, + consultingStage: updatedState.currentStageId, + collectedInfo: stateForDb.collectedInfo, + recommendedPrograms: updatedState.assessmentResult?.recommendedPrograms, + conversionPath: updatedState.conversionPath, + }); + } + // Save assistant response const assistantMessage = this.messageRepo.create({ conversationId: dto.conversationId,