@keith9681/dsh-sidebar 0.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/README_EN.md +0 -0
  4. package/cordis.patch.yml +49 -0
  5. package/lib/client-editor.js +34651 -0
  6. package/lib/client-mermaid.js +200629 -0
  7. package/lib/client-registry.js +13388 -0
  8. package/lib/client-terminal.js +8904 -0
  9. package/lib/client.js +13388 -0
  10. package/lib/index.js +3959 -0
  11. package/lib/invariant.js +22 -0
  12. package/lib/types/agent-pty.d.ts +226 -0
  13. package/lib/types/browser-probe.d.ts +15 -0
  14. package/lib/types/bundle-route.d.ts +12 -0
  15. package/lib/types/client/BrowserView.d.ts +22 -0
  16. package/lib/types/client/DiffTab.d.ts +6 -0
  17. package/lib/types/client/DiffView.d.ts +51 -0
  18. package/lib/types/client/EditorHost.d.ts +12 -0
  19. package/lib/types/client/FileTree.d.ts +36 -0
  20. package/lib/types/client/GitView.d.ts +8 -0
  21. package/lib/types/client/OrphanedTab.d.ts +11 -0
  22. package/lib/types/client/PdfView.d.ts +6 -0
  23. package/lib/types/client/RenderBoundary.d.ts +32 -0
  24. package/lib/types/client/SandboxStatusBar.d.ts +10 -0
  25. package/lib/types/client/SideCardSection.d.ts +74 -0
  26. package/lib/types/client/SideChatView.d.ts +16 -0
  27. package/lib/types/client/Sidebar.d.ts +6 -0
  28. package/lib/types/client/SubagentView.d.ts +16 -0
  29. package/lib/types/client/TabBar.d.ts +43 -0
  30. package/lib/types/client/TerminalView.d.ts +24 -0
  31. package/lib/types/client/TextEditor.d.ts +10 -0
  32. package/lib/types/client/TreePanel.d.ts +23 -0
  33. package/lib/types/client/UploadOverlay.d.ts +20 -0
  34. package/lib/types/client/add-plugin-modal.d.ts +15 -0
  35. package/lib/types/client/api.d.ts +268 -0
  36. package/lib/types/client/binary-download.d.ts +12 -0
  37. package/lib/types/client/breakpoints.d.ts +12 -0
  38. package/lib/types/client/browser.d.ts +50 -0
  39. package/lib/types/client/builtins/index.d.ts +18 -0
  40. package/lib/types/client/builtins/tabs.d.ts +11 -0
  41. package/lib/types/client/builtins/viewers.d.ts +3 -0
  42. package/lib/types/client/chunk-loader.d.ts +124 -0
  43. package/lib/types/client/chunks/editor.d.ts +9 -0
  44. package/lib/types/client/chunks/mermaid.d.ts +10 -0
  45. package/lib/types/client/chunks/terminal.d.ts +9 -0
  46. package/lib/types/client/cm-themes.d.ts +24 -0
  47. package/lib/types/client/conversation-draft.d.ts +14 -0
  48. package/lib/types/client/desktop-env.d.ts +35 -0
  49. package/lib/types/client/editable-state.d.ts +27 -0
  50. package/lib/types/client/editor-load.d.ts +66 -0
  51. package/lib/types/client/frame-batcher.d.ts +24 -0
  52. package/lib/types/client/icons.d.ts +57 -0
  53. package/lib/types/client/image-types.d.ts +3 -0
  54. package/lib/types/client/ime-guard.d.ts +36 -0
  55. package/lib/types/client/index.d.ts +19 -0
  56. package/lib/types/client/intercept.d.ts +33 -0
  57. package/lib/types/client/lang.d.ts +12 -0
  58. package/lib/types/client/lazy-chunk.d.ts +25 -0
  59. package/lib/types/client/link-intercept.d.ts +42 -0
  60. package/lib/types/client/locales.d.ts +366 -0
  61. package/lib/types/client/mermaid-blocks.d.ts +41 -0
  62. package/lib/types/client/mermaid-sanitize.d.ts +2 -0
  63. package/lib/types/client/mermaid.d.ts +12 -0
  64. package/lib/types/client/open-when-sized.d.ts +20 -0
  65. package/lib/types/client/open-with-settings.d.ts +4 -0
  66. package/lib/types/client/open-with.d.ts +87 -0
  67. package/lib/types/client/openpath-intercept.d.ts +41 -0
  68. package/lib/types/client/paths.d.ts +35 -0
  69. package/lib/types/client/pdf-types.d.ts +2 -0
  70. package/lib/types/client/plugin-settings.d.ts +8 -0
  71. package/lib/types/client/plugins-shared.d.ts +27 -0
  72. package/lib/types/client/plugins-tabs.d.ts +3 -0
  73. package/lib/types/client/plugins-viewers.d.ts +3 -0
  74. package/lib/types/client/prefs.d.ts +41 -0
  75. package/lib/types/client/produced-files.d.ts +23 -0
  76. package/lib/types/client/selection-payload.d.ts +27 -0
  77. package/lib/types/client/service.d.ts +440 -0
  78. package/lib/types/client/settings-nav-icon.d.ts +19 -0
  79. package/lib/types/client/shell-presets.d.ts +48 -0
  80. package/lib/types/client/sidechat-transcript.d.ts +103 -0
  81. package/lib/types/client/split-pane.d.ts +30 -0
  82. package/lib/types/client/state.d.ts +359 -0
  83. package/lib/types/client/subagent-detect.d.ts +54 -0
  84. package/lib/types/client/subagent-jobs.d.ts +63 -0
  85. package/lib/types/client/tab-content-memo.d.ts +33 -0
  86. package/lib/types/client/terminal-font.d.ts +20 -0
  87. package/lib/types/client/theme.d.ts +45 -0
  88. package/lib/types/client/titlebar-strip.d.ts +23 -0
  89. package/lib/types/client/upload.d.ts +69 -0
  90. package/lib/types/client/wco.d.ts +47 -0
  91. package/lib/types/config.d.ts +64 -0
  92. package/lib/types/context-types.d.ts +603 -0
  93. package/lib/types/fs-operations.d.ts +28 -0
  94. package/lib/types/fs-search.d.ts +24 -0
  95. package/lib/types/fs-tree.d.ts +51 -0
  96. package/lib/types/git.d.ts +82 -0
  97. package/lib/types/html-route.d.ts +59 -0
  98. package/lib/types/index.d.ts +47 -0
  99. package/lib/types/invariant.d.ts +15 -0
  100. package/lib/types/jobs-routes.d.ts +45 -0
  101. package/lib/types/open-external.d.ts +24 -0
  102. package/lib/types/prefs-shared.d.ts +225 -0
  103. package/lib/types/pty-deps.d.ts +78 -0
  104. package/lib/types/pty-manager.d.ts +168 -0
  105. package/lib/types/sidechat-core.d.ts +172 -0
  106. package/lib/types/sidechat-routes.d.ts +30 -0
  107. package/lib/types/subagent-activity.d.ts +44 -0
  108. package/lib/types/subagent-live-route.d.ts +44 -0
  109. package/lib/types/tools.d.ts +31 -0
  110. package/lib/types/trust-fence.d.ts +24 -0
  111. package/lib/types/wire.d.ts +38 -0
  112. package/package.json +173 -0
  113. package/scripts/install.ps1 +289 -0
  114. package/scripts/install.sh +287 -0
  115. package/src/agent-pty.ts +527 -0
  116. package/src/browser-probe.ts +26 -0
  117. package/src/bundle-route.ts +129 -0
  118. package/src/client/BrowserView.tsx +253 -0
  119. package/src/client/DiffTab.tsx +110 -0
  120. package/src/client/DiffView.tsx +305 -0
  121. package/src/client/EditorHost.tsx +525 -0
  122. package/src/client/FileTree.tsx +653 -0
  123. package/src/client/GitView.tsx +558 -0
  124. package/src/client/OrphanedTab.tsx +27 -0
  125. package/src/client/PdfView.tsx +110 -0
  126. package/src/client/RenderBoundary.tsx +49 -0
  127. package/src/client/SandboxStatusBar.tsx +60 -0
  128. package/src/client/SideCardSection.module.css +960 -0
  129. package/src/client/SideCardSection.tsx +1152 -0
  130. package/src/client/SideChatView.module.css +437 -0
  131. package/src/client/SideChatView.tsx +644 -0
  132. package/src/client/Sidebar.tsx +1148 -0
  133. package/src/client/SubagentView.module.css +547 -0
  134. package/src/client/SubagentView.tsx +883 -0
  135. package/src/client/TabBar.tsx +305 -0
  136. package/src/client/TerminalView.tsx +383 -0
  137. package/src/client/TextEditor.tsx +500 -0
  138. package/src/client/TreePanel.tsx +273 -0
  139. package/src/client/UploadOverlay.tsx +62 -0
  140. package/src/client/add-plugin-modal.tsx +199 -0
  141. package/src/client/api.ts +335 -0
  142. package/src/client/binary-download.tsx +23 -0
  143. package/src/client/breakpoints.ts +51 -0
  144. package/src/client/browser.ts +119 -0
  145. package/src/client/builtins/index.ts +37 -0
  146. package/src/client/builtins/tabs.tsx +331 -0
  147. package/src/client/builtins/viewers.tsx +125 -0
  148. package/src/client/chunk-loader.ts +351 -0
  149. package/src/client/chunks/editor.tsx +9 -0
  150. package/src/client/chunks/mermaid.tsx +10 -0
  151. package/src/client/chunks/terminal.tsx +9 -0
  152. package/src/client/cm-themes.ts +129 -0
  153. package/src/client/conversation-draft.ts +29 -0
  154. package/src/client/css-modules.d.ts +5 -0
  155. package/src/client/desktop-env.ts +72 -0
  156. package/src/client/editable-state.ts +70 -0
  157. package/src/client/editor-load.ts +92 -0
  158. package/src/client/frame-batcher.ts +56 -0
  159. package/src/client/icons.tsx +161 -0
  160. package/src/client/image-types.ts +8 -0
  161. package/src/client/ime-guard.ts +47 -0
  162. package/src/client/index.tsx +369 -0
  163. package/src/client/intercept.tsx +110 -0
  164. package/src/client/lang.ts +103 -0
  165. package/src/client/layout.css +94 -0
  166. package/src/client/lazy-chunk.tsx +89 -0
  167. package/src/client/link-intercept.ts +73 -0
  168. package/src/client/locales.ts +734 -0
  169. package/src/client/mermaid-blocks.ts +110 -0
  170. package/src/client/mermaid-sanitize.ts +93 -0
  171. package/src/client/mermaid.tsx +401 -0
  172. package/src/client/open-when-sized.ts +43 -0
  173. package/src/client/open-with-settings.tsx +135 -0
  174. package/src/client/open-with.ts +221 -0
  175. package/src/client/openpath-intercept.ts +62 -0
  176. package/src/client/paths.ts +47 -0
  177. package/src/client/pdf-types.ts +4 -0
  178. package/src/client/plugin-settings.ts +43 -0
  179. package/src/client/plugins-shared.ts +29 -0
  180. package/src/client/plugins-tabs.ts +87 -0
  181. package/src/client/plugins-viewers.ts +30 -0
  182. package/src/client/prefs.ts +207 -0
  183. package/src/client/produced-files.ts +91 -0
  184. package/src/client/selection-payload.ts +86 -0
  185. package/src/client/service.ts +838 -0
  186. package/src/client/settings-nav-icon.ts +45 -0
  187. package/src/client/shell-presets.ts +83 -0
  188. package/src/client/sidebar.module.css +2577 -0
  189. package/src/client/sidechat-transcript.ts +321 -0
  190. package/src/client/split-pane.tsx +322 -0
  191. package/src/client/state.ts +1175 -0
  192. package/src/client/subagent-detect.ts +137 -0
  193. package/src/client/subagent-jobs.ts +161 -0
  194. package/src/client/tab-content-memo.ts +46 -0
  195. package/src/client/terminal-font.ts +28 -0
  196. package/src/client/theme.ts +110 -0
  197. package/src/client/titlebar-strip.ts +37 -0
  198. package/src/client/upload.ts +187 -0
  199. package/src/client/wco.ts +120 -0
  200. package/src/config.ts +155 -0
  201. package/src/context-types.ts +610 -0
  202. package/src/fs-operations.ts +99 -0
  203. package/src/fs-search.ts +86 -0
  204. package/src/fs-tree.ts +158 -0
  205. package/src/git.ts +244 -0
  206. package/src/html-route.ts +106 -0
  207. package/src/index.ts +1132 -0
  208. package/src/invariant.ts +32 -0
  209. package/src/jobs-routes.ts +257 -0
  210. package/src/open-external.ts +90 -0
  211. package/src/prefs-shared.ts +268 -0
  212. package/src/pty-deps.ts +240 -0
  213. package/src/pty-manager.ts +376 -0
  214. package/src/sidechat-core.ts +468 -0
  215. package/src/sidechat-routes.ts +344 -0
  216. package/src/subagent-activity.ts +91 -0
  217. package/src/subagent-live-route.ts +93 -0
  218. package/src/tools.ts +479 -0
  219. package/src/trust-fence.ts +77 -0
  220. package/src/wire.ts +100 -0
@@ -0,0 +1,110 @@
1
+ /** Browser-native PDF preview with an always-available download fallback. */
2
+ import { useEffect, useRef, useState } from 'react'
3
+ import clsx from 'clsx'
4
+ import { downloadUrl, mediaUrl, type SessionScope } from './api.ts'
5
+ import { t } from './locales.ts'
6
+ import css from './sidebar.module.css'
7
+
8
+ export function PdfView(props: { scope: SessionScope; path: string; title: string }) {
9
+ const { scope, path, title } = props
10
+ const [load, setLoad] = useState<
11
+ | { status: 'loading' }
12
+ | { status: 'ready'; url: string }
13
+ | { status: 'error'; message: string }
14
+ >({ status: 'loading' })
15
+ const [interactionBlocked, setInteractionBlocked] = useState(false)
16
+ const frameRef = useRef<HTMLIFrameElement>(null)
17
+ const shieldRef = useRef<HTMLDivElement>(null)
18
+
19
+ useEffect(() => {
20
+ const controller = new AbortController()
21
+ let objectUrl: string | undefined
22
+ setLoad({ status: 'loading' })
23
+ void (async () => {
24
+ try {
25
+ const response = await fetch(mediaUrl(scope, path), { signal: controller.signal })
26
+ if (!response.ok) throw new Error(`HTTP ${response.status}`)
27
+ const bytes = await response.arrayBuffer()
28
+ if (controller.signal.aborted) return
29
+ // A direct iframe navigation may download when an old host process or
30
+ // proxy cached application/octet-stream. The Blob URL owns an explicit
31
+ // PDF MIME and therefore consistently opens the browser PDF viewer.
32
+ objectUrl = URL.createObjectURL(new Blob([bytes], { type: 'application/pdf' }))
33
+ setLoad({ status: 'ready', url: objectUrl })
34
+ } catch (error) {
35
+ if (controller.signal.aborted) return
36
+ setLoad({ status: 'error', message: error instanceof Error ? error.message : String(error) })
37
+ }
38
+ })()
39
+ return () => {
40
+ controller.abort()
41
+ if (objectUrl !== undefined) URL.revokeObjectURL(objectUrl)
42
+ }
43
+ }, [scope.sessionId, scope.cwd, path])
44
+
45
+ useEffect(() => {
46
+ const block = (): void => {
47
+ setInteractionBlocked(true)
48
+ if (frameRef.current !== null) frameRef.current.style.pointerEvents = 'none'
49
+ if (shieldRef.current !== null) shieldRef.current.style.pointerEvents = 'auto'
50
+ }
51
+ const unblock = (): void => {
52
+ setInteractionBlocked(false)
53
+ if (frameRef.current !== null) frameRef.current.style.pointerEvents = ''
54
+ if (shieldRef.current !== null) shieldRef.current.style.pointerEvents = 'none'
55
+ }
56
+ const blockForResize = (event: PointerEvent): void => {
57
+ const target = event.target
58
+ if (target instanceof Element
59
+ && target.closest(`.${css.panelResize}, .${css.divider}`) !== null) {
60
+ block()
61
+ }
62
+ }
63
+ // An iframe is a separate browsing context and otherwise swallows the
64
+ // dragover/pointer stream as soon as the cursor crosses it. Temporarily
65
+ // remove it from hit-testing while a tab drag or pane resize is active.
66
+ document.addEventListener('dragstart', block, true)
67
+ document.addEventListener('dragend', unblock, true)
68
+ document.addEventListener('drop', unblock, true)
69
+ window.addEventListener('pointerdown', blockForResize, true)
70
+ window.addEventListener('pointerup', unblock, true)
71
+ window.addEventListener('pointercancel', unblock, true)
72
+ window.addEventListener('blur', unblock)
73
+ return () => {
74
+ document.removeEventListener('dragstart', block, true)
75
+ document.removeEventListener('dragend', unblock, true)
76
+ document.removeEventListener('drop', unblock, true)
77
+ window.removeEventListener('pointerdown', blockForResize, true)
78
+ window.removeEventListener('pointerup', unblock, true)
79
+ window.removeEventListener('pointercancel', unblock, true)
80
+ window.removeEventListener('blur', unblock)
81
+ }
82
+ }, [])
83
+
84
+ return (
85
+ <div className={css.editorPdf}>
86
+ <div className={css.editorPdfToolbar}>
87
+ <a className={css.editorDownloadLink} href={downloadUrl(scope, path)} download>
88
+ {t('downloadToView')}
89
+ </a>
90
+ </div>
91
+ <div className={css.editorPdfStage}>
92
+ {load.status === 'loading' && <div className={css.editorPlaceholder}>{t('loading')}</div>}
93
+ {load.status === 'error' && <div className={css.editorError}>{load.message}</div>}
94
+ {load.status === 'ready' && (
95
+ <iframe
96
+ ref={frameRef}
97
+ className={clsx(css.editorPdfFrame, interactionBlocked && css.editorPdfFrameBlocked)}
98
+ src={load.url}
99
+ title={title}
100
+ />
101
+ )}
102
+ <div
103
+ ref={shieldRef}
104
+ className={clsx(css.editorPdfDragShield, interactionBlocked && css.editorPdfDragShieldActive)}
105
+ aria-hidden="true"
106
+ />
107
+ </div>
108
+ </div>
109
+ )
110
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The generic render error boundary for the sidebar tree: a render error in
3
+ * the wrapped subtree shows a dismissible error strip (retry re-renders the
4
+ * children) instead of blanking the shell. Used at two scopes:
5
+ *
6
+ * - ROOT (index.tsx, `css.boundaryError`): last-resort containment for
7
+ * errors in the sidebar shell itself (Workbench, drag layout, …) — a full
8
+ * swap keeps the page alive.
9
+ * - PER-TAB (Sidebar.tsx TabContent, `css.tabBoundaryError`): a crashing
10
+ * viewer/editor shows a strip inside ITS OWN pane; the toggle cluster, the
11
+ * other tabs, and the panel itself stay alive (issue #31 — a tab crash
12
+ * must never take down the whole sidebar).
13
+ *
14
+ * The className prop selects the strip's geometry: the root's full-height
15
+ * fixed rail vs. the tab's pane-filling block.
16
+ */
17
+ import { Component, type ErrorInfo, type ReactNode } from 'react'
18
+ import { t } from './locales.ts'
19
+ import css from './sidebar.module.css'
20
+
21
+ export class RenderBoundary extends Component<{ children?: ReactNode; className?: string }, { error: string | null }> {
22
+ state = { error: null as string | null }
23
+
24
+ static getDerivedStateFromError(error: unknown): { error: string } {
25
+ return { error: error instanceof Error ? error.message : String(error) }
26
+ }
27
+
28
+ componentDidCatch(error: Error, info: ErrorInfo): void {
29
+ console.error('[dsh-better-sidebar] render error:', error, info.componentStack)
30
+ }
31
+
32
+ render(): ReactNode {
33
+ if (this.state.error !== null) {
34
+ return (
35
+ <div className={this.props.className}>
36
+ <span>dsh-better-sidebar: {this.state.error}</span>
37
+ <button
38
+ type="button"
39
+ className={css.terminalRetry}
40
+ onClick={() => { this.setState({ error: null }) }}
41
+ >
42
+ {t('terminalRetry')}
43
+ </button>
44
+ </div>
45
+ )
46
+ }
47
+ return this.props.children
48
+ }
49
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The live sandbox status row of the two built-in web surfaces (HTML
3
+ * preview and the browser tab): a green "sandbox on" state with a one-tap
4
+ * TEMPORARY unlock, or a RED "sandbox off" state (global setting or the
5
+ * temporary unlock) with a restore action.
6
+ *
7
+ * The temporary unlock is component state only — it never writes the
8
+ * global side card setting (`htmlViewerNoSandbox` / `browserNoSandbox`);
9
+ * it lasts until the surface unmounts (tab switch / file switch) or the
10
+ * user restores the sandbox from the row. When the global setting already
11
+ * drops the sandbox, no unlock/restore action is offered (changing the
12
+ * global setting is the settings page's job) — the red warning stands.
13
+ */
14
+ import clsx from 'clsx'
15
+ import { t } from './locales.ts'
16
+ import css from './sidebar.module.css'
17
+
18
+ export function SandboxStatusBar(props: {
19
+ /** The effective sandbox state (global pref OR the local temporary unlock). */
20
+ sandboxed: boolean
21
+ /** Whether the sandbox is off due to the LOCAL temporary unlock (shows the restore action). */
22
+ local: boolean
23
+ /** The red-state explanation (e.g. "the page runs with full GUI privileges"). */
24
+ dangerCopy: string
25
+ onUnlock: () => void
26
+ onRestore: () => void
27
+ }) {
28
+ const { sandboxed, local, dangerCopy, onUnlock, onRestore } = props
29
+ if (sandboxed) {
30
+ const copy = t('sandboxStatusOn')
31
+ return (
32
+ <div className={clsx(css.sandboxStatus, css.sandboxStatusOn)}>
33
+ <span className={css.sandboxDot} />
34
+ <span className={css.sandboxStatusText} title={copy}>{copy}</span>
35
+ <button
36
+ type="button"
37
+ className={css.sandboxAction}
38
+ onClick={onUnlock}
39
+ >
40
+ {t('sandboxUnlock')}
41
+ </button>
42
+ </div>
43
+ )
44
+ }
45
+ return (
46
+ <div className={clsx(css.sandboxStatus, css.sandboxStatusOff)}>
47
+ <span className={css.sandboxDot} />
48
+ <span className={css.sandboxStatusText} title={dangerCopy}>{dangerCopy}</span>
49
+ {local && (
50
+ <button
51
+ type="button"
52
+ className={css.sandboxAction}
53
+ onClick={onRestore}
54
+ >
55
+ {t('sandboxRestore')}
56
+ </button>
57
+ )}
58
+ </div>
59
+ )
60
+ }