Skip to content

feat(chat-apps): add Telegram, DingTalk, and WhatsApp integration#64

Merged
hrygo merged 28 commits into
mainfrom
feat/53-chat-apps-integration
Feb 3, 2026
Merged

feat(chat-apps): add Telegram, DingTalk, and WhatsApp integration#64
hrygo merged 28 commits into
mainfrom
feat/53-chat-apps-integration

Conversation

@hrygo

@hrygo hrygo commented Feb 3, 2026

Copy link
Copy Markdown
Owner

概述

引入聊天应用集成功能,允许用户通过 Telegram、WhatsApp、钉钉等常用聊天平台直接与 DivineSense AI 助手交互。这是继 Geek Mode 和 Evolution Mode 之后, DivineSense AI 代理能力的又一次重要扩展。

主要功能

🤖 多平台支持

平台 类型 支持状态
Telegram Bot API ✅ 完全支持
WhatsApp Baileys 桥接 ✅ 完全支持
钉钉 企业机器人 ✅ 完全支持

🔐 安全加固

  • AES-256-GCM 加密:所有访问令牌使用 AES-256-GCM 加密存储
  • 启动时验证:服务启动时验证加密密钥配置,失败快速报错
  • 输入验证:平台白名单 + 字段长度限制(防注入)
  • Webhook 签名验证
    • 钉钉:HMAC-SHA256 + 时间戳验证(5分钟窗口,防重放攻击)
    • Telegram:Bot Token 匹配验证
    • WhatsApp:桥接服务连接状态检查
  • 并发安全:修复 Token 缓存竞态条件

📝 前端管理界面

  • 设置页面新增「聊天应用」配置面板
  • 支持凭证注册、删除、启用/禁用
  • Webhook URL 自动生成
  • 完整的 i18n 支持(中英文)

🤖 AI 代理集成

  • 消息自动路由到合适的 AI 代理(灰灰/时巧/折衷)
  • 支持流式响应,提升用户体验
  • 支持笔记查询、日程管理等核心功能

技术变更

新增数据库表chat_app_credential

新增 API 服务ChatAppService

新增目录

plugin/chat_apps/
├── channels/
│   ├── base.go           # ChatChannel 接口
│   ├── router.go         # 通道路由器
│   ├── telegram/         # Telegram Bot 实现
│   ├── whatsapp/         # WhatsApp 桥接
│   └── dingtalk/         # 钉钉机器人
├── store/
│   ├── db.go              # 数据库操作
│   └── crypto.go          # Token 加密
├── metrics/
│   └── metrics.go         # 指标收集
└── types.go               # 类型定义

环境变量

  • DIVINESENSE_CHAT_APPS_SECRET_KEY(必需)- 32字节加密密钥
  • DIVINESENSE_INSTANCE_URL(必需)- 实例 URL(生成 Webhook)
  • DIVINESENSE_WHATSAPP_BRIDGE_URL(可选)- WhatsApp 桥接服务地址

升级指南

  1. 拉取最新代码
  2. 配置环境变量(生成 32 字节加密密钥)
  3. 运行数据库迁移
  4. 重启服务

详细指南v0.91.0 Chat Apps Integration Release Notes

文档更新

已知问题

问题 影响 解决方案
钉钉媒体上传 不支持图片/文件自动发送 以文本形式提示
WhatsApp 桥接服务 需要独立部署 使用 PM2 或 systemd 管理
SQLite 数据库 不支持 Chat Apps 功能 使用 PostgreSQL

贡献者


Resolves #53

🤖 Generated with Claude Code

hrygo pushed a commit that referenced this pull request Feb 3, 2026
- Add input validation (platform whitelist, length limits) in store layer
- Add startup validation for DIVINESENSE_CHAT_APPS_SECRET_KEY
- Fix DingTalk token cache race condition (RWMutex → Mutex)
- Add timestamp validation to DingTalk webhook signature (prevent replay)
- Improve WhatsApp Bridge health check (verify connection status)
- Update media upload fallback behavior with clear logging

Security improvements:
- MaxPlatformUserID: 255, MaxAccessToken: 2048, MaxAppSecret: 2048
- Webhook timestamp window: 5 minutes with clock skew tolerance
- Fail-fast on missing/invalid encryption key at service startup

Refs #64

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
hrygo pushed a commit that referenced this pull request Feb 3, 2026
- Add Chat Apps architecture section to ARCHITECTURE.md
- Update BACKEND_DB.md with security details (input validation, webhook security)
- Enhance CHAT_APPS.md developer guide with security mechanisms
- Add comprehensive release notes for v6.1

Documentation highlights:
- Security: AES-256-GCM encryption, startup validation, input limits
- Webhook security: HMAC-SHA256 + timestamp validation (5-min window)
- Concurrency safety: fixed token cache race condition
- Architecture diagrams and data flow documentation

Related: #64 #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
hotplex-ai and others added 26 commits February 3, 2026 22:34
Phase 1 of #53: Infrastructure setup for Telegram, WhatsApp, DingTalk

- Add ChatChannel interface for platform abstraction
- Add proto definitions for ChatAppService (API + Store)
- Add database migrations for chat_app_credential table
- Add channel_type column to conversation_context
- Implement skeleton for Telegram, WhatsApp, DingTalk channels
- Add media processing interface (Whisper OCR placeholder)
- Add token encryption utilities for secure credential storage

Created files:
- docs/specs/chat-apps-integration.md (technical specification)
- proto/api/v1/chat_app_service.proto
- proto/store/chat_app_service.proto
- plugin/chat_apps/ (channels, media, store)
- store/migration/postgres/20260203_*.sql

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ments

- Implement Telegram media download with HTTP client
- Add RWMutex to ChannelRouter for concurrent safety
- Configure HTTP client timeout and connection pool
- Add structured logging (log/slog) to store and channels
- Enhance Telegram webhook verification (method, content-type)
- Fix string concatenation in SendChunkedMessage (use strings.Builder)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ram DownloadMedia

## Changes

### Telegram Channel (plugin/chat_apps/channels/telegram/telegram.go)
- Complete DownloadMedia implementation with HTTP download
- Add HTTP client to TelegramChannel struct
- Fix file.Link() method call (requires bot token parameter)
- Add proper error handling and MIME type detection

### Store Proto (proto/store/chat_app_service.proto)
- Remove google.api.http annotations (store layer doesn't need HTTP)
- Add google.protobuf.Empty import

### API v1 Service (server/router/api/v1/chat_app_service.go)
- Implement all 7 ChatAppService RPC methods:
  - RegisterCredential: bind chat app account with encryption
  - ListCredentials: list user's chat app bindings
  - DeleteCredential: remove binding with ownership check
  - UpdateCredential: modify access token/webhook URL
  - HandleWebhook: process incoming webhook events
  - SendMessage: send messages to chat platforms
  - GetWebhookInfo: return webhook setup instructions
- Add conversion functions between proto and internal types
- Add ChannelRegistry interface for channel management
- Integrate with Store.GetDriver().GetDB() for database access
- Use os.Getenv() for environment variable access

### Gateway Registration (server/router/api/v1/v1.go)
- Add UnimplementedChatAppServiceServer embedding
- Register ChatAppService with gRPC-Gateway

### Generated Files
- Regenerate proto files with buf generate
- Add chat_app_service.connect.go for Connect RPC

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## HandleWebhook Enhancement

- Add credential lookup by PlatformUserID to find DivineSense user
- Add credential enabled check
- Implement asynchronous message processing (non-blocking webhook response)
- Add processChatAppMessage for AI routing (stub for future implementation)

The webhook now:
1. Validates the incoming request
2. Parses the message using channel-specific parser
3. Looks up the user credential by platform user ID
4. Returns immediately with success (async processing)
5. Processes the message in background (stub for AI routing)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## DingTalk Channel Enhancements

### New Features
- Add HTTP client for API calls
- Add access token caching with thread-safe double-check locking
- Token expires 5 minutes early to avoid edge cases

### Completed Methods
- `sendText()`: Send text messages via webhook
- `sendMedia()`: Send media messages (placeholder with text fallback)
- `sendWebhook()`: HTTP POST to DingTalk webhook with error handling
- `GetAccessToken()`: Fetch and cache access tokens (2hr expiry)
- `DownloadMedia()`: Download media using downloadCode

### Technical Details
- Implements DingTalk signature validation (HMAC-SHA256)
- Supports webhook-based outgoing messages
- Uses context with timeout for all HTTP requests
- Proper error handling with structured logging

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## Frontend Chat Apps Settings

### New Component
- Create ChatAppsSection component in `web/src/components/Settings/ChatAppsSection.tsx`
- Add chat apps account management UI with:
  - List existing credentials with platform labels
  - Enable/disable toggle
  - Delete credential button
  - Webhook info display

### Add Credential Dialog
- Platform selection (Telegram, WhatsApp, DingTalk)
- Platform user ID input with hints
- Access token input (password type)
- Webhook URL input (DingTalk only)
- Platform-specific help text

### Integration
- Add "chat-apps" to BASIC_SECTIONS (available to all users)
- Add MessageSquare icon for the section
- Render ChatAppsSection in Setting.tsx

### i18n
- Add English translations in `en.json`
- Add Chinese translations in `zh-Hans.json`
- Includes all labels, hints, and error messages

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create Node.js bridge service for WhatsApp integration using Baileys library.

Features:
- Express HTTP server with health check endpoint
- WhatsApp Web API connection via Baileys
- QR code pairing for WhatsApp authentication
- Message forwarding from WhatsApp to DivineSense webhook
- Send message endpoint for DivineSense to WhatsApp
- Media download endpoint
- Auto-reconnection on connection loss
- Environment-based configuration

Files added:
- plugin/chat_apps/channels/whatsapp/bridge/package.json
- plugin/chat_apps/channels/whatsapp/bridge/src/index.js
- plugin/chat_apps/channels/whatsapp/bridge/README.md

The bridge service runs as a standalone Node.js process and communicates
with DivineSense via HTTP endpoints. This architecture is required because
the Baileys library only works in a Node.js runtime.

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use double %%w for error wrapping in DownloadMedia
- Add rows.Err() check in ListCredentials

Fixes:
- errorlint: non-wrapping format verb for fmt.Errorf
- rowserrcheck: rows.Err must be checked

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix Platform enum usage (TELEGRAM not PLATFORM_TELEGRAM)
- Remove unused imports (Checkbox, AlertDialogAction, useToast)
- Change AlertDialog to Dialog (standard component)
- Add useEffect for proper lifecycle
- Add inline error display instead of toast
- Fix duplicate i18n keys in en.json and zh-Hans.json
  - Remove duplicate 'chat-apps' string key
  - Remove duplicate 'webhook-url' key
  - Remove duplicate 'storage'/'storage-section' keys
- Format code with Biome

Fixes:
- TypeScript enum access errors
- Biome import organization issues
- Duplicate object keys in locale files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Complete zero-barrier entry guide for Chat Apps integration:
- Feature introduction and platform comparison
- Detailed Telegram, WhatsApp, DingTalk setup guides
- Step-by-step instructions with examples
- Troubleshooting section with common issues
- Security best practices
- Advanced configuration options

File: docs/user-guides/CHAT_APPS.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit implements multi-platform chat app integration, allowing
users to interact with DivineSense AI agents through Telegram, DingTalk,
and WhatsApp.

Features:
- Register/list/delete chat app credentials
- Webhook endpoint for receiving messages (all 3 platforms)
- AI integration using AUTO agent routing
- Token encryption (AES-256-GCM) with fail-fast validation
- Frontend settings panel with i18n support
- WhatsApp via Baileys Node.js bridge service (complete implementation)
- Metrics tracking for webhook events

Code Quality Fixes:
- Fixed double close channel panic (goroutine owns channel close)
- Removed insecure plaintext fallback (fail-fast on missing encryption key)
- Consolidated duplicate functions (~100 lines removed)
- Fixed metrics tracking (moved after credential lookup)
- Added typed context key to prevent collisions

Documentation:
- Added comprehensive user guide (docs/guides/CHAT_APPS.md)
- Updated architecture docs with Chat Apps module
- Added database schema documentation for chat_app_credential table
- Added frontend component documentation for ChatAppsSection

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Auto-formatted by pre-commit hook.

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use fields in test to avoid unused warnings
- Remove unnecessary int64 conversion (messagesProcessed is already int64)
- Remove unused getAIResponse function and its imports (strings, sync)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
用户手册更新 (docs/user-guides/CHAT_APPS.md):
- 添加详细的平台配置步骤(Telegram/WhatsApp/钉钉)
- 新增架构说明和 QR 码配对流程
- 完善 FAQ 和故障排查章节
- 添加调试信息获取指南

开发者指南更新 (docs/guides/CHAT_APPS.md):
- 添加系统架构图和核心组件说明
- 完善数据模型和 API 端点文档
- 新增平台集成技术细节
- 添加安全机制、加密存储说明
- 完善开发调试和部署指南
- 新增扩展新平台的步骤指南

WhatsApp Bridge README 更新:
- 添加架构图和功能特性表格
- 完善 API 端点文档和请求示例
- 新增 PM2/Systemd/Docker 部署指南
- 添加故障排查章节
- 完善安全建议

其他修复:
- 修复 qrcode-terminal ES 模块导入问题

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit adds comprehensive deployment automation for the WhatsApp Bridge
service (Baileys), integrating it into the main installation workflow.

## New Files

### deploy/baileys-bridge.sh
- Standalone deployment management script for WhatsApp Bridge
- Commands: install, start, stop, restart, status, logs, health, qr, backup, update, uninstall
- Supports both PM2 and systemd process managers
- Health check endpoint monitoring
- QR code display for WhatsApp pairing

### docker/compose/with-whatsapp.yml
- Docker Compose configuration including DivineSense, PostgreSQL, and Baileys Bridge
- Health checks for all services
- Proper networking and volume management

### plugin/chat_apps/channels/whatsapp/bridge/ecosystem.config.cjs
- PM2 ecosystem configuration for process management
- Automatic restart, logging, resource limits
- Health check integration

### plugin/chat_apps/channels/whatsapp/bridge/baileys-bridge.service
- systemd service file for production deployment
- Security hardening (NoNewPrivileges, ProtectSystem)
- Resource limits (512M memory, 50% CPU)

### plugin/chat_apps/channels/whatsapp/bridge/.env.example
- Environment configuration template
- Documentation for all configuration options

## Modified Files

### deploy/install.sh
- Added INSTALL_WHATSAPP variable to interactive wizard
- Added --whatsapp command-line flag
- Integrated WhatsApp Bridge installation into both binary and docker modes
- Added help text for WhatsApp Bridge option

### deploy/lib/common.sh
- Added WhatsApp Bridge management commands to user Makefile
- Added sudoers entries for baileys-bridge.sh and baileys-bridge.service
- Added bash aliases: ds-wa-status, ds-wa-qr, ds-wa-logs, ds-wa-install
- Fixed systemd service user from 'divinesense' to 'divine'

## Usage

### Installation
```bash
# Interactive installation with WhatsApp option
curl -fsSL https://raw.githubusercontent.com/hrygo/divinesense/main/deploy/install.sh | sudo bash -s -- --interactive

# Direct installation with WhatsApp Bridge
curl -fsSL ... | sudo bash -s -- --whatsapp
```

### Management (via divine user)
```bash
make whatsapp-status   # Check bridge status
make whatsapp-qr       # Display QR code for pairing
make whatsapp-logs     # View logs
ds-wa-status          # Shortcut alias
```

Resolves #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit addresses security and reliability issues identified in code review.

## Security Improvements

### Optional API Key Authentication
- Added BRIDGE_API_KEY environment variable for protecting sensitive endpoints
- /send and /download endpoints now support optional API key auth via X-Bridge-Api-Key header
- When BRIDGE_API_KEY is set, requests must include valid API key

### CORS Origin Restriction
- Added ALLOWED_ORIGINS environment variable
- Default behavior unchanged (*), but production can now restrict origins
- Documented in .env.example with examples

## Error Handling Improvements

### Health Check Validation
- baileys-bridge.sh now checks health check return value
- Installation shows warning if service fails to start
- Provides troubleshooting hints on failure

### File Copy Robustness
- Added explicit log message when copying bridge files
- Sets correct ownership (divine:divine) after copy
- Warns if source directory not found

## Service Reliability

### systemd BindsTo Directive
- Added BindsTo=divinesense.service to baileys-bridge.service
- Ensures bridge restarts when DivineSense restarts
- Prevents orphaned bridge service

### Better Error Messages
- Installation now distinguishes between success and failure
- Shows manual installation command on failure
- Webhook URL template warns against using localhost in production

## Configuration Updates

- Updated all configuration files (.env.example, ecosystem.config.cjs,
  baileys-bridge.service, with-whatsapp.yml) to include new security
  environment variables
- Added .gitignore to exclude Baileys auth data directory

Resolves code review findings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add missing translation keys in en.json for SSO section:
- custom
- delete-sso
- disabled-password-login-warning
- display-name
- identifier-filter
- no-sso-found
- redirect-url
- scopes
- single-sign-on
- sso-created
- sso-list
- sso-updated
- template
- token-endpoint
- update-sso
- user-endpoint

These keys existed in zh-Hans.json but were missing in en.json,
causing TypeScript type errors during lint checks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add input validation (platform whitelist, length limits) in store layer
- Add startup validation for DIVINESENSE_CHAT_APPS_SECRET_KEY
- Fix DingTalk token cache race condition (RWMutex → Mutex)
- Add timestamp validation to DingTalk webhook signature (prevent replay)
- Improve WhatsApp Bridge health check (verify connection status)
- Update media upload fallback behavior with clear logging

Security improvements:
- MaxPlatformUserID: 255, MaxAccessToken: 2048, MaxAppSecret: 2048
- Webhook timestamp window: 5 minutes with clock skew tolerance
- Fail-fast on missing/invalid encryption key at service startup

Refs #64

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Chat Apps architecture section to ARCHITECTURE.md
- Update BACKEND_DB.md with security details (input validation, webhook security)
- Enhance CHAT_APPS.md developer guide with security mechanisms
- Add comprehensive release notes for v6.1

Documentation highlights:
- Security: AES-256-GCM encryption, startup validation, input limits
- Webhook security: HMAC-SHA256 + timestamp validation (5-min window)
- Concurrency safety: fixed token cache race condition
- Architecture diagrams and data flow documentation

Related: #64 #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix Issue link from #63 to #53 (correct issue number)
- Include previous code fixes and documentation updates

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add all required translation keys for Chat Apps settings
- Remove duplicate chat-apps section in locale files
- Fix code formatting issues

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Apply buf format to chat_app_service.proto files
- Collapse multi-line http options to single line
- Fix import/option ordering

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use .title suffix for chat-apps menu label
- Fixes missing Chat Apps entry in settings dropdown

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Apply same fix to SectionMenuItem component
- Both desktop and mobile menus now display "Chat Apps" correctly

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document DIVINESENSE_CHAT_APPS_SECRET_KEY requirement
- Add instructions for generating encryption key

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@hrygo hrygo force-pushed the feat/53-chat-apps-integration branch from 51b6da0 to 53ec929 Compare February 3, 2026 14:35
… vars

- Add DIVINESENSE_INSTANCE_URL for webhook URL generation
- Add DIVINESENSE_WHATSAPP_BRIDGE_URL for optional WhatsApp bridge
- Document both variables in .env.example with usage descriptions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add DIVINESENSE_CHAT_APPS_SECRET_KEY for token encryption
- Add DIVINESENSE_WHATSAPP_BRIDGE_URL for optional WhatsApp bridge
- Keep in sync with root .env.example

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@hrygo hrygo merged commit c0f5a47 into main Feb 3, 2026
11 checks passed
@hrygo hrygo deleted the feat/53-chat-apps-integration branch February 4, 2026 13:24
hrygo added a commit that referenced this pull request Feb 5, 2026
* feat(chat-apps): add foundation for multi-platform chat apps integration

Phase 1 of #53: Infrastructure setup for Telegram, WhatsApp, DingTalk

- Add ChatChannel interface for platform abstraction
- Add proto definitions for ChatAppService (API + Store)
- Add database migrations for chat_app_credential table
- Add channel_type column to conversation_context
- Implement skeleton for Telegram, WhatsApp, DingTalk channels
- Add media processing interface (Whisper OCR placeholder)
- Add token encryption utilities for secure credential storage

Created files:
- docs/specs/chat-apps-integration.md (technical specification)
- proto/api/v1/chat_app_service.proto
- proto/store/chat_app_service.proto
- plugin/chat_apps/ (channels, media, store)
- store/migration/postgres/20260203_*.sql

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat_apps): complete Telegram channel DownloadMedia + QA improvements

- Implement Telegram media download with HTTP client
- Add RWMutex to ChannelRouter for concurrent safety
- Configure HTTP client timeout and connection pool
- Add structured logging (log/slog) to store and channels
- Enhance Telegram webhook verification (method, content-type)
- Fix string concatenation in SendChunkedMessage (use strings.Builder)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement ChatAppService handlers and complete Telegram DownloadMedia

## Changes

### Telegram Channel (plugin/chat_apps/channels/telegram/telegram.go)
- Complete DownloadMedia implementation with HTTP download
- Add HTTP client to TelegramChannel struct
- Fix file.Link() method call (requires bot token parameter)
- Add proper error handling and MIME type detection

### Store Proto (proto/store/chat_app_service.proto)
- Remove google.api.http annotations (store layer doesn't need HTTP)
- Add google.protobuf.Empty import

### API v1 Service (server/router/api/v1/chat_app_service.go)
- Implement all 7 ChatAppService RPC methods:
  - RegisterCredential: bind chat app account with encryption
  - ListCredentials: list user's chat app bindings
  - DeleteCredential: remove binding with ownership check
  - UpdateCredential: modify access token/webhook URL
  - HandleWebhook: process incoming webhook events
  - SendMessage: send messages to chat platforms
  - GetWebhookInfo: return webhook setup instructions
- Add conversion functions between proto and internal types
- Add ChannelRegistry interface for channel management
- Integrate with Store.GetDriver().GetDB() for database access
- Use os.Getenv() for environment variable access

### Gateway Registration (server/router/api/v1/v1.go)
- Add UnimplementedChatAppServiceServer embedding
- Register ChatAppService with gRPC-Gateway

### Generated Files
- Regenerate proto files with buf generate
- Add chat_app_service.connect.go for Connect RPC

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement webhook message processing

## HandleWebhook Enhancement

- Add credential lookup by PlatformUserID to find DivineSense user
- Add credential enabled check
- Implement asynchronous message processing (non-blocking webhook response)
- Add processChatAppMessage for AI routing (stub for future implementation)

The webhook now:
1. Validates the incoming request
2. Parses the message using channel-specific parser
3. Looks up the user credential by platform user ID
4. Returns immediately with success (async processing)
5. Processes the message in background (stub for AI routing)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): complete DingTalk channel implementation

## DingTalk Channel Enhancements

### New Features
- Add HTTP client for API calls
- Add access token caching with thread-safe double-check locking
- Token expires 5 minutes early to avoid edge cases

### Completed Methods
- `sendText()`: Send text messages via webhook
- `sendMedia()`: Send media messages (placeholder with text fallback)
- `sendWebhook()`: HTTP POST to DingTalk webhook with error handling
- `GetAccessToken()`: Fetch and cache access tokens (2hr expiry)
- `DownloadMedia()`: Download media using downloadCode

### Technical Details
- Implements DingTalk signature validation (HMAC-SHA256)
- Supports webhook-based outgoing messages
- Uses context with timeout for all HTTP requests
- Proper error handling with structured logging

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): add frontend Chat Apps settings panel

## Frontend Chat Apps Settings

### New Component
- Create ChatAppsSection component in `web/src/components/Settings/ChatAppsSection.tsx`
- Add chat apps account management UI with:
  - List existing credentials with platform labels
  - Enable/disable toggle
  - Delete credential button
  - Webhook info display

### Add Credential Dialog
- Platform selection (Telegram, WhatsApp, DingTalk)
- Platform user ID input with hints
- Access token input (password type)
- Webhook URL input (DingTalk only)
- Platform-specific help text

### Integration
- Add "chat-apps" to BASIC_SECTIONS (available to all users)
- Add MessageSquare icon for the section
- Render ChatAppsSection in Setting.tsx

### i18n
- Add English translations in `en.json`
- Add Chinese translations in `zh-Hans.json`
- Includes all labels, hints, and error messages

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement WhatsApp Baileys bridge service

Create Node.js bridge service for WhatsApp integration using Baileys library.

Features:
- Express HTTP server with health check endpoint
- WhatsApp Web API connection via Baileys
- QR code pairing for WhatsApp authentication
- Message forwarding from WhatsApp to DivineSense webhook
- Send message endpoint for DivineSense to WhatsApp
- Media download endpoint
- Auto-reconnection on connection loss
- Environment-based configuration

Files added:
- plugin/chat_apps/channels/whatsapp/bridge/package.json
- plugin/chat_apps/channels/whatsapp/bridge/src/index.js
- plugin/chat_apps/channels/whatsapp/bridge/README.md

The bridge service runs as a standalone Node.js process and communicates
with DivineSense via HTTP endpoints. This architecture is required because
the Baileys library only works in a Node.js runtime.

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(chat-apps): format DingTalk channel code

* lint(chat-apps): fix golangci-lint issues

- Use double %%w for error wrapping in DownloadMedia
- Add rows.Err() check in ListCredentials

Fixes:
- errorlint: non-wrapping format verb for fmt.Errorf
- rowserrcheck: rows.Err must be checked

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* lint(chat-apps): fix frontend lint and i18n issues

- Fix Platform enum usage (TELEGRAM not PLATFORM_TELEGRAM)
- Remove unused imports (Checkbox, AlertDialogAction, useToast)
- Change AlertDialog to Dialog (standard component)
- Add useEffect for proper lifecycle
- Add inline error display instead of toast
- Fix duplicate i18n keys in en.json and zh-Hans.json
  - Remove duplicate 'chat-apps' string key
  - Remove duplicate 'webhook-url' key
  - Remove duplicate 'storage'/'storage-section' keys
- Format code with Biome

Fixes:
- TypeScript enum access errors
- Biome import organization issues
- Duplicate object keys in locale files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): add comprehensive user manual

Complete zero-barrier entry guide for Chat Apps integration:
- Feature introduction and platform comparison
- Detailed Telegram, WhatsApp, DingTalk setup guides
- Step-by-step instructions with examples
- Troubleshooting section with common issues
- Security best practices
- Advanced configuration options

File: docs/user-guides/CHAT_APPS.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): complete Telegram, DingTalk, and WhatsApp integration

This commit implements multi-platform chat app integration, allowing
users to interact with DivineSense AI agents through Telegram, DingTalk,
and WhatsApp.

Features:
- Register/list/delete chat app credentials
- Webhook endpoint for receiving messages (all 3 platforms)
- AI integration using AUTO agent routing
- Token encryption (AES-256-GCM) with fail-fast validation
- Frontend settings panel with i18n support
- WhatsApp via Baileys Node.js bridge service (complete implementation)
- Metrics tracking for webhook events

Code Quality Fixes:
- Fixed double close channel panic (goroutine owns channel close)
- Removed insecure plaintext fallback (fail-fast on missing encryption key)
- Consolidated duplicate functions (~100 lines removed)
- Fixed metrics tracking (moved after credential lookup)
- Added typed context key to prevent collisions

Documentation:
- Added comprehensive user guide (docs/guides/CHAT_APPS.md)
- Updated architecture docs with Chat Apps module
- Added database schema documentation for chat_app_credential table
- Added frontend component documentation for ChatAppsSection

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(chat-apps): format code with go fmt

Auto-formatted by pre-commit hook.

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* lint(chat-apps): fix golangci-lint issues

- Use fields in test to avoid unused warnings
- Remove unnecessary int64 conversion (messagesProcessed is already int64)
- Remove unused getAIResponse function and its imports (strings, sync)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): 完善用户手册和开发者手册

用户手册更新 (docs/user-guides/CHAT_APPS.md):
- 添加详细的平台配置步骤(Telegram/WhatsApp/钉钉)
- 新增架构说明和 QR 码配对流程
- 完善 FAQ 和故障排查章节
- 添加调试信息获取指南

开发者指南更新 (docs/guides/CHAT_APPS.md):
- 添加系统架构图和核心组件说明
- 完善数据模型和 API 端点文档
- 新增平台集成技术细节
- 添加安全机制、加密存储说明
- 完善开发调试和部署指南
- 新增扩展新平台的步骤指南

WhatsApp Bridge README 更新:
- 添加架构图和功能特性表格
- 完善 API 端点文档和请求示例
- 新增 PM2/Systemd/Docker 部署指南
- 添加故障排查章节
- 完善安全建议

其他修复:
- 修复 qrcode-terminal ES 模块导入问题

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(deploy): add WhatsApp Bridge deployment automation

This commit adds comprehensive deployment automation for the WhatsApp Bridge
service (Baileys), integrating it into the main installation workflow.

## New Files

### deploy/baileys-bridge.sh
- Standalone deployment management script for WhatsApp Bridge
- Commands: install, start, stop, restart, status, logs, health, qr, backup, update, uninstall
- Supports both PM2 and systemd process managers
- Health check endpoint monitoring
- QR code display for WhatsApp pairing

### docker/compose/with-whatsapp.yml
- Docker Compose configuration including DivineSense, PostgreSQL, and Baileys Bridge
- Health checks for all services
- Proper networking and volume management

### plugin/chat_apps/channels/whatsapp/bridge/ecosystem.config.cjs
- PM2 ecosystem configuration for process management
- Automatic restart, logging, resource limits
- Health check integration

### plugin/chat_apps/channels/whatsapp/bridge/baileys-bridge.service
- systemd service file for production deployment
- Security hardening (NoNewPrivileges, ProtectSystem)
- Resource limits (512M memory, 50% CPU)

### plugin/chat_apps/channels/whatsapp/bridge/.env.example
- Environment configuration template
- Documentation for all configuration options

## Modified Files

### deploy/install.sh
- Added INSTALL_WHATSAPP variable to interactive wizard
- Added --whatsapp command-line flag
- Integrated WhatsApp Bridge installation into both binary and docker modes
- Added help text for WhatsApp Bridge option

### deploy/lib/common.sh
- Added WhatsApp Bridge management commands to user Makefile
- Added sudoers entries for baileys-bridge.sh and baileys-bridge.service
- Added bash aliases: ds-wa-status, ds-wa-qr, ds-wa-logs, ds-wa-install
- Fixed systemd service user from 'divinesense' to 'divine'

## Usage

### Installation
```bash
# Interactive installation with WhatsApp option
curl -fsSL https://raw.githubusercontent.com/hrygo/divinesense/main/deploy/install.sh | sudo bash -s -- --interactive

# Direct installation with WhatsApp Bridge
curl -fsSL ... | sudo bash -s -- --whatsapp
```

### Management (via divine user)
```bash
make whatsapp-status   # Check bridge status
make whatsapp-qr       # Display QR code for pairing
make whatsapp-logs     # View logs
ds-wa-status          # Shortcut alias
```

Resolves #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(deploy): security hardening and error handling improvements

This commit addresses security and reliability issues identified in code review.

## Security Improvements

### Optional API Key Authentication
- Added BRIDGE_API_KEY environment variable for protecting sensitive endpoints
- /send and /download endpoints now support optional API key auth via X-Bridge-Api-Key header
- When BRIDGE_API_KEY is set, requests must include valid API key

### CORS Origin Restriction
- Added ALLOWED_ORIGINS environment variable
- Default behavior unchanged (*), but production can now restrict origins
- Documented in .env.example with examples

## Error Handling Improvements

### Health Check Validation
- baileys-bridge.sh now checks health check return value
- Installation shows warning if service fails to start
- Provides troubleshooting hints on failure

### File Copy Robustness
- Added explicit log message when copying bridge files
- Sets correct ownership (divine:divine) after copy
- Warns if source directory not found

## Service Reliability

### systemd BindsTo Directive
- Added BindsTo=divinesense.service to baileys-bridge.service
- Ensures bridge restarts when DivineSense restarts
- Prevents orphaned bridge service

### Better Error Messages
- Installation now distinguishes between success and failure
- Shows manual installation command on failure
- Webhook URL template warns against using localhost in production

## Configuration Updates

- Updated all configuration files (.env.example, ecosystem.config.cjs,
  baileys-bridge.service, with-whatsapp.yml) to include new security
  environment variables
- Added .gitignore to exclude Baileys auth data directory

Resolves code review findings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(i18n): add missing English translations for SSO settings

Add missing translation keys in en.json for SSO section:
- custom
- delete-sso
- disabled-password-login-warning
- display-name
- identifier-filter
- no-sso-found
- redirect-url
- scopes
- single-sign-on
- sso-created
- sso-list
- sso-updated
- template
- token-endpoint
- update-sso
- user-endpoint

These keys existed in zh-Hans.json but were missing in en.json,
causing TypeScript type errors during lint checks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(chat-apps): address security and concurrency issues from code review

- Add input validation (platform whitelist, length limits) in store layer
- Add startup validation for DIVINESENSE_CHAT_APPS_SECRET_KEY
- Fix DingTalk token cache race condition (RWMutex → Mutex)
- Add timestamp validation to DingTalk webhook signature (prevent replay)
- Improve WhatsApp Bridge health check (verify connection status)
- Update media upload fallback behavior with clear logging

Security improvements:
- MaxPlatformUserID: 255, MaxAccessToken: 2048, MaxAppSecret: 2048
- Webhook timestamp window: 5 minutes with clock skew tolerance
- Fail-fast on missing/invalid encryption key at service startup

Refs #64

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): complete documentation for v6.1 release

- Add Chat Apps architecture section to ARCHITECTURE.md
- Update BACKEND_DB.md with security details (input validation, webhook security)
- Enhance CHAT_APPS.md developer guide with security mechanisms
- Add comprehensive release notes for v6.1

Documentation highlights:
- Security: AES-256-GCM encryption, startup validation, input limits
- Webhook security: HMAC-SHA256 + timestamp validation (5-min window)
- Concurrency safety: fixed token cache race condition
- Architecture diagrams and data flow documentation

Related: #64 #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(release): fix issue link in v6.1 release notes

- Fix Issue link from #63 to #53 (correct issue number)
- Include previous code fixes and documentation updates

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(i18n): add missing chat-apps translation keys

- Add all required translation keys for Chat Apps settings
- Remove duplicate chat-apps section in locale files
- Fix code formatting issues

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(proto): format protobuf files with buf

- Apply buf format to chat_app_service.proto files
- Collapse multi-line http options to single line
- Fix import/option ordering

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(settings): add Chat Apps section menu item display

- Use .title suffix for chat-apps menu label
- Fixes missing Chat Apps entry in settings dropdown

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(settings): use .title suffix for chat-apps in sidebar menu too

- Apply same fix to SectionMenuItem component
- Both desktop and mobile menus now display "Chat Apps" correctly

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(env): add Chat Apps configuration to .env.example

- Document DIVINESENSE_CHAT_APPS_SECRET_KEY requirement
- Add instructions for generating encryption key

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): add missing INSTANCE_URL and WHATSAPP_BRIDGE_URL env vars

- Add DIVINESENSE_INSTANCE_URL for webhook URL generation
- Add DIVINESENSE_WHATSAPP_BRIDGE_URL for optional WhatsApp bridge
- Document both variables in .env.example with usage descriptions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(deploy): add Chat Apps env vars to production config template

- Add DIVINESENSE_CHAT_APPS_SECRET_KEY for token encryption
- Add DIVINESENSE_WHATSAPP_BRIDGE_URL for optional WhatsApp bridge
- Keep in sync with root .env.example

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: 黄飞虹 <aaronwong1989@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
hrygo added a commit that referenced this pull request Feb 5, 2026
* feat(chat-apps): add foundation for multi-platform chat apps integration

Phase 1 of #53: Infrastructure setup for Telegram, WhatsApp, DingTalk

- Add ChatChannel interface for platform abstraction
- Add proto definitions for ChatAppService (API + Store)
- Add database migrations for chat_app_credential table
- Add channel_type column to conversation_context
- Implement skeleton for Telegram, WhatsApp, DingTalk channels
- Add media processing interface (Whisper OCR placeholder)
- Add token encryption utilities for secure credential storage

Created files:
- docs/specs/chat-apps-integration.md (technical specification)
- proto/api/v1/chat_app_service.proto
- proto/store/chat_app_service.proto
- plugin/chat_apps/ (channels, media, store)
- store/migration/postgres/20260203_*.sql

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat_apps): complete Telegram channel DownloadMedia + QA improvements

- Implement Telegram media download with HTTP client
- Add RWMutex to ChannelRouter for concurrent safety
- Configure HTTP client timeout and connection pool
- Add structured logging (log/slog) to store and channels
- Enhance Telegram webhook verification (method, content-type)
- Fix string concatenation in SendChunkedMessage (use strings.Builder)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement ChatAppService handlers and complete Telegram DownloadMedia

- Complete DownloadMedia implementation with HTTP download
- Add HTTP client to TelegramChannel struct
- Fix file.Link() method call (requires bot token parameter)
- Add proper error handling and MIME type detection

- Remove google.api.http annotations (store layer doesn't need HTTP)
- Add google.protobuf.Empty import

- Implement all 7 ChatAppService RPC methods:
  - RegisterCredential: bind chat app account with encryption
  - ListCredentials: list user's chat app bindings
  - DeleteCredential: remove binding with ownership check
  - UpdateCredential: modify access token/webhook URL
  - HandleWebhook: process incoming webhook events
  - SendMessage: send messages to chat platforms
  - GetWebhookInfo: return webhook setup instructions
- Add conversion functions between proto and internal types
- Add ChannelRegistry interface for channel management
- Integrate with Store.GetDriver().GetDB() for database access
- Use os.Getenv() for environment variable access

- Add UnimplementedChatAppServiceServer embedding
- Register ChatAppService with gRPC-Gateway

- Regenerate proto files with buf generate
- Add chat_app_service.connect.go for Connect RPC

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement webhook message processing

- Add credential lookup by PlatformUserID to find DivineSense user
- Add credential enabled check
- Implement asynchronous message processing (non-blocking webhook response)
- Add processChatAppMessage for AI routing (stub for future implementation)

The webhook now:
1. Validates the incoming request
2. Parses the message using channel-specific parser
3. Looks up the user credential by platform user ID
4. Returns immediately with success (async processing)
5. Processes the message in background (stub for AI routing)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): complete DingTalk channel implementation

- Add HTTP client for API calls
- Add access token caching with thread-safe double-check locking
- Token expires 5 minutes early to avoid edge cases

- `sendText()`: Send text messages via webhook
- `sendMedia()`: Send media messages (placeholder with text fallback)
- `sendWebhook()`: HTTP POST to DingTalk webhook with error handling
- `GetAccessToken()`: Fetch and cache access tokens (2hr expiry)
- `DownloadMedia()`: Download media using downloadCode

- Implements DingTalk signature validation (HMAC-SHA256)
- Supports webhook-based outgoing messages
- Uses context with timeout for all HTTP requests
- Proper error handling with structured logging

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): add frontend Chat Apps settings panel

- Create ChatAppsSection component in `web/src/components/Settings/ChatAppsSection.tsx`
- Add chat apps account management UI with:
  - List existing credentials with platform labels
  - Enable/disable toggle
  - Delete credential button
  - Webhook info display

- Platform selection (Telegram, WhatsApp, DingTalk)
- Platform user ID input with hints
- Access token input (password type)
- Webhook URL input (DingTalk only)
- Platform-specific help text

- Add "chat-apps" to BASIC_SECTIONS (available to all users)
- Add MessageSquare icon for the section
- Render ChatAppsSection in Setting.tsx

- Add English translations in `en.json`
- Add Chinese translations in `zh-Hans.json`
- Includes all labels, hints, and error messages

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement WhatsApp Baileys bridge service

Create Node.js bridge service for WhatsApp integration using Baileys library.

Features:
- Express HTTP server with health check endpoint
- WhatsApp Web API connection via Baileys
- QR code pairing for WhatsApp authentication
- Message forwarding from WhatsApp to DivineSense webhook
- Send message endpoint for DivineSense to WhatsApp
- Media download endpoint
- Auto-reconnection on connection loss
- Environment-based configuration

Files added:
- plugin/chat_apps/channels/whatsapp/bridge/package.json
- plugin/chat_apps/channels/whatsapp/bridge/src/index.js
- plugin/chat_apps/channels/whatsapp/bridge/README.md

The bridge service runs as a standalone Node.js process and communicates
with DivineSense via HTTP endpoints. This architecture is required because
the Baileys library only works in a Node.js runtime.

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(chat-apps): format DingTalk channel code

* lint(chat-apps): fix golangci-lint issues

- Use double %%w for error wrapping in DownloadMedia
- Add rows.Err() check in ListCredentials

Fixes:
- errorlint: non-wrapping format verb for fmt.Errorf
- rowserrcheck: rows.Err must be checked

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* lint(chat-apps): fix frontend lint and i18n issues

- Fix Platform enum usage (TELEGRAM not PLATFORM_TELEGRAM)
- Remove unused imports (Checkbox, AlertDialogAction, useToast)
- Change AlertDialog to Dialog (standard component)
- Add useEffect for proper lifecycle
- Add inline error display instead of toast
- Fix duplicate i18n keys in en.json and zh-Hans.json
  - Remove duplicate 'chat-apps' string key
  - Remove duplicate 'webhook-url' key
  - Remove duplicate 'storage'/'storage-section' keys
- Format code with Biome

Fixes:
- TypeScript enum access errors
- Biome import organization issues
- Duplicate object keys in locale files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): add comprehensive user manual

Complete zero-barrier entry guide for Chat Apps integration:
- Feature introduction and platform comparison
- Detailed Telegram, WhatsApp, DingTalk setup guides
- Step-by-step instructions with examples
- Troubleshooting section with common issues
- Security best practices
- Advanced configuration options

File: docs/user-guides/CHAT_APPS.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): complete Telegram, DingTalk, and WhatsApp integration

This commit implements multi-platform chat app integration, allowing
users to interact with DivineSense AI agents through Telegram, DingTalk,
and WhatsApp.

Features:
- Register/list/delete chat app credentials
- Webhook endpoint for receiving messages (all 3 platforms)
- AI integration using AUTO agent routing
- Token encryption (AES-256-GCM) with fail-fast validation
- Frontend settings panel with i18n support
- WhatsApp via Baileys Node.js bridge service (complete implementation)
- Metrics tracking for webhook events

Code Quality Fixes:
- Fixed double close channel panic (goroutine owns channel close)
- Removed insecure plaintext fallback (fail-fast on missing encryption key)
- Consolidated duplicate functions (~100 lines removed)
- Fixed metrics tracking (moved after credential lookup)
- Added typed context key to prevent collisions

Documentation:
- Added comprehensive user guide (docs/guides/CHAT_APPS.md)
- Updated architecture docs with Chat Apps module
- Added database schema documentation for chat_app_credential table
- Added frontend component documentation for ChatAppsSection

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(chat-apps): format code with go fmt

Auto-formatted by pre-commit hook.

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* lint(chat-apps): fix golangci-lint issues

- Use fields in test to avoid unused warnings
- Remove unnecessary int64 conversion (messagesProcessed is already int64)
- Remove unused getAIResponse function and its imports (strings, sync)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): 完善用户手册和开发者手册

用户手册更新 (docs/user-guides/CHAT_APPS.md):
- 添加详细的平台配置步骤(Telegram/WhatsApp/钉钉)
- 新增架构说明和 QR 码配对流程
- 完善 FAQ 和故障排查章节
- 添加调试信息获取指南

开发者指南更新 (docs/guides/CHAT_APPS.md):
- 添加系统架构图和核心组件说明
- 完善数据模型和 API 端点文档
- 新增平台集成技术细节
- 添加安全机制、加密存储说明
- 完善开发调试和部署指南
- 新增扩展新平台的步骤指南

WhatsApp Bridge README 更新:
- 添加架构图和功能特性表格
- 完善 API 端点文档和请求示例
- 新增 PM2/Systemd/Docker 部署指南
- 添加故障排查章节
- 完善安全建议

其他修复:
- 修复 qrcode-terminal ES 模块导入问题

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(deploy): add WhatsApp Bridge deployment automation

This commit adds comprehensive deployment automation for the WhatsApp Bridge
service (Baileys), integrating it into the main installation workflow.

- Standalone deployment management script for WhatsApp Bridge
- Commands: install, start, stop, restart, status, logs, health, qr, backup, update, uninstall
- Supports both PM2 and systemd process managers
- Health check endpoint monitoring
- QR code display for WhatsApp pairing

- Docker Compose configuration including DivineSense, PostgreSQL, and Baileys Bridge
- Health checks for all services
- Proper networking and volume management

- PM2 ecosystem configuration for process management
- Automatic restart, logging, resource limits
- Health check integration

- systemd service file for production deployment
- Security hardening (NoNewPrivileges, ProtectSystem)
- Resource limits (512M memory, 50% CPU)

- Environment configuration template
- Documentation for all configuration options

- Added INSTALL_WHATSAPP variable to interactive wizard
- Added --whatsapp command-line flag
- Integrated WhatsApp Bridge installation into both binary and docker modes
- Added help text for WhatsApp Bridge option

- Added WhatsApp Bridge management commands to user Makefile
- Added sudoers entries for baileys-bridge.sh and baileys-bridge.service
- Added bash aliases: ds-wa-status, ds-wa-qr, ds-wa-logs, ds-wa-install
- Fixed systemd service user from 'divinesense' to 'divine'

```bash
curl -fsSL https://raw.githubusercontent.com/hrygo/divinesense/main/deploy/install.sh | sudo bash -s -- --interactive

curl -fsSL ... | sudo bash -s -- --whatsapp
```

```bash
make whatsapp-status   # Check bridge status
make whatsapp-qr       # Display QR code for pairing
make whatsapp-logs     # View logs
ds-wa-status          # Shortcut alias
```

Resolves #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(deploy): security hardening and error handling improvements

This commit addresses security and reliability issues identified in code review.

- Added BRIDGE_API_KEY environment variable for protecting sensitive endpoints
- /send and /download endpoints now support optional API key auth via X-Bridge-Api-Key header
- When BRIDGE_API_KEY is set, requests must include valid API key

- Added ALLOWED_ORIGINS environment variable
- Default behavior unchanged (*), but production can now restrict origins
- Documented in .env.example with examples

- baileys-bridge.sh now checks health check return value
- Installation shows warning if service fails to start
- Provides troubleshooting hints on failure

- Added explicit log message when copying bridge files
- Sets correct ownership (divine:divine) after copy
- Warns if source directory not found

- Added BindsTo=divinesense.service to baileys-bridge.service
- Ensures bridge restarts when DivineSense restarts
- Prevents orphaned bridge service

- Installation now distinguishes between success and failure
- Shows manual installation command on failure
- Webhook URL template warns against using localhost in production

- Updated all configuration files (.env.example, ecosystem.config.cjs,
  baileys-bridge.service, with-whatsapp.yml) to include new security
  environment variables
- Added .gitignore to exclude Baileys auth data directory

Resolves code review findings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(i18n): add missing English translations for SSO settings

Add missing translation keys in en.json for SSO section:
- custom
- delete-sso
- disabled-password-login-warning
- display-name
- identifier-filter
- no-sso-found
- redirect-url
- scopes
- single-sign-on
- sso-created
- sso-list
- sso-updated
- template
- token-endpoint
- update-sso
- user-endpoint

These keys existed in zh-Hans.json but were missing in en.json,
causing TypeScript type errors during lint checks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(chat-apps): address security and concurrency issues from code review

- Add input validation (platform whitelist, length limits) in store layer
- Add startup validation for DIVINESENSE_CHAT_APPS_SECRET_KEY
- Fix DingTalk token cache race condition (RWMutex → Mutex)
- Add timestamp validation to DingTalk webhook signature (prevent replay)
- Improve WhatsApp Bridge health check (verify connection status)
- Update media upload fallback behavior with clear logging

Security improvements:
- MaxPlatformUserID: 255, MaxAccessToken: 2048, MaxAppSecret: 2048
- Webhook timestamp window: 5 minutes with clock skew tolerance
- Fail-fast on missing/invalid encryption key at service startup

Refs #64

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): complete documentation for v6.1 release

- Add Chat Apps architecture section to ARCHITECTURE.md
- Update BACKEND_DB.md with security details (input validation, webhook security)
- Enhance CHAT_APPS.md developer guide with security mechanisms
- Add comprehensive release notes for v6.1

Documentation highlights:
- Security: AES-256-GCM encryption, startup validation, input limits
- Webhook security: HMAC-SHA256 + timestamp validation (5-min window)
- Concurrency safety: fixed token cache race condition
- Architecture diagrams and data flow documentation

Related: #64 #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(release): fix issue link in v6.1 release notes

- Fix Issue link from #63 to #53 (correct issue number)
- Include previous code fixes and documentation updates

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(i18n): add missing chat-apps translation keys

- Add all required translation keys for Chat Apps settings
- Remove duplicate chat-apps section in locale files
- Fix code formatting issues

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(proto): format protobuf files with buf

- Apply buf format to chat_app_service.proto files
- Collapse multi-line http options to single line
- Fix import/option ordering

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(settings): add Chat Apps section menu item display

- Use .title suffix for chat-apps menu label
- Fixes missing Chat Apps entry in settings dropdown

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(settings): use .title suffix for chat-apps in sidebar menu too

- Apply same fix to SectionMenuItem component
- Both desktop and mobile menus now display "Chat Apps" correctly

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(env): add Chat Apps configuration to .env.example

- Document DIVINESENSE_CHAT_APPS_SECRET_KEY requirement
- Add instructions for generating encryption key

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): add missing INSTANCE_URL and WHATSAPP_BRIDGE_URL env vars

- Add DIVINESENSE_INSTANCE_URL for webhook URL generation
- Add DIVINESENSE_WHATSAPP_BRIDGE_URL for optional WhatsApp bridge
- Document both variables in .env.example with usage descriptions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(deploy): add Chat Apps env vars to production config template

- Add DIVINESENSE_CHAT_APPS_SECRET_KEY for token encryption
- Add DIVINESENSE_WHATSAPP_BRIDGE_URL for optional WhatsApp bridge
- Keep in sync with root .env.example

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: 黄飞虹 <aaronwong1989@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
hrygo added a commit that referenced this pull request Feb 5, 2026
* ci: trigger workflow run

* feat(chat-apps): add Telegram, DingTalk, and WhatsApp integration (#64)

* feat(chat-apps): add foundation for multi-platform chat apps integration

Phase 1 of #53: Infrastructure setup for Telegram, WhatsApp, DingTalk

- Add ChatChannel interface for platform abstraction
- Add proto definitions for ChatAppService (API + Store)
- Add database migrations for chat_app_credential table
- Add channel_type column to conversation_context
- Implement skeleton for Telegram, WhatsApp, DingTalk channels
- Add media processing interface (Whisper OCR placeholder)
- Add token encryption utilities for secure credential storage

Created files:
- docs/specs/chat-apps-integration.md (technical specification)
- proto/api/v1/chat_app_service.proto
- proto/store/chat_app_service.proto
- plugin/chat_apps/ (channels, media, store)
- store/migration/postgres/20260203_*.sql

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat_apps): complete Telegram channel DownloadMedia + QA improvements

- Implement Telegram media download with HTTP client
- Add RWMutex to ChannelRouter for concurrent safety
- Configure HTTP client timeout and connection pool
- Add structured logging (log/slog) to store and channels
- Enhance Telegram webhook verification (method, content-type)
- Fix string concatenation in SendChunkedMessage (use strings.Builder)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement ChatAppService handlers and complete Telegram DownloadMedia

- Complete DownloadMedia implementation with HTTP download
- Add HTTP client to TelegramChannel struct
- Fix file.Link() method call (requires bot token parameter)
- Add proper error handling and MIME type detection

- Remove google.api.http annotations (store layer doesn't need HTTP)
- Add google.protobuf.Empty import

- Implement all 7 ChatAppService RPC methods:
  - RegisterCredential: bind chat app account with encryption
  - ListCredentials: list user's chat app bindings
  - DeleteCredential: remove binding with ownership check
  - UpdateCredential: modify access token/webhook URL
  - HandleWebhook: process incoming webhook events
  - SendMessage: send messages to chat platforms
  - GetWebhookInfo: return webhook setup instructions
- Add conversion functions between proto and internal types
- Add ChannelRegistry interface for channel management
- Integrate with Store.GetDriver().GetDB() for database access
- Use os.Getenv() for environment variable access

- Add UnimplementedChatAppServiceServer embedding
- Register ChatAppService with gRPC-Gateway

- Regenerate proto files with buf generate
- Add chat_app_service.connect.go for Connect RPC

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement webhook message processing

- Add credential lookup by PlatformUserID to find DivineSense user
- Add credential enabled check
- Implement asynchronous message processing (non-blocking webhook response)
- Add processChatAppMessage for AI routing (stub for future implementation)

The webhook now:
1. Validates the incoming request
2. Parses the message using channel-specific parser
3. Looks up the user credential by platform user ID
4. Returns immediately with success (async processing)
5. Processes the message in background (stub for AI routing)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): complete DingTalk channel implementation

- Add HTTP client for API calls
- Add access token caching with thread-safe double-check locking
- Token expires 5 minutes early to avoid edge cases

- `sendText()`: Send text messages via webhook
- `sendMedia()`: Send media messages (placeholder with text fallback)
- `sendWebhook()`: HTTP POST to DingTalk webhook with error handling
- `GetAccessToken()`: Fetch and cache access tokens (2hr expiry)
- `DownloadMedia()`: Download media using downloadCode

- Implements DingTalk signature validation (HMAC-SHA256)
- Supports webhook-based outgoing messages
- Uses context with timeout for all HTTP requests
- Proper error handling with structured logging

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): add frontend Chat Apps settings panel

- Create ChatAppsSection component in `web/src/components/Settings/ChatAppsSection.tsx`
- Add chat apps account management UI with:
  - List existing credentials with platform labels
  - Enable/disable toggle
  - Delete credential button
  - Webhook info display

- Platform selection (Telegram, WhatsApp, DingTalk)
- Platform user ID input with hints
- Access token input (password type)
- Webhook URL input (DingTalk only)
- Platform-specific help text

- Add "chat-apps" to BASIC_SECTIONS (available to all users)
- Add MessageSquare icon for the section
- Render ChatAppsSection in Setting.tsx

- Add English translations in `en.json`
- Add Chinese translations in `zh-Hans.json`
- Includes all labels, hints, and error messages

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): implement WhatsApp Baileys bridge service

Create Node.js bridge service for WhatsApp integration using Baileys library.

Features:
- Express HTTP server with health check endpoint
- WhatsApp Web API connection via Baileys
- QR code pairing for WhatsApp authentication
- Message forwarding from WhatsApp to DivineSense webhook
- Send message endpoint for DivineSense to WhatsApp
- Media download endpoint
- Auto-reconnection on connection loss
- Environment-based configuration

Files added:
- plugin/chat_apps/channels/whatsapp/bridge/package.json
- plugin/chat_apps/channels/whatsapp/bridge/src/index.js
- plugin/chat_apps/channels/whatsapp/bridge/README.md

The bridge service runs as a standalone Node.js process and communicates
with DivineSense via HTTP endpoints. This architecture is required because
the Baileys library only works in a Node.js runtime.

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(chat-apps): format DingTalk channel code

* lint(chat-apps): fix golangci-lint issues

- Use double %%w for error wrapping in DownloadMedia
- Add rows.Err() check in ListCredentials

Fixes:
- errorlint: non-wrapping format verb for fmt.Errorf
- rowserrcheck: rows.Err must be checked

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* lint(chat-apps): fix frontend lint and i18n issues

- Fix Platform enum usage (TELEGRAM not PLATFORM_TELEGRAM)
- Remove unused imports (Checkbox, AlertDialogAction, useToast)
- Change AlertDialog to Dialog (standard component)
- Add useEffect for proper lifecycle
- Add inline error display instead of toast
- Fix duplicate i18n keys in en.json and zh-Hans.json
  - Remove duplicate 'chat-apps' string key
  - Remove duplicate 'webhook-url' key
  - Remove duplicate 'storage'/'storage-section' keys
- Format code with Biome

Fixes:
- TypeScript enum access errors
- Biome import organization issues
- Duplicate object keys in locale files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): add comprehensive user manual

Complete zero-barrier entry guide for Chat Apps integration:
- Feature introduction and platform comparison
- Detailed Telegram, WhatsApp, DingTalk setup guides
- Step-by-step instructions with examples
- Troubleshooting section with common issues
- Security best practices
- Advanced configuration options

File: docs/user-guides/CHAT_APPS.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(chat-apps): complete Telegram, DingTalk, and WhatsApp integration

This commit implements multi-platform chat app integration, allowing
users to interact with DivineSense AI agents through Telegram, DingTalk,
and WhatsApp.

Features:
- Register/list/delete chat app credentials
- Webhook endpoint for receiving messages (all 3 platforms)
- AI integration using AUTO agent routing
- Token encryption (AES-256-GCM) with fail-fast validation
- Frontend settings panel with i18n support
- WhatsApp via Baileys Node.js bridge service (complete implementation)
- Metrics tracking for webhook events

Code Quality Fixes:
- Fixed double close channel panic (goroutine owns channel close)
- Removed insecure plaintext fallback (fail-fast on missing encryption key)
- Consolidated duplicate functions (~100 lines removed)
- Fixed metrics tracking (moved after credential lookup)
- Added typed context key to prevent collisions

Documentation:
- Added comprehensive user guide (docs/guides/CHAT_APPS.md)
- Updated architecture docs with Chat Apps module
- Added database schema documentation for chat_app_credential table
- Added frontend component documentation for ChatAppsSection

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(chat-apps): format code with go fmt

Auto-formatted by pre-commit hook.

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* lint(chat-apps): fix golangci-lint issues

- Use fields in test to avoid unused warnings
- Remove unnecessary int64 conversion (messagesProcessed is already int64)
- Remove unused getAIResponse function and its imports (strings, sync)

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): 完善用户手册和开发者手册

用户手册更新 (docs/user-guides/CHAT_APPS.md):
- 添加详细的平台配置步骤(Telegram/WhatsApp/钉钉)
- 新增架构说明和 QR 码配对流程
- 完善 FAQ 和故障排查章节
- 添加调试信息获取指南

开发者指南更新 (docs/guides/CHAT_APPS.md):
- 添加系统架构图和核心组件说明
- 完善数据模型和 API 端点文档
- 新增平台集成技术细节
- 添加安全机制、加密存储说明
- 完善开发调试和部署指南
- 新增扩展新平台的步骤指南

WhatsApp Bridge README 更新:
- 添加架构图和功能特性表格
- 完善 API 端点文档和请求示例
- 新增 PM2/Systemd/Docker 部署指南
- 添加故障排查章节
- 完善安全建议

其他修复:
- 修复 qrcode-terminal ES 模块导入问题

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(deploy): add WhatsApp Bridge deployment automation

This commit adds comprehensive deployment automation for the WhatsApp Bridge
service (Baileys), integrating it into the main installation workflow.

- Standalone deployment management script for WhatsApp Bridge
- Commands: install, start, stop, restart, status, logs, health, qr, backup, update, uninstall
- Supports both PM2 and systemd process managers
- Health check endpoint monitoring
- QR code display for WhatsApp pairing

- Docker Compose configuration including DivineSense, PostgreSQL, and Baileys Bridge
- Health checks for all services
- Proper networking and volume management

- PM2 ecosystem configuration for process management
- Automatic restart, logging, resource limits
- Health check integration

- systemd service file for production deployment
- Security hardening (NoNewPrivileges, ProtectSystem)
- Resource limits (512M memory, 50% CPU)

- Environment configuration template
- Documentation for all configuration options

- Added INSTALL_WHATSAPP variable to interactive wizard
- Added --whatsapp command-line flag
- Integrated WhatsApp Bridge installation into both binary and docker modes
- Added help text for WhatsApp Bridge option

- Added WhatsApp Bridge management commands to user Makefile
- Added sudoers entries for baileys-bridge.sh and baileys-bridge.service
- Added bash aliases: ds-wa-status, ds-wa-qr, ds-wa-logs, ds-wa-install
- Fixed systemd service user from 'divinesense' to 'divine'

```bash
curl -fsSL https://raw.githubusercontent.com/hrygo/divinesense/main/deploy/install.sh | sudo bash -s -- --interactive

curl -fsSL ... | sudo bash -s -- --whatsapp
```

```bash
make whatsapp-status   # Check bridge status
make whatsapp-qr       # Display QR code for pairing
make whatsapp-logs     # View logs
ds-wa-status          # Shortcut alias
```

Resolves #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(deploy): security hardening and error handling improvements

This commit addresses security and reliability issues identified in code review.

- Added BRIDGE_API_KEY environment variable for protecting sensitive endpoints
- /send and /download endpoints now support optional API key auth via X-Bridge-Api-Key header
- When BRIDGE_API_KEY is set, requests must include valid API key

- Added ALLOWED_ORIGINS environment variable
- Default behavior unchanged (*), but production can now restrict origins
- Documented in .env.example with examples

- baileys-bridge.sh now checks health check return value
- Installation shows warning if service fails to start
- Provides troubleshooting hints on failure

- Added explicit log message when copying bridge files
- Sets correct ownership (divine:divine) after copy
- Warns if source directory not found

- Added BindsTo=divinesense.service to baileys-bridge.service
- Ensures bridge restarts when DivineSense restarts
- Prevents orphaned bridge service

- Installation now distinguishes between success and failure
- Shows manual installation command on failure
- Webhook URL template warns against using localhost in production

- Updated all configuration files (.env.example, ecosystem.config.cjs,
  baileys-bridge.service, with-whatsapp.yml) to include new security
  environment variables
- Added .gitignore to exclude Baileys auth data directory

Resolves code review findings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(i18n): add missing English translations for SSO settings

Add missing translation keys in en.json for SSO section:
- custom
- delete-sso
- disabled-password-login-warning
- display-name
- identifier-filter
- no-sso-found
- redirect-url
- scopes
- single-sign-on
- sso-created
- sso-list
- sso-updated
- template
- token-endpoint
- update-sso
- user-endpoint

These keys existed in zh-Hans.json but were missing in en.json,
causing TypeScript type errors during lint checks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(chat-apps): address security and concurrency issues from code review

- Add input validation (platform whitelist, length limits) in store layer
- Add startup validation for DIVINESENSE_CHAT_APPS_SECRET_KEY
- Fix DingTalk token cache race condition (RWMutex → Mutex)
- Add timestamp validation to DingTalk webhook signature (prevent replay)
- Improve WhatsApp Bridge health check (verify connection status)
- Update media upload fallback behavior with clear logging

Security improvements:
- MaxPlatformUserID: 255, MaxAccessToken: 2048, MaxAppSecret: 2048
- Webhook timestamp window: 5 minutes with clock skew tolerance
- Fail-fast on missing/invalid encryption key at service startup

Refs #64

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): complete documentation for v6.1 release

- Add Chat Apps architecture section to ARCHITECTURE.md
- Update BACKEND_DB.md with security details (input validation, webhook security)
- Enhance CHAT_APPS.md developer guide with security mechanisms
- Add comprehensive release notes for v6.1

Documentation highlights:
- Security: AES-256-GCM encryption, startup validation, input limits
- Webhook security: HMAC-SHA256 + timestamp validation (5-min window)
- Concurrency safety: fixed token cache race condition
- Architecture diagrams and data flow documentation

Related: #64 #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(release): fix issue link in v6.1 release notes

- Fix Issue link from #63 to #53 (correct issue number)
- Include previous code fixes and documentation updates

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(i18n): add missing chat-apps translation keys

- Add all required translation keys for Chat Apps settings
- Remove duplicate chat-apps section in locale files
- Fix code formatting issues

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(proto): format protobuf files with buf

- Apply buf format to chat_app_service.proto files
- Collapse multi-line http options to single line
- Fix import/option ordering

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(settings): add Chat Apps section menu item display

- Use .title suffix for chat-apps menu label
- Fixes missing Chat Apps entry in settings dropdown

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(settings): use .title suffix for chat-apps in sidebar menu too

- Apply same fix to SectionMenuItem component
- Both desktop and mobile menus now display "Chat Apps" correctly

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(env): add Chat Apps configuration to .env.example

- Document DIVINESENSE_CHAT_APPS_SECRET_KEY requirement
- Add instructions for generating encryption key

Refs #53

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(chat-apps): add missing INSTANCE_URL and WHATSAPP_BRIDGE_URL env vars

- Add DIVINESENSE_INSTANCE_URL for webhook URL generation
- Add DIVINESENSE_WHATSAPP_BRIDGE_URL for optional WhatsApp bridge
- Document both variables in .env.example with usage descriptions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(deploy): add Chat Apps env vars to production config template

- Add DIVINESENSE_CHAT_APPS_SECRET_KEY for token encryption
- Add DIVINESENSE_WHATSAPP_BRIDGE_URL for optional WhatsApp bridge
- Keep in sync with root .env.example

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: 黄飞虹 <aaronwong1989@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): implement Unified Block Model (Issue #71)

This PR implements the Unified Block Model to consolidate data storage
for Normal/Geek/Evolution AI modes into a single Block-based structure.

Phase 1: Database & Store
- Add ai_block table with JSONB for flexible data storage
- Implement AIBlockStore with full CRUD operations
- Add migration for PostgreSQL (SQLite stub for compatibility)

Phase 2: Proto & API
- Add Block message types to ai_service.proto
- Add Block-related RPC methods (List/Get/Create/Update/Delete)
- Implement gRPC handlers with authentication and ownership checks
- Add Connect RPC wrappers

Phase 3: Frontend Types
- Create block.ts with type definitions and utility functions
- Add type guards and constants for BlockType/BlockMode/BlockStatus

Phase 4: Frontend Hooks
- Create useBlockQueries.ts with React Query hooks
- Implement hooks for all Block operations

Phase 5: Chat Handler Integration
- Create BlockManager for Block lifecycle management
- Integrate with existing chat handlers

Phase 6: Testing
- Add unit tests for PostgreSQL AIBlockStore
- Integration tests (require database setup)

Resolves #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ai): remove unused code and fix lint issues

- Remove unused convertAgentTypeToBlockMode function
- Remove unused formatMetadata function from block_manager
- Remove unused encoding/json import
- Fix nil check on map (len() handles nil correctly)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): optimize Unified Block Model implementation

Backend optimizations:
- Add database trigger for auto-increment round_number (eliminates extra query)
- Add AppendEventsBatch method for efficient event streaming
- Add CompleteBlock transaction method for atomicity
- Optimize database indexes (composite, GIN with jsonb_path_ops, partial)

Frontend optimizations:
- Add React Query cache configuration with staleTime/gcTime
- Implement optimistic updates with rollback support
- Add comprehensive error handling system (blockErrors.ts)
- Add useBlockStream hook for efficient streaming
- Add usePrefetchBlock hook for data preloading

DevOps:
- Set up GitHub branch protection (reject force push, reject deletion)

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): complete Unified Block Model Phase 4-6

Complete implementation of the Unified Block Model for AI chat:

Phase 4 (Frontend):
- ChatMessages.tsx: Support AIBlock[] data structure with backward compatibility
- AIChatContext: Add loadBlocks, appendUserInput, updateBlockStatus methods
- block.ts: Add blockModeToParrotAgentType() helper function
- Clean up: Remove unused useBlockStream.ts and blockErrors.ts

Phase 5 (Backend Integration):
- handler.go: Integrate BlockManager into ParrotHandler streaming flow
  - Create Block at chat start with proper mode (normal/geek/evolution)
  - Append events asynchronously during streaming
  - Complete or mark error on Block at stream end
- ai_service_chat.go: Wire up BlockManager in createChatHandler()

Phase 6 (Tests):
- Add block_manager_test.go with 13 test cases
  - Block creation (normal, geek, evolution modes)
  - Event appending (single and batch)
  - Status updates and completion
  - Error handling
  - All tests passing

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): integrate Block API in frontend (Issue #71)

Phase 4: Frontend integration of Unified Block Model

- AIChat.tsx now uses useBlocks() hook to load AIBlock[] data
- Added block_id to ChatResponse proto for streaming updates
- Backend handler sends block_id in all ChatResponse messages
- Frontend useChat hook invalidates blocks cache on block_id event
- Regenerated proto types for Go and TypeScript

Changes:
- proto/api/v1/ai_service.proto: Add block_id field (field 10)
- server/router/api/v1/ai/handler.go: Include BlockId in all stream responses
- web/src/pages/AIChat.tsx: Use useBlocks() hook and pass blocks to ChatMessages
- web/src/hooks/useAIQueries.ts: Handle block_id events, invalidate blocks cache
- proto/gen/*: Regenerated proto types

This connects the frontend to the existing Block API, enabling
real-time Block updates during streaming chat.

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): add Block append user input and error fallback (Issue #71 P1)

Phase 4 enhancements for Unified Block Model:

1. **追加用户输入到 Block** (Append User Input to Block)
   - AIChat.tsx detects streaming Block state when user sends message
   - Calls appendUserInput() API to append to current Block instead of creating new message
   - Added isActiveStatus import from block.ts for Block status detection

2. **错误处理回退** (Error Handling & Fallback)
   - Added useBlocksWithFallback() hook in useBlockQueries.ts
   - Returns shouldFallback flag when Block API fails or returns empty
   - AIChat.tsx uses fallback mode to display ChatItem[] when Block API unavailable
   - Ensures UI remains functional even when Block backend is down

Changes:
- web/src/pages/AIChat.tsx: Import isActiveStatus, appendUserInput, loadBlocks
- web/src/pages/AIChat.tsx: Detect streaming Block and append user input
- web/src/pages/AIChat.tsx: Use useBlocksWithFallback() with error fallback
- web/src/hooks/useBlockQueries.ts: Add useBlocksWithFallback() hook
- docs/specs/block-design: Update documentation

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): implement Unified Block Model (Issue #71) (#78)

* docs(research): add layout spacing unification research report

- Analyze current layout spacing inconsistencies across all pages
- Define unified spacing specification (mobile: pt-4, desktop: pt-6)
- Document sidebar width standardization (w-72 = 288px)
- Create implementation roadmap with file change list

Refs #74

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): implement Unified Block Model (Issue #71)

This PR implements the Unified Block Model to consolidate data storage
for Normal/Geek/Evolution AI modes into a single Block-based structure.

Phase 1: Database & Store
- Add ai_block table with JSONB for flexible data storage
- Implement AIBlockStore with full CRUD operations
- Add migration for PostgreSQL (SQLite stub for compatibility)

Phase 2: Proto & API
- Add Block message types to ai_service.proto
- Add Block-related RPC methods (List/Get/Create/Update/Delete)
- Implement gRPC handlers with authentication and ownership checks
- Add Connect RPC wrappers

Phase 3: Frontend Types
- Create block.ts with type definitions and utility functions
- Add type guards and constants for BlockType/BlockMode/BlockStatus

Phase 4: Frontend Hooks
- Create useBlockQueries.ts with React Query hooks
- Implement hooks for all Block operations

Phase 5: Chat Handler Integration
- Create BlockManager for Block lifecycle management
- Integrate with existing chat handlers

Phase 6: Testing
- Add unit tests for PostgreSQL AIBlockStore
- Integration tests (require database setup)

Resolves #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ai): remove unused code and fix lint issues

- Remove unused convertAgentTypeToBlockMode function
- Remove unused formatMetadata function from block_manager
- Remove unused encoding/json import
- Fix nil check on map (len() handles nil correctly)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(frontend): resolve TypeScript lint issues

- Fix proto enum references (BlockMode.NORMAL vs BLOCK_MODE_NORMAL)
- Fix bigint to number conversion for id fields
- Reorganize imports to satisfy Biome linter
- Update type guards to handle both enum and string types

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): optimize Unified Block Model implementation

Backend optimizations:
- Add database trigger for auto-increment round_number (eliminates extra query)
- Add AppendEventsBatch method for efficient event streaming
- Add CompleteBlock transaction method for atomicity
- Optimize database indexes (composite, GIN with jsonb_path_ops, partial)

Frontend optimizations:
- Add React Query cache configuration with staleTime/gcTime
- Implement optimistic updates with rollback support
- Add comprehensive error handling system (blockErrors.ts)
- Add useBlockStream hook for efficient streaming
- Add usePrefetchBlock hook for data preloading

DevOps:
- Set up GitHub branch protection (reject force push, reject deletion)

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): complete Unified Block Model Phase 4-6

Complete implementation of the Unified Block Model for AI chat:

Phase 4 (Frontend):
- ChatMessages.tsx: Support AIBlock[] data structure with backward compatibility
- AIChatContext: Add loadBlocks, appendUserInput, updateBlockStatus methods
- block.ts: Add blockModeToParrotAgentType() helper function
- Clean up: Remove unused useBlockStream.ts and blockErrors.ts

Phase 5 (Backend Integration):
- handler.go: Integrate BlockManager into ParrotHandler streaming flow
  - Create Block at chat start with proper mode (normal/geek/evolution)
  - Append events asynchronously during streaming
  - Complete or mark error on Block at stream end
- ai_service_chat.go: Wire up BlockManager in createChatHandler()

Phase 6 (Tests):
- Add block_manager_test.go with 13 test cases
  - Block creation (normal, geek, evolution modes)
  - Event appending (single and batch)
  - Status updates and completion
  - Error handling
  - All tests passing

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ai): remove tautological nil check for sessionSummary

sessionSummary is always non-nil (created as pointer to struct literal),
so the nil check is redundant. Remove it to satisfy golangci-lint.

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(ai): fix code quality issues from code review

- Simplify redundant switch statement in block_manager.go (all branches return same value)
- Remove unused GIN index on event_stream (no query by event content exists)
- Fix enum comparison in ChatMessages (use strict equality instead of String/includes)
- Update schema version comment to remove misleading "Phase 1" reference

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style(proto): fix proto file formatting for buf linter

Align comments to single space indentation for buf format compliance.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: reorganize specification documents and fix optimistic UI

- Reorganized Unified Block Model specs into docs/specs/block-design/
- Archived Phase 1-6 implementation specs in archived/ subfolder
- Updated main documentation indexes (INDEX.md, README.md)
- Fixed broken relative links in documentation
- Fixed optimistic UI update logic in useCreateBlock hook
- Added joint-audit-report.md and improvement.md for block model

* feat: implement timestamp normalization and tree-like branching foundations

- Normalized all conversation timestamps to milliseconds (Postgres & Go)
- Added parent_block_id to ai_block table for tree-branching support
- Updated protobuf definitions for block structure extension
- Optimized block storage and conversation summarization logic
- Synchronized frontend dependencies

* refactor(ai): remove GenUI functionality from normal mode agents

Remove Generative UI (GenUI) feature from three normal mode agents:
- MemoParrot (灰灰) - removed ui_memo_preview event
- SchedulerAgentV2 (时巧) - removed wrapUICallback system and UI events
- AmazingParrot (折衷) - removed ui_memo_preview and ui_schedule_list events

Backend changes:
- ai/agent/amazing_parrot.go: removed uiPreviewCardLimit and UI event generation
- ai/agent/memo_parrot.go: removed ui_memo_preview event generation
- ai/agent/scheduler_v2.go: removed wrapUICallback and 5 helper functions
- ai/agent/scheduler_test.go: updated test expectations

Frontend changes:
- Deleted web/src/components/ScheduleAI/ directory (16 GenUI components)
- Deleted web/src/hooks/useAITools.ts
- Removed uiTools props and handlers from AIChat.tsx, ChatMessages.tsx, Schedule.tsx
- Simplified useScheduleAgent.ts, useScheduleQueries.ts, useAIQueries.ts
- Created simplified StreamingFeedback.tsx for ScheduleQuickInput

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(schedule): i18n optimization for StreamingFeedback component

Replace hardcoded English text with i18n keys:
- schedule.ai.creating-schedule
- schedule.ai.checking-schedule
- schedule.ai.updating-schedule
- schedule.ai.finding-free-time
- schedule.ai.thinking
- schedule.ai.processing
- schedule.ai.using-tool

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ai): add event transformers and improve test comments

- Add eventTransformers.ts with utilities for extracting ThinkingStep
  and ToolCall from BlockEvent[] stream
- Improve scheduler_test.go comments explaining callback mechanism
  and why FindSchedules is called twice during ExecuteWithCallback

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(proto): remove trailing whitespace in ai_service.proto

Fix buf format lint error by removing trailing spaces in comments.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: 黄飞虹 <aaronwong1989@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* docs(reports): add Unified Block Model gap analysis report

Comprehensive analysis of specification vs implementation for Issue #71.

Key findings:
- Implementation significantly ahead of documentation
- Phases 1-5 complete (83%), Phase 6 partially done
- Only real gap: frontend unit tests

Report location: docs/reports/unified-block-model-gap-analysis-2026-02-05.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs(ai): add Unified Block Model runtime gap analysis (Issue #71)

根因分析报告,识别出运行时差距的关键问题:

P0 - 异步事件追加错误抑制
- handler.go:483-486 goroutine 忽略 AppendEvent 错误
- 导致 event_stream 刷新后为空
- 用户报告:"仅仅持久化了用户输入和最终模型返回消息"

P1 - 前端 Fallback 逻辑缺陷
- useBlockQueries.ts:627 空数组触发 shouldFallback
- 新会话强制回退到 items,无法使用 Block API

问题分析:
- Mode 正确持久化(数据库验证通过)
- event_stream 为空是异步错误抑制导致
- SessionSummary.mode 优先级可能导致主题随机变化

修复方案:
- 添加错误通道或同步追加
- 区分"新会话"和"API 失败"
- 添加数据库验证日志

Refs #71
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(ai): remove SessionSummary.mode, Block.mode is single source of truth

重构目标:移除 SessionSummary.mode,让 Block.mode 成为 Mode 的唯一载体。

变更:
1. proto/api/v1/ai_service.proto - 移除 SessionSummary.mode 字段
2. server/router/api/v1/ai/handler.go - 移除 mode 赋值逻辑
3. web/src/components/AIChat/ChatMessages.tsx - useEffectiveParrotId 只从 Block.mode 读取
4. web/src/types/parrot.ts - 移除 SessionSummary.mode 类型定义

问题解决:
- 前端主题不再随机变化
- 消除 SessionSummary.mode 与 Block.mode 的不一致性
- 统一数据来源,简化前端逻辑

新增文档:
- docs/specs/block-design/session-summary-positioning.md
  三种模式对比图解,SessionSummary 正确定位说明

Refs #71
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(ai): rename SessionSummary to BlockSummary, fix 1:1 relationship

- Rename proto message SessionSummary to BlockSummary (semantic clarity)
- Remove BlockSummary.mode field (Block.mode is single source of truth)
- Fix frontend: each Block now reads summary from its own sessionStats
- Add sessionStatsToBlockSummary() converter function
- Update MessageBlock interface: attachBlockSummary → blockSummary
- ChatMessagesProps.blockSummary now only for streaming block

This ensures Block and BlockSummary maintain a 1:1 relationship:
- Completed blocks: summary from Block.sessionStats (persisted in DB)
- Streaming block: summary from ChatResponse.blockSummary (real-time)

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ai): address code review issues from SessionSummary→BlockSummary rename

- P0: Add error logging to async AppendEvent (was suppressing errors)
- P1: Fix streamingBlockSummary condition (only apply to last streaming block)
- P2: Remove duplicate Chinese comments in handler.go

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(ai): extract message merge helpers and fix lint issues

Extract complex mergeMessagesIntoState (86 lines) into 5 pure functions
for better testability and readability. Fix multiple lint issues
discovered during code review.

Frontend refactor:
- Extract getMessageUid: Get unique identifier from ChatItem
- Extract findOptimisticMatch: Find local optimistic update to replace
- Extract replaceOptimisticMessage: Replace with metadata preservation
- Extract mergeMessageLists: Core merge logic with 3 strategies
- Simplify mergeMessagesIntoState from 86 to 30 lines (-65%)

Lint fixes:
- Add SessionStats import from @/types/block
- Fix totalCostUsd → totalCostUSD field name
- Fix totalInputTokens → inputTokens field mapping
- Fix SessionStats.status → isError conversion
- Fix loadMoreMessages dependency: convertMessageFromPb → convertBlockToChatItem

Backend monitoring:
- Add structured "metric" attribute to event persistence failure logs
  for monitoring/alerting systems

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ai): resolve code review issues and enable continuous messaging

Code review fixes (11 issues):
- P1: Fix race condition in block append (AIChat.tsx)
- P1: Add context.WithoutCancel for async goroutines (handler.go)
- P2: Add panic recovery in streaming goroutine (ai_service_chat.go)
- P2: Pre-allocate toolsUsed slice for performance
- P2: Use useMemo for actionDescription (ChatHeader.tsx)
- P2: Rename TOOL_CALL_OFFSET_MS → TOOL_CALL_OFFSET_US (constants.ts)
- P2: Fix type assertion in useBlockQueries.ts
- P3: Add AUTO to PARROT_AGENTS and fix parrotToProtoAgentType mapping
- P3: Simplify BLOCK_THEMES to use BlockMode only (NORMAL/GEEK/EVOLUTION)

Features:
- Remove isTyping restriction: allow sending messages at any time
- Messages append to streaming block when available

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(chat): display appended user inputs in UnifiedMessageBlock

Fix issue where appended user inputs (via appendUserInput API) were not
displayed in the UI. Now:

- Split Block.userInputs array: first as userMessage, rest as additionalUserInputs
- Pass additionalUserInputs to UnifiedMessageBlock component
- Add additionalUserInputs field to MessageBlock interface

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: remove accidentally committed large binary file

- Remove 67MB 'divinesense' binary from repository
- Add to .gitignore to prevent future accidental commits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: resolve conflict markers in ai_block.go

* fix: format sqlite.go

* fix: resolve conflict markers in useBlockQueries.ts

* fix: rename SessionSummary to BlockSummary in ChatMessages

* fix(block): correct isActiveStatus to use numeric enum comparison

BlockStatus enum values are numeric (PENDING=1, STREAMING=2),
but isActiveStatus was comparing string constants like
"BLOCK_STATUS_STREAMING" with numeric values, always returning false.

This caused streaming blocks to be incorrectly treated as inactive,
resulting in new blocks being created instead of appending user input
to the active streaming block.

- Change type signature to accept number type
- Convert status to numeric before comparison
- Compare against enum values (1=PENDING, 2=STREAMING) directly

Fixes Geek/Evolution mode user input appending issue.

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(ai): map AUTO agent type to DEFAULT proto type

AUTO agent type should map to DEFAULT proto type to trigger
backend routing. Previously it fell through to AMAZING.

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: prop name and unused variable in ChatMessages

* fix: rename sessionSummary to blockSummary in ChatMessagesProps

* style: format useEffectiveParrotId function signature

* refactor: fix code review issues from block integration

- Optimize translateThinkingSteps to skip array creation when no translation needed
- Update JSDoc comments: session summary → block summary (2 occurrences)
- Update inline comments for consistency
- Improve factory.go comment precision for AUTO → DEFAULT mapping

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: resolve P0-P1 code review issues from last 50 commits

- Fix UUID namespace collision in cc_runner.go (P0)
  - Use project-specific UUID namespace instead of DNS namespace
  - Prevents potential collision with other services

- Unify React Query cache keys with blockKeys factory (P1)
  - Import blockKeys in AIChatContext for consistent cache invalidation
  - Prevents stale data issues

- Optimize logo animation selector performance (P1)
  - Change from body-scoped to class-scoped selector
  - Add logo-animated class to NavigationDrawer img element

- Replace 'any' types with ApiError interface (P1)
  - Create web/src/config/errors.ts with type-safe error handling
  - Update useBlockQueries.ts to use ApiError instead of any

- Centralize config constants (P2)
  - Create web/src/config/chat.ts for chat-related constants
  - Replace magic numbers across codebase

- Remove unused variable (P2)
  - Remove unused isLoadingBlocks from AIChat.tsx destructuring

Refs #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: 黄飞虹 <aaronwong1989@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] Chat Apps 接入支持 (Telegram/WhatsApp/钉钉)

2 participants