Commit Graph

9 Commits

Author SHA1 Message Date
hailin 8d8df53e56 fix(conversations): exclude DELETED conversations from evolution queries and user operations
- findForEvolution() now excludes DELETED conversations (should not learn from deleted data)
- getConversation() rejects DELETED conversations for user-facing operations (sendMessage, getMessages, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 20:55:04 -08:00
hailin d083008001 fix(conversations): implement soft-delete for conversation deletion
The delete conversation endpoint was a no-op — it verified ownership but
never actually modified the record. Users saw conversations disappear
(frontend optimistic removal) but they reappeared on refresh.

Changes:
- conversation.entity.ts: Add DELETED status, softDelete() and isDeleted()
- conversation.service.ts: Call softDelete() + update instead of no-op
- conversation-postgres.repository.ts: Exclude DELETED conversations
  from findByUserId() queries so they don't appear in user's list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 20:49:03 -08:00
hailin 00a0ac3820 feat(agents): add admin-configurable evaluation gate for agent loop quality control
Add a configurable evaluation gate system that allows administrators to
define quality rules per consulting stage. The gate checks are executed
programmatically before the agent loop returns a response to the user.

## Architecture

- **Zero-config safe**: Empty rules table = no checks = current behavior preserved
- **Callback-based decoupling**: agent-loop.ts receives an optional callback,
  stays decoupled from database layer
- **Max 1 retry**: On RETRY/SUPPLEMENT failure, recurse once without gate to
  prevent infinite loops
- **Error-tolerant**: Gate exceptions are caught and logged, never block responses

## New files

- `database/migrations/20260206_add_evaluation_rules.sql` — DB migration
- `domain/entities/evaluation-rule.entity.ts` — Domain entity with 6 rule types
  (FIELD_COMPLETENESS, ASSESSMENT_QUALITY, RESPONSE_LENGTH, MUST_CONTAIN,
  STAGE_MIN_TURNS, CONVERSION_SIGNAL) and 4 failure actions (RETRY, SUPPLEMENT,
  WARN_AND_PASS, ESCALATE)
- `domain/repositories/evaluation-rule.repository.interface.ts` — Repository contract
- `infrastructure/database/postgres/entities/evaluation-rule.orm.ts` — TypeORM ORM entity
- `infrastructure/database/postgres/repositories/evaluation-rule.repository.ts` — Repository impl
- `infrastructure/agents/coordinator/evaluation-gate.service.ts` — Core evaluation engine
  with 5-minute rule cache, per-rule-type evaluators, severity-based action resolution,
  and feedback message builder for model retry
- `application/dtos/evaluation-rule.dto.ts` — Create/Update/Test DTOs
- `adapters/inbound/admin-evaluation-rule.controller.ts` — Admin CRUD API with 8 endpoints:
  list, get, create, update, delete, toggle, test (dry-run), clear cache

## Modified files

- `agent.types.ts` — Add optional `evaluationGate` callback to `AgentLoopParams`
- `stream.types.ts` — Add `EvaluationWarningEvent`, `'evaluating'` phase
- `agent-loop.ts` — Insert gate check at termination point (line 315)
- `coordinator-agent.service.ts` — Inject EvaluationGateService, build callback,
  handle `evaluation_warning` event in StreamChunk mapping
- `agents.module.ts` — Register EvaluationRuleORM, repository, EvaluationGateService
- `conversation.module.ts` — Register AdminEvaluationRuleController

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 18:56:52 -08:00
hailin 691a3523e8 feat(analytics): add Agent usage analytics to admin panel
Add full-stack Agent execution tracking and analytics:

**Database (conversation-service)**
- New `agent_executions` table: tracks each specialist Agent invocation
  with agentType, agentName, durationMs, success, tenantId
- Migration: AddAgentExecutionsTable1738800000000
- ORM entity: AgentExecutionORM with indexes on tenant, conversation,
  agentType, createdAt, and (tenant+date) composite

**Data Capture (conversation-service)**
- conversation.service.ts: captures `agent_start` and `agent_complete`
  StreamChunk events in the sendMessage() async generator loop
- Persists agent execution records to DB after each message completes
- Non-blocking: agent persistence failures are logged but don't break
  the main conversation flow

**Admin API (conversation-service)**
- GET /conversations/admin/statistics/agents?days=30
  Aggregated stats per agent type: totalCalls, successCount, failureCount,
  successRate, avgDurationMs, min/max duration
- GET /conversations/admin/statistics/agents/trend?days=7&agentType=
  Daily trend data: date, agentType, calls, avgDurationMs, successRate
- GET /conversations/admin/:id/agent-executions
  Per-conversation agent execution records ordered by createdAt

**Admin Client - Analytics Page**
- New AgentAnalyticsTab component with:
  - 4 summary cards (total calls, success rate, avg duration, top agent)
  - Agent statistics table (Ant Design Table with sortable columns,
    color-coded Tags, Progress bar for success rate)
  - Stacked bar trend chart (Recharts BarChart, color per agent type)
  - Time range selectors (7/14/30/90 days)
- Added as third tab "Agent 使用分析" in AnalyticsPage dimension tabs

**Admin Client - Conversations Page**
- Added "Agent 使用详情" section to conversation detail drawer
  (between Token Usage and Messages sections)
- Shows per-conversation agent execution table with agent name (color Tag),
  duration, success/failure status, and timestamp
- Empty state: "暂无 Agent 使用记录"

Agent color mapping: policy_expert=#1890ff, assessment_expert=#52c41a,
strategist=#722ed1, objection_handler=#eb2f96, case_analyst=#faad14,
memory_manager=#13c2c2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 08:00:55 -08:00
hailin 16cc0e4c08 feat(agents): implement multi-agent collaboration architecture
借鉴 Claude Code 的架构模式,将单一 Agent 重构为 Coordinator + 6 Specialist 多 Agent 协作系统。

## 新增文件 (36个)

### 架构设计文档 (docs/architecture/, 12个)
- 00-overview.md ~ 11-prompt-templates.md: 完整架构设计,覆盖所有 Agent 的详细设计、
  Prompt 模板、协作流程、工具并发系统、动态上下文注入

### 多 Agent 系统 (infrastructure/agents/, 23个)
- coordinator/coordinator-agent.service.ts: 主协调器,替代 ClaudeAgentServiceV2
- coordinator/agent-loop.ts: 核心递归 async generator 循环(参考 Claude Code aM())
- coordinator/context-injector.service.ts: 动态上下文注入(8种上下文类型按优先级注入)
- specialists/base-specialist.service.ts: Agent 基类(封装 Claude API 调用 + prompt 缓存)
- specialists/policy-expert.service.ts: 政策专家 (Sonnet 4, temp=0)
- specialists/assessment-expert.service.ts: 评估专家 (Sonnet 4, temp=0)
- specialists/strategist.service.ts: 策略顾问 (Sonnet 4, temp=0.3)
- specialists/objection-handler.service.ts: 异议处理 (Sonnet 4, temp=0.2)
- specialists/case-analyst.service.ts: 案例分析 (Haiku, temp=0)
- specialists/memory-manager.service.ts: 记忆管理 (Haiku, temp=0)
- prompts/coordinator-system-prompt.ts: 协调器 Prompt(1095行,13章)
- prompts/{policy,assessment,strategist,objection,case,memory}-*-prompt.ts: 各专家 Prompt
- tools/coordinator-tools.ts: 16个工具定义(6 Agent 调用 + 10 直接工具)
- tools/tool-execution-queue.ts: 并发执行队列(isConcurrencySafe 控制并行/串行)
- types/agent.types.ts: Agent 配置、输入/输出类型定义
- types/stream.types.ts: 流式事件类型(含 agent_start/complete/coordinator_thinking)
- types/context.types.ts: 上下文注入类型
- agents.module.ts: NestJS 模块注册

### 前端 Agent 状态展示 (1个)
- AgentStatusIndicator.tsx: 多 Agent 工作状态组件(含动画)

## 修改文件 (15个)

### 后端集成
- conversation.service.ts: 切换到 CoordinatorAgentService
- conversation.gateway.ts: 新增 agent_start/agent_complete/coordinator_thinking 事件
- claude.module.ts: 引入 AgentsModule
- agents.module.ts: 注册 ImmigrationToolsService(复用旧版生产测试的工具实现)
- knowledge-client.service.ts: 新增 search()/getUserContext() 便捷方法

### 旧代码标记 @deprecated
- claude-agent.service.ts, claude-agent-v2.service.ts
- strategy-engine.service.ts, intent-classifier.ts, response-gate.ts

### 前端适配
- chatStore.ts: 新增 ActiveAgent/CompletedAgent/CoordinatorPhase 状态
- useChat.ts: 新增 WebSocket 事件处理
- ChatWindow.tsx: 集成 AgentStatusIndicator
- globals.css: 新增 agentPulse/agentSlideIn 动画

### 共享类型
- conversation.types.ts: 新增 AGENT_START/AGENT_COMPLETE/COORDINATOR_THINKING 事件

## 核心设计决策

1. **新旧结合**: Coordinator 的 10 个直接工具委托给旧版 ImmigrationToolsService
   (经过生产测试的 Google Search、汇率 API、新闻 API 等),6 个 Agent 调用工具
   走新的 Specialist Agent 系统
2. **递归 async generator**: agent-loop 支持流式输出 + 工具递归 + 成本/轮次控制
3. **并行 Agent 执行**: ToolExecutionQueue 根据 isConcurrencySafe 自动并行/串行
4. **Prompt 缓存**: 所有 Agent 的 system prompt 使用 cache_control: ephemeral
5. **速率限制重试**: 429/529 指数退避,最多 2 次
6. **向后兼容**: LegacyConversationContext 类型别名,StreamChunk 扩展不破坏现有结构

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 04:26:39 -08:00
hailin 7acdf78e0c fix(conversation): improve token tracking accuracy
- Add 'error' chunk type to StreamChunk for partial token capture
- Record partial tokens to token_usage table even on API errors
- Capture error chunk tokens in conversation.service.ts
- Save partial response and tokens before re-throwing errors
- Add token aggregation from token_usage table for accurate stats
- Display detailed token info in admin (cache tokens, cost, API calls)
- Export TokenDetails type for frontend consumption

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 17:23:25 -08:00
hailin ae99b78579 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>
2026-01-25 17:08:23 -08:00
hailin 6a3a2130bf feat(conversation): add device tracking and optimize admin-client build
## Device Tracking (conversation-service)
- Add DeviceInfoDto class for validating device information
- Extract client IP from X-Forwarded-For and X-Real-IP headers
- Capture User-Agent header automatically on conversation creation
- Support optional fingerprint and region from client
- Pass deviceInfo through service layer to entity for persistence

Files changed:
- conversation.controller.ts: Add extractClientIp() method and header capture
- conversation.dto.ts: Add DeviceInfoDto with validation decorators
- conversation.service.ts: Update CreateConversationParams interface

## Build Optimization (admin-client)
- Implement code splitting via Rollup manualChunks
- Separate vendor libraries into cacheable chunks:
  - vendor-react: react, react-dom, react-router-dom (160KB)
  - vendor-antd: antd, @ant-design/icons (1013KB)
  - vendor-charts: recharts (409KB)
  - vendor-data: @tanstack/react-query, axios, zustand (82KB)
- Main bundle reduced from 1732KB to 61KB (96% reduction)
- Set chunkSizeWarningLimit to 1100KB for antd

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 09:45:47 -08:00
hailin afd707d15f refactor(services): implement 4-layer Clean Architecture for all backend services
Refactored all 6 backend services to 4-layer Clean Architecture pattern
following knowledge-service as reference implementation.

## Architecture Pattern (4-Layer)

```
src/
├── domain/              # Pure business entities and interfaces
│   ├── entities/        # Domain entities (no ORM decorators)
│   ├── repositories/    # Repository interfaces + Symbol tokens
│   └── value-objects/   # Enums and value types
├── application/
│   ├── dtos/            # Data transfer objects
│   └── services/        # Application services (use case orchestration)
├── adapters/
│   ├── inbound/         # Controllers, gateways (API endpoints)
│   └── outbound/
│       ├── persistence/ # Repository implementations
│       ├── clients/     # External service clients
│       └── storage/     # File storage adapters
└── infrastructure/
    └── database/postgres/
        └── entities/    # ORM entities with decorators
```

## Services Refactored

### user-service
- adapters/inbound: AuthController, UserController
- adapters/outbound/persistence: UserPostgresRepository, VerificationCodePostgresRepository
- application/services: AuthService, UserService
- application/dtos: AuthDto, UserDto

### payment-service
- adapters/inbound: OrderController, PaymentController
- adapters/outbound/persistence: OrderPostgresRepository, PaymentPostgresRepository
- adapters/outbound/payment-methods: AlipayAdapter, WechatPayAdapter, StripeAdapter
- application/services: OrderService, PaymentService
- application/dtos: OrderDto, PaymentDto

### file-service
- adapters/inbound: FileController
- adapters/outbound/persistence: FilePostgresRepository
- adapters/outbound/storage: MinioStorageAdapter
- application/services: FileService
- application/dtos: UploadFileDto

### conversation-service
- adapters/inbound: ConversationController, InternalController, ConversationGateway
- adapters/outbound/persistence: ConversationPostgresRepository, MessagePostgresRepository, TokenUsagePostgresRepository
- application/services: ConversationService
- application/dtos: ConversationDto

### knowledge-service
- adapters/inbound: KnowledgeController, MemoryController, InternalMemoryController
- adapters/outbound/persistence: KnowledgePostgresRepository, MemoryPostgresRepository
- application/services: KnowledgeService, MemoryService
- application/dtos: KnowledgeDto, MemoryDto

### evolution-service
- domain/entities: AdminEntity
- domain/repositories: IAdminRepository (Symbol-based DI)
- domain/value-objects: AdminRole enum
- adapters/inbound: AdminController, EvolutionController
- adapters/outbound/persistence: AdminPostgresRepository
- adapters/outbound/clients: ConversationClient, KnowledgeClient
- application/services: AdminService, EvolutionService
- application/dtos: AdminDto, EvolutionDto
- infrastructure/database/postgres/entities: AdminORM

## Key Improvements
- Symbol-based dependency injection for repository interfaces
- ORM entities separated from domain entities
- Consistent 4-layer structure across all services
- DTOs for API contracts
- Clear separation: domain logic vs infrastructure concerns

## Configuration
- Updated turbo.json: renamed "pipeline" to "tasks" for Turbo 2.0+

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 22:18:22 -08:00