Repository navigation
Feature: give plugins a seam for the chat link context menu #11933
Replies: 1 comment
Correction to two claims in the post aboveAfter further investigation I have to retract two things. The core ask (a 1. The main window already forwards The post says the main window's // app/lib/main.js, inside createWindow()
window.webContents.setWindowOpenHandler(({ url }) => {
if (["http:", "https:"].includes(new URL(url).protocol)) shell.openExternal(url);
return { action: "deny" };
});The deny-only handler I quoted is a different call in a different class: // app/lib/main.js — inside `DesktopPolicyTestAuth`, the login window
contents.setWindowOpenHandler(() => ({ action: "deny" }));There are seven → Section "c. Fix 2. A plugin can reach the path and the workspace root without any patch. The post claims the path "never reaches the DOM". In the shipped bundle the // baseline dsh-web-frontend/dist/assets/index-*.js — no patch applied
d.jsxs("button", {
type: "button",
className: he(St.fileMention, St.fileLink),
title: l === void 0 ? e.path : void 0, // ← the path, already rendered
onClick: () => { i(e.path, ...) },
children: [...]
})And a client plugin can read the workspace root off the sessions store: const rows = ctx.sessions.list.getSnapshot().byId
const cwd = rows?.[sessionId]?.cwd
const abs = path.startsWith("/") ? path : `${cwd.replace(/\/+$/, "")}/${path}`
Several plugins already ship exactly this, with no app patch at all — What is still missing, and still worth fixing: there is no native And one documentation fix that survives: |
Uh oh!
There was an error while loading. Please reload this page.
Problem
There is no extension point for the context menu of a link in the chat, so a
plugin cannot offer "Reveal in Finder" / "Copy file path" on a file mention.
Two things block it, and both are structural rather than bugs:
1. The Electron main-process menu never sees the link.
app/lib/main.jsbuilds the menu fromwebContents.on("context-menu", params => …)and reads only
isEditableandselectionText:params.linkURLis never consulted — and even if it were, it would be emptyfor dsh's file mentions.
2. File mentions are not anchors.
ui-chatrenders a file reference as a<button>, not<a href>:Chromium only fills
linkURLfor real<a href>elements, so the main processsees
""on every file mention. Verified in DevTools: right-clicking a filemention reports
{"linkURL":"","selectionText":"…","isEditable":false}, anddocument.elementFromPoint(x, y)returnsCODE < BUTTON < P < DIV.Scrollback makes it worse: the click handler closes over
openFile, whichknows the path, but the path never reaches the DOM, so nothing outside the
component can read it.
What a plugin has to do today
To get a working reveal, four separate edits are needed, two of them inside
the shipped app:
dsh-web-frontend/dist/assets/index-*.jsto stampdata-dsh-file-path/data-dsh-file-abson the rendered button;dsh-client-ui-chatso the markdown delegate context carriescwd(a relative path is rejected by the Host — see below);
app/lib/main.jsbecausesetWindowOpenHandler(() => ({action:"deny"}))silently swallows every
window.open, which is how a chat link opens a URL;contextmenuand callsremote.session.openWorkspacePath({ path, action: "reveal" }).Step 4 alone is right; steps 1–3 exist because there is no seam.
Proposal
Expose the link data a plugin needs, in the layer that already has it.
a. Stamp the path on the rendered element.
<a href>for external links is already fine —linkURLworks there.b. Add a context-menu extension point.
Either of these is enough:
slotsseat, e.g.conversation.link.contextMenu, rendered with theclicked link's descriptor (
{ kind: "file" | "url", path?, href?, sessionId });context-menu, for the case wherethe plugin owns the whole menu.
c. Fix
setWindowOpenHandlerinapp/lib/main.js.A deny-only handler makes every chat link dead with no error and no log. The
WebContentsViewhandler a few hundred lines above already does thiscorrectly, so this looks like an oversight rather than a policy.
One more thing the docs could state
session.openWorkspacePath({ path })requires an absolute path:The request field is documented as "Path after best-effort Session workspace
resolution, in Host filesystem syntax", which reads as if a workspace-relative
path would be resolved for you. It is not. The error text is also opaque — a
plugin author sees "Path has no verified Host path" and cannot tell that the
problem is relativity. Suggest either resolving relative paths against the
session root, or naming the reason in the message.
Environment
0.2.1-rc.5(desktop, macOS 26 / arm64)links (reveal in Finder, copy path, open in browser, copy link address).
Happy to share the implementation as a reference.
Alternatives considered
linkURLis empty for buttons.class names carry a per-build hash (
_fileLink_1ypvv_59).internals and would break on a React major.
All reactions