@chatcode/cco-better-sidebar 0.18.0-alpha.0

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 (329) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +554 -0
  3. package/README_EN.md +563 -0
  4. package/assets/logo.svg +1 -0
  5. package/cordis.patch.yml +79 -0
  6. package/lib/client-editor.js +55744 -0
  7. package/lib/client-mermaid.js +208256 -0
  8. package/lib/client-registry.js +30378 -0
  9. package/lib/client-terminal.js +16894 -0
  10. package/lib/client.js +30378 -0
  11. package/lib/index.js +6897 -0
  12. package/lib/invariant.js +22 -0
  13. package/lib/types/agent-opens.d.ts +65 -0
  14. package/lib/types/agent-pty.d.ts +226 -0
  15. package/lib/types/browser-probe.d.ts +15 -0
  16. package/lib/types/bundle-route.d.ts +12 -0
  17. package/lib/types/chatcode-update.d.ts +47 -0
  18. package/lib/types/client/AccountMenu.d.ts +1 -0
  19. package/lib/types/client/AiRatioSection.d.ts +3 -0
  20. package/lib/types/client/BrowserView.d.ts +39 -0
  21. package/lib/types/client/ChatcodeGate.d.ts +6 -0
  22. package/lib/types/client/CodingPlanModelsSettings.d.ts +9 -0
  23. package/lib/types/client/DiffTab.d.ts +6 -0
  24. package/lib/types/client/DiffView.d.ts +51 -0
  25. package/lib/types/client/EditorHost.d.ts +13 -0
  26. package/lib/types/client/FenceErrorNotice.d.ts +5 -0
  27. package/lib/types/client/FileTree.d.ts +41 -0
  28. package/lib/types/client/FreeWindow.d.ts +29 -0
  29. package/lib/types/client/GitView.d.ts +12 -0
  30. package/lib/types/client/MarkdownHtml.d.ts +32 -0
  31. package/lib/types/client/OrphanedTab.d.ts +11 -0
  32. package/lib/types/client/PdfView.d.ts +6 -0
  33. package/lib/types/client/ReleaseNotesDialog.d.ts +11 -0
  34. package/lib/types/client/RenderBoundary.d.ts +32 -0
  35. package/lib/types/client/SandboxStatusBar.d.ts +10 -0
  36. package/lib/types/client/SideCardSection.d.ts +74 -0
  37. package/lib/types/client/Sidebar.d.ts +8 -0
  38. package/lib/types/client/TabBar.d.ts +54 -0
  39. package/lib/types/client/TerminalView.d.ts +24 -0
  40. package/lib/types/client/TextEditor.d.ts +10 -0
  41. package/lib/types/client/TreePanel.d.ts +27 -0
  42. package/lib/types/client/UpdateDialog.d.ts +10 -0
  43. package/lib/types/client/UpdateSettingsPanel.d.ts +1 -0
  44. package/lib/types/client/UpdateSettingsSection.d.ts +10 -0
  45. package/lib/types/client/UploadOverlay.d.ts +20 -0
  46. package/lib/types/client/UsageHeatmapSection.d.ts +4 -0
  47. package/lib/types/client/add-plugin-modal.d.ts +15 -0
  48. package/lib/types/client/api.d.ts +345 -0
  49. package/lib/types/client/binary-download.d.ts +12 -0
  50. package/lib/types/client/breakpoints.d.ts +17 -0
  51. package/lib/types/client/browser.d.ts +60 -0
  52. package/lib/types/client/builtins/index.d.ts +18 -0
  53. package/lib/types/client/builtins/tabs.d.ts +11 -0
  54. package/lib/types/client/builtins/viewers.d.ts +3 -0
  55. package/lib/types/client/chat-presentation.d.ts +13 -0
  56. package/lib/types/client/chunk-loader.d.ts +124 -0
  57. package/lib/types/client/chunks/editor.d.ts +9 -0
  58. package/lib/types/client/chunks/mermaid.d.ts +10 -0
  59. package/lib/types/client/chunks/terminal.d.ts +9 -0
  60. package/lib/types/client/cm-themes.d.ts +24 -0
  61. package/lib/types/client/conversation-draft.d.ts +14 -0
  62. package/lib/types/client/desktop-env.d.ts +35 -0
  63. package/lib/types/client/editor-load.d.ts +66 -0
  64. package/lib/types/client/frame-batcher.d.ts +24 -0
  65. package/lib/types/client/icons.d.ts +66 -0
  66. package/lib/types/client/image-types.d.ts +3 -0
  67. package/lib/types/client/ime-guard.d.ts +36 -0
  68. package/lib/types/client/index.d.ts +19 -0
  69. package/lib/types/client/intercept.d.ts +44 -0
  70. package/lib/types/client/lang.d.ts +14 -0
  71. package/lib/types/client/layout-push.d.ts +15 -0
  72. package/lib/types/client/lazy-chunk.d.ts +25 -0
  73. package/lib/types/client/link-intercept.d.ts +42 -0
  74. package/lib/types/client/locales-ar.d.ts +18 -0
  75. package/lib/types/client/locales-de.d.ts +4 -0
  76. package/lib/types/client/locales-fr.d.ts +10 -0
  77. package/lib/types/client/locales-hi.d.ts +17 -0
  78. package/lib/types/client/locales-id.d.ts +15 -0
  79. package/lib/types/client/locales-it.d.ts +8 -0
  80. package/lib/types/client/locales-ja.d.ts +17 -0
  81. package/lib/types/client/locales-ko.d.ts +9 -0
  82. package/lib/types/client/locales-nl.d.ts +16 -0
  83. package/lib/types/client/locales-pl.d.ts +19 -0
  84. package/lib/types/client/locales-pt.d.ts +1 -0
  85. package/lib/types/client/locales-ru.d.ts +13 -0
  86. package/lib/types/client/locales-sv.d.ts +1 -0
  87. package/lib/types/client/locales-th.d.ts +17 -0
  88. package/lib/types/client/locales-tr.d.ts +17 -0
  89. package/lib/types/client/locales-vi.d.ts +17 -0
  90. package/lib/types/client/locales-zh-HK.d.ts +32 -0
  91. package/lib/types/client/locales-zh-MO.d.ts +32 -0
  92. package/lib/types/client/locales-zh-TW.d.ts +32 -0
  93. package/lib/types/client/locales.d.ts +571 -0
  94. package/lib/types/client/markdown-html.d.ts +96 -0
  95. package/lib/types/client/markdown-images.d.ts +45 -0
  96. package/lib/types/client/markdown-labels.d.ts +21 -0
  97. package/lib/types/client/md-toc.d.ts +4 -0
  98. package/lib/types/client/mermaid-blocks.d.ts +47 -0
  99. package/lib/types/client/mermaid-sanitize.d.ts +2 -0
  100. package/lib/types/client/mermaid.d.ts +12 -0
  101. package/lib/types/client/open-when-sized.d.ts +20 -0
  102. package/lib/types/client/open-with-settings.d.ts +4 -0
  103. package/lib/types/client/open-with.d.ts +87 -0
  104. package/lib/types/client/openpath-intercept.d.ts +52 -0
  105. package/lib/types/client/paths.d.ts +43 -0
  106. package/lib/types/client/pdf-types.d.ts +2 -0
  107. package/lib/types/client/pinned.d.ts +86 -0
  108. package/lib/types/client/plugin-settings.d.ts +8 -0
  109. package/lib/types/client/plugins-shared.d.ts +27 -0
  110. package/lib/types/client/plugins-tabs.d.ts +3 -0
  111. package/lib/types/client/plugins-viewers.d.ts +3 -0
  112. package/lib/types/client/prefs.d.ts +41 -0
  113. package/lib/types/client/produced-files.d.ts +29 -0
  114. package/lib/types/client/selection-payload.d.ts +27 -0
  115. package/lib/types/client/service.d.ts +445 -0
  116. package/lib/types/client/session-pins.d.ts +14 -0
  117. package/lib/types/client/settings-nav-icon.d.ts +27 -0
  118. package/lib/types/client/shell-presets.d.ts +48 -0
  119. package/lib/types/client/split-pane.d.ts +38 -0
  120. package/lib/types/client/state.d.ts +480 -0
  121. package/lib/types/client/tab-content-memo.d.ts +40 -0
  122. package/lib/types/client/terminal-font.d.ts +78 -0
  123. package/lib/types/client/terminal-links.d.ts +119 -0
  124. package/lib/types/client/theme.d.ts +45 -0
  125. package/lib/types/client/titlebar-strip.d.ts +23 -0
  126. package/lib/types/client/ui-tweaks/appicons.d.ts +16 -0
  127. package/lib/types/client/ui-tweaks/archive.d.ts +42 -0
  128. package/lib/types/client/ui-tweaks/branding.d.ts +45 -0
  129. package/lib/types/client/ui-tweaks/cachehit.d.ts +41 -0
  130. package/lib/types/client/ui-tweaks/gitbar.d.ts +103 -0
  131. package/lib/types/client/ui-tweaks/index.d.ts +279 -0
  132. package/lib/types/client/ui-tweaks/mcp.d.ts +28 -0
  133. package/lib/types/client/ui-tweaks/notifier.d.ts +125 -0
  134. package/lib/types/client/ui-tweaks/whale.d.ts +55 -0
  135. package/lib/types/client/upload.d.ts +69 -0
  136. package/lib/types/client/useChatcodeAccount.d.ts +10 -0
  137. package/lib/types/client/wco.d.ts +47 -0
  138. package/lib/types/codingplan.d.ts +37 -0
  139. package/lib/types/config.d.ts +95 -0
  140. package/lib/types/context-types.d.ts +540 -0
  141. package/lib/types/fs-operations.d.ts +30 -0
  142. package/lib/types/fs-search.d.ts +24 -0
  143. package/lib/types/fs-tree.d.ts +51 -0
  144. package/lib/types/git.d.ts +124 -0
  145. package/lib/types/html-route.d.ts +59 -0
  146. package/lib/types/index.d.ts +47 -0
  147. package/lib/types/invariant.d.ts +15 -0
  148. package/lib/types/login-route.d.ts +2 -0
  149. package/lib/types/open-external.d.ts +24 -0
  150. package/lib/types/path-security.d.ts +26 -0
  151. package/lib/types/prefs-shared.d.ts +257 -0
  152. package/lib/types/pty-deps.d.ts +79 -0
  153. package/lib/types/pty-manager.d.ts +168 -0
  154. package/lib/types/tools.d.ts +34 -0
  155. package/lib/types/trust-fence.d.ts +24 -0
  156. package/lib/types/ui-tweaks/archive.d.ts +71 -0
  157. package/lib/types/ui-tweaks/config.d.ts +186 -0
  158. package/lib/types/ui-tweaks/git-web.d.ts +43 -0
  159. package/lib/types/ui-tweaks/git.d.ts +311 -0
  160. package/lib/types/ui-tweaks/index.d.ts +17 -0
  161. package/lib/types/ui-tweaks/mcp.d.ts +103 -0
  162. package/lib/types/ui-tweaks/turn-outcome.d.ts +57 -0
  163. package/lib/types/ui-tweaks/web.d.ts +55 -0
  164. package/lib/types/wire.d.ts +38 -0
  165. package/package.json +213 -0
  166. package/scripts/install.ps1 +310 -0
  167. package/scripts/install.sh +287 -0
  168. package/src/agent-opens.ts +265 -0
  169. package/src/agent-pty.ts +527 -0
  170. package/src/browser-probe.ts +26 -0
  171. package/src/bundle-route.ts +129 -0
  172. package/src/chatcode-update.ts +193 -0
  173. package/src/client/AccountMenu.tsx +177 -0
  174. package/src/client/AiRatioSection.module.css +329 -0
  175. package/src/client/AiRatioSection.tsx +292 -0
  176. package/src/client/BrowserView.tsx +289 -0
  177. package/src/client/ChatcodeGate.tsx +35 -0
  178. package/src/client/CodingPlanModelsSettings.module.css +118 -0
  179. package/src/client/CodingPlanModelsSettings.tsx +101 -0
  180. package/src/client/DiffTab.tsx +114 -0
  181. package/src/client/DiffView.tsx +305 -0
  182. package/src/client/EditorHost.tsx +563 -0
  183. package/src/client/FenceErrorNotice.tsx +40 -0
  184. package/src/client/FileTree.tsx +701 -0
  185. package/src/client/FreeWindow.tsx +337 -0
  186. package/src/client/GitView.tsx +722 -0
  187. package/src/client/MarkdownHtml.tsx +296 -0
  188. package/src/client/OrphanedTab.tsx +27 -0
  189. package/src/client/PdfView.tsx +110 -0
  190. package/src/client/ReleaseNotesDialog.tsx +91 -0
  191. package/src/client/RenderBoundary.tsx +49 -0
  192. package/src/client/SandboxStatusBar.tsx +60 -0
  193. package/src/client/SideCardSection.module.css +932 -0
  194. package/src/client/SideCardSection.tsx +1169 -0
  195. package/src/client/Sidebar.tsx +1857 -0
  196. package/src/client/TabBar.tsx +365 -0
  197. package/src/client/TerminalView.tsx +424 -0
  198. package/src/client/TextEditor.tsx +468 -0
  199. package/src/client/TreePanel.tsx +279 -0
  200. package/src/client/UpdateDialog.tsx +186 -0
  201. package/src/client/UpdateSettingsPanel.tsx +29 -0
  202. package/src/client/UpdateSettingsSection.tsx +22 -0
  203. package/src/client/UploadOverlay.tsx +62 -0
  204. package/src/client/UsageHeatmapSection.module.css +440 -0
  205. package/src/client/UsageHeatmapSection.tsx +301 -0
  206. package/src/client/add-plugin-modal.tsx +199 -0
  207. package/src/client/api.ts +433 -0
  208. package/src/client/binary-download.tsx +23 -0
  209. package/src/client/breakpoints.ts +61 -0
  210. package/src/client/browser.ts +167 -0
  211. package/src/client/builtins/index.ts +37 -0
  212. package/src/client/builtins/tabs.tsx +275 -0
  213. package/src/client/builtins/viewers.tsx +125 -0
  214. package/src/client/chat-presentation.ts +95 -0
  215. package/src/client/chunk-loader.ts +350 -0
  216. package/src/client/chunks/editor.tsx +9 -0
  217. package/src/client/chunks/mermaid.tsx +10 -0
  218. package/src/client/chunks/terminal.tsx +9 -0
  219. package/src/client/cm-themes.ts +129 -0
  220. package/src/client/conversation-draft.ts +29 -0
  221. package/src/client/css-modules.d.ts +5 -0
  222. package/src/client/desktop-env.ts +72 -0
  223. package/src/client/editor-load.ts +92 -0
  224. package/src/client/frame-batcher.ts +56 -0
  225. package/src/client/icons.tsx +170 -0
  226. package/src/client/image-types.ts +8 -0
  227. package/src/client/ime-guard.ts +47 -0
  228. package/src/client/index.tsx +501 -0
  229. package/src/client/intercept.tsx +172 -0
  230. package/src/client/lang.ts +225 -0
  231. package/src/client/layout-push.ts +37 -0
  232. package/src/client/layout.css +156 -0
  233. package/src/client/lazy-chunk.tsx +89 -0
  234. package/src/client/link-intercept.ts +73 -0
  235. package/src/client/locales-ar.ts +387 -0
  236. package/src/client/locales-de.ts +372 -0
  237. package/src/client/locales-fr.ts +379 -0
  238. package/src/client/locales-hi.ts +386 -0
  239. package/src/client/locales-id.ts +384 -0
  240. package/src/client/locales-it.ts +377 -0
  241. package/src/client/locales-ja.ts +486 -0
  242. package/src/client/locales-ko.ts +378 -0
  243. package/src/client/locales-nl.ts +384 -0
  244. package/src/client/locales-pl.ts +388 -0
  245. package/src/client/locales-pt.ts +369 -0
  246. package/src/client/locales-ru.ts +384 -0
  247. package/src/client/locales-sv.ts +369 -0
  248. package/src/client/locales-th.ts +386 -0
  249. package/src/client/locales-tr.ts +386 -0
  250. package/src/client/locales-vi.ts +386 -0
  251. package/src/client/locales-zh-HK.ts +401 -0
  252. package/src/client/locales-zh-MO.ts +401 -0
  253. package/src/client/locales-zh-TW.ts +401 -0
  254. package/src/client/locales.ts +1229 -0
  255. package/src/client/markdown-html.ts +331 -0
  256. package/src/client/markdown-images.ts +137 -0
  257. package/src/client/markdown-labels.tsx +31 -0
  258. package/src/client/md-toc.tsx +127 -0
  259. package/src/client/mermaid-blocks.ts +110 -0
  260. package/src/client/mermaid-sanitize.ts +93 -0
  261. package/src/client/mermaid.tsx +406 -0
  262. package/src/client/open-when-sized.ts +43 -0
  263. package/src/client/open-with-settings.tsx +135 -0
  264. package/src/client/open-with.ts +221 -0
  265. package/src/client/openpath-intercept.ts +79 -0
  266. package/src/client/paths.ts +63 -0
  267. package/src/client/pdf-types.ts +4 -0
  268. package/src/client/pinned.ts +184 -0
  269. package/src/client/plugin-settings.ts +43 -0
  270. package/src/client/plugins-shared.ts +29 -0
  271. package/src/client/plugins-tabs.ts +153 -0
  272. package/src/client/plugins-viewers.ts +44 -0
  273. package/src/client/prefs.ts +216 -0
  274. package/src/client/produced-files.ts +120 -0
  275. package/src/client/selection-payload.ts +86 -0
  276. package/src/client/service.ts +873 -0
  277. package/src/client/session-pins.tsx +334 -0
  278. package/src/client/settings-nav-icon.ts +55 -0
  279. package/src/client/shell-presets.ts +83 -0
  280. package/src/client/sidebar.module.css +3607 -0
  281. package/src/client/split-pane.tsx +333 -0
  282. package/src/client/state.ts +1646 -0
  283. package/src/client/tab-content-memo.ts +55 -0
  284. package/src/client/terminal-font.ts +224 -0
  285. package/src/client/terminal-links.ts +194 -0
  286. package/src/client/theme.ts +110 -0
  287. package/src/client/titlebar-strip.ts +37 -0
  288. package/src/client/ui-tweaks/appicons.ts +24 -0
  289. package/src/client/ui-tweaks/archive.tsx +281 -0
  290. package/src/client/ui-tweaks/branding.tsx +232 -0
  291. package/src/client/ui-tweaks/cachehit.tsx +122 -0
  292. package/src/client/ui-tweaks/gitbar.tsx +2559 -0
  293. package/src/client/ui-tweaks/index.tsx +1696 -0
  294. package/src/client/ui-tweaks/mcp.tsx +582 -0
  295. package/src/client/ui-tweaks/notifier.ts +514 -0
  296. package/src/client/ui-tweaks/whale.tsx +171 -0
  297. package/src/client/upload.ts +187 -0
  298. package/src/client/useChatcodeAccount.ts +103 -0
  299. package/src/client/wco.ts +120 -0
  300. package/src/codingplan.ts +146 -0
  301. package/src/config.ts +207 -0
  302. package/src/context-types.ts +559 -0
  303. package/src/fs-operations.ts +97 -0
  304. package/src/fs-search.ts +113 -0
  305. package/src/fs-tree.ts +158 -0
  306. package/src/git.ts +446 -0
  307. package/src/html-route.ts +106 -0
  308. package/src/index.ts +1524 -0
  309. package/src/invariant.ts +32 -0
  310. package/src/login-route.ts +26 -0
  311. package/src/open-external.ts +90 -0
  312. package/src/path-security.ts +81 -0
  313. package/src/prefs-shared.ts +303 -0
  314. package/src/pty-deps.ts +241 -0
  315. package/src/pty-manager.ts +376 -0
  316. package/src/tools.ts +482 -0
  317. package/src/trust-fence.ts +84 -0
  318. package/src/ui-tweaks/archive.ts +293 -0
  319. package/src/ui-tweaks/config.ts +257 -0
  320. package/src/ui-tweaks/git-web.ts +421 -0
  321. package/src/ui-tweaks/git.ts +1524 -0
  322. package/src/ui-tweaks/index.ts +61 -0
  323. package/src/ui-tweaks/mcp.ts +535 -0
  324. package/src/ui-tweaks/turn-outcome.ts +105 -0
  325. package/src/ui-tweaks/web.ts +225 -0
  326. package/src/wire.ts +110 -0
  327. package/vendor/addon-fit.js +2 -0
  328. package/vendor/xterm.css +218 -0
  329. package/vendor/xterm.js +5 -0
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Terminal URL hyperlinks: xterm's `registerLinkProvider` is fed per-line
3
+ * link descriptors built from the pty stream, so URLs printed by any tool
4
+ * become hoverable / clickable spans.
5
+ *
6
+ * To stay out of the user's way (a terminal's primary interaction is text
7
+ * selection, not browsing), a click only activates when the user holds
8
+ * Ctrl (Win/Linux) or Cmd (mac) — a plain click is left for xterm's
9
+ * normal selection handling. Only http(s) URLs are dispatched to the
10
+ * browser; other schemes (`file://`, `mailto:`, `javascript:`, …) are
11
+ * underlined for visibility but rejected at activation, so a `file://`
12
+ * URL printed by a tool stays inert instead of being handed to
13
+ * `window.open`.
14
+ *
15
+ * Kept as a pure module (no xterm import) so the regex, the line
16
+ * scanner, the modifier gate and the scheme guard are unit-testable
17
+ * without mounting a terminal. `buildTerminalLinks` returns plain-object
18
+ * descriptors whose shape matches xterm's `ILink` minus the `activate`
19
+ * callback — the caller attaches `activate` (which closes over the
20
+ * event modifier check + `openTerminalUrl`) so this module never
21
+ * imports xterm types.
22
+ */
23
+ /**
24
+ * The URL pattern used to scan each terminal line.
25
+ *
26
+ * A word boundary (`\b`) guards the leading scheme so `notttps://…` does
27
+ * not match. The character class excludes ASCII whitespace and the
28
+ * wrapping punctuation that shells commonly emit around URLs (quotes,
29
+ * angle brackets, brackets/braces, pipes, backslashes, backticks) so a
30
+ * URL printed as `"https://example.com"` or `<https://example.com>` does
31
+ * not drag the wrapping character into the link target.
32
+ *
33
+ * Carries the `g` flag so `findTerminalUrlsInLine` can iterate every
34
+ * match on a line; callers must reset `lastIndex` before reuse (the
35
+ * helper does this defensively).
36
+ */
37
+ export declare const TERMINAL_URL_REGEX: RegExp;
38
+ /** A URL match in a terminal line: the text and its 0-based start offset. */
39
+ export interface TerminalUrlMatch {
40
+ /** 0-based start index of the URL within the line string. */
41
+ start: number;
42
+ /** The matched URL text. */
43
+ text: string;
44
+ }
45
+ /**
46
+ * Find every http(s) URL in a line of terminal text, in source order
47
+ * with 0-based start offsets. A link provider maps these to buffer
48
+ * ranges for xterm's `registerLinkProvider`.
49
+ *
50
+ * Trailing unmatched closing parens are trimmed from each match (see
51
+ * {@link trimUnbalancedTrailingParens}), so a URL wrapped in parens by
52
+ * a shell opens without the trailing `)`, while Wikipedia-style URLs
53
+ * with balanced parens stay intact.
54
+ *
55
+ * Resets the regex's `lastIndex` before and after the scan so a
56
+ * previous partial iteration can't desynchronize a later one (the
57
+ * regex carries the `g` flag and is module-shared).
58
+ */
59
+ export declare function findTerminalUrlsInLine(line: string): TerminalUrlMatch[];
60
+ /**
61
+ * A buffer range in xterm's coordinate system. xterm's cell `x` is
62
+ * 1-based (1..cols) and `y` is the buffer line number; the `end` is
63
+ * inclusive (the last cell covered by the link). Structurally
64
+ * compatible with xterm's `IBufferRange` so the caller can pass it
65
+ * straight through without importing xterm types here.
66
+ */
67
+ export interface TerminalLinkRange {
68
+ start: {
69
+ x: number;
70
+ y: number;
71
+ };
72
+ end: {
73
+ x: number;
74
+ y: number;
75
+ };
76
+ }
77
+ /**
78
+ * A link descriptor: a buffer range plus the URL text. The caller
79
+ * (the link provider in `TerminalView`) attaches the `activate`
80
+ * callback, which closes over the modifier gate and `openTerminalUrl`.
81
+ */
82
+ export interface TerminalLinkDescriptor {
83
+ range: TerminalLinkRange;
84
+ text: string;
85
+ }
86
+ /**
87
+ * Build link descriptors for every URL found in a terminal line.
88
+ *
89
+ * @param lineText - the line's text (e.g. from
90
+ * `IBufferLine.translateToString(true)`).
91
+ * @param lineNumber - the buffer line number xterm passed to
92
+ * `ILinkProvider.provideLinks` (used as the `y` of every range; URLs
93
+ * never span wrapped lines because each wrapped row is its own
94
+ * buffer line).
95
+ * @returns descriptors in source order; empty when the line has no URL.
96
+ */
97
+ export declare function buildTerminalLinks(lineText: string, lineNumber: number): TerminalLinkDescriptor[];
98
+ /**
99
+ * Decide whether a click on a terminal link should activate (open the URL).
100
+ *
101
+ * Mirrors what every modern terminal does (Windows Terminal, iTerm2, the
102
+ * VSCode integrated terminal): a plain click stays a text-selection
103
+ * gesture, and only Ctrl (Win/Linux) or Cmd (mac) hands the URL to the
104
+ * browser. The modifier is read off the activating `MouseEvent`, not
105
+ * tracked separately, so a key-up between hover and click never
106
+ * desynchronizes the gate.
107
+ */
108
+ export declare function shouldActivateTerminalLink(event: MouseEvent): boolean;
109
+ /**
110
+ * Open a URL matched in the terminal, with a scheme guard so a printed
111
+ * `file://` or anything that slipped past the regex cannot reach
112
+ * `window.open`. The URL is constructed via `new URL(...)` which throws
113
+ * on malformed input; the catch makes the function total so the xterm
114
+ * handler never throws into the terminal's event loop.
115
+ *
116
+ * @returns `true` when the URL was dispatched to `window.open`, `false`
117
+ * when it was rejected (bad URL, disallowed scheme, no `window`).
118
+ */
119
+ export declare function openTerminalUrl(uri: string): boolean;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Live theme access for surfaces that cannot consume the token colors
3
+ * directly — xterm's palette and CodeMirror's theme extensions need concrete
4
+ * values, but the app's scheme flips at runtime (ui-layout's ThemePresenter
5
+ * projects prefers-color-scheme and the user's choice onto
6
+ * body[data-ds-dark-theme] and html { color-scheme }). This module reads the
7
+ * resolved scheme and token values, and notifies subscribers on flips, so
8
+ * the terminal and the editor re-theme in place instead of freezing in the
9
+ * scheme they happened to be created under.
10
+ */
11
+ /** Whether the app shell resolved to the dark scheme.
12
+ *
13
+ * The presenter sets `html { color-scheme }` together with the body palette
14
+ * attribute, so a set color-scheme means the decision is authoritative (an
15
+ * absent attribute is then LIGHT even when the OS prefers dark — the user
16
+ * chose light). Before the presenter has run, fall back to the OS media
17
+ * query as the best guess.
18
+ */
19
+ export declare function isDarkScheme(): boolean;
20
+ /** One token's computed value on <body> ('' while the theme has not applied). */
21
+ export declare function tokenValue(name: string): string;
22
+ /** The alpha channel of a computed CSS color, or null when the format is
23
+ * not parseable (named colors, `color()`… — treated as opaque). Handles
24
+ * the shapes getComputedStyle actually returns: the rgb()/rgba() and
25
+ * hsl()/hsla() function forms (comma or space syntax, with or without the
26
+ * `/ alpha` slot) and the #rgb/#rgba/#rrggbb/#rrggbbaa hex family. */
27
+ export declare function colorAlpha(color: string): number | null;
28
+ /**
29
+ * A token value that actually PAINTS something — the guard for text
30
+ * surfaces (issue #90). Skin systems routinely set global tokens to
31
+ * `transparent` (glass skins) or translucent glass values (`rgba(…,0.16–0.7)`,
32
+ * e.g. the dsh-web-ui skins) — both are truthy strings, so callers using
33
+ * `|| fallback` never fire and the terminal/editor goes see-through over
34
+ * the skin's backdrop. This returns '' for visually inert values (unset
35
+ * keywords, transparent, and any color below the opacity floor) so the
36
+ * caller's fallback chain engages; effectively opaque values pass through.
37
+ */
38
+ export declare function effectiveTokenValue(name: string): string;
39
+ /**
40
+ * Subscribe to color-scheme flips (the presenter toggles the body
41
+ * attribute). The callback fires after the attribute changed; re-read the
42
+ * scheme inside it.
43
+ * @returns the disposer.
44
+ */
45
+ export declare function subscribeColorScheme(callback: () => void): () => void;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The title-bar strip resolution chain — the ONE place that decides how
3
+ * many pixels the sidebar yields at the top. Standard signals first, then
4
+ * the user's chosen scheme; never a per-shell branch:
5
+ *
6
+ * 0. `web` scheme — EXPLICIT "ChatCode CLI Web": never adapt, not even
7
+ * standard WCO geometry (the user declares the plain web UI).
8
+ * 1. Window Controls Overlay real geometry (standard API, authoritative
9
+ * when present — even 0, e.g. the overlay is hidden while maximized).
10
+ * 2. The `dsh-desktop-titlebar-inset` URL contract parameter (a shell
11
+ * declares the exact pixels it reserves).
12
+ * 3. The active shell preset's strip (scheme `preset` — opt-in data).
13
+ * 4. The legacy manual `titleBarStripPx` (scheme `custom`).
14
+ * 5. 0 — plain-browser semantics, nothing modified.
15
+ *
16
+ * The result drives `--dsh-title-bar-strip` + `body[data-dsh-title-bar-compat]`
17
+ * exactly like the legacy boolean did; only the VALUE source changed.
18
+ */
19
+ import type { DesktopEnv } from './desktop-env.ts';
20
+ import type { TitleBarScheme } from '../prefs-shared.ts';
21
+ import type { WcoSnapshot } from './wco.ts';
22
+ import { type ShellPreset } from './shell-presets.ts';
23
+ export declare function computeTitleBarStrip(env: DesktopEnv, wco: WcoSnapshot, scheme: TitleBarScheme, preset: ShellPreset | undefined, customStripPx: number): number;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Official app icons for the 打开项目 menu — JetBrains product marks are
3
+ * the full-color SVGs from resources.jetbrains.com (gradient ids namespaced
4
+ * per icon so several can coexist on one page), VS Code from simple-icons,
5
+ * Explorer a filled Windows-yellow folder. Sizing lives in CSS.
6
+ * @module dsh-ui-tweaks/client/appicons
7
+ */
8
+ /** target key -> inline SVG markup (trusted build-time constants). */
9
+ export declare const APP_ICONS: {
10
+ explorer: string;
11
+ vscode: string;
12
+ idea: string;
13
+ goland: string;
14
+ webstorm: string;
15
+ pycharm: string;
16
+ };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * dsh-ui-tweaks — Archive manager (browser half).
3
+ *
4
+ * Renders the "归档" settings section (shown in the Settings dialog; usable
5
+ * when the `archiveManagerEnabled` toggle in 界面调整 is on — otherwise it
6
+ * shows an invite card with a one-click enable). The section lists every
7
+ * archived session — enriched from the framework `useSessions` /
8
+ * `useWorkspaces` feeds — with per-row actions and batch actions that go
9
+ * through the same-origin archive route (`/_dsh/ui-tweaks/archive`):
10
+ *
11
+ * - **恢复** (Restore): remove the session from the archive set — its log and
12
+ * workspace slot are kept, so the conversation reappears in the normal
13
+ * sidebar list.
14
+ * - **删除** (Delete): PERMANENTLY delete the session — the server removes its
15
+ * durable log, workspace accounting, archive-set entry and caches; the list
16
+ * then refreshes so the row (and the session itself) disappear.
17
+ * - **全部恢复 / 全部删除**: the same actions for every archived session.
18
+ *
19
+ * Live (open/running) sessions are refused by the server; the client maps the
20
+ * `session-live` error code to localized copy.
21
+ * @module dsh-ui-tweaks/client/archive
22
+ */
23
+ import type { ISessions, SessionListState } from '@deepseek-ai/dsh-api-session-controller/client';
24
+ import type { WorkspaceSnapshot } from '@deepseek-ai/dsh-api-workspace-controller/client';
25
+ import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';
26
+ import type { SettingsClient } from './index.tsx';
27
+ /** Locale keys the Archive manager reads off the `ui-tweaks` dictionary. */
28
+ type ArchiveLabelKey = 'archiveNav' | 'archiveTitle' | 'archiveEmpty' | 'archiveRestore' | 'archiveRestoring' | 'archiveDelete' | 'archiveDeleteAll' | 'archiveRestoreAll' | 'archiveCount' | 'archiveUnavailable' | 'archiveLiveError' | 'archiveDisabledHint' | 'archiveEnable' | 'archiveRestored' | 'unavailable';
29
+ type Translate = (key: ArchiveLabelKey) => string;
30
+ export declare const ARCHIVE_CSS = "\n.dut-arc{display:grid;gap:12px;max-width:680px;padding:6px 2px 36px}\n.dut-arc-head{display:flex;align-items:center;gap:10px;padding:14px 16px 0}\n.dut-arc-head h2{margin:0;font-size:15px;font-weight:600;letter-spacing:-.01em;color:var(--dsw-alias-label-primary)}\n.dut-arc-count{font-size:11.5px;color:var(--dsw-alias-label-secondary);padding:2px 8px;border-radius:999px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1)}\n.dut-arc-spacer{flex:1}\n.dut-arc-btn{display:inline-flex;align-items:center;height:28px;padding:0 12px;border-radius:999px;border:1px solid var(--dsw-alias-border-l1);background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;cursor:pointer;transition:background .15s ease,color .15s ease,border-color .15s ease}\n.dut-arc-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.dut-arc-btn:disabled{opacity:.5;cursor:default}\n.dut-arc-btn.dut-arc-del:hover{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 55%,transparent);color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}\n.dut-arc-btn.dut-arc-confirm{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 55%,transparent);color:var(--dsw-alias-state-error-primary);font-weight:600}\n.dut-arc-body{display:grid;gap:2px;margin-top:4px}\n.dut-arc-row{display:flex;align-items:center;gap:8px;padding:10px 16px;border-radius:12px}\n.dut-arc-row:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.dut-arc-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;text-align:left;background:transparent;border:none;padding:0;cursor:default;color:var(--dsw-alias-label-primary);font:inherit}\n.dut-arc-title{font-size:13.5px;font-weight:600;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}\n.dut-arc-sub{font-size:11.5px;color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}\n.dut-arc-empty{padding:32px 16px;text-align:center;font-size:12.5px;color:var(--dsw-alias-label-secondary)}\n.dut-arc-alert{margin:8px 16px 0;padding:8px 12px;border-radius:10px;font-size:12px;line-height:1.5;background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary)}\n.dut-arc-off{padding:20px 16px;display:grid;gap:12px}\n.dut-arc-off p{margin:0;font-size:12.5px;line-height:1.6;color:var(--dsw-alias-label-secondary)}\n";
31
+ /** Install the Archive stylesheet once (idempotent); returns the disposer. */
32
+ export declare function installArchiveStyles(): () => void;
33
+ export interface ArchiveSectionProps {
34
+ controller: SettingsClient;
35
+ t: Translate;
36
+ sessionsService: ISessions;
37
+ /** Framework standard feeds: session list + workspace archive set. */
38
+ useSessions: SnapshotSelectorHook<SessionListState>;
39
+ useWorkspaces: SnapshotSelectorHook<WorkspaceSnapshot>;
40
+ }
41
+ export declare function ArchiveSection({ controller, t, sessionsService, useSessions, useWorkspaces }: ArchiveSectionProps): import("react").JSX.Element;
42
+ export {};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * ChatCode CLI visual identity.
3
+ *
4
+ * The host owns its component tree, so this module deliberately uses stable
5
+ * semantics (roles, composer data attributes and visible labels) instead of
6
+ * the host's CSS-module hashes. A small observer reapplies the few DOM
7
+ * affordances after the host swaps a session or rerenders its sidebar.
8
+ */
9
+ import type { ReactNode } from 'react';
10
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
11
+ interface SlotMap {
12
+ 'sidebar.brand.mark': {
13
+ kind: 'single';
14
+ scope: 'root';
15
+ owner: {
16
+ size: number;
17
+ };
18
+ };
19
+ 'sidebar.brand.name': {
20
+ kind: 'single';
21
+ scope: 'root';
22
+ owner: Record<never, never>;
23
+ };
24
+ }
25
+ }
26
+ /** Browser URL for the project-owned `assets/logo.svg` file. */
27
+ export declare const PROJECT_LOGO_URL = "/_dsh/ui-tweaks/assets/logo.svg";
28
+ /** Reusable rendering of the packaged project logo. */
29
+ export declare function ProjectLogoIcon({ className }: {
30
+ className?: string;
31
+ }): ReactNode;
32
+ /** New-session brand-mark slot supplied by the conversation package. */
33
+ export declare function HeroProjectLogo({ size, className }: {
34
+ size: number;
35
+ className?: string | undefined;
36
+ }): ReactNode;
37
+ /** Sidebar mark shared by the expanded header and the collapsed rail. */
38
+ export declare function SidebarProjectLogo({ size }: {
39
+ size: number;
40
+ }): ReactNode;
41
+ /** Expanded-sidebar wordmark supplied through the host's dedicated slot. */
42
+ export declare function SidebarProjectName(): ReactNode;
43
+ export declare const BRANDING_CSS = "\n/* Keep the light-theme type hierarchy in ChatCode's restrained red family,\n while leaving every surface and interaction state (including workspace /\n sidebar hover and selected fills, menus, the composer and shadows) owned\n by the host theme. */\nbody:not([data-ds-dark-theme]){\n --dsw-alias-label-primary:#301111;\n --dsw-alias-label-secondary:#754745;\n --dsw-alias-label-tertiary:#a77471;\n}\n/* Saturated brand red remains exclusive to explicitly marked primary actions. */\nbody:not([data-ds-dark-theme]) .dut-unicom-primary-action{background:linear-gradient(135deg,#9B0B09,#b71916) !important;border-color:#9B0B09 !important;color:#fff !important;box-shadow:0 7px 18px rgba(155,11,9,.24) !important}\nbody:not([data-ds-dark-theme]) .dut-unicom-primary-action:hover{background:linear-gradient(135deg,#b71916,#cf302c) !important;border-color:#b71916 !important;color:#fff !important;box-shadow:0 10px 24px rgba(155,11,9,.30) !important}\nbody:not([data-ds-dark-theme]) .dut-unicom-primary-action:active{transform:translateY(1px);box-shadow:0 4px 11px rgba(155,11,9,.22) !important}\n/* In dark mode, alter only the resting background of primary buttons. Once\n hovered, the host owns the complete interaction treatment again. */\nbody[data-ds-dark-theme] .dut-unicom-primary-action:not(:hover){background:#9B0B09 !important}\n.dut-project-logo{display:block;object-fit:contain}\n.dut-left-logo{width:44px !important;height:44px !important}\n.dut-brand-title{font-size:18px !important;font-weight:600 !important}\n.dut-sidebar-logo{width:44px !important;height:44px !important}\n/* The alpha sidebar keeps its slotted identity at 24px and clips the brand\n button. Give only our expanded identity the full artwork height so the\n 44px knot is not cropped by that host-owned overflow boundary. */\n[class*=\"brandIdentity\"]:has(.dut-sidebar-logo){height:44px !important}\n.dut-sidebar-brand-name{font-size:18px !important;line-height:22px !important;font-weight:600 !important;letter-spacing:0 !important;white-space:nowrap}\n.dut-brand-version{display:none !important}\n.dut-hero-preview{display:none !important}\n.dut-hero-logo{width:60px !important;height:60px !important}\n[class*=\"headline\"]:has(.dut-hero-logo){grid-template-columns:60px auto !important;font-size:26px !important;line-height:34px !important}\n.dut-settings-logo{width:19px;height:19px;object-fit:contain}\n";
44
+ /** Install the brand theme and retain it across host navigation/rerenders. */
45
+ export declare function installBranding(): () => void;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * dsh-ui-tweaks — precise cache-hit readout (browser half).
3
+ *
4
+ * Rewrites the cache-hit figure in the composer stats line under the input
5
+ * box ("缓存命中 96%" / "Cache hit 96%") to two decimal places ("96.35%").
6
+ * DSH rounds the share to an integer before display (adding decimals only to
7
+ * avoid a false 100%); the exact figure needs the raw token buckets, which
8
+ * this seat reads through the framework's per-session projection hook
9
+ * (`useProjection('tokenUsage')`) — the same durable whole-log totals the
10
+ * stock number is computed from.
11
+ *
12
+ * - Mounted in `conversation.composer.dock` (the band under the composer card
13
+ * that hosts the shipped stats line), registered only while the
14
+ * `preciseCacheHitEnabled` toggle is on — off costs nothing. The entry
15
+ * renders nothing itself: it is a live reader that patches the stock span's
16
+ * text in place, so layout, truncation and tooltip behavior stay DSH's own.
17
+ * - A MutationObserver re-applies the precise figure whenever React repaints
18
+ * the line (token updates, group churn); writes are idempotent — a rewrite
19
+ * only happens when the text actually differs — so the loop settles after
20
+ * one pass. Toggling off restores the original texts.
21
+ * @module dsh-ui-tweaks/client/cachehit
22
+ */
23
+ import type { UseProjection } from '@deepseek-ai/dsh-api-session-controller/client';
24
+ /** Client-side slice of dsh-token-meter's cumulative projection. */
25
+ interface TokenUsageProjection {
26
+ uncachedInputTokens: number;
27
+ cacheReadTokens: number;
28
+ cacheWriteTokens: number;
29
+ }
30
+ declare module '@deepseek-ai/dsh-session-projection/types' {
31
+ interface SessionProjectionMap {
32
+ tokenUsage: TokenUsageProjection | undefined;
33
+ }
34
+ }
35
+ export interface PreciseCacheHitEntryProps {
36
+ /** Framework seat (PropsRuntime): key-addressed per-session projection reader. */
37
+ useProjection: UseProjection;
38
+ }
39
+ /** Session-scoped composer-dock seat that keeps the stock cache-hit figure at two decimals. */
40
+ export declare function PreciseCacheHitEntry({ useProjection }: PreciseCacheHitEntryProps): null;
41
+ export {};
@@ -0,0 +1,103 @@
1
+ /**
2
+ * dsh-ui-tweaks — GitBar (browser half).
3
+ *
4
+ * Two compact DSH-native pills that live INSIDE the composer's tool row
5
+ * (`conversation.input.left` / `.right`), styled to match the input bar's
6
+ * resident chrome (access mode / model select):
7
+ *
8
+ * - **branch** (`conversation.input.left`, right after the access-mode
9
+ * control): current branch; opens a popup with local/remote branches and a
10
+ * new-branch field.
11
+ * - **diff** (`conversation.input.right`, just before the model select): ±line
12
+ * counts; opens a right slide-over panel with the changed-file list and
13
+ * per-file diff (changed hunks by default, whole file on toggle). The panel
14
+ * keeps its commit band at the foot, so committing still works from the diff
15
+ * view.
16
+ *
17
+ * The standalone commit pill (a third pill on its own row above the composer)
18
+ * is gone — the input area no longer carries a separate GitBar row above the
19
+ * card, which is what kept it tall.
20
+ *
21
+ * All colors ride the DSH theme tokens (`--dsw-alias-*`), so light and dark
22
+ * both work. Each pill renders nothing when the setting is off, the session
23
+ * has no cwd, or the directory is not a git repository.
24
+ * @module dsh-ui-tweaks/client/gitbar
25
+ */
26
+ import type { ISessions } from '@deepseek-ai/dsh-api-session-controller/client';
27
+ import type { SessionSnapshot } from '@deepseek-ai/dsh-api-session-controller/client';
28
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
29
+ import type { SettingsClient } from './index.tsx';
30
+ /** Locale keys the GitBar reads off the `ui-tweaks` dictionary. */
31
+ type GitBarLabelKey = 'commitMessage' | 'diffFiles' | 'branchLocal' | 'branchRemote' | 'branchNew' | 'branchNewPlaceholder' | 'branchCreate' | 'diffTitle' | 'diffOnly' | 'diffFull' | 'commitTitle' | 'commitPlaceholder' | 'commitHint' | 'commitWillCommit' | 'commitViewDiff' | 'commitEmpty' | 'commitCancel' | 'commitSubmit' | 'commitSubmitPush' | 'commitBusy' | 'dirty' | 'clean' | 'noChanges' | 'loading' | 'branchDelete' | 'branchDeleteConfirm' | 'includeFile' | 'excludeFile' | 'branchPushRemote' | 'branchRemoteDelete' | 'branchFrom' | 'branchFromHead' | 'branchGraph' | 'branchRefresh' | 'branchCancel' | 'graphTitle' | 'graphColGraph' | 'graphColCommit' | 'graphColSubject' | 'graphColAuthor' | 'graphColDate' | 'openProject' | 'terminal' | 'openExplorer' | 'openVscode' | 'openIdea' | 'openGoland' | 'openWebstorm' | 'openPycharm' | 'termConnecting' | 'termExited' | 'termUnavailable' | 'termLost';
32
+ type Translate = (key: GitBarLabelKey) => string;
33
+ /**
34
+ * Where git ops resolve their working directory: a real session id, or a
35
+ * workspace title for the hero/new-session screen (which has no materialized
36
+ * session yet — the server resolves the picked workspace's path instead).
37
+ */
38
+ export interface GitTarget {
39
+ session?: string;
40
+ ws?: string;
41
+ }
42
+ export declare const GITBAR_CSS = "\n/* DSH does not force border-box globally; normalize it for the whole GitBar\n subtree (including the body-portaled panels/modal), or widths overflow. */\n.gbar,.gbar *,.gbar-side,.gbar-side *,.gbar-modal-wrap,.gbar-modal-wrap *,.gbar-notice,.gbar-notice *{box-sizing:border-box}\n/* Anchor around each pill inside the composer tool row\n (conversation.input.left / .right): the branch pill's containing block, so\n its popup opens from the pill itself. flex:0 1 auto + min-width:0 let the\n pill compress when the row is squeezed instead of spilling over neighbours. */\n.gbar{position:relative;display:inline-flex;align-items:center;gap:6px;flex:0 1 auto;min-width:0}\n/* Pills match the input bar's resident chrome (access mode / model select):\n 28px tall, fully-rounded, transparent at rest with a soft hover fill.\n overflow:hidden clips the pill's content while it compresses. */\n.gbar-pill{\n display:inline-flex;align-items:center;gap:6px;\n height:28px;padding:0 8px;min-width:0;overflow:hidden;\n background:transparent;\n border:none;\n border-radius:24px;\n color:var(--dsw-alias-label-secondary);\n font:inherit;font-size:13px;font-weight:500;line-height:20px;\n cursor:pointer;\n transition:background .15s ease;\n white-space:nowrap;\n -webkit-user-select:none;user-select:none;\n}\n.gbar-pill:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.gbar-pill:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}\n/* Long branch names ellipsize instead of stretching the row. */\n.gbar-pill .gbar-branch{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:140px}\n/* Icons match the resident access-mode trigger exactly: 14px, full color,\n no fade, and box-centered (same vertical centre as the access icon). */\n.gbar-pill .gbar-ico{width:14px;height:14px;flex:none;opacity:1}\n.gbar-pill .gbar-caret{font-size:8px;color:var(--dsw-alias-label-tertiary);margin-left:1px}\n.gbar-pill .gbar-dot{width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-state-warn-primary);flex:none}\n.gbar-pill .gbar-add{color:var(--dsw-alias-state-success-primary);font-weight:600;font-variant-numeric:tabular-nums}\n.gbar-pill .gbar-del{color:var(--dsw-alias-state-error-primary);font-weight:600;font-variant-numeric:tabular-nums}\n.gbar-pill .gbar-meta{color:var(--dsw-alias-label-secondary)}\n.gbar-pill .gbar-hint{color:var(--dsw-alias-label-tertiary);font-weight:400}\n.gbar-pill.gbar-active{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-business-primary)}\n.gbar-pill.gbar-active .gbar-hint{color:var(--dsw-alias-state-business-primary)}\n.gbar-pill:disabled{opacity:.5;cursor:default}\n/* The composer tool row is an inline-size container (DSH sets\n container-type:inline-size on it), so these container queries track the\n row's actual width. When the stretched diff panel pushes the conversation\n column and the row tightens \u2014 the same squeeze that makes the resident\n access / model chrome collapse its labels to icons \u2014 the pills follow suit\n instead of ever overlapping their neighbours: first drop the \"\u00B7 K \u4E2A\u6587\u4EF6\"\n meta, then go icon-only (before the row gets narrow enough for the branch\n name to collide with the access control). */\n@container (max-width: 700px){\n .gbar-pill .gbar-meta{display:none}\n}\n@container (max-width: 620px){\n .gbar-pill .gbar-text{display:none}\n .gbar-pill .gbar-caret{display:none}\n}\n\n/* branch popup \u2014 the chip lives in the session HEADER now, so the menu opens\n DOWNWARD (top-anchored, small arrow pointing up). Pinned header (current\n branch + worktree state) and pinned action bar surround a freely scrolling\n branch list. */\n.gbar-pop{\n position:absolute;left:0;top:calc(100% + 8px);z-index:120;\n width:300px;\n background:var(--dsw-alias-bg-layer-1);\n border:1px solid var(--dsw-alias-border-l2);border-radius:14px;\n box-shadow:var(--dsw-shadow-lv2);\n display:flex;flex-direction:column;overflow:hidden;\n animation:gpop-down .16s cubic-bezier(.32,.72,0,1);\n}\n.gbar-pop::before{content:\"\";position:absolute;top:-5px;left:22px;width:9px;height:9px;\n background:var(--dsw-alias-bg-layer-1);border-left:1px solid var(--dsw-alias-border-l2);\n border-top:1px solid var(--dsw-alias-border-l2);transform:rotate(45deg)}\n@keyframes gpop-down{from{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:none}}\n.gbar-pop-head{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-module-platform)}\n.gbar-pop-head .gbar-bicon{width:14px;height:14px;flex:none}\n.gbar-pop-head .gbar-curname{display:flex;align-items:center;gap:7px;min-width:0;font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary)}\n.gbar-pop-head .gbar-curname .gbar-bicon{color:var(--dsw-alias-state-business-primary)}\n.gbar-pop-head .gbar-curname>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.gbar-pop-head .gbar-state{margin-left:auto;flex:none;display:flex;align-items:center;gap:6px;font-size:11px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums}\n.gbar-pop-head .gbar-dot{width:6px;height:6px;border-radius:50%;flex:none}\n.gbar-pop-head .gbar-dot.gbar-dirty{background:var(--dsw-alias-state-warn-primary)}\n.gbar-pop-head .gbar-dot.gbar-clean{background:var(--dsw-alias-state-success-primary)}\n.gbar-pop-body{max-height:min(330px,calc(100vh - 250px));overflow-y:auto;padding:3px 6px 5px;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--dsw-alias-label-tertiary) 35%,transparent) transparent}\n.gbar-pop-body::-webkit-scrollbar{width:5px}\n.gbar-pop-body::-webkit-scrollbar-track{background:transparent}\n.gbar-pop-body::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--dsw-alias-label-tertiary) 35%,transparent);border-radius:4px}\n.gbar-pop .gbar-sec{display:flex;align-items:center;gap:6px;font-size:10.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--dsw-alias-label-tertiary);padding:8px 9px 3px}\n.gbar-pop .gbar-sec .gbar-count{margin-left:auto;font-size:10px;font-weight:500;letter-spacing:0;line-height:15px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-module-platform);border-radius:999px;padding:0 7px}\n.gbar-pop .gbar-loading{display:flex;align-items:center;justify-content:center;gap:8px;padding:14px 9px;font-size:12px;color:var(--dsw-alias-label-tertiary)}\n.gbar-pop .gbar-row{\n display:flex;align-items:center;gap:8px;width:100%;\n padding:6px 8px;border:none;border-radius:8px;\n background:transparent;color:var(--dsw-alias-label-primary);\n font:inherit;font-size:12.5px;cursor:pointer;text-align:left;\n transition:background .12s ease;\n}\n.gbar-pop .gbar-row:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.gbar-pop .gbar-row.gbar-cur{color:var(--dsw-alias-state-business-primary);font-weight:600}\n.gbar-pop .gbar-row .gbar-bicon{width:13px;height:13px;flex:none;color:var(--dsw-alias-label-tertiary);opacity:.85}\n.gbar-pop .gbar-row.gbar-cur .gbar-bicon{color:var(--dsw-alias-state-business-primary);opacity:1}\n.gbar-pop .gbar-row .gbar-check{margin-left:auto;color:var(--dsw-alias-state-business-primary);font-weight:700}\n.gbar-pop .gbar-row .gbar-rm{flex:none;font-size:10px;line-height:15px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-module-platform);border-radius:999px;padding:0 7px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:90px}\n/* branch row wrapper: main switch button + delete button */\n.gbar-pop .gbar-rowwrap{display:flex;align-items:center;gap:2px;border-radius:8px;transition:background .12s ease}\n.gbar-pop .gbar-rowwrap:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.gbar-pop .gbar-rowwrap .gbar-row{background:transparent}\n.gbar-pop .gbar-del{\n flex:none;display:inline-flex;align-items:center;justify-content:center;\n width:26px;height:26px;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);\n font:inherit;font-size:10.5px;cursor:pointer;border-radius:7px;margin-right:4px;\n transition:color .12s ease,background .12s ease;\n}\n.gbar-pop .gbar-del svg{width:13px;height:13px;display:block}\n.gbar-pop .gbar-del:hover{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}\n.gbar-pop .gbar-del.gbar-arm{width:auto;padding:0 8px;color:var(--dsw-alias-state-error-primary);font-weight:600;background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}\n.gbar-pushrow{display:flex;align-items:center;gap:7px;padding:0 8px 7px}\n.gbar-pushrow .gbar-pushlabel{font-size:12px;color:var(--dsw-alias-label-secondary)}\n.gbar-pop .gbar-newrow{display:flex;gap:6px;padding:8px 6px 6px}\n.gbar-pop input{\n flex:1;min-width:0;height:32px;padding:0 11px;\n border:1px solid var(--dsw-alias-border-l2);border-radius:9px;\n background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);\n font:inherit;font-size:13px;outline:none;\n}\n.gbar-pop input:focus{border-color:var(--dsw-alias-state-business-primary)}\n.gbar-pop input::placeholder{color:var(--dsw-alias-label-tertiary)}\n.gbar-mini{\n flex:none;height:32px;padding:0 14px;border:none;border-radius:9px;\n background:var(--dsw-alias-state-business-primary);color:#fff;\n font:inherit;font-size:13px;font-weight:500;cursor:pointer;\n}\n.gbar-mini:hover{opacity:.92}\n.gbar-mini:disabled{opacity:.5;cursor:default}\n\n/* branch popup action entries (new branch / graph) \u2014 pinned below the\n scrolling list; the border-top separates it from the body. */\n.gbar-actions{display:flex;gap:6px;padding:8px;border-top:1px solid var(--dsw-alias-border-l1)}\n.gbar-act{\n flex:1;display:inline-flex;align-items:center;justify-content:center;gap:7px;\n height:34px;border:none;border-radius:10px;\n background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);\n font:inherit;font-size:12.5px;font-weight:500;cursor:pointer;\n}\n.gbar-act:hover{background:var(--dsw-alias-interactive-bg-hover-solid)}\n.gbar-act svg{width:14px;height:14px;opacity:.9;flex:none}\n/* base-branch selector (new-branch dialog) */\n.gbar-baserow{display:flex;align-items:center;gap:7px;padding:0}\n.gbar-baselabel{font-size:12px;color:var(--dsw-alias-label-secondary);flex:none}\n.gbar-base{\n flex:1;min-width:0;height:32px;padding:0 10px;\n border:1px solid var(--dsw-alias-border-l2);border-radius:9px;\n background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);\n font:inherit;font-size:12.5px;outline:none;cursor:pointer;\n}\n.gbar-base:focus{border-color:var(--dsw-alias-state-business-primary)}\n.gbar-modal input{\n width:100%;height:38px;padding:0 13px;\n border:1px solid var(--dsw-alias-border-l2);border-radius:10px;\n background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);\n font:inherit;font-size:13.5px;outline:none;\n}\n.gbar-modal input:focus{border-color:var(--dsw-alias-state-business-primary)}\n.gbar-modal input::placeholder{color:var(--dsw-alias-label-tertiary)}\n.gbar-modal .gbar-head{padding-bottom:10px;border-bottom:1px solid var(--dsw-alias-border-l1)}\n/* \"push to remote\" row becomes an inset card so it reads as one option group. */\n.gbar-modal .gbar-pushrow{padding:9px 11px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-2)}\n.gbar-modal .gbar-pushrow .gbar-pushlabel{font-size:12.5px;color:var(--dsw-alias-label-primary)}\n.gbar-x:disabled{opacity:.5;cursor:default}\n/* commit-graph dialog */\n.gbar-modal.gbar-graph-modal{width:min(760px,calc(100vw - 40px));gap:10px}\n/* Refresh sits immediately left of close, both pinned to the right edge: the\n refresh takes the auto margin (specificity .gbar-x.gbar-refresh beats the\n .gbar-x override below), close drops it so they stay adjacent. */\n.gbar-modal.gbar-graph-modal .gbar-head .gbar-x.gbar-refresh{margin-left:auto}\n.gbar-modal.gbar-graph-modal .gbar-head .gbar-x{margin-left:0}\n.gbar-modal.gbar-graph-modal .gbar-x svg{width:15px;height:15px;display:block}\n.gbar-graph-empty{padding:28px 12px;text-align:center;font-size:13px;color:var(--dsw-alias-label-tertiary)}\n.gbar-graph-table{display:flex;flex-direction:column;max-height:min(60vh,540px);overflow:auto;border:1px solid var(--dsw-alias-border-l1);border-radius:12px;background:var(--dsw-alias-bg-layer-2)}\n.gbar-graph-row{display:grid;grid-template-columns:62px 1fr 96px 90px;align-items:center;gap:8px;padding:5px 12px;border-bottom:1px solid var(--dsw-alias-border-l1);transition:background .12s ease}\n.gbar-graph-row:last-child{border-bottom:none}\n/* Zebra striping for scanability; the hover rule matches its specificity and\n comes later in the sheet, so pointing at a row still wins. */\n.gbar-graph-row:not(.gbar-graph-head):nth-child(odd){background:color-mix(in srgb,var(--dsw-alias-bg-module-platform) 35%,transparent)}\n.gbar-graph-row:not(.gbar-graph-head):hover{background:var(--dsw-alias-interactive-bg-hover)}\n.gbar-graph-head{position:sticky;top:0;background:var(--dsw-alias-bg-module-platform);font-size:10.5px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--dsw-alias-label-tertiary);z-index:1;border-bottom:1px solid var(--dsw-alias-border-l1)}\n.gbar-c-hash code{font-family:var(--dsw-font-markdown-code-font-family,\"SF Mono\",Consolas,monospace);font-size:11px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-module-platform);border-radius:6px;padding:2px 6px}\n.gbar-c-subject{min-width:0;display:flex;align-items:center;gap:8px}\n.gbar-subject{font-size:12.5px;color:var(--dsw-alias-label-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.gbar-refs{flex:none;font-size:10.5px;color:var(--dsw-alias-state-business-primary);background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);border-radius:999px;padding:1px 8px;white-space:nowrap;max-width:220px;overflow:hidden;text-overflow:ellipsis}\n.gbar-c-author{font-size:12px;color:var(--dsw-alias-label-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.gbar-c-date{font-size:11.5px;color:var(--dsw-alias-label-tertiary);text-align:right;white-space:nowrap}\n\n/* diff side panel \u2014 fixed on the right; the conversation is pushed left via\n #root { margin-right } so the panel never overlaps the message column. */\n.gbar-side{\n position:fixed;right:0;top:0;bottom:0;z-index:80;\n display:flex;flex-direction:column;overflow:hidden;\n /* bg-base instead of bg-layer-1: in dark mode layer-1 (#232324) reads gray\n next to the conversation's base (#151517); base matches it exactly, and in\n light mode both aliases are #fff so nothing changes. */\n background:var(--dsw-alias-bg-base);\n border-left:1px solid var(--dsw-alias-border-l2);\n box-shadow:var(--dsw-shadow-lv2);\n animation:gbar-in .18s cubic-bezier(.32,.72,0,1);\n}\n/* drag handle on the panel's left edge */\n.gbar-resize{\n position:absolute;left:-5px;top:0;bottom:0;width:10px;cursor:col-resize;\n touch-action:none;\n}\n.gbar-resize::after{\n content:\"\";position:absolute;left:4px;top:0;bottom:0;width:2px;\n background:transparent;transition:background .15s ease;\n}\n.gbar-side:hover .gbar-resize::after{background:var(--dsw-alias-border-l2)}\n.gbar-resize:active::after{background:var(--dsw-alias-state-business-primary)}\n@keyframes gbar-in{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}\n.gbar-side-head{display:flex;align-items:center;gap:10px;padding:12px 14px;border-bottom:1px solid var(--dsw-alias-border-l1)}\n.gbar-side-head .gbar-title{font-size:13.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.gbar-side-head .gbar-sub{font-size:12px;color:var(--dsw-alias-label-tertiary);flex:none;font-variant-numeric:tabular-nums}\n.gbar-side-head .gbar-sub .gbar-a{color:var(--dsw-alias-state-success-primary)}\n.gbar-side-head .gbar-sub .gbar-d{color:var(--dsw-alias-state-error-primary)}\n.gbar-side-head .gbar-spacer{flex:1}\n.gbar-seg{display:inline-flex;padding:3px;gap:2px;border-radius:10px;background:var(--dsw-alias-bg-module-platform);flex:none}\n.gbar-seg button{border:none;border-radius:8px;padding:4px 10px;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;cursor:pointer}\n.gbar-seg button.gbar-on{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);box-shadow:var(--dsw-shadow-lv1)}\n.gbar-side-x{border:none;background:transparent;color:var(--dsw-alias-label-tertiary);font-size:15px;cursor:pointer;width:28px;height:28px;border-radius:8px;flex:none}\n.gbar-side-x:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.gbar-side-body{flex:1;overflow:hidden;display:flex;flex-direction:column;min-height:0}\n/* The three stacked sections (files / diff / commit) are sized by drag: the two\n neighbours carry an explicit inline height and the diff pane absorbs whatever\n is left, so a drag can never overflow the panel. The dividing hairlines are\n painted by the splitters, not by the sections' own borders. */\n.gbar-files{flex:none;overflow-y:auto;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--dsw-alias-label-tertiary) 35%,transparent) transparent}\n.gbar-files::-webkit-scrollbar{width:5px}\n.gbar-files::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--dsw-alias-label-tertiary) 35%,transparent);border-radius:4px}\n/* horizontal drag splitters between the sections */\n.gbar-vsplit{\n flex:none;position:relative;height:7px;\n cursor:row-resize;touch-action:none;-webkit-user-select:none;user-select:none;\n}\n.gbar-vsplit::after{\n content:\"\";position:absolute;left:0;right:0;top:3px;height:1px;\n background:var(--dsw-alias-border-l1);transition:background .15s ease,height .15s ease;\n}\n.gbar-vsplit:hover::after{background:var(--dsw-alias-border-l2);height:2px}\n.gbar-vsplit.gbar-dragging::after{background:var(--dsw-alias-state-business-primary);height:2px}\n.gbar-file{\n display:flex;align-items:center;gap:6px;width:100%;\n padding:3px 14px;background:transparent;\n}\n.gbar-file .gbar-file-main{\n flex:1;min-width:0;display:flex;align-items:center;gap:9px;\n padding:5px 4px;border:none;border-radius:7px;background:transparent;\n color:var(--dsw-alias-label-primary);font:inherit;font-size:12.5px;cursor:pointer;text-align:left;\n}\n.gbar-file .gbar-file-main:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.gbar-file.gbar-on .gbar-file-main{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 9%,transparent);box-shadow:inset 2px 0 0 var(--dsw-alias-state-business-primary)}\n.gbar-file.gbar-excl{opacity:.55}\n.gbar-chk{\n flex:none;width:16px;height:16px;padding:0;\n border:1px solid var(--dsw-alias-border-l2);border-radius:5px;\n background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-state-business-primary);\n font-size:11px;line-height:1;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;\n}\n.gbar-chk:hover{border-color:var(--dsw-alias-state-business-primary)}\n.gbar-chk.gbar-off{color:transparent}\n.gbar-file .gbar-st{\n flex:none;min-width:17px;height:17px;padding:0 4px;\n display:inline-flex;align-items:center;justify-content:center;\n font-weight:700;font-size:10.5px;border-radius:5px;\n}\n.gbar-file .gbar-st.gbar-m{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 13%,transparent)}\n.gbar-file .gbar-st.gbar-a{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 13%,transparent)}\n.gbar-file .gbar-st.gbar-d{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent)}\n.gbar-file .gbar-st.gbar-u{color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-module-platform)}\n.gbar-file .gbar-path{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--dsw-font-markdown-code-font-family,\"SF Mono\",Consolas,monospace);font-size:12px}\n/* Directory part dims, filename stays bright \u2014 GitHub-style path rendering. */\n.gbar-file .gbar-path .gbar-dir{color:var(--dsw-alias-label-tertiary)}\n.gbar-file .gbar-nums{flex:none;font-variant-numeric:tabular-nums;font-size:11.5px}\n.gbar-file .gbar-nums .gbar-a{color:var(--dsw-alias-state-success-primary)}\n.gbar-file .gbar-nums .gbar-d{color:var(--dsw-alias-state-error-primary)}\n.gbar-diff{\n flex:1;min-height:0;overflow:auto;\n font-family:var(--dsw-font-markdown-code-font-family,\"SF Mono\",Consolas,monospace);font-size:12px;line-height:1.7;padding:8px 0;\n scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--dsw-alias-label-tertiary) 35%,transparent) transparent;\n}\n.gbar-diff::-webkit-scrollbar{width:5px;height:5px}\n.gbar-diff::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--dsw-alias-label-tertiary) 35%,transparent);border-radius:4px}\n/* Hunk header: a centered pill strip (GitHub-style), gutter numbers hidden but\n still occupying space so the code column stays aligned. */\n.gbar-diff .gbar-line.gbar-hunk{background:transparent;padding-top:7px;padding-bottom:3px}\n.gbar-diff .gbar-line.gbar-hunk .gbar-ln{visibility:hidden}\n.gbar-diff .gbar-line.gbar-hunk .gbar-code{color:var(--dsw-alias-state-business-primary)}\n.gbar-diff .gbar-line{display:flex;align-items:center;min-height:21px;padding:0 14px 0 0;white-space:pre}\n.gbar-diff .gbar-line .gbar-ln{flex:none;width:34px;text-align:right;padding-right:8px;color:var(--dsw-alias-label-tertiary);font-size:11px;-webkit-user-select:none;user-select:none}\n.gbar-diff .gbar-line .gbar-ln+.gbar-ln{border-right:1px solid var(--dsw-alias-border-l1);margin-right:10px}\n.gbar-diff .gbar-line .gbar-code{flex:1;white-space:pre;color:var(--dsw-alias-label-primary);padding-right:14px}\n.gbar-diff .gbar-line.gbar-add{background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 13%,transparent);box-shadow:inset 2px 0 0 color-mix(in srgb,var(--dsw-alias-state-success-primary) 55%,transparent)}\n.gbar-diff .gbar-line.gbar-add .gbar-ln{color:var(--dsw-alias-state-success-primary)}\n.gbar-diff .gbar-line.gbar-del{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);box-shadow:inset 2px 0 0 color-mix(in srgb,var(--dsw-alias-state-error-primary) 50%,transparent)}\n.gbar-diff .gbar-line.gbar-del .gbar-ln{color:var(--dsw-alias-state-error-primary)}\n.gbar-diff .gbar-line.gbar-ctx .gbar-code{color:var(--dsw-alias-label-secondary)}\n.gbar-diff .gbar-empty{display:flex;align-items:center;justify-content:center;min-height:140px;font-size:12px;color:var(--dsw-alias-label-tertiary)}\n/* The hairline above the foot is drawn by the commit splitter that precedes it. */\n.gbar-side-foot{flex:none;padding:8px 14px;font-size:11.5px;color:var(--dsw-alias-label-tertiary);display:flex;gap:8px;align-items:center}\n.gbar-side-foot .gbar-dot{width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-state-warn-primary);flex:none}\n/* commit row inside the diff panel \u2014 height is drag-adjustable, so the message\n field stretches to fill whatever the user gives this section. */\n.gbar-side-commit{flex:none;min-height:0;overflow:hidden;display:flex;flex-direction:column;gap:7px;padding:9px 12px;border-top:1px solid var(--dsw-alias-border-l1)}\n.gbar-side-commit .gbar-crow{flex:1;min-height:0;display:flex;align-items:stretch;gap:6px}\n.gbar-side-commit textarea{\n flex:1;min-width:0;min-height:30px;padding:6px 10px;resize:none;\n border:1px solid var(--dsw-alias-border-l2);border-radius:8px;\n background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);\n font:inherit;font-size:12px;line-height:1.6;outline:none;overflow-y:auto;\n}\n.gbar-side-commit textarea:focus{border-color:var(--dsw-alias-state-business-primary)}\n.gbar-side-commit textarea::placeholder{color:var(--dsw-alias-label-tertiary)}\n.gbar-side-commit .gbar-actions{flex:none;display:flex;align-items:center;justify-content:flex-end;gap:6px}\n.gbar-side-commit .gbar-btn{height:28px;padding:0 12px;font-size:12px;border-radius:8px}\n\n/* commit modal */\n.gbar-modal-wrap{\n position:fixed;inset:0;z-index:120;\n display:flex;align-items:center;justify-content:center;\n background:rgba(0,0,0,.35);\n}\n.gbar-modal{\n width:min(520px,calc(100vw - 40px));max-height:calc(100vh - 48px);overflow:hidden auto;\n background:var(--dsw-alias-bg-layer-1);\n border:1px solid var(--dsw-alias-border-l2);border-radius:16px;\n box-shadow:var(--dsw-shadow-lv2);\n padding:18px;\n display:flex;flex-direction:column;gap:12px;\n animation:gbar-in .18s cubic-bezier(.32,.72,0,1);\n}\n.gbar-modal .gbar-head{display:flex;align-items:center;gap:10px}\n.gbar-modal .gbar-head .gbar-title{font-size:15px;font-weight:600}\n.gbar-modal .gbar-head .gbar-branch{font-size:12px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-module-platform);border-radius:999px;padding:3px 10px}\n.gbar-modal .gbar-head .gbar-x{margin-left:auto;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);font-size:16px;cursor:pointer;width:28px;height:28px;border-radius:8px}\n.gbar-modal .gbar-head .gbar-x:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.gbar-modal textarea{\n width:100%;min-height:64px;height:auto;max-height:220px;resize:none;\n overflow-y:auto;scrollbar-width:none;\n border:1px solid var(--dsw-alias-border-l2);border-radius:12px;\n background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);\n font:inherit;font-size:14px;line-height:1.6;padding:10px 14px;outline:none;\n}\n.gbar-modal textarea::-webkit-scrollbar{display:none}\n.gbar-modal textarea:focus{border-color:var(--dsw-alias-state-business-primary)}\n.gbar-modal textarea::placeholder{color:var(--dsw-alias-label-tertiary)}\n.gbar-modal .gbar-hint{font-size:12px;color:var(--dsw-alias-label-tertiary);line-height:1.6}\n.gbar-modal .gbar-files-head{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--dsw-alias-label-tertiary);margin-top:2px}\n.gbar-modal .gbar-files-head .gbar-hint{font-size:11px;font-weight:400;text-transform:none;letter-spacing:0}\n.gbar-modal .gbar-files{\n display:flex;flex-direction:column;gap:1px;max-height:132px;overflow-y:auto;\n border:1px solid var(--dsw-alias-border-l1);border-radius:10px;\n background:var(--dsw-alias-bg-layer-2);padding:4px;\n}\n.gbar-modal .gbar-file{\n display:flex;align-items:center;gap:6px;width:100%;\n padding:2px 6px;border-radius:7px;background:transparent;\n}\n.gbar-modal .gbar-file .gbar-file-main{\n padding:4px 4px;font-size:12px;border-radius:6px;\n}\n.gbar-modal .gbar-file .gbar-file-main:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.gbar-modal .gbar-file.gbar-on .gbar-file-main{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 10%,transparent)}\n.gbar-modal .gbar-file .gbar-path{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--dsw-font-markdown-code-font-family,\"SF Mono\",Consolas,monospace);font-size:11.5px}\n.gbar-modal .gbar-file .gbar-goto{flex:none;color:var(--dsw-alias-label-tertiary);font-size:10px}\n.gbar-modal .gbar-file.gbar-on .gbar-goto{color:var(--dsw-alias-state-business-primary)}\n.gbar-modal .gbar-foot{display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:2px;flex-wrap:wrap}\n.gbar-btn{\n height:34px;padding:0 16px;border:none;border-radius:10px;\n font:inherit;font-size:13.5px;cursor:pointer;\n display:inline-flex;align-items:center;gap:6px;\n}\n.gbar-btn.gbar-ghost{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary)}\n.gbar-btn.gbar-ghost:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}\n.gbar-btn.gbar-soft{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-state-business-primary)}\n.gbar-btn.gbar-soft:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 18%,transparent)}\n.gbar-btn.gbar-primary{background:var(--dsw-alias-state-business-primary);color:#fff;font-weight:500}\n.gbar-btn.gbar-primary:hover:not(:disabled){opacity:.92}\n/* Disabled buttons (e.g. while a task is running) must NOT light up on hover \u2014\n they keep their muted look, though the tooltip hint still shows. */\n.gbar-btn:disabled{opacity:.5;cursor:default}\n.gbar-btn:disabled:hover{opacity:.5}\n.gbar-notice{\n position:fixed;z-index:150;left:50%;bottom:28px;transform:translateX(-50%);\n max-width:min(520px,90vw);padding:9px 16px;border-radius:10px;font-size:12.5px;line-height:1.5;\n box-shadow:var(--dsw-shadow-lv2);animation:gbar-in .18s cubic-bezier(.32,.72,0,1);\n}\n.gbar-notice.gbar-ok{background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 16%,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-state-success-primary)}\n.gbar-notice.gbar-err{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-state-error-primary)}\n.gbar-spin{width:12px;height:12px;border-radius:50%;border:2px solid color-mix(in srgb,var(--dsw-alias-label-tertiary) 30%,transparent);border-top-color:currentColor;animation:gbar-spin .7s linear infinite}\n@keyframes gbar-spin{to{transform:rotate(360deg)}}\n\n/* branch capsule \u2014 the only interactive half of the header seat: 22px tall\n like the resident agent-preset badge (same 12px type), fully-rounded,\n quiet fill on hover, active tint while the popup is open. */\n.gbar-chip{position:relative;display:inline-flex;align-items:center;gap:4px;height:22px;padding:0 9px;\n border:none;border-radius:16px;background:transparent;color:var(--dsw-alias-label-secondary);\n font:inherit;font-size:12px;font-weight:400;line-height:22px;cursor:pointer;white-space:nowrap;\n -webkit-user-select:none;user-select:none;transition:background .15s ease}\n.gbar-chip:hover,.gbar-chip:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}\n.gbar-chip.gbar-open{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,var(--dsw-alias-bg-module-platform));color:var(--dsw-alias-state-business-primary)}\n.gbar-chip svg{width:14px;height:14px;flex:none;opacity:.9}\n.gbar-chip .gbar-bname{max-width:110px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n/* folder label \u2014 plain context beside the capsule: NO background (not a\n capsule), not clickable and no hover, so only the branch carries the pill.\n Same 22px / 12px type as the agent-preset badge beside it, and like that\n label the folder name stays selectable so it can be copied with the mouse;\n cursor:auto lets the browser show the text caret over the selectable name,\n exactly like that label. */\n.gbar-fchip{display:inline-flex;align-items:center;gap:4px;height:22px;padding:0 2px;\n color:var(--dsw-alias-label-secondary);\n font:inherit;font-size:12px;font-weight:400;line-height:22px;white-space:nowrap;\n -webkit-user-select:text;user-select:text;cursor:auto}\n.gbar-fchip svg{width:14px;height:14px;flex:none;opacity:.9}\n.gbar-fchip .gbar-folder{max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n/* wraps the interactive branch capsule so its popup anchors to the capsule,\n not to the whole folder + branch row */\n.gbar-bwrap{position:relative;display:inline-flex;align-items:center}\n\n/* header utilities row: \u6253\u5F00\u9879\u76EE / \u7EC8\u7AEF / \u5DEE\u5F02 */\n.gbar-hicons{margin-left:auto;display:inline-flex;align-items:center;gap:2px;position:relative}\n/* The three header utility icons are injected into the title row's utilities\n slot (beside \"Session log\"), but they belong in the view-tabs row (\u5BF9\u8BDD /\n \u8F68\u8FF9) right below it. The session header is their containing block: anchor\n them to the right edge, vertically centred on the 16px tab text line that\n starts under the 32px title row (12px header top padding + 32px title row\n + 4px tab margin). The 24px button starts exactly at the title row's\n bottom edge so its hover surface never touches \"Session log\" above. The\n :has() guard keeps the in-flow position for the rare header without a\n tablist, and z-index keeps them above the tabs' own stacking context. */\nheader:has([role=\"tablist\"]) .gbar-hicons{\n position:absolute;\n top:calc(12px + 32px + 4px + (16px - 24px)/2);\n right:28px;\n z-index:2;\n}\n.gbar-hicon{position:relative;width:32px;height:24px;display:inline-flex;align-items:center;justify-content:center;\n border:none;background:transparent;border-radius:8px;color:var(--dsw-alias-label-secondary);cursor:pointer;\n transition:background .14s ease,color .14s ease}\n.gbar-hicon:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.gbar-hicon.gbar-on{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);color:var(--dsw-alias-state-business-primary)}\n.gbar-hicon svg{width:16px;height:16px}\n/* uncommitted-changes dot on the diff icon \u2014 warn-primary, the same color\n the branch chip / diff footer use for the dirty state */\n.gbar-hicon-dot{position:absolute;top:2.5px;right:2.5px;width:6px;height:6px;border-radius:50%;\n background:var(--dsw-alias-state-warn-primary);pointer-events:none}\n\n/* \u300C\u6253\u5F00\u9879\u76EE\u300Dmenu \u2014 a flat dropdown opening leftward from the icon group:\n right edge sits 20px inside the window (the group anchors 28px from the\n edge, so right:-8px), no bubble tail, compact rows, width fits content */\n.gbar-openmenu{position:absolute;top:calc(100% + 6px);right:-8px;min-width:150px;max-width:260px;width:max-content;z-index:130;\n background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:10px;\n box-shadow:var(--dsw-shadow-lv2);padding:4px;text-align:left;animation:gpop-down .16s cubic-bezier(.32,.72,0,1)}\n.gbar-omrow{display:flex;align-items:center;gap:9px;width:100%;padding:5px 8px;border:none;border-radius:7px;\n background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12.5px;line-height:1.2;cursor:pointer;text-align:left;\n white-space:nowrap}\n.gbar-omrow:hover{background:var(--dsw-alias-interactive-bg-hover)}\n/* brand app icons (official full-color SVGs) \u2014 fixed slot, sized by CSS */\n.gbar-omrow .gbar-aicon{width:15px;height:15px;flex:none;display:inline-flex}\n.gbar-aicon svg{width:100%;height:100%;display:block}\n\n/* terminal panel body \u2014 follows the app theme surface (tokens live on body,\n and the panel portal renders inside body, so the var resolves); the xterm\n viewport is transparent, so this is also the terminal's own backdrop */\n.gbar-term{flex:1;min-height:0;background:var(--dsw-alias-bg-base,#16161b);color:var(--dsw-alias-label-primary,#d6d6dc);cursor:text;\n font-family:var(--dsw-font-markdown-code-font-family,\"SF Mono\",Consolas,monospace);font-size:12px;line-height:1.75;\n padding:10px 14px;overflow:auto;scrollbar-width:thin}\n.gbar-term:focus-visible{outline:none}\n.gbar-term .gbar-ps1{color:#7d94ff}\n.gbar-term .gbar-tcmd{color:#ffffff}\n.gbar-term .gbar-tout{white-space:pre-wrap;word-break:break-all;opacity:.88}\n.gbar-term .gbar-tdim{opacity:.45}\n.gbar-term .gbar-terr{color:#ef6b70}\n.gbar-term .gbar-tin{display:flex;align-items:baseline}\n.gbar-term .gbar-tin input{flex:1;min-width:0;background:transparent;border:none;outline:none;color:#ffffff;\n font:inherit;font-size:12px;line-height:1.75;caret-color:#7d94ff;padding:0}\n\n/* xterm host variant \u2014 the emulator fills the body and sizes itself via the\n fit addon, so the container clips instead of scrolling. */\n.gbar-xterm{padding:4px 6px;overflow:hidden;cursor:normal}\n.gbar-xterm .xterm{height:100%}\n.gbar-xterm .xterm .xterm-viewport{background:transparent !important}\n\n/* fatal terminal error banner (pty unavailable / socket refused) */\n.gbar-term-error{position:absolute;left:12px;right:12px;bottom:12px;z-index:6;display:flex;align-items:center;gap:10px;\n padding:9px 12px;border-radius:10px;border:1px solid color-mix(in srgb,#ef6b70 45%,transparent);\n background:var(--dsw-alias-bg-base,#16161b);box-shadow:0 8px 24px rgba(0,0,0,.25)}\n.gbar-term-error-text{flex:1;min-width:0;font-size:12px;color:var(--dsw-alias-label-primary);\n overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.gbar-term-error button{border:1px solid var(--dsw-alias-border-l1);background:transparent;border-radius:7px;\n color:var(--dsw-alias-label-secondary);width:26px;height:26px;cursor:pointer;flex:none;font-size:13px}\n.gbar-term-error button:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n\n/* half-screen toggle button in side-panel heads */\n.gbar-side-half{border:1px solid var(--dsw-alias-border-l1);background:transparent;color:var(--dsw-alias-label-tertiary);\n width:28px;height:28px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;\n cursor:pointer;flex:none;transition:background .15s ease,color .15s ease,border-color .15s ease}\n.gbar-side-half:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.gbar-side-half.gbar-on{background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent);\n color:var(--dsw-alias-state-business-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary) 40%,transparent)}\n.gbar-side-half svg{width:15px;height:15px;display:block}\n\n/* hero (new-session) floating chip wrapper */\n.gbar-hero{position:fixed;z-index:110;transform:translateY(-50%);display:inline-flex;align-items:center;gap:6px}\n@media (prefers-reduced-motion:reduce){.gbar-side,.gbar-modal,.gbar-notice,.gbar-pop,.gbar-openmenu{animation:none}}\n";
43
+ /** Install the GitBar stylesheet once (idempotent); returns the disposer. */
44
+ export declare function installGitBarStyles(): () => void;
45
+ /**
46
+ * Fetch a target's status into the shared cache WITHOUT rendering anything.
47
+ *
48
+ * The session-header chips mount only after the conversation projection
49
+ * finishes loading — seconds on large inactive sessions — so their own fetch
50
+ * would start just as late. This warmup runs from the input dock, which mounts
51
+ * immediately on session switch: by the time the header chip appears it reads
52
+ * a warm cache and paints folder+branch instantly.
53
+ */
54
+ export declare function warmGitStatus(target: GitTarget): void;
55
+ /** Input-dock seat for {@link warmGitStatus}: mounts immediately on session
56
+ * switch (long before the session header does) and kicks off the prefetch. */
57
+ export declare function GitWarmup({ sessionId }: {
58
+ sessionId: SessionId;
59
+ }): null;
60
+ export interface BranchChipProps {
61
+ /** Framework session kit: the definite current session id. */
62
+ sessionId: SessionId;
63
+ /** Injected: the client sessions service (list feed carrying each row's cwd). */
64
+ sessionsService: ISessions;
65
+ /** Injected: the ui-tweaks settings store (reads `gitBarEnabled`). */
66
+ controller: SettingsClient;
67
+ /** Locale-bound translator for the GitBar labels. */
68
+ t: Translate;
69
+ }
70
+ export declare function BranchChipEntry({ sessionId, sessionsService, controller, t }: BranchChipProps): import("react").JSX.Element | null;
71
+ export interface DiffPanelProps {
72
+ /** Framework session kit: the definite current session id. */
73
+ sessionId: SessionId;
74
+ /** Framework session kit: live conversation snapshot selector. */
75
+ useSession: <T>(selector: (snapshot: SessionSnapshot) => T) => T;
76
+ /** Injected: the ui-tweaks settings store (reads `gitBarEnabled`). */
77
+ controller: SettingsClient;
78
+ /** Locale-bound translator for the GitBar labels. */
79
+ t: Translate;
80
+ /** Parent closes the panel (icon toggles; outside clicks route here too). */
81
+ onClose: () => void;
82
+ }
83
+ export declare function DiffPanel({ sessionId, useSession, controller, t, onClose }: DiffPanelProps): import("react").ReactPortal | null;
84
+ export declare function TerminalPanel({ sessionId, controller, t, onClose }: {
85
+ sessionId: SessionId;
86
+ controller: SettingsClient;
87
+ t: Translate;
88
+ onClose: () => void;
89
+ }): import("react").ReactPortal | null;
90
+ export interface HeaderUtilitiesProps {
91
+ sessionId: SessionId;
92
+ useSession: <T>(selector: (snapshot: SessionSnapshot) => T) => T;
93
+ controller: SettingsClient;
94
+ t: Translate;
95
+ }
96
+ export declare function HeaderUtilities({ sessionId, useSession, controller, t }: HeaderUtilitiesProps): import("react").JSX.Element | null;
97
+ /**
98
+ * Mount the hero floating chip: watch for the workspace picker appearing
99
+ * (hero mounts/unmounts as sessions open and close), keep a fixed-position
100
+ * React root anchored just left of it, and re-render on settings changes.
101
+ */
102
+ export declare function installHeroChip(controller: SettingsClient, t: Translate): () => void;
103
+ export {};