Commit Graph

31 Commits

Author SHA1 Message Date
hailin 20325a84bd feat: redesign chat UI from bubble style to timeline workflow
Replace traditional chat bubble layout with a Claude Code-inspired
timeline/workflow design:
- Vertical gray line connecting sequential event nodes
- Colored dots for each event (green=done, red=error, yellow=warning)
- Animated spinning asterisk (*) on active nodes
- Streaming text with blinking cursor in timeline nodes
- Tool execution shown as code blocks within timeline
- User prompts as distinct nodes with person icon

New file: timeline_event_node.dart (TimelineEventNode, CodeBlock)
Rewritten: chat_page.dart (timeline layout, no more bubbles)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:33:42 -08:00
hailin 74be945e4a feat: enable token-level streaming and fix duplicate message bubble
Backend:
- Add includePartialMessages: true to SDK query options
- Handle stream_event/content_block_delta for real-time text streaming
- Skip text/thinking blocks from complete assistant messages (already
  streamed via deltas) to avoid duplication
- Change default result summary to empty string

Flutter:
- Only show CompletedEvent summary when no assistant text was streamed
  (prevents duplicate message bubble)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:24:48 -08:00
hailin 5e31b15dcf fix: use IOWebSocketChannel for headers support
WebSocketChannel.connect does not accept headers parameter in
web_socket_channel 2.4.0. Use IOWebSocketChannel.connect instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:45:35 -08:00
hailin 803cea0fe4 fix: pass JWT token in WebSocket connection headers
WebSocket connections to /ws/agent were rejected by Kong (401)
because the Authorization header was not included. Now reads
access_token from secure storage and passes it in the WebSocket
upgrade request headers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:43:31 -08:00
hailin a6cd3c20d9 feat: add WebSocket robustness to voice call (heartbeat, reconnect, jitter buffer)
Addresses reliability gaps in the real-time voice WebSocket connection
between Flutter client and Python voice-service backend.

Backend (voice-service):
- Heartbeat: new _heartbeat_sender coroutine sends JSON ping text frames
  every 15s alongside the Pipecat pipeline; failed send = dead connection
- Session preservation: on WebSocket disconnect, sessions are now marked
  "disconnected" with a timestamp instead of being deleted, allowing
  reconnection within a configurable TTL (default 60s)
- Reconnect endpoint: POST /sessions/{id}/reconnect verifies the session
  is alive and in "disconnected" state, returns fresh websocket_url
- Reconnect-aware WS handler: detects "disconnected" sessions, cancels
  stale pipeline tasks, creates a new pipeline, sends "session.resumed"
- Background cleanup: asyncio loop every 30s removes sessions that have
  been disconnected longer than session_ttl
- Structured event protocol: text frames = JSON control messages
  (ping/pong/session.resumed/session.ended/error), binary = PCM audio
- New settings: session_ttl (60s), heartbeat_interval (15s),
  heartbeat_timeout (45s)

Flutter (agent_call_page.dart):
- Heartbeat monitoring: tracks last server ping timestamp, triggers
  reconnect if no ping received in 45s (3 missed intervals)
- Auto-reconnect: exponential backoff (1s→2s→4s→8s→16s), max 5 attempts;
  calls /reconnect endpoint to verify session, rebuilds WebSocket,
  resets audio buffer, restarts heartbeat
- Reconnecting UI: yellow warning banner "重新连接中... (N/5)" with
  spinner overlay during reconnection attempts
- WebSocket data routing: _onWsData distinguishes String (JSON control)
  from binary (audio) frames, handles ping/session.resumed/session.ended
- User-initiated disconnect guard: _userEndedCall flag prevents reconnect
  attempts when user intentionally hangs up
- session_id field compatibility: supports session_id/sessionId/id

Flutter (pcm_player.dart):
- Jitter buffer: queues incoming PCM chunks, starts playback only after
  accumulating 4800 bytes (150ms at 16kHz 16-bit mono) to smooth out
  network timing variance
- reset() method: clears buffer on reconnect to discard stale audio
- Buffer underrun handling: re-enters buffering phase if queue empties

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 07:32:19 -08:00
hailin dfc541b571 feat: add Markdown rendering and phone-call voice entry to chat UI
Chat message rendering:
- MessageBubble: replace plain SelectableText with MarkdownBody for
  assistant messages, with full dark-theme stylesheet (headers, code
  blocks, tables, blockquotes, list bullets)
- StreamTextWidget: render completed messages as MarkdownBody, keep
  plain-text + blinking cursor for actively streaming messages

Voice interaction redesign:
- Remove all long-press-to-record code (~100 lines): AudioRecorder,
  SpeechEnhancer, mic pulse animation, voice indicator bar,
  SingleTickerProviderStateMixin
- Add phone-call button in AppBar (Icons.call) that navigates to the
  existing AgentCallPage for full-duplex voice conversation
- Add prominent "语音通话" entry button on empty chat state
- AgentCallPage was already fully implemented (ringing → connecting →
  active → ended, dual-direction WebSocket audio, GTCRN denoise,
  Kokoro TTS playback, waveform visualization) but previously unused

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 07:31:40 -08:00
hailin 6dcfe7cd9a chore: gitignore iOS 自动生成文件
- ios/Flutter/ephemeral/ — 构建临时文件
- ios/Runner/GeneratedPluginRegistrant.* — 插件注册表

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 05:10:54 -08:00
hailin 4651291468 style: 导航栏去掉蓝色药丸背景,改为图标/文字高亮
- indicatorColor: transparent 去掉 Material 3 默认的选中背景
- 选中项:图标 + 文字改为 primary 紫色,字重 w600
- 未选中项:图标 + 文字灰色 (textSecondary),字重 w400
- 与微信/支付宝/飞书的导航栏风格一致

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 05:09:34 -08:00
hailin 6a84519090 refactor: 移除 AppBar 刷新按钮,统一使用下拉刷新
6 个页面(仪表盘、服务器、任务、告警、审批、常驻指令)
删除右上角 IconButton(Icons.refresh),保留已有的 RefreshIndicator 下拉刷新。
Terminal 页面的刷新按钮是"重新连接"功能,保持不变。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 05:08:16 -08:00
hailin 666b173906 fix: 根治 Unhandled Exception — async void 拦截器 + 全局错误兜底
根本原因:Dio interceptor 的 onError/onRequest 签名是 void,
标 async 后变成 Future<void> 但没人 await,内部异常全部变成
Unhandled Exception 崩溃。

修复:
- RetryInterceptor: onError 改为同步调度,retry 逻辑移到独立
  _retry() 方法并用 try/catch 包裹全部路径
- DedupInterceptor: 防止 Completer 重复 complete,retry 请求
  跳过去重避免与原始请求冲突
- TokenInterceptor: onRequest 和 onError 的 async lambda 全部
  包裹 try/catch,异常时 fallback 到 handler.next()
- main.dart: 三层全局错误兜底 —
  1) FlutterError.onError 捕获框架错误
  2) PlatformDispatcher.onError 捕获平台通道错误
  3) runZonedGuarded 捕获所有漏网的异步异常
- receiveTimeout/sendTimeout 不再触发重试(服务器已收到请求)
- 超时调整: connect 10s, send 30s, receive 30s
- 仪表盘卡片 IntrinsicHeight 等高对齐

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 04:37:39 -08:00
hailin 68004409a3 fix: 仪表盘概览卡片等高对齐
- Row 外层包 IntrinsicHeight + CrossAxisAlignment.stretch,三卡自动等高
- Loading/Error 卡片去掉固定 height:140,改为 padding + stretch 拉伸

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 04:28:40 -08:00
hailin 4e55e9a616 feat: 补齐大厂级网络层 — 401并发锁、请求去重、结构化错误日志
## 1. TokenRefreshLock(401 并发刷新竞态修复)
- 新增 `core/network/token_refresh_lock.dart`
- 使用 Completer 实现互斥锁:多个请求同时 401 时,
  仅第一个触发 refreshToken(),其余等待同一结果
- 防止 5 个页面同时 401 → 5 次 refresh → 4 次失败踢出用户

## 2. DedupInterceptor(请求去重)
- 新增 `core/network/dedup_interceptor.dart`
- 相同 GET URL 在飞行中时,后续请求复用第一个的结果
- 防止:用户快速点重试、页面切换重复加载、下拉刷新连点
- 仅限 GET,POST/PUT/DELETE 等写操作始终放行

## 3. ErrorLogInterceptor + ErrorLogger(结构化错误日志)
- 新增 `core/network/error_log_interceptor.dart` — Dio 拦截器
- 新增 `core/services/error_logger.dart` — 持久化日志服务
- 每个失败请求记录:时间戳、方法、URL、状态码、错误类型、重试次数
- 本地 SharedPreferences 存储最近 50 条,支持 summary 统计
- debug 模式同步 debugPrint 输出
- 预留 Sentry/Crashlytics flush 接口

## 4. Dio 拦截器管线优化
拦截器顺序调整为大厂标准管线:
1. DedupInterceptor — 去重(最先,防止重复请求进入管线)
2. TokenInterceptor — 注入 token + 401 刷新(带并发锁)
3. TenantInterceptor — 注入 X-Tenant-Id
4. RetryInterceptor — 指数退避重试
5. ErrorLogInterceptor — 错误日志(最后,记录最终失败)

移除 LogInterceptor(被 ErrorLogInterceptor 替代,且不再在
release 模式下打印请求 body 造成性能损耗)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 04:05:53 -08:00
hailin 94652857cd feat: 生产级 API 错误处理 — 重试拦截器、友好错误提示、网络监测、WebSocket 退避
## 问题
用户看到原始 DioException 堆栈(如 "DioException [unknown]: null Error:
HttpException: Connection reset by peer"),且无重试机制,网络抖动即报错。

## 变更

### 1. RetryInterceptor(指数退避自动重试)
- 新增 `core/network/retry_interceptor.dart`
- 自动重试:连接超时、发送超时、Connection reset、502/503/504/429
- 指数退避(800ms → 1.6s → 3.2s)+ 随机抖动防雪崩
- 最多 3 次重试,非瞬态错误(401/403/404)不重试
- 集成到 dio_client,优化超时:connect 8s、send 15s、receive 20s

### 2. ErrorHandler 全面升级(友好中文错误提示)
- 重写 `core/errors/error_handler.dart`,新增 `friendlyMessage()` 静态方法
- 所有 DioExceptionType 映射为具体中文:
  - Connection reset → "连接被服务器重置,请稍后重试"
  - Connection refused → "服务器拒绝连接,请确认服务是否启动"
  - Timeout → "连接超时,服务器无响应"
  - 401 → "登录已过期,请重新登录"
  - 403/404/429/500/502/503 各有独立提示
- 新增 TimeoutFailure 类型
- 所有 Failure.message 默认中文

### 3. 网络连接监测 + 离线 Banner
- 新增 `core/network/connectivity_provider.dart` — 每30秒探测服务器可达性
- 新增 `core/widgets/offline_banner.dart` — 黄色警告横幅 "网络连接不可用"
- 集成到 ScaffoldWithNav,所有页面顶部自动显示离线状态

### 4. 统一错误展示(杜绝 e.toString())
- 新增 `core/widgets/error_view.dart` — 统一错误 UI(图标 + 友好文案 + 重试按钮)
- 替换 6 个页面的内联错误 Column 为 ErrorView:
  tasks_page / servers_page / alerts_page / approvals_page / standing_orders_page
- 替换 dashboard 的 3 处 _SummaryCardError(message: e.toString())
- 替换 4 个 provider 的 e.toString(): chat / auth / settings / approvals
- 全项目零 e.toString() 残留(仅剩 time.minute.toString() 时间格式化)

### 5. WebSocket 重连增强
- 指数退避(1s → 2s → 4s → ... → 60s 上限)+ 随机抖动
- 最多 10 次自动重连,超限后停止
- disconnect() 阻止自动重连
- 新增 reconnect() 手动重连方法

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 04:01:04 -08:00
hailin 1075a6b265 refactor: 重构 chat_page 对接完整架构,集成全部 stream event widget
## 问题
chat_page.dart 包含内联的简化版 ChatMessage/ChatState/ChatNotifier(约180行),
绕过了已实现的完整 Clean Architecture 层:
- domain/entities/chat_message.dart(含 ToolExecution、ApprovalRequest)
- domain/entities/stream_event.dart(9种 sealed class 事件)
- chat_providers.dart(完整 ChatNotifier 支持审批/工具/常驻指令)
- 5 个独立 widget 全部闲置未使用

## 变更
1. 删除内联重复代码(~180行):ChatRole、ChatContentType、内联 ChatMessage、
   内联 ChatState、内联 ChatNotifier、chatMessagesProvider
2. 切换到正式 chatProvider(chat_providers.dart),支持全部 9 种 StreamEvent
3. 集成 5 个已有 widget:
   - MessageBubble — 用户/AI 消息气泡(带时间戳)
   - StreamTextWidget — AI 流式回复动画光标
   - ToolExecutionCard — 工具执行详情(名称/输入/输出/状态/风险等级)
   - ApprovalActionCard — 审批卡片(倒计时/通过/拒绝/过期处理)
   - AgentThinkingIndicator — 思考动画指示器
4. 新增 _AgentStatusBar — 实时状态条(思考中/执行中/等待审批)
5. 新增 _StandingOrderDraftCard — 常驻指令草案渲染
6. AppBar + 输入区添加停止按钮,审批等待时显示提示
7. 消息渲染按 MessageType 分发:text/thinking/toolUse/toolResult/approval/standingOrderDraft

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 03:21:44 -08:00
hailin 15e6fca6c0 fix: translate all remaining English UI strings to Chinese and remove dead code
- Translate approval_action_card (Approve/Reject/Cancel/Expired)
- Translate tool_execution_card status labels (Executing/Completed/Error)
- Translate chat_providers error messages and stream content
- Translate message_bubble "Thinking..." indicator
- Translate terminal page tooltips (Reconnect/Disconnect)
- Translate fallback values (Untitled/Unknown/No message) across all pages
- Translate auth error "Login failed" and stream error messages
- Remove dead voice_providers.dart (used speech_to_text which is not installed)
- Remove dead voice_input_button.dart (not referenced anywhere)
- Fix widget_test.dart (was referencing non-existent MyApp class)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 02:07:57 -08:00
hailin 9f44878fea fix: unify all pages to Chinese + fix bottom nav selected state
1. 所有页面英文文本统一替换为中文(仪表盘、对话、任务、告警、
   服务器、常驻指令、审批、终端、设置)
2. 底部导航栏添加 selectedIndex 追踪当前路由,点击后正确高亮
3. 导航图标添加 outlined/filled 选中态区分
4. 设置页重构为大厂风格(圆角图标分组 + 主题底部弹窗选择)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:59:09 -08:00
hailin b76b5246cc fix: align settings page style with other pages using Card containers
设置页改为与 Dashboard/Alerts 等页面一致的卡片分组风格:
每个设置分区用 Card 容器包裹,内部 ListTile 用 Divider(height:1) 分隔,
统一使用 AppColors.surface 卡片背景色,外边距 padding: 16。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:51:42 -08:00
hailin d1993a1175 feat: add auto-login with token restore on app startup
App 启动时从 SecureStorage 读取已存储的 JWT,解析用户信息自动恢复登录状态,
无需每次重新输入密码。Token 过期则自动尝试 refresh,refresh 失败才跳转登录页。

- 新增 tryRestoreSession() 从 JWT payload 解码用户信息
- 新增 _isTokenExpired() 检查 token 是否过期(预留 60s 缓冲)
- refreshToken() 成功后恢复 AuthState + tenant 上下文
- 新增 /splash 启动页,尝试恢复后决定跳转 dashboard 或 login

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:47:20 -08:00
hailin 8015154a3e feat: replace default Flutter icon with iAgent robot logo
使用项目自有的绿色机器人 SVG logo 生成各分辨率 Android 启动图标,
替换默认的 Flutter 蓝色纸飞机。支持 Android Adaptive Icon(白底 + 机器人前景)。
同时生成 iOS 图标。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:41:36 -08:00
hailin 3d9b25391e fix: enable core library desugaring for flutter_local_notifications
flutter_local_notifications 插件依赖 java.time API,需要启用 Android core
library desugaring 才能在低版本设备上运行。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 01:24:38 -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 6a293d734b chore: 提交 Flutter 项目默认 README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:12:27 -08:00
hailin 51430adafc fix: 修复登录问题 — 重置用户密码 + 配置生产环境API地址
问题排查过程:
  1. 用户 hailin@it0.com 存在于 public.users,is_active=true
  2. 直接调用 auth-service login 接口返回 401 Invalid credentials
  3. 确认是密码不匹配 — 将密码重置为 admin123 (与 admin 账号相同)
  4. 重置后登录成功,Kong Gateway 路由也正常

App配置修改:
  - development: 端口从 8000 改为 18000 (匹配 Kong 映射)
  - production: 指向服务器 http://154.84.135.121:18000
  - 默认使用 production 配置 (之前是 development)

登录凭据:
  - admin@it0.com / admin123 (管理员)
  - hailin@it0.com / admin123 (运维员,请登录后修改密码)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:56:38 -08:00
hailin 68d0c9d6f7 fix: 移除logo白色背景 + 优化登录页面UI和中文化
Logo修复:
  - 移除 logo.svg 中的白色背景矩形 (fill="#ffffff")
  - Logo 现在为透明背景,在深色主题上正确显示

登录页面优化:
  - 添加 "iAgent" 品牌标题 (28px, bold, 带字间距)
  - 副标题改为中文 "服务器集群运维智能体"
  - 表单中文化: 邮箱/密码/登录
  - 错误提示改为带背景色的卡片样式 (红色图标+文字)
  - 添加邮箱输入框 placeholder (user@example.com)
  - 密码框支持回车提交
  - 底部提示: "账号由管理员在后台创建或通过邀请链接注册"
  - 限制表单最大宽度 360px,外层改用 SingleChildScrollView 防溢出

用户账号说明:
  App 端不提供自助注册功能,用户账号通过以下方式创建:
  1. 管理员在 Web 后台 (用户管理页) 直接创建
  2. 管理员发送邀请链接,用户通过链接注册
  3. 通过 Web 端自助注册 (可选填公司名创建新租户)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:42:42 -08:00
hailin 5d12ada262 fix: 添加 assets/images/.gitkeep 保留空目录,修复构建报错
问题: pubspec.yaml 声明了 assets/images/ 目录,但该目录为空。
Git 不追踪空目录,其他机器 clone 后缺少此目录,导致:
"Error: unable to find directory entry in pubspec.yaml: assets\images\"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:31:29 -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 913267fb9d fix: 提交完整的Android项目配置文件,修复跨机器构建失败
问题描述:
  在其他机器 (C:\Users\ph) 上执行 flutter build apk 时报错:
  "Build failed due to use of deleted Android v1 embedding."
  原因是 Android 项目配置文件未被提交到 Git 仓库。

根本原因:
  之前重新生成 Android 项目(从 speech_to_text 迁移到 record 包)时,
  新生成的 Android 构建文件只在本地存在,未提交到远程仓库。
  其他机器 clone/pull 后缺少这些文件,导致构建失败。

本次提交包含的文件:
  Android 构建配置:
  - android/settings.gradle.kts — Gradle 插件配置 (AGP 8.11.1, Kotlin 2.2.20)
  - android/build.gradle.kts — 根项目 Gradle 配置
  - android/app/build.gradle.kts — 应用模块配置 (namespace: com.iagent.it0_app, Java 17)
  - android/gradle.properties — JVM 参数 (8G heap), AndroidX 启用
  - android/gradle/wrapper/gradle-wrapper.properties — Gradle 8.14

  Android 清单与入口:
  - android/app/src/main/AndroidManifest.xml — 主清单 (v2 embedding, INTERNET+RECORD_AUDIO权限, cleartext允许)
  - android/app/src/debug/AndroidManifest.xml — Debug 清单
  - android/app/src/profile/AndroidManifest.xml — Profile 清单
  - android/app/src/main/kotlin/.../MainActivity.kt — FlutterActivity (v2 embedding)

  Android 资源:
  - res/drawable/ — 启动画面背景
  - res/mipmap-*/ — 应用图标 (hdpi~xxxhdpi)
  - res/values/ — 主题样式 (LaunchTheme + NormalTheme, 含夜间模式)

  Flutter 项目元数据:
  - .gitignore — Flutter 项目忽略规则
  - .metadata — Flutter SDK 版本追踪
  - android/.gitignore — Android 构建产物忽略规则

构建要求:
  - Flutter SDK >= 3.38.0 (pubspec.lock 约束)
  - 其他机器需执行: flutter clean && flutter pub get 后重新构建

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:17:18 -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 39c0d83424 feat: rename app from IT0 to iAgent (我智能体)
Web Admin:
- Update browser title to "iAgent Admin Console"
- Translation: en appTitle "iAgent", zh appTitle "我智能体"
- Sidebar: en "iAgent Admin", zh "我智能体"
- Settings placeholder: "iAgent Platform" / "我智能体平台"
- Update alt tags on logo images

Flutter:
- MaterialApp title: "iAgent"
- Chat: "Ask iAgent..." / "Start a conversation with iAgent"
- Terminal: "iAgent Remote Terminal"
- Agent call: "iAgent Calling" / "iAgent"

Logo SVG: text changed from "AI AGENT" to "iAgent"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 06:39:40 -08:00
hailin 2f228e4591 feat: integrate robot logo into web admin and Flutter app
- Add logo.svg (green robot character) to project root
- Web admin: replace text "IT" badge with SVG logo in sidebar
- Web admin: add logo image to login, register, invite pages
- Web admin: add SVG favicon and apple-touch-icon metadata
- Flutter: add flutter_svg dependency, replace text "IT0" with logo on login page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 06:17:08 -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