☰
Routa双后端架构深度解析:Next.js与Rust如何做到API语义完全对齐
2026/10/11 20:58:31 网站建设 项目流程

【免费下载链接】routa

Workspace-first multi-agent coordination platform for AI development, with shared Specs, Kanban orchestration, and MCP/ACP/ A2A support across web and desktop.

项目地址:https://gitcode.com/gh_mirrors/ro/routa
点击查看免费下载

Routa 是一个工作区优先的多智能体协作平台(Workspace-first multi-agent coordination platform),它同时提供 Web(Next.js)与桌面(Tauri + Rust/Axum)两种形态。这两个后端由完全不同的语言编写,却对外暴露完全一致的 API 语义——这套「双后端架构」正是 Routa 区别于其他 AI 开发工具的关键设计。本文将从契约文件、组装点、一致性检查与行为级测试四个层面,完整拆解它是怎么做到的。

为什么是「双后端」而不是「两个产品」

一个很自然的做法是:Web 版和桌面版各自独立开发、共享一套前端界面。这条路短期很快,但长期有隐患——两套后端会逐渐形成不同的领域概念、不同的字段命名、不同的错误码,最终演变成两个心智模型割裂的产品。对「人与 Agent 共用一个工作区」的平台来说,这种漂移是不可接受的。

Routa 在项目早期就把这个问题固化成了架构决策记录(ADR),明确了一个核心结论:

Web 和桌面是同一个产品,只有两个运行时表面(runtime surface)。

完整决策文档见 0001-dual-backend-semantic-parity.md。它要求两个后端做到三件事:

  1. 共享同一套领域词汇:workspace(工作区)、session(会话)、task(任务)、kanban board(看板)、specialist(专家)、worktree(工作树)……任何一侧先出现的新概念都不算「发布」,必须双端落地。
  2. 暴露同一形状的 API:由仓库根目录的 api-contract.yaml 统一管理。
  3. 在 CI 中运行契约一致性测试:npm run api:test:nextjs对比npm run api:test:rust,同一套测试脚本分别打向两个后端。

一个容易忽略的细节是:存储可以不同,语义不能不同。Web 版跑在 Postgres(Neon Serverless)上,桌面版跑在本机 SQLite 上,但两端的 store 接口与领域语义必须保持一致。

契约先行:api-contract.yaml 是唯一事实来源

Routa 采用「契约优先」(Contract-First)的 API 治理方式。所有端点、请求/响应结构、枚举值,先定义在一份 OpenAPI 3.1 规范里,再分别去两个后端实现。

这份契约文件有 7000 多行,开头就写明了规则:

openapi: 3.1.0 info: title: Routa.js API Contract description: | Single source of truth for the Routa.js dual-backend API. Both the Next.js backend (src/app/api/) and the Rust backend (crates/routa-server/) MUST implement all endpoints defined here with compatible request/response shapes.

几个值得注意的设计点:

  • 枚举集中定义。像TaskStatus(PENDING / IN_PROGRESS / REVIEW_REQUIRED / COMPLETED…)、AgentStatus、VerificationVerdict这类状态机枚举,在契约的components.schemas中统一定义一次,两个后端必须使用完全相同的取值。这样任务状态在 Web 和桌面之间切换时不会出现语义错位。
  • 服务器声明即双端口。契约里直接声明了两个服务地址:Next.js 后端localhost:3000与 Rust 后端localhost:3210,契约文件本身就描述了「一个产品、两个运行时」的结构。
  • 变更有流程约束。按 api-contract.md 中的规则:添加新端点必须先改契约、再双端实现、最后跑npm run api:check验证;破坏性变更默认禁止,必须走版本化或废弃流程。

对称的组装点:TypeScript 与 Rust 各有一个「系统工厂」

契约管的是「API 长什么样」,而「系统怎么组装」则由两个对称的工厂函数保证。ADR 中明确指出了这两处:

角色TypeScript 侧Rust 侧
组装点src/core/routa-system.tscrates/routa-core/src/state.rs

TypeScript 侧的RoutaSystem是一个中心对象,持有全部 store(agent、task、workspace、kanban board、note……)、事件总线(EventBus)与工具集(AgentTools、NoteTools、WorkspaceTools),并支持 InMemory / Postgres / SQLite 三种存储模式。

Rust 侧的AppStateInner结构体做了完全对称的事情:同样是 workspace_store、agent_store、task_store、kanban_store、note_store、event_bus 等成员一一对应,外加 ACP 管理(AcpManager、AcpRuntimeManager)等桌面端运行所需的能力。

这种「镜像式组装」保证了:无论从哪个后端进入系统,拿到的都是同一组领域服务、同一套事件语义。前端与 Agent 只需要按契约调用,不用关心背后是谁在响应。

三层防线:静态检查 + 行为测试 + 健康度门禁

光有契约文件不够,Routa 用三层自动化防线确保契约不被悄悄破坏。

第一层:路由静态对账(api:check)

check-api-parity.ts 会同时从三个来源提取路由定义并做差集对比:

  1. 解析api-contract.yaml中声明的端点;
  2. 扫描 Next.js 的文件约定路由(src/app/api/ 下的route.ts导出函数);
  3. 解析 Rust 侧 Axum 路由(crates/routa-server/src/api/ 各模块的router()定义)。

输出报告包含missingInNextjs/missingInRust/extraInContract等字段——哪一侧漏实现了契约端点、哪一侧私加了契约外端点,都会被列出来。该检查支持--json机器可读输出和--fix-hint修复建议。

第二层:行为级契约测试(同一套脚本打两个后端)

tests/api-contract/ 目录下的测试运行器 run.ts 是关键:它把同一套用例(workspaces、agents、tasks、notes、sessions、skills、schema-validation 七个套件)分别指向BASE_URL=http://localhost:3000(Next.js)和BASE_URL=http://localhost:3210(Rust),验证的是行为一致性而不只是路由存在性。对应脚本命令定义在 package.json 的api:test:nextjs/api:test:rust中。

针对 Rust 后端还有专门的端到端测试矩阵 rust-api-test.md,按「端点 × 场景」登记每个用例的状态:VERIFIED(已验证并给出测试文件路径)、BLOCKED(有阻塞原因)、TODO(待补齐)。覆盖范围包括成功路径、负向路径(如空名创建返回 400、缺失参数返回 404、非法状态转移返回冲突)和回归路径,例如POST /api/tasks/{id}/status必须验证无效状态转移会被拒绝——这类状态机语义正是「语义对齐」最容易悄悄漂移的地方。

第三层:健康度体系中的硬门禁

契约检查不是独立脚本,而是接入了 Routa 的 fitness(工程健康度)评分体系。在 api-contract.md 中,api_contract维度的openapi_schema_valid和api_parity_check两个指标都标记为hard_gate: true——也就是说 Schema 校验失败或双端不一致时,门禁直接不放行。Rust 侧端点测试同样登记在 rust-api-test.md 的前置元数据中,作为 maintainability 维度的证据来源。整套健康度文件清单见 manifest.yaml。

对使用者的实际意义

这套架构对普通用户意味着什么?三个具体好处:

  • 数据与体验跨端一致:在 Web 上创建的工作区、看板卡片、任务状态,切到桌面端打开时概念完全对得上,不需要「翻译」。
  • 桌面端是本地优先的:按 desktop.md 的说明,桌面版提供 local-first 持久化与执行能力,而 Web 版适合自托管和团队浏览器访问(web.md),两者只是部署形态差异。
  • 新能力双端同步落地:任何新领域概念必须双端实现后才算发布,不会出现「Web 有、桌面没有」的半拉子功能。

关键文件速查

文件作用
api-contract.yaml双后端 API 契约,唯一事实来源
docs/adr/0001-dual-backend-semantic-parity.md双后端语义对齐的架构决策记录
src/core/routa-system.tsTypeScript 侧系统工厂
crates/routa-core/src/state.rsRust 侧共享应用状态
scripts/fitness/check-api-parity.ts三源路由静态对账脚本
tests/api-contract/双后端行为级契约测试
docs/fitness/api-contract.md契约维度健康度门禁配置
docs/fitness/rust-api-test.mdRust 端点测试矩阵

总结

Routa 的双后端架构可以概括为一句话:契约先行定义语义,镜像组装保证结构,自动化门禁守住底线。一份 OpenAPI 契约作为唯一事实来源,两个语言的系统工厂对称组装相同的领域服务,再叠加静态路由对账、行为级对比测试和 hard gate 健康度门禁,让 Next.js 与 Rust/Axum 这对「异卵双胞胎」始终说同一种 API 语言。对任何需要同时维护 Web 与桌面两个运行时的项目来说,这套「契约 + 镜像 + 门禁」的组合都值得直接借鉴。

【免费下载链接】routa

Workspace-first multi-agent coordination platform for AI development, with shared Specs, Kanban orchestration, and MCP/ACP/ A2A support across web and desktop.

项目地址:https://gitcode.com/gh_mirrors/ro/routa
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询