GSD Web 界面完整指南:浏览器化项目管理、实时监控与多项目协作

原创2026-09-28 23:00:411,718 阅读
文章标签:人工智能AI Agent代码智能体CLIMCP 服务前端

GSD Web 界面完整指南:浏览器化项目管理、实时监控与多项目协作

本文基于 GSD 仓库 docs/zh-CN/user-docs/web-interface.md 编写,并结合 src/、web/ 目录下的真实源码与集成测试,深入讲解 gsd --web 的启动方式、CLI 参数、架构原理与平台注意事项。读完本文,你将掌握如何在本机或局域网启动 GSD 的 Web 仪表板、在单标签页内管理多个项目、利用 Server-Sent Events(SSE)实时跟踪自动模式执行进度,以及如何避开 Node v24 与 Windows 平台上的已知坑点。

快速开始:一条命令打开 GSD 仪表板

GSD 从 v2.41.0 起提供了基于浏览器的 Web 界面(Web 模式)。与传统的 TUI 或命令行输出不同,Web 模式把 GSD 的里程碑(milestone)、切片(slice)与任务(task)可视化地呈现在仪表板中,适合项目管理、进度盯盘和多项目协同场景。

启动方式非常直接:

gsd --web

该命令会启动一个本地 Web 服务器,并在默认浏览器中打开 GSD 仪表板。除了 --web 标志,CLI 还支持等价的子命令形式。从 src/cli-web-branch.ts 的 runWebCliBranch 实现可以看出,gsd web、gsd web start [path]、gsd web <path> 都是 gsd --web [path] 的别名:

# 以下三种写法等价(均可附带项目路径)
gsd --web ./my-project
gsd web ./my-project
gsd web start ./my-project

当通过 --web 或子命令指定了项目路径时,CLI 会先校验路径是否存在,不存在则直接报错退出;随后还会调用 resolveContextAwareCwd 做“上下文感知启动”——如果你在 onboarding 中配置了 dev root,且当前目录位于该 root 下的某个项目内,它会自动解析到该项目目录,让浏览器打开后直接进入对应项目(src/cli-web-branch.ts)。

停止 Web 服务器同样有专门的子命令(源码见 src/web-mode.ts):

# 停止当前项目对应的 Web 实例
gsd web stop

# 停止指定项目的 Web 实例
gsd web stop /path/to/project

# 停止所有 Web 实例
gsd web stop --all

gsd web stop 的实现依赖 web-instances.json 实例注册表:每次启动时 src/web-mode.ts 会把 { pid, port, url, cwd } 写入注册表,停止时按 cwd 匹配并发送 SIGTERM;针对早期遗留的单实例 PID 文件也保留了向后兼容路径。

CLI 参数:host、port 与 CORS 来源(v2.42.0)

从 v2.42.0 开始,Web 模式支持三个可控参数(对应 CHANGELOG 中的 #1847 / #1873):

gsd --web --host 0.0.0.0 --port 8080 --allowed-origins "https://example.com"
参数 默认值 说明
--host localhost Web 服务器监听地址
--port 3000 Web 服务器端口
--allowed-origins (无) 允许的 CORS 来源列表,逗号分隔

这些参数在 src/cli-web-branch.ts 的 parseCliArgs 中被解析:

  • --host:直接存入 flags.webHost,最终作为 launchWebMode 的 host 选项传入。源码中定义的主机默认值实际为 127.0.0.1(见 src/web-mode.ts 的 DEFAULT_HOST),文档语义中的 localhost 与此一致;
  • --port:会先经过 parseInt 与范围校验(0 < port < 65536),非法值会被静默忽略;若未显式指定端口,launchWebMode 会调用 reserveWebPort 动态预留一个空闲端口(监听 0 号端口让操作系统分配,见 src/web-mode.ts),再通过 PORT/GSD_WEB_PORT 环境变量传给 Web host;
  • --allowed-origins:按逗号切分、去空格并过滤空项,可重复出现多次累加,最终以逗号拼接的 GSD_WEB_ALLOWED_ORIGINS 环境变量注入 Web 进程(见 src/web-mode.ts)。该变量用于本地代理层对浏览器跨源请求的放行控制。

需要说明:文档记载的默认端口为 3000;而源码层面,若完全不指定 --port,启动器会优先动态预留一个可用端口,避免与占用冲突。实际使用时,建议显式传 --port 以获得可预期的地址。

核心功能一览

  • 项目管理:在可视化仪表板中查看 milestones、slices 和 tasks;
  • 实时进度:通过 Server-Sent Events 在自动模式执行期间推送状态更新;
  • 多项目支持:通过 ?project= URL 参数,在单个浏览器标签页中管理多个项目;
  • 切换项目根目录:无需重启服务器即可在 Web UI 中切换项目目录(v2.44);
  • 首次引导流程:可在浏览器中完成 API key 设置和 provider 配置;
  • 模型选择:直接从 Web UI 切换模型和 provider。

其中“实时进度”的实现可以在仓库中找到直接证据:web/app/api/session/events/route.ts、web/app/api/terminal/stream/route.ts 与 web/app/api/bridge-terminal/stream/route.ts 均以 ReadableStream 构建流式响应,并设置 Content-Type: text/event-stream; charset=utf-8,这正是 SSE 的标准响应头。浏览器侧订阅该流即可获得自动模式执行期间的状态推送,无需轮询。

“切换项目根目录”则由前端状态管理层支撑:web/lib/project-store-manager.tsx 暴露 switchProject(projectCwd),web/components/gsd/projects-view.tsx 在项目视图里调用它并处理切换失败的错误提示。切换发生在 Web UI 内部,后端进程无需重启。

架构:Next.js + 按项目隔离的 Bridge 实例

Web 界面基于 Next.js 构建,并通过“桥接服务”(bridge service)与 GSD 后端通信。每个项目都会拥有自己的 bridge 实例,以便在并发会话中保持隔离。这一点与 src/web/bridge-service.ts 中的实现一一对应:projectBridgeRegistry 是一个 Map<string, BridgeService>,键为规范化后的项目路径。

关键组件:

  • ProjectBridgeService:按项目分配的命令路由和 SSE 订阅服务;
  • getProjectBridgeServiceForCwd():根据项目路径返回独立实例的注册表;
  • resolveProjectCwd():从请求 URL 中读取 ?project=,若不存在则回退到 GSD_WEB_PROJECT_CWD。

看具体源码。getProjectBridgeServiceForCwd(src/web/bridge-service.ts)先对传入路径做 resolve 归一化,再查注册表;命中则直接复用,未命中则基于该路径新建 BridgeService 并注册——这就是“每个项目一个 bridge、并发会话互不干扰”的机制来源。同一文件里的 BridgeService 类还维护了 idle → starting → ready → failed 的生命周期(BridgeLifecyclePhase),并实现了 bridge_status、live_state_invalidation 等事件广播(src/web/bridge-service.ts),供 Web 前端刷新工作区索引与自动模式仪表板。

resolveProjectCwd(src/web/bridge-service.ts)则负责请求维度的项目解析:

const url = new URL(request.url);
const projectParam = url.searchParams.get("project");
if (projectParam) return decodeURIComponent(projectParam);
// 兜底:GSD_WEB_PROJECT_CWD || null

配套的 requireProjectCwd 在项目上下文缺失时抛出 NoProjectError,保证 API 路由不会在“未选择项目”状态下执行错误操作。此外,每个 bridge 启动时会加载一个包含项目元信息、工作区索引(GSDWorkspaceIndex)、自动仪表板数据(AutoDashboardData)、onboarding 状态与可恢复会话列表的 Boot Payload(见 src/web/bridge-service.ts),Web 首页的 GET /api/boot 即返回该快照——launchWebMode 在启动后也是通过轮询 /api/boot 等待“就绪”(waitForBootReady,见 src/web-mode.ts)。

配置与环境变量

默认情况下,Web 服务器监听在 localhost:3000。如需覆盖,可使用 --host、--port 和 --allowed-origins(见上面的 CLI 参数)。

环境变量

变量 说明
GSD_WEB_PROJECT_CWD 当未指定 ?project= 时使用的默认项目路径

该变量的解析逻辑集中在 resolveBridgeRuntimeConfig(src/web/bridge-service.ts):

const projectCwd = projectCwdOverride || env.GSD_WEB_PROJECT_CWD || process.cwd();
const projectSessionsDir = env.GSD_WEB_PROJECT_SESSIONS_DIR || getProjectSessionsDir(projectCwd);
const packageRoot = env.GSD_WEB_PACKAGE_ROOT || getDefaultPackageRoot();

即优先级为:显式覆盖参数 > GSD_WEB_PROJECT_CWD > 当前工作目录。启动器在 launchWebMode 中会把该项目路径连同会话目录、包根目录、鉴权令牌与允许来源一起写入子进程环境(src/web-mode.ts),因此即便你手动 npm run dev 启动 Web 前端,也可以通过设置 GSD_WEB_PROJECT_CWD 来固定默认项目。

此外,源码还定义了与 Web 模式相关的其他环境变量,供调试与测试使用:GSD_WEB_PROJECT_SESSIONS_DIR(项目会话目录)、GSD_WEB_PACKAGE_ROOT(包根目录)、GSD_WEB_ALLOWED_ORIGINS(允许的 CORS 来源)、GSD_WEB_HOST / GSD_WEB_PORT、GSD_WEB_AUTH_TOKEN 与 GSD_WEB_HOST_KIND。集成测试(如 src/tests/integration/web-bridge-contract.test.ts)普遍通过注入 GSD_WEB_PROJECT_CWD 来固定被测项目。

认证与令牌持久化

从 v2.42.0 起,Web UI 会把认证令牌持久化到 sessionStorage,因此页面刷新后不会丢失登录态(对应 CHANGELOG 中的 #1877)。在此之前,每次刷新都需要重新认证。

令牌的注入链路在源码中同样可见:launchWebMode 启动时生成 32 字节随机令牌(randomBytes(32).toString('hex')),并在浏览器打开时拼接到 URL 的 hash 片段中——${url}/#token=${authToken}(src/web-mode.ts)。前端拿到令牌后写入 sessionStorage,后续请求通过代理层校验(例如 web/lib/auth-guard.ts 的 verifyAuthToken 被多个管理类 API 路由引用,作为纵深防御的二次校验)。这既保证了本地访问的便捷性,又避免了令牌在历史记录中直接暴露为可共享的完整 URL。

Node v24 兼容性

Node v24 对类型剥离(type stripping)做了破坏性改动,曾导致 Web 启动时报 ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING。该问题已在 v2.42.0+ 中修复(CHANGELOG 中对应 #1864)。如果你仍然遇到这个错误,请先升级 GSD 到 v2.42.0 或更高版本。

仓库中保留了针对此场景的集成测试 src/tests/integration/web-boot-node24.test.ts:测试会构造 Node 24 环境下 GSD_WEB_PROJECT_CWD 指向的工程,并断言 Web 进程能够正常完成 boot 快照加载。此外,bridge 侧对子进程脚本的执行也做了兼容处理——bridge-service.ts 通过 resolveTypeStrippingFlag 与 resolveSubprocessModule(src/web/ts-subprocess-flags.ts)决定是否需要附加 --experimental-strip-types 等前缀参数,从而在多个 Node 主版本下都能以子进程方式加载 TS 模块。

平台说明

  • Windows:由于 Next.js webpack 在系统目录上会触发 EPERM 问题,Windows 下会跳过 Web 构建。CLI 仍然可完整使用。换言之,Windows 用户可以用 GSD 的全部 CLI、TUI 与 headless 能力,但无法使用浏览器仪表板;
  • macOS / Linux:完整支持,包括 Web 构建、仪表板、SSE 实时推送与多实例管理。

从启动器源码可以进一步印证:resolveWebHostBootstrap 会优先查找打包产物 dist/web/standalone/server.js(packaged-standalone 形态),找不到则回退到源码目录 web/ 并执行 npm run dev(source-dev 形态,见 src/web-mode.ts);Windows 下若宿主为源码形态,会使用 npm.cmd 并通过 shell: true 启动。而 Windows 构建被跳过意味着发行包中不会携带 dist/web/standalone,这正是 EPERM 问题的规避方式。

小结与排障要点

GSD 的 Web 界面把“规格驱动的多里程碑项目执行”搬进了浏览器:一条 gsd --web 命令即可获得仪表板;--host / --port / --allowed-origins 三个参数与 GSD_WEB_PROJECT_CWD 环境变量共同决定服务的网络面与默认项目;按项目隔离的 bridge 实例保证了多项目、多会话的并发安全;SSE 流让自动模式的进度实时可见。

实际使用中遇到问题时,可按以下顺序自查:

  1. 端口冲突或地址不可达:显式指定 --port 8080,并确认 --host 使用的是 0.0.0.0(局域网访问)还是 127.0.0.1(仅本机);
  2. 跨源被拦截:检查 --allowed-origins 是否包含了浏览器页面所在的源;
  3. Node v24 下 ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING:升级到 v2.42.0+;
  4. Web 打开的是错误项目:优先通过 ?project=<绝对路径> 指定,或在启动时传入 GSD_WEB_PROJECT_CWD;
  5. 怀疑后端与 Web 前端脱节:参考 src/web/bridge-service.ts 的 bridge 生命周期状态机与 src/tests/integration/web-bridge-contract.test.ts 中约定的 API 契约。

更多命令与参数可参考 gitbook/reference/cli-flags.md,版本演进记录见 CHANGELOG.md。

登录后查看全文
gsd-2