Tambo AI Monorepo 开发规范与 AI Agent 协作指南:从仓库结构到工程实践的完整解读
【免费下载链接】hydra-aiGenerative UI SDK for React项目地址: https://gitcode.com/GitHub_Trending/hy/hydra-ai
本指南基于 Tambo AI 开源仓库根目录的 AGENTS.md(Claude Code 等 AI Agent 与人类开发者共同遵循的工程规范文档),系统梳理这个同时承载 Tambo AI 框架与 Tambo Cloud 平台的 Turborepo 单仓库的架构布局、编码标准、开发工作流与协作纪律。读完本文,你将掌握该仓库的模块划分与端口规划、Node.js 22 环境下的开发命令体系、TypeScript/前端/后端/数据库的硬性规范,以及提交 PR 前必须通过的验证检查项,能够以符合项目预期的方式在此仓库中独立开发与协作。
一、仓库全景:一个 Monorepo,两大产品线
Tambo AI 采用 Turborepo 组织整个代码库,根目录 package.json 通过workspaces字段声明了全部工作区:react-sdk、showcase、docs、cli、create-tambo-app、packages/*与apps/*。整个仓库被划分为两个层次:Tambo AI 框架包(面向开源 SDK 使用者)与Tambo Cloud 平台(SaaS 云服务)。
1.1 框架包(Turborepo 根级)
| 包 | 名称 | 定位 |
|---|---|---|
react-sdk/ | @tambo-ai/react | React 官方 SDK,提供核心 hooks、providers、类型,支持组件注册与线程管理;同时输出 CommonJS(dist/)与 ESM(esm/)双格式 |
packages/client/ | @tambo-ai/client | 框架无关的核心客户端引擎,TamboClient类提供getState()/subscribe(),TamboStream异步可迭代对象用于流式响应;既被@tambo-ai/react复用,也可独立在 Node.js、Vue、Svelte 等环境使用 |
cli/ | tambo | 命令行工具,负责项目脚手架、组件生成与开发辅助 |
showcase/ | @tambo-ai/showcase | 演示应用(端口 8262),展示全部 Tambo 组件与模式,兼具文档与测试场职能 |
docs/ | @tambo-ai/docs | Fumadocs 文档站(端口 8263),MDX 内容 + 交互式示例 |
create-tambo-app/ | create-tambo-app | 应用引导器,负责从模板初始化新项目、处理 git 初始化与依赖安装 |
community/ | — | 社区资源与活动物料 |
值得注意的两个工程约束:
- showcase 组件由 CLI 注册表自动同步:
showcase/中的组件来源于 CLI registry(代码结构上对应cli/dist/registry/的生成产物),修改时应改 CLI 注册表而非直接编辑 showcase 组件; - docs 组件以 cli 包为源:文档站中的 UI 组件源自
cli/包,任何组件改动都应先在 cli 包完成,再复制到 docs 包,避免双份代码漂移。
从 react-sdk/package.json 可以看到 SDK 包的构建脚本build由build:cjs(tsc -p tsconfig.cjs.json)与build:esm(tsc -p tsconfig.esm.json && tsc-esm-fix --target=esm)组成,这正是“双格式输出”的实现方式;其exports字段还通过@tambo-ai/source条件导出指向./src/index.ts,方便消费方直接引用源码。
1.2 Tambo Cloud 平台
| 包 | 定位 |
|---|---|
apps/web | Next.js 前端(端口 8260) |
apps/api | NestJS OpenAPI 服务端(端口 8261) |
packages/db | Drizzle ORM schema + 迁移 + 数据库辅助 |
packages/core | 纯工具库(不访问数据库) |
packages/backend | LLM/Agent 侧辅助与流式工具 |
packages/eslint-config、packages/typescript-config | 共享工具链配置 |
1.3 环境前提与工具版本管理
- Node.js >= 22,npm >= 11(根 package.json 的
devEngines字段直接声明,不满足会报错); - 运行时与测试代码可直接使用
crypto.randomUUID(),无需降级 polyfill; - 官方推荐使用 mise(大多数工具)与
.node-version(Node.js,.nvmrc保持同步以兼容 nvm),这些文件由 Renovate 自动更新。
从 mise.toml 可以看到工具清单:cspell、gh、jq、shellcheck,并通过npm:corepack管理 npm/yarn/pnpm 版本(postinstall = "corepack enable && corepack enable npm"),同时禁用了顶层包管理器安装,避免版本漂移;环境变量中还默认关闭了 Turbo 与 Next.js 的遥测(TURBO_TELEMETRY_DISABLED、NEXT_TELEMETRY_DISABLED)。
mise 的日常用法:
mise install # 安装/更新工具到正确版本 mise exec -- <command> # 脚本/CI/非交互 shell 推荐用法 eval "$(mise activate)" # 仅交互式 shell 使用变更工具版本的流程:提交 PR 修改权威版本文件;涉及 Node.js 时必须同时更新.node-version与.nvmrc;随后运行mise install并用npm run lint && npm run check-types && npm test验证。本地临时覆盖使用.mise.local.toml(已 gitignore),且只允许增量或补丁级变更,不允许覆盖 Node.js 版本或使用不兼容版本。
二、核心开发原则:快速迭代与高标准的平衡
AGENTS.md 用一组哲学原则约束所有代码产出:
- 快速推进但保持高标准:清晰与可维护性优先于“聪明”的写法;
- 先读代码再动手:遵循既有模式与命名;
- 小而简单:函数优先于类,避免不必要的抽象;
- 持续简化:激进地移除复杂度,能工作的最简单设计通常最好;
- 偏好不可变:不修改入参,返回新值;多用
const、toSorted、对象/数组展开; - 前置错误处理:用 guard clause 与 early return 尽早返回。
关注点分离
业务逻辑必须与 UI 组件分离:计算、数据转换等逻辑抽取到独立文件(utils/、services/、lib/),UI 组件只做编排而不实现复杂逻辑。这样既易于测试,也提升复用性。
Fail-Fast,禁止静默兜底
- 条件不满足时立即失败,静默回退会掩盖 bug 并制造不可预测的系统行为;
- 出错时用清晰错误信息终止执行,说明“什么失败了、期望什么”,例如:
throw new Error(`Required model ${modelName} not found`);- 数据映射(如枚举/联合类型转换)必须显式处理所有已知值,遇到未知值直接抛错,禁止用 catch-all 默认值掩盖数据完整性问题;确需跳过无效数据时要记日志告警。
命名规范
- 文件/目录:
kebab-case;类:PascalCase;变量/函数/方法:camelCase;环境变量:UPPER_SNAKE_CASE; - 使用英文与公认缩写(API、URL、ctx、req、res、next);
- 布尔值以
is/has/can/should开头;函数用动词命名,返回布尔值用isX/hasX/canX,返回void倾向executeX/saveX; - React 专属命名遵循 devdocs/NAMING_CONVENTIONS.md:组件
TamboXxx、hooksuseTamboXxx、Props 接口TamboXxxProps、事件 props 以onX开头、内部处理器用handleX。该文档还给出 Props 一律使用Readonly<T>包裹的约定:
export const TamboMessage: React.FC<Readonly<TamboMessageProps>> = () => { /* ... */ };以及“动作最后置”的 hook 命名检查:useTamboMessage()与useTamboMessageState()是正确写法,useMessageTambo()则是错误前缀顺序。
代码组织
- 函数短小单一职责(理想 <20 条语句);文件聚焦合理规模(理想 <200–300 行);
- 避免
let——用返回新值的函数替代; - 避免深层嵌套:优先提前退出与提取辅助函数;用
map/filter迭代; - 偏好不可变数据,适用处用
readonly与as const; - 组合优于继承;如确需类,保持小规模(<200 语句、<10 属性/方法)并在内部校验不变量。
避免过度抽象
- DRY 有度——有时少量重复优于错误的抽象;
- 三次法则:出现 3 处相似代码后再提取共享工具;
- 过早抽象制造耦合、加大改动成本;事后提取共性远比撤销糟糕抽象容易。
导出规范
- 偏好具名导出;关联符号可一起导出(如组件 + 相关类型);
- 避免默认导出;
- 内部模块不要建
index.tsbarrel,直接从源文件导入;例外是包入口(如packages/core/src/index.ts); - 迁移符号时同步更新所有消费方,不向后兼容重导出;
- 禁止用动态
import()做常规导入(含类型导入),一律顶部静态导入;动态导入仅用于特定场景的代码分割(如懒加载路由)。
三、TypeScript 标准:严格类型与可推断优先
类型安全
- 默认严格 TypeScript:不用
any、不强制类型断言,除非不可避免; - 类型不确定时用
unknown再做收窄,而不是any; - 键值对象优先
Record<string, unknown>,而非object或{ [key: string]: unknown }; - 除非明确要求,禁止关闭 ESLint 规则或 TypeScript 报错——修复根因;
- 泛型用
extends约束(<T extends SomeType>,避免宽泛<T>); - 互斥状态用可辨识联合(discriminated union),如
{ success: true; data: T } | { success: false; error: Error }; - 用
as const保留字面量类型(数组应保持元组); - 复用内置工具类型(
Pick、Omit、Partial、Required、ReturnType、Parameters),不要重复造轮子; - 避免
{}类型——它表示“任意非空值”包含原始类型;应选用unknown、object或Record<string, unknown>。
type-fest 工具类型
复杂派生类型优先查type-fest包(PartialDeep、ReadonlyDeep、RequiredDeep、Merge、ValueOf、SetOptional等)。type-fest已装于仓库根,但各包使用时必须显式声明:被包公开导出类型引用则放入dependencies,仅内部代码或测试使用则放入devDependencies。
类型推断
- 值容易推断时不要加冗余类型标注(事件处理器参数、显而易见的返回值、局部变量);
- 让 TypeScript 推断明显可推断的返回类型;
- 不要为内部函数创建一次性中间辅助类型;
- 优先使用数据库 schema、tRPC schema 等“事实来源”推断出的类型;
- 除非必要否则避免类型转换(
as):优先调整函数签名/类型让代码无需转换;通过unknown转换通常是坏味道,确需在互操作边界使用时,先做运行时校验(如 Zod)并保持转换局部化; - 用
satisfies在保留推断的同时检查对象字面量是否符合类型(仅编译期);它不校验运行时数据,不可信输入仍需 schema 校验器; - 类型守卫必须做真实运行时检查来收窄;仅当值真正未知(JSON 反序列化、用户输入)时才用
unknown作为入参类型;避免“伪造守卫”——只断言不校验。
类型转换
避免不必要的构造器/强制转换。必须转换时:字符串用`${value}`、布尔用!!value、数字用+value。
异步与控制流
- 返回 Promise 的函数必须声明
async;调用 async 函数必须await; - 大多数情况避免
.catch()/.then(),用async/await+try/catch让错误自然传播;.catch()仅用于确实无法await的场景(如useEffect清理),并用void显式标记有意的 fire-and-forget 调用; - 避免 IIFE,尤其不要用它规避 async 调用;
- 避免嵌套/链式三元表达式,用
if/else或switch;多值判断用switch;利用 TypeScript 穷尽性检查(尽量不用default)。
函数式模式与正则克制
- 多用
map、filter、find、some、every;避免reduce()(除非心智模型确实需要累加,如求和); - 避免复杂方法链,拆成具名中间步骤;
- 正则能不用就不用:优先
str.includes()、str.startsWith()、str.split()、str.replace();避免全局标志/g(lastIndex残留导致隐蔽 bug)与多行标志/m(平台换行差异);实在无法避免时保持简单、加注释解释模式、充分测试边界。
四、前端开发规范(React + Next.js)
组件架构与状态管理
- 不要在
apps/web新增/api端点,使用应用私有 tRPC API 与服务端工具; - 优先函数式、声明式组件;全站 TypeScript,对象形态用 interface;
- 优先
React.FC,按需使用PropsWithChildren与ComponentProps[WithRef|WithoutRef]; - 本地 UI 状态用
useState;跨组件共享用 React Context,但仅传 1–2 层时优先 props 而非新建 context;静态不变配置(用户 ID、API Key)不要建 context,直接 props 传递; - 最小化
useEffect,能派生状态就派生、能记忆就记忆;传给子组件的回调用useCallback; - 网络请求优先用 tRPC/React Query 的 loading 状态而非手维护 loading 标志,参考 devdocs/LOADING_STATES.md:该文档指出分析类查询若超过 200ms 会造成 UI 闪烁,要求同时解构
data与isLoading,并用 Skeleton 组件或禁用态替代纯 spinner,例如:
const { data: totalUsage, isLoading: isLoadingMessageUsage } = api.project.getTotalMessageUsage.useQuery( { period: messagesPeriod }, { enabled: !!session }, );布局、样式与排版
- Tailwind + shadcn 体系:布局用 flex/grid,间距用
gap-*与内边距(p-*、pt-*等); - 避免修改元素外边距(
m-*、mt-*等)与space-x-*/space-y-*;超长文本用text-ellipsis截断;Tailwind 用量保持克制,避免临场 CSS; - 字体体系:标题用 Sentient(
font-heading/font-sentient)、正文用 Geist Sans(font-sans)、代码用 Geist Mono(font-mono),配置见 apps/web/lib/fonts.ts。
JSX 模式与可访问性
- 避免手工改字符串大小写——若内部 key(如
agent_mode)需要展示给用户,应单独提供英文文案("Agent Mode")而非靠代码转写; - 避免超长 JSX:复杂 JSX 拆成独立组件;简单显隐用
&&;避免三元嵌套;map()内层 JSX 保持几行之内;JSX 内出现if/else、switch语句时(需要给 JSX 加大括号)就是应拆分组件的信号; - 全组件遵循可访问性规范:可点击元素用 button 而非 div/span;合理使用 aria 标签与角色;适当使用语义化 HTML。
五、后端开发规范(NestJS)
- 模块化结构:每个主路由/域一个模块,每个路由一个主 controller;输入用 DTO(class-validator),输出用简单类型;
- Service 封装业务逻辑,尽量保持纯函数;守卫/过滤器/拦截器通过核心模块提供,共享工具放共享模块;
- 错误处理:即使 controller 内也尽量保持逻辑纯净、不存状态;边界处(controller/service)适时转换为 HTTP/Nest 异常;
- 测试:公开函数做单元测试;controller/模块做集成或 e2e 测试,工具为 Jest + supertest(对应 apps/api/test 下的
app.e2e-spec.ts等)。
六、数据库规范(Drizzle ORM)
- Schema 事实来源是 packages/db/src/schema.ts,禁止手改生成的 SQL;
- 迁移必须用
npm run db:generate生成,禁止手工编写迁移; - 不要反范式化可由关系推导的外键:例如
runs.threadId已存在且 threads 有projectId,就不要给runs加projectId; - 数据库操作必须下沉到 packages/db/src/operations/:
apps/api的 Service 应调用 operation 函数而非内联写 DB 查询,并从packages/db/src/operations/index.ts导出新操作,以促进复用、集中管理 DB 逻辑。
数据库命令(从仓库根执行,需带-w packages/db):
npm run db:generate -w packages/db # 根据 schema 变更生成迁移 npm run db:migrate -w packages/db # 应用迁移 npm run db:check -w packages/db # 检查状态 npm run db:studio -w packages/db # 打开 Drizzle Studio从 packages/db/src/schema.ts 可以看到平台核心表(sessions、projects、projectMembers、apiKeys、threads、runs、messages、projectMessageUsage、deviceAuthCodes等),与 packages/db/migrations/ 下按序号排列的迁移文件(0000_init_setup.sql至0094_stiff_sentinel.sql)一一对应。
七、共享包与工具的分层约定
- packages/core:纯工具(校验、JSON、加密、线程、工具函数),禁止访问数据库,不应有任何数据库依赖;
- packages/backend:LLM/Agent 侧辅助与流式工具;
- 复用优先,禁止重复实现:跨包有用的工具放 core,LLM 专属放 backend,数据库相关放 db;
- 共享配置(ESLint、TypeScript config)集中在
packages/;跨包依赖使用 workspace 协议(*); @tambo-ai/typescript-sdk是外部依赖——它由apps/api的 OpenAPI spec 经stlcCLI 生成(CI 中运行,工作区在stainless/),详见 RELEASING.md。
八、开发工作流:命令体系与热重载机制
常用命令
# 开发(注意:这是两个不同的应用体系!) npm run dev:cloud # 启动 Tambo Cloud(web + API)- 端口 8260 + 8261 - 使用 turbo watch npm run dev # 启动 React SDK(showcase + docs) npm run dev:sdk # React SDK watch 模式 + showcase(SDK 开发用) npm run build:sdk # 一次性构建 React SDK # 质量检查 npm run lint # 全仓库 lint npm run lint:fix # 自动修复 lint 问题 npm run check-types # TypeScript 类型检查 npm test # 运行全部测试 npm run format # Prettier 格式化 # 单个包开发(从包目录或使用 -w 标志) npm run dev -w cli # 启动指定 workspace npm run dev:showcase # 仅启动 showcase npm run build -w react-sdk # 构建指定包热重载机制:按应用类型区分
Next.js 应用(web、showcase、docs):通过transpilePackages配置直接编译 workspace 的 TypeScript 源码,workspace 包(core、backend、db、react)的改动会自动触发 HMR,无需手动重建。
NestJS API:使用turbo watch配合interruptible: true自动重启,并监控 workspace 输入目录packages/core/src/**、packages/backend/src/**、packages/db/src/**,workspace 包变化时 API 服务自动重启。
这一架构可以从 turbo.json 的@tambo-ai-cloud/api#dev任务定义中得到印证:它声明了"persistent": true、"interruptible": true及上述inputs监听路径;根 package.json 的dev:cloud脚本正是turbo watch dev --filter=@tambo-ai-cloud/web --filter=@tambo-ai-cloud/api。效果是:编辑任意 workspace 包文件,Next.js 立即 HMR、NestJS 立即重启,全程无需人工干预。
Turbo 命令(替代方案)与构建系统
turbo dev # 以开发模式启动所有包 turbo build # 构建所有包 turbo lint # 全仓库 lint turbo test # 跨包运行测试 turbo check-types # 全仓库类型检查构建系统由 Turborepo 编排,共享依赖在根级管理,各包依赖在包内管理。构建产物按包类型区分:React SDK 双 CJS/ESM、CLI 为 ESM 可执行文件、应用为 Next.js 构建产物。跨包开发时的协作检查点:react-sdk 改动用npm run dev:sdk/build:sdk并跑测试与 showcase 集成验证;cli 改动要测试组件生成、验证注册表更新并同步 showcase;showcase 改动走 CLI 注册表(自动同步);docs 改动要确保示例与当前 API 一致。
关键配置文件与知识库
- turbo.json:Turborepo 任务流水线与缓存;
- package.json:workspace 配置与脚本;
- 各包 package.json:包级配置;
- 知识库:编码标准、命名规范、加载状态等详细指南见 devdocs/;新增解决方案知识时,写入 devdocs/solutions/ 对应目录。
九、测试与质量保障
测试策略
- 各包内单元测试用 Jest;
- 集成测试经 showcase 应用完成;
- CLI 测试通过模板生成与安装流程验证;
- 文档测试通过示例代码校验完成;
- 后端 e2e 测试(controller/module)用 Jest + supertest。
测试文件布局
- 文件命名:所有测试必须以
.test.ts或.test.tsx结尾(不接受.spec等后缀); - 单元测试:与被测文件同目录存放(
foo.ts旁放foo.test.ts,不放进__tests__); - 集成测试:是唯一允许放在
__tests__目录中的测试,且文件名必须描述场景(不能只是另一个文件名的镜像); - Fixtures 与 mocks:共享辅助统一放在包源码根目录的
__fixtures__或__mocks__目录(如 apps/web/mocks),严禁嵌套在功能目录内。
Mocking 纪律
- 避免过度 mock——测试应尽可能走真实代码路径;如果为了隔离单元而 mock 内部函数,很可能是在测实现细节而非行为;
- 只在系统边界 mock:外部 API、数据库、文件系统、网络调用及其他带副作用的 I/O;
- 不 mock 自己拥有的代码:纯且快的辅助函数直接调用;mock 自家代码会把测试与实现耦合。
提交/PR 前验证清单
npm run check-types # 全 workspace TS 类型检查 npm run lint:fix # ESLint 自动修复 npm run format # Prettier 写入 npm test # 单元/集成测试十、Git 工作流与 PR 规范
分支命名
格式为<userid>/<feature-name>,例如alecf/add-dark-mode、jane/fix-login-bug。
Conventional Commits
所有 PR 标题必须遵循<type>(scope): <description>格式,例如:
feat(api): add transcript export fix(web): prevent duplicate project creation chore(db): reorganize migration filestype 集合包括 feat、fix、perf、deps、revert、docs、style、chore、refactor、test、build、ci;常用 scope:api、web、core、db、deps、ci、config、react-sdk、cli、showcase、docs。
PR 要求
适用时在 PR 描述中写明 "Fixes #123"(GitHub)或 "Fixes TAM-123"(Linear)。
十一、Agent 开发规则与约束
必须做
- 提交前在根目录运行
npm run lint、npm run check-types、npm run test; - 跨包改动必须一起测试;
- 文档同步三件套:开发者文档变更必须同步到 docs 站点(先读 docs/AGENTS.md);检查并更新包根 README;更新包树中的 AGENTS.md 反映变更;
- 包版本遵循语义化版本;
- 新逻辑必须补测试;
- 测试失败时不要改代码硬凑测试,两条路:① 让代码改动向后兼容既有测试(优先);② 请用户修改测试。除非用户明确要求,不做破坏性变更,且必须提前警告。
禁止做
- 未经明确要求不得引入依赖或修改工具配置(eslint、tsconfig 等由人类负责);
- 不提交密钥,一律使用 env 文件。
何时询问用户
任何涉及 lint 或 TypeScript 规则的改动都必须先征求用户同意。
十二、Agent 行为准则与代码注释纪律
AGENTS.md 对 AI Agent 的行为姿态也做了明确规定:直接、坦率,不奉承用户,指令含糊时追问细节但不过度请求确认;每段代码都被视为“关键任务”。具体到代码产出:
- 编写 JSDoc 时务必补充
@returns描述函数返回值(不写类型,类型由 TS 推断); - 代码注释禁止引用规划文档、提案或设计文档(如
// See plans/foo.md)——这些产物生命周期短而注释永久存在,注释必须自包含; - 规划文档、提案、设计文档存入
devdocs/(解决方案放devdocs/solutions/、头脑风暴放devdocs/brainstorms/等),唯一例外是plans/保留在仓库根以便可见; - 注释与文档中的 Tambo 自有 URL 一律使用
tambo.co域名(不用旧.ai域名),遇到旧域名链接优先在相关改动中一并更新;外部(非 Tambo)链接不受限。
结语:让规范成为协作的地基
Tambo AI 的 AGENTS.md 本质上是一份“人与 AI 共写”的工程宪法:它用 Turborepo 单仓承载 SDK 框架与云平台两条产品线,用 Node.js 22 + mise 固化工具链,用 turbo watch + HMR 消除跨包开发的等待成本,再以严格但可执行的 TypeScript、前端、后端、数据库规范守住代码质量下限。无论你是人类开发者还是 AI Agent,只要遵循本文梳理的结构、命令与纪律——尤其是提交前的四项验证(check-types、lint:fix、format、test)与“Fail-Fast、不静默兜底”的核心哲学——就能在这个仓库中高效、低摩擦地推进功能,同时保持整个框架与平台的一致性。
【免费下载链接】hydra-aiGenerative UI SDK for React项目地址: https://gitcode.com/GitHub_Trending/hy/hydra-ai
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考