Commit Graph

241 Commits

Author SHA1 Message Date
hailin 9a1ecf10ec fix: add restart policy, global error handlers, and fix tenant schema bug
- Add restart: unless-stopped to all 12 Docker services
- Add process.on(unhandledRejection/uncaughtException) to all 7 service main.ts
- Fix handleEventTrigger using tenantId UUID as schema name instead of slug lookup
- Wrap Redis event subscription callbacks in try/catch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 05:30:34 -08:00
hailin 1c291ce6c0 fix: Scheduler 用 slug 构建 tenant schema 名
tenant schema 是 it0_t_{slug}(如 it0_t_default),不是 it0_t_{uuid}。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 05:03:04 -08:00
hailin 09274aa6af fix: Scheduler 查询 public.tenants 而非 it0_shared.tenants
数据库实际 schema 是 public.tenants,不是 it0_shared.tenants。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 05:00:17 -08:00
hailin 840318f449 fix: Scheduler 缺少 tenant 上下文导致 ops-service 卡死
根因: @Cron 定时任务在 HTTP 请求上下文之外运行,
TenantAwareRepository 需要 AsyncLocalStorage 中的 tenant 信息,
每分钟抛 "Tenant context not initialized" 错误。

修复:
- scanCronOrders: 查 it0_shared.tenants 获取所有活跃租户,
  在 TenantContextService.run() 上下文中逐一执行
- handleEventTrigger: 从 Redis event 中提取 tenantId,
  同样包裹在 TenantContextService.run() 中
- 每个 tenant 循环加 try/catch 防止单个租户出错影响其他

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 04:55:52 -08:00
hailin 092a561867 feat: 完成 iAgent App 三大功能 + 修复租户上下文
## 功能一:设置页(完整实现)
- 新增浅色主题(lightTheme),支持深色/浅色/跟随系统三种模式
- app.dart 接入 themeMode 动态切换
- 设置页完整重写:个人信息编辑、修改密码、主题切换、通知开关
- 新增 settings_remote_datasource 对接后端 admin/settings API
- settings_providers 新增 AccountProfileNotifier 管理远程个人资料

## 功能二:语音通话(音频集成)
- 添加 flutter_sound 依赖,创建 PcmPlayer 流式 PCM 播放器
- agent_call_page 替换空壳:真实麦克风采集(record + GTCRN 降噪)
- 真实 PCM 16kHz 流式播放,基于 RMS 能量驱动波形动画
- 修复 WebSocket URL 路径:/ws/voice/ → /api/v1/voice/ws/
- voice_repository_impl 支持后端返回相对路径自动拼接

## 功能三:推送通知(WebSocket MVP)
- 添加 flutter_local_notifications + socket_io_client 依赖
- 创建 AppNotification 实体、NotificationService(Socket.IO 连接 comm-service)
- 通知 providers:列表管理 + 未读计数
- 登录后自动连接通知服务,登出断开
- 底部导航 Alerts 标签添加未读角标(Badge)
- AndroidManifest 添加 POST_NOTIFICATIONS 权限
- main.dart 初始化本地通知插件

## 修复:租户上下文未初始化(500错误)
- 根因:登录后未设置 currentTenantIdProvider,导致 X-Tenant-Id 头缺失
- Flutter 端:login() 成功后从 JWT 设置 tenantId,logout 时清除
- 后端:tenant-context.middleware 增加 JWT tenantId 回退逻辑
- AuthUser 模型新增 tenantId 字段解析

新增 5 个文件,修改 16 个文件,添加 3 个依赖包

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:10:52 -08:00
hailin 4e1b75483d fix: 修复 .gitignore 误忽略 Flutter data/models/ 源码导致构建失败
问题描述:
  在其他机器上构建报错:
  "Error when reading 'lib/features/auth/data/models/auth_response.dart': 系统找不到指定的路径"
  导致 AuthUser、AuthResponse 等类型找不到,编译失败。

根本原因:
  根目录 .gitignore 第75行 "models/" 规则本意是忽略 ML 模型大文件,
  但该规则匹配了所有目录名为 models/ 的路径,包括 Flutter 项目中
  DDD 架构的 data/models/ 源码目录(共 11 个 models/ 目录、10 个 .dart 文件)。
  这些文件在本地存在但从未被 Git 追踪,其他机器 pull 后缺失这些文件。

修复内容:
  1. 修改 .gitignore: 将宽泛的 "models/" 替换为精确的规则
     - packages/services/voice-service/models/ — voice-service 下载的 ML 模型
     - *.pt, *.pth, *.safetensors — PyTorch/HuggingFace 模型二进制文件
     - 不再影响 Flutter 的 data/models/ 源码目录

  2. 提交之前被忽略的 10 个 Flutter model 文件:
     - auth/data/models/auth_response.dart — 登录响应 (accessToken, refreshToken, user)
     - chat/data/models/chat_message_model.dart — 聊天消息模型
     - chat/data/models/session_model.dart — 会话模型
     - chat/data/models/stream_event_model.dart — SSE 流事件模型
     - servers/data/models/server_model.dart — 服务器状态模型
     - approvals/data/models/approval_model.dart — 审批请求模型
     - alerts/data/models/alert_event_model.dart — 告警事件模型
     - agent_call/data/models/voice_session_model.dart — 语音会话模型
     - standing_orders/data/models/standing_order_model.dart — 常设指令模型
     - tasks/data/models/task_model.dart — 任务模型

  3. 同时提交:
     - it0_app/test/widget_test.dart — Flutter 默认测试
     - packages/services/voice-service/src/models/__init__.py — Python 模块初始化

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:29:03 -08:00
hailin a568558585 feat: replace speech_to_text with GTCRN ML noise reduction + backend STT
Replace traditional on-device speech_to_text with a modern pipeline:
- Record audio via `record` package with hardware noise suppression
- Apply GTCRN neural denoising (sherpa-onnx, ICASSP 2024, 48K params)
- Trim silence, POST to backend /voice/transcribe (faster-whisper)

Changes:
- Add /transcribe endpoint to voice-service for audio file upload
- Add SpeechEnhancer wrapper for sherpa-onnx GTCRN model (523KB)
- Rewrite chat_page.dart voice input: record → denoise → transcribe
- Keep NoiseReducer.trimSilence for silence removal only
- Upgrade record to v6.2.0, add sherpa_onnx, path_provider

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 07:59:15 -08:00
hailin 89955f6db8 fix: remove SQL comment lines before splitting to prevent filtering CREATE TABLE statements
The previous approach split by semicolons then filtered statements starting
with '--', which incorrectly removed entire CREATE TABLE blocks that had
comment headers (e.g., '-- Agent Sessions\nCREATE TABLE...').

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 03:26:37 -08:00
hailin 7ff012cd91 fix: use underscores in tenant slug for valid PostgreSQL schema names
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 03:23:14 -08:00
hailin 5d81667ddd feat: add dual tenant registration (self-service + invitation)
Backend:
- Enhanced register endpoint to accept companyName for self-service
  tenant creation with schema provisioning and admin user setup
- Added TenantInvite entity with token-based invitation system
- Added invite CRUD endpoints to TenantController (create/list/revoke)
- Added public endpoints for invite validation and acceptance

Frontend:
- Created registration page with optional organization name field
- Created invitation acceptance page at /invite/[token]
- Added invite management UI to tenant detail page
- Updated login page with link to registration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 03:10:18 -08:00
hailin 7dbd2c1414 feat: add settings, roles, permissions, and metrics controllers
Implement remaining backend controllers for all web admin menu pages:
- SettingsController: general, notification, theme, account, API keys
- RoleController: CRUD roles with permission assignment
- PermissionController: permission matrix for RBAC management
- MetricsController: server metrics overview and per-server data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 01:03:34 -08:00
hailin 8f89b8121c fix: format tenant API response to match frontend DTO
Map flat quota fields to nested quota object and add userCount field
to match the frontend's expected Tenant interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:41:19 -08:00
hailin 3816d6841d fix: add users endpoint, admin route, and fix agent-config paths
- Add UsersController to auth-service for user CRUD (GET/POST/PUT/DELETE /api/v1/auth/users)
- Add Kong route /api/v1/admin -> auth-service for tenant management
- Remove AuthGuard from TenantController (Kong handles JWT)
- Fix frontend agent-config API paths from /api/v1/agent/config to /api/v1/agent-config

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:35:57 -08:00
hailin 52b85f085e fix: decode JWT in middleware to populate req.user for RolesGuard
Kong validates the JWT but doesn't populate req.user on the backend.
The middleware now decodes the JWT payload to extract user info (id,
email, tenantId, roles) so RolesGuard can check role-based access.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:25:32 -08:00
hailin f393a07092 fix: correct alert-rules API paths and remove audit ACL plugin
- Frontend alert-rules paths changed from /monitoring/alert-rules to
  /monitor/alerts/rules to match backend routes
- Removed Kong ACL plugin on audit-routes (JWT auth is sufficient)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:21:50 -08:00
hailin e98cf26587 fix: add missing columns to tenant schema template (runbook.updated_at, contact.role)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:18:46 -08:00
hailin e0ef15df1e fix: add SnakeNamingStrategy for TypeORM to match snake_case DB columns
TypeORM entities use camelCase properties (tenantId, passwordHash) but
database tables use snake_case columns (tenant_id, password_hash). The
naming strategy automatically converts between the two conventions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:10:08 -08:00
hailin a72cbd3778 fix: use any types in TenantContextMiddleware to avoid express dependency
The @it0/database package doesn't have @types/express, causing build
failures. Use any types for req/res/next parameters instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:00:55 -08:00
hailin 5b6e7ee363 fix: add TenantContextMiddleware to initialize tenant context from X-Tenant-Id header
All services using TenantAwareRepository require AsyncLocalStorage tenant
context to set the correct PostgreSQL search_path. The middleware reads
X-Tenant-Id from request headers and wraps the request with
TenantContextService.run(), using schema naming convention it0_t_{tenantId}.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:58:01 -08:00
hailin 806113554b fix: remove AuthGuard('jwt') from all service controllers
Kong handles JWT validation at the gateway level. Service-level
AuthGuard('jwt') fails because services don't register a Passport
JWT strategy (only auth-service does). Removed from 17 controllers
across ops, inventory, monitor, comm, audit, and agent services.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:42:37 -08:00
hailin c710303b60 fix: per-service JWT in Kong, fix auth-service tenant-aware repos
- Replace global JWT plugin with per-service JWT (skip auth-service)
  to fix auth routes being blocked by global JWT in DB-less mode
- Fix UserRepository and ApiKeyRepository to use standard TypeORM
  instead of TenantAwareRepository (users are global, not per-schema)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:31:32 -08:00
hailin 7dd7de4a22 fix: use COPY --chmod for Kong entrypoint (non-root image)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:24:37 -08:00
hailin 48e47975ca fix: configure Kong JWT auth flow with consumer credentials
- Add kid claim to auth-service JWT for Kong validation
- Add Kong consumer with JWT credential (shared secret via env)
- Add agent-config route to Kong for /api/v1/agent-config
- Kong Dockerfile uses entrypoint script to inject JWT_SECRET at runtime
- Fix frontend login path (/auth/login → /api/v1/auth/login)
- Extract tenantId from JWT on login and store as current_tenant
- Add auth guard in admin layout (redirect to /login if no token)
- Pass JWT_SECRET env var to Kong container in docker-compose

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 23:20:06 -08:00
hailin e5dcfa6113 feat: configure it0.szaiai.com and it0api.szaiai.com domains
- Update Kong CORS origins to allow it0.szaiai.com
- Update WebSocket URL to wss://it0api.szaiai.com
- Fix proxy route to read API_BASE_URL at request time
  (was being inlined at build time by Next.js standalone)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:54:17 -08:00
hailin d8cb2a9c6f fix: use standard TypeORM repos and header-based tenant extraction
- Replace TenantAwareRepository with standard @InjectRepository
  (TenantAwareRepository requires AsyncLocalStorage tenant context
  middleware which agent-service does not have)
- Replace @TenantId() decorator with @Headers('x-tenant-id')
  for direct HTTP header extraction
- Return defaults gracefully when no tenant is selected

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:41:30 -08:00
hailin f897cfe240 fix: remove AuthGuard('jwt') from agent-service controllers
Agent-service does not have a registered Passport JWT strategy —
JWT validation is handled by Kong API gateway. The AuthGuard was
causing 500 "Unknown authentication strategy" errors on all
new controller endpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:36:46 -08:00
hailin 5ee1227800 feat: add backend controllers for agent config, skills, and hooks
Implement missing REST API endpoints that the web-admin frontend
pages were calling but had no backend support:

- GET/POST/PUT /api/v1/agent-config (engine, prompt, turns, budget, tools)
- GET/POST/PUT/DELETE /api/v1/agent/skills (CRUD for agent skills)
- GET/POST/PUT/DELETE /api/v1/agent/hooks (CRUD for hook scripts)

Each endpoint includes entity, repository, service, and controller
layers following the existing DDD + tenant-aware patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:26:25 -08:00
hailin 8b92abcce9 fix: handle undefined from eventQueue.shift() in SDK engine
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:10:43 -08:00
hailin c75ad27771 feat: add Claude Agent SDK engine with multi-tenant support
Add @anthropic-ai/claude-agent-sdk as a third engine (pure additive, no changes
to existing CLI/API engines). Includes full frontend admin page.

Backend (agent-service):
- ClaudeAgentSdkEngine: implements AgentEnginePort using SDK's query() API
- ApprovalGate: L2 tool approval with configurable auto-approve timeout (default 120s)
- TenantAgentConfig entity: per-tenant billing mode, encrypted API key, timeout, tool lists
- AllowedToolsResolverService: RBAC-based tool whitelist (admin/operator/viewer)
- TenantAgentConfigController: REST endpoints for admin config management
- Default subscription billing (operator's Claude login, no API key needed)
- Optional per-tenant API key with AES-256-GCM encryption

Frontend (web-admin):
- SDK Config page at /agent-config/sdk with billing, timeout, tool permissions
- Sidebar navigation entry under Agent Config
- React Query key for tenant SDK config

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 18:38:30 -08:00
hailin a06b489a1e fix: load voice models in background thread to unblock startup
Model downloads (Whisper, Kokoro, Silero VAD) are synchronous blocking
calls that prevent uvicorn from completing startup and responding to
healthchecks. Move all model loading to a daemon thread so the server
starts immediately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:26:06 -08:00
hailin 3702fa3f52 fix: make voice-service startup graceful and fix device config
- Wrap model loading in try/except so server starts even if models fail
- Fix device env var mapping (unified 'device' field instead of 'whisper_device')
- Default Whisper model to 'base' instead of 'large-v3' (3GB) for CPU deployment
- Increase healthcheck start_period to 120s for model download time

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:20:12 -08:00
hailin 39718a9a09 fix: resolve runtime errors for NestJS, Kong, and voice-service
- Dockerfile.service: fix entry point path (dist/services/{name}/src/main)
  due to tsconfig paths widening rootDir during compilation
- Kong config: remove unsupported ws/wss protocols (WebSocket works
  automatically over http/https in Kong 3.7)
- voice-service: fix pipecat import path for v0.0.30 API
  (pipecat.transports.network.websocket_server with lowercase class names)
- voice-service: add openai dependency required by pipecat anthropic service

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 19:00:03 -08:00
hailin 93c4a21f06 fix: upgrade faster-whisper to 1.2.1 to resolve av build failure
faster-whisper 1.0.0 depends on av==11.* which has no prebuilt wheels
and fails to compile. Version 1.2.1 uses av 12+ with prebuilt wheels.
Also removed unnecessary FFmpeg dev libraries from Dockerfile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:40:04 -08:00
hailin 6deaf16365 fix: add pkg-config and FFmpeg dev libs for PyAV build
PyAV (av==11, dep of faster-whisper) requires pkg-config and
FFmpeg development headers to compile from source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 05:20:37 -08:00
hailin c0b4f77de5 fix: remove China mirrors, add build-essential for voice-service
Server is on HK network, no need for China mirrors. Added
build-essential for compiling native Python packages (kokoro, etc).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 05:11:39 -08:00
hailin 9a95cdc4a9 fix: update numpy to 1.26.4 for pipecat-ai compatibility
pipecat-ai==0.0.30 requires numpy~=1.26.4, conflicting with 1.26.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 05:09:01 -08:00
hailin b382e6e469 fix: add China registry mirrors for npm and pip in Dockerfiles
web-admin npm ci was timing out on the server. Added npmmirror.com
for npm and tsinghua mirror for pip to resolve network issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 04:59:09 -08:00
hailin e7570a3710 fix: add missing @it0/common dependency to @it0/testing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 04:48:49 -08:00
hailin ee1ee7b484 fix: remove non-existent scripts/ COPY from voice-service Dockerfile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 04:39:02 -08:00
hailin e875cd49bb fix: resolve Kong image tag and port conflicts for shared server
- Change Kong base image from kong:3.7-alpine (non-existent) to kong:3.7
- Remap all host ports to avoid conflicts with existing iconsulting services:
  - Backend services: 13001-13008 (was 3001-3008)
  - Web admin: 13000 (was 3000)
  - API gateway: 18000/18001 (was 8000/8001)
  - PostgreSQL: 15432 (was 5432)
  - Redis: 16379 (was 6379)
- Add container_name with it0- prefix to all services
- Update deploy.sh health check ports to match new mappings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 04:36:23 -08:00
hailin 00f8801d51 Initial commit: IT0 AI-powered server cluster operations platform
Full-stack monorepo with DDD + Clean Architecture:
- Backend: 7 NestJS microservices + 5 shared libraries (TypeScript)
- Mobile: Flutter app with Riverpod (Dart)
- Web Admin: Next.js dashboard with Zustand + React Query
- Voice: Python voice service (STT/TTS/VAD)
- Infra: Docker Compose, K8s manifests, Turborepo build

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 22:54:37 -08:00