dsh-zen-remote 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/docs/remote-access.md +2 -2
  4. package/lan-gate.mjs +15 -1
  5. package/lib/client.js +271 -30
  6. package/lib/fingerprint.js +4 -2
  7. package/lib/fingerprint.js.map +1 -1
  8. package/lib/intercept.js +161 -14
  9. package/lib/intercept.js.map +1 -1
  10. package/lib/merge-streams.js +11 -4
  11. package/lib/merge-streams.js.map +1 -1
  12. package/lib/relay-access.js.map +1 -1
  13. package/lib/relay-server.js +32 -11
  14. package/lib/relay-server.js.map +1 -1
  15. package/lib/types/client/effects/model-group-side.d.ts +13 -0
  16. package/lib/types/client/effects/model-group-side.d.ts.map +1 -0
  17. package/lib/types/client/index.d.ts.map +1 -1
  18. package/lib/types/client/styles/compat.css.d.ts +1 -1
  19. package/lib/types/client/styles/compat.css.d.ts.map +1 -1
  20. package/lib/types/client/styles/composer.css.d.ts +1 -1
  21. package/lib/types/client/styles/composer.css.d.ts.map +1 -1
  22. package/lib/types/client/styles/remote-session.css.d.ts +1 -1
  23. package/lib/types/client/styles/remote-session.css.d.ts.map +1 -1
  24. package/lib/types/client-data/model-group-side.d.ts +44 -0
  25. package/lib/types/client-data/model-group-side.d.ts.map +1 -0
  26. package/lib/types/fingerprint.d.ts +4 -2
  27. package/lib/types/fingerprint.d.ts.map +1 -1
  28. package/lib/types/intercept.d.ts +19 -9
  29. package/lib/types/intercept.d.ts.map +1 -1
  30. package/lib/types/merge-streams.d.ts +7 -2
  31. package/lib/types/merge-streams.d.ts.map +1 -1
  32. package/lib/types/relay-access.d.ts.map +1 -1
  33. package/lib/types/relay-server.d.ts.map +1 -1
  34. package/lib/types/virtual-id.d.ts +14 -0
  35. package/lib/types/virtual-id.d.ts.map +1 -1
  36. package/lib/virtual-id.js +14 -0
  37. package/lib/virtual-id.js.map +1 -1
  38. package/package.json +48 -49
  39. package/src/client/effects/model-group-side.ts +132 -0
  40. package/src/client/index.tsx +7 -0
  41. package/src/client/styles/compat.css.ts +14 -8
  42. package/src/client/styles/composer.css.ts +2 -1
  43. package/src/client/styles/remote-session.css.ts +43 -20
  44. package/src/client-data/model-group-side.ts +65 -0
  45. package/src/fingerprint.ts +4 -2
  46. package/src/intercept.ts +167 -12
  47. package/src/merge-streams.ts +11 -4
  48. package/src/relay-access.ts +6 -3
  49. package/src/relay-server.ts +49 -11
  50. package/src/virtual-id.ts +15 -0
@@ -1,2 +1,2 @@
1
- export declare const REMOTE_SESSION_CSS = "/* ---------- remote session: hide the open-on-the-server-machine entries ----------\n A remote session's files live on the relay SERVER; every \"open\" control here\n would act on the machine the DSH process runs on, not the one the browser is\n on. Hidden while the current session is remote (html[data-zr-remote-session]):\n - [data-open-target] is dsh-client-ui-open-in-app's own mount marker (RT\n dsh-client-ui-open-in-app lib/client.js ~325: the split-button anchor\n React renders with data-open-target={kind}) \u2014 one selector covers the\n session-header \"Open In...\" button, the document-preview actions, AND the\n \"Open / Show in Finder / Choose an application\" buttons of the changes\n panel and the deliverable cards (RT dsh-client-ui-deliverables\n lib/client.js ~1702, ~1963: those cards render the open-in-app package's\n FileRouteAction through the deliverables.file.actions and\n deliverables.review.file.actions slots, the same OpenTargetButton anchor).\n The attribute is the component's own contract, not a generated class. */\nhtml[data-zr-remote-session=\"1\"] [data-open-target] {\n display: none !important;\n}\n\n/* ---------- remote session: hide dsh-better-sidebar's file surfaces (T53) ----------\n dsh-better-sidebar 0.24.x is the second big \"open the machine's files\" UI.\n Every tab it registers (files/editor, git changes, subagent/tasks, side\n chat, the markdown/html/code file viewers) builds its requests from a\n {sessionId, cwd} scope and POSTs them to the plugin's own /sidebar/api/*\n routes on whichever machine answers \u2014 in a remote session that is the\n SUB-CLIENT's machine (client.js call() ~3111, fetchUpload ~3162,\n encodeHtmlUrl /sidebar/html/ ~3069-3414), so the tree would show same-named\n LOCAL files as if they were the session's and an edit would WRITE locally.\n Per the T53 decision the interfaces are hidden, not proxied: the relay\n carries no /sidebar routes and none are added.\n\n Anchors, all the plugin's or the host's own rendered contracts (no hashed\n class names; the one suffix selector, _chipIcon, is unique among the\n profile's packages \u2014 checked dsh-vision-router / dsh-auto-approve /\n dsh-mem0 / dsh-llm-verifier / dsh-plugin-subscriptions /\n @liustack/modsearch / @wxg-prc-cpg/browser-skill-dsh-plugin (modsearch /\n browser-skill) / dshmarket and every @deepseek-ai sidebar package for it):\n\n HONEST LIMITS (T53-fix): everything here is display:none ONLY. The plugin's\n components stay mounted and keep silently POSTing READ-ONLY /sidebar/api\n requests to the local machine (session.cwd, changes.ops, the tree reads a\n mounted tab refreshes with) \u2014 the data never leaves that machine, and no\n write can happen because every write control is inside the hidden surfaces.\n Known boundary: a dsh-resource://file/** address opened through\n sidebarRight.openResource in a remote session (file links in chat,\n deliverables, @-references, skills) is CLAIMED by the plugin's editor\n registration (client.js ~21377: patterns [\"dsh-resource://file/**\"]) before\n the host preview sees it \u2014 the right sidebar expands, the rules below hide\n the tab's body and chip, and an EMPTY panel remains. Root fix needs\n zen-remote's own remote file tree; separate discussion.\n\n - [data-dsh-bottom-toggle] \u2014 the header-utilities button that expands the\n bottom workbench (client.js BottomDockToggle ~20863; slot registration\n ~21492-21498, id dsh-better-sidebar:bottom-toggle). Our own phone header\n button drives the OFFICIAL right sidebar (MobileSessionHeader.tsx), so\n hiding this does not strand the phone.\n - [data-dsh-panel-host] \u2014 the fixed viewport layer the plugin appends to\n document.body (client.js ~20763); the bottom workbench panel\n ([data-dsh-bottom-panel]) is its only child, so hiding the layer hides\n the workbench whole (tab strip, + menu, tree, editor and all).\n - --dsh-sidebar-height \u2014 the plugin's layout push: written INLINE on <html>\n while the workbench is open (client.js writeGeometry ~20482-20488) and\n spent by its own layout.css as the center column's margin-bottom\n (client.js layout css ~23009: #root [data-dsh-center-col] { margin-bottom:\n var(--dsh-sidebar-height, 0px) }). Hiding the panel alone would leave\n that reserved band as a blank strip under the conversation, so the remote\n html zeroes the variable. A stylesheet !important beats a non-important\n inline style, and the plugin's JS state is never touched: the moment the\n attribute is removed (back on a local session) its own value applies\n again, transitions included.\n - [data-dsh-native-tab-host] \u2014 the wrapper the plugin renders around EVERY\n tab body it contributes to the host's native right Sidebar\n (client.js NativeTabBody ~21074, marker ~21110/21120). The host's pane\n chrome is untouched: the strip keeps the \"+\" (guide) button and the\n collapse/fullscreen controls, so a tab that was already open leaves no\n dead panel \u2014 an empty body behind a strip that still collapses, and the\n \"+\" re-opens the guide page (whose plugin capsules these rules hide, see\n below). React keeps mounting into the display:none node: no errors, and\n the restore on returning to a local session is instant.\n - [data-dockkit-tab]:has([class$=\"_chipIcon\"]) \u2014 the native tab STRIP's\n chips for plugin tabs, so an already-open tab does not survive as a\n clickable ghost. The chip button is dockkit's ([data-dockkit-tab], dsh-web\n frontend bundle: role=tab, renderTabTitle inside a\n span[data-dockkit-tab-title]); its content is the plugin's\n NativeTabTitle (~21172-21197), which always leads with a\n [class$=\"_chipIcon\"] glyph span because every built-in descriptor ships an\n icon \u2014 a chip with no glyph (an external tab registered through the\n plugin's viewer service without an icon) keeps its chip; its body is\n still hidden by the rule above. Host tabs' chips never contain a\n _chipIcon (checked all four @deepseek-ai sidebar packages), so the\n remote-aware host files page survives alongside.\n - [data-floating-window]:has([data-window-body]) \u2014 the plugin's\n body-PORTALED floating windows (client.js FloatingWindow ~15078-15120):\n the task edit window (teams.taskCreate/Update with rootSessionId via\n /sidebar/api, writeTask ~3124-3140) and the job-output window (host jobs\n kill). Both open from the subagent/tasks tab; portal escapes the tab\n body's display:none, so they need their own rule. Anchored on the\n window's own root attribute plus its own inner body marker, so a foreign\n [data-floating-window] without that shape never matches.\n - guide capsules \u2014 the empty-sidebar doorway buttons the HOST renders from\n the plugin's registrations ([data-sidebar-right-guide-entry=\"<kind>\"], RT\n dsh-client-ui-sidebar-right lib/client.js:466): kinds git / subagent /\n sidechat exist only while this plugin registers them, so those selectors\n are inert without it. The \"files\" capsule is the one ambiguous kind:\n dsh-client-ui-sidebar-files registers the SAME kind (its filesDefinition,\n lib/client.js:14-31) and that page is REMOTE-AWARE (it injects the host's\n remote.workspaceFiles service). T53-fix discriminates on the capsule's\n own rendered contract instead of plugin presence: the host's EntryBox\n renders aria-keyshortcuts from the shortcut matching entry.commandId (RT\n sidebar-right lib/client.js:461-467) \u2014 the host files guide row carries\n commandId \"workspace.files\" (dsh-client-ui-sidebar-files\n lib/client.js:30), while better-sidebar's guide rows carry NO commandId\n (client.js registerNativeSurface ~21385-21400), so its capsule never\n renders the attribute. :not([aria-keyshortcuts]) therefore hides the\n plugin's takeover capsule and spares the host's wherever the host has a\n default binding. Boundary: that \"wherever\" is not everywhere \u2014 the host\n registers workspace.files defaults for desktop:macos/windows/linux and\n web:macos/windows only (dsh-client-ui-sidebar-files lib/client.js:949-977),\n so on any other platform the OFFICIAL capsule also renders without the\n attribute and this rule hides it too (cosmetic; the page stays reachable\n through its shortcut command path and the plugin's takeover is the\n \"files\" implementation on every deployment this plugin pairs with\n better-sidebar anyway). */\nhtml[data-zr-remote-session=\"1\"] [data-dsh-bottom-toggle] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-dsh-panel-host] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] {\n --dsh-sidebar-height: 0px !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-dsh-native-tab-host] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-dockkit-tab]:has([class$=\"_chipIcon\"]) {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-floating-window]:has([data-window-body]) {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-sidebar-right-guide-entry=\"git\"],\nhtml[data-zr-remote-session=\"1\"] [data-sidebar-right-guide-entry=\"subagent\"],\nhtml[data-zr-remote-session=\"1\"] [data-sidebar-right-guide-entry=\"sidechat\"] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-sidebar-right-guide-entry=\"files\"]:not([aria-keyshortcuts]) {\n display: none !important;\n}\n\n/* ---------- T52: model-menu groups follow the session's side ----------\n The model catalog is GLOBAL (one shared load per page), so the merged\n catalog shows the server's groups everywhere; but a selection is only\n runnable on the side the open session lives on \u2014 the interceptor refuses\n the other side with a clear message. Hide what cannot run, by the one\n stable mark the menu carries:\n - the model menu renders one section[role=\"group\"] per provider group\n with aria-labelledby=\"<useId>-<group.id>\" (RT dsh-client-ui-model-\n selection lib/client.js:830-835), so a VIRTUAL group's section carries\n the \"zr~\" prefix in that attribute \u2014 an attribute the component itself\n writes, like data-open-target above;\n - the menu is a portal under <body>, but <html> is still its ancestor,\n so the html-level session attribute scopes it with no host-depth\n assumption and no :has();\n - the [role=\"menu\"] scope keeps the rule inside dropdown menus (where the\n model picker lives); if DSH ever drops the aria mark the rule simply\n stops matching \u2014 the interceptor's refusals remain the backstop.\n In a remote session only the server's groups stay; otherwise only the\n local ones (the home page and dialogs read as local, which is right:\n the model picker only mounts inside a session, and a blank local\n session cannot run server models either). */\nhtml[data-zr-remote-session=\"1\"] [role=\"menu\"] section[role=\"group\"]:not([aria-labelledby*=\"zr~\"]) {\n display: none !important;\n}\nhtml:not([data-zr-remote-session]) [role=\"menu\"] section[role=\"group\"][aria-labelledby*=\"zr~\"] {\n display: none !important;\n}\n\n/* ---------- T52-fix: hide the virtual groups in NATIVE <option> pickers ----\n The model menu above is React DOM, but dsh-vision-router's settings render\n its vision-backend picker as a native <select> of <option value={group.id}>\n rows, and its filter (dsh-vision-router lib/client.js:661-670\n filterVisionBackendGroups) drops only vision-http / vision-chain / *-vision\n \u2014 a merged virtual group (\"zr~<id>~\u2026\") survives into that picker even\n though a server model can never be a LOCAL vision backend (the router calls\n providers from the machine it runs on). Native <option> rows honor\n display:none in the dropdown list, so this hides them wherever they appear:\n - no scoping attribute on purpose: a virtual group is not a runnable\n backend in ANY local context, and the option element itself carries the\n value \u2014 no host-depth assumption, no :has();\n - when the vision router (or any other <option>-rendering surface) is not\n installed, nothing matches \u2014 dead rule, zero cost;\n - zen-remote's own surfaces are checked: our settings forms render fixed\n enum options (\"web\" / \"desktop-client\" / role kinds /\n configForm enum strings, src/client/settings/SettingsSection.tsx:641,690-701)\n and none can start with \"zr~\" (virtual group ids only ever exist inside\n model-catalog payloads and model-selection arguments). */\noption[value^=\"zr~\"] {\n display: none !important;\n}\n\n/* ---------- remote session: hide the session-export menu item (T51, T51-fix) ----------\n A remote session's log lives on the relay server and the backend refuses\n /api/session.export for a virtual id with 403 remote-unsupported\n (fetch-route-intercept.ts) \u2014 the item would only ever end in the \"Export\n failed\" modal, so it is hidden IN THE MENU (T51-fix: the anchor button\n stays, because it also opens the \u53CD\u9988 entry, which a remote session can\n still use). The DOM, verified against RT:\n - the Menu renders its anchor and its list as SIBLINGS inside its own\n span root (RT dsh-client-ui-primitives lib/index.js ~4265-4273:\n children = [anchor, portal ? createPortal(list) : list]), and the\n export Menu passes no portal flag (default false, ~3923) \u2014 so the list\n is the anchor's next sibling, matched by the general-sibling\n combinator below;\n - the list surface carries role=\"menu\" (Menu passes it at ~4243;\n MenuSurface spreads ...props onto its root div, ~3778-3795) and the\n items viewport inside it is div[role=\"presentation\"] (~4249-4252);\n - every data item is ONE div (the itemWrap wrapper, ~4143), so\n :first-child of the viewport is the FIRST item \u2014 and the export\n package puts \u4E0B\u8F7D/\u5BFC\u51FA first by construction (RT dsh-session-log-export\n lib/client.js 202-206, the optional feedback entry appended after at\n 207-211).\n The anchor button class suffix is matched the way compat.css.ts matches\n module classes (the hash prefix is build-local, \"_moreButton\" is the\n source name; unique in this slot \u2014 the only other moreButton in the RT\n tree, dsh-client-ui-sidebar-documentpreview lib/client.excel.js, lives in\n the sidebar, never under conversation.session.header.utilities).\n Known costs, accepted: with the feedback UI absent the menu's only item\n is the export, so the opened menu is EMPTY; and keyboard navigation still\n steps into the hidden item (focusable but invisible) until activated or\n escaped \u2014 it cannot be triggered through the visibility, only tabbed\n past blindly. */\nhtml[data-zr-remote-session=\"1\"] [data-slot=\"conversation.session.header.utilities\"] [class$=\"_moreButton\"] ~ [role=\"menu\"] > [role=\"presentation\"] > :first-child {\n display: none !important;\n}\n";
1
+ export declare const REMOTE_SESSION_CSS = "/* ---------- remote session: hide the open-on-the-server-machine entries ----------\n A remote session's files live on the relay SERVER; every \"open\" control here\n would act on the machine the DSH process runs on, not the one the browser is\n on. Hidden while the current session is remote (html[data-zr-remote-session]):\n - [data-open-target] is dsh-client-ui-open-in-app's own mount marker (RT\n dsh-client-ui-open-in-app lib/client.js ~325: the split-button anchor\n React renders with data-open-target={kind}) \u2014 one selector covers the\n session-header \"Open In...\" button, the document-preview actions, AND the\n \"Open / Show in Finder / Choose an application\" buttons of the changes\n panel and the deliverable cards (RT dsh-client-ui-deliverables\n lib/client.js ~1702, ~1963: those cards render the open-in-app package's\n FileRouteAction through the deliverables.file.actions and\n deliverables.review.file.actions slots, the same OpenTargetButton anchor).\n The attribute is the component's own contract, not a generated class. */\nhtml[data-zr-remote-session=\"1\"] [data-open-target] {\n display: none !important;\n}\n\n/* ---------- remote session: hide dsh-better-sidebar's file surfaces (T53) ----------\n dsh-better-sidebar 0.24.x is the second big \"open the machine's files\" UI.\n Every tab it registers (files/editor, git changes, subagent/tasks, side\n chat, the markdown/html/code file viewers) builds its requests from a\n {sessionId, cwd} scope and POSTs them to the plugin's own /sidebar/api/*\n routes on whichever machine answers \u2014 in a remote session that is the\n SUB-CLIENT's machine (client.js call() ~3111, fetchUpload ~3162,\n encodeHtmlUrl /sidebar/html/ ~3069-3414), so the tree would show same-named\n LOCAL files as if they were the session's and an edit would WRITE locally.\n Per the T53 decision the interfaces are hidden, not proxied: the relay\n carries no /sidebar routes and none are added.\n\n Anchors, all the plugin's or the host's own rendered contracts (no hashed\n class names; the one suffix selector, _chipIcon, is unique among the\n profile's packages \u2014 checked dsh-vision-router / dsh-auto-approve /\n dsh-mem0 / dsh-llm-verifier / dsh-plugin-subscriptions /\n @liustack/modsearch / @wxg-prc-cpg/browser-skill-dsh-plugin (modsearch /\n browser-skill) / dshmarket and every @deepseek-ai sidebar package for it):\n\n HONEST LIMITS (T53-fix): everything here is display:none ONLY. The plugin's\n components stay mounted and keep silently POSTing READ-ONLY /sidebar/api\n requests to the local machine (session.cwd, changes.ops, the tree reads a\n mounted tab refreshes with) \u2014 the data never leaves that machine, and no\n write can happen because every write control is inside the hidden surfaces.\n Known boundary: a dsh-resource://file/** address opened through\n sidebarRight.openResource in a remote session (file links in chat,\n deliverables, @-references, skills) is CLAIMED by the plugin's editor\n registration (client.js ~21377: patterns [\"dsh-resource://file/**\"]) before\n the host preview sees it \u2014 the right sidebar expands, the rules below hide\n the tab's body and chip, and an EMPTY panel remains. Root fix needs\n zen-remote's own remote file tree; separate discussion.\n\n - [data-dsh-bottom-toggle] \u2014 the header-utilities button that expands the\n bottom workbench (client.js BottomDockToggle ~20863; slot registration\n ~21492-21498, id dsh-better-sidebar:bottom-toggle). Our own phone header\n button drives the OFFICIAL right sidebar (MobileSessionHeader.tsx), so\n hiding this does not strand the phone.\n - [data-dsh-panel-host] \u2014 the fixed viewport layer the plugin appends to\n document.body (client.js ~20763); the bottom workbench panel\n ([data-dsh-bottom-panel]) is its only child, so hiding the layer hides\n the workbench whole (tab strip, + menu, tree, editor and all).\n - --dsh-sidebar-height \u2014 the plugin's layout push: written INLINE on <html>\n while the workbench is open (client.js writeGeometry ~20482-20488) and\n spent by its own layout.css as the center column's margin-bottom\n (client.js layout css ~23009: #root [data-dsh-center-col] { margin-bottom:\n var(--dsh-sidebar-height, 0px) }). Hiding the panel alone would leave\n that reserved band as a blank strip under the conversation, so the remote\n html zeroes the variable. A stylesheet !important beats a non-important\n inline style, and the plugin's JS state is never touched: the moment the\n attribute is removed (back on a local session) its own value applies\n again, transitions included.\n - [data-dsh-native-tab-host] \u2014 the wrapper the plugin renders around EVERY\n tab body it contributes to the host's native right Sidebar\n (client.js NativeTabBody ~21074, marker ~21110/21120). The host's pane\n chrome is untouched: the strip keeps the \"+\" (guide) button and the\n collapse/fullscreen controls, so a tab that was already open leaves no\n dead panel \u2014 an empty body behind a strip that still collapses, and the\n \"+\" re-opens the guide page (whose plugin capsules these rules hide, see\n below). React keeps mounting into the display:none node: no errors, and\n the restore on returning to a local session is instant.\n - [data-dockkit-tab]:has([class$=\"_chipIcon\"]) \u2014 the native tab STRIP's\n chips for plugin tabs, so an already-open tab does not survive as a\n clickable ghost. The chip button is dockkit's ([data-dockkit-tab], dsh-web\n frontend bundle: role=tab, renderTabTitle inside a\n span[data-dockkit-tab-title]); its content is the plugin's\n NativeTabTitle (~21172-21197), which always leads with a\n [class$=\"_chipIcon\"] glyph span because every built-in descriptor ships an\n icon \u2014 a chip with no glyph (an external tab registered through the\n plugin's viewer service without an icon) keeps its chip; its body is\n still hidden by the rule above. Host tabs' chips never contain a\n _chipIcon (checked all four @deepseek-ai sidebar packages), so the\n remote-aware host files page survives alongside.\n - [data-floating-window]:has([data-window-body]) \u2014 the plugin's\n body-PORTALED floating windows (client.js FloatingWindow ~15078-15120):\n the task edit window (teams.taskCreate/Update with rootSessionId via\n /sidebar/api, writeTask ~3124-3140) and the job-output window (host jobs\n kill). Both open from the subagent/tasks tab; portal escapes the tab\n body's display:none, so they need their own rule. Anchored on the\n window's own root attribute plus its own inner body marker, so a foreign\n [data-floating-window] without that shape never matches.\n - guide capsules \u2014 the empty-sidebar doorway buttons the HOST renders from\n the plugin's registrations ([data-sidebar-right-guide-entry=\"<kind>\"], RT\n dsh-client-ui-sidebar-right lib/client.js:466): kinds git / subagent /\n sidechat exist only while this plugin registers them, so those selectors\n are inert without it. The \"files\" capsule is the one ambiguous kind:\n dsh-client-ui-sidebar-files registers the SAME kind (its filesDefinition,\n lib/client.js:14-31) and that page is REMOTE-AWARE (it injects the host's\n remote.workspaceFiles service). T53-fix discriminates on the capsule's\n own rendered contract instead of plugin presence: the host's EntryBox\n renders aria-keyshortcuts from the shortcut matching entry.commandId (RT\n sidebar-right lib/client.js:461-467) \u2014 the host files guide row carries\n commandId \"workspace.files\" (dsh-client-ui-sidebar-files\n lib/client.js:30), while better-sidebar's guide rows carry NO commandId\n (client.js registerNativeSurface ~21385-21400), so its capsule never\n renders the attribute. :not([aria-keyshortcuts]) therefore hides the\n plugin's takeover capsule and spares the host's wherever the host has a\n default binding. Boundary: that \"wherever\" is not everywhere \u2014 the host\n registers workspace.files defaults for desktop:macos/windows/linux and\n web:macos/windows only (dsh-client-ui-sidebar-files lib/client.js:949-977),\n so on any other platform the OFFICIAL capsule also renders without the\n attribute and this rule hides it too (cosmetic; the page stays reachable\n through its shortcut command path and the plugin's takeover is the\n \"files\" implementation on every deployment this plugin pairs with\n better-sidebar anyway). */\nhtml[data-zr-remote-session=\"1\"] [data-dsh-bottom-toggle] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-dsh-panel-host] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] {\n --dsh-sidebar-height: 0px !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-dsh-native-tab-host] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-dockkit-tab]:has([class$=\"_chipIcon\"]) {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-floating-window]:has([data-window-body]) {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-sidebar-right-guide-entry=\"git\"],\nhtml[data-zr-remote-session=\"1\"] [data-sidebar-right-guide-entry=\"subagent\"],\nhtml[data-zr-remote-session=\"1\"] [data-sidebar-right-guide-entry=\"sidechat\"] {\n display: none !important;\n}\nhtml[data-zr-remote-session=\"1\"] [data-sidebar-right-guide-entry=\"files\"]:not([aria-keyshortcuts]) {\n display: none !important;\n}\n\n/* ---------- T52/T74: model-menu groups follow the session's side ----------\n The model catalog is GLOBAL (one shared load per page), so the merged\n catalog shows the server's groups everywhere; but a selection is only\n runnable on the side the open session lives on \u2014 the interceptor refuses\n the other side with a clear message. Hide what cannot run.\n\n What changed and why the mechanism is a STAMP now (T74): through 0.1.7\n each menu group rendered aria-labelledby=\"<useId>-<group.id>\" (RT017\n dsh-client-ui-model-selection lib/client.js ~824-830) \u2014 the group id was\n IN the attribute, and rules could key on a virtual group's \"zr~\" prefix\n directly. 0.2.0 renders the groups with the primitives' MenuGroup\n instead (RT dsh-client-ui-primitives lib/index.js ~4283-4304): the\n section's aria-labelledby carries ONLY the useId, the heading is a child\n div[data-menu-group-heading], and the menu container is a div whose id\n ends in \"-models\" with role=\"menu\" (RT dsh-client-ui-model-selection\n lib/client.js ~974-980). Two consequences killed the old rules: a group\n section no longer says anywhere in its markup which group it is, and the\n same MenuGroup renders OTHER menus' groups too \u2014 the old\n [role=\"menu\"] section[role=\"group\"] scope alone was too wide and would\n have hidden every unmarked group of every menu in a remote session\n (leaving just the search box), while missing the server's groups in\n local ones.\n\n The new keys on what EVERY version actually renders, the heading text:\n each virtual group's name is prefixed with the invisible WORD JOINER\n (VIRTUAL_GROUP_NAME_MARK, virtual-id.ts; written by mergeModelCatalogs).\n The browser effect (effects/model-group-side.ts) reads each group's\n heading and stamps data-zr-group=\"remote|local\" on the section \u2014 but\n only inside a CONTAINER (the sections' shared parent element) that holds\n at least one marked heading. That container rule is what scopes these\n rules to the model menu alone WITHOUT assuming menu structure: an\n unpaired client's model menu, every other menu, and the whole rest of\n the page hold no marked heading, receive no stamp, and match neither\n rule. And since the merged catalog only ever APPENDS virtual groups to\n the local list, within a decided container the unmarked groups are\n exactly the local ones \u2014 mixed containers (the norm) decide each group\n separately. The menu is a portal under <body>, but <html> is still its\n ancestor, so the html-level session attribute scopes both rules. If the\n effect is not running (uninstalled, or a host-role page that never had\n it), no stamp exists and both rules go inert \u2014 nothing stays hidden.\n\n KNOWN BOUNDARY (accepted, not fixed): in a remote session, searching the\n model menu and pressing Enter can commit a HIDDEN local model \u2014 the\n interceptor refuses it with its usual message. */\nhtml[data-zr-remote-session=\"1\"] section[role=\"group\"][data-zr-group=\"local\"] {\n display: none !important;\n}\nhtml:not([data-zr-remote-session]) section[role=\"group\"][data-zr-group=\"remote\"] {\n display: none !important;\n}\n\n/* ---------- T52-fix: hide the virtual groups in NATIVE <option> pickers ----\n The model menu above is React DOM, but dsh-vision-router's settings render\n its vision-backend picker as a native <select> of <option value={group.id}>\n rows, and its filter (dsh-vision-router lib/client.js:661-670\n filterVisionBackendGroups) drops only vision-http / vision-chain / *-vision\n \u2014 a merged virtual group (\"zr~<id>~\u2026\") survives into that picker even\n though a server model can never be a LOCAL vision backend (the router calls\n providers from the machine it runs on). Native <option> rows honor\n display:none in the dropdown list, so this hides them wherever they appear:\n - no scoping attribute on purpose: a virtual group is not a runnable\n backend in ANY local context, and the option element itself carries the\n value \u2014 no host-depth assumption, no :has();\n - when the vision router (or any other <option>-rendering surface) is not\n installed, nothing matches \u2014 dead rule, zero cost;\n - zen-remote's own surfaces are checked: our settings forms render fixed\n enum options (\"web\" / \"desktop-client\" / role kinds /\n configForm enum strings, src/client/settings/SettingsSection.tsx:641,690-701)\n and none can start with \"zr~\" (virtual group ids only ever exist inside\n model-catalog payloads and model-selection arguments). */\noption[value^=\"zr~\"] {\n display: none !important;\n}\n\n/* ---------- remote session: hide the session-export menu item (T51, T51-fix) ----------\n A remote session's log lives on the relay server and the backend refuses\n /api/session.export for a virtual id with 403 remote-unsupported\n (fetch-route-intercept.ts) \u2014 the item would only ever end in the \"Export\n failed\" modal, so it is hidden IN THE MENU (T51-fix: the anchor button\n stays, because it also opens the \u53CD\u9988 entry, which a remote session can\n still use). The DOM, verified against RT:\n - the Menu renders its anchor and its list as SIBLINGS inside its own\n span root (RT dsh-client-ui-primitives lib/index.js ~4265-4273:\n children = [anchor, portal ? createPortal(list) : list]), and the\n export Menu passes no portal flag (default false, ~3923) \u2014 so the list\n is the anchor's next sibling, matched by the general-sibling\n combinator below;\n - the list surface carries role=\"menu\" (Menu passes it at ~4243;\n MenuSurface spreads ...props onto its root div, ~3778-3795) and the\n items viewport inside it is div[role=\"presentation\"] (~4249-4252);\n - every data item is ONE div (the itemWrap wrapper, ~4143), so\n :first-child of the viewport is the FIRST item \u2014 and the export\n package puts \u4E0B\u8F7D/\u5BFC\u51FA first by construction (RT dsh-session-log-export\n lib/client.js 202-206, the optional feedback entry appended after at\n 207-211).\n The anchor button class suffix is matched the way compat.css.ts matches\n module classes (the hash prefix is build-local, \"_moreButton\" is the\n source name; unique in this slot \u2014 the only other moreButton in the RT\n tree, dsh-client-ui-sidebar-documentpreview lib/client.excel.js, lives in\n the sidebar, never under conversation.session.header.utilities).\n Known costs, accepted: with the feedback UI absent the menu's only item\n is the export, so the opened menu is EMPTY; and keyboard navigation still\n steps into the hidden item (focusable but invisible) until activated or\n escaped \u2014 it cannot be triggered through the visibility, only tabbed\n past blindly. */\nhtml[data-zr-remote-session=\"1\"] [data-slot=\"conversation.session.header.utilities\"] [class$=\"_moreButton\"] ~ [role=\"menu\"] > [role=\"presentation\"] > :first-child {\n display: none !important;\n}\n";
2
2
  //# sourceMappingURL=remote-session.css.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"remote-session.css.d.ts","sourceRoot":"","sources":["../../../../src/client/styles/remote-session.css.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,kBAAkB,4+dA0O9B,CAAA"}
1
+ {"version":3,"file":"remote-session.css.d.ts","sourceRoot":"","sources":["../../../../src/client/styles/remote-session.css.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,kBAAkB,i9gBAiQ9B,CAAA"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * T74: which side of the pairing a model-menu GROUP belongs to, as pure
3
+ * functions — the readable core of the browser effect
4
+ * (src/client/effects/model-group-side.ts).
5
+ *
6
+ * WHY: the merged catalog (merge-streams.ts mergeModelCatalogs) appends the
7
+ * server's provider groups everywhere, but a selection only runs on the side
8
+ * the open session lives on — the interceptor refuses the other side. Through
9
+ * DSH 0.1.7 every menu group carried its id in `aria-labelledby`
10
+ * (`<useId>-<group.id>`), so CSS keyed the hiding on the `zr~` prefix (T52).
11
+ * DSH 0.2.0 renders the groups with the primitives' MenuGroup, whose
12
+ * `aria-labelledby` is a bare useId — the id is gone — and the same component
13
+ * renders OTHER menus' groups too, so attribute scoping misfires in both
14
+ * directions. Classification therefore moved to the one mark every version
15
+ * renders: virtual group NAMES start with VIRTUAL_GROUP_NAME_MARK
16
+ * (virtual-id.ts), read off each group's heading text.
17
+ *
18
+ * The container rule is what keeps the effect inert wherever it cannot be
19
+ * sure: a container with not ONE marked heading — the model menu of a
20
+ * sub-client with no shared models, every other menu on the page, the whole
21
+ * rest of the page — classifies as `undefined` for every group, which the
22
+ * effect reads as "leave the DOM alone". Only a container holding at least
23
+ * one marked heading is decided, and inside it the unmarked groups are
24
+ * exactly the LOCAL ones: the merged catalog only ever APPENDS virtual
25
+ * groups to the local list, never mixes them the other way.
26
+ *
27
+ * Defensive like the rest of client-data: an empty or missing heading never
28
+ * counts as a mark, so it can never decide a container by accident.
29
+ */
30
+ /** One group's display description, as the DOM shows it. */
31
+ export interface ModelGroupHeading {
32
+ /** Groups sharing one container share one key (the effect numbers the
33
+ * parent elements it scans). */
34
+ containerKey: number;
35
+ /** The group's heading text ('' when no heading could be found). */
36
+ headingText: string;
37
+ }
38
+ /** Per-group verdict, in input order: `remote` for marked headings, `local`
39
+ * for the rest of a container that has at least one, and `undefined` —
40
+ * "stamp nothing" — for every group of a container that holds no mark at
41
+ * all. */
42
+ export type ModelGroupSide = 'remote' | 'local' | undefined;
43
+ export declare function classifyModelGroups(groups: readonly ModelGroupHeading[]): ModelGroupSide[];
44
+ //# sourceMappingURL=model-group-side.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-group-side.d.ts","sourceRoot":"","sources":["../../../src/client-data/model-group-side.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC;oCACgC;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;UAGU;AACV,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;AAE3D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,iBAAiB,EAAE,GAAG,cAAc,EAAE,CAiB1F"}
@@ -8,8 +8,10 @@
8
8
  * definitions, the server puts its map into the handshake, the client
9
9
  * compares group by group, and the settings page lists the differing groups.
10
10
  * Identical maps mean fully compatible — the DSH version numbers themselves
11
- * are deliberately NOT compared (docs/spike-relay.md §2.3: 0.1.7 and 0.2.0
12
- * share byte-identical remote interfaces, so a version gate would misreject).
11
+ * are deliberately NOT compared (docs/spike-relay.md §2.3: 0.1.7-rc.2 and
12
+ * 0.2.0-rc.1 share byte-identical remote interfaces, so a version gate would
13
+ * misreject; 0.2.0-rc.2 then changed the session group within one minor —
14
+ * an additive optional field — which a version gate would have missed).
13
15
  *
14
16
  * What is hashed, per group, in priority order:
15
17
  *
@@ -1 +1 @@
1
- {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAQH,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,gBAAgB,CAAA;AAQpD,iFAAiF;AACjF,eAAO,MAAM,YAAY,WAAW,CAAA;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOvE,CAAA;AAKD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CACzC;AAED,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC5B;AAED,oEAAoE;AACpE,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,mEAAmE;IACnE,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB;;6BAEyB;IACzB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AA+CD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAqB9E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAE9E;AA0CD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAK/F;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAYlE;AAyDD;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAShI;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAwBrF"}
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAQH,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,gBAAgB,CAAA;AAQpD,iFAAiF;AACjF,eAAO,MAAM,YAAY,WAAW,CAAA;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOvE,CAAA;AAKD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CACzC;AAED,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC5B;AAED,oEAAoE;AACpE,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,mEAAmE;IACnE,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB;;6BAEyB;IACzB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AA+CD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAqB9E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAE9E;AA0CD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAK/F;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAYlE;AAyDD;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAShI;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAwBrF"}
@@ -57,11 +57,14 @@
57
57
  * `agentId` and `eventId` become `zr~<serverId>~…` virtual ids (those are
58
58
  * the ONLY session ids a forwarded waterfall carries — the request bodies
59
59
  * are tool/question data, verified against dsh-tools/dsh-user-questions),
60
- * and the remote `ready`/`emit` frames are DROPPED: the client face of the
60
+ * and the remote `ready`/`emit` frames are DROPPED — except, since T75, a
61
+ * shared session's `api-session/status` emit, which crosses with its
62
+ * session id virtualized (the one share-scoped emit; every other emit
63
+ * broadcasts server-wide state the UI must not mistake for local
64
+ * sessions). The client face of the
61
65
  * gateway (dsh-api-gateway lib/client.js) accepts a ready frame only as
62
- * the FIRST frame of the stream and would fail the stream on a second one,
63
- * and emit events broadcast server-wide state the UI must not mistake for
64
- * local sessions. Prompts this leg showed are closed when the leg dies —
66
+ * the FIRST frame of the stream and would fail the stream on a second one.
67
+ * Prompts this leg showed are closed when the leg dies —
65
68
  * each gets a synthesized `cancel` — so a disconnect cannot leave an
66
69
  * approval on screen that no server can settle anymore (T32-fix).
67
70
  * - `dispatchRpc('$events/result', …)` splits on the eventId: a virtual id
@@ -336,11 +339,18 @@ export declare function rewriteResult(endpoint: string, value: unknown, serverId
336
339
  * whole thing in `zr~<serverId>~`.
337
340
  * - `cancel`: `{type, eventId}` — the correlation id goes virtual so the UI
338
341
  * can match it against the waterfall it showed and close the prompt.
339
- * - everything else — `ready`, `emit`, non-objects, unknown types, and any
340
- * waterfall/cancel failing the client face's exact-keys shape — is
341
- * DROPPED (T32-fix2 mirrors the server side). `ready` and `emit` carry
342
- * facts the UI must never see (the local stream opened with ITS ready
343
- * frame; emit broadcasts server-wide state); a malformed frame that
342
+ * - `emit`: dropped, with ONE exception (T75) — a well-formed
343
+ * `api-session/status` frame (the only emit the server forwards, and only
344
+ * for accessible sessions) has its `args[0]` session id virtualized and
345
+ * its `args[1]` running flag passed through, so the UI's
346
+ * `api-session/status` listener keeps the remote session's running state
347
+ * in step with the host's (RT dsh-api-session-controller lib/client.js
348
+ * `handleSessionStatus`).
349
+ * - everything else — `ready`, non-status emits, non-objects, unknown
350
+ * types, and any frame failing the client face's exact-keys shape — is
351
+ * DROPPED (T32-fix2 mirrors the server side). `ready` and the other emits
352
+ * carry facts the UI must never see (the local stream opened with ITS
353
+ * ready frame; emits broadcast server-wide state); a malformed frame that
344
354
  * slipped through would fail `parseRemoteEventFrame` and take the UI's
345
355
  * whole `$events` generation down with it, failing and reconnecting in a
346
356
  * loop. Mirrors the server's own forwardable-shape gate, so the two ends
@@ -1 +1 @@
1
- {"version":3,"file":"intercept.d.ts","sourceRoot":"","sources":["../../src/intercept.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"intercept.d.ts","sourceRoot":"","sources":["../../src/intercept.ts"],"names":[],"mappings":"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"}
@@ -305,8 +305,13 @@ export declare function mergeSessionList(localResult: unknown, remoteResult: unk
305
305
  * order, RT dsh-client-ui-model-selection lib/client.js:510 — appended
306
306
  * groups render last); each group id becomes the virtual group id
307
307
  * `zr~<serverId>~<original>` and its name is prefixed
308
- * `${serverName} · ${name}` — the same workspace title discipline the
309
- * merger uses;
308
+ * `${VIRTUAL_GROUP_NAME_MARK}${serverName} · ${name}` — the same workspace
309
+ * title discipline the merger uses, PLUS the invisible WORD JOINER (T74):
310
+ * the model menu's groups stopped carrying their id in the markup (0.2.0's
311
+ * MenuGroup renders `aria-labelledby={useId()}` only), so the browser
312
+ * classifies menu groups by this heading prefix instead
313
+ * (client-data/model-group-side.ts). The sidebar's workspace TITLES stay
314
+ * unmarked — those groups are keyed by their `zr~` row ids;
310
315
  * - `default` and `failures` stay LOCAL untouched: the default drives what a
311
316
  * blank LOCAL session would run (a remote session's current model comes
312
317
  * from its projection instead), and the UI renders every failure as a
@@ -1 +1 @@
1
- {"version":3,"file":"merge-streams.d.ts","sourceRoot":"","sources":["../../src/merge-streams.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"merge-streams.d.ts","sourceRoot":"","sources":["../../src/merge-streams.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-access.d.ts","sourceRoot":"","sources":["../../src/relay-access.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relay-access.d.ts","sourceRoot":"","sources":["../../src/relay-access.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-server.d.ts","sourceRoot":"","sources":["../../src/relay-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relay-server.d.ts","sourceRoot":"","sources":["../../src/relay-server.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,20 @@
18
18
  */
19
19
  /** The fixed prefix every virtual id starts with. */
20
20
  export declare const VIRTUAL_ID_PREFIX = "zr~";
21
+ /**
22
+ * The invisible WORD JOINER (U+2060) every virtual GROUP NAME starts with
23
+ * (T74). DSH 0.2.0 renders the model menu's provider groups with the
24
+ * primitives' MenuGroup, whose `aria-labelledby` carries only a useId — the
25
+ * group id is gone from the markup — so the browser half can no longer tell
26
+ * a virtual group from a local one by attribute. The merged catalog's group
27
+ * NAME (merge-streams.ts mergeModelCatalogs) is the one mark that survives
28
+ * in both 0.1.7 and 0.2.0, and effects/model-group-side.ts classifies each
29
+ * group container by which headings start with it. Zero-width: headings
30
+ * read exactly as before. Sidebar workspace TITLES deliberately do NOT
31
+ * carry it — those groups are told apart by their `zr~` row ids, not by
32
+ * text.
33
+ */
34
+ export declare const VIRTUAL_GROUP_NAME_MARK = "\u2060";
21
35
  /** The two halves {@link fromVirtual} recovers from a virtual id. */
22
36
  export interface VirtualIdParts {
23
37
  serverId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-id.d.ts","sourceRoot":"","sources":["../../src/virtual-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,QAAQ,CAAA;AAMtC,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;CACX;AAED,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CASnE;AAED,4DAA4D;AAC5D,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAE9C"}
1
+ {"version":3,"file":"virtual-id.d.ts","sourceRoot":"","sources":["../../src/virtual-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,QAAQ,CAAA;AAEtC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,WAAW,CAAA;AAM/C,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;CACX;AAED,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CASnE;AAED,4DAA4D;AAC5D,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAE9C"}
package/lib/virtual-id.js CHANGED
@@ -18,6 +18,20 @@
18
18
  */
19
19
  /** The fixed prefix every virtual id starts with. */
20
20
  export const VIRTUAL_ID_PREFIX = 'zr~';
21
+ /**
22
+ * The invisible WORD JOINER (U+2060) every virtual GROUP NAME starts with
23
+ * (T74). DSH 0.2.0 renders the model menu's provider groups with the
24
+ * primitives' MenuGroup, whose `aria-labelledby` carries only a useId — the
25
+ * group id is gone from the markup — so the browser half can no longer tell
26
+ * a virtual group from a local one by attribute. The merged catalog's group
27
+ * NAME (merge-streams.ts mergeModelCatalogs) is the one mark that survives
28
+ * in both 0.1.7 and 0.2.0, and effects/model-group-side.ts classifies each
29
+ * group container by which headings start with it. Zero-width: headings
30
+ * read exactly as before. Sidebar workspace TITLES deliberately do NOT
31
+ * carry it — those groups are told apart by their `zr~` row ids, not by
32
+ * text.
33
+ */
34
+ export const VIRTUAL_GROUP_NAME_MARK = '\u2060';
21
35
  /** The server id half: exactly the 8 lowercase hex chars relay-server.ts
22
36
  * mints (`randomBytes(4).toString('hex')`). */
23
37
  const SERVER_ID_PATTERN = /^[0-9a-f]{8}$/;
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-id.js","sourceRoot":"","sources":["../src/virtual-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,qDAAqD;AACrD,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAA;AAEtC;+CAC+C;AAC/C,MAAM,iBAAiB,GAAG,eAAe,CAAA;AAQzC,yEAAyE;AACzE,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,EAAU;IACpD,OAAO,GAAG,iBAAiB,GAAG,QAAQ,IAAI,EAAE,EAAE,CAAA;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,EAAW;IACrC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC;QAAE,OAAO,SAAS,CAAA;IACjF,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAC/C,0EAA0E;IAC1E,yDAAyD;IACzD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,SAAS,CAAA;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACjC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;AACxC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,SAAS,CAAC,EAAW;IACnC,OAAO,WAAW,CAAC,EAAE,CAAC,KAAK,SAAS,CAAA;AACtC,CAAC"}
1
+ {"version":3,"file":"virtual-id.js","sourceRoot":"","sources":["../src/virtual-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,qDAAqD;AACrD,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAA;AAEtC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,QAAQ,CAAA;AAE/C;+CAC+C;AAC/C,MAAM,iBAAiB,GAAG,eAAe,CAAA;AAQzC,yEAAyE;AACzE,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,EAAU;IACpD,OAAO,GAAG,iBAAiB,GAAG,QAAQ,IAAI,EAAE,EAAE,CAAA;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,EAAW;IACrC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC;QAAE,OAAO,SAAS,CAAA;IACjF,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAC/C,0EAA0E;IAC1E,yDAAyD;IACzD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,SAAS,CAAA;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACjC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;AACxC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,SAAS,CAAC,EAAW;IACnC,OAAO,WAAW,CAAC,EAAE,CAAC,KAAK,SAAS,CAAA;AACtC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-zen-remote",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "一个插件、两种角色:主服务端把 DeepSeek Harness 变成手机能安全访问的 PWA(移动端界面、配对码网关、Web Push),并把选定会话共享给已配对的桌面端;子客户端在另一台 DSH 桌面端的侧边栏里远程使用这些会话。One DSH plugin, two roles: the host turns DeepSeek Harness into a phone-reachable PWA (mobile UI, pairing-code gateway behind your own reverse proxy, Web Push) and shares chosen sessions to paired desktops; the client uses those sessions remotely from another DSH desktop app's sidebar.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -82,18 +82,18 @@
82
82
  },
83
83
  "peerDependencies": {
84
84
  "@deepseek-ai/cordis": "*",
85
- "@deepseek-ai/dsh-client-locale": "^0.1.7-rc.2 || ^0.2.0-rc.1",
86
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.7-rc.2 || ^0.2.0-rc.1",
87
- "@deepseek-ai/dsh-client-ui-layout": "^0.1.7-rc.2 || ^0.2.0-rc.1",
88
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-rc.2 || ^0.2.0-rc.1",
89
- "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.7-rc.2 || ^0.2.0-rc.1",
90
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-rc.2 || ^0.2.0-rc.1",
91
- "@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1",
92
- "@deepseek-ai/dsh-session": "^0.1.7-rc.2 || ^0.2.0-rc.1",
93
- "@deepseek-ai/dsh-session-log-export": "^0.1.7-rc.2 || ^0.2.0-rc.1",
94
- "@deepseek-ai/dsh-session-query": "^0.1.7-rc.2 || ^0.2.0-rc.1",
95
- "@deepseek-ai/dsh-tools": "^0.1.7-rc.2 || ^0.2.0-rc.1",
96
- "@deepseek-ai/dsh-workspace": "^0.1.7-rc.2 || ^0.2.0-rc.1",
85
+ "@deepseek-ai/dsh-client-locale": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
86
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
87
+ "@deepseek-ai/dsh-client-ui-layout": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
88
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
89
+ "@deepseek-ai/dsh-client-ui-sidebar": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
90
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
91
+ "@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
92
+ "@deepseek-ai/dsh-session": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
93
+ "@deepseek-ai/dsh-session-log-export": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
94
+ "@deepseek-ai/dsh-session-query": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
95
+ "@deepseek-ai/dsh-tools": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
96
+ "@deepseek-ai/dsh-workspace": "^0.1.7-rc.2 || ^0.2.0-rc.1 || ^0.2.1-alpha.1",
97
97
  "@deepseek-ai/schemastery": "*",
98
98
  "react": "^18.2.0"
99
99
  },
@@ -115,43 +115,42 @@
115
115
  }
116
116
  },
117
117
  "devDependencies": {
118
- "@deepseek-ai/cordis": "4.0.4",
118
+ "@deepseek-ai/cordis": "4.0.5-alpha.1",
119
119
  "@deepseek-ai/cosmokit": "1.8.5",
120
- "@deepseek-ai/dsh-agent": "0.1.7-rc.2",
121
- "@deepseek-ai/dsh-api-remotes": "0.1.7-rc.2",
122
- "@deepseek-ai/dsh-api-session-controller": "0.1.7-rc.2",
123
- "@deepseek-ai/dsh-api-workspace-controller": "0.1.7-rc.2",
124
- "@deepseek-ai/dsh-brand": "0.1.7-rc.2",
125
- "@deepseek-ai/dsh-client-connection": "0.1.7-rc.2",
126
- "@deepseek-ai/dsh-client-locale": "0.1.7-rc.2",
127
- "@deepseek-ai/dsh-client-store": "0.1.7-rc.2",
128
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.7-rc.2",
129
- "@deepseek-ai/dsh-client-ui-layout": "0.1.7-rc.2",
130
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.7-rc.2",
131
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.7-rc.2",
132
- "@deepseek-ai/dsh-client-ui-session": "0.1.7-rc.2",
133
- "@deepseek-ai/dsh-client-ui-sidebar": "0.1.7-rc.2",
134
- "@deepseek-ai/dsh-client-ui-slots": "0.1.7-rc.2",
135
- "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.2",
136
- "@deepseek-ai/dsh-invariants": "0.1.7-rc.2",
137
- "@deepseek-ai/dsh-llm": "0.1.7-rc.2",
138
- "@deepseek-ai/dsh-ptc-runtime": "0.1.7-rc.2",
139
- "@deepseek-ai/dsh-sandbox": "0.1.7-rc.2",
140
- "@deepseek-ai/dsh-sandbox-policy": "0.1.7-rc.2",
141
- "@deepseek-ai/dsh-scope": "0.1.7-rc.2",
142
- "@deepseek-ai/dsh-session": "0.1.7-rc.2",
143
- "@deepseek-ai/dsh-session-log-export": "0.1.7-rc.2",
144
- "@deepseek-ai/dsh-session-projection": "0.1.7-rc.2",
145
- "@deepseek-ai/dsh-session-query": "0.1.7-rc.2",
146
- "@deepseek-ai/dsh-session-stats": "0.1.7-rc.2",
147
- "@deepseek-ai/dsh-subagent": "0.1.7-rc.2",
148
- "@deepseek-ai/dsh-timeout": "0.1.7-rc.2",
149
- "@deepseek-ai/dsh-token-meter": "0.1.7-rc.2",
150
- "@deepseek-ai/dsh-tools": "0.1.7-rc.2",
151
- "@deepseek-ai/dsh-typert-protocol": "0.1.7-rc.2",
152
- "@deepseek-ai/dsh-util-crypto": "0.1.7-rc.2",
153
- "@deepseek-ai/dsh-util-values": "0.1.7-rc.2",
154
- "@deepseek-ai/dsh-workspace": "0.1.7-rc.2",
120
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
121
+ "@deepseek-ai/dsh-api-remotes": "0.2.1-alpha.2",
122
+ "@deepseek-ai/dsh-api-session-controller": "0.2.1-alpha.2",
123
+ "@deepseek-ai/dsh-api-workspace-controller": "0.2.1-alpha.2",
124
+ "@deepseek-ai/dsh-brand": "0.2.1-alpha.2",
125
+ "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.2",
126
+ "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.2",
127
+ "@deepseek-ai/dsh-client-store": "0.2.1-alpha.2",
128
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.2",
129
+ "@deepseek-ai/dsh-client-ui-layout": "0.2.1-alpha.2",
130
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.2",
131
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.2",
132
+ "@deepseek-ai/dsh-client-ui-session": "0.2.1-alpha.2",
133
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.2.1-alpha.2",
134
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.2",
135
+ "@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.2",
136
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
137
+ "@deepseek-ai/dsh-ptc-runtime": "0.2.1-alpha.2",
138
+ "@deepseek-ai/dsh-sandbox": "0.2.1-alpha.2",
139
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.2",
140
+ "@deepseek-ai/dsh-scope": "0.2.1-alpha.2",
141
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
142
+ "@deepseek-ai/dsh-session-log-export": "0.2.1-alpha.2",
143
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
144
+ "@deepseek-ai/dsh-session-query": "0.2.1-alpha.2",
145
+ "@deepseek-ai/dsh-session-stats": "0.2.1-alpha.2",
146
+ "@deepseek-ai/dsh-subagent": "0.2.1-alpha.2",
147
+ "@deepseek-ai/dsh-timeout": "0.2.1-alpha.2",
148
+ "@deepseek-ai/dsh-token-meter": "0.2.1-alpha.2",
149
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
150
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.2",
151
+ "@deepseek-ai/dsh-util-crypto": "0.2.1-alpha.2",
152
+ "@deepseek-ai/dsh-util-values": "0.2.1-alpha.2",
153
+ "@deepseek-ai/dsh-workspace": "0.2.1-alpha.2",
155
154
  "@deepseek-ai/schemastery": "3.18.4",
156
155
  "@types/node": "^26.2.0",
157
156
  "@types/react": "~18.3.1",
@@ -0,0 +1,132 @@
1
+ import type { ClientContext } from '../compat/types.ts'
2
+ import { classifyModelGroups, type ModelGroupHeading } from '../../client-data/model-group-side.ts'
3
+
4
+ /**
5
+ * T74: stamp every model-menu group with the side of the pairing it belongs
6
+ * to, so remote-session.css.ts can hide the groups the open session cannot
7
+ * run. The stamps are `data-zr-group="remote|local"` on each
8
+ * `section[role="group"]`; which sections get one (and which get none) is
9
+ * the pure classifier's container rule (client-data/model-group-side.ts) —
10
+ * only a container holding at least one marked (WORD JOINER-prefixed, see
11
+ * virtual-id.ts) heading is decided at all, so every other menu and the
12
+ * whole rest of the page is never touched.
13
+ *
14
+ * Synchronous in the observer callback, never behind rAF: the callback is a
15
+ * microtask and runs before this frame paints, so a group that must be
16
+ * hidden is hidden the first time it is drawn. A rAF would land a frame late
17
+ * and show one frame of the groups the CSS is about to hide (AGENTS.md's
18
+ * "晚一帧" rule — the same shape the turn-fold and model-sheet-extras bugs
19
+ * shared). The cheap batch gate below keeps the full rescan off the hot
20
+ * path: most mutations (chat streaming, composer typing) touch no group.
21
+ */
22
+ const GROUP_SELECTOR = 'section[role="group"]'
23
+
24
+ /** The stamp this effect writes; remote-session.css.ts hides
25
+ * `[data-zr-group="local"]` in a remote session and
26
+ * `[data-zr-group="remote"]` everywhere else. */
27
+ const STAMP = 'data-zr-group'
28
+
29
+ /**
30
+ * The heading text a group section renders, across the two DSH layouts:
31
+ * 0.1.7 points `aria-labelledby` at a heading div (id `<useId>-<group.id>`);
32
+ * 0.2.0's MenuGroup points it at its own useId heading — which is also the
33
+ * first `[data-menu-group-heading]` child — and its first child is an
34
+ * id-less position sentinel span. Falls through in that order, then to the
35
+ * first id-bearing child (0.1.7's heading, should `aria-labelledby` ever be
36
+ * dropped), and gives up with `null`.
37
+ */
38
+ export function headingTextOf(section: Element, getElementById: (id: string) => Element | null): string | null {
39
+ const labelledby = section.getAttribute('aria-labelledby')
40
+ if (labelledby !== null) {
41
+ const heading = getElementById(labelledby)
42
+ if (heading !== null) return heading.textContent
43
+ }
44
+ const own = section.querySelector(':scope > [data-menu-group-heading]')
45
+ if (own !== null) return own.textContent
46
+ for (const child of section.children) {
47
+ if (child.id !== '') return child.textContent
48
+ }
49
+ return null
50
+ }
51
+
52
+ /** Does this mutation involve a group section, inside or as a node? Groups
53
+ * are rare; everything else (streaming text, composer typing) bails here. */
54
+ function touchesGroup(mutation: MutationRecord): boolean {
55
+ if (mutation.type === 'childList') {
56
+ for (const node of mutation.addedNodes) if (isGroupish(node)) return true
57
+ for (const node of mutation.removedNodes) if (isGroupish(node)) return true
58
+ }
59
+ const target = mutation.target
60
+ const el = target.nodeType === 1 ? (target as Element) : target.parentElement
61
+ return el !== null && el.closest(GROUP_SELECTOR) !== null
62
+ }
63
+
64
+ function isGroupish(node: Node): boolean {
65
+ if (node.nodeType !== 1) return false
66
+ const el = node as Element
67
+ return el.matches(GROUP_SELECTOR) || el.querySelector(GROUP_SELECTOR) !== null
68
+ }
69
+
70
+ export function installModelGroupSide(ctx: ClientContext): void {
71
+ ctx.effect(() => {
72
+ const applyVerdict = (section: Element, verdict: 'remote' | 'local' | undefined): void => {
73
+ // Write only on change — the observer does not watch attributes (so a
74
+ // stamp cannot re-trigger it), but a removed section's container may
75
+ // be re-decided, and an unconditional set would still churn
76
+ // style/attribute machinery for no effect.
77
+ if (verdict === undefined) {
78
+ if (section.hasAttribute(STAMP)) section.removeAttribute(STAMP)
79
+ } else if (section.getAttribute(STAMP) !== verdict) {
80
+ section.setAttribute(STAMP, verdict)
81
+ }
82
+ }
83
+
84
+ const scan = (): void => {
85
+ const sections = document.querySelectorAll(GROUP_SELECTOR)
86
+ // Group by parent element, in document order: querySelectorAll walks
87
+ // the document, and one parent's children form a contiguous run of it,
88
+ // so a running number per distinct parent is a stable container key.
89
+ const containerKeys = new Map<Element, number>()
90
+ const rows: Array<ModelGroupHeading & { section: Element }> = []
91
+ for (const section of sections) {
92
+ const parent = section.parentElement
93
+ if (parent === null) continue
94
+ let key = containerKeys.get(parent)
95
+ if (key === undefined) {
96
+ key = containerKeys.size
97
+ containerKeys.set(parent, key)
98
+ }
99
+ const text = headingTextOf(section, (id) => document.getElementById(id))
100
+ rows.push({ section, containerKey: key, headingText: text ?? '' })
101
+ }
102
+ const verdicts = classifyModelGroups(rows)
103
+ rows.forEach((row, i) => applyVerdict(row.section, verdicts[i]))
104
+ }
105
+
106
+ // childList + subtree catches mounted/unmounted/re-parented groups,
107
+ // characterData catches heading texts changing in place. Attributes are
108
+ // deliberately unwatched: this effect is their only writer.
109
+ const observer = new MutationObserver((mutations) => {
110
+ for (const mutation of mutations) {
111
+ if (touchesGroup(mutation)) {
112
+ scan()
113
+ return
114
+ }
115
+ }
116
+ })
117
+ observer.observe(document.body, { childList: true, subtree: true, characterData: true })
118
+ // The initial paint may already hold groups (session restored under an
119
+ // open menu): stamp them synchronously at install, like every observer
120
+ // effect here does.
121
+ scan()
122
+
123
+ return () => {
124
+ observer.disconnect()
125
+ // Undo every stamp so the host DOM reads exactly as before the effect
126
+ // ran — the CSS rules key on the stamp, so this un-hides everything.
127
+ for (const section of document.querySelectorAll(`${GROUP_SELECTOR}[${STAMP}]`)) {
128
+ section.removeAttribute(STAMP)
129
+ }
130
+ }
131
+ }, 'dsh-zen-remote: model group side')
132
+ }