Version: 0.9.76.dev.260505

后端:
1.阶段 6 agent / memory 服务化收口
- 新增 cmd/agent 独立进程入口,承载 agent zrpc server、agent outbox relay / consumer 和运行时依赖初始化
- 补齐 services/agent/rpc 的 Chat stream 与 conversation meta/list/timeline、schedule-preview、context-stats、schedule-state unary RPC
- 新增 gateway/client/agent 与 shared/contracts/agent,将 /api/v1/agent chat 和非 chat 门面切到 agent zrpc
- 收缩 gateway 本地 AgentService 装配,双 RPC 开关开启时不再初始化本地 agent 编排、LLM、RAG 和 memory reader fallback
- 将 backend/memory 物理迁入 services/memory,私有实现收入 internal,保留 module/model/observe 作为 memory 服务门面
- 调整 memory outbox、memory reader 和 agent 记忆渲染链路的 import 与服务边界,cmd/memory 独占 memory worker / consumer
- 关闭 gateway 侧 agent outbox worker 所有权,agent relay / consumer 由 cmd/agent 独占,gateway 仅保留 HTTP/SSE 门面与迁移期开关回退
- 更新阶段 6 文档,记录 agent / memory 当前切流点、smoke 结果,以及 backend/client 与 gateway/shared 的目录收口口径
This commit is contained in:
Losita
2026-05-05 19:31:39 +08:00
parent d7184b776b
commit 2a96f4c6f9
72 changed files with 2775 additions and 291 deletions

View File

@@ -71,10 +71,11 @@ Gin Gateway 只做边缘层职责:
当前 gateway 切流点:
1. `/api/v1/user/*``backend/gateway/api/userauth` 承载 HTTP 入口,核心能力通过 `backend/gateway/client/userauth``cmd/userauth` zrpc。
1. `/api/v1/user/*``backend/gateway/api/userauth` 承载 HTTP 入口,核心能力通过 zrpc client`cmd/userauth` zrpc。
2. `gateway/middleware` 的 JWT 鉴权和 token quota guard 只调 `userauth`,不直接读写 `users`、Redis 黑名单或额度缓存。
3. `notification``active-scheduler` 等跨服务 zrpc client 统一放在 `backend/gateway/client/<service>`HTTP 门面统一放在 `backend/gateway/api`
3. `notification``active-scheduler``agent``memory` 等跨服务 zrpc client 终态统一放在 `backend/client/<service>`;当前 `backend/gateway/client/<service>` 是迁移期旧位置,下一轮目录收口应机械迁出
4. zrpc client 不放进 `cmd``cmd` 只负责进程入口和装配,不承载跨服务 client 语义。
5. HTTP 门面统一放在 `backend/gateway/api`gateway 内部可新增 `backend/gateway/shared`,只放 HTTP/SSE/bind/multipart/respond 等门面复用能力,禁止服务层 import。
### 3.2 服务层
@@ -134,6 +135,8 @@ gozero 服务负责领域能力:
6. 换句话说,`shared` 是“跨进程契约层 + 少量跨服务底座”,不是“公共业务层”。
7. 阶段 2 已经新增 `backend/shared/contracts/userauth``backend/shared/ports`只承载跨层契约和端口接口user/auth 的 JWT、DAO、额度治理、黑名单实现不进入 `shared`
8. 阶段 3 已经新增 `backend/shared/contracts/notification`,只承载 notification 跨层 DTO通知通道 DAO、投递状态机、provider、重试策略和 outbox handler 都留在 `backend/services/notification`
9. `backend/client` 是跨进程调用客户端层,不属于 gateway 私有目录gateway 和服务进程都可以 import但 client 只能依赖 `shared/contracts``shared/ports`、rpc/pb 和通用错误适配,不反向依赖 `gateway/api` 或服务私有 `sv/dao/model`
10. `backend/gateway/shared` 与根 `backend/shared` 分层:前者只服务 gateway 门面内部复用,后者服务全后端跨服务契约。服务代码禁止 import `gateway/shared`,避免形成“服务依赖网关”的反向边界。
---
@@ -503,7 +506,16 @@ flowchart LR
1. `backend/newAgent/*` 已按机械搬迁方式迁入 `backend/services/agent/*`Go import 路径和 `agent*` 包名前缀已切到新位置。
2. `backend/service/agentsvc/*` 已继续机械迁入 `backend/services/agent/sv/*`,启动装配和 Agent HTTP handler 直接依赖 `agent/sv.AgentService`
3. 历史 timeline payload key`newagent_history_kind`)暂不改名,避免破坏旧会话兼容
3. `backend/cmd/agent/main.go` 已补齐独立进程入口:负责 DB / Redis / LLM / RAG 初始化、agent outbox consumer 启停和 agent zrpc server 生命周期;旧 `backend/cmd/start.go` 的 gateway 本地链路继续保留
4. agent 事件归属继续复用 `backend/service/events` 与服务级 outbox 路由:`chat.*` / `agent.*` 事件归 `ServiceAgent``memory.extract.requested` 只登记路由不再由 agent 进程消费,`task.urgency.promote.requested` 仍是 publish-only 写入 `task_outbox_messages`
5. `backend/services/agent/rpc` 已补齐 `Ping``Chat` server-stream 以及 conversation meta/list/timeline、schedule-preview、context-stats、schedule-state 6 个 unary JSON 透传 RPC跨进程 chat 边界传 `ChatChunk`,不传 Go channelGateway 继续对前端输出原 SSE 协议。
6. `backend/gateway/client/agent``gateway/api/agent.go` 已接入 `agent.rpc.chat.enabled``agent.rpc.api.enabled` 两个开关;本地 `config.yaml``config.example.yaml` 当前默认 `true`,真实 UTF-8 中文 SSE smoke 已通过chat 主链路走 `agent RPC Chat(stream)` 再转 SSE非 chat `/agent/*` 走 agent unary RPC。
7. 历史 timeline payload key`newagent_history_kind`)暂不改名,避免破坏旧会话兼容。
8. `backend/memory/*` 已物理迁入 `backend/services/memory/*``module.go``model/``observe/` 作为公共门面保留,`cleanup/``orchestrator/``repo/``service/``utils/``vectorsync/``worker/` 收入 `internal/`,旧 `backend/memory` 目录已删除。
9. `cmd/start.go` 不再创建/注册/启动 agent outbox event busagent relay / consumer 由 `cmd/agent` 独占memory worker / 管理能力由 `cmd/memory` 承担。
10. `cmd/start.go` 已收缩 gateway 本地 `AgentService` 构建:当 `agent.rpc.chat.enabled=true``agent.rpc.api.enabled=true`gateway 不再初始化 agent 本地编排、LLM、RAG、memory reader fallback只有任一 RPC 开关关闭时才保守装配本地 fallback。
11. 最新验证:重建并重启 `api` / `agent`UTF-8 中文 SSE smoke 通过且只有单个 `[DONE]`6 个非 chat `/agent/*` HTTP smoke 中 meta/list/timeline/context-stats 返回 200schedule-preview / schedule-state 在无快照场景返回预期业务 400。
12. 下一轮目录收口按新口径推进:把 `backend/gateway/client/*` 机械迁到 `backend/client/*`,让 gateway 和服务进程共同复用 zrpc client保留根 `backend/shared` 承载跨服务契约,同时新增 `backend/gateway/shared` 承载 HTTP/SSE/bind/respond 等 gateway 门面复用。
建议提交点:
@@ -552,18 +564,18 @@ flowchart LR
当前建议按这个顺序推进:
注:阶段 1.5 / 1.6 / 2 / 3 / 4 已完成首轮收口;`notification``active-scheduler` 都不再作为“未拆服务”待办
注:阶段 1.5 / 1.6 / 2 / 3 / 4 已完成首轮收口;阶段 5 的 schedule / task / course / task-class 已完成首轮服务化和 HTTP 切流;当前推进点是阶段 6 的 agent / memory 收口
1. 以阶段 1 的服务级 outbox 为当前基线,不再回头做共享 outbox 方案。
2. 保持 `backend/services/llm``backend/services/rag` 为 canonical 入口,不再把它们写成待办。
3. 保持 `backend/services/userauth` + `cmd/userauth` 为阶段 2 样板,不再回头恢复 Gin 单体 user/auth。
4. 下一步进入阶段 5优先切 schedule / task / course / task-class,逐步替换 active-scheduler 当前的跨域 DB 依赖
5. 再切 agent / memory把聊天编排、主动调度会话复跑和记忆链路独立出去。
4. 保持 schedule / task / course / task-class 的 zrpc 边界为阶段 5 当前基线,不再把它们重新列为未拆服务
5. 继续收 agent / memory把聊天编排、主动调度会话复跑和记忆链路独立出去。
6. 最后把 Gin 收口成纯 Gateway。
一句话总结:
> outbox 的服务级基础设施、llm-service、rag-service、user/auth 样板服务和 notification 阶段 3 都已经完成;下一步让 active-scheduler、schedule、task、course、task-class 按稳定边界逐步独立;再把 agent / memory 独立出来,完成聊天编排和记忆链路的服务化;最后把 Gin 收口成真正的 Gateway。
> outbox 的服务级基础设施、llm-service、rag-service、user/authnotificationactive-scheduler、schedule、task、course、task-class 都已经完成首轮服务化基线;当前继续把 agent / memory 独立出来,完成聊天编排和记忆链路的服务化;最后把 Gin 收口成真正的 Gateway。
---
@@ -749,7 +761,7 @@ SmartFlow-Agent/
> 4. `backend/services/agent/*` 已承接原 `backend/newAgent/*` 内核,`backend/services/agent/sv/*` 已承接原 `backend/service/agentsvc/*` 编排层;后面再按风险拆到 `internal/{prompt,graph,stream,tool,session,router}`。
> 5. `backend/services/notification/*` 已经是阶段 3 终态样板;`backend/cmd/notification` 是独立进程入口,`backend/gateway/client/notification` 是 gateway 侧 zrpc client`backend/shared/contracts/notification` 只放跨层契约;旧 `backend/notification/*`、旧 DAO/model 和旧 `service/events/notification_feishu.go` 不再作为活跃实现。
> 6. `backend/services/active_scheduler/*` 已经是阶段 4 当前样板;`backend/cmd/active-scheduler` 是独立进程入口,`backend/gateway/client/activescheduler` 是 gateway 侧 zrpc client`backend/services/active_scheduler/core` 承载迁移期领域核心;旧 `backend/active_scheduler/*` 不再作为活跃实现。
> 7. `backend/memory/*`,后面要收束到 `backend/services/memory/`;当前 `memory/service/*` 只是迁移过渡态,终态还是按 `sv/` 或 `internal/` 拆开
> 7. `backend/services/memory/*` 已成为 memory 当前 canonical 入口;`module.go`、`model/`、`observe/` 是对外可见门面,服务私有实现已收入 `internal/`,旧 `backend/memory/*` 只在 legacy 文档中作为历史路径出现
>
> 说明 4`shared` 先保留 `events` 和少量跨服务底座型 `infra`。以后如果真的出现跨服务 DTO / 枚举 / 常量,再新增 `contracts` 一类目录,但不要把 `dao`、`model`、`sv`、`handler` 这类服务私有层塞进去。
@@ -759,7 +771,7 @@ SmartFlow-Agent/
>
> 说明 7目录树里如果暂时写成 `backend/services/llm/` 和 `backend/services/rag/`,那只是目录名写法;后文所有职责判断都以 `llm-service` / `rag-service` 这两个逻辑服务名为准。
>
> 说明 8阶段 2 已经采用 `backend/services/userauth/` 作为实际目录名,不再使用 `user-auth`。阶段 3 已经采用 `backend/services/notification/` 作为实际目录名。gateway 侧 zrpc client 放在 `backend/gateway/{userauth,notification}/`进程入口放在 `backend/cmd/{userauth,notification}/`不要把 rpc client 放进 `cmd`。
> 说明 8阶段 2 已经采用 `backend/services/userauth/` 作为实际目录名,不再使用 `user-auth`。阶段 3 已经采用 `backend/services/notification/` 作为实际目录名。zrpc client 终态放在 `backend/client/<service>/`,迁移期旧 `backend/gateway/client/<service>/` 要按机械迁移逐步挪出;进程入口放在 `backend/cmd/<service>/`不要把 rpc client 放进 `cmd`。
### 6.3 哪些可以不用变
@@ -910,19 +922,22 @@ graph TD
5. 阶段 3 `notification` 已完成实现、code review 修复和真实 smoke`llm-service``rag-service` 也已完成,不要重新当成待办。
6. 阶段 4 `active-scheduler` 已完成首轮收口;后续不要再把它当成“未拆服务”,除非是在补契约测试或继续替换跨域 DB 访问。
7. `shared` 只保留跨进程契约和少量跨服务底座不承载业务逻辑、DAO、模型或状态机。
8. 如果后续要改目录,必须先回答“这个文件属于哪一个典型用例”,回答不清楚就先别动结构
9. 当前文档已经可以作为切对话基线;后续代理默认按本文件推进。现阶段的迁移基线入口是 `backend/cmd/api``backend/cmd/worker``backend/cmd/all`,它们只是当前仓库的启动壳,不是终态。`backend/cmd/userauth` 是阶段 2 的独立服务入口,`backend/cmd/notification` 是阶段 3 的独立服务入口,`backend/cmd/active-scheduler` 是阶段 4 的独立服务入口,`backend/cmd/schedule``backend/cmd/task``backend/cmd/task-class``backend/cmd/course` 是阶段 5 已落地的独立服务入口。终态仍然是“一个服务一个独立 `main.go`”,只在出现新的契约风险、边界变化或业务语义变化时再重新讨论架构
8. `backend/client` 是 zrpc client 的终态共享位置,`backend/gateway/client` 只是迁移期旧位置;后续服务或 gateway 需要复用 client 时,优先推进机械搬迁到根 `client`
9. `backend/gateway/shared` 只放 gateway 门面复用,服务代码禁止 import跨服务契约仍留在根 `backend/shared`
10. 如果后续要改目录,必须先回答“这个文件属于哪一个典型用例”,回答不清楚就先别动结构。
11. 当前文档已经可以作为切对话基线;后续代理默认按本文件推进。现阶段的迁移基线入口是 `backend/cmd/api``backend/cmd/worker``backend/cmd/all`,它们只是当前仓库的启动壳,不是终态。`backend/cmd/userauth` 是阶段 2 的独立服务入口,`backend/cmd/notification` 是阶段 3 的独立服务入口,`backend/cmd/active-scheduler` 是阶段 4 的独立服务入口,`backend/cmd/schedule``backend/cmd/task``backend/cmd/task-class``backend/cmd/course` 是阶段 5 已落地的独立服务入口。终态仍然是“一个服务一个独立 `main.go`”,只在出现新的契约风险、边界变化或业务语义变化时再重新讨论架构。
### 6.10 启动方式与进程模型
1. 终态里每个 gozero 服务都应当是独立进程:一个服务一个 `main.go`,一份配置,一组日志,一套端口和资源连接。
2. 目录上可以继续采用 `backend/cmd/<service>/main.go` 作为可执行入口,`backend/services/<service>/` 负责 `sv/``dao/``model/``internal/``rpc/`gateway 自己的 HTTP 适配 zrpc client 放在 `backend/gateway/...`,不要把 rpc client 放进 `cmd`
2. 目录上可以继续采用 `backend/cmd/<service>/main.go` 作为可执行入口,`backend/services/<service>/` 负责 `sv/``dao/``model/``internal/``rpc/`gateway 自己的 HTTP 适配放在 `backend/gateway/...`,跨服务 zrpc client 放在 `backend/client/<service>/`,不要把 rpc client 放进 `cmd` 或长期留在 `gateway/client`
3. 本地开发为了方便,可以保留 `backend/cmd/all``make dev` 或类似聚合启动器,但它只负责拉起多个独立进程,不在同一个 Go 进程里把所有服务 `startXXX()` 混着跑。
4. `go startxxx()` 这种“一个进程里同时起多个服务”的方式只适合作为过渡调试壳,不作为最终部署形态。
5. 如果某些服务需要联动启动应通过脚本、Makefile、docker compose 或开发编排器去启动多个二进制,而不是把进程边界打穿。
6. 带 worker 的服务可以继续保留多入口角色,例如 `api` / `worker` / `all`,但它们仍然是同一服务的不同可执行角色,不是把多个服务硬塞进一个进程。
7. MySQL / Redis 容器的启动归 `docker compose` 或运维层Go 服务只负责在自己的进程里建立连接、做自己的 AutoMigrate 和连通性检查。
8. 阶段 5 后,旧 `cmd/start.go` / `cmd/all` 只是 gateway 和迁移期组合壳;本地完整 smoke 必须额外启动 `cmd/userauth``cmd/notification``cmd/active-scheduler``cmd/schedule``cmd/task``cmd/task-class``cmd/course`。如果同机已有另一条线占用默认端口,应复制临时配置,把 HTTP / zrpc 端口整体平移后再启动服务。
9. 阶段 6 后,`cmd/agent``cmd/memory` 也应纳入完整本地 smoke目录收口时优先把服务与 gateway 共同使用的 zrpc client 从 `gateway/client` 挪到根 `client`,再清理 gateway 门面复用到 `gateway/shared`
### 6.11 测试自动化与 smoke 权限边界