@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.
- package/LICENSE +21 -0
- package/README.md +554 -0
- package/README_EN.md +563 -0
- package/assets/logo.svg +1 -0
- package/cordis.patch.yml +79 -0
- package/lib/client-editor.js +55744 -0
- package/lib/client-mermaid.js +208256 -0
- package/lib/client-registry.js +30378 -0
- package/lib/client-terminal.js +16894 -0
- package/lib/client.js +30378 -0
- package/lib/index.js +6897 -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/chatcode-update.d.ts +47 -0
- package/lib/types/client/AccountMenu.d.ts +1 -0
- package/lib/types/client/AiRatioSection.d.ts +3 -0
- package/lib/types/client/BrowserView.d.ts +39 -0
- package/lib/types/client/ChatcodeGate.d.ts +6 -0
- package/lib/types/client/CodingPlanModelsSettings.d.ts +9 -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/FenceErrorNotice.d.ts +5 -0
- package/lib/types/client/FileTree.d.ts +41 -0
- package/lib/types/client/FreeWindow.d.ts +29 -0
- package/lib/types/client/GitView.d.ts +12 -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/ReleaseNotesDialog.d.ts +11 -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/Sidebar.d.ts +8 -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 +27 -0
- package/lib/types/client/UpdateDialog.d.ts +10 -0
- package/lib/types/client/UpdateSettingsPanel.d.ts +1 -0
- package/lib/types/client/UpdateSettingsSection.d.ts +10 -0
- package/lib/types/client/UploadOverlay.d.ts +20 -0
- package/lib/types/client/UsageHeatmapSection.d.ts +4 -0
- package/lib/types/client/add-plugin-modal.d.ts +15 -0
- package/lib/types/client/api.d.ts +345 -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/chat-presentation.d.ts +13 -0
- package/lib/types/client/chunk-loader.d.ts +124 -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 +66 -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 +19 -0
- package/lib/types/client/intercept.d.ts +44 -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 +571 -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 +21 -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 +52 -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 +445 -0
- package/lib/types/client/session-pins.d.ts +14 -0
- package/lib/types/client/settings-nav-icon.d.ts +27 -0
- package/lib/types/client/shell-presets.d.ts +48 -0
- package/lib/types/client/split-pane.d.ts +38 -0
- package/lib/types/client/state.d.ts +480 -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/ui-tweaks/appicons.d.ts +16 -0
- package/lib/types/client/ui-tweaks/archive.d.ts +42 -0
- package/lib/types/client/ui-tweaks/branding.d.ts +45 -0
- package/lib/types/client/ui-tweaks/cachehit.d.ts +41 -0
- package/lib/types/client/ui-tweaks/gitbar.d.ts +103 -0
- package/lib/types/client/ui-tweaks/index.d.ts +279 -0
- package/lib/types/client/ui-tweaks/mcp.d.ts +28 -0
- package/lib/types/client/ui-tweaks/notifier.d.ts +125 -0
- package/lib/types/client/ui-tweaks/whale.d.ts +55 -0
- package/lib/types/client/upload.d.ts +69 -0
- package/lib/types/client/useChatcodeAccount.d.ts +10 -0
- package/lib/types/client/wco.d.ts +47 -0
- package/lib/types/codingplan.d.ts +37 -0
- package/lib/types/config.d.ts +95 -0
- package/lib/types/context-types.d.ts +540 -0
- package/lib/types/fs-operations.d.ts +30 -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/login-route.d.ts +2 -0
- package/lib/types/open-external.d.ts +24 -0
- package/lib/types/path-security.d.ts +26 -0
- package/lib/types/prefs-shared.d.ts +257 -0
- package/lib/types/pty-deps.d.ts +79 -0
- package/lib/types/pty-manager.d.ts +168 -0
- package/lib/types/tools.d.ts +34 -0
- package/lib/types/trust-fence.d.ts +24 -0
- package/lib/types/ui-tweaks/archive.d.ts +71 -0
- package/lib/types/ui-tweaks/config.d.ts +186 -0
- package/lib/types/ui-tweaks/git-web.d.ts +43 -0
- package/lib/types/ui-tweaks/git.d.ts +311 -0
- package/lib/types/ui-tweaks/index.d.ts +17 -0
- package/lib/types/ui-tweaks/mcp.d.ts +103 -0
- package/lib/types/ui-tweaks/turn-outcome.d.ts +57 -0
- package/lib/types/ui-tweaks/web.d.ts +55 -0
- package/lib/types/wire.d.ts +38 -0
- package/package.json +213 -0
- package/scripts/install.ps1 +310 -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/chatcode-update.ts +193 -0
- package/src/client/AccountMenu.tsx +177 -0
- package/src/client/AiRatioSection.module.css +329 -0
- package/src/client/AiRatioSection.tsx +292 -0
- package/src/client/BrowserView.tsx +289 -0
- package/src/client/ChatcodeGate.tsx +35 -0
- package/src/client/CodingPlanModelsSettings.module.css +118 -0
- package/src/client/CodingPlanModelsSettings.tsx +101 -0
- package/src/client/DiffTab.tsx +114 -0
- package/src/client/DiffView.tsx +305 -0
- package/src/client/EditorHost.tsx +563 -0
- package/src/client/FenceErrorNotice.tsx +40 -0
- package/src/client/FileTree.tsx +701 -0
- package/src/client/FreeWindow.tsx +337 -0
- package/src/client/GitView.tsx +722 -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/ReleaseNotesDialog.tsx +91 -0
- package/src/client/RenderBoundary.tsx +49 -0
- package/src/client/SandboxStatusBar.tsx +60 -0
- package/src/client/SideCardSection.module.css +932 -0
- package/src/client/SideCardSection.tsx +1169 -0
- package/src/client/Sidebar.tsx +1857 -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 +279 -0
- package/src/client/UpdateDialog.tsx +186 -0
- package/src/client/UpdateSettingsPanel.tsx +29 -0
- package/src/client/UpdateSettingsSection.tsx +22 -0
- package/src/client/UploadOverlay.tsx +62 -0
- package/src/client/UsageHeatmapSection.module.css +440 -0
- package/src/client/UsageHeatmapSection.tsx +301 -0
- package/src/client/add-plugin-modal.tsx +199 -0
- package/src/client/api.ts +433 -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 +275 -0
- package/src/client/builtins/viewers.tsx +125 -0
- package/src/client/chat-presentation.ts +95 -0
- package/src/client/chunk-loader.ts +350 -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 +170 -0
- package/src/client/image-types.ts +8 -0
- package/src/client/ime-guard.ts +47 -0
- package/src/client/index.tsx +501 -0
- package/src/client/intercept.tsx +172 -0
- package/src/client/lang.ts +225 -0
- package/src/client/layout-push.ts +37 -0
- package/src/client/layout.css +156 -0
- package/src/client/lazy-chunk.tsx +89 -0
- package/src/client/link-intercept.ts +73 -0
- package/src/client/locales-ar.ts +387 -0
- package/src/client/locales-de.ts +372 -0
- package/src/client/locales-fr.ts +379 -0
- package/src/client/locales-hi.ts +386 -0
- package/src/client/locales-id.ts +384 -0
- package/src/client/locales-it.ts +377 -0
- package/src/client/locales-ja.ts +486 -0
- package/src/client/locales-ko.ts +378 -0
- package/src/client/locales-nl.ts +384 -0
- package/src/client/locales-pl.ts +388 -0
- package/src/client/locales-pt.ts +369 -0
- package/src/client/locales-ru.ts +384 -0
- package/src/client/locales-sv.ts +369 -0
- package/src/client/locales-th.ts +386 -0
- package/src/client/locales-tr.ts +386 -0
- package/src/client/locales-vi.ts +386 -0
- package/src/client/locales-zh-HK.ts +401 -0
- package/src/client/locales-zh-MO.ts +401 -0
- package/src/client/locales-zh-TW.ts +401 -0
- package/src/client/locales.ts +1229 -0
- package/src/client/markdown-html.ts +331 -0
- package/src/client/markdown-images.ts +137 -0
- package/src/client/markdown-labels.tsx +31 -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 +79 -0
- package/src/client/paths.ts +63 -0
- package/src/client/pdf-types.ts +4 -0
- package/src/client/pinned.ts +184 -0
- package/src/client/plugin-settings.ts +43 -0
- package/src/client/plugins-shared.ts +29 -0
- package/src/client/plugins-tabs.ts +153 -0
- package/src/client/plugins-viewers.ts +44 -0
- package/src/client/prefs.ts +216 -0
- package/src/client/produced-files.ts +120 -0
- package/src/client/selection-payload.ts +86 -0
- package/src/client/service.ts +873 -0
- package/src/client/session-pins.tsx +334 -0
- package/src/client/settings-nav-icon.ts +55 -0
- package/src/client/shell-presets.ts +83 -0
- package/src/client/sidebar.module.css +3607 -0
- package/src/client/split-pane.tsx +333 -0
- package/src/client/state.ts +1646 -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/ui-tweaks/appicons.ts +24 -0
- package/src/client/ui-tweaks/archive.tsx +281 -0
- package/src/client/ui-tweaks/branding.tsx +232 -0
- package/src/client/ui-tweaks/cachehit.tsx +122 -0
- package/src/client/ui-tweaks/gitbar.tsx +2559 -0
- package/src/client/ui-tweaks/index.tsx +1696 -0
- package/src/client/ui-tweaks/mcp.tsx +582 -0
- package/src/client/ui-tweaks/notifier.ts +514 -0
- package/src/client/ui-tweaks/whale.tsx +171 -0
- package/src/client/upload.ts +187 -0
- package/src/client/useChatcodeAccount.ts +103 -0
- package/src/client/wco.ts +120 -0
- package/src/codingplan.ts +146 -0
- package/src/config.ts +207 -0
- package/src/context-types.ts +559 -0
- package/src/fs-operations.ts +97 -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 +1524 -0
- package/src/invariant.ts +32 -0
- package/src/login-route.ts +26 -0
- package/src/open-external.ts +90 -0
- package/src/path-security.ts +81 -0
- package/src/prefs-shared.ts +303 -0
- package/src/pty-deps.ts +241 -0
- package/src/pty-manager.ts +376 -0
- package/src/tools.ts +482 -0
- package/src/trust-fence.ts +84 -0
- package/src/ui-tweaks/archive.ts +293 -0
- package/src/ui-tweaks/config.ts +257 -0
- package/src/ui-tweaks/git-web.ts +421 -0
- package/src/ui-tweaks/git.ts +1524 -0
- package/src/ui-tweaks/index.ts +61 -0
- package/src/ui-tweaks/mcp.ts +535 -0
- package/src/ui-tweaks/turn-outcome.ts +105 -0
- package/src/ui-tweaks/web.ts +225 -0
- package/src/wire.ts +110 -0
- package/vendor/addon-fit.js +2 -0
- package/vendor/xterm.css +218 -0
- package/vendor/xterm.js +5 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pending-writes queue for the file tree's open-with config: pin toggles and
|
|
3
|
+
* (outside the settings popup) config edits land in the sidebar prefs as
|
|
4
|
+
* `pluginSettings['editor']`. Writes are serialized through one promise chain
|
|
5
|
+
* so a quick burst of pin clicks can never read a stale pluginSettings map
|
|
6
|
+
* and drop an earlier toggle; each write pushes the whole open map patch
|
|
7
|
+
* through the revision-free settings route and adopts the returned document.
|
|
8
|
+
*
|
|
9
|
+
* (The settings popup has its own serialized commit — SideCardSection's —
|
|
10
|
+
* so its rows and this helper rarely race; the shared route's last-write-wins
|
|
11
|
+
* semantics cover the uncommon overlap.)
|
|
12
|
+
*/
|
|
13
|
+
import { api } from './api.ts'
|
|
14
|
+
import { parsePrefs } from './prefs.ts'
|
|
15
|
+
import type { SidebarStore } from './state.ts'
|
|
16
|
+
|
|
17
|
+
let queue: Promise<void> = Promise.resolve()
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Merge one plugin-owned settings blob of one descriptor and persist it.
|
|
21
|
+
* @param store - the sidebar store (its prefs are replaced by the write result).
|
|
22
|
+
* @param descriptorId - the descriptor whose blob is patched ('editor' here).
|
|
23
|
+
* @param updater - pure patch function; receives a shallow copy of the blob.
|
|
24
|
+
*/
|
|
25
|
+
export function updatePluginSettings(
|
|
26
|
+
store: SidebarStore,
|
|
27
|
+
descriptorId: string,
|
|
28
|
+
updater: (blob: Record<string, unknown>) => Record<string, unknown>,
|
|
29
|
+
): void {
|
|
30
|
+
queue = queue.then(async () => {
|
|
31
|
+
const prefs = store.getPrefs()
|
|
32
|
+
const blob = prefs.pluginSettings[descriptorId] ?? {}
|
|
33
|
+
const next = updater({ ...blob })
|
|
34
|
+
const view = await api.settingsUpdate({
|
|
35
|
+
pluginSettings: { ...prefs.pluginSettings, [descriptorId]: next },
|
|
36
|
+
})
|
|
37
|
+
store.setPrefs(parsePrefs(view.value))
|
|
38
|
+
}).catch((error: unknown) => {
|
|
39
|
+
// The pin stays visually unchanged (no optimistic flip) and the menu
|
|
40
|
+
// keeps working — the write failure is logged, not surfaced.
|
|
41
|
+
console.error('open-with settings write failed', error)
|
|
42
|
+
})
|
|
43
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared vocabulary of the recommended plugin catalogs: the entry shape and
|
|
3
|
+
* the GitHub topic URL. The two catalogs live in sibling modules —
|
|
4
|
+
* `plugins-tabs.ts` (tab registrations) and `plugins-viewers.ts` (file
|
|
5
|
+
* previewer registrations) — and are shown in the two "add plugin" modals
|
|
6
|
+
* (Side card settings → the dashed cards at the end of the 侧边栏内容 /
|
|
7
|
+
* 文件预览 grids).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** The GitHub topic page listing every repo tagged `dsh-better-sidebar`. */
|
|
11
|
+
export const PLUGIN_TOPIC_URL = 'https://github.com/topics/dsh-better-sidebar'
|
|
12
|
+
|
|
13
|
+
/** One curated plugin entry (name / url / description / install script). */
|
|
14
|
+
export interface PluginEntry {
|
|
15
|
+
/** Unique id (the npm package name). */
|
|
16
|
+
id: string
|
|
17
|
+
/** Short display name. */
|
|
18
|
+
name: string
|
|
19
|
+
/** GitHub repository URL. */
|
|
20
|
+
url: string
|
|
21
|
+
/** One-line description (i18n friendly: string or () => string). */
|
|
22
|
+
description: string | (() => string)
|
|
23
|
+
/** Optional catalog group heading (i18n friendly); entries without one
|
|
24
|
+
* render under the plain list (a flat catalog stays flat). */
|
|
25
|
+
category?: string | (() => string)
|
|
26
|
+
/** The full shell command pre-filled into the install terminal (not
|
|
27
|
+
* executed until the user presses Enter). */
|
|
28
|
+
install: string
|
|
29
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in catalog of TAB-registration plugins (sidebar pages),
|
|
3
|
+
* shown in the "add tab plugin" modal (Side card settings → 侧边栏内容 grid
|
|
4
|
+
* → the dashed card). Adding an entry: append one object here (unique
|
|
5
|
+
* `id` = npm package name, `url` = GitHub repo, `description` =
|
|
6
|
+
* i18n-friendly (add a `pluginXxxDesc` key in locales.ts), `install` = the
|
|
7
|
+
* full one-line install script — it starts with `cd ~/.chatcode-cli` so the install
|
|
8
|
+
* runs with the ChatCode CLI home as the working directory). Data integrity is
|
|
9
|
+
* guarded by `tests/plugin-list.spec.ts`.
|
|
10
|
+
*/
|
|
11
|
+
import { t } from './locales.ts'
|
|
12
|
+
import type { PluginEntry } from './plugins-shared.ts'
|
|
13
|
+
|
|
14
|
+
/** Tab-registration plugins (alphabetical order). */
|
|
15
|
+
export const builtinTabPlugins: readonly PluginEntry[] = [
|
|
16
|
+
{
|
|
17
|
+
id: '@dsh-external/dsh-sentinel',
|
|
18
|
+
name: 'dsh-sentinel 唤醒系统',
|
|
19
|
+
url: 'https://github.com/fuhefei/dsh-sentinel',
|
|
20
|
+
description: () => t('pluginSentinelDesc'),
|
|
21
|
+
// The official one-line bundle-channel install (git source, build
|
|
22
|
+
// artifacts committed — no build step needed). The `github:…` form is
|
|
23
|
+
// the upstream's documented command, `cd ~/.chatcode-cli` keeps the profile
|
|
24
|
+
// context consistent with the other entries.
|
|
25
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add "github:fuhefei/dsh-sentinel#v0.7.0"',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: '@dsh-external/ego-browser',
|
|
29
|
+
name: 'ego-browser Agent 浏览器',
|
|
30
|
+
url: 'https://github.com/Fisfzy/ego-browser',
|
|
31
|
+
description: () => t('pluginEgoBrowserDesc'),
|
|
32
|
+
// Registers a sidebar tab for the agent browser; optional peer of
|
|
33
|
+
// better-sidebar (auto-tab when present, floating bubble when not).
|
|
34
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add git+https://github.com/Fisfzy/ego-browser.git',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'dsh-better-overleaf',
|
|
38
|
+
name: 'dsh-better-overleaf Overleaf 标签页',
|
|
39
|
+
url: 'https://github.com/Hoemr/dsh-better-overleaf',
|
|
40
|
+
description: () => t('pluginBetterOverleafDesc'),
|
|
41
|
+
// Published on npm; peer-depends on dsh-better-sidebar (Overleaf tab),
|
|
42
|
+
// so the install line installs the prerequisite first.
|
|
43
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add dsh-better-overleaf',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'dsh-docs-panel',
|
|
47
|
+
name: 'dsh-docs-panel 全局文档',
|
|
48
|
+
url: 'https://github.com/mlosun/dsh-docs-panel',
|
|
49
|
+
description: () => t('pluginDocsPanelDesc'),
|
|
50
|
+
// dsh-docs-panel hard-depends on dsh-better-sidebar (required peer), so
|
|
51
|
+
// the install line installs the prerequisite first, then the plugin.
|
|
52
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add dsh-docs-panel',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'dsh-flowglass',
|
|
56
|
+
name: 'dsh-flowglass 流镜',
|
|
57
|
+
url: 'https://github.com/Iwctwbh/dsh-flowglass',
|
|
58
|
+
description: () => t('pluginFlowglassDesc'),
|
|
59
|
+
// Flowglass keeps its standalone drawer as a fallback and registers the
|
|
60
|
+
// native tab automatically when better-sidebar is present.
|
|
61
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add dsh-flowglass',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'dsh-git-forge',
|
|
65
|
+
name: 'dsh-git-forge Git 凭据',
|
|
66
|
+
url: 'https://github.com/thirsty5034/dsh-git-forge',
|
|
67
|
+
description: () => t('pluginGitForgeDesc'),
|
|
68
|
+
// Peer-depends on dsh-better-sidebar (Git Forge tab). Install the
|
|
69
|
+
// prerequisite first; package is GitHub-sourced until npm publish.
|
|
70
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add "dsh-git-forge@github:thirsty5034/dsh-git-forge"',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: 'dsh-git-remotes',
|
|
74
|
+
name: 'dsh-git-remotes Git 远程',
|
|
75
|
+
url: 'https://github.com/yq04/dsh-git-remotes',
|
|
76
|
+
description: () => t('pluginGitRemotesDesc'),
|
|
77
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add git+https://github.com/yq04/dsh-git-remotes.git',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'dsh-github-workbench',
|
|
81
|
+
name: 'dsh-github-workbench GitHub 工作台',
|
|
82
|
+
url: 'https://github.com/meyaomiao/dsh-github-workbench',
|
|
83
|
+
description: () => t('pluginGithubWorkbenchDesc'),
|
|
84
|
+
// Full GitHub workbench tab: remote repo tree + Issues/PRs/Actions tabs
|
|
85
|
+
// with write support (create/comment/merge/re-run). lib/ is committed,
|
|
86
|
+
// so the pinned github:-form install works without a local build.
|
|
87
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add "github:meyaomiao/dsh-github-workbench#v0.1.0"',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'dsh-sidebar-qa',
|
|
91
|
+
name: 'dsh-sidebar-qa 划选追问',
|
|
92
|
+
url: 'https://github.com/ChenRuoT/dsh-sidebar-qa',
|
|
93
|
+
description: () => t('pluginSidebarQaDesc'),
|
|
94
|
+
// dsh-sidebar-qa hard-depends on dsh-better-sidebar (required peer), so
|
|
95
|
+
// the install line installs the prerequisite first, then the plugin.
|
|
96
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add git+https://github.com/ChenRuoT/dsh-sidebar-qa.git',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 'dsh-sidenote',
|
|
100
|
+
name: 'dsh-sidenote 侧边聊天',
|
|
101
|
+
url: 'https://github.com/g-yixuan/dsh-sidenote',
|
|
102
|
+
description: () => t('pluginSidenoteDesc'),
|
|
103
|
+
// dsh-sidenote hard-depends on dsh-better-sidebar (required peer), so
|
|
104
|
+
// the install line installs the prerequisite first, then the plugin.
|
|
105
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add dsh-sidenote',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 'dsh-server-deck',
|
|
109
|
+
name: 'dsh-server-deck 服务器甲板',
|
|
110
|
+
url: 'https://github.com/meyaomiao/DSH-server-deck',
|
|
111
|
+
description: () => t('pluginServerDeckDesc'),
|
|
112
|
+
// Published on npm; dual-mount like flowglass — registers the native
|
|
113
|
+
// "Servers" tab when better-sidebar is present, standalone drawer
|
|
114
|
+
// otherwise. Install the prerequisite first.
|
|
115
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add dsh-server-deck@latest',
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: 'dsh-suhuang-scroll',
|
|
119
|
+
name: 'dsh-suhuang-scroll 苏黄共阅',
|
|
120
|
+
url: 'https://github.com/YZDame/dsh-suhuang-scroll',
|
|
121
|
+
description: () => t('pluginSuhuangScrollDesc'),
|
|
122
|
+
// Suhuang Scroll is a DSH Web plugin whose runtime console registers in
|
|
123
|
+
// better-sidebar. Install the sidebar prerequisite before the npm package.
|
|
124
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add dsh-suhuang-scroll',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: 'dsh-ssh-tunnel',
|
|
128
|
+
name: 'dsh-ssh-tunnel SSH 隧道',
|
|
129
|
+
url: 'https://github.com/thirsty5034/dsh-ssh-tunnel',
|
|
130
|
+
description: () => t('pluginSshTunnelDesc'),
|
|
131
|
+
// Peer-depends on dsh-better-sidebar (SSH Tunnel tab + center terminal/SFTP).
|
|
132
|
+
// Install the prerequisite first; package is GitHub-sourced until npm publish.
|
|
133
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add "dsh-ssh-tunnel@github:thirsty5034/dsh-ssh-tunnel"',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: 'dsh-turn-review',
|
|
137
|
+
name: 'dsh-turn-review 本轮审查',
|
|
138
|
+
url: 'https://github.com/yq04/dsh-turn-review',
|
|
139
|
+
description: () => t('pluginTurnReviewDesc'),
|
|
140
|
+
// Needs dsh-better-sidebar (optional peer) for the tab; no model tools.
|
|
141
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add git+https://github.com/yq04/dsh-turn-review.git',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: 'dsh-bilingual-reader',
|
|
145
|
+
name: 'dsh-bilingual-reader 双语阅读',
|
|
146
|
+
url: 'https://github.com/Johnblur/dsh-bilingual-reader',
|
|
147
|
+
description: () => t('pluginBilingualReaderDesc'),
|
|
148
|
+
// Bilingual paper reading: a native-PDF tab with LLM selection translation,
|
|
149
|
+
// isolated from the main conversation context. Hard-depends on the
|
|
150
|
+
// better-sidebar tab service, so install the prerequisite first.
|
|
151
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-better-sidebar && cco plugin --profile web add github:Johnblur/dsh-bilingual-reader',
|
|
152
|
+
},
|
|
153
|
+
]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in catalog of FILE-PREVIEWER plugins (file-type previewers),
|
|
3
|
+
* shown in the "add preview plugin" modal (Side card settings → 文件预览
|
|
4
|
+
* grid → the dashed card). Adding an entry: append one object here (unique
|
|
5
|
+
* `id` = npm package name, `url` = GitHub repo, `description` =
|
|
6
|
+
* i18n-friendly, `install` = the full shell command pre-filled into the
|
|
7
|
+
* install terminal — it starts with `cd ~/.chatcode-cli` so the install runs with
|
|
8
|
+
* the ChatCode CLI home as the working directory). Data integrity is guarded by
|
|
9
|
+
* `tests/plugin-list.spec.ts`.
|
|
10
|
+
*/
|
|
11
|
+
import { t } from './locales.ts'
|
|
12
|
+
import type { PluginEntry } from './plugins-shared.ts'
|
|
13
|
+
|
|
14
|
+
/** File-previewer plugins (alphabetical order). */
|
|
15
|
+
export const builtinViewerPlugins: readonly PluginEntry[] = [
|
|
16
|
+
{
|
|
17
|
+
id: '@huanlin/dsh-plugin-better-sidebar-plugin-office',
|
|
18
|
+
name: 'Office 预览插件',
|
|
19
|
+
url: 'https://github.com/HuanLinOTO/dsh-plugin-better-sidebar-plugin-office',
|
|
20
|
+
description: () => t('pluginOfficeDesc'),
|
|
21
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add @huanlin/dsh-plugin-better-sidebar-plugin-office',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'dsh-md-export',
|
|
25
|
+
name: 'Markdown 导出插件',
|
|
26
|
+
url: 'https://github.com/AnakinCao/dsh-md-export',
|
|
27
|
+
description: () => t('pluginMdExportDesc'),
|
|
28
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-md-export',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: 'dsh-code-nav',
|
|
32
|
+
name: '代码预览导航',
|
|
33
|
+
url: 'https://github.com/AnakinCao/dsh-code-nav',
|
|
34
|
+
description: () => t('pluginCodeNavDesc'),
|
|
35
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add https://github.com/AnakinCao/dsh-code-nav.git',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'dsh-video-preview',
|
|
39
|
+
name: '视频预览插件',
|
|
40
|
+
url: 'https://github.com/zemul/dsh-video-preview',
|
|
41
|
+
description: () => t('pluginVideoPreviewDesc'),
|
|
42
|
+
install: 'cd ~/.chatcode-cli && cco plugin --profile web add dsh-video-preview',
|
|
43
|
+
},
|
|
44
|
+
]
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side read of the user-facing "Side card" preferences. The host owns
|
|
3
|
+
* the namespace through the settings seam (in-process); the DSH settings RPC
|
|
4
|
+
* domain only serves allowlisted namespaces to configuration clients, so the
|
|
5
|
+
* client reads and writes THIS namespace through the plugin's own fenced
|
|
6
|
+
* /sidebar routes instead (api.settingsGet/settingsUpdate). Any failure
|
|
7
|
+
* (route rejected, namespace absent, a field of the wrong type, a value out
|
|
8
|
+
* of the contract range) falls back to the schema defaults — the side card
|
|
9
|
+
* must keep working exactly as composed when the settings surface is missing.
|
|
10
|
+
*/
|
|
11
|
+
import type { api } from './api.ts'
|
|
12
|
+
import {
|
|
13
|
+
clampTerminalFontSize,
|
|
14
|
+
clampTitleBarStrip,
|
|
15
|
+
clampWidthPercent,
|
|
16
|
+
SIDEBAR_PREFS_DEFAULTS,
|
|
17
|
+
TITLE_BAR_SCHEMES,
|
|
18
|
+
TITLE_BAR_STRIP_DEFAULT,
|
|
19
|
+
type SidebarPrefs,
|
|
20
|
+
type TitleBarScheme,
|
|
21
|
+
} from '../prefs-shared.ts'
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
SIDEBAR_PREFS_DEFAULTS,
|
|
25
|
+
TITLE_BAR_SCHEMES,
|
|
26
|
+
TITLE_BAR_STRIP_DEFAULT,
|
|
27
|
+
clampTerminalFontSize,
|
|
28
|
+
clampTitleBarStrip,
|
|
29
|
+
clampWidthPercent,
|
|
30
|
+
}
|
|
31
|
+
export type { SidebarPrefs, TitleBarScheme }
|
|
32
|
+
|
|
33
|
+
/** The settings wire face the preferences need (a subset of the plugin api). */
|
|
34
|
+
export type SidebarSettingsClient = Pick<typeof api, 'settingsGet' | 'settingsUpdate'>
|
|
35
|
+
|
|
36
|
+
/** Validate one raw resolved value into {@link SidebarPrefs}. Used for the
|
|
37
|
+
* settings.get payload AND the settings.update response (both carry the
|
|
38
|
+
* layered resolved value); any malformed field falls back to its default.
|
|
39
|
+
* @param value - the raw resolved section from the settings wire.
|
|
40
|
+
* @returns validated prefs (always well-formed).
|
|
41
|
+
*/
|
|
42
|
+
export function parsePrefs(value: unknown): SidebarPrefs {
|
|
43
|
+
if (value === null || typeof value !== 'object') return { ...SIDEBAR_PREFS_DEFAULTS }
|
|
44
|
+
const record = value as Record<string, unknown>
|
|
45
|
+
return {
|
|
46
|
+
openByDefault: typeof record.openByDefault === 'boolean'
|
|
47
|
+
? record.openByDefault
|
|
48
|
+
: SIDEBAR_PREFS_DEFAULTS.openByDefault,
|
|
49
|
+
defaultWidthPercent: typeof record.defaultWidthPercent === 'number' && Number.isFinite(record.defaultWidthPercent)
|
|
50
|
+
? clampWidthPercent(record.defaultWidthPercent)
|
|
51
|
+
: SIDEBAR_PREFS_DEFAULTS.defaultWidthPercent,
|
|
52
|
+
autoOpenSubagent: typeof record.autoOpenSubagent === 'boolean'
|
|
53
|
+
? record.autoOpenSubagent
|
|
54
|
+
: SIDEBAR_PREFS_DEFAULTS.autoOpenSubagent,
|
|
55
|
+
autoOpenJobs: typeof record.autoOpenJobs === 'boolean'
|
|
56
|
+
? record.autoOpenJobs
|
|
57
|
+
: SIDEBAR_PREFS_DEFAULTS.autoOpenJobs,
|
|
58
|
+
agentTerminalTools: typeof record.agentTerminalTools === 'boolean'
|
|
59
|
+
? record.agentTerminalTools
|
|
60
|
+
: SIDEBAR_PREFS_DEFAULTS.agentTerminalTools,
|
|
61
|
+
agentOpenTools: typeof record.agentOpenTools === 'boolean'
|
|
62
|
+
? record.agentOpenTools
|
|
63
|
+
: SIDEBAR_PREFS_DEFAULTS.agentOpenTools,
|
|
64
|
+
bottomPanelAutoTerminal: typeof record.bottomPanelAutoTerminal === 'boolean'
|
|
65
|
+
? record.bottomPanelAutoTerminal
|
|
66
|
+
: SIDEBAR_PREFS_DEFAULTS.bottomPanelAutoTerminal,
|
|
67
|
+
terminalFontFamily: typeof record.terminalFontFamily === 'string'
|
|
68
|
+
? record.terminalFontFamily
|
|
69
|
+
: SIDEBAR_PREFS_DEFAULTS.terminalFontFamily,
|
|
70
|
+
terminalShell: typeof record.terminalShell === 'string'
|
|
71
|
+
? record.terminalShell
|
|
72
|
+
: SIDEBAR_PREFS_DEFAULTS.terminalShell,
|
|
73
|
+
terminalShellArgs: typeof record.terminalShellArgs === 'string'
|
|
74
|
+
? record.terminalShellArgs
|
|
75
|
+
: SIDEBAR_PREFS_DEFAULTS.terminalShellArgs,
|
|
76
|
+
terminalFontSize: typeof record.terminalFontSize === 'number' && Number.isFinite(record.terminalFontSize)
|
|
77
|
+
? clampTerminalFontSize(record.terminalFontSize)
|
|
78
|
+
: SIDEBAR_PREFS_DEFAULTS.terminalFontSize,
|
|
79
|
+
interceptOpenPath: typeof record.interceptOpenPath === 'boolean'
|
|
80
|
+
? record.interceptOpenPath
|
|
81
|
+
: SIDEBAR_PREFS_DEFAULTS.interceptOpenPath,
|
|
82
|
+
editorExplorer: typeof record.editorExplorer === 'boolean'
|
|
83
|
+
? record.editorExplorer
|
|
84
|
+
: SIDEBAR_PREFS_DEFAULTS.editorExplorer,
|
|
85
|
+
workspaceFence: typeof record.workspaceFence === 'boolean'
|
|
86
|
+
? record.workspaceFence
|
|
87
|
+
: SIDEBAR_PREFS_DEFAULTS.workspaceFence,
|
|
88
|
+
// The title-bar scheme (auto | web | preset | custom). The schema
|
|
89
|
+
// declares the field WITHOUT a default, so documents written by older
|
|
90
|
+
// plugin versions resolve without it — migrate from the legacy fields:
|
|
91
|
+
// a document that ALREADY HAS VALUES (the manual compat flag on, or a
|
|
92
|
+
// non-default strip px — both only reachable through the old gear
|
|
93
|
+
// popup) maps to the `custom` scheme so the user's numbers keep
|
|
94
|
+
// working; a pristine document keeps the conservative `auto` scheme.
|
|
95
|
+
titleBarScheme: isTitleBarScheme(record.titleBarScheme)
|
|
96
|
+
? record.titleBarScheme
|
|
97
|
+
: (record.titleBarCompat === true || hasLegacyStripValue(record.titleBarStripPx) ? 'custom' : 'auto'),
|
|
98
|
+
titleBarPresetId: typeof record.titleBarPresetId === 'string'
|
|
99
|
+
? record.titleBarPresetId
|
|
100
|
+
: SIDEBAR_PREFS_DEFAULTS.titleBarPresetId,
|
|
101
|
+
customCss: typeof record.customCss === 'string'
|
|
102
|
+
? record.customCss
|
|
103
|
+
: SIDEBAR_PREFS_DEFAULTS.customCss,
|
|
104
|
+
titleBarCompat: typeof record.titleBarCompat === 'boolean'
|
|
105
|
+
? record.titleBarCompat
|
|
106
|
+
: SIDEBAR_PREFS_DEFAULTS.titleBarCompat,
|
|
107
|
+
titleBarStripPx: typeof record.titleBarStripPx === 'number' && Number.isFinite(record.titleBarStripPx)
|
|
108
|
+
? clampTitleBarStrip(record.titleBarStripPx)
|
|
109
|
+
: SIDEBAR_PREFS_DEFAULTS.titleBarStripPx,
|
|
110
|
+
htmlViewerNoSandbox: typeof record.htmlViewerNoSandbox === 'boolean'
|
|
111
|
+
? record.htmlViewerNoSandbox
|
|
112
|
+
: SIDEBAR_PREFS_DEFAULTS.htmlViewerNoSandbox,
|
|
113
|
+
htmlViewerDefaultUnsafe: typeof record.htmlViewerDefaultUnsafe === 'boolean'
|
|
114
|
+
? record.htmlViewerDefaultUnsafe
|
|
115
|
+
: SIDEBAR_PREFS_DEFAULTS.htmlViewerDefaultUnsafe,
|
|
116
|
+
browserNoSandbox: typeof record.browserNoSandbox === 'boolean'
|
|
117
|
+
? record.browserNoSandbox
|
|
118
|
+
: SIDEBAR_PREFS_DEFAULTS.browserNoSandbox,
|
|
119
|
+
browserInterceptLinks: typeof record.browserInterceptLinks === 'boolean'
|
|
120
|
+
? record.browserInterceptLinks
|
|
121
|
+
: SIDEBAR_PREFS_DEFAULTS.browserInterceptLinks,
|
|
122
|
+
browserInterceptHttp: typeof record.browserInterceptHttp === 'boolean'
|
|
123
|
+
? record.browserInterceptHttp
|
|
124
|
+
: SIDEBAR_PREFS_DEFAULTS.browserInterceptHttp,
|
|
125
|
+
browserInterceptHttps: typeof record.browserInterceptHttps === 'boolean'
|
|
126
|
+
? record.browserInterceptHttps
|
|
127
|
+
: SIDEBAR_PREFS_DEFAULTS.browserInterceptHttps,
|
|
128
|
+
browserAllowedLoopback: typeof record.browserAllowedLoopback === 'string'
|
|
129
|
+
? record.browserAllowedLoopback
|
|
130
|
+
: SIDEBAR_PREFS_DEFAULTS.browserAllowedLoopback,
|
|
131
|
+
tabsEnabled: booleanMapOf(record.tabsEnabled),
|
|
132
|
+
viewersEnabled: booleanMapOf(record.viewersEnabled),
|
|
133
|
+
pluginSettings: pluginSettingsMapOf(record.pluginSettings),
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Validate the plugin-owned settings map (v0.12.0+): `{ descriptorId: { key:
|
|
139
|
+
* value } }`, nested open maps. Any non-object value (or a malformed whole)
|
|
140
|
+
* falls back to the empty map — the schema defaults already guard the wire
|
|
141
|
+
* shape, this is the client's second line.
|
|
142
|
+
*/
|
|
143
|
+
function pluginSettingsMapOf(value: unknown): Record<string, Record<string, unknown>> {
|
|
144
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) return {}
|
|
145
|
+
const out: Record<string, Record<string, unknown>> = {}
|
|
146
|
+
for (const [id, blob] of Object.entries(value as Record<string, unknown>)) {
|
|
147
|
+
if (blob !== null && typeof blob === 'object' && !Array.isArray(blob)) {
|
|
148
|
+
out[id] = blob as Record<string, unknown>
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return out
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Validate one enable-switch map (per-tab / per-viewer). Only boolean values
|
|
156
|
+
* survive; a non-object or a non-boolean entry falls back to the empty map /
|
|
157
|
+
* drops the entry — an absent key means the feature stays enabled.
|
|
158
|
+
*/
|
|
159
|
+
function booleanMapOf(value: unknown): Record<string, boolean> {
|
|
160
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) return {}
|
|
161
|
+
const out: Record<string, boolean> = {}
|
|
162
|
+
for (const [key, item] of Object.entries(value as Record<string, unknown>)) {
|
|
163
|
+
if (typeof item === 'boolean') out[key] = item
|
|
164
|
+
}
|
|
165
|
+
return out
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Type guard for the title-bar scheme union (anything else falls back). */
|
|
169
|
+
function isTitleBarScheme(value: unknown): value is TitleBarScheme {
|
|
170
|
+
return typeof value === 'string' && (TITLE_BAR_SCHEMES as readonly string[]).includes(value)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Whether the legacy document carries an explicit strip value (only
|
|
175
|
+
* reachable through the old gear popup): a stored number different from the
|
|
176
|
+
* default counts as "the user already configured something" and migrates to
|
|
177
|
+
* the `custom` scheme.
|
|
178
|
+
*/
|
|
179
|
+
function hasLegacyStripValue(value: unknown): boolean {
|
|
180
|
+
return typeof value === 'number' && Number.isFinite(value) && value !== TITLE_BAR_STRIP_DEFAULT
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Read the resolved side card preferences through the plugin's settings route.
|
|
185
|
+
* @param settings - the settings wire face (the plugin api by default).
|
|
186
|
+
* @returns validated prefs, or the schema defaults when the route rejects,
|
|
187
|
+
* the namespace is absent, or a stored value violates the contract.
|
|
188
|
+
*/
|
|
189
|
+
export async function loadPrefs(settings: SidebarSettingsClient): Promise<SidebarPrefs> {
|
|
190
|
+
try {
|
|
191
|
+
const view = await settings.settingsGet()
|
|
192
|
+
return parsePrefs(view.value)
|
|
193
|
+
} catch {
|
|
194
|
+
// Transport/fence rejection or a malformed response: keep the defaults.
|
|
195
|
+
return { ...SIDEBAR_PREFS_DEFAULTS }
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Read the external-disable flag from the same settings route: the
|
|
201
|
+
* dsh-web-ui family's aionui-panel provider choice. True only when the host
|
|
202
|
+
* resolved `aionui-panel.rightPanel` to 'aionui-panel' — while true the
|
|
203
|
+
* sidebar must not mount (the two right panels are mutually exclusive). Any
|
|
204
|
+
* failure (route rejected, aionui absent, malformed response) reads false,
|
|
205
|
+
* so a missing family never hides the sidebar.
|
|
206
|
+
* @param settings - the settings wire face (the plugin api by default).
|
|
207
|
+
* @returns the external-disable flag (false on any failure).
|
|
208
|
+
*/
|
|
209
|
+
export async function loadExternalDisable(settings: SidebarSettingsClient): Promise<boolean> {
|
|
210
|
+
try {
|
|
211
|
+
const view = await settings.settingsGet()
|
|
212
|
+
return view.externalDisable === true
|
|
213
|
+
} catch {
|
|
214
|
+
return false
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure derivation of one turn's produced files from finalized conversation
|
|
3
|
+
* nodes — a structural replica of ui-deliverables' `producedForClosing`
|
|
4
|
+
* (the mutation tools' follow-along `locations`, by render intent: a diff
|
|
5
|
+
* card or a generic edit card; reads/deletes/failures produce nothing).
|
|
6
|
+
* Kept dependency-free so the takeover logic is unit-testable and the
|
|
7
|
+
* replica is easy to diff against upstream when it drifts.
|
|
8
|
+
*/
|
|
9
|
+
import { isAbsolutePath } from './paths.ts'
|
|
10
|
+
|
|
11
|
+
/** Paths a tool-result view reports as produced, by render intent. */
|
|
12
|
+
export function producedPaths(view: unknown): readonly string[] {
|
|
13
|
+
if (view === null || typeof view !== 'object') return []
|
|
14
|
+
const record = view as { card?: unknown; kind?: unknown; locations?: unknown }
|
|
15
|
+
const isEdit = record.card === 'diff' || (record.card === 'generic' && record.kind === 'edit')
|
|
16
|
+
if (!isEdit) return []
|
|
17
|
+
if (!Array.isArray(record.locations)) return []
|
|
18
|
+
const paths: string[] = []
|
|
19
|
+
for (const location of record.locations) {
|
|
20
|
+
if (location !== null && typeof location === 'object' && typeof (location as { path?: unknown }).path === 'string') {
|
|
21
|
+
paths.push((location as { path: string }).path)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return paths
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Files produced by the turn the assistant at `seq` closes. Accumulation
|
|
29
|
+
* resets on turn boundaries (a user message, or a node reporting a different
|
|
30
|
+
* turn number); paths keep first-seen order and appear once.
|
|
31
|
+
* @param nodes - snapshot nodes in surface order (structural, unknown-safe).
|
|
32
|
+
* @param seq - the closing assistant's seq (the render site's anchor).
|
|
33
|
+
* @returns produced paths; empty when the turn wrote nothing.
|
|
34
|
+
*/
|
|
35
|
+
export function producedForClosing(nodes: readonly unknown[], seq: number): readonly string[] {
|
|
36
|
+
let pending: string[] = []
|
|
37
|
+
let seen = new Set<string>()
|
|
38
|
+
let turn: number | undefined
|
|
39
|
+
for (const node of nodes) {
|
|
40
|
+
if (node === null || typeof node !== 'object') continue
|
|
41
|
+
const record = node as { kind?: unknown; isError?: unknown; callView?: unknown; turn?: unknown; seq?: unknown }
|
|
42
|
+
if (record.kind === 'tool-result') {
|
|
43
|
+
if (record.isError === true) continue
|
|
44
|
+
for (const path of producedPaths(record.callView)) {
|
|
45
|
+
if (seen.has(path)) continue
|
|
46
|
+
seen.add(path)
|
|
47
|
+
pending.push(path)
|
|
48
|
+
}
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
if (record.kind === 'user') {
|
|
52
|
+
turn = undefined
|
|
53
|
+
pending = []
|
|
54
|
+
seen = new Set()
|
|
55
|
+
} else if (typeof record.turn === 'number') {
|
|
56
|
+
if (turn !== undefined && record.turn !== turn) {
|
|
57
|
+
pending = []
|
|
58
|
+
seen = new Set()
|
|
59
|
+
}
|
|
60
|
+
turn = record.turn
|
|
61
|
+
}
|
|
62
|
+
if (record.kind === 'assistant' && record.seq === seq) return pending
|
|
63
|
+
}
|
|
64
|
+
return []
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Claim the turn-tail chain only when the closing turn produced files.
|
|
69
|
+
*
|
|
70
|
+
* The authoritative source is the engine Turn data — the same value
|
|
71
|
+
* ui-deliverables reads (`owner.turn.data.get('deliverables')`): a
|
|
72
|
+
* `{ produced: [{ seq, path }, ...] }` record accumulated per Turn. The
|
|
73
|
+
* node-based replica below stays as a fallback for compositions that do not
|
|
74
|
+
* publish it.
|
|
75
|
+
* @param owner - the turn-tail owner currency ({turn, seq, openFile}).
|
|
76
|
+
* @returns produced paths as the matched value, or null to decline.
|
|
77
|
+
*/
|
|
78
|
+
export function selectProducedFiles(owner: unknown): readonly string[] | null {
|
|
79
|
+
const record = owner as {
|
|
80
|
+
turn?: { data?: { get?: (key: string) => unknown } }
|
|
81
|
+
nodes?: unknown
|
|
82
|
+
seq?: unknown
|
|
83
|
+
} | null
|
|
84
|
+
if (record === null || typeof record !== 'object') return null
|
|
85
|
+
const seq = typeof record.seq === 'number' ? record.seq : Number.POSITIVE_INFINITY
|
|
86
|
+
const data = record.turn?.data?.get?.('deliverables') as
|
|
87
|
+
| { produced?: unknown }
|
|
88
|
+
| null
|
|
89
|
+
| undefined
|
|
90
|
+
if (data !== null && typeof data === 'object' && Array.isArray(data.produced)) {
|
|
91
|
+
const paths: string[] = []
|
|
92
|
+
const seen = new Set<string>()
|
|
93
|
+
for (const item of data.produced) {
|
|
94
|
+
if (item === null || typeof item !== 'object') continue
|
|
95
|
+
const produced = item as { path?: unknown; seq?: unknown }
|
|
96
|
+
if (typeof produced.path !== 'string' || produced.path === '') continue
|
|
97
|
+
if (typeof produced.seq === 'number' && produced.seq > seq) continue
|
|
98
|
+
if (seen.has(produced.path)) continue
|
|
99
|
+
seen.add(produced.path)
|
|
100
|
+
paths.push(produced.path)
|
|
101
|
+
}
|
|
102
|
+
return paths.length === 0 ? null : paths
|
|
103
|
+
}
|
|
104
|
+
if (!Array.isArray(record.nodes)) return null
|
|
105
|
+
const paths = producedForClosing(record.nodes, seq)
|
|
106
|
+
return paths.length === 0 ? null : paths
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Resolve a (possibly relative) path against the session cwd for the sidebar.
|
|
111
|
+
* Absolute detection mirrors the host (see client/paths.isAbsolutePath):
|
|
112
|
+
* POSIX roots, drive letters and UNC shares must not be joined onto the cwd.
|
|
113
|
+
*/
|
|
114
|
+
export function resolveSidebarPath(cwd: string | undefined, path: string): string {
|
|
115
|
+
if (isAbsolutePath(path)) return path
|
|
116
|
+
const base = cwd ?? ''
|
|
117
|
+
if (base === '') return path
|
|
118
|
+
const separator = base.includes('\\') ? '\\' : '/'
|
|
119
|
+
return `${base.replace(/[\\/]+$/, '')}${separator}${path}`
|
|
120
|
+
}
|