diff --git a/packages/services/agent-service/src/infrastructure/dingtalk/dingtalk-router.service.ts b/packages/services/agent-service/src/infrastructure/dingtalk/dingtalk-router.service.ts index 50b7c06..7ce8a93 100644 --- a/packages/services/agent-service/src/infrastructure/dingtalk/dingtalk-router.service.ts +++ b/packages/services/agent-service/src/infrastructure/dingtalk/dingtalk-router.service.ts @@ -256,11 +256,19 @@ export class DingTalkRouterService implements OnModuleInit, OnModuleDestroy { const instance = await this.instanceRepo.findById(entry.instanceId); if (!instance) throw new Error('智能体实例不存在'); - // Store openId — this matches senderId in incoming bot messages (used for routing) - instance.dingTalkUserId = openId; + + // Store userId (staffId) as the binding identifier if resolved — this matches senderStaffId + // in incoming DingTalk bot messages, enabling correct routing. + // Fall back to openId if userId could not be resolved (routing may still work if + // DingTalk delivers openId in senderId for this app type). + const bindingId = userId ?? openId; + instance.dingTalkUserId = bindingId; await this.instanceRepo.save(instance); - this.logger.log(`OAuth binding saved: instance ${entry.instanceId} → dingTalkUserId(openId)=${openId}`); + this.logger.log( + `OAuth binding saved: instance ${entry.instanceId} → dingTalkUserId=${bindingId} ` + + `(${userId ? 'staffId/userId' : 'openId fallback — staffId not resolved'})`, + ); // Send proactive greeting using userId (staffId). Skip if not resolved. this.sendGreeting(userId, openId, instance.name).catch((e: Error) => diff --git a/packages/services/agent-service/src/interfaces/rest/controllers/agent.controller.ts b/packages/services/agent-service/src/interfaces/rest/controllers/agent.controller.ts index f0cf284..5810584 100644 --- a/packages/services/agent-service/src/interfaces/rest/controllers/agent.controller.ts +++ b/packages/services/agent-service/src/interfaces/rest/controllers/agent.controller.ts @@ -146,6 +146,10 @@ export class AgentController { tenantId, userId, userEmail, + // Pass session ID so Claude uses the wget oauth-trigger endpoint (works for ALL engine types). + // The oauth-trigger endpoint emits an oauth_prompt WS event to this session's stream, + // which Flutter's chat page handles the same way as voice sessions. + sessionId: session.id, }); // Fire-and-forget: run the task stream