dsh-coding-sidebar 1.0.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.
- package/LICENSE +21 -0
- package/README.md +524 -0
- package/cordis.patch.yml +49 -0
- package/lib/client-editor.js +48229 -0
- package/lib/client-mermaid.js +200745 -0
- package/lib/client-registry.js +21867 -0
- package/lib/client-terminal.js +9361 -0
- package/lib/client.js +21867 -0
- package/lib/index.js +4556 -0
- package/lib/invariant.js +22 -0
- package/lib/types/agent-opens.d.ts +65 -0
- package/lib/types/agent-pty.d.ts +226 -0
- package/lib/types/browser-probe.d.ts +15 -0
- package/lib/types/bundle-route.d.ts +12 -0
- package/lib/types/client/BrowserView.d.ts +39 -0
- package/lib/types/client/DiffTab.d.ts +6 -0
- package/lib/types/client/DiffView.d.ts +51 -0
- package/lib/types/client/EditorHost.d.ts +13 -0
- package/lib/types/client/FileTree.d.ts +38 -0
- package/lib/types/client/FreeWindow.d.ts +29 -0
- package/lib/types/client/GitView.d.ts +10 -0
- package/lib/types/client/MarkdownHtml.d.ts +32 -0
- package/lib/types/client/OrphanedTab.d.ts +11 -0
- package/lib/types/client/PdfView.d.ts +6 -0
- package/lib/types/client/RenderBoundary.d.ts +32 -0
- package/lib/types/client/SandboxStatusBar.d.ts +10 -0
- package/lib/types/client/SideCardSection.d.ts +74 -0
- package/lib/types/client/SideChatView.d.ts +16 -0
- package/lib/types/client/Sidebar.d.ts +6 -0
- package/lib/types/client/SubagentView.d.ts +16 -0
- package/lib/types/client/TabBar.d.ts +54 -0
- package/lib/types/client/TerminalView.d.ts +24 -0
- package/lib/types/client/TextEditor.d.ts +10 -0
- package/lib/types/client/TreePanel.d.ts +24 -0
- package/lib/types/client/UploadOverlay.d.ts +20 -0
- package/lib/types/client/add-plugin-modal.d.ts +15 -0
- package/lib/types/client/api.d.ts +275 -0
- package/lib/types/client/binary-download.d.ts +12 -0
- package/lib/types/client/breakpoints.d.ts +17 -0
- package/lib/types/client/browser.d.ts +60 -0
- package/lib/types/client/builtins/index.d.ts +18 -0
- package/lib/types/client/builtins/tabs.d.ts +11 -0
- package/lib/types/client/builtins/viewers.d.ts +3 -0
- package/lib/types/client/chunk-loader.d.ts +131 -0
- package/lib/types/client/chunks/editor.d.ts +9 -0
- package/lib/types/client/chunks/mermaid.d.ts +10 -0
- package/lib/types/client/chunks/terminal.d.ts +9 -0
- package/lib/types/client/cm-themes.d.ts +24 -0
- package/lib/types/client/conversation-draft.d.ts +14 -0
- package/lib/types/client/desktop-env.d.ts +35 -0
- package/lib/types/client/editor-load.d.ts +66 -0
- package/lib/types/client/frame-batcher.d.ts +24 -0
- package/lib/types/client/icons.d.ts +59 -0
- package/lib/types/client/image-types.d.ts +3 -0
- package/lib/types/client/ime-guard.d.ts +36 -0
- package/lib/types/client/index.d.ts +25 -0
- package/lib/types/client/intercept.d.ts +46 -0
- package/lib/types/client/lang.d.ts +14 -0
- package/lib/types/client/layout-push.d.ts +15 -0
- package/lib/types/client/lazy-chunk.d.ts +25 -0
- package/lib/types/client/link-intercept.d.ts +42 -0
- package/lib/types/client/locales-ar.d.ts +18 -0
- package/lib/types/client/locales-de.d.ts +4 -0
- package/lib/types/client/locales-fr.d.ts +10 -0
- package/lib/types/client/locales-hi.d.ts +17 -0
- package/lib/types/client/locales-id.d.ts +15 -0
- package/lib/types/client/locales-it.d.ts +8 -0
- package/lib/types/client/locales-ja.d.ts +17 -0
- package/lib/types/client/locales-ko.d.ts +9 -0
- package/lib/types/client/locales-nl.d.ts +16 -0
- package/lib/types/client/locales-pl.d.ts +19 -0
- package/lib/types/client/locales-pt.d.ts +1 -0
- package/lib/types/client/locales-ru.d.ts +13 -0
- package/lib/types/client/locales-sv.d.ts +1 -0
- package/lib/types/client/locales-th.d.ts +17 -0
- package/lib/types/client/locales-tr.d.ts +17 -0
- package/lib/types/client/locales-vi.d.ts +17 -0
- package/lib/types/client/locales-zh-HK.d.ts +32 -0
- package/lib/types/client/locales-zh-MO.d.ts +32 -0
- package/lib/types/client/locales-zh-TW.d.ts +32 -0
- package/lib/types/client/locales.d.ts +452 -0
- package/lib/types/client/markdown-html.d.ts +96 -0
- package/lib/types/client/markdown-images.d.ts +45 -0
- package/lib/types/client/markdown-labels.d.ts +38 -0
- package/lib/types/client/md-toc.d.ts +4 -0
- package/lib/types/client/mermaid-blocks.d.ts +47 -0
- package/lib/types/client/mermaid-sanitize.d.ts +2 -0
- package/lib/types/client/mermaid.d.ts +12 -0
- package/lib/types/client/open-when-sized.d.ts +20 -0
- package/lib/types/client/open-with-settings.d.ts +4 -0
- package/lib/types/client/open-with.d.ts +87 -0
- package/lib/types/client/openpath-intercept.d.ts +85 -0
- package/lib/types/client/paths.d.ts +43 -0
- package/lib/types/client/pdf-types.d.ts +2 -0
- package/lib/types/client/pinned.d.ts +86 -0
- package/lib/types/client/plugin-settings.d.ts +8 -0
- package/lib/types/client/plugins-shared.d.ts +27 -0
- package/lib/types/client/plugins-tabs.d.ts +3 -0
- package/lib/types/client/plugins-viewers.d.ts +3 -0
- package/lib/types/client/prefs.d.ts +41 -0
- package/lib/types/client/produced-files.d.ts +29 -0
- package/lib/types/client/selection-payload.d.ts +27 -0
- package/lib/types/client/service.d.ts +439 -0
- package/lib/types/client/settings-nav-icon.d.ts +19 -0
- package/lib/types/client/shell-presets.d.ts +48 -0
- package/lib/types/client/sidechat-transcript.d.ts +103 -0
- package/lib/types/client/split-pane.d.ts +36 -0
- package/lib/types/client/state.d.ts +432 -0
- package/lib/types/client/subagent-detect.d.ts +54 -0
- package/lib/types/client/subagent-jobs.d.ts +63 -0
- package/lib/types/client/tab-content-memo.d.ts +40 -0
- package/lib/types/client/terminal-font.d.ts +78 -0
- package/lib/types/client/terminal-links.d.ts +119 -0
- package/lib/types/client/theme.d.ts +45 -0
- package/lib/types/client/titlebar-strip.d.ts +23 -0
- package/lib/types/client/upload.d.ts +69 -0
- package/lib/types/client/wco.d.ts +47 -0
- package/lib/types/config.d.ts +64 -0
- package/lib/types/context-types.d.ts +605 -0
- package/lib/types/fs-operations.d.ts +28 -0
- package/lib/types/fs-search.d.ts +24 -0
- package/lib/types/fs-tree.d.ts +51 -0
- package/lib/types/git.d.ts +124 -0
- package/lib/types/html-route.d.ts +59 -0
- package/lib/types/index.d.ts +47 -0
- package/lib/types/invariant.d.ts +15 -0
- package/lib/types/jobs-routes.d.ts +45 -0
- package/lib/types/open-external.d.ts +24 -0
- package/lib/types/path-security.d.ts +20 -0
- package/lib/types/prefs-shared.d.ts +236 -0
- package/lib/types/pty-deps.d.ts +78 -0
- package/lib/types/pty-manager.d.ts +168 -0
- package/lib/types/sidechat-core.d.ts +172 -0
- package/lib/types/sidechat-routes.d.ts +30 -0
- package/lib/types/subagent-activity.d.ts +44 -0
- package/lib/types/subagent-live-route.d.ts +44 -0
- package/lib/types/tools.d.ts +34 -0
- package/lib/types/trust-fence.d.ts +24 -0
- package/lib/types/wire.d.ts +38 -0
- package/package.json +172 -0
- package/scripts/install.ps1 +306 -0
- package/scripts/install.sh +287 -0
- package/src/agent-opens.ts +265 -0
- package/src/agent-pty.ts +527 -0
- package/src/browser-probe.ts +26 -0
- package/src/bundle-route.ts +129 -0
- package/src/client/BrowserView.tsx +289 -0
- package/src/client/DiffTab.tsx +114 -0
- package/src/client/DiffView.tsx +305 -0
- package/src/client/EditorHost.tsx +558 -0
- package/src/client/FileTree.tsx +669 -0
- package/src/client/FreeWindow.tsx +337 -0
- package/src/client/GitView.tsx +717 -0
- package/src/client/MarkdownHtml.tsx +296 -0
- package/src/client/OrphanedTab.tsx +27 -0
- package/src/client/PdfView.tsx +110 -0
- package/src/client/RenderBoundary.tsx +49 -0
- package/src/client/SandboxStatusBar.tsx +60 -0
- package/src/client/SideCardSection.module.css +960 -0
- package/src/client/SideCardSection.tsx +1163 -0
- package/src/client/SideChatView.module.css +437 -0
- package/src/client/SideChatView.tsx +645 -0
- package/src/client/Sidebar.tsx +1370 -0
- package/src/client/SubagentView.module.css +547 -0
- package/src/client/SubagentView.tsx +883 -0
- package/src/client/TabBar.tsx +365 -0
- package/src/client/TerminalView.tsx +424 -0
- package/src/client/TextEditor.tsx +468 -0
- package/src/client/TreePanel.tsx +275 -0
- package/src/client/UploadOverlay.tsx +62 -0
- package/src/client/add-plugin-modal.tsx +199 -0
- package/src/client/api.ts +357 -0
- package/src/client/binary-download.tsx +23 -0
- package/src/client/breakpoints.ts +61 -0
- package/src/client/browser.ts +167 -0
- package/src/client/builtins/index.ts +37 -0
- package/src/client/builtins/tabs.tsx +340 -0
- package/src/client/builtins/viewers.tsx +125 -0
- package/src/client/chunk-loader.ts +358 -0
- package/src/client/chunks/editor.tsx +9 -0
- package/src/client/chunks/mermaid.tsx +10 -0
- package/src/client/chunks/terminal.tsx +9 -0
- package/src/client/cm-themes.ts +129 -0
- package/src/client/conversation-draft.ts +29 -0
- package/src/client/css-modules.d.ts +5 -0
- package/src/client/desktop-env.ts +72 -0
- package/src/client/editor-load.ts +92 -0
- package/src/client/frame-batcher.ts +56 -0
- package/src/client/icons.tsx +152 -0
- package/src/client/image-types.ts +8 -0
- package/src/client/ime-guard.ts +47 -0
- package/src/client/index.tsx +427 -0
- package/src/client/intercept.tsx +188 -0
- package/src/client/lang.ts +225 -0
- package/src/client/layout-push.ts +24 -0
- package/src/client/layout.css +90 -0
- package/src/client/lazy-chunk.tsx +89 -0
- package/src/client/link-intercept.ts +73 -0
- package/src/client/locales-ar.ts +368 -0
- package/src/client/locales-de.ts +353 -0
- package/src/client/locales-fr.ts +360 -0
- package/src/client/locales-hi.ts +367 -0
- package/src/client/locales-id.ts +365 -0
- package/src/client/locales-it.ts +358 -0
- package/src/client/locales-ja.ts +367 -0
- package/src/client/locales-ko.ts +359 -0
- package/src/client/locales-nl.ts +365 -0
- package/src/client/locales-pl.ts +369 -0
- package/src/client/locales-pt.ts +350 -0
- package/src/client/locales-ru.ts +365 -0
- package/src/client/locales-sv.ts +350 -0
- package/src/client/locales-th.ts +367 -0
- package/src/client/locales-tr.ts +367 -0
- package/src/client/locales-vi.ts +367 -0
- package/src/client/locales-zh-HK.ts +382 -0
- package/src/client/locales-zh-MO.ts +382 -0
- package/src/client/locales-zh-TW.ts +382 -0
- package/src/client/locales.ts +894 -0
- package/src/client/markdown-html.ts +331 -0
- package/src/client/markdown-images.ts +137 -0
- package/src/client/markdown-labels.tsx +52 -0
- package/src/client/md-toc.tsx +127 -0
- package/src/client/mermaid-blocks.ts +110 -0
- package/src/client/mermaid-sanitize.ts +93 -0
- package/src/client/mermaid.tsx +406 -0
- package/src/client/open-when-sized.ts +43 -0
- package/src/client/open-with-settings.tsx +135 -0
- package/src/client/open-with.ts +221 -0
- package/src/client/openpath-intercept.ts +143 -0
- package/src/client/paths.ts +63 -0
- package/src/client/pdf-types.ts +4 -0
- package/src/client/pinned.ts +183 -0
- package/src/client/plugin-settings.ts +43 -0
- package/src/client/plugins-shared.ts +29 -0
- package/src/client/plugins-tabs.ts +96 -0
- package/src/client/plugins-viewers.ts +30 -0
- package/src/client/prefs.ts +210 -0
- package/src/client/produced-files.ts +120 -0
- package/src/client/selection-payload.ts +86 -0
- package/src/client/service.ts +859 -0
- package/src/client/settings-nav-icon.ts +45 -0
- package/src/client/shell-presets.ts +83 -0
- package/src/client/sidebar.module.css +2788 -0
- package/src/client/sidechat-transcript.ts +321 -0
- package/src/client/split-pane.tsx +331 -0
- package/src/client/state.ts +1497 -0
- package/src/client/subagent-detect.ts +137 -0
- package/src/client/subagent-jobs.ts +161 -0
- package/src/client/tab-content-memo.ts +55 -0
- package/src/client/terminal-font.ts +224 -0
- package/src/client/terminal-links.ts +194 -0
- package/src/client/theme.ts +110 -0
- package/src/client/titlebar-strip.ts +37 -0
- package/src/client/upload.ts +187 -0
- package/src/client/wco.ts +120 -0
- package/src/config.ts +154 -0
- package/src/context-types.ts +611 -0
- package/src/fs-operations.ts +95 -0
- package/src/fs-search.ts +113 -0
- package/src/fs-tree.ts +158 -0
- package/src/git.ts +446 -0
- package/src/html-route.ts +106 -0
- package/src/index.ts +1291 -0
- package/src/invariant.ts +32 -0
- package/src/jobs-routes.ts +257 -0
- package/src/open-external.ts +90 -0
- package/src/path-security.ts +75 -0
- package/src/prefs-shared.ts +280 -0
- package/src/pty-deps.ts +240 -0
- package/src/pty-manager.ts +376 -0
- package/src/sidechat-core.ts +468 -0
- package/src/sidechat-routes.ts +344 -0
- package/src/subagent-activity.ts +91 -0
- package/src/subagent-live-route.ts +93 -0
- package/src/tools.ts +482 -0
- package/src/trust-fence.ts +84 -0
- package/src/wire.ts +100 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Context } from '../../context-types.ts';
|
|
2
|
+
import type { TabDescriptor } from '../service.ts';
|
|
3
|
+
/** How many UI-owned terminals may be open at once (agent-owned ones are uncapped). */
|
|
4
|
+
export declare const TERMINAL_LIMIT = 3;
|
|
5
|
+
/** Optional per-registration builtin behavior (currently terminal title). */
|
|
6
|
+
export interface BuiltinTabOptions {
|
|
7
|
+
/** Returns the display title for newly opened terminal tabs. */
|
|
8
|
+
terminalTitle?: () => string;
|
|
9
|
+
}
|
|
10
|
+
/** The 6 built-in tab descriptors. */
|
|
11
|
+
export declare function builtinTabs(ctx: Context, options?: BuiltinTabOptions): readonly TabDescriptor[];
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy chunk loader for the client bundle. The heavy preview/terminal
|
|
3
|
+
* libraries (CodeMirror, xterm — the editor/terminal stacks, several MB)
|
|
4
|
+
* live in separate build-time bundles (`lib/client-<name>.js`) fetched only
|
|
5
|
+
* on first use of the feature that needs them, so startup downloads/parses
|
|
6
|
+
* only the ~1MB core bundle. (The office stack — Univer / docx-preview /
|
|
7
|
+
* pptx-renderer — is no longer bundled here: Office previews moved to the
|
|
8
|
+
* recommended office plugin, see plugins-viewers.ts.)
|
|
9
|
+
*
|
|
10
|
+
* How a chunk script works (see tsdown.config.ts chunkBundle):
|
|
11
|
+
*
|
|
12
|
+
* globalThis.__dshChunks__ = globalThis.__dshChunks__ || {};
|
|
13
|
+
* globalThis.__dshChunks__["terminal"] = (require) => { ...exports };
|
|
14
|
+
*
|
|
15
|
+
* The script registers its factory on a plugin-owned global registry (NOT
|
|
16
|
+
* through window.__ModuleLoader__.load — the module loader's import() only
|
|
17
|
+
* resolves seed words, shell-own modules, registered factories, and boot
|
|
18
|
+
* graph rows; a chunk id is none of those, so resolution would be version-
|
|
19
|
+
* dependent). Materialization is plugin-owned:
|
|
20
|
+
*
|
|
21
|
+
* 1. inject <script src="/sidebar/bundle/<name>.js"> (classic same-origin
|
|
22
|
+
* script; the official /plugins/<id>/client.js route cannot serve
|
|
23
|
+
* arbitrary file names, so the plugin's own host route serves the chunks),
|
|
24
|
+
* 2. read the factory from the global registry,
|
|
25
|
+
* 3. call it with a require that resolves the platform externals through
|
|
26
|
+
* `__DSH_MODULES__.import(spec)` — the seed-word branch, the one part of
|
|
27
|
+
* the module system that is stable across versions.
|
|
28
|
+
*
|
|
29
|
+
* Caching contract (three layers, each with a failure path):
|
|
30
|
+
* - In-memory: one in-flight promise per chunk, memoized until
|
|
31
|
+
* {@link resetChunks}; a failed load removes its entry so the next call
|
|
32
|
+
* retries from scratch. HMR re-activation keeps the resolved exports of
|
|
33
|
+
* unchanged chunks (ETag revalidation via
|
|
34
|
+
* {@link revalidateChunksOnReactivate}) — the next lazy open skips the
|
|
35
|
+
* re-inject / re-execute.
|
|
36
|
+
* - Script execution: each re-execution overwrites the global registry slot
|
|
37
|
+
* (assignment, never registration) — no "duplicate factory registration"
|
|
38
|
+
* class of errors; a failed materialization clears the cache so the retry
|
|
39
|
+
* re-injects and re-executes.
|
|
40
|
+
* - HTTP: the bundle route revalidates every request (`cache-control:
|
|
41
|
+
* no-cache` + ETag, 304 when unchanged), so page refreshes and HMR
|
|
42
|
+
* re-activations never re-download a multi-MB chunk that did not change.
|
|
43
|
+
*
|
|
44
|
+
* HMR: each plugin activation calls {@link revalidateChunksOnReactivate},
|
|
45
|
+
* which HEADs every loaded chunk against the bundle route and keeps the
|
|
46
|
+
* in-memory cache for the ones whose ETag is unchanged (a hot-reloaded core
|
|
47
|
+
* bundle therefore does not re-execute multi-MB chunk scripts). Chunk-only
|
|
48
|
+
* source edits still need a manual page refresh (the HMR poll watches only
|
|
49
|
+
* client.js); an edit that does land while a core HMR happens is caught by
|
|
50
|
+
* the ETag comparison on the next activation.
|
|
51
|
+
*/
|
|
52
|
+
export type ChunkName = 'terminal' | 'editor' | 'mermaid';
|
|
53
|
+
/** The module exports a chunk factory provides (namespace-ish record). */
|
|
54
|
+
export type ChunkExports = Record<string, unknown>;
|
|
55
|
+
/**
|
|
56
|
+
* The platform externals a chunk bundle may require (mirror of
|
|
57
|
+
* CLIENT_EXTERNALS in tsdown.config.ts — the chunk builds keep these
|
|
58
|
+
* external and the loader resolves them here). A superset is safe: the
|
|
59
|
+
* require only answers what the chunk actually asks for. The shell's static
|
|
60
|
+
* module table seeds React, Cordis, and the UI libraries (primitives/slots);
|
|
61
|
+
* `dsh-client-runtime/client` normalizes onto the runtime package row
|
|
62
|
+
* (stripClientSuffix). dsh-client-web-react / dsh-client-schema-form were
|
|
63
|
+
* dropped in DSH 0.1.0-rc.8 (no rc.8 publish, nothing requires them) — the
|
|
64
|
+
* chunks never asked for them, so they no longer belong here.
|
|
65
|
+
*
|
|
66
|
+
* DSH 0.1.2-alpha.1 removed the `dsh-client-runtime` package outright (the
|
|
67
|
+
* seed table gained bare-name `@deepseek-ai/dsh-client-store` instead); the
|
|
68
|
+
* runtime/client row below stays for 0.1.1-rc.x hosts — no chunk requires
|
|
69
|
+
* it, and {@link buildExternalsRequire} keeps an unresolvable spec
|
|
70
|
+
* undefined until a chunk actually asks (only then is it a loud error), so
|
|
71
|
+
* the entry is inert on 0.1.2-alpha.1+.
|
|
72
|
+
*/
|
|
73
|
+
export declare const CHUNK_EXTERNALS: readonly string[];
|
|
74
|
+
/**
|
|
75
|
+
* The client module system surface this loader needs to resolve externals.
|
|
76
|
+
* DSH 0.1.0-rc.8 provides it as the `ctx.modules` service (no page global
|
|
77
|
+
* anymore); the plugin injects it at activation via
|
|
78
|
+
* {@link setChunkModuleSystem}. The rc.7-era `window.__DSH_MODULES__` global
|
|
79
|
+
* remains as a fallback so older hosts and the test harness keep working.
|
|
80
|
+
*/
|
|
81
|
+
export interface ChunkModuleSystem {
|
|
82
|
+
import(specifier: string): Promise<unknown>;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Inject the client module system the chunk externals resolve through.
|
|
86
|
+
* Called by the client half's apply() with `ctx.modules` (rc.8+); pass
|
|
87
|
+
* undefined to clear (tests). Survives {@link resetChunks} — the module
|
|
88
|
+
* system is shell state, not chunk state, and stays live across HMR.
|
|
89
|
+
*/
|
|
90
|
+
export declare function setChunkModuleSystem(system: ChunkModuleSystem | undefined): void;
|
|
91
|
+
/** Script-load hook; tests replace it with a stub (the default needs a real DOM + network). */
|
|
92
|
+
export type ChunkScriptLoader = (src: string) => Promise<void>;
|
|
93
|
+
/** Test hook: replace the chunk-script loader (pass null to restore the default). */
|
|
94
|
+
export declare function setChunkScriptLoaderForTests(loader: ChunkScriptLoader | null): void;
|
|
95
|
+
export declare function registerChunkForTests(name: ChunkName, loader: () => Promise<ChunkExports>): void;
|
|
96
|
+
/**
|
|
97
|
+
* Load (once) and materialize a lazy chunk, returning its module exports.
|
|
98
|
+
* Concurrent callers share one in-flight load; a failure clears the cache
|
|
99
|
+
* entry so the next call retries (the script re-executes and overwrites its
|
|
100
|
+
* global registry slot — assignments are idempotent).
|
|
101
|
+
* @param name - the chunk to load.
|
|
102
|
+
*/
|
|
103
|
+
export declare function loadChunk(name: ChunkName): Promise<ChunkExports>;
|
|
104
|
+
/**
|
|
105
|
+
* Drop all chunk state for a fresh plugin activation (HMR-safe): clear the
|
|
106
|
+
* in-memory cache and any test-registry entries, so the next lazy open
|
|
107
|
+
* re-fetches and re-executes the current chunk scripts (the registry slots
|
|
108
|
+
* are overwritten by the re-execution — no cleanup needed). A pending
|
|
109
|
+
* revalidation barrier is cleared too: it was only guarding the cache reads
|
|
110
|
+
* of the state being dropped, so the next load must not wait on it (the
|
|
111
|
+
* orphaned task still settles and its identity-guarded `finally` no-ops).
|
|
112
|
+
*/
|
|
113
|
+
export declare function resetChunks(): void;
|
|
114
|
+
/**
|
|
115
|
+
* HMR-safe re-activation hook (index.tsx calls this instead of a full
|
|
116
|
+
* reset): keep the resolved exports of every loaded chunk and drop only the
|
|
117
|
+
* ones whose script changed on disk — the bundle route revalidates every
|
|
118
|
+
* request (cache-control: no-cache + ETag), so an unchanged chunk keeps its
|
|
119
|
+
* memory cache and the next lazy open skips the re-inject / re-execute.
|
|
120
|
+
* Fail-open: an unreachable, ETag-less, or timed-out chunk is dropped
|
|
121
|
+
* (re-fetch on next open). Test-registry entries are always cleared
|
|
122
|
+
* (per-test fixtures).
|
|
123
|
+
* A page refresh remains the authoritative reset (the HMR poll watches only
|
|
124
|
+
* client.js; chunk-only edits surface here on the next core re-activation).
|
|
125
|
+
*
|
|
126
|
+
* The returned promise is also a BARRIER for {@link loadChunk}: while a
|
|
127
|
+
* revalidation is pending, every chunk load awaits it before serving cache,
|
|
128
|
+
* so a lazy tab opening mid-revalidation can never render stale exports
|
|
129
|
+
* that the sweep is about to invalidate (CR #232 P1).
|
|
130
|
+
*/
|
|
131
|
+
export declare function revalidateChunksOnReactivate(): Promise<void>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy chunk entry: the code/markdown/html text editor (CodeMirror 6 + the
|
|
3
|
+
* language packages). Built as `lib/client-editor.js` and registered under
|
|
4
|
+
* `dsh-coding-sidebar/editor` — fetched only when a text file is first
|
|
5
|
+
* opened (see chunk-loader.ts and docs/plans/2026-08-12-lazy-chunks-design.md).
|
|
6
|
+
* Never import this module from the core bundle: it pulls CodeMirror into
|
|
7
|
+
* the startup path.
|
|
8
|
+
*/
|
|
9
|
+
export { TextEditor } from '../TextEditor.tsx';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy chunk entry: the mermaid diagram renderer for the markdown preview
|
|
3
|
+
* (mermaid + its d3/dagre/cytoscape graph deps). Built as
|
|
4
|
+
* lib/client-mermaid.js and registered under the `mermaid` global chunk
|
|
5
|
+
* slot — fetched only when a previewed markdown file contains a mermaid
|
|
6
|
+
* fence (see chunk-loader.ts and the mermaid markdown preview design doc).
|
|
7
|
+
* Never import this module from the core bundle: it pulls mermaid into the
|
|
8
|
+
* startup path.
|
|
9
|
+
*/
|
|
10
|
+
export { MermaidMarkdown } from '../mermaid.tsx';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy chunk entry: the interactive terminal (xterm + fit addon). Built as
|
|
3
|
+
* `lib/client-terminal.js` and registered under
|
|
4
|
+
* `dsh-coding-sidebar/terminal` — fetched only when a terminal tab is first
|
|
5
|
+
* opened (see chunk-loader.ts and docs/plans/2026-08-12-lazy-chunks-design.md).
|
|
6
|
+
* Never import this module from the core bundle: it pulls xterm (and its
|
|
7
|
+
* stylesheet) into the startup path.
|
|
8
|
+
*/
|
|
9
|
+
export { TerminalView } from '../TerminalView.tsx';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeMirror 6 theme pieces for the sidebar editor. The editor surface
|
|
3
|
+
* (background, caret, gutter) rides the DSH theme tokens so it blends with
|
|
4
|
+
* the panel in both schemes; only the syntax token colors need concrete
|
|
5
|
+
* values, and those come from the same designed palettes the app's code
|
|
6
|
+
* surfaces use — the one-dark family for dark, the one-light family for
|
|
7
|
+
* light. The scheme flip reconfigures these via a compartment (see
|
|
8
|
+
* TextEditor), so the document, undo history and scroll survive re-theming.
|
|
9
|
+
*/
|
|
10
|
+
import { Compartment } from '@codemirror/state';
|
|
11
|
+
/** Token-driven surface shared by both schemes (pure CSS values). */
|
|
12
|
+
export declare const cmSurfaceTheme: import("@codemirror/state").Extension;
|
|
13
|
+
/**
|
|
14
|
+
* A Compartment holding the two scheme-dependent extensions. Created once
|
|
15
|
+
* per editor view; a scheme flip dispatches `reconfigure(dark)` on it, so
|
|
16
|
+
* the document, undo history, scroll and keymaps survive re-theming.
|
|
17
|
+
*/
|
|
18
|
+
export declare class CmThemeCompartment {
|
|
19
|
+
private readonly compartment;
|
|
20
|
+
/** `of(...)` payload for EditorState.create. */
|
|
21
|
+
of(dark: boolean): ReturnType<Compartment['of']>;
|
|
22
|
+
/** Reconfigure for a new scheme. */
|
|
23
|
+
reconfigure(dark: boolean): ReturnType<Compartment['reconfigure']>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Append text to the current session's composer draft through the
|
|
3
|
+
* conversation service — the shared path behind the explorer's @-reference
|
|
4
|
+
* button and the viewer selection popup. The service is resolved lazily
|
|
5
|
+
* through `ctx.get` (the inject-free read the app's own plugins use); a
|
|
6
|
+
* missing service or scope degrades to a logged no-op, never a crash.
|
|
7
|
+
*/
|
|
8
|
+
import type { Context } from '../context-types.ts';
|
|
9
|
+
/**
|
|
10
|
+
* Append `text` to the session's composer draft (space-separated, like the
|
|
11
|
+
* @-mentions). Returns false — and logs — when the conversation service or
|
|
12
|
+
* the session scope is unavailable.
|
|
13
|
+
*/
|
|
14
|
+
export declare function appendToDraft(ctx: Context, sessionId: string, text: string): boolean;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Desktop-shell detection for the sidebar. Shells may stamp the render URL
|
|
3
|
+
* with `dsh-desktop-mode` / `dsh-desktop-platform` (the official Electron
|
|
4
|
+
* shell does) and expose `window.__DSH_DESKTOP_FILE_PATH__` through a
|
|
5
|
+
* preload. Parsed once per page and memoized (the URL never changes
|
|
6
|
+
* mid-session); `resetDesktopEnvForTests` clears the memo for unit tests.
|
|
7
|
+
*
|
|
8
|
+
* GEOMETRY POLICY: this module only REPORTS shell facts — it never decides
|
|
9
|
+
* how to adapt. The strip height comes from standard signals first (the
|
|
10
|
+
* Window Controls Overlay API, see wco.ts), then the documented contract
|
|
11
|
+
* parameter `dsh-desktop-titlebar-inset` (a shell may stamp the real pixels
|
|
12
|
+
* it reserves at the top), then the user's chosen scheme (preset / custom).
|
|
13
|
+
* The legacy win32-advanced 32px constant is gone from the core: it lives
|
|
14
|
+
* in the opt-in shell preset (shell-presets.ts) as a fallback for shells
|
|
15
|
+
* without the WCO API.
|
|
16
|
+
*/
|
|
17
|
+
export interface DesktopEnv {
|
|
18
|
+
/** Running inside a desktop shell (any URL stamp or preload marker). */
|
|
19
|
+
readonly desktop: boolean;
|
|
20
|
+
/** `advanced` = frameless/custom-titlebar shell; `compatibility` = native frame. */
|
|
21
|
+
readonly mode: 'compatibility' | 'advanced' | null;
|
|
22
|
+
/** Shell platform stamp ('darwin' | 'win32' | …), lowercased, or null. */
|
|
23
|
+
readonly platform: string | null;
|
|
24
|
+
/**
|
|
25
|
+
* Contract parameter `dsh-desktop-titlebar-inset`: pixels the shell
|
|
26
|
+
* reserves at the top of the web content for its own chrome (0–120,
|
|
27
|
+
* clamped; 0 when absent). Standard WCO geometry takes precedence over
|
|
28
|
+
* this whenever the API is available.
|
|
29
|
+
*/
|
|
30
|
+
readonly titlebarInset: number;
|
|
31
|
+
}
|
|
32
|
+
/** Read the shell's desktop stamps (memoized per page; SSR-safe). */
|
|
33
|
+
export declare function parseDesktopEnv(): DesktopEnv;
|
|
34
|
+
/** Test hook: drop the memo so the next parse re-reads the URL/globals. */
|
|
35
|
+
export declare function resetDesktopEnvForTests(): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure editor-load planning: the decision logic the editor host needs to
|
|
3
|
+
* turn a matched file viewer + a host fs.read result into a render action.
|
|
4
|
+
* Kept dependency-free (no React, no fetch) so the strategy dispatch is
|
|
5
|
+
* unit-testable and the wire contract (head bytes, binary flag) is pinned.
|
|
6
|
+
*
|
|
7
|
+
* The host flow this module drives:
|
|
8
|
+
* 1. `matchFileViewer(path)` picks a viewer by extension/priority.
|
|
9
|
+
* 2. `planFirstMatch` dispatches its fetchStrategy.
|
|
10
|
+
* 3. An fsRead viewer fetches through the host; `planFsReadOutcome`
|
|
11
|
+
* decides what to do with the result — including the head-based
|
|
12
|
+
* re-match that lets a `detect` viewer claim a binary the extension
|
|
13
|
+
* match could not see (the builtin NUL probe on `binary-download`).
|
|
14
|
+
*/
|
|
15
|
+
import type { FileViewerDescriptor } from './service.ts';
|
|
16
|
+
/** One host fs.read result (mirror of the wire; `head` present when binary). */
|
|
17
|
+
export interface FsReadOutcome {
|
|
18
|
+
binary: boolean;
|
|
19
|
+
content: string;
|
|
20
|
+
truncated: boolean;
|
|
21
|
+
/** base64 of the first bytes (present on binary reads; sniffing material). */
|
|
22
|
+
head?: string;
|
|
23
|
+
}
|
|
24
|
+
/** What the editor host should do next. */
|
|
25
|
+
export type EditorLoadAction =
|
|
26
|
+
/** No renderer: show the download UI. */
|
|
27
|
+
{
|
|
28
|
+
kind: 'binary';
|
|
29
|
+
}
|
|
30
|
+
/** Render `viewer`'s component with the carried payload. */
|
|
31
|
+
| {
|
|
32
|
+
kind: 'render';
|
|
33
|
+
viewer: FileViewerDescriptor;
|
|
34
|
+
content?: string;
|
|
35
|
+
truncated?: boolean;
|
|
36
|
+
mediaUrl?: string;
|
|
37
|
+
customData?: unknown;
|
|
38
|
+
}
|
|
39
|
+
/** Fetch the file through the host (fsRead strategy). */
|
|
40
|
+
| {
|
|
41
|
+
kind: 'fetchFsRead';
|
|
42
|
+
viewer: FileViewerDescriptor;
|
|
43
|
+
}
|
|
44
|
+
/** Call the viewer's load() and render with its return value. */
|
|
45
|
+
| {
|
|
46
|
+
kind: 'customLoad';
|
|
47
|
+
viewer: FileViewerDescriptor;
|
|
48
|
+
};
|
|
49
|
+
/** Decode the host's base64 head bytes into the sniffing buffer. */
|
|
50
|
+
export declare function decodeHead(headBase64: string): Uint8Array;
|
|
51
|
+
/**
|
|
52
|
+
* Dispatch one matched viewer's fetchStrategy. A missing viewer or a
|
|
53
|
+
* `binary-download` strategy both mean "no client-side renderer" → the
|
|
54
|
+
* download UI. `mediaUrlOf` builds the media URL for `mediaUrl`/`none`
|
|
55
|
+
* strategies (pure, but scope-bound — injected by the host).
|
|
56
|
+
*/
|
|
57
|
+
export declare function planFirstMatch(viewer: FileViewerDescriptor | undefined, mediaUrlOf: () => string): EditorLoadAction;
|
|
58
|
+
/**
|
|
59
|
+
* Decide what an fsRead result means for the editor.
|
|
60
|
+
* - Text: the first match stands (content is valid for any fsRead viewer).
|
|
61
|
+
* - Binary: the host head bytes enable a re-match — a `detect` viewer (e.g.
|
|
62
|
+
* a plugin sniffing a binary format) may claim the file. `custom` viewers
|
|
63
|
+
* load their own bytes; `mediaUrl`/`none` viewers render the media route;
|
|
64
|
+
* an fsRead viewer or nothing cannot render binary → download UI.
|
|
65
|
+
*/
|
|
66
|
+
export declare function planFsReadOutcome(viewer: FileViewerDescriptor, result: FsReadOutcome, rematch: (head: Uint8Array) => FileViewerDescriptor | undefined, mediaUrlOf: () => string): EditorLoadAction;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-frame task coalescing for pointer-driven interactions.
|
|
3
|
+
*
|
|
4
|
+
* Pointer streams fire several times faster than the display refresh, and
|
|
5
|
+
* applying every event (a React setState, a store reduce) re-renders whole
|
|
6
|
+
* trees at event cadence — the visible drag lag on slower CPUs (#315). This
|
|
7
|
+
* batcher keeps the LATEST scheduled task, runs it at most once per
|
|
8
|
+
* animation frame, and lets the caller flush synchronously on release (so
|
|
9
|
+
* the final pointer position is never lost to a cancelled frame).
|
|
10
|
+
*
|
|
11
|
+
* Callers compose the pending value in a ref before scheduling; the
|
|
12
|
+
* scheduled task reads that ref, so replacing the task on every event is
|
|
13
|
+
* cheap (one ref write + one rAF check).
|
|
14
|
+
*/
|
|
15
|
+
export interface FrameBatcher {
|
|
16
|
+
/** Schedule (or replace) the per-frame task. Safe to call on every event. */
|
|
17
|
+
schedule(task: () => void): void;
|
|
18
|
+
/** Cancel any pending frame and run the scheduled task synchronously
|
|
19
|
+
* (no-op when nothing is scheduled). */
|
|
20
|
+
flushNow(): void;
|
|
21
|
+
/** Cancel any pending frame and drop the task without running it. */
|
|
22
|
+
dispose(): void;
|
|
23
|
+
}
|
|
24
|
+
export declare function createFrameBatcher(): FrameBatcher;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icons the sidebar needs beyond the primitives set: a terminal glyph (the
|
|
3
|
+
* icon library has none), a diff glyph, and the two panel-toggle glyphs for
|
|
4
|
+
* the top-right cluster. Per-tab icons live on the tab descriptors
|
|
5
|
+
* (`descriptor.icon`), not in a type-keyed switch — the icon mapping was
|
|
6
|
+
* registry-ized with the tab types.
|
|
7
|
+
*/
|
|
8
|
+
import type { IconProps } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
9
|
+
/**
|
|
10
|
+
* Right-panel toggle glyph (the "侧拉" button): a frame with a filled strip
|
|
11
|
+
* along its RIGHT edge, in the app's outline style (1.5px stroke,
|
|
12
|
+
* currentColor).
|
|
13
|
+
*/
|
|
14
|
+
export declare const IconPanelRightOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
15
|
+
/**
|
|
16
|
+
* Terminal glyph in the app's outline style (1.5px stroke, currentColor):
|
|
17
|
+
* a rounded frame with a prompt chevron and underscore cursor.
|
|
18
|
+
*/
|
|
19
|
+
export declare const IconTerminalOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
20
|
+
/** Diff glyph in the app's outline style: a file frame with a plus and a minus row. */
|
|
21
|
+
export declare const IconDiffOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
22
|
+
/**
|
|
23
|
+
* Stop glyph for the background-job kill button: a filled square in the
|
|
24
|
+
* app's outline scale (16), the universal "halt this work" mark.
|
|
25
|
+
*/
|
|
26
|
+
export declare const IconStopOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
27
|
+
/** Upload glyph in the app's outline style: an arrow rising into a tray
|
|
28
|
+
* (the file-manager "upload into the workspace" action). */
|
|
29
|
+
export declare const IconUploadOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
30
|
+
/**
|
|
31
|
+
* Pin glyph in the app's outline style (1.5px stroke, currentColor): a pushpin
|
|
32
|
+
* tilted to the lower-right. Used by the PinnedRail and the tab context menu's
|
|
33
|
+
* pin entry (v0.17.0+).
|
|
34
|
+
*/
|
|
35
|
+
export declare const IconPinOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
36
|
+
/** Image viewer glyph: a picture frame with a sun and a mountain. */
|
|
37
|
+
export declare const IconImageOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
38
|
+
/** PDF viewer glyph: a document frame with the "PDF" label. */
|
|
39
|
+
export declare const IconPdfOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
40
|
+
/** Markdown viewer glyph: the classic "M with a down arrow" badge. */
|
|
41
|
+
export declare const IconMarkdownOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
42
|
+
/** HTML viewer glyph: a document frame with a "‹/›" tag pair. */
|
|
43
|
+
export declare const IconHtmlOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
44
|
+
/** Browser tab glyph: a globe with meridians. */
|
|
45
|
+
export declare const IconGlobeOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
46
|
+
/** History glyph (thread switcher): a clock with a counterclockwise arrow,
|
|
47
|
+
* in the app's outline style — the "past conversations" mark. */
|
|
48
|
+
export declare const IconHistoryOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
49
|
+
/** Save glyph (save-as-new-session): the classic floppy disk, in the app's
|
|
50
|
+
* outline style. */
|
|
51
|
+
export declare const IconSaveOutline16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
52
|
+
/**
|
|
53
|
+
* Visual Studio Code brand mark for the file-tree "open with" menu. The
|
|
54
|
+
* path is the Simple Icons `visualstudiocode` glyph (CC0 1.0,
|
|
55
|
+
* simple-icons@11.0.0 — later releases dropped it over Microsoft's brand
|
|
56
|
+
* policy, so it is inlined here rather than pulled from react-icons),
|
|
57
|
+
* rendered monochrome via currentColor to follow the active skin.
|
|
58
|
+
*/
|
|
59
|
+
export declare const IconVscode16: ({ size, className }: IconProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IME-composition key guard.
|
|
3
|
+
*
|
|
4
|
+
* While a Chinese/Japanese/Korean input method is composing (the user is
|
|
5
|
+
* picking a candidate from the IME window), every pressed key BELONGS to the
|
|
6
|
+
* input method: arrows move the candidate highlight, Enter/Space confirm the
|
|
7
|
+
* composition, Escape cancels it. Page code must not process those keys —
|
|
8
|
+
* a component that does (a number stepper calling preventDefault() on
|
|
9
|
+
* ArrowUp/ArrowDown, a submit handler reacting to Enter, ...) silently
|
|
10
|
+
* breaks the IME: candidates stop responding, the composition gets torn
|
|
11
|
+
* apart, and only bare letters come out.
|
|
12
|
+
*
|
|
13
|
+
* This guard enforces that rule at the document boundary: a capture-phase
|
|
14
|
+
* keydown/keyup listener that stops the event from propagating further
|
|
15
|
+
* whenever a composition is in progress. Because it runs in the capture
|
|
16
|
+
* phase on `document` — the outermost node — it fires BEFORE React's
|
|
17
|
+
* delegated handlers (attached at the root container) and before any native
|
|
18
|
+
* target/bubble listener, so an inlined third-party component (e.g. the
|
|
19
|
+
* Univer office UI bundled into this plugin) can never intercept
|
|
20
|
+
* composition keys. The browser's native IME processing is untouched:
|
|
21
|
+
* stopPropagation only silences page JS, not the default action.
|
|
22
|
+
*
|
|
23
|
+
* The composition signal follows the DSH core convention (InputBar's IME
|
|
24
|
+
* guard, issue #535): `isComposing` for modern engines, keyCode 229 as the
|
|
25
|
+
* legacy signal engines emit without isComposing.
|
|
26
|
+
*/
|
|
27
|
+
/** The pure decision: is this keyboard event part of an IME composition? */
|
|
28
|
+
export declare function isImeComposition(event: {
|
|
29
|
+
isComposing: boolean;
|
|
30
|
+
keyCode: number;
|
|
31
|
+
}): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Register the document-level capture guard. Returns the disposer
|
|
34
|
+
* (HMR-safe; call through `ctx.effect`).
|
|
35
|
+
*/
|
|
36
|
+
export declare function registerImeGuard(): () => void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Context } from '../context-types.ts';
|
|
2
|
+
import './layout.css';
|
|
3
|
+
/** Services required before mounting (provided by the client runtime; the
|
|
4
|
+
* locale service backs the sidebar's copy — see locales.ts). `modules`
|
|
5
|
+
* (rc.8+) is the client module system the chunk loader resolves its
|
|
6
|
+
* externals through — Cordis guards service access without inject.
|
|
7
|
+
* `remote` + `remote.session` pin this build to the 0.1.2-alpha.1+ carrier:
|
|
8
|
+
* the open-path interception wraps the session namespace, and the deep path
|
|
9
|
+
* is validated AS A WHOLE by the traceable service proxy (a bare ctx.get
|
|
10
|
+
* clears the first hop, then `cannot get property "remote.session" without
|
|
11
|
+
* inject` on the second). Cordis inject is all-required, so a carrier
|
|
12
|
+
* without these never mounts this plugin — same policy as `modules`. */
|
|
13
|
+
export declare const inject: string[];
|
|
14
|
+
/**
|
|
15
|
+
* Error boundary over the sidebar tree (root scope): a render error in the
|
|
16
|
+
* sidebar SHELL itself must never blank the page silently — the shared
|
|
17
|
+
* RenderBoundary shows a dismissible error strip and logs the stack. The
|
|
18
|
+
* per-tab scope (Sidebar.tsx) catches viewer/editor crashes first; this root
|
|
19
|
+
* boundary stays as the last resort for Workbench/shell errors.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Client plugin body.
|
|
23
|
+
* @param ctx - the client cordis context (slots, sessions).
|
|
24
|
+
*/
|
|
25
|
+
export declare function apply(ctx: Context): void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Context } from '../context-types.ts';
|
|
2
|
+
import { type SidebarStore } from './state.ts';
|
|
3
|
+
/** Open a file in the sidebar's editor (used by the intercepted row and the explorer). */
|
|
4
|
+
export declare function openSidebarFile(ctx: Context, store: SidebarStore, sessionId: string, path: string): void;
|
|
5
|
+
/**
|
|
6
|
+
* Reveal the produced files in the sidebar explorer: expand their parent
|
|
7
|
+
* directories, highlight the rows, and focus the explorer tab (expanding the
|
|
8
|
+
* hosting panel when it is collapsed). Unknown files fall back to revealing
|
|
9
|
+
* the workspace root itself.
|
|
10
|
+
*/
|
|
11
|
+
export declare function revealInExplorer(ctx: Context, store: SidebarStore, sessionId: string, files: readonly string[]): void;
|
|
12
|
+
/** The intercepted produced-files row (visual twin of the deliverables chips). */
|
|
13
|
+
export declare function SidebarProducedFiles(props: {
|
|
14
|
+
matched: readonly string[];
|
|
15
|
+
openInSidebar: (path: string) => void;
|
|
16
|
+
/** Reveal the produced files in the explorer ("Show in folder" twin). */
|
|
17
|
+
onShowInFolder: (files: readonly string[]) => void;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
/**
|
|
20
|
+
* Register the turn-tail interception (returns the disposer).
|
|
21
|
+
*
|
|
22
|
+
* The slot is a CHILD slot the host's ui-conversation declares in its
|
|
23
|
+
* `conversation.chat.node` children table (kind: chain, scope: session).
|
|
24
|
+
* Registering it directly races the declaration — the ui-slots core's
|
|
25
|
+
* load-time validation throws "not declared (a parent entry's children
|
|
26
|
+
* table must declare it)" when the parent entry is not on the ledger yet.
|
|
27
|
+
* slots.inject waits for the declaration: the callback runs synchronously
|
|
28
|
+
* when the slot is already declared, otherwise it runs inside the declaring
|
|
29
|
+
* register() call once the declaration commits; declaration collapse
|
|
30
|
+
* disposes the entry and a later declaration re-registers it. This mirrors
|
|
31
|
+
* @deepseek-ai/dsh-client-ui-deliverables' registration of the same slot.
|
|
32
|
+
*/
|
|
33
|
+
export declare function registerTurnTailInterception(ctx: Context, store: SidebarStore): () => void;
|
|
34
|
+
/**
|
|
35
|
+
* Register the chat file-open interception: wraps BOTH file-open doors so
|
|
36
|
+
* opens land in the sidebar editor instead of the Host OS — the folder-reveal
|
|
37
|
+
* gesture ("Show in folder" passes `'.'`) is the one exception, routed to the
|
|
38
|
+
* explorer. The doors: `ctx.workspaces.openPath` (the pre-0.1.2 funnel) and
|
|
39
|
+
* `ctx.remote.session.openWorkspacePath` (the 0.1.2-alpha.1 funnel, a direct
|
|
40
|
+
* RPC that left the old door dead); each is wrapped only when present, so one
|
|
41
|
+
* build intercepts baselines on either side of the migration. Gated by BOTH
|
|
42
|
+
* the `interceptOpenPath` pref and the editor tab's enable switch; declined
|
|
43
|
+
* opens fall through to the original method. Returns the disposer restoring
|
|
44
|
+
* both doors (HMR-safe).
|
|
45
|
+
*/
|
|
46
|
+
export declare function registerOpenPathInterception(ctx: Context, store: SidebarStore): () => void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax highlighting for the file editor: extension → CodeMirror language
|
|
3
|
+
* mapping. The key derivation is pure and unit-tested; the factories pull in
|
|
4
|
+
* the CodeMirror language packages (bundled into the client).
|
|
5
|
+
*/
|
|
6
|
+
import { Language, LanguageSupport } from '@codemirror/language';
|
|
7
|
+
/** The lowercased file extension of a path ('' when none). */
|
|
8
|
+
export declare function extOf(path: string): string;
|
|
9
|
+
/** Language key for an extension, or null for plain text. Pure (tested). */
|
|
10
|
+
export declare function languageKeyForExt(ext: string): string | null;
|
|
11
|
+
/** Every language key the extension table can produce (test seam). */
|
|
12
|
+
export declare function supportedLanguageKeys(): readonly string[];
|
|
13
|
+
/** The CodeMirror language support for a path, or null for plain text. */
|
|
14
|
+
export declare function languageForPath(path: string): Language | LanguageSupport | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Width written to `--dsh-sidebar-width`: the app shell gives up this much
|
|
3
|
+
* of the viewport while the sidebar is open (0 while collapsed), so the
|
|
4
|
+
* conversation column (output + composer) is squeezed instead of covered.
|
|
5
|
+
* The value is capped at the viewport so a stale persisted size (e.g.
|
|
6
|
+
* fullscreen on a bigger window) can never crush the app shell to zero.
|
|
7
|
+
*/
|
|
8
|
+
export interface LayoutPushInput {
|
|
9
|
+
narrow: boolean;
|
|
10
|
+
panelOpen: boolean;
|
|
11
|
+
width: number;
|
|
12
|
+
viewportWidth: number;
|
|
13
|
+
}
|
|
14
|
+
/** Compute the live layout-push width. Narrow drawers float and push 0. */
|
|
15
|
+
export declare function layoutPushSize(input: LayoutPushInput): number;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy chunk view wrapper: mounts a component that lives in a lazy chunk,
|
|
3
|
+
* showing a loading placeholder while the chunk script loads and an error +
|
|
4
|
+
* retry affordance on failure. Used by the built-in tab/viewer descriptors.
|
|
5
|
+
*
|
|
6
|
+
* Contract note: {@link lazyChunkComponent} returns a plain render-prop
|
|
7
|
+
* function — the descriptor contract is `component: (props) => ReactNode`,
|
|
8
|
+
* and the repo renders descriptors BOTH ways: Sidebar calls
|
|
9
|
+
* `descriptor.component(props)` directly, EditorHost renders it via
|
|
10
|
+
* `createElement`. The wrapper function body therefore contains no hooks;
|
|
11
|
+
* all state lives in the inner {@link LazyChunkView} component.
|
|
12
|
+
*/
|
|
13
|
+
import { type ComponentType, type ReactNode } from 'react';
|
|
14
|
+
import { type ChunkExports, type ChunkName } from './chunk-loader.ts';
|
|
15
|
+
/**
|
|
16
|
+
* Build a descriptor-compatible lazy wrapper for a chunk-resident component.
|
|
17
|
+
* The returned function is the descriptor `component` itself: it returns an
|
|
18
|
+
* element and never calls hooks, so both invocation styles (plain function
|
|
19
|
+
* call and createElement/JSX render) work. `pick` must be a module-level
|
|
20
|
+
* function (stable identity) — an inline lambda would re-trigger the load
|
|
21
|
+
* effect on every render.
|
|
22
|
+
* @param chunk - the chunk name (see chunk-loader.ts).
|
|
23
|
+
* @param pick - select the component from the chunk's exports.
|
|
24
|
+
*/
|
|
25
|
+
export declare function lazyChunkComponent<P extends object>(chunk: ChunkName, pick: (mod: ChunkExports) => ComponentType<P> | undefined): (props: P) => ReactNode;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat/GUI external-link interception: clicking an http(s) link that points
|
|
3
|
+
* OUTSIDE the GUI (chat messages, tool rows, prose mentions) opens the
|
|
4
|
+
* sidebar instead of a new browser tab. Gated by the caller through
|
|
5
|
+
* `takeoverEnabled(url)` — the `browserInterceptLinks` master, the URL's
|
|
6
|
+
* protocol flag (`browserInterceptHttp` / `browserInterceptHttps`) and the
|
|
7
|
+
* target tab's enable switch — and a Ctrl/Cmd/Shift/Alt-modified click
|
|
8
|
+
* always bypasses the takeover so the user can still force a real browser
|
|
9
|
+
* tab.
|
|
10
|
+
*
|
|
11
|
+
* Only the GUI's OWN document is watched — links inside the browser tab's
|
|
12
|
+
* sandboxed iframe live in another document and never bubble here (and
|
|
13
|
+
* their clicks must keep working inside the sidebar).
|
|
14
|
+
*/
|
|
15
|
+
/** The pure decision: the URL to open in the sidebar, or null to let the
|
|
16
|
+
* click fall through. Extracted so the policy is unit-testable without a
|
|
17
|
+
* DOM. `anchorHref` must be the ABSOLUTE href (`<a>.href` already is).
|
|
18
|
+
* The protocol/same-origin policy lives HERE; the prefs gates (master +
|
|
19
|
+
* protocol flags + target enablement) live in the caller's
|
|
20
|
+
* `takeoverEnabled(url)` callback. */
|
|
21
|
+
export declare function shouldInterceptLink(anchorHref: string, selfOrigin: string): string | null;
|
|
22
|
+
/** Whether a left-click may be taken over (unmodified left click only). */
|
|
23
|
+
export declare function isPlainLeftClick(event: {
|
|
24
|
+
button: number;
|
|
25
|
+
metaKey: boolean;
|
|
26
|
+
ctrlKey: boolean;
|
|
27
|
+
shiftKey: boolean;
|
|
28
|
+
altKey: boolean;
|
|
29
|
+
}): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Register the document-level click capture that funnels external links
|
|
32
|
+
* into the sidebar. Returns the disposer (HMR-safe).
|
|
33
|
+
*/
|
|
34
|
+
export declare function registerLinkInterception(opts: {
|
|
35
|
+
/** Whether the takeover may happen for THIS url (the caller's prefs
|
|
36
|
+
* gates: master switch, protocol flag, target enablement). */
|
|
37
|
+
takeoverEnabled: (url: URL) => boolean;
|
|
38
|
+
/** Open the sidebar tab at `url` (the caller resolves the target type). */
|
|
39
|
+
openInSidebar: (url: string) => void;
|
|
40
|
+
/** The GUI's own origin (window.location.origin at registration). */
|
|
41
|
+
selfOrigin: string;
|
|
42
|
+
}): () => void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ar (Arabic) dictionary for the betterSidebar namespace.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the key set of `zh` in `locales.ts`. The sidebar's `t()`
|
|
5
|
+
* consults this dict when `attachBetterLocale(store)` has been called
|
|
6
|
+
* with an active better-locale store whose `active` is `'ar'`; absent
|
|
7
|
+
* that, the existing zh/en chain runs unchanged.
|
|
8
|
+
*
|
|
9
|
+
* Translation conventions:
|
|
10
|
+
* - Modern Standard Arabic (فصحى); UI text is RTL-ready (the framework
|
|
11
|
+
* handles direction).
|
|
12
|
+
* - Git vocabulary follows standard Arabic localizations (إدراج، تثبيت، فرع).
|
|
13
|
+
* - Placeholders keep `{name}` verbatim (interpolation runs after lookup).
|
|
14
|
+
* - English brand names (VS Code, Cursor, Zed, SSH, Git, HTML, PDF, Markdown)
|
|
15
|
+
* stay as-is.
|
|
16
|
+
*/
|
|
17
|
+
/** The ar dictionary (key-set-equal to zh, enforced by the type annotation in locales.ts). */
|
|
18
|
+
export declare const ar: Record<string, string>;
|