Follow proper microservices architecture:
- knowledge-service owns system_experiences table
- evolution-service uses KnowledgeClient API to save experiences
- Deleted SystemExperienceORM from evolution-service
- Added internal API endpoints in knowledge-service
- Disabled synchronize in all services for safety
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Breaking change: evolution-service no longer directly accesses
conversations and messages tables.
Changes:
- Add internal API endpoints to conversation-service for service-to-service calls
- Create ConversationClient in evolution-service to call conversation-service API
- Remove ConversationORM and MessageORM from evolution-service
- Update evolution.service to use ConversationClient
This follows microservices best practices:
- Each service owns its data
- Services communicate via API, not shared tables
TODO: Apply same pattern to system_experiences (knowledge-service)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use init-db.sql for schema management instead of TypeORM auto-sync.
synchronize:true is dangerous in production and causes conflicts
when multiple services share tables.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add @Index decorators for conversation_id, created_at, role
- Set created_at to timestamptz type to match database
- Set columns nullable to match database schema
This prevents synchronize:true from trying to modify columns
that have dependent indexes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add input_tokens and output_tokens columns that evolution-service
defines to prevent synchronize:true from trying to drop them.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add columns that evolution-service defines to prevent synchronize:true
from trying to drop them:
- userMessageCount, assistantMessageCount
- totalInputTokens, totalOutputTokens
- rating, feedback, hasConverted
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove migration-based approach which kept failing
- Enable synchronize:true to auto-sync Entity with database
- Schema will always match Entity definition on startup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add migrations path to TypeORM config
- Set migrationsRun: true to run pending migrations on startup
- This ensures V2 columns are created automatically when app starts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add data-source.prod.ts for compiled JS migrations
- Add migration:run:prod script to package.json
- Update deploy.sh to try prod migration first, fallback to dev
- Keep SQL fallback in full-reset as safety net with proper indexes
This ensures migrations work in Docker where ts-node may not be available.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Switch ConversationService to use ClaudeAgentServiceV2
- Pass consultingState and deviceInfo from conversation to context
- Handle state_update chunks and save updated state to database
- Move dotenv to dependencies for migration runtime
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 8-stage consulting workflow (greeting → handoff)
- Create StrategyEngineService for state management and transitions
- Add ClaudeAgentServiceV2 with integrated strategy guidance
- Support old user recognition via get_user_context tool
- Add device info (IP, fingerprint) for new user icebreaking
- Extend ConversationEntity with consulting state fields
- Add database migration for new JSONB columns
Stages: greeting, needs_discovery, info_collection, assessment,
recommendation, objection_handling, conversion, handoff
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix Usage type cast by using unknown intermediate type
- Add PricingTier interface and proper Record type for PRICING
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TokenUsageEntity to store per-request token consumption
- Add TokenUsageService with cost calculation and statistics APIs
- Record input/output/cache tokens per API call
- Calculate estimated cost based on Claude pricing
- Provide user/conversation/global stats aggregation
- Support daily stats and top users ranking
- Integrate token tracking in ClaudeAgentService
- Track latency, tool calls, response length
- Accumulate tokens across tool loop iterations
- Add token_usages table to init-db.sql with proper indexes
This enables:
- Per-user token consumption tracking
- Cost analysis and optimization
- Future billing/quota features
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Reduce tokensPerChar from 2 to 1.8 for more accurate Chinese token estimation
- Use min() instead of max() to enforce upper limits on token counts
- CHAT: max 200 tokens (was min 256)
- SIMPLE_QUERY: max 600 tokens (was min 512)
- CLARIFICATION: max 300 tokens (was min 256)
- CONFIRMATION: max 400 tokens (was min 384)
- DEEP_CONSULTATION: 800-1600 tokens (was 1024-4096)
- ACTION_NEEDED: 500-1000 tokens (was 768-2048)
This should result in more concise AI responses that better match
the intent classifier's suggested length limits.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
TypeORM doesn't natively support pgvector type. Add custom transformer
to convert between JavaScript arrays and pgvector string format [1,2,3].
Fixes: invalid input syntax for type vector errors
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add OPENAI_BASE_URL configuration to .env.example
- Update EmbeddingService to disable TLS verification for IP-based proxy URLs
- Mirror the same proxy handling pattern used in Anthropic API
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change MessageEntity.role from enum to VARCHAR(20)
- Change MessageEntity.type from enum to VARCHAR(30)
- Change ConversationEntity.status from enum to VARCHAR(20)
- Add nullable: true to userId to match database schema
- Add length constraints to match database schema
- Convert enums to const objects with type exports for type safety
This ensures TypeORM entities match the database schema exactly,
avoiding potential issues with enum type creation in production.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add missing 'type' column to MessageORM entity
- Add 'TEXT_WITH_ATTACHMENTS' to messages.type CHECK constraint
(matches MessageType enum in conversation-service)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The embedding column was declared as float[] but the database uses
VECTOR(1536) from pgvector. TypeORM doesn't natively support pgvector
types, causing 500 errors when querying the system_experiences table.
Fixed by:
- Changed column type to 'text' with select: false
- This prevents TypeORM from trying to select/map the vector column
- The embedding field is only used for similarity searches via raw SQL
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add the following real-time tools to ImmigrationToolsService:
- get_current_datetime: Get current date/time with timezone support
- web_search: Search internet for latest immigration news/policies (Google CSE)
- get_exchange_rate: Query real-time currency exchange rates (for investment immigration)
- fetch_immigration_news: Fetch latest immigration announcements
All tools include graceful degradation with fallback responses when external APIs are unavailable.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The API interceptor was redirecting to /login on 401 errors, but since
admin-client is deployed under /admin/, it should redirect to /admin/login.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add base: '/admin/' to vite.config.ts for proper asset paths
- Replace vite.svg favicon with inline SVG emoji icon
- Fixes 404 errors when accessing admin panel at /admin/ path
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change flex container from items-end to items-center
- Use top-1/2 -translate-y-1/2 for send button vertical centering
- Adjust paperclip button padding for consistent sizing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Set overflow-hidden by default on textarea
- Only show scrollbar when content exceeds max height (200px)
- Fix scrollbar appearing on empty input
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add clipboard paste handler for images and files (Ctrl+V / Cmd+V)
- Add drag-and-drop zone with visual feedback
- Update placeholder text to inform users about new features
- Improve file upload UX with drop overlay
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix DataTypeNotSupportedError by explicitly specifying PostgreSQL column types
for nullable fields that TypeORM was incorrectly inferring as Object type.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add MinIO object storage to docker-compose infrastructure
- Create file-service microservice for upload management with presigned URLs
- Add files table to database schema
- Update nginx and Kong for MinIO proxy routes
- Implement file upload UI in chat InputArea with drag-and-drop
- Add attachment preview in MessageBubble component
- Update conversation-service to handle multimodal messages
- Add Claude Vision API integration for image analysis
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These services were using DB_HOST, DB_USER etc. but docker-compose
sets POSTGRES_HOST, POSTGRES_USER etc.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Payment service was listening on wrong port (3004) because it used
PAYMENT_SERVICE_PORT which wasn't set in docker-compose.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The health check endpoint should be at /health not /api/v1/health
for Docker health checks to work properly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /health endpoints to all NestJS services (user, payment, knowledge, conversation, evolution)
- Fix nginx healthcheck to use 127.0.0.1 instead of localhost (IPv6 issue)
- Add healthcheck configuration to docker-compose for all backend services
- Use start_period to allow services time to initialize before health checks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Frontend:
- Add sidebarOpen state to chatStore with toggle functionality
- Make sidebar collapsible with smooth animation
- Add mobile-friendly drawer behavior with overlay
- Add toggle button for desktop view
- Implement delete conversation functionality with loading state
Backend:
- Add DELETE /conversations/:id endpoint
- Implement deleteConversation service method
- Delete messages before conversation (foreign key constraint)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix streaming JSON parsing for tool inputs by accumulating partial JSON
and parsing only on content_block_stop
- Implement proper tool loop to continue conversation after tool execution
- Send tool results back to Claude to get final response
- Add safety limit of 10 iterations for tool loops
This fixes the issue where AI responses were truncated after using tools
like search_knowledge.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When ANTHROPIC_BASE_URL points to an IP address (proxy server),
disable TLS certificate verification to allow connection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove https-proxy-agent dependency since ANTHROPIC_BASE_URL already
supports pointing to a proxy server directly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>