Repository navigation
Replies: 1 comment
|
补充一条来自同类环境的实测(Windows 11 + 桌面版 0.2.0-rc.2,GUI 同样在 一、桌面壳窗口那条链路(源码级)聊天视图这样构造图片 URL: // @deepseek-ai/dsh-client-ui-chat/lib/client.js
const fileImages = { resolve: (path) => fileMediaUrl(document.baseURI, resolveWorkspacePath(cwd, path)) };
// @deepseek-ai/dsh-client-ui-sidebar-documentpreview/lib/client.js
function fileMediaUrl(base, path) {
if (!/^https?:/u.test(base) && !base.startsWith("dsh-app://app/")
|| !isAbsoluteWorkspacePath(path)
|| /^[/\\]{2}/u.test(path)
|| /[\u0000-\u001f\u007f]/u.test(path)) return void 0;
return new URL(`api/file?path=${encodeURIComponent(path)}`, base).href;
}Markdown 渲染器接受的目标只有 // lib/main.js
protocol.handle("dsh-app", (request) => {
const url = new URL(request.url);
if (url.hostname === "app") {
if (/"/index.html"/, "/assets/…") …) return serveWebDocument(request, …dist);
return forwardWebRequest(request, hostUrl, hostCookie); // 其余一律转发给 Host
}
});
二、
|
| 请求 | 结果 |
|---|---|
GET /api/file?path=…(裸请求,无 cookie) |
401 unauthorized |
同上,带按 client-connection/browser-session 密钥正确签名的 cookie |
200,字节数与原文件完全一致,Content-Type: image/png |
| 同一接口取 1,585,185 B(约 1.5 MB)的 PNG | 200,未触发上限 |
结论:服务端本身是好的。失败只可能发生在“浏览器拿不到可用 URL”或“URL 已损坏”这两处——后者正是本报告定位的 \. 转义。
三、一个已验证的绕行方案
GUI 文档没有任何 CSP(响应头里没有 Content-Security-Policy,HTML 里也没有对应 meta),而渲染器对绝对 http(s) 目标是无条件放行的。于是把图片交给一个本地静态服务,就能完全绕开“手写路径 → /api/file → cookie”整条链:
# 目录里放图片,回环端口起一个静态服务
pythonw -m http.server 8791 --bind 127.0.0.1 --directory <图片目录>回复里写  即可内联显示,桌面窗口与浏览器窗口都正常。该方案不依赖路径转义规则,也不依赖 cookie 是否送达。
四、两点建议
- 短期(交付指引层):面向模型的图片/文件交付规则里明确写“Windows 路径一律用正斜杠,不要用
<...>包裹本地路径”。本报告已证明尖括号不能阻止反斜杠转义,而反斜杠一旦被 Markdown 吃掉,客户端无法从结果里还原(信息已丢失),只能在写入侧防住。 - 长期(结构化引用):工具结果里已经有
type: "image"+attachment.attachmentId(sha256:…),前端也已具备把持久化附件引用解析为blob:URL 的缓存(dsh-client-ui-conversation的 image cache)。让消息直接携带该引用、由宿主在渲染时解析,就不再依赖模型手写文件系统路径,/api/file的鉴权门与转义规则也就都绕开了。
English summary (same environment: Windows 11, Desktop 0.2.0-rc.2, same GUI at 127.0.0.1:19387):
- Desktop-shell path — left untested by the original report. Chat resolves image destinations via
fileMediaUrl(document.baseURI, resolveWorkspacePath(cwd, path)), i.e.<baseURI>/api/file?path=…; the Markdown renderer accepts onlyhttp:/https:/blob:/data:/dsh-app://app/api/file?targets. In a Desktop windowdocument.baseURIisdsh-app://app/, so the request goes through the shell'sprotocol.handle→forwardWebRequest, which injects the Host-issued cookie and strips only connection-level headers (set-cookie,content-encoding,content-length,transfer-encoding,connection,keep-alive,te,trailer,upgrade,proxy-*).content-typesurvives — so this failure is not Desktop-shell-specific; both window types share the same URL-construction point. /api/fileauth fence — the route is registered bySessionMediaReferencesindsh-api-session-controller; authentication is the browser-session cookie (HttpOnly; SameSite=Strict; Path=/). Measured here: a bare request returns401 unauthorized; a request carrying a correctly signed cookie returns200with byte-identical content (image/png, verified up to 1.5 MB). The server side is sound, so the failure lies in URL construction — exactly the\.escaping this report identified.- Verified workaround — the GUI document carries no CSP (no header, no meta) and the renderer accepts absolute
http(s)targets unconditionally, so serving images from a tiny loopback static server and referencinghttp://127.0.0.1:<port>/x.pngbypasses the hand-written path,/api/file, and the cookie entirely. Works in both window types. - Suggested fixes — (a) short term, state in the model-facing delivery guidance that Windows paths must use forward slashes and must not be wrapped in
<...>(the escaping destroys the backslash irrecoverably, so it can only be prevented on the writing side); (b) long term, prefer passing the already-present structuredattachment.attachmentIdso the client resolves it through its image cache instead of relying on model-authored filesystem paths.
Uh oh!
There was an error while loading. Please reload this page.
Summary
Windows 上,图片生成 MCP 已成功返回结构化 PNG 附件,但 Agent 在最终回复中用未经 Markdown 转义的 Windows 原生路径引用该附件,聊天显示「图片无法预览」。后续 Agent 复制图片为
.png并调用present,只得到需要点击的文件卡片,未满足用户「生成后直接在聊天显示」的预期。此报告提交到 Discussions 是因为当前仓库
has_issues: false。请维护者视情况转入内部 Bug / 改进任务。定位结论:这是图片交付链路的路径书写/防护问题,不是图片生成失败,也不是要求修改 CommonMark 转义规则。 以下文件路径均已匿名化,没有上传参考图、生成图、凭据或原始会话日志。
Reproduction
type: image附件。C:\Users\example\.dsh\attachments\v1\objects\ab\<sha256>。\.解释为转义,图片目标变成:/api/file?path=...请求,接口返回 404,图片onError后显示「图片无法预览」。尖括号并不会禁用 Markdown 的反斜杠转义。Current behavior / evidence
已经在正在运行的 GUI(不是替代开发服务器)中,用真实浏览器加载原聊天,并抓到了损坏后的请求路径和 HTTP 404。
使用同一原始图片附件进行对照,不重新生成、不复制文件:
.dsh前的路径分隔符C:/Users/example/.dsh/...工具的持久化结果包含:
{ "type": "image", "attachment": { "attachmentId": "sha256:<redacted>", "mediaType": "image/png", "width": 1024, "height": 1536, "bytes": 2427356 } }图片字节本身有效。正确的无扩展名附件路径经
/api/file返回application/octet-stream,但实测浏览器仍能解码并展示;因此不能把本次故障归因于缺少.png扩展名或 MIME 类型。另有一个用户体验问题:发生失败后,Agent 调用
present只提供文件卡片,不等同于聊天内联展示。这个后续动作是错误的绕行策略,并不是原故障的修复。Expected behavior
生成图片后,应能直接在聊天中看到结果,不应要求复制附件、补扩展名、再次生成或额外点击文件卡片。
建议至少为 Agent 提供明确的 Windows Markdown 路径书写规则:使用正斜杠或正确编码的目标,路径中的特殊字符另行处理;
<...>不是反斜杠转义的解决方法。更稳健的长期方案是使用工具结果中已有的结构化图片附件,在聊天中直接展示,或提供稳定的附件引用/展示能力,减少对模型手写文件系统路径的依赖。
不建议全局修改 Markdown 解析器来保留
\.,因为目前的解析结果符合 CommonMark。这个问题应在路径作者/附件交付层防住。Environment
0.2.0-rc.2http://127.0.0.1:19387gpt-6.1-solLocal workaround / scope
已在本地全局
AGENTS.md加入 Windows Markdown 图片/文件链接使用正斜杠、优先内联展示、失败先检查实际请求 URL 的规则。没有修改官方源码,没有重启 Host,也没有实现代码级自动防护。这是行为约束而非可靠的程序级修复;提交此报告希望官方完善图片交付指引和/或结构化展示链路。
All reactions