@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,257 @@
1
+ /**
2
+ * Shared "Side card" preference vocabulary (types + constants), consumed by
3
+ * BOTH halves: the host registers the schemastery schema over these values
4
+ * (config.ts) and the client reads/writes them through the settings RPC
5
+ * (client/prefs.ts, client/SideCardSection.tsx). Kept free of schemastery so
6
+ * the browser bundle never pulls the schema runtime in.
7
+ */
8
+ /** The user-settings namespace holding the side card preferences. */
9
+ export declare const SIDEBAR_PREFS_NS = "dsh-better-sidebar";
10
+ /** User-facing side card preferences (new-conversation defaults). */
11
+ export interface SidebarPrefs {
12
+ /** Whether a brand-new conversation opens the side card by default. */
13
+ openByDefault: boolean;
14
+ /** Default panel width as a percent of the window width (20–60). */
15
+ defaultWidthPercent: number;
16
+ /**
17
+ * Whether the sidebar auto-activates (opens the panel) and expands the
18
+ * Subagent page when the current conversation spawns a new subagent.
19
+ */
20
+ autoOpenSubagent: boolean;
21
+ /**
22
+ * Whether the sidebar auto-activates (opens the panel) and expands the
23
+ * Jobs page when a NEW background job appears for the current
24
+ * conversation (any new job id, not just the first one).
25
+ */
26
+ autoOpenJobs: boolean;
27
+ /**
28
+ * Whether the model-facing agent terminal tools (terminal_create / list /
29
+ * send / read / wait_for / resize / signal / close) are injected into the
30
+ * model's toolset. Off by default: the feature stays dormant until the
31
+ * user explicitly enables it in the side card settings.
32
+ */
33
+ agentTerminalTools: boolean;
34
+ /**
35
+ * Whether the model-facing `sidebar_open` tool is injected into the
36
+ * model's toolset — one tool that lets the model actively open a local
37
+ * file, a local folder (as a tree rooted there), or an HTTP(S) page in
38
+ * the calling session's sidebar. Off by default: the feature stays
39
+ * dormant until the user explicitly enables it in the side card settings.
40
+ */
41
+ agentOpenTools: boolean;
42
+ /**
43
+ * Custom terminal font-family stack (a CSS font-family value, e.g.
44
+ * `'JetBrains Mono', monospace`). Empty string follows the app's theme
45
+ * monospace font (`--ds-font-family-code`). Applied live to every
46
+ * terminal tab; configured under the terminal card's secondary settings.
47
+ */
48
+ terminalFontFamily: string;
49
+ /**
50
+ * Custom terminal font size in px (9–32). Applied live to every terminal
51
+ * tab; configured under the terminal card's secondary settings.
52
+ */
53
+ terminalFontSize: number;
54
+ /**
55
+ * Whether expanding the bottom panel for the FIRST time in a session tries
56
+ * to open a fresh terminal tab there (the terminal quota/type still gates
57
+ * the attempt). On by default; the switch lives under the terminal tab's
58
+ * row in the Side card settings.
59
+ */
60
+ bottomPanelAutoTerminal: boolean;
61
+ /**
62
+ * Whether chat-side file opens (tool-row path links, the produced-files
63
+ * row, prose file mentions — every path that funnels through the client
64
+ * runtime's `ctx.workspaces.openPath`) open in the sidebar editor instead
65
+ * of the Host OS's default application. On by default; the editor tab's
66
+ * own enable switch gates it too (both must be on for the takeover).
67
+ */
68
+ interceptOpenPath: boolean;
69
+ /**
70
+ * Whether the editor tab runs in merged mode: a path input replaces the
71
+ * plain header and a toggleable file-tree panel (with a global name
72
+ * search) docks at the tab's right edge. On by default; also makes brand
73
+ * new sessions seed an empty editor tab (tree panel open) instead of the
74
+ * explorer tab. The switch lives under the editor card's gear in the
75
+ * Side card settings; off restores the pre-merge editor exactly.
76
+ */
77
+ editorExplorer: boolean;
78
+ /**
79
+ * Whether the sidebar's filesystem routes enforce the workspace fence:
80
+ * every client-supplied path must resolve (through symlinks) inside the
81
+ * session workspace, else the route answers 403 "outside workspace". On
82
+ * by default; turning it OFF lets the file tree / editor read+write /
83
+ * media / HTML preview / upload routes reach ANY host path (e.g. the
84
+ * global ~/.chatcode-cli/AGENTS.md or a linked worktree outside the session cwd)
85
+ * — the trade-off being that any same-origin script (including
86
+ * third-party consumer plugins) can read/write outside the workspace
87
+ * through those routes while it is off. The switch lives under the files
88
+ * tab's gear in the Side card settings; the fence error surfaces offer a
89
+ * one-click global off + retry.
90
+ */
91
+ workspaceFence: boolean;
92
+ /**
93
+ * The shell the UI and agent terminals spawn (absolute path or bare
94
+ * executable name). Empty (default) keeps the legacy resolution order:
95
+ * `cordis.patch.yml` `config.shell`, then `$SHELL` / login shell /
96
+ * `powershell.exe` on Windows. Set it from the terminal card's gear in
97
+ * the Side card settings (or the yaml) to pin a specific shell — takes
98
+ * effect for terminals opened afterwards.
99
+ */
100
+ terminalShell: string;
101
+ /**
102
+ * Explicit arguments for `terminalShell`, space-separated (empty keeps
103
+ * the platform defaults; when set, they fully replace them — same
104
+ * contract as the yaml `shellArgs`).
105
+ */
106
+ terminalShellArgs: string;
107
+ /**
108
+ * Title-bar / shell compatibility scheme (the "位置兼容模式" setting):
109
+ * - `auto` (default): CONSERVATIVE — only the standard Window Controls
110
+ * Overlay API (present in frameless Chromium shells that draw the
111
+ * native caption buttons over web content) contributes real geometry;
112
+ * without it nothing is modified, so plain-browser (web) behavior is
113
+ * untouched.
114
+ * - `web`: EXPLICIT "ChatCode CLI Web" — never adapt, not even WCO
115
+ * geometry (the user declares they run the plain web UI).
116
+ * - `preset`: apply the built-in shell preset named by
117
+ * `titleBarPresetId` (data-driven, opt-in — see shell-presets.ts).
118
+ * - `custom`: apply the free-form `customCss` (and the legacy
119
+ * `titleBarStripPx` strip).
120
+ */
121
+ titleBarScheme: TitleBarScheme;
122
+ /**
123
+ * The built-in shell preset id applied while `titleBarScheme` is
124
+ * `preset` ('' = no preset — nothing extra is applied).
125
+ */
126
+ titleBarPresetId: string;
127
+ /**
128
+ * Free-form CSS injected into the page (last in the cascade, so it can
129
+ * override the plugin's styles; use `!important` to override JS-written
130
+ * inline CSS variables). Applied while `titleBarScheme` is `custom`.
131
+ */
132
+ customCss: string;
133
+ /**
134
+ * LEGACY (kept for read-migration and downgrade mirroring only): position
135
+ * compatibility mode flag. The UI writes `titleBarScheme` instead; a
136
+ * stored `true` without a scheme migrates to the `custom` scheme (with
137
+ * `titleBarStripPx` preserved).
138
+ */
139
+ titleBarCompat: boolean;
140
+ /**
141
+ * LEGACY (kept for read-migration and downgrade mirroring only): the
142
+ * reserved top strip height in px used by the `custom` scheme (0–120,
143
+ * default 40). Drives the `--dsh-title-bar-strip` CSS variable: the
144
+ * toggle cluster drops `strip + 3px` and the right panel's content
145
+ * starts `strip` px below its top edge.
146
+ */
147
+ titleBarStripPx: number;
148
+ /**
149
+ * Whether the HTML previewer drops its sandboxed iframe. Sandbox ON (the
150
+ * default) renders previewed HTML in an opaque-origin iframe that cannot
151
+ * touch the GUI; turning it OFF runs the previewed page with the GUI's
152
+ * own origin — full read/write access to session files and internal
153
+ * APIs. Only for trusted local content; the setting copy warns.
154
+ */
155
+ htmlViewerNoSandbox: boolean;
156
+ /**
157
+ * Whether a newly opened HTML preview starts UNSANDBOXED (the per-surface
158
+ * temporary unlock pre-applied). Off by default: previews open sandboxed
159
+ * and the status row offers the one-tap unlock; when on, previews open
160
+ * in the red unsandboxed state and the status row offers a one-tap
161
+ * restore for the current file.
162
+ */
163
+ htmlViewerDefaultUnsafe: boolean;
164
+ /**
165
+ * Whether the browser tab drops its sandboxed iframe. Sandbox ON (the
166
+ * default) keeps browsed sites in an opaque origin with no GUI access;
167
+ * turning it OFF runs any visited site with the GUI's own origin — it
168
+ * can read session data and act as the logged-in GUI. Only for trusted
169
+ * sites; the setting copy warns.
170
+ */
171
+ browserNoSandbox: boolean;
172
+ /**
173
+ * MASTER switch: whether clicking an EXTERNAL link in the GUI (chat
174
+ * messages, tool rows, prose mentions) is taken over into the sidebar at
175
+ * all. On by default; the per-protocol granularity lives in
176
+ * `browserInterceptHttp` / `browserInterceptHttps` (the protocol flag
177
+ * must also be on), and the target tab's own enable switch gates it too.
178
+ * Ctrl/Cmd+click always bypasses the takeover. Kept as the master so old
179
+ * documents keep their meaning with no migration (an explicit `false`
180
+ * stays "never take over").
181
+ */
182
+ browserInterceptLinks: boolean;
183
+ /**
184
+ * Whether clicking an http EXTERNAL link in the GUI opens the sidebar
185
+ * (the built-in browser tab, or a plugin tab that declares `urlTarget`)
186
+ * instead of a new browser tab. On by default; gated on the
187
+ * `browserInterceptLinks` master and the target tab's own enable switch.
188
+ */
189
+ browserInterceptHttp: boolean;
190
+ /**
191
+ * Whether clicking an https EXTERNAL link in the GUI opens the sidebar
192
+ * instead of a new browser tab. OFF by default — most https sites (e.g.
193
+ * GitHub) refuse iframe embedding, so the system browser is the smoother
194
+ * default; gated on the `browserInterceptLinks` master and the target
195
+ * tab's own enable switch.
196
+ */
197
+ browserInterceptHttps: boolean;
198
+ /**
199
+ * Comma-separated allowlist of local (loopback) authorities the browser
200
+ * tab may navigate to — `localhost`, `127.0.0.1`, `127.0.0.1:5174`, or
201
+ * host:port pairs. Empty by default: loopback addresses stay blocked so a
202
+ * browsed page cannot probe local services. Each entry is either a bare
203
+ * hostname (all ports) or host:port; the GUI's own origin is always
204
+ * allowed regardless. The iframe sandbox still renders allowed local
205
+ * pages in an opaque origin, exactly like any other site.
206
+ */
207
+ browserAllowedLoopback: string;
208
+ /**
209
+ * Per-tab enable switches, keyed by tab descriptor id (`'explorer'`,
210
+ * `'my-plugin:db'`). An ABSENT key means enabled — only an explicit
211
+ * `false` disables a tab type (hidden from the + menu, `openTab` refuses,
212
+ * and derived flows like subagent auto-open / agent-terminal tabs stop).
213
+ * Already-open tabs of a disabled type keep rendering (closing one
214
+ * prevents reopening), matching the "existing conversations keep their
215
+ * own layouts" rule.
216
+ */
217
+ tabsEnabled: Record<string, boolean>;
218
+ /**
219
+ * Per-viewer enable switches, keyed by file viewer descriptor id
220
+ * (`'image'`, `'my-plugin:csv'`). An ABSENT key means enabled; a disabled
221
+ * viewer is skipped by `matchFileViewer` so files fall through to the
222
+ * next matching viewer (or the download button when none match).
223
+ */
224
+ viewersEnabled: Record<string, boolean>;
225
+ /**
226
+ * Plugin-owned settings blobs (v0.12.0+), keyed by descriptor id: each
227
+ * registered tab/viewer that declares `settings.pluginToggles` (or writes
228
+ * through `settings.render`'s `updatePluginSetting`) persists its values
229
+ * here — an open map, so third-party keys need no host PrefsSchema field.
230
+ * Values are JSON-serializable (the row controls produce strings /
231
+ * numbers / booleans; custom panels are responsible for their own).
232
+ */
233
+ pluginSettings: Record<string, Record<string, unknown>>;
234
+ }
235
+ /** Range contract of {@link SidebarPrefs.defaultWidthPercent}. */
236
+ export declare const WIDTH_PERCENT_MIN = 20;
237
+ export declare const WIDTH_PERCENT_MAX = 60;
238
+ export declare const WIDTH_PERCENT_DEFAULT = 35;
239
+ /** Range contract of {@link SidebarPrefs.terminalFontSize}. */
240
+ export declare const TERMINAL_FONT_SIZE_MIN = 9;
241
+ export declare const TERMINAL_FONT_SIZE_MAX = 32;
242
+ export declare const TERMINAL_FONT_SIZE_DEFAULT = 13;
243
+ /** Range contract of {@link SidebarPrefs.titleBarStripPx}. */
244
+ export declare const TITLE_BAR_STRIP_MIN = 0;
245
+ export declare const TITLE_BAR_STRIP_MAX = 120;
246
+ export declare const TITLE_BAR_STRIP_DEFAULT = 40;
247
+ /** The title-bar / shell compatibility schemes (see {@link SidebarPrefs.titleBarScheme}). */
248
+ export declare const TITLE_BAR_SCHEMES: readonly ["auto", "web", "preset", "custom"];
249
+ export type TitleBarScheme = typeof TITLE_BAR_SCHEMES[number];
250
+ /** Fallback prefs used whenever the settings document is unreachable or malformed. */
251
+ export declare const SIDEBAR_PREFS_DEFAULTS: SidebarPrefs;
252
+ /** Clamp one width percent into the contract range (shared by schema and client reads). */
253
+ export declare function clampWidthPercent(value: number): number;
254
+ /** Clamp one terminal font size into the contract range (shared by schema and client reads). */
255
+ export declare function clampTerminalFontSize(value: number): number;
256
+ /** Clamp one title-bar strip height into the contract range (shared by schema and client reads). */
257
+ export declare function clampTitleBarStrip(value: number): number;
@@ -0,0 +1,79 @@
1
+ import type * as nodePtyNs from 'node-pty';
2
+ /** The node-pty module surface the registries consume (spawn/kill/resize/…). */
3
+ export type NodePtyModule = typeof nodePtyNs;
4
+ /**
5
+ * The node-pty version range this plugin ships. MUST stay identical to the
6
+ * range DSH core declares (`@deepseek-ai/dsh-subprocess-local`): the same
7
+ * range keeps pnpm resolving both to one physical package.
8
+ */
9
+ export declare const DSH_NODE_PTY_RANGE = "^1.1.0";
10
+ /**
11
+ * The WebSocket close-code-1011 reason the host sends when node-pty is
12
+ * unavailable. The client recognizes this exact marker and fetches the full
13
+ * repair details from `/sidebar/api/terminal.deps` (a WS close reason is
14
+ * capped at 123 bytes, so the command itself cannot ride the close frame).
15
+ */
16
+ export declare const PTY_DEPS_MISSING = "pty-deps-missing";
17
+ /** A require-compatible loader, injectable for tests. */
18
+ export type NodePtyRequire = (id: string) => unknown;
19
+ /**
20
+ * Load node-pty once (synchronously) and cache the outcome. Returns null
21
+ * when the package or its native binding cannot be loaded; the cause stays
22
+ * queryable through {@link nodePtyLoadCause}. Never throws.
23
+ */
24
+ export declare function loadNodePty(requireImpl?: NodePtyRequire): NodePtyModule | null;
25
+ /** The recorded load failure (undefined when the load succeeded or never ran). */
26
+ export declare function nodePtyLoadCause(): unknown;
27
+ /** Forget the cached outcome (tests only — a real reload is otherwise one-shot). */
28
+ export declare function resetNodePtyCache(): void;
29
+ /** Load node-pty or throw the canonical degraded-mode error (class-constructor default). */
30
+ export declare function loadRequiredNodePty(): NodePtyModule;
31
+ /**
32
+ * Detect the DSH profile directory this plugin is installed into: the
33
+ * nearest ancestor of the plugin module that carries both `package.json`
34
+ * and `pnpm-workspace.yaml` (the profile root; the plugin resolves from the
35
+ * profile's node_modules). Falls back to `$CHATCODE_CLI_HOME/profiles/web`
36
+ * (with legacy `$DSH_HOME` as a read-only compatibility input), then the
37
+ * canonical ChatCode CLI home, and finally null.
38
+ */
39
+ export declare function findProfileDir(fromFile?: string): string | null;
40
+ /** The plugin package root (walk-up from the module; works for lib/ and src/ layouts). */
41
+ export declare function findPluginRoot(fromFile?: string): string | null;
42
+ /** Options for {@link buildRepairCommand}. */
43
+ export interface RepairCommandOptions {
44
+ /** The plugin package root (where scripts/install.sh / install.ps1 live). */
45
+ pluginRoot: string | null;
46
+ /** The detected profile directory (null → the standard `web` profile). */
47
+ profileDir: string | null;
48
+ /** Platform override for tests; defaults to the live process. */
49
+ platform?: NodeJS.Platform;
50
+ }
51
+ /**
52
+ * The pasteable repair command for a broken node-pty install: rerun the
53
+ * plugin's own installer in `--repair` mode (idempotent: it re-writes the
54
+ * profile's `allowBuilds: node-pty: true` and re-installs/rebuilds the
55
+ * dependency). Falls back to ChatCode CLI's plugin command when the scripts are not
56
+ * shipped (exotic layouts).
57
+ */
58
+ export declare function buildRepairCommand(options: RepairCommandOptions): {
59
+ command: string;
60
+ note?: string;
61
+ };
62
+ /** Structured status served by the `/sidebar/api/terminal.deps` endpoint. */
63
+ export type NodePtyDepsStatus = {
64
+ ok: true;
65
+ } | {
66
+ ok: false;
67
+ /** The require-time error message (module missing, native binding broken…). */
68
+ cause: string;
69
+ /** The pasteable repair command (terminal/cmd). */
70
+ command: string;
71
+ /** The detected profile name (null when undetected → the command defaults to web). */
72
+ profile: string | null;
73
+ /** Optional supplementary hint (fallback command only). */
74
+ note?: string;
75
+ };
76
+ /** Current node-pty dependency status (loaded vs degraded + repair info). */
77
+ export declare function depsStatus(options?: {
78
+ fromFile?: string;
79
+ }): NodePtyDepsStatus;
@@ -0,0 +1,168 @@
1
+ import type { IPty } from 'node-pty';
2
+ import { type NodePtyModule } from './pty-deps.ts';
3
+ /**
4
+ * Restore the executable bit pnpm strips from node-pty's prebuilt
5
+ * spawn-helper (the macOS helper that forks and sets up the pty). Without it
6
+ * every spawn fails with `posix_spawnp failed`. Idempotent; mirrors
7
+ * @deepseek-ai/dsh-terminal-bash's ensure-spawn-helper postinstall, run at
8
+ * plugin activation so link-installed deployments get the fix too.
9
+ */
10
+ export declare function ensureSpawnHelper(): void;
11
+ /** One live terminal. */
12
+ export interface SidebarPty {
13
+ /** `${sessionId}:${tabId}` registry key. */
14
+ key: string;
15
+ sessionId: string;
16
+ tabId: string;
17
+ /** The working directory the process was SPAWNED with (a reconnect that
18
+ * resolves a different authoritative cwd respawns instead of reusing —
19
+ * the page-load hydrate race can attach the real cwd after the first
20
+ * connect, and a shell in the wrong directory must not linger). */
21
+ cwd: string;
22
+ pty: IPty;
23
+ /** Output accumulated since spawn (bounded; head dropped when over the limit). */
24
+ transcript: string;
25
+ /** Whether the top-level process exited (transcript stays replayable). */
26
+ exited: boolean;
27
+ exitCode?: number | null;
28
+ }
29
+ /**
30
+ * The terminal registry. `maxPerSession` bounds concurrent processes per
31
+ * conversation (the client caps tabs at the same number).
32
+ *
33
+ * Lifecycle of a UI-tab pty when its WebSocket drops:
34
+ * - **Close frame** (`{type:'close'}`): the user closed the tab → schedule a
35
+ * 0-ms close (quota released immediately).
36
+ * - **Park frame** (`{type:'park'}`): the user switched to another
37
+ * conversation; the tab is still open in its session's persisted state but
38
+ * its view unmounted → mark the pty as parked (no auto-close countdown).
39
+ * The pty stays alive until the user switches back (a reconnecting view
40
+ * calls `open()` which clears the parked state) or the tab is later closed
41
+ * (a `{type:'close'}` frame from a fresh connection). Without `park`, a
42
+ * bare socket drop would start the reconnect-grace countdown and kill the
43
+ * shell after `reconnectGraceMs` — wrong for a session switch, where the
44
+ * user is still actively using the app, just in another conversation.
45
+ * - **Bare socket drop** (no frame): page refresh, crash, plugin teardown →
46
+ * schedule a close after `reconnectGraceMs` so a quick reconnect reattaches
47
+ * the same shell.
48
+ */
49
+ export declare class PtyManager {
50
+ private readonly shell;
51
+ private readonly maxPerSession;
52
+ private readonly shellArgs;
53
+ /** The loaded node-pty module (injected so a broken install degrades instead of crashing the plugin). */
54
+ private readonly nodePty;
55
+ private readonly sessions;
56
+ private readonly pendingCloses;
57
+ /** Tabs whose view unmounted because the user switched conversations — the
58
+ * tab is still open in its session's state, so the pty must NOT enter the
59
+ * reconnect-grace countdown. Cleared by `cancelClose` (a reconnecting
60
+ * view's `open()` cancels it) or by `scheduleClose` (an explicit close
61
+ * frame still kills a parked pty). */
62
+ private readonly parked;
63
+ constructor(shell: string, maxPerSession: number, shellArgs?: string[],
64
+ /** The loaded node-pty module (injected so a broken install degrades instead of crashing the plugin). */
65
+ nodePty?: NodePtyModule);
66
+ /** All live terminal keys of one session. */
67
+ keysOf(sessionId: string): string[];
68
+ /**
69
+ * Open (or reuse) the terminal for a session/tab key. A handle whose
70
+ * process already exited is replaced with a fresh spawn (reconnecting a
71
+ * dead terminal must yield a live shell, not an input sink), and so is a
72
+ * live handle whose spawn cwd differs from the now-authoritative one (the
73
+ * first connect of a page load can arrive before the session hydrates, so
74
+ * it fell back to the process cwd — reconnecting with the real cwd must
75
+ * restart the shell in the right directory). Reopening also cancels any
76
+ * pending scheduled close (a reconnect within the grace window keeps the
77
+ * process alive).
78
+ * @param sessionId - conversation id.
79
+ * @param tabId - client tab id.
80
+ * @param cwd - initial working directory (the session's cwd).
81
+ * @param cols - initial terminal width.
82
+ * @param rows - initial terminal height.
83
+ * @returns the live handle.
84
+ * @throws {SidebarError} pty-error when the per-session cap is reached.
85
+ */
86
+ open(sessionId: string, tabId: string, cwd: string, cols: number, rows: number, shell?: string, shellArgs?: string[]): SidebarPty;
87
+ /**
88
+ * Schedule the terminal's destruction after `delayMs`. A tab close sends
89
+ * delay 0 (release the quota immediately); a bare socket drop (refresh,
90
+ * crash) uses the grace period so a quick reconnect keeps the process.
91
+ * `open()` cancels any pending close. Clears the parked state — an explicit
92
+ * close frame on a parked pty (the user switched back and closed the tab)
93
+ * still kills it.
94
+ */
95
+ scheduleClose(key: string, delayMs: number): void;
96
+ /**
97
+ * Park a terminal: the owning tab's view unmounted because the user
98
+ * switched to another conversation, but the tab is still open in its
99
+ * session's persisted state. Cancels any pending grace close and marks
100
+ * the pty so the host's `ws.on('close')` handler does NOT start the
101
+ * reconnect-grace countdown — the pty stays alive until the user switches
102
+ * back (a reconnecting view's `open()` clears this) or explicitly closes
103
+ * the tab (a `{type:'close'}` frame's `scheduleClose` clears this).
104
+ */
105
+ park(key: string): void;
106
+ /** Whether this pty was parked (its view unmounted for a session switch). */
107
+ isParked(key: string): boolean;
108
+ /** Cancel a pending scheduled close (the terminal is being reopened).
109
+ * Also clears the parked state — a reconnecting view reattaches a parked
110
+ * pty and resumes normal lifecycle. */
111
+ cancelClose(key: string): void;
112
+ /** Resolve a live handle by key, or undefined. */
113
+ get(key: string): SidebarPty | undefined;
114
+ /** Close a terminal and drop its state (the owning tab was closed). */
115
+ close(key: string): void;
116
+ /** Close every terminal (plugin teardown). */
117
+ disposeAll(): void;
118
+ }
119
+ /**
120
+ * Inputs for {@link defaultShell} resolution. Every field is optional and
121
+ * defaults to the live process, which keeps the no-argument call sites
122
+ * working while tests (and exotic embedders) can pin the platform, the
123
+ * environment, and the existence probe independently — the Windows chain
124
+ * never executes on the ubuntu CI runners, so it is only testable through
125
+ * these injection points.
126
+ */
127
+ export interface ShellResolutionOptions {
128
+ /** Platform override (defaults to `process.platform`). */
129
+ platform?: NodeJS.Platform;
130
+ /** Environment override; the resolver only reads SHELL, DSH_SIDEBAR_SHELL, PATH, ProgramW6432, ProgramFiles, LOCALAPPDATA. */
131
+ env?: NodeJS.ProcessEnv;
132
+ /** Explicitly configured shell (the `shell` config field); wins over every automatic source. Empty means unset. */
133
+ explicit?: string;
134
+ /** File-existence probe override (defaults to `existsSync`). */
135
+ exists?: (path: string) => boolean;
136
+ }
137
+ /**
138
+ * The interactive shell for this platform, resolved like a terminal
139
+ * emulator: an explicitly configured shell (the `shell` config field) wins,
140
+ * then `$SHELL` on POSIX (deployment override), then the account's login
141
+ * shell from passwd, then `/bin/bash`. The passwd step matters because
142
+ * service managers and container inits often start dsh without `SHELL`, and
143
+ * the tab should still open the user's login shell (e.g. zsh) instead of
144
+ * silently degrading to bash.
145
+ *
146
+ * Windows previously short-circuited to `powershell.exe` (the inbox 5.1)
147
+ * before any resolution, so PowerShell 7 users always got a legacy shell
148
+ * without `??`/`?.`/ternary and with poor ANSI/UTF-8 defaults. The Windows
149
+ * chain is now: explicit shell → `DSH_SIDEBAR_SHELL` env override → first
150
+ * `pwsh.exe` found on PATH or in a known install directory → the 5.1
151
+ * fallback (machines without PowerShell 7 keep working).
152
+ */
153
+ export declare function defaultShell(options?: ShellResolutionOptions): string;
154
+ /**
155
+ * A short display name for a shell executable, used as the terminal tab
156
+ * title. `/bin/zsh` → `zsh`, `C:\...\powershell.exe` → `powershell`.
157
+ * Falls back to the raw value when no basename can be derived.
158
+ */
159
+ export declare function shellDisplayName(shell: string): string;
160
+ /**
161
+ * Spawn arguments that make the shell behave like a terminal-emulator tab:
162
+ * POSIX shells start as login shells (`-l`) so they read the profile files
163
+ * (`~/.profile`, `~/.zprofile`); Windows PowerShell takes no login flag.
164
+ *
165
+ * When explicit `configured` args are supplied they REPLACE the platform
166
+ * defaults entirely, giving deployments full control over shell startup.
167
+ */
168
+ export declare function shellSpawnArgs(configured?: string[]): string[];
@@ -0,0 +1,34 @@
1
+ import type { Context } from './context-types.ts';
2
+ import { AgentPtyRegistry } from './agent-pty.ts';
3
+ /**
4
+ * Bound a string to a byte limit, marking truncation. Truncation never
5
+ * splits a multi-byte UTF-8 sequence: when the byte cap lands inside one,
6
+ * the walk-back retreats to the sequence's leading byte so the retained
7
+ * prefix decodes cleanly (a split would decode to U+FFFD).
8
+ * @internal exported for the unit tests, like {@link snapshotOf}.
9
+ */
10
+ export declare function boundBytes(text: string, maxBytes: number): {
11
+ text: string;
12
+ truncated: boolean;
13
+ };
14
+ /**
15
+ * Register the eight terminal tools against the host tool registry. The
16
+ * `resolveCwd` callback threads the live session cwd (authoritative from the
17
+ * session store, falling back to the process cwd) so a freshly-created
18
+ * terminal lands in the right directory without the model passing it.
19
+ * Every uuid-keyed tool first asserts the terminal belongs to the calling
20
+ * session (`registry.assertOwned`), so one agent can never reach another
21
+ * session's terminals.
22
+ * @param ctx - host plugin context (carries the tools service).
23
+ * @param registry - the agent-owned terminal registry.
24
+ * @param resolveCwd - async cwd resolver for one session id. Resolves through
25
+ * the session header, the client-supplied cwd, and the persistence index
26
+ * before falling back to the host process cwd (production always provides
27
+ * persistence, so the fallback is reached only in tests / stripped-down hosts).
28
+ * @returns a disposer that unregisters all eight tools (the caller gates
29
+ * registration on the side-card setting and calls this to turn them off).
30
+ */
31
+ export declare function registerTools(ctx: Context, registry: AgentPtyRegistry, resolveCwd: (sessionId: string) => Promise<string>, readShellOverrides: () => {
32
+ shell?: string;
33
+ shellArgs?: string[];
34
+ }): () => void;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Browser-trust fence for the sidebar routes, behaviorally identical to the
3
+ * /api gateway's fence in @deepseek-ai/dsh-client-connection
4
+ * (src/api-request-trust.ts + src/loopback-hostname.ts, BSD-3-Clause,
5
+ * copied here because the package does not export these helpers and the
6
+ * plugin must not depend on its internals). Host-header loopback or a
7
+ * configured trusted authority passes; cross-site browser markers refuse.
8
+ * This is a DNS-rebinding / cross-site defense, not authentication.
9
+ */
10
+ import type { IncomingHttpHeaders } from 'node:http';
11
+ /** The request facts the fence reads (structural subset of IncomingMessage). */
12
+ interface ApiTrustRequest {
13
+ headers: IncomingHttpHeaders;
14
+ }
15
+ /** Whether a normalized URL hostname names the local loopback authority. */
16
+ export declare function isLoopbackHostname(hostname: string): boolean;
17
+ /**
18
+ * Decide whether one sidebar request may reach the plugin routes.
19
+ * @param request - node HTTP request facts (headers).
20
+ * @param trustedHosts - non-loopback authorities this deployment serves.
21
+ * @returns true when the Host is ours (loopback or trusted) and browser markers are same-origin.
22
+ */
23
+ export declare function isTrustedApiRequest(request: ApiTrustRequest, trustedHosts: readonly string[]): boolean;
24
+ export {};
@@ -0,0 +1,71 @@
1
+ /**
2
+ * dsh-ui-tweaks — archive manager (host half).
3
+ *
4
+ * The browser Archive manager (the "归档" settings section, shown when the
5
+ * archiveManagerEnabled setting is on) lists archived sessions and offers
6
+ * two per-session actions plus batch actions through this same-origin route:
7
+ *
8
+ * - **restore** / **restore-all**: move a session out of the archive set. The
9
+ * session log and its workspace accounting slot are kept untouched, so the
10
+ * conversation reappears in the normal sidebar list.
11
+ * - **delete** / **delete-all**: PERMANENTLY delete a session — its durable
12
+ * JSONL log is removed from disk, it is detached from every workspace's
13
+ * accounting, removed from the archive set, dropped from the workspace
14
+ * registry's in-memory header index, and best-effort-cleaned from the
15
+ * session projection cache. Only a genuinely RUNNING agent is refused;
16
+ * opened-but-idle sessions are also removed from the in-memory SessionStore
17
+ * so they vanish from the live list immediately (the host relays
18
+ * `session/disposed` as `host/session-removed`).
19
+ *
20
+ * DSH has no public API for either operation. The archive set lives in the
21
+ * `workspace` storage domain's global singleton (the same record
22
+ * `WorkspaceRegistry` keeps in memory), so this backend writes the filtered
23
+ * set through the live domain handle (`ctx.storageDomain.get('workspace')`)
24
+ * and keeps the registry's in-memory cache coherent in the same write, so the
25
+ * registry's next mutation cannot resurrect a restored id. Session-log
26
+ * deletion uses the persistence backend's own locator (`findLog`) so only the
27
+ * exact encoded session directory is removed; workspace accounting removal
28
+ * uses the registry's public `WorkspaceEntity.detachSession`.
29
+ * @module dsh-ui-tweaks/archive
30
+ */
31
+ import type { IncomingMessage, ServerResponse } from 'node:http';
32
+ import type { Context } from '@deepseek-ai/cordis';
33
+ /** Exact route used by the browser Archive panel. */
34
+ export declare const ARCHIVE_ROUTE = "/_dsh/ui-tweaks/archive";
35
+ /** Public Archive snapshot. Only session ids cross this boundary — the browser
36
+ * enriches them with titles / paths from its own session list feed. */
37
+ export interface ArchiveSnapshot {
38
+ archivedSessionIds: string[];
39
+ }
40
+ /** A live session was targeted by a permanent delete. */
41
+ export declare class SessionLiveError extends Error {
42
+ readonly code = "session-live";
43
+ constructor();
44
+ }
45
+ /** Same-origin Archive read/write handler. */
46
+ export declare class ArchiveBackend {
47
+ private readonly ctx;
48
+ constructor(ctx: Context);
49
+ private registry;
50
+ private storageDomain;
51
+ private snapshot;
52
+ /** Remove one (or all) ids from the durable archive set, syncing the
53
+ * registry's in-memory cache in the same write. */
54
+ private writeArchiveSet;
55
+ /** Restore one session: remove it from the durable archive set. */
56
+ private restore;
57
+ /** Restore every archived session at once. */
58
+ private restoreAll;
59
+ /** Permanently delete one session: log, accounting, archive set, and caches. */
60
+ private deleteSession;
61
+ /** Permanently delete every archived session (live ones are skipped). */
62
+ private deleteAll;
63
+ /** Handle the exact Archive route. */
64
+ handle(req: IncomingMessage, res: ServerResponse): Promise<void>;
65
+ }
66
+ /**
67
+ * Attach the Archive route whenever a webServer service is present.
68
+ * @param ctx - plugin context owning route effects.
69
+ * @param backend - Archive handler.
70
+ */
71
+ export declare function installArchiveWeb(ctx: Context, backend: ArchiveBackend): void;