Mastra Studio Vercel PR 预览指南:独立 Workspace、种子数据与 Serverless 构建全解析
2026/9/13 3:42:08 网站建设 项目流程

Mastra Studio Vercel PR 预览指南:独立 Workspace、种子数据与 Serverless 构建全解析

【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra

本文围绕 Mastra 仓库中的 Studio Preview 应用(packages/playground/vercel-preview)展开,讲清楚它如何作为 Mastra Studio 的 Vercel PR 预览目标:如何以独立 workspace 的方式被部署、如何用内存存储与确定性种子数据让 Studio 各页面开箱即有数据,以及本地安装、Vercel 项目配置、模型选择与链接依赖构建的完整实操链路。读完后你能复现一个“打开预览 URL 即可测试可用 Agent 页面”的 Studio 预览环境,并理解其中每个关键设计(独立 lockfile、link:依赖、冷启动重新种子化)背后的源码依据。

这个应用是什么,为什么放在 packages/playground 里

Studio Preview 是 Mastra Studio 的 Vercel PR 预览目标应用:它把 Studio 前端和一个最小化的 Mastra API 一起部署,评审人打开预览 URL 就能测试一个真正可运行的 Agent 页面。

从源码结构看,该应用刻意与 monorepo 其余部分保持隔离,核心机制是其自带的 pnpm-workspace.yaml:

packages: - '.' pnpm: overrides: hono@<4.12.34: 4.12.34 # a dependency install script this project never needed must not fail a preview deploy strictDepBuilds: false

packages: ['.']使该目录成为自己的 workspace root:它拥有独立的 pnpm-lock.yaml,永远不会作为 monorepo 的一部分被安装。仓库原 README 指出这样做的目的有二:

  • 它只是内部预览基础设施,不属于发布产物,monorepo 特有的模式(link:依赖、根目录 turbo 构建)不应被复制到面向用户的示例中;
  • 该目录的任何改动对 turbo 和 changeset-bot 来说都算 playground 变更。这一代价被接受——因为应用很少变更,且纯预览用途的修改无需 changeset。

应用定位(package.json)也印证了其内部工具属性:

{ "name": "studio-preview", "type": "module", "private": true, "version": "0.0.0", "license": "Apache-2.0", "packageManager": "pnpm@11.21.0+sha512...." }

private: true保证它不会被意外发布;自带的packageManager字段固定了 pnpm 版本,供后面的依赖安装脚本读取。

Serverless 友好的应用设计

README 明确该应用是“intentionally serverless-friendly”的,源码中每一条约束都有对应实现:

  • 仅内存存储——无文件型存储,无 LibSQL / DuckDB 依赖。store.ts 只有一行核心代码:
import { InMemoryStore } from '@mastra/core/storage'; export const storage = new InMemoryStore();

注释强调这个实例同时交给 Mastra、Agent 的Memory和种子例程使用,因此种子写入的数据都能通过 Studio 实际查询的那几个 store 读回。

  • 一个确定性工具——preview-status.ts 定义了preview-status工具,输入是一个枚举areastudio | agent | api | vercel),返回对应区域的确定性检查清单(如 “Mastra API routes are served under /api/*”)和status: 'ready'。它不访问任何外部服务,评审人可以拿它验证工具执行链路是否打通。

  • 一个启用 Memory 的 Agent——studio-preview-agent.ts 中注册了studio-preview-agent,可在/agents/studio-preview-agent/chat/new打开。它启用 Memory 但只保留历史消息、关闭语义召回:

memory: new Memory({ storage, options: { lastMessages: 20, semanticRecall: false, }, }),

注释说明这样做的效果:聊天侧边栏会报告 memory 可用,种子线程能显示出来,且实时聊天也持久化到同一个共享内存 store。同文件还注册了一个editorShowcaseAgent——它不持有 instructions/tools,而是通过editor: { instructions: true, tools: true }声明这两项由 Studio Editor 接管,专门用于演示编辑器版本管理流程。

  • 启动时种子化的确定性演示数据——见下一节。

Mastra 实例的入口把这些部件组装起来,其中几处配置值得注意:

export const mastra = new Mastra({ agents: { studioPreviewAgent, editorShowcaseAgent }, tools: { previewStatusTool }, editor: new MastraEditor({ source: 'db' }), scorers: previewScorers, storage, bundler: { sourcemap: true }, deployer: new VercelDeployer({ studio: true, maxDuration: 60 }), server: { build: { openAPIDocs: true, swaggerUI: true } }, }); void seedStudioPreview();

源码注释解释了两个关键取舍:

  1. Editor 必须用source: 'db'而非'code'——code 模式会拉起 FilesystemStore 并尝试mkdir一个mastra/editor目录,在 Vercel 只读的 serverless 文件系统上会抛 ENOENT 并让所有 API 路由 504;db模式把编辑器数据留在共享内存 store 里,随冷启动一起重置。
  2. 种子调用是void seedStudioPreview()故意不 await——写入是同步且极快的,这样种子永远不会阻塞服务启动。

种子演示数据:确定性、免调用、24 小时窗口内

启动时应用会向共享内存 store 写入一套共享演示数据,让评审人无需手动创建任何东西即可预览 Studio 中数据密集的页面。按 README 的清单:

  • Threads——预览 Agent 的几个带消息的聊天线程(Agent 聊天页侧边栏);
  • Traces——带 model 与 tool span 的 Agent 运行(Observability 页面);
  • Metrics——token 用量、模型成本、agent/tool 延迟、活跃线程/资源,全部落在默认 24 小时窗口内(对应 Model Usage & Cost、Token usage by agent、Traces volume、Latency、Memory 卡片);
  • Scores——两个确定性 scorer(answer-relevancetone-quality)的分数行与聚合;
  • Datasets——两个带条目的数据集。

这套数据“确定且免费产生”——不发起模型调用,种子本身不需要任何 provider key。

种子写入的实现细节

seed.ts 的seedStudioPreview有三个工程特征:

  1. 进程内幂等:种子 Promise 被 memoize,重复调用只执行一次;
  2. 域间隔离:memory / observability / scores / datasets 四个域各自 try/catch,一个域失败不影响其他域写入;
  3. 写入路径与 Studio 查询路径一致:直接调用storage.getStore('memory' | 'observability' | 'scores' | 'datasets')saveThreadsaveMessagesbatchCreateSpansbatchCreateMetricssaveScorecreateDatasetbatchInsertItems等真实存储 API。

seed-data.ts 的头部注释解释了数据构造策略:

  • 所有时间戳相对now(冷启动时刻)计算,保证永远落在 Studio 默认指标窗口的最近 24 小时内;
  • 无随机数——同样的now产生同样的数据,预览可复现;
  • 指标名称与列 key 精确镜像 Studio 各指标卡片的查询方式,因此表格能直接渲染出内容。

示例数据中还包括固定的模型目录(gpt-4o-minigpt-4o及其 per-1M token 美元费率)和几个虚构的调用方会话(web-session-anitaapi-key-acme等),用来填充 Memory 的“top resources / threads”表格。

为什么“不持久”是刻意为之

因为 store 是内存型的,它不持久:每次冷启动各自进程重新种子化。演示数据因此永远存在,但预览会话中实时创建的内容可能不会跨 serverless 实例存活。README 强调这一点“对预览场景是有意为之”——评审者要的是“打开就有数据”,不是真实状态。

两个 scorer 的实现(preview-scorers.ts)也贯彻“免费且确定”的原则:

export const answerRelevanceScorer = createScorer({ id: 'answer-relevance', type: 'agent', }).generateScore(() => 0.9); export const toneQualityScorer = createScorer({ id: 'tone-quality', type: 'agent', }).generateScore(() => 0.82);

固定分数替代 LLM judge,因此无论种子还是实时 Agent 运行,打分都不产生额外模型调用。

本地使用

README 给出的本地命令是从仓库根目录执行(该应用是独立 workspace root,所以用--dir进入):

pnpm --dir packages/playground/vercel-preview install --frozen-lockfile pnpm --dir packages/playground/vercel-preview build

本地 Studio 开发则先复制环境变量模板再启动 dev:

cp packages/playground/vercel-preview/.env.example packages/playground/vercel-preview/.env pnpm --dir packages/playground/vercel-preview dev

模板 .env.example 的内容:

OPENAI_API_KEY= # ANTHROPIC_API_KEY= # MASTRA_PREVIEW_MODEL=__GATEWAY_OPENAI_MODEL_BASE__

对照 package.json 的脚本可以看到dev/build都会先执行build:linked-workspace-deps(即 scripts/build-linked-workspace-deps.mjs),再执行mastra:build/mastra:dev——后者实际调用的是仓库内packages/cli/dist/index.jsbuild/dev子命令。这意味着本地运行前需要先构建好 monorepo 里的 CLI 产物。

Vercel 项目配置与环境变量

为整个仓库创建一个 Vercel 项目并指向该应用。README 特别提示:如果项目早于本次从examples/迁出,需要把 Root Directory 设置从examples/studio-preview更新为packages/playground/vercel-preview,否则迁移前创建的分支预览会在 rebase 前持续失败。

配置项如下:

  • Root Directory:packages/playground/vercel-preview
  • Build Command:pnpm build
  • Install Command:pnpm install --frozen-lockfile
  • Output Directory:留空
  • Node.js Version:22.x
  • Root Directory 设置:允许使用 root 目录之外的源文件

仓库的 vercel.json 与上述一致,并额外在构建命令前注入了环境变量:

{ "installCommand": "pnpm install --frozen-lockfile", "buildCommand": "MASTRA_AGENT_SIGNALS=false pnpm build" }

预览部署策略方面,README 建议在 Vercel 项目中把预览部署限定为“仅 PR 生成”;由于仓库本身不包含分支 allowlist 或生产跳过脚本,生产部署行为应在 Vercel 项目设置中控制。

Preview 部署需要配置以下环境变量:

OPENAI_API_KEY=...

也可以配置 Anthropic:

ANTHROPIC_API_KEY=...

若两者同时配置,Studio 的模型控件会同时展示这两个已连接 provider。

模型选择逻辑:MASTRA_PREVIEW_MODEL 与回退链

README 说明预览 Agent 默认优先 OpenAI(若已配置),否则回退 Anthropic;也可用MASTRAs_PREVIEW_MODEL(源码中为MASTRA_PREVIEW_MODEL)覆盖默认模型,取值为占位 token(如__GATEWAY_ANTHROPIC_MODEL_SONNET__)或具体provider/modelID。

studio-preview-agent.ts 给出了完整解析链:

const PREVIEW_MODEL_TOKENS: Record<string, string> = { __GATEWAY_OPENAI_MODEL_BASE__: 'openai/gpt-5', __GATEWAY_ANTHROPIC_MODEL_SONNET__: 'anthropic/claude-sonnet-4-6', }; function resolvePreviewModel() { if (process.env.MASTRA_PREVIEW_MODEL) { return PREVIEW_MODEL_TOKENS[process.env.MASTRA_PREVIEW_MODEL] ?? process.env.MASTRA_PREVIEW_MODEL; } if (process.env.OPENAI_API_KEY) return PREVIEW_MODEL_TOKENS.__GATEWAY_OPENAI_MODEL_BASE__; if (process.env.ANTHROPIC_API_KEY) return PREVIEW_MODEL_TOKENS.__GATEWAY_ANTHROPIC_MODEL_SONNET__; return PREVIEW_MODEL_TOKENS.__GATEWAY_OPENAI_MODEL_BASE__; }

即:显式设置的MASTRA_PREVIEW_MODEL(占位 token 或provider/model)> 有OPENAI_API_KEY时用openai/gpt-5> 有ANTHROPIC_API_KEY时用anthropic/claude-sonnet-4-6> 兜底仍为 OpenAI 默认模型。注释解释了 token 常量为何本地硬编码而非从 docs 导入:导入 docs 会把其未安装的 tsconfig 拖进 deployer 分析。

链接依赖与构建链:预览永远跑当前分支的代码

README 中最有深度的一段说明了为什么预览不会用到任何“发布版本”的 Mastra 包:package.json 中所有用到的 Mastra 包都是link:依赖——

"dependencies": { "@mastra/core": "link:../../../packages/core", "@mastra/deployer-vercel": "link:../../../deployers/vercel", "@mastra/editor": "link:../../../packages/editor", "@mastra/memory": "link:../../../packages/memory", "hono": "^4.12.34", "zod": "^4.4.3" }, "devDependencies": { "mastra": "link:../../../packages/cli", "turbo": "^2.9.12", ... }

因此预览永远运行当前分支的代码,也不存在“发布版本 pin 漂移出 peer 依赖范围”的问题。

build/dev前置的build:linked-workspace-deps步骤由 build-linked-workspace-deps.mjs 实现,它解决“turbo 远端缓存 miss”时的构建问题:

  1. 读取仓库根package.jsonpackageManager字段,取出 pnpm 版本号;
  2. 在仓库根用该 pnpm 版本执行install --frozen-lockfile,按--filter <name>...安装五个链接包(mastra@mastra/deployer-vercel@mastra/core@mastra/memory@mastra/editor)的完整依赖图;
  3. 调用应用自己 node_modules 里 pin 死的 turbo(注释说明:脚本必须在脱离pnpm run.bin不在 PATH 的场景下也能工作)在仓库根执行build --concurrency=2,只构建这五个链接包——低并发是为把峰值内存控制在 Vercel 预览构建器的限额内。

脚本注释点明了触发场景:远端缓存 miss = turbo 会真正构建链接包,此时必须先把根工具链装好。最终 Vercel 只部署该应用生成的产物,而不是整个仓库。

构建完成后,Vercel 使用生成的.vercel/output文件夹,路由约定为:

  • Studio 前端服务在/
  • Mastra API 服务在/api/*之下(preview-status工具的检查清单也佐证了这一点,如GET /api/agents)。

推荐预览 URL 清单与安全注意

README 给出了一份验收用的推荐预览 URL 清单,评审 PR 时可逐项打开:

URL预览内容
/Studio 外壳
/agentsAgent 列表
/agents/studio-preview-agent/chat/new可用的 Agent 聊天(侧边栏带种子线程)
/observability种子化的 traces
/metrics种子化的用量、成本、延迟与内存指标
/scorers种子化的 scorers 与 scores
/datasets种子化的数据集与条目

安全方面,README 的最后一条建议:在广泛公开预览之前,用 Vercel Deployment Protection 或 Studio auth 保护该项目——因为 Studio 可以访问 Mastra server 暴露的全部 agents、tools 和 workflows。

小结

Studio Preview 应用展示了 Mastra 一套可借鉴的“框架自举”实践:用pnpm-workspace.yaml把内部工具隔离成独立 workspace root;用InMemoryStore+ 进程内幂等种子换取 serverless 场景下的零外部依赖;用link:依赖 + 前置依赖图安装脚本保证预览代码与当前分支严格一致;用preview-status工具、确定性 scorer 与 24 小时窗口内的种子数据构成一套无需模型调用即可验收的 PR 预览清单。对照 README、vercel.json 与 src/mastra 目录 下的源码,即可完整复现这套预览基础设施。

【免费下载链接】mastraMastra is the modern TypeScript framework for AI-powered applications and agents.项目地址: https://gitcode.com/GitHub_Trending/ma/mastra

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

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

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

立即咨询