尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

qwen-code 守护进程工作区持久化注册(Persistent Workspace Registration)设计与实现解析

qwen-code 守护进程工作区持久化注册(Persistent Workspace Registration)设计与实现解析 qwen-code 守护进程工作区持久化注册Persistent Workspace Registration设计与实现解析【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code导读本指南围绕 qwen-code 中qwen serve守护进程daemon的工作区持久化注册Persistent Workspace Registration机制展开讲解如何让 Web Shell 中动态添加的次级工作区secondary workspace在守护进程以相同主工作区与QWEN_HOME重启后自动恢复。读完本文你将掌握该机制的存储布局、生命周期与恢复流程、管理 API 契约、安全与故障处理边界以及它与源码实现workspace-registration-store.ts、workspace-management.ts、run-qwen-serve.ts之间的对应关系能够直接基于该能力设计自己的持久化工作区管理方案。一、设计目标动态工作区在重启后依然可用qwen serve以主工作区 若干次级工作区的方式运行Web Shell 可以通过管理 API 动态注册额外的次级工作区。在持久化注册机制引入之前这些动态注册是进程内状态守护进程一旦重启所有动态加入的工作区全部丢失用户不得不在每次重启后重新添加。本设计的目标非常聚焦当守护进程以相同的主工作区primary workspace和相同的QWEN_HOME重新启动时Web Shell 中曾添加的工作区能够自动恢复无需人工重新注册。相关设计文档见 docs/design/2026-07-11-daemon-persistent-workspace-registration.md。这里的关键约束是相同的QWEN_HOME与相同的主工作区持久化存储按主工作区做作用域划分详见下一节因此换一个主工作区或换一个QWEN_HOME目录恢复的集合也随之不同。二、状态归属与存储布局2.1 谁拥有这份状态设计文档明确了状态归属原则动态工作区注册是用户私有的守护进程配置既不是项目配置也不是一次性的运行时输出。因此它被存放在守护进程自己的数据目录而不是任何被管理的工作区目录内。2.2 存储路径与作用域哈希注册文件存放路径为${QWEN_HOME:-~/.qwen}/daemon/workspaces/primary-scope-sha256.json其中QWEN_HOME默认取~/.qwen可通过环境变量覆盖primary-scope-sha256是主工作区规范化路径的完整 SHA-256 十六进制摘要Windows 平台先转小写再哈希见 workspace-registration-store.ts 中的normalizedScopePath与workspaceRegistrationScopeHash该作用域哈希使得同一台机器、不同主工作区的守护进程互不串扰各自的注册集合彼此隔离。存储文件的实际路径由getWorkspaceRegistrationStorePath计算workspace-registration-store.ts目录落在getGlobalQwenDirLite()返回的全局 qwen 目录下。2.3 文件内容与 schema文件为 JSON 格式schemaVersion当前为 1。文档给出的典型结构如下{ schemaVersion: 1, primaryWorkspace: /repo/main, workspaces: [/repo/service-a] }从源码看文件内部还支持可选的displayNames映射workspace-registration-store.ts用于持久化工作区的显示名其键为注册 IDworkspaceRegistrationId值是经过校验的显示名字符串{ schemaVersion: 1, primaryWorkspace: /repo/main, workspaces: [/repo/service-a], displayNames: { 3f4a2c1b9e8d7f60: Service A } }注意几个设计要点文件中重复主工作区路径作用域哈希已经隐含了主工作区但文件内仍显式保存primaryWorkspace字段用于在校验时比对——若哈希与内容不一致比如文件被复制、损坏或作用域错配则整个存储被拒绝而不是被静默采用只存储规范化后的次级路径workspaces数组中的每一项都是规范化canonical后的绝对路径信任状态trust、环境、工作区 ID、会话以及运行时错误等信息不落盘每次守护进程启动时重新推导文档 Only canonical secondary paths are stored 一节。这样做避免了持久化文件中的信任信息被篡改后越权信任某个目录。2.4 容量边界存储上限有两层workspace-registration-store.ts 与 workspace-inputs.ts总注册工作区上限MAX_REGISTERED_WORKSPACES 256可通过启动参数配置但不得超过MAX_CONFIGURED_REGISTERED_WORKSPACES 256次级工作区secondary上限为配置上限减 1即 255 个主工作区不可作为次级注册文件大小上限MAX_STORE_BYTES 8 * 1024 * 10248 MiB读取与写入前都会检查单条路径长度不得超过守护进程工作区路径上限MAX_WORKSPACE_PATH_LENGTH来自 acp-bridge 的 workspacePaths显示名最长 256 字符MAX_WORKSPACE_DISPLAY_NAME_LENGTH且不允许包含控制字符workspace-registration-store.ts。三、生命周期从启动恢复、动态持久化到遗忘3.1 启动恢复流程生产环境守护进程runQwenServe在解析并规范化主工作区之后读取注册文件恢复流程如下对应 run-qwen-serve.ts若调用方未显式注入注册存储且环境变量QWEN_SERVE_NO_PERSISTENT_REGISTRATION不等于1则基于主工作区创建WorkspaceRegistrationStore读取存储快照遍历workspaces中的每个条目显式--workspace输入优先如果某条存储路径与显式输入命中同一规范化路径则将该条目的注册 ID 追加到显式输入的registrationIds并补充显示名如缺失不重复创建运行时路径被 Conversations 保留、无法规范化validateAndCanonicalizeWorkspace失败、或与已显式/已恢复路径嵌套冲突的条目都会打印警告并跳过但不会从存储中删除保留在磁盘上等待后续重启通过校验的路径作为新的workspaceInputs条目进入正常的次级运行时构造循环。恢复完成后检查总量若显式输入数 恢复条目数超过配置上限则抛出明确的启动错误提示操作者恢复之前的容量配置或先遗忘部分注册错误信息明确说明registration store was not changed——存储文件不会被这次失败改动。恢复路径进入常规的次级运行时构造循环的时间点位于WorkspaceRegistry以及 Express/ACP 表面组装之前。这意味着能力capabilities、工作区限定workspace-qualified的 ACP 挂载、状态聚合以及默认的总会话上限都与恢复后的运行时集合保持一致——不会出现先按单工作区快照启动、再事后补挂载的不一致。3.2 进程内动态添加的持久化对于应用组装完成之后的进程内添加设计上有两个关键决策ACP 路由的懒挂载只要存在注册存储registry exists工作区限定的 ACP 路由就保持挂载状态并在首次使用时惰性创建受信任的次级挂载。文档明确指出这样做的目的避免启动时只有一个工作区的快照导致后续 Web Shell 注册在重启前不可用persist: true才落盘POST /workspaces接受persist布尔字段。只有persist: true的请求才会写入注册文件省略该字段的既有调用方保持原有进程内行为不变兼容性优先。3.3 幂等性与提交语义幂等对已激活的工作区重复发送persist: true请求会提升/确认其存储注册并以幂等方式成功返回不会重复追加条目存储层按规范化路径去重见add实现中的snapshot.workspaces.some(...)去重判断先落盘再应答一个成功的持久化请求不会被提前确认——必须等注册文件更新成功完成之后才返回成功响应。从POST /workspaces的路由实现看workspace-management.ts先调用workspaceRegistrationStore.add(...)落盘之后才res.status(201).json(...)回滚如果运行时注册workspaceRegistry.add等后续步骤失败而持久化记录已经写入路由会尝试通过removeById回滚该条持久化记录再销毁运行时workspace-management.ts。3.4 管理 API与持久化注册直接相关的管理端点如下方法与路径作用备注POST /workspaces动态注册工作区请求体支持cwd、persist布尔、displayName、kind: scratchpersist: true时写入注册存储GET /workspace-registrations列出期望的持久化集合返回schemaVersion、primaryWorkspace与entries含id、cwd、可选displayName、active、persisted: true未启用持久化时返回 501persistence_not_availableDELETE /workspace-registrations/:id遗忘一条存储注册遗忘后活跃的运行时继续存活直到重启若对应注册当前活跃响应中restartRequired: trueDELETE /workspaces/:workspace移除工作区运行时会同时清除其持久化注册persistedRegistrationRemoved字段反映是否清除了持久化记录几个语义要点来自 workspace-management.ts 的实现主工作区永远不能通过该表面被存储或被遗忘存储层在add与解析阶段都会校验主工作区不得作为次级注册Primary workspace cannot be stored as a secondary registrationPOST /workspaces对主工作区携带persist: true返回 400invalid_persist_targetGET /workspace-registrations中的active字段表示该存储条目当前是否有对应的活跃运行时按注册 ID 匹配workspace-management.ts遗忘注册DELETE /workspace-registrations/:id与移除运行时DELETE /workspaces/:workspace是两条独立路径前者只影响下一次重启是否恢复后者才会真正卸载活跃运行时。3.5 显示名displayName的持久化POST /workspaces的请求体支持displayNamePATCH /workspaces/:workspace允许更新或置null清除显示名。持久化路径上新增注册时显示名随add(workspace, displayName, ...)一并写入displayNames更新时setDisplayNameByIds会按注册 ID 批量写入存储再同步运行时元数据workspaceRegistry.syncRuntimeMetadata显示名校验规则必须是字符串、trim 后不超过 256 字符、不含控制字符源码normalizeWorkspaceDisplayName不合法返回 400invalid_display_name。3.6 启动恢复时的显示名启动恢复时若存储条目带displayNames恢复出的运行时也会带上对应的显示名run-qwen-serve.ts若显式输入已存在则仅当显式输入缺少显示名时才用存储值补充。这一行为与设计文档信任、环境、工作区 id、会话、运行时错误均在启动时重新推导的基调一致——显示名是少数被持久化的用户可见配置之一。四、安全与故障行为设计文档给出了明确的保障清单以下逐条对应源码实现保障条款源码依据存储上限 24 条次级路径文档原文需说明文档写作时描述为 24当前源码已演进为基于MAX_CONFIGURED_REGISTERED_WORKSPACES的动态上限默认 255 个次级以当前仓库源码为准读取拒绝符号链接、非普通文件、超大文件、畸形 JSON、未知 schema 版本、主工作区作用域不匹配workspace-registration-store.tslstat先检查普通文件openNoFollow打开Windows 上以 lstat/open/fstat 身份校验替代 O_NOFOLLOW见注释中的 #8227超过MAX_STORE_BYTES抛WorkspaceRegistrationStoreTooLargeErrorparseSnapshot拒绝 schema 不匹配、primary 不匹配、重复路径、主工作区作为次级、显示名引用未知注册 ID写入使用进程内互斥 跨进程文件锁 共享原子写助手mode 0600、不跟随符号链接[workspace-registration-store.ts](https://link.gitcode.com/i/84c127b6f37961c2c55a6b24eaa04106#L284-L334, L542-L598)withInProcessLock按文件路径串行化内存中的更新链、proper-lockfile跨进程锁stale: 10s、自动续期、onCompromised使锁失效、atomicWriteFile(..., { mode: 0o600, forceMode: true, noFollow: true })损坏的存储绝不能被变更路径当作空处理update在持锁后read()任何解析失败都会向上抛出不会进入 mutation 覆盖文件测试refuses a malformed store without overwriting it与refuses a primary-scope mismatch without overwriting itworkspace-registration-store.test.ts持久化信任被刻意省略恢复的工作区走当前 trusted-folder 计算存储中不保存信任位POST /workspaces发布运行时还会经过runWorkspaceTrustOperation若有的信任判定缺失/不可访问/嵌套/超限的存储条目被跳过但不删除重复条目使存储无效且不会被隐式重写恢复循环中continue跳过并告警不调用removeByIdparseSnapshot对重复路径抛错测试rejects unknown schema versions and duplicate entries额外的并发细节注册、提升promotion、移除、遗忘、更新等管理变更按规范化 cwd 通过inFlightmap 串行化workspace-management.ts避免并发请求跨越各自的校验/持久化提交点互相踩踏。锁释放失败的处理也值得注意如果写入已提交但锁释放失败会抛出WorkspaceRegistrationStoreCommittedError路由层捕获后仍按成功处理并记录诊断qwen serve: ${err.message}因为注册已提交这一事实不会因锁释放失败而改变。五、兼容性与能力通告持久化注册被设计为纯增量能力能力通告新增能力标识persistent_workspace_registrationcapabilities.ts仅在persistentWorkspaceRegistrationAvailable为 true 时对外通告capabilities.tsrunQwenServe的能力配置中对应字段为persistentWorkspaceRegistrationAvailable: truerun-qwen-serve.tsSDK 侧TypeScript SDK 中注册请求支持可选的persist: truebody 标志响应中的persisted字段为增量字段sdk-typescript daemon types嵌入方式差异runQwenServe负责自动的启动恢复而直接嵌入createServeApp的调用方只有在显式提供注册存储时才会获得持久化管理路由并且它们需要自行负责在创建应用之前恢复注入的工作区注册表workspace registry。这是文档明确的兼容性契约。环境变量QWEN_SERVE_NO_PERSISTENT_REGISTRATION1可用于关闭自动恢复run-qwen-serve.ts适合希望完全由自己管理工作区集合的部署场景。六、后续边界热移除保持独立设计文档明确指出后续边界热移除hot removal仍保持独立。遗忘一条注册只会影响下一次重启不会终止会话也不会释放一个仍处于活跃状态的工作区桥接bridge。对应地DELETE /workspace-registrations/:id的响应通过restartRequired字段告知调用方该注册对应的活跃运行时将在重启后才消失。七、测试覆盖与验证路径仓库为持久化注册提供了较完整的测试覆盖可作为理解行为边界的补充材料存储层单测 workspace-registration-store.test.ts覆盖读写往返、去重、删除、显示名设置/清除、上限255 条、并发写入串行化、损坏存储拒绝且不覆盖、primary 作用域不匹配拒绝、未知 schema/重复条目拒绝等路由层测试 workspace-management.test.ts 与 server.test.ts覆盖POST /workspaces的 persist 语义、幂等提升、GET /workspace-registrations、DELETE /workspace-registrations/:id等管理面行为启动恢复测试 run-qwen-serve.test.ts覆盖runQwenServe自动读取存储并恢复次级运行时、显式输入优先、超限报错等场景。结语qwen-code 的工作区持久化注册通过主工作区作用域哈希 小 JSON 文件 严格校验 原子写入的组合在不改变既有进程内动态注册行为的前提下为 Web Shell 添加的工作区提供了可靠的重启恢复能力。理解它的存储布局${QWEN_HOME}/daemon/workspaces/sha256.json、生命周期语义显式输入优先、先落盘再应答、幂等提升、遗忘不卸载以及安全边界拒绝损坏存储、不持久化信任、上限约束是正确使用qwen serve多工作区能力、以及在其上构建管理工具的关键。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表