Backend (evolution-service):
- Add analytics module with scheduled statistics aggregation
- Implement daily_statistics aggregation (OVERALL, CHANNEL, CATEGORY)
- Add monthly financial report generation and management
- Create audit log service for operation tracking
- Schedule cron jobs for automatic data aggregation
Frontend (admin-client):
- Replace dashboard mock data with real API calls
- Add analytics page with trend charts and dimension breakdown
- Add financial reports page with confirm/lock workflow
- Add audit logs page with filtering and detail view
- Update navigation with analytics submenu
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TransactionService for atomic database operations with optimistic lock retry
- Implement pessimistic locking in payment callback handling to prevent race conditions
- Add idempotency check via transactionId unique index to prevent duplicate processing
- Add version columns to PaymentORM and OrderORM for optimistic locking
- Add composite indexes for performance (order_status, transaction_id)
- Optimize connection pool settings for both payment and conversation services
- Update init-db.sql with version columns and new indexes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add configure_system_nginx_ssl() function to generate nginx HTTPS config
- HTTP 80 redirects to HTTPS, HTTPS 443 proxies to Docker nginx 8080
- Include TLS 1.2/1.3, secure ciphers, HSTS headers
- Update renew_ssl_cert() to reload both system and Docker nginx
- Update auto-renew cron to reload system nginx
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add file-service to SERVICE_PORTS (port 3006)
- Add file-service to SERVICE_DIRS and DOCKER_SERVICES mappings
- Include file-service in build, start, stop, restart commands
- Update rebuild service name mapping
- Include file-service in db migrate command
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed nuke command to only delete iConsulting project resources:
- Only project containers (via docker-compose down)
- Only project images (iconsulting-*, *-service)
- Only project volumes (postgres_data, redis_data, etc.)
- Only project networks (iconsulting-network)
Does NOT affect other projects on the same Docker host.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add nuclear option to completely remove:
- All Docker containers
- All Docker images
- All Docker volumes (database data)
- All Docker networks
- All build cache
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
Add missing V2 fields to init-db.sql to match conversation.entity.ts:
- consulting_stage
- consulting_state
- collected_info
- recommended_programs
- conversion_path
- device_info
Also add indexes for the new fields.
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>
- rebuild now uses cache by default
- only ignores cache when --no-cache is explicitly passed
Usage:
./deploy.sh rebuild conversation # uses cache
./deploy.sh rebuild conversation --no-cache # ignores cache
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add do_rebuild function to rebuild Docker images without cache.
Supports rebuilding individual services or all services at once.
Usage:
./deploy.sh rebuild conversation # rebuild single service
./deploy.sh rebuild all # rebuild all services
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove image deletion and rebuild steps
- Only delete database volumes and restart services
- TypeORM synchronize:true handles schema creation
- Much faster: no recompilation needed
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>
- Add SQL to create consulting_stage, consulting_state, collected_info,
recommended_programs, conversion_path, device_info columns
- Runs after migration step in full-reset to ensure V2 features work
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add do_full_reset function that deletes all data and rebuilds system
- Preserves SSL certificates (stored in /etc/letsencrypt/)
- Requires explicit YES confirmation before proceeding
- Includes: stop services, clean Docker, rebuild, migrate, restart
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>
- Remove foreign key constraint from conversations.user_id
- Remove foreign key constraint from user_memories.user_id
- Add FACT and INTENT to user_memories.memory_type enum
- Both tables now support anonymous users (UUID without registration)
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>