ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

qwen serve 多工作区架构 Phase 4:Workspace-Qualified ACP 路由隔离设计与实现解析

qwen serve 多工作区架构 Phase 4:Workspace-Qualified ACP 路由隔离设计与实现解析 qwen serve 多工作区架构 Phase 4Workspace-Qualified ACP 路由隔离设计与实现解析【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-codeqwen serve 是 qwen-code 开源 AI 编码代理内置的守护进程服务。当单个 daemon 同时托管多个工作区运行时multi-workspace传统单一 ACP 端点无法区分请求归属的工作区。本文围绕设计文档 daemon-multi-workspace-phase4-acp.md 展开系统讲解 Phase 4 如何在/workspaces/:workspace/acp挂载按工作区隔离的 ACP 传输端点、如何通过单个 WebSocket upgrade 监听器按 URL 分发、以及设备流注册表、CDP 隧道、信任门控与能力广告的落地方式。读完本文你将掌握 qwen serve 多工作区 ACP 的完整路由与隔离模型并能对照仓库源码定位每一处关键实现。背景为什么 ACP 需要按工作区隔离qwen serve的 ACPAgent Client Protocol传输是 Web Shell 与桌面客户端连接 daemon 的主要通道承载 Streamable HTTP 与反向 WebSocket 两种形态。在 Phase 2a/2b 引入多工作区注册与 REST 级 workspace-qualified 路由之后/acp仍是单一挂载点一个 daemon 只有一个AcpDispatcher天然绑定在主工作区primary runtime上。这意味着非主工作区的会话无法通过 ACP 独立寻址不同工作区的文件读写、权限、MCP、记忆等操作共享同一份 dispatcher 状态无法按工作区隔离Web Shell 无法针对特定工作区建立独立的 ACP 连接。Phase 4对应 issue #6378的目标即是在qwen serve上实现workspace-qualified ACP为每个已注册的工作区运行时挂载独立的 ACP 端点/workspaces/:workspace/acp每个运行时拥有自己的 dispatcher 与连接状态同时保持旧有/acp端点绑定主运行时确保现有 Web Shell 与既有 ACP 客户端不受影响。需要明确的是Phase 4 的范围限定在 ACP 传输本身Streamable HTTP 反向/acpWebSocket、其镜像的工作区方法、以及反向 MCP/CDP。语音端点/workspaces/:workspace/voice/stream与 daemon 管理的 channel worker 属于Phase 4b动态工作区增删属于Phase 5均不在本文讨论范围内。核心结论这是接线与路由改造而非重写设计文档在勘测现有代码后给出一个关键判断Phase 4 大部分工作是wiring and routing接线与路由不是重写。依据如下AcpDispatcher在构造上已经按工作区绑定其构造参数包含bridge、boundWorkspace、workspace、workspaceRememberLane、fsFactory、deviceFlowRegistry、sessionShellCommandEnabled、registry、archiveCoordinator见 dispatch.ts L644-656。dispatcher 服务的每个镜像工作区方法都读取这些字段因此把 dispatcher 绑定到某个运行时文件、权限、设置、信任、工具、MCP、记忆、代理、认证天然就被限定在该运行时内。parseRequestedWorkspacedispatch.ts L694-697已存在一致性校验当请求中的workspaceCwd不等于this.boundWorkspace时抛出WorkspaceMismatchError并映射为INVALID_PARAMSL577。Phase 3 已把镜像 REST 表面改为 per-runtimeclientMcpSenderRegistry已是 per-runtime 字段。真正需要做的工作只有四项1把单一 ACP 挂载拆成每个运行时一个 dispatcher每个都有自己的 remember-lane但仍是一次mountAcpHttp调用、一个upgrade 监听器由AcpHttpHandle统一持有所有运行时的注册表2扩展该 WebSocket upgrade 监听器按 URL 路径分发3保持设备流注册表为 daemon 全局单例所有挂载共享并尽力将事件扇出到每个受信任运行时的 bridge4将新的workspace_qualified_acp能力标签同步到 SDK/CLI 能力类型与测试。系统性重构八大加固轴评审过程中发现过一个 Critical 问题早期迭代把设备流注册表做成 per-runtime导致次级挂载未认证报device_flow not configured。最终 ACP 挂载沿八个轴重构形成最终架构运行时 ACP 挂载工厂一次mountAcpHttp调用持有primaryMount加secondaryMounts映射每个非主运行时一个RuntimeAcpMount每个挂载携带primary标记。HTTP 与 WS 两条路径都先按选择器解析挂载再委托给共享处理器。路由 连接隔离复数选择器plural selector把主工作区别名到primaryMount否则解析 per-runtime 挂载。不受信任的非主工作区在 HTTP 与 WS 两条路径上、在派生任何子进程之前即以 403 拒绝。原始 request-target 的 WS 解析upgrade 监听器解析原始request-target而非new URL().pathname——后者会规范化%2e%2e使得非规范化的点段/反斜杠选择器在路由之前就被销毁。Daemon 全局设备流 扇出设备流注册表保持为 daemon 单实例OAuth 凭据是进程级全局状态。次级挂载通过opts.deviceFlowRegistry共享它认证流事件尽力扇出到每个受信任运行时的 bridgeresolveEventBridges。仅主挂载启用 CDP 与客户端 MCPCDP 隧道声明以activeMount.primary为门槛复数 POST 返回 dispatch promise。已处置生命周期门控dispose()之后共享 HTTP 处理器返回503 server_disposed而不是在关停排空期间与已拆除的注册表竞争。dispose()幂等。聚合可观测性AcpHttpHandle.getSnapshot()汇总主挂载与每个次级挂载的连接数与 WS 流数使 daemon 指标报告所有工作区的 ACP 连接而非仅主工作区。能力广告resolveAcpHttpEnabled()是对QWEN_SERVE_ACP_HTTP的唯一解释workspace_qualified_acp仅在 ACP HTTP 表面已启用且多工作区会话激活时广告。在 index.ts 中RuntimeAcpMount接口L540-563完整体现了这一模型每个挂载携带primary、workspaceCwd、routeLabel、rateLimitScope、registry、dispatcher、workspaceRememberLane、WebSocket 集合、draining 标记以及ensureChromeDevToolsMcpRegistered/removeChromeDevToolsMcpIfUnused与clientMcpProviderFactory后三者对非主挂载为空实现见下。审查后的边界加固六项缺口收口挂载架构保持不变的前提下最终修复轮次在不替换AcpHttpHandle、不引入新路由策略模块的前提下收口了六个边界缺口单一合格路由就绪判定workspace-qualified ACP 仅在ACP HTTP 已启用且工作区注册表包含超过一个运行时时才算就绪。HTTP 路由注册、WebSocket 路径识别、能力广告与外层限流器豁免必须与该判定一致。单工作区 daemon 继续只暴露传统/acp。单一限流计费外层 Express 限流器精确豁免已启用的/workspaces/single-selector/acp传输路径含该路由既有的大小写与尾斜杠行为邻近路径仍受限。ACP 传输仍负责应用 JSON-RPC 方法分层因此一次合格提示词只消耗提示词桶而不会同时消耗 mutation 与提示词两个桶。结构化畸形路径失败Express 路由参数解码失败若同时是URIError实例且标记了 HTTP 400 状态返回结构化400 invalid_request其他URIError与无关失败保留通用 500 处理。WebSocket 路径保留其现有显式 400 响应。日志安全选择器用于面向运维的 WebSocket 拒绝日志的解码选择器经过现有logSafe清洗器编码的终端控制字符无法伪造或拆分 stderr 行。对应的回归测试见 workspace-qualified-acp.test.ts L2024。终结性处置dispose()是不可逆的生命周期转换。运行后attachServer()无法重建 WebSocket 服务器或 upgrade 监听器重复调用dispose()与attachServer()保持无害。带工作区归属的完整诊断聚合 ACP 快照新增附加连接诊断装饰workspaceId、workspaceCwd与primary汇总计数器不变公开的主registry为兼容性保留daemon 的detailfull读取聚合连接列表。现有连接上限保持 per-mount 限制因为每个挂载都以同一配置上限构造。每一项契约都在生产变更之前由一条回归测试钉死。验证覆盖聚焦的 ACP、限流、daemon-status 与 serve-server 测试套件外加构建、类型检查、lint 与 serve fast-path bundle 闭合检查。架构per-runtime ACP 挂载Phase 4 采用一个 daemon、N 个独立工作区运行时Option B。对 ACP 而言每个已注册运行时获得自己的AcpDispatcherConnectionRegistry 反向 MCP provider 工厂全部绑定到该运行时的bridge/workspace/routeFileSystemFactory/clientMcpSenderRegistry/env每个 dispatcher 收到同一个 daemon 全局设备流注册表。旧/acp保持绑定主运行时的 dispatcher线上行为不变。新/workspaces/:workspace/acp绑定到解析出的运行时的 dispatcher。不变量mountAcpHttp仍恰好调用一次并恰好安装一个httpServer.on(upgrade, ...)监听器。其入参从单一 bridge opts改为接受WorkspaceRegistry外加共享的非工作区关注点token、allowedOrigins、hostname、checkRate、sessionShellCommandEnabled、cdpTunnelRegistry。内部构建MapworkspaceId, RuntimeAcpMount主条目仍可通过旧/acp路径寻址。每个RuntimeAcpMount以该运行时自己的bridge、workspace、routeFileSystemFactory、clientMcpSenderRegistry、env、新的 per-runtimeWorkspaceRememberTaskLane(runtime.bridge)、其AcpDispatcher与其ConnectionRegistry构造。daemon 全局设备流注册表、archiveCoordinator与sessionShellCommandEnabled共享。四个分发入口都必须选择解析出的运行时的挂载而非主挂载复数路径上的POST、GETSSE与DELETEExpress经resolveWorkspaceRuntimeFromParam基线实现各自闭包单一 dispatcher以及 WS upgrade 分支。旧/acp的 POST/GET/DELETE/upgrade 继续分发到主挂载。在源码层面index.ts 的createSecondaryAcpMountL1343-1439展示了次级挂载的完整构造独立ConnectionRegistry含独立的preAttachBudget与连接上限opts.maxConnections、以rt.bridge/rt.workspaceCwd新建的WorkspaceRememberTaskLaneL1368-1371、以rt.bridgert.workspaceCwd等运行时字段构造的AcpDispatcherL1379-1410、共享的opts.deviceFlowRegistryL1392与archiveCoordinatorL1395以及按opts.clientMcpOverWs条件创建的clientMcpProviderFactoryL1429-1437闭包rt.clientMcpSenderRegistry与rt.bridge。secondaryMounts为Mapstring, RuntimeAcpMountL1441mountForWorkspace按 workspaceId 在主挂载与次级挂载间切换L1444-1449getOrCreateSecondaryMount仅为受信任、非主、非内部运行时创建挂载L1450-1465——不受信任的工作区在 HTTP 与 WS 两条路径上都会先被 403 拒绝为它们分配 dispatcher/registry/remember-lane 纯属浪费。会话生命周期方面复数挂载上的 ACPsession/new/load/resume必须触发同样的 bridge 生命周期register/remove回调喂给 Phase 2b 的WorkspaceSessionOwnerIndex见 workspace-registry.ts L48-119。这样通过/workspaces/B/acp创建的会话必须能被 REST owner-routed 读取context、stats 等与resolveLiveSessionOwner发现——ACP 创建也要喂给 owner 索引实现跨传输的会话归属一致性。HTTP 路由实现/workspaces/:workspace/acp 的注册与解析复数 ACP 路由在 index.ts L1522-1540 注册当workspaceQualifiedAcpEnabled即opts.workspaceRegistry ! undefined为真时对/workspaces/:workspace/acp分别注册POST、GET、DELETE三者都先经resolvePluralMount(req, res)解析挂载再把请求委托给共享的handleAcpPost/handleAcpGet/handleAcpDelete。resolvePluralMountL1480-1519的解析顺序无workspaceRegistry时返回400 workspace_mismatch调用resolveWorkspaceEntryFromParamworkspace-route-runtime.ts L24-60先按 workspace id 精确匹配再按可移植绝对路径匹配含规范化 canonical cwd 比对失败返回400 workspace_mismatch运行时条目非 active/draining 时返回sendWorkspaceRuntimeUnavailable非主且不受信任时返回403 untrusted_workspace带workspaceCwd与workspaceId主运行时直接返回primaryMount否则getOrCreateSecondaryMount失败返回400 workspace_mismatch。这条链同时实现了三种失败语义未知选择器400workspace_mismatch、不受信任运行时403untrusted_workspace、未注册挂载400workspace_mismatch且从不回退到主挂载。WebSocket upgrade 分发核心设计upgrade 监听器是 ACP 路由中唯一不由 Express 驱动的位置因此需要显式路径处理。设计要点共享安全检查前置loopback / host allowlist / CSRF(origin) / bearer token 检查保持原样在任何工作区解析之前统一应用。扩展路径分类基线是pathname /acp | /cdp | extraRoutePhase 4 增加/workspaces/:workspace/acp分支匹配前缀并提取原始:workspace选择器段用纯函数resolveRegisteredWorkspaceRuntimeByPathSelector(registry, decodeURIComponent(selector))解析id 优先然后编码的 canonical cwd与 REST 解析器一致无匹配以 400 级关闭拒绝 upgradesocket.write(HTTP/1.1 400 ...)destroy()镜像 REST 的workspace_mismatch不回退主挂载匹配对解析出的运行时的 dispatcher ConnectionRegistry而非主挂载的执行 ACP initialize 握手。源码层面upgrade 监听器index.ts L1587 起先用rawRequestPathname(req.url)取原始路径L1611再用pluralWorkspaceRawSelector匹配复数 ACP 形状L1619-1622。这是刻意的安全设计WHATWG URL 会规范化点段/workspaces/%2e%2e/acp会被折叠为/acp而静默绑定主挂载原始路径解析使其无法绕过。对应的回归测试见 workspace-qualified-acp.test.ts L1855%2e%2e点段拒绝与 L2024日志清洗。安全检查通过后路径分支如下/cdp分支L1760-1769仅在opts.cdpTunnelOverWs true且提供cdpTunnelRegistry时可达升级后交给attachCdpClient复数 Voice 形状L1771-1817Phase 4b 预留路径按 id/路径解析运行时并校验信任后交给opts.workspaceVoiceConnection复数 ACP 形状L1824 起解码选择器解码放在形状/遍历检查之后防止解码重新引入/或..workspaceRegistry缺失时 400 拒绝解析运行时后按信任门控最终以wss.handleUpgrade升级并接入解析出的运行时的 dispatcher旧/acp保持绑定primaryMount。几个值得注意的细节1%2F编码的 cwd 选择器——daemon 自行解析原始 upgrade URLnew URL(req.url, ...)不受 Express 路径解码影响但反向代理仍可能规范化%2F因此代理部署下推荐使用基于id的选择器与 Phase 2b/3 REST 的建议一致HTTP 复数路由复用resolveWorkspaceRuntimeFromParam读取req.paramsExpress 解码一次免费继承了 Phase 3 的编码选择器处理。2可观测性——WS upgrade 路径与 ACP 分发绕过 Express 中间件因此 daemon 遥测/日志必须在此显式打上解析出的 workspace 印记这也是checkRate穿过opts的同一原因Phase 1 的请求时 workspace 哈希只覆盖 Express 路由。Dispatcher 镜像表面与运行时绑定反向/acpWS 镜像了庞大的 REST 表面文件 read/list/glob/stat、workspace mcp / skills / providers / env / preflight / trust / permissions / voice / tools / agents / memory / auth、会话组、setup-github 等。由于这些方法全部读取 dispatcher 的构造字段把 dispatcher 绑定到运行时即可免费完成作用域隔离。Phase 4不重新实现它们只确保每个运行时的 dispatcher 用该运行时的依赖构造——该集合显式包含 per-runtime 的deviceFlowRegistry与WorkspaceRememberTaskLane如果任一项仍用主运行时单例非主运行时的_qwen/workspace/memory/remember与auth/device_flow调用会静默打到主 bridge 上。一致性保证由于每个挂载的 dispatcher 都是运行时绑定的且parseRequestedWorkspace在请求workspaceCwd与boundWorkspace不一致时抛WorkspaceMismatchError连接到/workspaces/A/acp却发送workspaceCwd: B的客户端会被拒绝。对应的回归测试见 workspace-qualified-acp.test.ts L967。同一守卫也覆盖session/newparseOptionalWorkspaceCwddispatch.ts L1059。反向 MCP 与 CDP 隔离反向工具通道基线的clientMcpProviderFactory闭包主运行时的clientMcpSenderRegistryprimaryBridgeserver.ts L1252-1257。per-runtime 挂载从解析出的运行时的clientMcpSenderRegistrybridge构建工厂因此/workspaces/B/acp上的 WS 连接只把客户端托管的 MCP 服务器注册进 B 的运行时。回归测试见 workspace-qualified-acp.test.tsmcp_register 落在 B 的 registry/bridge一类用例。每连接的ClientMcpWsConnection与cdpEndpoint保持每连接属性只是挂到所属运行时的 dispatcher 上。CDP 隧道cdpTunnelRegistry是进程级作用域CDP bridge 由clientInfo.name qwen-cdp-bridge的扩展/acp连接声明。Phase 4 务实地把 CDP 声明保留在旧/acp主上工作区级 CDP 作为 Open Question 而非本阶段解决——单个 loopback puppeteer 客户端 一个/cdp端点无法干净地映射到 N 个运行时。具体实现上非主RuntimeAcpMount的ensureChromeDevToolsMcpRegistered/removeChromeDevToolsMcpIfUnused为空实现index.ts L1423-1424/cdp分支与chrome-devtools运行时 MCP 注册仅由主挂载接线次级工作区不能声明 CDP 隧道有专门回归测试L2051。信任门控Trust Gate不受信任的已注册工作区保持可见/只读但不得派生子进程。在/workspaces/:workspace/acp上授予所有权的操作session/new、session/load、session/resumedispatch.tsCONN_ROUTED_METHODSL239-243必须以untrusted_workspace错误拒绝且不派生匹配 REST 中已实现的 403untrusted_workspace语义session-runtime.ts L39-53 与 session.ts 的 session create/load/resume 信任门与session_workspace_conflict。HTTP ACP 路由复用 Phase 3 经requireTrustedWorkspaceRuntime暴露的信任判定WS 路径的等价检查在握手授予会话之前对解析出的运行时的trusted标志执行。启动冻结信任是 Phase 2a 基线运行期信任翻转吊销时排空/停止该工作区的 ACP 子进程并清空其会话索引与信任变更阶段保持一致本阶段不重新实现。在 index.ts L1499-1507 的resolvePluralMount与 WS 分支L1824 起的runtime.trusted检查中可以看到 HTTP/WS 两侧信任门的具体落点。能力广告与 Web Shell 选择器在 capabilities.ts 中新增 ACP 特性标志workspace_qualified_acp声明于 L474仅在注册运行时超过一个且 ACP 已启用时广告L738-746 的谓词toggles.acpHttpEnabled true toggles.multiWorkspaceSessionsEnabled true镜像multi_workspace_sessions的门控。如果 Phase 4 跨多个 PR 落地在完整复数 ACP 回路HTTP WS device-flow owner-index 接线完成前不要广告该标签避免客户端针对半接线的表面构建/workspaces/:id/acpURL。同步该标签是 Phase 4 的必需工作而非可选涉及/capabilities响应构造routes/capabilities.ts、SDK 能力类型sdk-typescript/src/daemon/types.ts其中workspaces?: DaemonWorkspaceCapability[]于 L591、CLI serve 类型packages/cli/src/serve/types.ts以及 server.test.ts L3724-3744 的特性集断言广告仅在 ACP HTTP 多工作区会话同时启用时成立。workspaces[]已由 Phase 2a 提供在 routes/capabilities.ts L79-84 与 daemon-status.ts L432-437 构造每个运行时带id/cwd/primary/trusted。Web Shell 读取它并构建/workspaces/:id/acp连接 URL选择器禁用或只读标记不受信任条目。SDK 的DaemonClientPhase 3 引入已读取caps.workspaces[].cwd用于会话路由DaemonClient.ts L612 附近提及multi_workspace_sessions广告workspace-qualified ACP 连接辅助函数是自然的扩展方向能力类型同步是必需的辅助函数本身可以随后跟进。失败路径与错误语义汇总场景行为workspace_mismatch未知 WS/HTTP 选择器 → 400 级拒绝从不回退主挂载untrusted_workspace在不受信任运行时上执行授予所有权的 ACP 操作 → 拒绝不派生子进程workspaceCwd参数不匹配WorkspaceMismatchError→INVALID_PARAMS已有接线子进程崩溃隔离在所属运行时内其他运行时的 dispatcher 与连接不受影响单 daemon 更大故障半径是已记录的已知局限信任吊销当信任变更阶段落地时吊销运行时须排空/停止其 ACP 子进程并清空会话索引Phase 4 仅保证 per-runtime ACP 挂载可排空自身不增加信任变更全局关停先处置每个运行时的ConnectionRegistry再一次性处置 daemon 全局设备流注册表限流ACP HTTP/WS 准入使用按连接/会话键控的checkRateindex.ts L627-641、L1175-1178复数挂载共享同一限流器键必须跨运行时无歧义一个工作区不能耗尽或绕过另一个的预算容量maxConnections按 per-runtimeConnectionRegistry执行总 ACP 连接数可扩展到 N ×maxConnectionsper-workspace 预算匹配maxSessionsper-workspace 模型新会话总数仍受 Phase 2a 在 bridge 接缝处的maxTotalSessions准入约束ACP 会话创建必经此接缝生命周期方面index.ts L2481-2507 的dispose()展示全局关停顺序置disposed标志 → 移除所有 upgrade 监听器 → 处置主 registry 与主 remember-lane → 遍历secondaryMounts处置每个次级挂载的 remember-lane 与 registryL2495-2498→ 关闭所有wss.clients1012并关闭 WebSocketServer。工作区级排空则由beginWorkspaceDrain/cancelWorkspaceDrain/disposeWorkspace提供L2509-2559 附近配合workspace_draining503 响应Retry-After: 5实现平滑移除。测试策略契约先行设计文档为每个契约规定了回归测试已在 workspace-qualified-acp.test.ts180 行起中成规模落地WS upgrade 分发路径分类单测——/acp主、/workspaces/:id/acp解析、未知选择器拒绝、%2F编码 cwd 选择器、复数路径仍执行共享安全检查L1267、L1275、L2005、L1855。跨工作区隔离/workspaces/A/acp上的连接看不到也不能驱动 B 拥有的会话session/list与镜像读取只返回 A 的视图。跨传输所有权经/workspaces/B/acp创建的会话可被 REST owner-routed 读取如GET /session/:id/stats与resolveLiveSessionOwner发现确认 ACP 创建喂给了 owner 索引。一致性连接 A 但发送workspaceCwd: B→WorkspaceMismatchErrorL967。信任门在不受信任运行时上session/new|load|resume→ 拒绝、不派生子进程L1018、L1359。设备流每个挂载都可达 daemon 全局注册表事件发布扇出到主与受信任次级 bridge单个 bridge 故障不阻塞其余关停时一次性处置注册表L1890。反向 MCP/workspaces/B/acp上的mcp_register只落入 B 的clientMcpSenderRegistry与 B 的 bridge。限流/workspaces/A/acp与/workspaces/B/acp上的提示词/mutation 独立计量任一不能绕过共享限流器L551、L568。能力workspace_qualified_acp仅在运行时 1 时广告workspaces[]形状不变另见 server.test.ts L3724-3744 的谓词断言。生命周期dispose 后不再重建 WS 监听器L1570、不重建已处置挂载L1660、排空期间拒绝新 upgradeL1736、聚合快照跨主次级挂载L1579、次级挂载排空/回滚/处置/重建L1601。未决问题与对 Phase 3 的反馈保持resolveRegisteredWorkspaceRuntimeByPathSelector为纯函数WS upgrade 监听器无法使用 Express 绑定的resolveWorkspaceRuntimeFromParam。Phase 4 依赖纯解析器不耦合req/res。若 Phase 3 评审改变该接缝需保留(registry, selector) runtime | undefined的纯入口。设备流所有权已解决注册表保持 daemon 全局OAuth 凭据为进程级全局Phase 4 与每个 dispatcher 共享该注册表并把清洗后的事件扇出到受信任运行时 bridge。CDP 隧道 per-workspace 模型一个 loopback puppeteer 客户端 一个/cdp端点无法干净映射到 N 个运行时。Phase 4 将 CDP 保留在主挂载需确认该取舍可接受或将 workspace-qualified CDP 排入后续。语音延后尽管 ACP dispatcher 已暴露_qwen/workspace/voice读取确认语音在 Phase 4b 之前保持仅主挂载。archiveCoordinator作用域目前是单一SessionArchiveCoordinatorserver.ts L596。需确认跨运行时共享它是否安全考虑 Phase 3 的 workspace-qualified archive/organization或改为 per-runtime。限流键维度决定 ACP 复数准入键是否需要显式 workspace 维度或 per-connection/session 键已跨挂载无歧义当前实现以workspaceRateLimitKey将 clientKey 与mount.rateLimitScope组合见 index.ts L565-570后者即运行时 workspaceId。非目标Phase 4b / 5/workspaces/:workspace/voice/stream与 per-workspace 语音设置4b。Daemon 管理的 channel worker 分组 / pidfile / 状态4b。动态工作区增删与惰性运行时创建5。关键源码索引设计文档docs/design/daemon-multi-workspace-phase4-acp.mdACP 挂载核心实现packages/cli/src/serve/acp-http/index.tsRuntimeAcpMountL540-563primaryMountL915-929createSecondaryAcpMountL1343-1439resolvePluralMountL1480-1519复数路由注册 L1522-1540WS upgrade 监听与分发 L1587-1839disposeL2481-2507dispatcher 运行时绑定packages/cli/src/serve/acp-http/dispatch.ts构造参数 L644-656parseRequestedWorkspaceL694-697parseOptionalWorkspaceCwdL1059工作区运行时模型packages/cli/src/serve/workspace-registry.tsWorkspaceRuntimeL32-54WorkspaceSessionOwnerIndex相关 L48-119选择器解析与信任门packages/cli/src/serve/workspace-route-runtime.tsresolveWorkspaceEntryFromParamL24-60能力声明与广告packages/cli/src/serve/capabilities.tsflag 声明 L474广告谓词 L738-746服务装配packages/cli/src/serve/server.tssetupDeviceFlowRegistry与resolveEventBridges扇出 L1264-1284workspaceRegistry 创建 L1356-1380回归测试packages/cli/src/serve/acp-http/workspace-qualified-acp.test.ts、packages/cli/src/serve/server.test.tsL3724-3744SDK 能力类型packages/sdk-typescript/src/daemon/types.tsworkspaces[]L587-591【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表