首页
/ Cypress cy.prompt 开发指南:本地 Bundle 调试、类型同步与云端投递机制

Cypress cy.prompt 开发指南:本地 Bundle 调试、类型同步与云端投递机制

2026-09-05 18:40:48作者:戚魁泉Nursing

本文基于仓库内 guides/cy-prompt-development.md 的原始开发流程编写,覆盖 cy.prompt 命令在本地 cypress-services 与已部署环境下的完整调试方案、downloadPromptTypes 类型同步任务的用法,并结合 Cypress 主仓库源码深入讲解云侧 Bundle 的加载、哈希校验、热重载与错误上报等底层机制。读完后你可以独立搭建 cy.prompt 本地开发环境,并理解生产二进制中相关逻辑是如何被剥离与保护的。

1. 背景:cy.prompt 代码来自 Cloud 而非主仓库

在 CYPRESS 开发文档中说明:生产环境中,支撑 cy.prompt 命令的代码是从 Cloud 获取的。也就是说,cypress monorepo 本身并不包含 prompt 的具体实现,它只包含“加载、校验、挂载、错误上报”这一层基础设施;真正的 bundle 由 cypress-services 仓库(独立 monorepo)构建后发布,运行时按 hash 从云端下载。

这个“云投递 bundle(cloud-delivered bundle)”模型在源码中体现得非常清晰:

  • 生命周期管理:CyPromptLifecycleManager,负责会话创建、bundle 下载、哈希校验、本地 watch 热重载;
  • 运行时管理:CyPromptManager,负责 require 加载 bundle 的 server/index.js 并暴露 initializeRoutesaddSocketListenersconnectToBrowserreset 等同步方法;
  • Bundle 下载:ensure_cy_prompt_bundle.ts 复用通用的签名 bundle 下载逻辑(ensureSignedBundle),返回 manifest(文件名到 sha256 的映射)和 bundle 目录;
  • 会话 API:post_cy_prompt_session.ts 向 Cloud 的 cy-prompt/session 路由(定义于 routes.ts)发起带指数重试的 POST 请求,请求体固定携带 cyPromptMountVersion: 2
  • 共享类型定义:packages/types/src/cy-prompt/index.ts 声明了 CY_PROMPT_STATUSESNOT_INITIALIZED / INITIALIZING / INITIALIZED / IN_ERROR)以及 CyPromptManagerShapeCyPromptLifecycleManagerShape 等跨包接口。

理解了这层架构,再来看开发文档中“本地 vs 部署”两套环境变量的设计就顺理成章了:开发者要么用已部署的 bundle(只切 Cloud 环境),要么用本地构建的 bundle(额外提供本地路径,跳过下载与校验)。

2. 本地开发模式:基于 cypress-services 仓库调试

文档给出的本地调试流程如下,完整继承自 cy-prompt-development.md

2.1 构建并 watch 本地 bundle

  1. 克隆 cypress-services 仓库;
  2. 在仓库根目录执行 yarn && yarn all
  3. 进入 app/packages/cy-prompt 目录执行 yarn watch,持续产出构建产物。

2.2 设置环境变量

环境变量 取值示例 作用
CYPRESS_INTERNAL_ENV staging / production / development 指定请求哪个 Cloud 部署。staging/production 用于访问对应的 cypress-services 部署环境;development 用于访问本地运行的 cypress-services
CYPRESS_LOCAL_CY_PROMPT_PATH cypress-services/app/packages/cy-prompt/dist/development 目录的绝对路径 指向本地构建产物目录,Cypress 将直接从该目录加载 bundle 而不是从 Cloud 下载

CYPRESS_LOCAL_CY_PROMPT_PATH 在源码中的关键行为(均见 CyPromptLifecycleManager.ts):

  • 跳过哈希校验createCyPromptManager 中,未设置该变量时会对 cyPromptUrl 解析出 bundle hash,下载后计算 server/index.js 的 sha256 并与 manifest 中记录的期望哈希比对,不一致则抛出 Invalid hash for cy prompt server script(约 L212-L227);设置该变量后则直接把路径当作 bundle 目录,cyPromptHash 置为 'local'manifest 置为空对象(L206-L210),完全跳过下载与校验。
  • watch 模式热重载setupWatcher(L286-L322)仅在设置该变量时启动 chokidar 监听 <CYPRESS_LOCAL_CY_PROMPT_PATH>/server/index.js。文件变化(awaitWriteFinish: true,即等待写入完成后触发)时重新执行 createCyPromptManager,实现改一行代码即重载的效果。watcher 的关闭还通过 GracefulExit 注册为退出步骤,保证进程退出时资源被清理。
  • 监听器不一次性消费callRegisteredListeners 回调所有已注册的 ready 监听器后,云端模式下会清空监听器列表(一次性);本地模式下保留监听器,这样每次热重载都能再次触发它们(L255-L270)。同理,registerCyPromptReadyListener 在本地模式下若 manager 已就绪,会既立即调用又追加到列表(L329-L344)。
  • 跳过签名验证CyPromptManager.tssetup 向 bundle 注入的 verifyHash 回调里,只要 CYPRESS_LOCAL_CY_PROMPT_PATH 存在就直接返回 true(L41-L43),注释明确写道:本地运行时无需校验,且“该环境变量会在二进制中被剥离”。
  • 错误不进 Sentryreport_cy_prompt_error.ts(L52-L61)中,若设置了该变量(或 NODE_ENV === 'development'CYPRESS_INTERNAL_E2E_TESTING_SELF),错误只 console.error 到控制台而不回传 Cloud 的 /cy-prompt/errors 端点——本地调试时避免污染遥测数据。

对应的单测位于 CyPromptLifecycleManager_spec.tsreport_cy_prompt_error_spec.ts,其中明确覆盖了 “CYPRESS_LOCAL_CY_PROMPT_PATH 设置时进入 watch 模式”“立即调用并保留监听器”“不向 Sentry 上报”等场景。

2.3 启动 Cypress 并登录 Cloud

无论使用本地还是部署版 bundle,Cypress 主仓库侧的操作相同:

  1. 克隆 cypress 仓库;
  2. 执行 yarn
  3. 执行 yarn cypress:open
  4. 通过 App 登录 Cloud。

注意一个容易忽略的细节:即使设置了 CYPRESS_LOCAL_CY_PROMPT_PATHpostCyPromptSession 的会话请求仍然会发起(见 L184-L186 的调用顺序),因为会话接口还承担鉴权与元数据职责,本地模式只是跳过了后续的 bundle 下载。

2.4 Cloud 环境如何被解析

CYPRESS_INTERNAL_ENV 的消费点见 get_cloud_metadata.ts

const cloudEnv = (process.env.CYPRESS_CONFIG_ENV || process.env.CYPRESS_INTERNAL_ENV || 'production') as 'development' | 'staging' | 'production'
const cloudUrl = cloudDataSource.getCloudUrl(cloudEnv)

即优先级为 CYPRESS_CONFIG_ENV > CYPRESS_INTERNAL_ENV > 默认 production,据此选择对应的 Cloud URL。而 Gulp 任务侧在 gulpCloudDeliveredTypes.ts 首行也做了 process.env.CYPRESS_INTERNAL_ENV ??= 'production' 的兜底。

3. 类型同步:downloadPromptTypes 任务

文档 “Types” 一节指出:prompt bundle 会为 appdriverserver 三个接口提供类型定义,需要将其纳入主代码库。同步命令:

yarn gulp downloadPromptTypes

或指向本地 cypress-services 仓库的产物目录:

CYPRESS_LOCAL_CY_PROMPT_PATH=<path-to-cypress-services/app/packages/cy-prompt/dist/development-directory> yarn gulp downloadPromptTypes

任务实现位于 scripts/gulp/tasks/gulpCloudDeliveredTypes.ts,并注册于 gulpfile.ts。其执行逻辑为:

  1. 未设置 CYPRESS_LOCAL_CY_PROMPT_PATH:调用 postCyPromptSession({ projectId: 'ypt4pf' }) 获取 bundle URL,从 URL 末段提取 hash 作为目录名(getBundlePath,L24-L32,存放于 os.tmpdir()/cypress/cy-prompt/<hash>),再通过 ensureCyPromptBundle 下载并校验 bundle;
  2. 已设置该变量:直接以本地路径为源,跳过会话与下载;
  3. 按映射表复制类型文件。prompt 的三处映射(createPromptTypeMappings,L83-L98)为:
bundle 内源文件 主仓库目标文件
app/types.ts packages/app/src/prompt/prompt-app-types.ts
driver/types.ts packages/driver/src/cy/commands/prompt/prompt-driver-types.ts
server/types.ts packages/types/src/cy-prompt/cy-prompt-server-types.ts

这也解释了为什么 packages/types/src/cy-prompt/cy-prompt-server-types.ts 里的 CyPromptServerShape 等方法签名在 monorepo 中看似“凭空出现”——它是云侧构建产物的同步副本。同文件中还有结构完全对称的 downloadStudioTypes 任务(对应 CYPRESS_LOCAL_STUDIO_PATH),说明 prompt 与 studio 共用同一套 cloud-delivered types 基础设施。

4. 生产二进制中的剥离保护

本地开发能力必须不能泄漏进分发给用户的二进制。scripts/binary/binary-sources.jsgetCyPromptFileSource(L122-L130)在打包阶段执行:

if (!fileContents.includes('process.env.CYPRESS_LOCAL_CY_PROMPT_PATH')) {
  throw new Error(`Expected to find CYPRESS_LOCAL_CY_PROMPT_PATH in cy prompt file`)
}
return fileContents.replaceAll('process.env.CYPRESS_LOCAL_CY_PROMPT_PATH', 'undefined')

随后 validateCyPromptFile(L148-L154)复核产物中确实不再包含该环境变量。这意味着发布二进制中所有 process.env.CYPRESS_LOCAL_CY_PROMPT_PATH 判断恒为 falsy:哈希校验强制执行、watch 永不启用、错误始终上报 Cloud。这也与 CyPromptManager.ts 中“该环境变量会在二进制中被剥离”的注释相互印证。

5. 测试策略

文档 “Testing” 一节说明了两处测试的分工:

  • cypress monorepo 侧(支撑 cy.prompt 的云侧基础设施代码):按仓库统一的 unit / integration / e2e 分层测试,具体规范见 CONTRIBUTING.md。典型用例即前文提到的 CyPromptLifecycleManager_spec.ts(watch 模式、监听器生命周期、本地路径分支)与 report_cy_prompt_error_spec.ts(本地模式只打印不上报)。
  • cypress-services monorepo 侧(prompt 业务实现本身):单元测试与该仓库内代码同目录存放,随 bundle 工程独立维护。

对贡献者而言的实践含义是:改动主仓库中 cy-prompt 加载/校验逻辑后,应运行 packages/server 下对应的 vitest 单测并检查快照;改动 prompt 行为本身则需在 cypress-services 仓库走其自身的测试与发布流程,再通过第 2 节的 yarn watch + CYPRESS_LOCAL_CY_PROMPT_PATH 链路在主仓库中端到端验证。

6. 小结

  • 本地调试 cy.prompt 的核心是三件套:cypress-servicesyarn watch 持续构建、CYPRESS_LOCAL_CY_PROMPT_PATH 指向 dist/developmentCYPRESS_INTERNAL_ENV 选择目标 Cloud 环境(development 指向本地 cypress-services 服务);
  • 类型同步靠 yarn gulp downloadPromptTypes(可复用同一个本地路径变量指向本地产物);
  • 从源码结构看,本地模式在哈希校验、watch 热重载、错误上报三个维度与云端模式行为差异明确,且这些差异在二进制打包阶段会被强制剥离,保证生产路径始终走 Cloud 校验流程;
  • 测试分层遵循 monorepo 既有约定,主仓库测试覆盖“加载器”,cypress-services 仓库测试覆盖“bundle 本体”。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384