Replies: 1 comment
Follow-up: the same reachability gap, as an opt-in patchThis continues the desktop report above. Two gaps stop plugin routes from working under 1. The routes never exist in the shell. The shipped Desktop overlay keeps 2. A Patch
The opt-in is read from the launch environment snapshot, so either the process Deliberately not a Companion client fix (separate repo)The client half is in Gates
Live check, under the carrierLaunched with the shipped overlay untouched, only
One suggestion
|
Uh oh!
There was an error while loading. Please reload this page.
Environment
pnpm run dev:desktop --skip-build,DSH_HOME=~/.dsh, renderer origindsh-app://app.profiles/webprofile:dsh-better-sidebar,@goodandready/dsh-time-machine,@dsh-market/plugin,@nanmicoder/dsh-agent-teams,@linxin666/dsh-web-all,dsh-persona-memory,dsh-plugin-model-proxy,dsh-sidebar-title,dsh-answer-reviewer,dsh-loop-continue.Two separate desktop-shell gaps, both found while trying to use the same plugin set in the desktop app that already works in the browser UI. Patches are applied locally and working; posting here because
CONTRIBUTINGcloses issues and the repo takes Discussions only.Symptom 1 — plugin host APIs answer 403 for the desktop renderer
Every plugin whose host half fences on browser same-origin signals answers
403inside the desktop shell, while the identical request works in the browser UI. Concrete case: task-board's agent control plane (its non-idempotentPOST /dsh-task-board/...calls).Root cause: the renderer's origin is
dsh-app://app, so a request the host forwards to the embeddedwebServerstill reads as cross-origin. The desktop host owns both the renderer and the webServer, so the honest presentation is "same-origin loopback":Symptom 2 — plugin host routes are unreachable from the shell
assetHandleronly served the dist bundle plus the connection gateway. But plugin host halves register their routes on thewebServerservice (skill-explorer,task-board,time-machine,market, …), which the desktop host never consulted, so those routes fell through to the SPAindex.html(GET) or405(everything else).Patch: forward any non-asset request to
ctx.get('webServer')and treat404as "no plugin route" (fall back to the gateway); non-idempotent methods are proxied too instead of being rejected by the blanket405:For
/api/*the gateway must stay the fallback, and the connection prefix route answers rejected requests with a plain-textunauthorized/forbiddenmarker — that marker is distinguishable from a real plugin response because plugin routes answer JSON (related: #5770, #3186):Symptom 3 —
dsh-remote-web-ui's boot patch makes the in-app renderer hit its LAN gateThat plugin's boot patch rewrites loopback-fenced paths (
/api/*,/sidebar/*,/git/*,/pet/*) onto its gated/remoteprefix so a LAN browser can proxy through the desktop's webServer. The desktop renderer runs inside this host and is the host owner (ownsHost), so no pairing applies — but the rewritten path still arrives at the host. Unwrapping before dispatch fixes it:Symptom 4 — the dev shell never loads the shared web profile's plugins
The disposable development project links only first-party workspace deps, and the unpackaged dev shell exposes no settings UI to install anything. Meanwhile
DSH_PROFILEis effectively the only channel that reaches family plugins: the host child strips everyDSH_DESKTOP_*override, and the devuserDatadir carries no profile-selection state.Patch (2 parts, in
apps/desktop/scripts/):dev.ts—DSH_PROFILE: process.env.DSH_PROFILE ?? SHARED_WEB_PROFILE_NAME('web').development-project.ts— link the third-party bundles found in~/.dsh/profiles/web/node_modulesinto the dev project, mergedsh.profile.bundlesfrom the profile manifest, and copy the profile'scordis.patch.yml:mergeWebProfileManifest()derives bundles from the manifest and filters@deepseek-ai/dsh-*, so first-party rows keep coming from the workspace build.WEB_PROFILE_THIRD_PARTY_BUNDLESis the weak spot: I hardcoded my plugin set as a fallback. A maintainer-grade version probably wants either manifest-only derivation or an explicit opt-in list — guidance welcome.Also
apps/desktop-host/config/desktop.cordis.patch.ymlneedsweb-runtimeenabled (inject: [webServer],openBrowser: false,printUrl: false,surfaceContext: false) because plugin rows inject thewebRuntimeservice it supplies;webservergets pinned to loopback127.0.0.1:3199withcompression: none.Verification
With the patches above, in the unpackaged dev shell: task-board's control plane no longer returns 403, and
dsh-better-sidebar+@goodandready/dsh-time-machinebehave exactly as in the browser UI (bottom panel renders, toggle shows/hides it, time-machine registers its tab and snapshots the workspace). Checked over CDP againstdsh-app://app/index.html, plus a full host restart to confirm the fixes are not artifacts of one process.Diff: 4 files, +183/−6 (
apps/desktop-host/src/index.ts,apps/desktop-host/config/desktop.cordis.patch.yml,apps/desktop/scripts/dev.ts,apps/desktop/scripts/development-project.ts). Happy to turn it into whatever shape maintainers prefer — or to drop the env-specific pieces.Questions
ctx.get('webServer')insidedesktop-hostthe right seam, or should this be a first-class request-level seam (webServer middleware layer (ctx.webServer.use): a request-level seam so plugins can guard /api #3186) so each host doesn't re-implement it?origin/sec-fetch-siteacceptable, or would you rather plumb the renderer origin as trusted in the webServer's own config?中文摘要
在官方源码构建的未打包桌面 dev 壳里发现两处桌面端专属缺口(同一套插件在浏览器 UI 上工作正常):
dsh-app://app,宿主转发到内嵌webServer的请求被插件按跨域信号拒绝;宿主同时拥有渲染进程与 webServer,故按同源 loopback 呈现(改origin+sec-fetch-site)。webServer服务上,而assetHandler只看 dist 与 connection gateway → 落到 SPAindex.html或405;改为非资产请求先问webServer(404 视为无插件路由再回落 gateway),并放行非幂等方法;/api/*上用「plain-textunauthorized/forbidden」区分网关拒绝与插件响应。dsh-remote-web-ui的 boot patch 把 loopback 路径改写到它带门禁的/remote前缀;桌面渲染进程本身就是 host owner,故先脱壳再派发。profiles/web的第三方插件,且DSH_PROFILE是唯一能到达 family 插件的通道(host 子进程会剥离DSH_DESKTOP_*,dev userData 无 profile 选择状态)→dev.ts设DSH_PROFILE ?? 'web',development-project.ts镜像 profile 的第三方 bundle + 合并dsh.profile.bundles+ 复制cordis.patch.yml;另需在desktop.cordis.patch.yml启用web-runtime并固定webserver到127.0.0.1:3199。补丁已在本地工作树(4 文件 +183/−6),验证方式为 CDP 检查
dsh-app://app/index.html+ 完整重启宿主。因为CONTRIBUTING关闭 issues、只收 Discussions,故发在此处征求方向。All reactions