Commit Graph
25 Commits
Author SHA1 Message Date
Rogeeandrogee 0e9bf8dc14 fix(shangwutong): close contact sync review gaps (#4)
Co-authored-by: Rogee <rogee@ipao.vip>
2026-08-13 01:21:07 +08:00
Rogeeandrogee 83a8ab315a H-16: align takeover with channel AI workflow (#2)
* feat(conversations): complete manual AI takeover

* fix(conversations): align AI takeover flow with channel AI

* fix(conversations): close takeover review gaps

---------

Co-authored-by: Rogee <rogee@ipao.vip>
2026-08-12 22:57:06 +08:00
Rogee 3d7ff5a6b1 chore: complete Shangwutong connector integration 2026-08-04 18:00:10 +08:00
Rogee 4611c0201f test: improve backend unit coverage 2026-08-04 12:26:25 +08:00
rogee 897b4e018f feat(channels): add Shangwutong connector 2026-08-03 10:13:40 +08:00
Rogee 1446cfe701 feat(channels): 社交渠道 OAuth 改进 + 集成应用重命名 + AI 流程文档
- Facebook/Instagram/TikTok 渠道 OAuth 授权流程改进
- 新增 oauth/credentialstore 包
- 集成应用 OpenAI 重命名为 OpenAI 兼容 (migration 061)
- 消息生命周期与 AI 流程架构文档
- inbox 管理界面 i18n 更新
2026-08-01 19:38:27 +08:00
Rogee 63df5b8b91 fix(captain): 试验场不查 FAQ 知识库 + 添加常见问题报 400
三个问题修复:

1. 添加常见问题报 400 (assistant_id 类型不匹配)
   - CreateResponseDialog.vue: route.params.assistantId 是字符串,
     传给后端 uint 字段导致 JSON 反序列化失败
   - 修复: Number(route.params.assistantId) 转为数字
   - 同时修复 POST /assistant_responses 无尾部斜杠 307 重定向问题

2. 试验场 playground 不做 RAG 检索
   - generatePlaygroundLLMResponse 只构建 system prompt + 对话历史,
     从不查 FAQ 知识库
   - 新增 retrieveFAQContext(): embed 用户问题 → pgvector 搜索 approved
     FAQ → 注入 system prompt
   - 受 feature_faq 配置开关控制

3. FAQ embedding 无法写入 (pgvector 序列化 + 维度问题)
   - pgvector stub 无 driver.Valuer, GORM Save() 报 SQLSTATE 42804
   - 新增 UpdateEmbedding() 用 ?::vector 原始 SQL 绕过
   - SimilaritySearch 排除 embedding 列 + 手动格式化向量字面量
   - embedding 列从 vector(1536) 改为 vector (跟随模型维度)
   - FAQ 创建/更新时自动索引 embedding (SetRAGService 注入)
2026-08-01 19:37:19 +08:00
Rogee cd82d079e3 fix(ws): 发送 WebSocket 协议级 Ping 控制帧防止 60s 后连接断开
writePump 只发 ActionCable 文本 JSON ping,从不发 websocket.PingMessage,
导致 readPump 的 PongHandler 永远不触发,ReadDeadline(60s) 到期后连接
被强制关闭。前端每 60 秒弹出"离线""重连"通知。

修复:在 ticker 中先发 PingMessage 控制帧(浏览器自动回 Pong 重置
ReadDeadline),再发 ActionCable 文本 ping(保活 ConnectionMonitor)。

同时包含此前会话中的其他变更:
- 移除安全设置(SAML)页面及路由
- 新增超级管理员控制台前端页面
- platform agent_bots 路由使用 Platform* handler
- 超级管理员入口改为 SPA 内路由跳转
2026-07-30 16:55:44 +08:00
Rogee 37e6d77a2d fix: 帮助中心设置页报 Feature 'knowledge_base' is not available
三个问题:

1. router.go: portal 路由检查 FeatureKnowledgeBase("knowledge_base"),
   但账户 feature_flags 中只有 help_center,没有 knowledge_base。
   改为检查 FeatureHelpCenter("help_center")。

2. feature_flag.go: 中间件从 context 读取 feature_flags,但没有任何
   上游中间件设置它,导致 exists=false 直接 403。GoChat 是自托管非 SaaS,
   无 flags 时应放行(所有功能可用)。

3. feature_flag.go: Account.FeatureFlags 存储为 JSON 对象格式
   ({"help_center":true}),但旧代码只解析 JSON 数组格式。
   新增 JSON 对象解析支持。

测试:新增 JSONObjectFormat / JSONObjectFormatDisabled 用例,
更新 NoFeatureFlags 用例为 200(自托管放行)。
2026-07-30 11:40:02 +08:00
Rogee 04b999e377 refactor: 移除 FakeMessagePlatform channel 全部逻辑、展示、配置
- 删除 channels/fake/ 整个 Node.js FakeMessagePlatform (8文件)
- 删除后端 FakeProvider (fake.go + fake_test.go) + FakeWebhookHandler (fake_webhook.go)
- bootstrap.go: 移除 FakeProvider 接线 + isFakeChannelEnabled()
- router.go: 移除 FakeWebhook 字段 + /webhooks/fake/:identifier 路由
- provider.go: 移除 ChannelFake 常量
- inbox_service.go: 移除 fake channel 类型验证 + isFakeChannelAllowed()
- 前端: 移除 Fake.vue + ChannelFactory/ChannelList/ChannelItem 引用 + i18n (en/zh_CN)
- package.json: 移除 fake:start/dev/test/dev:all 脚本
- pnpm-workspace.yaml: 移除 channels/fake
- .env/.env.example/quickstart: 移除 GOCHAT_ALLOW_FAKE_CHANNEL
- 测试: bridge_listener_test 改用 web_widget, router_test 移除 fake 路由断言
- 保留 fake:ai LLM Provider (backend/internal/llm/fake_provider.go) — 与 channel 无关
2026-07-30 09:09:17 +08:00
Rogee 851ca7e372 refactor: 移除 SAML/LDAP/MFA 登录方式,仅保留本地账号密码和 OIDC
后端移除:
- SAML: auth/saml.go, handler/saml_handler.go, account_saml_settings_handler.go,
  model/account_saml_settings.go, model/saml_idp_config.go, repo/*.go
- LDAP: auth/ldap.go, handler/ldap_handler.go, model/account_ldap_settings.go,
  repo/account_ldap_settings_repo.go
- MFA: auth/mfa.go, handler/mfa_handler.go
- auth_service: 移除 mfaService 依赖、MFARequired 字段、LoginWithMFA 方法
- auth_handler: 移除 LoginMFA handler、MFA 分支逻辑
- bootstrap: 移除 SAML/LDAP/MFA service 初始化和 handler 注册
- sso_middleware: 精简为仅支持 OIDC provider
- router: 移除 SAML/LDAP/MFA 路由注册
- config: 移除 SAMLConfig/LDAPConfig struct 和 defaults

前端移除:
- v3/login: 移除 MFA 验证流程和 SAML 登录入口
- v3/api/auth: 移除 MFA 响应处理
- v3/routes: 移除 SSO login 路由
- dashboard: 移除 MFA 设置页面、SAML 安全设置页面
- i18n: 移除 mfa.json
- featureFlags: 移除 SAML feature flag

.env.example / .env: 移除 SAML/LDAP 配置段
2026-07-29 19:03:04 +08:00
Rogee dccd4b93f7 fix: 修复第二轮回归发现的已知 BUG
## 修复清单

### 后端路由修复
1.  — 新增 GET 路由与现有 POST 并存
   - 前端 widget.html 原使用 GET 调用但路由仅注册 POST,导致 404
   - 修复: 注册 GET + POST 双路由,handler 支持 query param + JSON body

### 前端修复
2.  — Config 调用方式修正
   - GET /api/v1/widget/config?website_token= → POST /api/v1/widget/config
   - 发送 JSON body: {"website_token":"..."}
   - 后端 Config handler 已同时支持两种调用方式

### 文档更新
3. 修正测试计划 §13.7 已知未实现端点状态
   - 标记 4 项已验证正常(copilot/config、agent_bot_inboxes/、reports/overview)
   - 标记 2 项已修复(widget/config GET+POST)
   - 保留 1 项 P3 未实现(conversation_workflows 需完整 CRUD handler)

### 已验证非 BUG 项
- 仪表盘会话计数的0问题:实际显示 1/13/14 ✅(之前为 stale snapshot)
- 会话列表为空:filter status=open 过滤掉 snoozed 会话 ✅(设计如此)
- Reports API:正确路由 /reports?metric=&since=&until= ✅
2026-07-28 21:46:53 +08:00
Rogee 9816848ca2 fix: Web Widget SDK + Auto-Reply AgentBot sender + LLM 真实模型对接
## 核心修复

### 1. Auto-Reply Sender 修复(所有渠道)
- AutoReplyListener.sendAutoReply() 通过 botInboxRepo 查询 inbox 关联的 AgentBot
- 使用正确的 SenderType="AgentBot"(非小写 agent_bot)传递真实 AgentBot ID
- bootstrap 注入 agentBotInboxRepo/agentBotRepo 依赖

### 2. 事件数据 BUG 修复(影响所有 Webhook 渠道)
- incoming_persister.dispatch(): 补全 sender_type/content 到 event.Data
- channel/webhook.go: HandleWebhook 同步分发也补全 sender_type/content
- 未补全前 AutoReplyListener 找不到字段直接跳过

### 3. Web Widget SDK 生产验证修复
- cookie → localStorage token 同步(frontend/index.html)
- 路由双注册修复(router.go)
- Vite SPA 模式 + /widget 重写(vite.config.ts)
- WidgetService 注入 Dispatcher 触发事件分发

### 4. LLM 真实模型对接
- 配置 deepseek-v4-flash @ http://10.58.144.6:2014/v1
- LLM-mode auto-reply 规则创建并验证通过
- Prompt 文档落地: docs/captain-ai-auto-replay-prompt.md

### 5. 新增基础设施
- Helm chart (deploy/helm/)
- Widget SDK 生产测试页面
- QA 报告

Closes: BUG-W2 (auth sync), BUG-W3 (route double-reg),
       BUG-WEBHOOK-EVENT (missing event data fields)
2026-07-28 14:03:19 +08:00
rogee c3806b701a feat(parity): align Chatwoot 4.15.1 contracts 2026-07-14 12:11:52 +08:00
rogee 8b9eedc0e2 feat(copilot): finish configuration center 2026-07-13 14:57:28 +08:00
rogee 0a69d80f7c feat(copilot): complete runtime provider configuration 2026-07-13 14:57:28 +08:00
rogee f39943629f fix: remove enterprise mode gating 2026-07-12 22:19:51 +08:00
rogee f923791d39 update 2026-07-12 12:20:23 +08:00
rogee 7f2d5579ff fix: stabilize development config and account settings 2026-07-11 17:15:38 +08:00
rogee 9c852cd99b add fake channel 2026-07-09 18:14:45 +08:00
rogee c72e359e48 Phase 3.1: Help Center semantic search with pgvector
- ArticleEmbeddingRepo (new): Upsert, GetByArticleID, DeleteByArticleID,
  SearchByEmbedding using pgvector cosine distance (vector_embedding column)
- ArticleEmbedding model: add VectorEmbedding pgvector.Vector field
  alongside existing JSONB Embedding (backward compatible)
- ArticleService: add SemanticSearch() — generates query embedding via LLM,
  searches articles by cosine similarity; add GenerateEmbedding() — creates
  and stores article embedding from title+description+content
- ArticleHandler: add SemanticSearch endpoint
  GET /portals/:portal_id/articles/semantic_search?query=...
- bootstrap.go: inject articleEmbeddingRepo + llmProvider into ArticleService
- router.go: register /articles/semantic_search route
- migration 000049: add vector(1536) column to article_embeddings table,
  create ivfflat index, migrate existing JSONB data to vector format

Verified: go build + go vet + go test all pass
2026-07-08 15:38:08 +08:00
rogee b769b9a3e4 Phase 2: AutoReplyRule integration + AgentBot Captain type
AutoReplyRule complete integration:
- bootstrap.go: instantiate AutoReplyRuleService + AutoReplyListener,
  register listener on channel dispatcher for message.created events
- router.go: register /captain/auto_reply_rules CRUD + /evaluate routes
- auto_reply_rule_handler.go: fix c.Param(id) → c.Param(account_id),
  override evalCtx.AccountID from path param
- auto_reply_rule_service.go: add JSON tags to AutoReplyEvaluationContext
  for correct request body binding
- auto_reply_listener.go (new): EventListener that triggers on incoming
  messages, evaluates active rules, composes reply (static/LLM/mixed),
  respects DelaySeconds and OneTimeOnly flags, sends via MessageService
- migration 000048: create captain_auto_reply_rules table

AgentBot + Captain integration:
- agent_bot_listener.go: add captainConvSvc field + SetCaptainConversationService
  method. In HandleEvent loop, check bot.BotType == captain and route
  to CaptainConversationService.BuildConversationResponseByAccount
  instead of webhook push. Extract assistant_id from bot.Config JSONB,
  extract conversation_id from event data.
- bootstrap.go: inject captainConversationService into agentBotListener

CaptainConversationService improvement:
- generateConversationResponse: use assistant config for system prompt,
  model name, and temperature instead of hardcoded values

Verified:
- go build ./... passes
- go vet passes on all internal packages
- go test passes (service + repository + llm, SQLite mode)
- Auto-reply CRUD: create/get/update/delete all work
- Auto-reply evaluate: correctly matches hello → should_reply=true,
  correctly rejects non-matching message
- Existing routes unaffected (assistants, RAG, conversation respond)
- Migration 000048 creates captain_auto_reply_rules table successfully
2026-07-08 15:38:08 +08:00
rogee 42b8b6c7f9 Activate Captain AI features: config, RAG routes, conversation handler
Phase 1 of AI_FEATURE_ROADMAP.md:

1. config.yaml: Add captain configuration section (llm_provider, llm_model,
   llm_api_key, llm_base_url, embedding_model, embedding_dims, max_tokens,
   temperature). Secrets injected via GOCHAT_CAPTAIN_LLM_API_KEY env var.

2. RAG route registration:
   - bootstrap.go: instantiate RAGService + RAGHandler, add to Handlers
   - router.go: register POST /captain/rag/query + /captain/rag/index/:response_id
   - rag_handler.go: fix account_id param name (was "id", route uses "account_id")

3. CaptainConversationService activation:
   - Remove "_ = captainConversationService" ignore in bootstrap.go
   - Create CaptainConversationHandler with BuildResponse endpoint
   - Register POST /captain/conversations/:conversation_id/respond route
   - Fix account_id param name in handler

Verified:
- go build ./... passes
- go vet passes on all modified packages
- go test passes (llm + service packages)
- Server starts with captain config loaded
- RAG query/index routes return proper handler responses (not 404)
- Conversation respond route returns proper skip for non-pending conversations
- Existing captain routes unaffected (assistants list still works)
2026-07-08 15:38:08 +08:00
rogee 10cc300f31 Fix canned_responses 500: add missing SQL migration
The canned_responses table was registered in autoMigrate() (app.go) but
autoMigrate() is never called on the serve path (Bootstrap -> NewDatabase
-> RunMigrations only). With no SQL migration file, the table never
existed, so POST /api/v1/accounts/:id/canned_responses failed with
'relation does not exist' -> 500.

Add migration 000049 to create the table matching the GORM model
(id, account_id, content, short_code, timestamps) with the account+
short_code partial unique index and deleted_at index.

Also include two related fixes staged in the working tree:
- router.go: register notifications.GET("") alongside GET("/") to avoid
  Gin 301 trailing-slash redirect that the Vite proxy doesn't follow
- notifications/actions.js: stop the infinite loader on fetch error to
  prevent IntersectionObserver re-fire loop
2026-07-08 11:43:34 +08:00
rogee aeddedf2a3 Reorganize repo: backend/, deploy/, docs/ layout + AGENTS.md
Restructure the monorepo into clear top-level directories:
- backend/: Go module root (cmd, internal, pkg, configs, migrations,
  docs/swagger, scripts, tests, go.mod, Makefile, .air.toml)
- deploy/: Docker (Dockerfile, docker-compose*), quickstart, fluentd
- docs/: project documentation + reports/ (moved from repo root)
- AGENTS.md: new AI coding-agent guide at repo root

Update all references to the new layout:
- Dockerfile: COPY backend/go.mod, COPY backend/ (context = repo root)
- docker-compose files: context ../.., dockerfile deploy/docker/Dockerfile,
  env_file ../../.env, volume mounts ../../backend:/app
- deploy/quickstart/compose.yaml: dockerfile deploy/docker/Dockerfile
- CI: working-directory: backend for go commands, file deploy/docker/Dockerfile,
  coverage path backend/coverage.out, health_check backend/scripts/
- backend/Makefile: docker target uses -f ../deploy/docker/Dockerfile ../
- README: architecture tree, quickstart, config paths updated

Move root stray scripts (rename_models.*, run_m11_tests.sh, verify_build.sh,
gorm_bool_main.go) to backend/scripts/legacy/. All moves via git mv to
preserve history. Build, vet, SQLite tests, and docker compose config verified.
2026-07-07 14:44:12 +08:00