@civilization/dsh-workspace-files 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -368,23 +368,12 @@ window.__ModuleLoader__.load({
368
368
  key: OFFICIAL_FILES_TAB_ID
369
369
  }, WorkspaceFilesTabTitle)), "dsh-workspace-files: official tab title");
370
370
  }
371
- const registerSettingsCard = (targetCtx) => {
372
- if (!targetCtx?.slots) return;
373
- targetCtx.effect?.(() => targetCtx.slots.inject("settings.plugin.item", function* () {
374
- yield targetCtx.slots.register({
375
- name: "settings.plugin.item",
376
- key: "workspace-files"
377
- }, WorkspaceFilesSettingsCard);
378
- yield targetCtx.slots.register({
379
- name: "settings.plugin.item",
380
- key: "@civilization/dsh-workspace-files"
381
- }, WorkspaceFilesSettingsCard);
382
- }), "dsh-workspace-files: settings card");
383
- };
384
- if (slots) registerSettingsCard(ctx);
385
- if (ctx.inject) ctx.inject(["settingsScope"], (scoped) => {
386
- registerSettingsCard(scoped);
387
- });
371
+ if (slots) ctx.effect(() => slots.inject("settings.plugins.tab", () => slots.register({
372
+ name: "settings.plugins.tab",
373
+ id: "workspace-files",
374
+ order: 20,
375
+ label: () => "工作区文件"
376
+ }, WorkspaceFilesSettingsCard)), "dsh-workspace-files: settings card");
388
377
  }
389
378
  const CONFIG_STORAGE_KEY = "dsh_workspace_files_config";
390
379
  function loadWorkspaceFilesConfig() {
@@ -685,9 +674,9 @@ window.__ModuleLoader__.load({
685
674
  className: "dsh-wf-head-text",
686
675
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
687
676
  className: "dsh-wf-name",
688
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "工作区文件" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
677
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "工作区文件" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
689
678
  className: "dsh-wf-version",
690
- children: "v0.3.0"
679
+ children: ["v", "0.3.2"]
691
680
  })]
692
681
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
693
682
  className: "dsh-wf-desc",
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["useState","useRef","useCallback","useMemo"],"sources":["../src/client/icons.tsx","../src/client/index.tsx"],"sourcesContent":["import type { JSX } from 'react'\n\nexport function IconFolder({ size = 15, open = false }: { size?: number; open?: boolean }): JSX.Element {\n if (open) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0, color: 'var(--dsw-alias-brand-primary, #4b70e2)' }}>\n <path d=\"M1.5 3.5A1.5 1.5 0 013 2h3l1.5 2H13a1.5 1.5 0 011.5 1.5v1H2.5l-1 7.5A1.5 1.5 0 003 15h10.5a1.5 1.5 0 001.5-1.5L14 6.5H2.5\" fill=\"currentColor\" fillOpacity=\"0.18\" />\n </svg>\n )\n }\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0, color: 'var(--dsw-alias-brand-primary, #4b70e2)' }}>\n <path d=\"M1.75 1A1.75 1.75 0 000 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0016 13.25v-8.5A1.75 1.75 0 0014.25 3H7.5a.25.25 0 01-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75z\" />\n </svg>\n )\n}\n\nexport function IconSearch({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"7\" cy=\"7\" r=\"5\" />\n <line x1=\"11\" y1=\"11\" x2=\"14.5\" y2=\"14.5\" />\n </svg>\n )\n}\n\nexport function IconAt({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path fillRule=\"evenodd\" d=\"M8 1a7 7 0 106.914 8.093.75.75 0 00-1.488-.186A5.5 5.5 0 1113.5 8c0 .64-.207 1.2-.6 1.597-.39.395-.94.653-1.65.653-.61 0-1.156-.25-1.5-.67-.344.42-.89.67-1.5.67A2.25 2.25 0 016 8a2.25 2.25 0 012.25-2.25c.61 0 1.156.25 1.5.67.344-.42.89-.67 1.5-.67.71 0 1.26.258 1.65.653.393.397.6 1.057.6 1.847A7.001 7.001 0 018 1zm0 5.75A1.25 1.25 0 108 9.25 1.25 1.25 0 008 6.75z\" />\n </svg>\n )\n}\n\nexport function IconCopy({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z\" />\n <path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z\" />\n </svg>\n )\n}\n\nexport function IconExpandAll({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 2 8 6 12 2\" />\n <polyline points=\"4 8 8 12 12 8\" />\n </svg>\n )\n}\n\nexport function IconCollapseAll({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 6 8 2 12 6\" />\n <polyline points=\"4 12 8 8 12 8\" />\n </svg>\n )\n}\n\nexport function IconRefresh({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path fillRule=\"evenodd\" d=\"M8 2.5a5.5 5.5 0 105.006 3.238.75.75 0 011.378-.592A7 7 0 118 1v1.5a.75.75 0 01-1.28.53L4.47 1.28a.75.75 0 010-1.06l2.25-1.75A.75.75 0 018-.75V1a7 7 0 010 1.5z\" />\n </svg>\n )\n}\n\nexport function IconClose({ size = 12 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path d=\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\" />\n </svg>\n )\n}\n\nexport function IconCheck({ size = 12 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path fillRule=\"evenodd\" d=\"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z\" />\n </svg>\n )\n}\n\nexport function FileGlyphIcon({ filename, size = 14 }: { filename: string; size?: number }): JSX.Element {\n const ext = filename.split('.').pop()?.toLowerCase() || ''\n\n // Color tokens\n let color = 'var(--dsw-alias-label-tertiary, #8c9ba5)'\n let badge = ''\n\n if (ext === 'ts' || ext === 'tsx') {\n color = '#3178c6'\n badge = ext === 'tsx' ? 'TSX' : 'TS'\n } else if (ext === 'js' || ext === 'jsx' || ext === 'mjs' || ext === 'cjs') {\n color = '#f7df1e'\n badge = 'JS'\n } else if (ext === 'json') {\n color = '#cbcb41'\n badge = '{}'\n } else if (ext === 'md' || ext === 'markdown') {\n color = '#42a5f5'\n badge = 'M↓'\n } else if (ext === 'drawio' || ext === 'dio') {\n color = '#f08705'\n badge = 'D'\n } else if (ext === 'css' || ext === 'scss' || ext === 'less') {\n color = '#42a5f5'\n badge = '#'\n } else if (ext === 'html' || ext === 'htm') {\n color = '#e44d26'\n badge = '<>'\n } else if (ext === 'py') {\n color = '#3776ab'\n badge = 'PY'\n } else if (ext === 'png' || ext === 'jpg' || ext === 'jpeg' || ext === 'svg' || ext === 'gif' || ext === 'webp') {\n color = '#26a69a'\n badge = 'IMG'\n } else if (ext === 'yml' || ext === 'yaml') {\n color = '#cb171e'\n badge = 'Y'\n }\n\n return (\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: size,\n height: size,\n fontSize: 9,\n fontWeight: 700,\n fontFamily: 'monospace',\n color,\n flexShrink: 0,\n }}\n title={filename}\n >\n {badge || '•'}\n </span>\n )\n}\n\nexport function IconList({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M2.5 12a.5.5 0 01.5-.5h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4a.5.5 0 01.5-.5h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4a.5.5 0 01.5-.5h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5z\" />\n </svg>\n )\n}\n\nexport function IconTree({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M2 3h4v4H2zM10 9h4v4h-4zM4 7v6h6\" />\n </svg>\n )\n}\n\nexport function IconChevronDown({ size = 14 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n )\n}\n\nexport function IconExplorer({ size = 12 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path d=\"M1.75 2A1.75 1.75 0 000 3.75v8.5C0 13.216.784 14 1.75 14h12.5A1.75 1.75 0 0016 12.25v-6.5A1.75 1.75 0 0014.25 4H7.5a.25.25 0 01-.2-.1l-.9-1.2C6.07 2.26 5.55 2 5 2H1.75zM1.5 5.5h13v6.75a.25.25 0 01-.25.25H1.75a.25.25 0 01-.25-.25V5.5z\" />\n </svg>\n )\n}\n\nexport function IconExternalApp({ size = 12 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.35\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path d=\"M12.5 9.5v3.25a1.25 1.25 0 01-1.25 1.25H3.25A1.25 1.25 0 012 12.75V4.75A1.25 1.25 0 013.25 3.5H6.5\" />\n <polyline points=\"10 2 14 2 14 6\" />\n <line x1=\"6.5\" y1=\"9.5\" x2=\"13.5\" y2=\"2.5\" />\n </svg>\n )\n}\n\n\n","/**\n * Browser entry for the enhanced workspace files explorer plugin.\n * Overrides DSH official 'files' tab using 'priority: extension'.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n FileGlyphIcon,\n IconAt,\n IconCheck,\n IconChevronDown,\n IconClose,\n IconCollapseAll,\n IconCopy,\n IconExpandAll,\n IconExplorer,\n IconExternalApp,\n IconFolder,\n IconList,\n IconRefresh,\n IconSearch,\n IconTree,\n} from './icons.js'\n\nexport const inject = ['slots', 'sidebarRightTabs']\n\nlet globalCtx: Context | null = null\n\nconst OFFICIAL_FILES_TAB_ID = '@civilization/dsh-workspace-files'\n\nexport interface FileItem {\n name: string\n path: string\n isDirectory: boolean\n size?: number\n mtime?: number\n children?: FileItem[]\n}\n\nexport interface WorkspaceFilesResult {\n root: string\n items: FileItem[]\n totalFiles: number\n totalDirs: number\n}\n\nfunction FolderGuideGlyph({ size = 20, className }: { size?: number; className?: string }) {\n return (\n <span className={className} style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>\n <IconFolder size={size} />\n </span>\n )\n}\n\nfunction WorkspaceFilesTabTitle({ useTabInfo }: any): JSX.Element {\n const info = useTabInfo ? useTabInfo() : null\n const title = info?.tab?.title || '文件'\n return (\n <>\n <IconFolder size={15} />\n <span>{title}</span>\n </>\n )\n}\n\nfunction WorkspaceFilesTabBody(props: any): JSX.Element {\n const { sessionId, useSessions, useTabInfo } = props\n const tabInfo = useTabInfo ? useTabInfo() : null\n const tabActions = tabInfo?.tab?.actions\n\n const sessionCwd = useSessions ? useSessions((sessions: any) => sessions?.byId?.[sessionId]?.cwd) : undefined\n\n return (\n <WorkspaceFilesView\n sessionId={sessionId}\n cwd={sessionCwd}\n onOpenFile={(filePath: string) => {\n if (tabActions?.openResource && sessionId) {\n const normalized = filePath.replace(/\\\\/g, '/').replace(/^\\.?\\//, '')\n tabActions.openResource(`dsh-resource://file/session/${encodeURIComponent(sessionId)}/${encodeURIComponent(normalized)}`)\n }\n }}\n />\n )\n}\n\nexport function apply(ctx: Context): void {\n globalCtx = ctx\n const sidebarRightTabs = (ctx as any).sidebarRightTabs\n const slots = (ctx as any).slots\n\n if (sidebarRightTabs && slots) {\n // 关键:kind: 'files', priority: 'extension'(Rank 3 > builtin 2),完美接管官方文件标签页\n ctx.effect(() => sidebarRightTabs.register({\n id: OFFICIAL_FILES_TAB_ID,\n kind: 'files',\n priority: 'extension',\n title: () => '文件',\n guide: [{\n order: 10,\n title: () => '文件',\n description: () => '浏览、搜索与一键引用项目文件',\n icon: FolderGuideGlyph,\n }],\n }), 'dsh-workspace-files: override official files tab')\n\n ctx.effect(() => slots.inject('sidebar.right.pane.tab', () => slots.register({\n name: 'sidebar.right.pane.tab',\n key: OFFICIAL_FILES_TAB_ID,\n }, WorkspaceFilesTabBody)), 'dsh-workspace-files: official tab body')\n\n ctx.effect(() => slots.inject('sidebar.right.pane.tab.title', () => slots.register({\n name: 'sidebar.right.pane.tab.title',\n key: OFFICIAL_FILES_TAB_ID,\n }, WorkspaceFilesTabTitle)), 'dsh-workspace-files: official tab title')\n }\n\n // 注入设置中心“插件配置”卡片(命名空间必须为 workspace-files,与 Host settings 服务注册一致)\n const registerSettingsCard = (targetCtx: any) => {\n if (!targetCtx?.slots) return\n targetCtx.effect?.(() => targetCtx.slots.inject('settings.plugin.item', function* () {\n yield targetCtx.slots.register({\n name: 'settings.plugin.item',\n key: 'workspace-files',\n }, WorkspaceFilesSettingsCard)\n yield targetCtx.slots.register({\n name: 'settings.plugin.item',\n key: '@civilization/dsh-workspace-files',\n }, WorkspaceFilesSettingsCard)\n }), 'dsh-workspace-files: settings card')\n }\n\n if (slots) {\n registerSettingsCard(ctx)\n }\n if ((ctx as any).inject) {\n (ctx as any).inject(['settingsScope'], (scoped: any) => {\n registerSettingsCard(scoped)\n })\n }\n}\n\n/* ── Workspace Files Configuration Store ── */\nexport interface WorkspaceFilesConfig {\n maxDepth: number\n showHidden: boolean\n}\n\nconst CONFIG_STORAGE_KEY = 'dsh_workspace_files_config'\n\nexport function loadWorkspaceFilesConfig(): WorkspaceFilesConfig {\n try {\n const raw = typeof localStorage !== 'undefined' ? localStorage.getItem(CONFIG_STORAGE_KEY) : null\n if (raw) {\n const parsed = JSON.parse(raw)\n return {\n maxDepth: typeof parsed.maxDepth === 'number' && parsed.maxDepth > 0 ? parsed.maxDepth : 16,\n showHidden: Boolean(parsed.showHidden),\n }\n }\n } catch {}\n return { maxDepth: 16, showHidden: false }\n}\n\nexport function saveWorkspaceFilesConfig(cfg: WorkspaceFilesConfig): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(CONFIG_STORAGE_KEY, JSON.stringify(cfg))\n }\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('dsh-workspace-files:config-change', { detail: cfg }))\n }\n fetch('/dsh-workspace-files/api/config.set', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(cfg),\n }).catch(() => {})\n } catch {}\n}\n\nfunction ensureSettingsStyle() {\n if (typeof document === 'undefined') return\n const id = 'dsh-workspace-files-settings-style'\n if (document.getElementById(id)) return\n const style = document.createElement('style')\n style.id = id\n style.textContent = `\n.dsh-wf-card {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-3, #fff);\n border-radius: 12px;\n list-style: none;\n transition: border-color .16s, background .16s;\n box-sizing: border-box;\n}\n.dsh-wf-card-open {\n background: var(--dsw-alias-bg-layer-2, #f7f8fa);\n border-color: var(--dsw-alias-label-dimmed, #c8ccd4);\n}\n.dsh-wf-header {\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: 0 0;\n border: 0;\n border-radius: 12px;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n display: flex;\n}\n.dsh-wf-head-text {\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n display: flex;\n}\n.dsh-wf-name {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-wf-version {\n font-size: 12px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n}\n.dsh-wf-desc {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 13px;\n line-height: 1.5;\n}\n.dsh-wf-chevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n flex: none;\n transition: transform .16s ease-in-out;\n display: inline-flex;\n}\n.dsh-wf-chevron-open {\n transform: rotate(180deg);\n}\n.dsh-wf-body {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n margin: 0 16px;\n padding: 8px 0 12px;\n}\n.dsh-wf-row {\n align-items: center;\n gap: 16px;\n padding: 12px 0;\n display: flex;\n justify-content: space-between;\n}\n.dsh-wf-row + .dsh-wf-row {\n border-top: 1px solid var(--dsw-alias-border-l2, rgba(118, 137, 166, 0.12));\n}\n.dsh-wf-label-box {\n flex-direction: column;\n flex: 1;\n gap: 3px;\n min-width: 0;\n display: flex;\n}\n.dsh-wf-label {\n font-size: 13.5px;\n font-weight: 550;\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n.dsh-wf-hint {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 12px;\n line-height: 18px;\n}\n.dsh-wf-ctrl {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-wf-seg {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n gap: 2px;\n padding: 2px;\n display: inline-flex;\n background: var(--dsw-alias-bg-layer-1, rgba(255, 255, 255, 0.05));\n}\n.dsh-wf-seg-btn {\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n background: 0 0;\n border: none;\n border-radius: 6px;\n padding: 4px 10px;\n font-size: 12px;\n line-height: 18px;\n transition: all 0.15s;\n}\n.dsh-wf-seg-btn:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n.dsh-wf-seg-active {\n background: var(--dsw-alias-bg-layer-3, #eef0f4);\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n font-weight: 600;\n box-shadow: 0 1px 2px rgba(0,0,0,0.05);\n}\n.dsh-wf-input {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2, #d1d5db);\n background: var(--dsw-alias-bg-layer-3, #fff);\n width: 64px;\n text-align: center;\n color: var(--dsw-alias-label-primary, #1f2328);\n font: inherit;\n border-radius: 7px;\n padding: 4px 6px;\n font-size: 12.5px;\n line-height: 18px;\n}\n.dsh-wf-input:focus {\n border-color: var(--dsw-alias-brand-primary, #4f6ef7);\n outline: 2px solid color-mix(in srgb, var(--dsw-alias-brand-primary, #4f6ef7) 18%, transparent);\n}\n.dsh-wf-toggle {\n position: relative;\n display: inline-block;\n width: 40px;\n height: 22px;\n cursor: pointer;\n}\n.dsh-wf-toggle input {\n opacity: 0;\n width: 0;\n height: 0;\n position: absolute;\n}\n.dsh-wf-toggle-track {\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background-color: var(--dsw-alias-border-l2, #ccc);\n transition: .2s cubic-bezier(.4, 0, .2, 1);\n border-radius: 22px;\n}\n.dsh-wf-toggle input:checked + .dsh-wf-toggle-track {\n background-color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n.dsh-wf-toggle-thumb {\n position: absolute;\n height: 16px;\n width: 16px;\n left: 3px;\n bottom: 3px;\n background-color: white;\n transition: .2s cubic-bezier(.4, 0, .2, 1);\n border-radius: 50%;\n box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n}\n.dsh-wf-toggle input:checked + .dsh-wf-toggle-track .dsh-wf-toggle-thumb {\n transform: translateX(18px);\n}\n.dsh-wf-footer {\n margin-top: 8px;\n padding-top: 10px;\n border-top: 1px solid var(--dsw-alias-border-l2, rgba(118, 137, 166, 0.12));\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n.dsh-wf-saved-hint {\n font-size: 11.5px;\n color: var(--dsw-alias-state-success-primary, #10b981);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.dsh-wf-btn-reset {\n background: transparent;\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 6px;\n padding: 3px 10px;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.15s;\n}\n.dsh-wf-btn-reset:hover {\n background: var(--dsw-alias-bg-layer-2, rgba(255,255,255,0.08));\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n`\n document.head.appendChild(style)\n}\n\nexport function WorkspaceFilesSettingsCard(): JSX.Element {\n const [open, setOpen] = useState(false)\n const [config, setConfig] = useState<WorkspaceFilesConfig>(() => loadWorkspaceFilesConfig())\n const [savedTick, setSavedTick] = useState(false)\n\n useEffect(() => {\n ensureSettingsStyle()\n }, [])\n\n const updateConfig = (patch: Partial<WorkspaceFilesConfig>) => {\n const next = { ...config, ...patch }\n setConfig(next)\n saveWorkspaceFilesConfig(next)\n setSavedTick(true)\n setTimeout(() => setSavedTick(false), 2000)\n }\n\n const handleDepthSelect = (depth: number) => {\n updateConfig({ maxDepth: depth })\n }\n\n const handleDepthInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n const val = parseInt(e.target.value, 10)\n if (!isNaN(val) && val >= 1 && val <= 100) {\n updateConfig({ maxDepth: val })\n }\n }\n\n const handleToggleHidden = () => {\n updateConfig({ showHidden: !config.showHidden })\n }\n\n const handleReset = () => {\n const def = { maxDepth: 16, showHidden: false }\n setConfig(def)\n saveWorkspaceFilesConfig(def)\n setSavedTick(true)\n setTimeout(() => setSavedTick(false), 2000)\n }\n\n return (\n <div className={open ? 'dsh-wf-card dsh-wf-card-open' : 'dsh-wf-card'}>\n <button\n type=\"button\"\n className=\"dsh-wf-header\"\n aria-expanded={open}\n onClick={() => setOpen(!open)}\n >\n <div className=\"dsh-wf-head-text\">\n <div className=\"dsh-wf-name\">\n <span>工作区文件</span>\n <span className=\"dsh-wf-version\">v0.3.0</span>\n </div>\n <div className=\"dsh-wf-desc\">\n 浏览与检索工作区文件树,支持递归目录扫描与一键引用。\n </div>\n </div>\n <span className={open ? 'dsh-wf-chevron dsh-wf-chevron-open' : 'dsh-wf-chevron'}>\n <IconChevronDown size={14} />\n </span>\n </button>\n\n {open && (\n <div className=\"dsh-wf-body\">\n <div className=\"dsh-wf-row\">\n <div className=\"dsh-wf-label-box\">\n <div className=\"dsh-wf-label\">目录扫描最大深度</div>\n <div className=\"dsh-wf-hint\">\n 工作区递归扫描的最大目录层级(默认 16,范围 1~100)。若工程目录较深可适当调大。\n </div>\n </div>\n <div className=\"dsh-wf-ctrl\">\n <div className=\"dsh-wf-seg\">\n {[8, 16, 32, 64].map((d) => (\n <button\n key={d}\n type=\"button\"\n className={config.maxDepth === d ? 'dsh-wf-seg-btn dsh-wf-seg-active' : 'dsh-wf-seg-btn'}\n onClick={() => handleDepthSelect(d)}\n >\n {d}\n </button>\n ))}\n </div>\n <input\n type=\"number\"\n min=\"1\"\n max=\"100\"\n className=\"dsh-wf-input\"\n value={config.maxDepth}\n onChange={handleDepthInput}\n title=\"自定义深度 (1-100)\"\n />\n </div>\n </div>\n\n <div className=\"dsh-wf-row\">\n <div className=\"dsh-wf-label-box\">\n <div className=\"dsh-wf-label\">默认显示隐藏文件</div>\n <div className=\"dsh-wf-hint\">\n 打开文件树时是否默认展示以点开头的隐藏文件或文件夹(如 .gitignore, .env 等)。\n </div>\n </div>\n <div className=\"dsh-wf-ctrl\">\n <label className=\"dsh-wf-toggle\">\n <input\n type=\"checkbox\"\n checked={config.showHidden}\n onChange={handleToggleHidden}\n />\n <span className=\"dsh-wf-toggle-track\">\n <span className=\"dsh-wf-toggle-thumb\" />\n </span>\n </label>\n </div>\n </div>\n\n <div className=\"dsh-wf-footer\">\n <div>\n {savedTick ? (\n <span className=\"dsh-wf-saved-hint\">\n <IconCheck size={12} />\n <span>已保存设置</span>\n </span>\n ) : (\n <span style={{ fontSize: 11, color: 'var(--dsw-alias-label-tertiary, #8b93a1)' }}>\n 设置改动即时生效并同步至工作区文件树\n </span>\n )}\n </div>\n <button\n type=\"button\"\n className=\"dsh-wf-btn-reset\"\n onClick={handleReset}\n >\n 恢复默认\n </button>\n </div>\n </div>\n )}\n </div>\n )\n}\n\n/* ── Main Workspace Files View ── */\nfunction WorkspaceFilesView({\n sessionId,\n cwd,\n onOpenFile,\n}: {\n sessionId?: string\n cwd?: string\n onOpenFile: (path: string) => void\n}): JSX.Element {\n const [data, setData] = useState<WorkspaceFilesResult | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [query, setQuery] = useState('')\n const [toast, setToast] = useState<string | null>(null)\n const [expandedPaths, setExpandedPaths] = useState<Set<string>>(() => new Set())\n const [activeConfig, setActiveConfig] = useState<WorkspaceFilesConfig>(() => loadWorkspaceFilesConfig())\n const [showHidden, setShowHidden] = useState(() => loadWorkspaceFilesConfig().showHidden)\n\n const toastTimer = useRef<number | null>(null)\n\n const showToastMsg = useCallback((msg: string) => {\n setToast(msg)\n if (toastTimer.current) window.clearTimeout(toastTimer.current)\n toastTimer.current = window.setTimeout(() => setToast(null), 2000)\n }, [])\n\n useEffect(() => {\n const handleCfgChange = (e: any) => {\n if (e.detail) {\n setActiveConfig(e.detail)\n setShowHidden(Boolean(e.detail.showHidden))\n }\n }\n window.addEventListener('dsh-workspace-files:config-change', handleCfgChange)\n return () => window.removeEventListener('dsh-workspace-files:config-change', handleCfgChange)\n }, [])\n\n const loadTree = useCallback(async (quiet = false, forceRefresh = false) => {\n if (!quiet) setLoading(true)\n setError(null)\n try {\n const res = await call<WorkspaceFilesResult>('files.tree', {\n sessionId,\n cwd,\n showHidden,\n maxDepth: activeConfig.maxDepth,\n forceRefresh,\n })\n setData(res)\n\n // 默认折叠,并从 localStorage 恢复已记录的展开状态\n setExpandedPaths(prev => {\n if (prev.size > 0) return prev\n const stored = loadStoredExpandedPaths(res.root || cwd)\n if (stored !== null) return stored\n // 默认全部关闭,不展开任何目录\n return new Set<string>()\n })\n } catch (err: any) {\n setError(err?.message || '无法加载文件列表')\n } finally {\n if (!quiet) setLoading(false)\n }\n }, [sessionId, cwd, showHidden, activeConfig.maxDepth])\n\n useEffect(() => {\n void loadTree()\n }, [loadTree])\n\n const handleToggleExpand = (path: string) => {\n setExpandedPaths(prev => {\n const next = new Set(prev)\n if (next.has(path)) next.delete(path)\n else next.add(path)\n saveStoredExpandedPaths(data?.root || cwd, next)\n return next\n })\n }\n\n const handleExpandAll = () => {\n if (!data) return\n const all = new Set<string>()\n function collect(items: FileItem[]) {\n for (const it of items) {\n if (it.isDirectory) {\n all.add(it.path)\n if (it.children) collect(it.children)\n }\n }\n }\n collect(data.items)\n setExpandedPaths(all)\n saveStoredExpandedPaths(data.root || cwd, all)\n }\n\n const handleCollapseAll = () => {\n const empty = new Set<string>()\n setExpandedPaths(empty)\n saveStoredExpandedPaths(data?.root || cwd, empty)\n }\n\n // 搜索时点击文件夹:跳回树形视图并展开该目录及全部祖先路径,自动平滑定位\n const handleJumpToFolderInTree = (dirPath: string) => {\n const parts = dirPath.split('/')\n const toExpand: string[] = []\n let acc = ''\n for (const p of parts) {\n if (!p) continue\n acc = acc ? `${acc}/${p}` : p\n toExpand.push(acc)\n }\n\n setExpandedPaths(prev => {\n const next = new Set(prev)\n for (const p of toExpand) {\n next.add(p)\n }\n saveStoredExpandedPaths(data?.root || cwd, next)\n return next\n })\n\n // 退出搜索状态回到树形视图\n setQuery('')\n showToastMsg(`已定位并展开目录: ${dirPath}/`)\n\n // 平滑滚动定位到该目录节点\n setTimeout(() => {\n try {\n const el = document.querySelector(`[data-tree-path=\"${dirPath}\"]`)\n if (el) {\n el.scrollIntoView({ block: 'center', behavior: 'smooth' })\n }\n } catch {}\n }, 60)\n }\n\n // 复制相对路径\n const handleCopyPath = (e: React.MouseEvent, path: string) => {\n e.stopPropagation()\n void navigator.clipboard.writeText(path).then(() => {\n showToastMsg(`已复制路径: ${path}`)\n })\n }\n\n // 一键 @ 引用到当前对话框输入框(优先插入官方原生交互式 Chip 胶囊)\n const handleMention = (e: React.MouseEvent, itemOrPath: string | FileItem) => {\n e.stopPropagation()\n const itemObj: FileItem = typeof itemOrPath === 'string'\n ? { name: itemOrPath.split('/').pop() || itemOrPath, path: itemOrPath, isDirectory: false }\n : itemOrPath\n\n const mentionText = formatMentionText(itemObj.path, itemObj.isDirectory)\n\n // 1. 优先尝试向会话输入框插入官方原生 ReferenceChipNode 胶囊卡片\n let inserted = false\n try {\n inserted = tryInsertNativeReferenceChip(globalCtx, sessionId, itemObj)\n } catch (err) {\n console.warn('[dsh-workspace-files] 原生 Chip 插入失败:', err)\n }\n\n // 2. 若原生 Chip 插入未成功,无缝降级为规范纯文本插入\n if (!inserted) {\n try {\n inserted = insertMentionToComposer(mentionText)\n } catch (err) {\n console.warn('[dsh-workspace-files] 降级纯文本插入失败:', err)\n }\n }\n\n // 写入剪贴板作为双重保障\n const displayName = itemObj.isDirectory ? `${itemObj.name}/` : itemObj.name\n void navigator.clipboard.writeText(mentionText.trim()).then(() => {\n if (inserted) {\n showToastMsg(`已引用${itemObj.isDirectory ? '目录' : '文件'}: ${displayName}`)\n } else {\n showToastMsg(`已复制引用: ${mentionText.trim()}`)\n }\n })\n }\n\n // 在文件资源管理器中定位/打开\n const handleRevealInExplorer = (e: React.MouseEvent, item: FileItem) => {\n e.stopPropagation()\n fetch('/dsh-workspace-files/api/files.open', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n action: 'reveal',\n path: item.path,\n isDirectory: Boolean(item.isDirectory),\n sessionId,\n cwd,\n }),\n })\n .then(res => res.json())\n .then(data => {\n if (data.ok) {\n showToastMsg(`已在资源管理器中显示: ${item.name}`)\n } else {\n showToastMsg(`打开失败: ${data.error?.message || '未知错误'}`)\n }\n })\n .catch(err => {\n showToastMsg(`请求失败: ${err?.message || String(err)}`)\n })\n }\n\n // 用系统默认应用打开\n const handleOpenDefaultApp = (e: React.MouseEvent, item: FileItem) => {\n e.stopPropagation()\n fetch('/dsh-workspace-files/api/files.open', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n action: 'openDefault',\n path: item.path,\n isDirectory: Boolean(item.isDirectory),\n sessionId,\n cwd,\n }),\n })\n .then(res => res.json())\n .then(data => {\n if (data.ok) {\n showToastMsg(`已启动系统应用打开: ${item.name}`)\n } else {\n showToastMsg(`打开失败: ${data.error?.message || '未知错误'}`)\n }\n })\n .catch(err => {\n showToastMsg(`请求失败: ${err?.message || String(err)}`)\n })\n }\n\n const [searchViewMode, setSearchViewMode] = useState<'flat' | 'tree'>('flat')\n const [searchExpandedPaths, setSearchExpandedPaths] = useState<Set<string>>(() => new Set())\n\n // 过滤树与扁平结果\n const { filteredTreeItems, flatSearchResults } = useMemo(() => {\n if (!data) return { filteredTreeItems: [], flatSearchResults: [] }\n const q = query.trim().toLowerCase()\n if (!q) return { filteredTreeItems: data.items, flatSearchResults: [] }\n\n // 扁平结果列表\n const flat: Array<{ item: FileItem; parentDir: string }> = []\n function traverseFlat(items: FileItem[], parentDir: string) {\n for (const it of items) {\n const match = it.name.toLowerCase().includes(q) || it.path.toLowerCase().includes(q)\n if (match) {\n flat.push({ item: it, parentDir })\n }\n if (it.isDirectory && it.children) {\n traverseFlat(it.children, it.path)\n }\n }\n }\n traverseFlat(data.items, '')\n\n // 树形过滤集合\n function filterNode(node: FileItem): FileItem | null {\n const selfMatch = node.name.toLowerCase().includes(q) || node.path.toLowerCase().includes(q)\n if (node.isDirectory) {\n const filteredChildren: FileItem[] = []\n for (const child of node.children || []) {\n const matchedChild = filterNode(child)\n if (matchedChild) filteredChildren.push(matchedChild)\n }\n if (selfMatch || filteredChildren.length > 0) {\n return { ...node, children: filteredChildren }\n }\n return null\n }\n return selfMatch ? node : null\n }\n\n const tree: FileItem[] = []\n for (const rootNode of data.items) {\n const matched = filterNode(rootNode)\n if (matched) tree.push(matched)\n }\n\n return { filteredTreeItems: tree, flatSearchResults: flat }\n }, [data, query])\n\n // 搜索关键字变化时,自动展开匹配的目录树节点,并允许用户后续自由折叠/展开\n useEffect(() => {\n if (!query.trim() || !data) return\n const q = query.trim().toLowerCase()\n const autoExpand = new Set<string>()\n function collect(items: FileItem[]) {\n for (const it of items) {\n if (it.isDirectory) {\n const selfMatch = it.name.toLowerCase().includes(q) || it.path.toLowerCase().includes(q)\n const childMatch = it.children?.some(c => c.name.toLowerCase().includes(q) || c.path.toLowerCase().includes(q))\n if (selfMatch || childMatch) autoExpand.add(it.path)\n if (it.children) collect(it.children)\n }\n }\n }\n collect(data.items)\n setSearchExpandedPaths(autoExpand)\n }, [query, data])\n\n const isSearchActive = Boolean(query.trim())\n\n return (\n <div className=\"dsh-files-root\">\n <GlobalFilesStyle />\n\n {/* Header */}\n <header className=\"dsh-files-header\">\n <div className=\"dsh-files-header-info\">\n <div className=\"dsh-files-title-row\">\n <span className=\"dsh-files-title\">文件</span>\n {data && (\n <span className=\"dsh-files-stats-badge\">\n {data.totalFiles} 文件 · {data.totalDirs} 目录\n </span>\n )}\n </div>\n <div className=\"dsh-files-root-path\" title={data?.root || cwd}>\n {data?.root || cwd || '当前会话没有工作目录'}\n </div>\n </div>\n </header>\n\n {/* Search & Actions Toolbar */}\n <div className=\"dsh-files-toolbar\">\n <div className=\"dsh-files-search-wrap\">\n <span className=\"dsh-files-search-icon\"><IconSearch size={13} /></span>\n <input\n type=\"text\"\n className=\"dsh-files-search-input\"\n placeholder=\"搜索文件 (支持路径筛选)...\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n onKeyDown={e => {\n if (e.key === 'Escape') setQuery('')\n }}\n />\n {query && (\n <button\n type=\"button\"\n className=\"dsh-files-clear-btn\"\n onClick={() => setQuery('')}\n title=\"清除搜索\"\n >\n <IconClose size={12} />\n </button>\n )}\n </div>\n\n <div className=\"dsh-files-toolbar-btns\">\n {isSearchActive ? (\n <button\n type=\"button\"\n className=\"dsh-files-tool-btn is-active\"\n onClick={() => setSearchViewMode(searchViewMode === 'flat' ? 'tree' : 'flat')}\n title={searchViewMode === 'flat' ? '当前为扁平列表,点击切换为树形视图' : '当前为树形视图,点击切换为扁平列表'}\n >\n {searchViewMode === 'flat' ? <IconTree size={13} /> : <IconList size={13} />}\n </button>\n ) : (\n <>\n <button\n type=\"button\"\n className=\"dsh-files-tool-btn\"\n onClick={handleExpandAll}\n title=\"全部展开\"\n >\n <IconExpandAll size={13} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-tool-btn\"\n onClick={handleCollapseAll}\n title=\"全部折叠\"\n >\n <IconCollapseAll size={13} />\n </button>\n </>\n )}\n\n <button\n type=\"button\"\n className={`dsh-files-tool-btn ${showHidden ? 'is-active' : ''}`}\n onClick={() => setShowHidden(!showHidden)}\n title={showHidden ? '隐藏点号开头的文件' : '显示点号开头的文件'}\n >\n <span style={{ fontSize: 11, fontWeight: 700 }}>.*</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-tool-btn\"\n onClick={() => void loadTree(false, true)}\n disabled={loading}\n title=\"刷新文件树\"\n >\n <IconRefresh size={13} />\n </button>\n </div>\n </div>\n\n {/* Error Banner */}\n {error && (\n <div className=\"dsh-files-banner-error\">\n <span>{error}</span>\n <button type=\"button\" className=\"dsh-files-banner-close\" onClick={() => setError(null)}>\n <IconClose size={12} />\n </button>\n </div>\n )}\n\n {/* Tree / Search Results Content */}\n <div className=\"dsh-files-body\">\n {loading && !data ? (\n <div className=\"dsh-files-centered\">\n <div className=\"dsh-files-spinner\" />\n <span>加载文件…</span>\n </div>\n ) : isSearchActive && flatSearchResults.length === 0 ? (\n <div className=\"dsh-files-empty\">\n <div className=\"dsh-files-empty-icon\"><IconFolder size={26} /></div>\n <div className=\"dsh-files-empty-title\">未搜索到匹配的文件</div>\n <div className=\"dsh-files-empty-detail\">请尝试更换搜索关键字,或按 Esc 清除搜索。</div>\n </div>\n ) : !isSearchActive && (!data || data.items.length === 0) ? (\n <div className=\"dsh-files-empty\">\n <div className=\"dsh-files-empty-icon\"><IconFolder size={26} /></div>\n <div className=\"dsh-files-empty-title\">工作区为空</div>\n <div className=\"dsh-files-empty-detail\">当前工作目录下暂无可显示的文件。</div>\n </div>\n ) : isSearchActive && searchViewMode === 'flat' ? (\n /* ── 扁平搜索结果列表 ── */\n <div className=\"dsh-files-search-container\">\n <div className=\"dsh-files-search-header\">\n <span className=\"dsh-files-search-count\">\n 找到 {flatSearchResults.length} 个匹配项\n {flatSearchResults.length > 150 ? '(展示前 150 项)' : ''}\n </span>\n <button\n type=\"button\"\n className=\"dsh-files-view-toggle-btn\"\n onClick={() => setSearchViewMode('tree')}\n title=\"切换为可折叠的树形视图\"\n >\n <IconTree size={12} />\n <span>切为树形</span>\n </button>\n </div>\n <div className=\"dsh-files-flat-list\">\n {flatSearchResults.slice(0, 150).map(({ item, parentDir }) => (\n <div\n key={item.path}\n className={`dsh-files-flat-row ${item.isDirectory ? 'is-directory' : ''}`}\n onClick={() => {\n if (item.isDirectory) {\n handleJumpToFolderInTree(item.path)\n } else {\n onOpenFile(item.path)\n }\n }}\n title={item.isDirectory ? `点击退出搜索并定位展开目录: ${item.path}/` : `点击预览打开文件: ${item.path}`}\n >\n <span className=\"dsh-files-flat-icon\">\n {item.isDirectory ? <IconFolder size={14} /> : <FileGlyphIcon filename={item.name} size={14} />}\n </span>\n <div className=\"dsh-files-flat-info\">\n <div className=\"dsh-files-flat-top\">\n <span className=\"dsh-files-flat-name\">\n <HighlightText text={item.name} query={query} />\n {item.isDirectory && '/'}\n </span>\n {item.size !== undefined && (\n <span className=\"dsh-files-size\">{formatFileSize(item.size)}</span>\n )}\n {item.isDirectory && (\n <span className=\"dsh-files-jump-hint\">跳回展开 ›</span>\n )}\n </div>\n {parentDir && (\n <div className=\"dsh-files-flat-parent\" title={parentDir}>\n {parentDir}\n </div>\n )}\n </div>\n <div className=\"dsh-files-row-actions\">\n <button\n type=\"button\"\n className=\"dsh-files-action-btn dsh-files-action-at\"\n onClick={e => handleMention(e, item)}\n title={`一键 @ 引用此${item.isDirectory ? '目录' : '文件'}到当前会话`}\n >\n <IconAt size={13} />\n <span className=\"dsh-files-action-at-text\">@引用</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => handleRevealInExplorer(e, item)}\n title={`在文件资源管理器中显示此${item.isDirectory ? '目录' : '文件'}`}\n >\n <IconExplorer size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => handleOpenDefaultApp(e, item)}\n title={`用系统默认应用打开此${item.isDirectory ? '目录' : '文件'}`}\n >\n <IconExternalApp size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => handleCopyPath(e, item.path)}\n title=\"复制相对路径\"\n >\n <IconCopy size={12} />\n </button>\n </div>\n </div>\n ))}\n {flatSearchResults.length > 150 && (\n <div style={{ padding: '10px 14px', fontSize: 11, textAlign: 'center', color: 'var(--dsw-alias-label-tertiary, #8b93a1)', borderTop: '1px dashed var(--dsw-alias-border-l2, #e5e7eb)' }}>\n 匹配项较多,已限制展示前 150 项以保证流畅度,请输入更详细关键字\n </div>\n )}\n </div>\n </div>\n ) : (\n /* ── 树形视图(普通模式或搜索树模式) ── */\n <div className=\"dsh-files-tree\">\n {isSearchActive && (\n <div className=\"dsh-files-search-header\">\n <span className=\"dsh-files-search-count\">树形匹配(自由折叠/展开)</span>\n <button\n type=\"button\"\n className=\"dsh-files-view-toggle-btn\"\n onClick={() => setSearchViewMode('flat')}\n title=\"切换为扁平搜索结果列表\"\n >\n <IconList size={12} />\n <span>切为列表</span>\n </button>\n </div>\n )}\n {filteredTreeItems.map(item => (\n <FileTreeNode\n key={item.path}\n item={item}\n depth={0}\n query={query}\n isSearchMode={isSearchActive}\n expandedPaths={isSearchActive ? searchExpandedPaths : expandedPaths}\n onToggleExpand={(path: string) => {\n if (isSearchActive) {\n setSearchExpandedPaths(prev => {\n const next = new Set(prev)\n if (next.has(path)) next.delete(path)\n else next.add(path)\n return next\n })\n } else {\n handleToggleExpand(path)\n }\n }}\n onOpenFile={onOpenFile}\n onMention={handleMention}\n onCopyPath={handleCopyPath}\n onRevealInExplorer={handleRevealInExplorer}\n onOpenDefaultApp={handleOpenDefaultApp}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Toast Notification */}\n {toast && (\n <div className=\"dsh-files-toast\">\n <IconCheck size={12} />\n <span>{toast}</span>\n </div>\n )}\n </div>\n )\n}\n\n/* ── Tree Node Component ── */\nfunction FileTreeNode(props: {\n item: FileItem\n depth: number\n query: string\n isSearchMode: boolean\n expandedPaths: Set<string>\n onToggleExpand: (path: string) => void\n onOpenFile: (path: string) => void\n onMention: (e: React.MouseEvent, item: FileItem) => void\n onCopyPath: (e: React.MouseEvent, path: string) => void\n onRevealInExplorer: (e: React.MouseEvent, item: FileItem) => void\n onOpenDefaultApp: (e: React.MouseEvent, item: FileItem) => void\n}): JSX.Element {\n const {\n item,\n depth,\n query,\n isSearchMode,\n expandedPaths,\n onToggleExpand,\n onOpenFile,\n onMention,\n onCopyPath,\n onRevealInExplorer,\n onOpenDefaultApp,\n } = props\n const isExpanded = expandedPaths.has(item.path)\n\n if (item.isDirectory) {\n const childCount = item.children?.length ?? 0\n return (\n <div className=\"dsh-files-dir-block\">\n <div\n className=\"dsh-files-dir-row\"\n data-tree-path={item.path}\n style={{ paddingLeft: `${depth * 14 + 10}px` }}\n onClick={() => onToggleExpand(item.path)}\n >\n <span className=\"dsh-files-chevron\" data-collapsed={!isExpanded ? 'true' : undefined}>▾</span>\n <span className=\"dsh-files-folder-icon\">\n <IconFolder size={14} open={isExpanded} />\n </span>\n <span className=\"dsh-files-folder-name\" title={item.path}>\n <HighlightText text={item.name} query={query} />\n </span>\n <span className=\"dsh-files-count-badge\">{childCount}</span>\n\n <div className=\"dsh-files-row-actions\">\n <button\n type=\"button\"\n className=\"dsh-files-action-btn dsh-files-action-at\"\n onClick={e => onMention(e, item)}\n title=\"一键 @ 引用此目录到当前会话\"\n >\n <IconAt size={13} />\n <span className=\"dsh-files-action-at-text\">@引用</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onRevealInExplorer(e, item)}\n title=\"在文件资源管理器中打开此目录\"\n >\n <IconExplorer size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onOpenDefaultApp(e, item)}\n title=\"用系统默认应用打开此目录\"\n >\n <IconExternalApp size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onCopyPath(e, item.path)}\n title=\"复制目录路径\"\n >\n <IconCopy size={12} />\n </button>\n </div>\n </div>\n {isExpanded && item.children && (\n <div className=\"dsh-files-children\">\n {item.children.map(child => (\n <FileTreeNode\n key={child.path}\n item={child}\n depth={depth + 1}\n query={query}\n isSearchMode={isSearchMode}\n expandedPaths={expandedPaths}\n onToggleExpand={onToggleExpand}\n onOpenFile={onOpenFile}\n onMention={onMention}\n onCopyPath={onCopyPath}\n onRevealInExplorer={onRevealInExplorer}\n onOpenDefaultApp={onOpenDefaultApp}\n />\n ))}\n </div>\n )}\n </div>\n )\n }\n\n // File item row\n return (\n <div\n className=\"dsh-files-row\"\n data-tree-path={item.path}\n style={{ paddingLeft: `${depth * 14 + 10}px` }}\n onClick={() => onOpenFile(item.path)}\n title={`点击打开: ${item.path}`}\n >\n <FileGlyphIcon filename={item.name} size={14} />\n <span className=\"dsh-files-name\">\n <HighlightText text={item.name} query={query} />\n </span>\n\n {item.size !== undefined && (\n <span className=\"dsh-files-size\" title={`大小: ${item.size} 字节`}>\n {formatFileSize(item.size)}\n </span>\n )}\n\n {/* Row Hover Actions */}\n <div className=\"dsh-files-row-actions\">\n <button\n type=\"button\"\n className=\"dsh-files-action-btn dsh-files-action-at\"\n onClick={e => onMention(e, item)}\n title=\"一键 @ 引用此文件到当前会话\"\n >\n <IconAt size={13} />\n <span className=\"dsh-files-action-at-text\">@引用</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onRevealInExplorer(e, item)}\n title=\"在文件资源管理器中显示此文件\"\n >\n <IconExplorer size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onOpenDefaultApp(e, item)}\n title=\"用系统默认应用打开此文件\"\n >\n <IconExternalApp size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onCopyPath(e, item.path)}\n title=\"复制相对路径\"\n >\n <IconCopy size={12} />\n </button>\n </div>\n </div>\n )\n}\n\n/* ── Helpers ── */\nfunction HighlightText({ text, query }: { text: string; query: string }): JSX.Element {\n const q = query.trim().toLowerCase()\n if (!q) return <span>{text}</span>\n const index = text.toLowerCase().indexOf(q)\n if (index === -1) return <span>{text}</span>\n\n const before = text.slice(0, index)\n const match = text.slice(index, index + q.length)\n const after = text.slice(index + q.length)\n\n return (\n <span>\n {before}\n <mark className=\"dsh-files-highlight\">{match}</mark>\n {after}\n </span>\n )\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n const kb = bytes / 1024\n if (kb < 1024) return `${kb.toFixed(1)} KB`\n const mb = kb / 1024\n return `${mb.toFixed(1)} MB`\n}\n\n/**\n * 按照 DSH 官方规范格式化引用路径:\n * - 纯路径无空格:@path\n * - 路径含空格:@\"path\"\n * - 目录末尾保留斜杠:@folder/ 或 @\"folder/\"\n */\nfunction formatMentionText(path: string, isDirectory = false): string {\n const cleanPath = path.replace(/\\\\/g, '/').replace(/^\\.?\\//, '')\n const finalPath = isDirectory ? (cleanPath.endsWith('/') ? cleanPath : `${cleanPath}/`) : cleanPath\n if (/\\s/u.test(finalPath)) {\n return `@\"${finalPath}\" `\n }\n return `@${finalPath} `\n}\n\nfunction getStorageKey(workspaceRoot?: string): string {\n const safe = (workspaceRoot || 'default').replace(/[^a-zA-Z0-9_-]/g, '_')\n return `dsh_files_expanded_${safe}`\n}\n\nfunction loadStoredExpandedPaths(workspaceRoot?: string): Set<string> | null {\n if (typeof window === 'undefined' || !window.localStorage) return null\n try {\n const raw = window.localStorage.getItem(getStorageKey(workspaceRoot))\n if (!raw) return null\n const list = JSON.parse(raw)\n if (Array.isArray(list)) return new Set<string>(list)\n } catch {}\n return null\n}\n\nfunction saveStoredExpandedPaths(workspaceRoot: string | undefined, paths: Set<string>): void {\n if (typeof window === 'undefined' || !window.localStorage) return\n try {\n window.localStorage.setItem(getStorageKey(workspaceRoot), JSON.stringify(Array.from(paths)))\n } catch {}\n}\n\n/**\n * 从当前 DOM 的 React Fiber 树或 Cordis RootContext 中提取当前活跃输入框的 SessionInputShell 实例\n */\nfunction findComposerShell(ctx: Context | null, sessionId?: string): any {\n // 1. 优先从 DOM 的 React Fiber 提取(直接命中当前活跃输入框的组件 props)\n try {\n const composerDom = document.querySelector<HTMLElement>(\n '[data-composer-input=\"true\"], [data-composer-input], [data-composer-card], div[role=\"textbox\"][contenteditable=\"true\"]'\n )\n if (composerDom) {\n const fiberKey = Object.keys(composerDom).find(k => k.startsWith('__reactFiber') || k.startsWith('__reactInternalInstance'))\n if (fiberKey) {\n let curr = (composerDom as any)[fiberKey]\n let depth = 0\n while (curr && depth < 25) {\n const p = curr.memoizedProps\n if (p) {\n if (p.keyboard && typeof p.keyboard.insertReference === 'function') {\n return p.keyboard\n }\n if (p.shell && typeof p.shell.insertReference === 'function') {\n return p.shell\n }\n }\n curr = curr.return\n depth++\n }\n }\n }\n } catch (e) {\n console.debug('[dsh-workspace-files] 从 Fiber 查找 keyboard 失败:', e)\n }\n\n // 2. 从 Cordis RootContext 查找\n if (ctx) {\n try {\n const root: any = (ctx as any).root || ctx\n const conversation = root.conversation || root.get?.('conversation') || (window as any).__dsh_conversation\n const inputService = conversation?.input || root['conversation.input'] || root.get?.('conversation.input')\n if (inputService) {\n if (sessionId) {\n const s = inputService.shell?.(sessionId) || inputService.shells?.get?.(sessionId)\n if (s) return s\n }\n if (inputService.shells instanceof Map && inputService.shells.size > 0) {\n const values = Array.from(inputService.shells.values())\n return values[values.length - 1]\n }\n }\n } catch (e) {\n console.debug('[dsh-workspace-files] 从 RootContext 查找 shell 失败:', e)\n }\n }\n\n return null\n}\n\n/**\n * 尝试向会话输入框插入原生的 ReferenceChipNode(官方胶囊 Tag 卡片)\n */\nfunction tryInsertNativeReferenceChip(ctx: Context | null, sessionId: string | undefined, item: FileItem): boolean {\n if (typeof document === 'undefined') return false\n try {\n // 聚焦输入框\n const composerDom = document.querySelector<HTMLElement>(\n '[data-composer-input=\"true\"], [data-composer-input], [data-composer-card] [contenteditable=\"true\"], div[role=\"textbox\"][contenteditable=\"true\"]'\n )\n if (composerDom) composerDom.focus()\n\n const shell = findComposerShell(ctx, sessionId)\n if (!shell) {\n return false\n }\n\n const cleanPath = item.path.replace(/\\\\/g, '/').replace(/^\\.?\\//, '')\n const mention = item.isDirectory ? (cleanPath.endsWith('/') ? `@${cleanPath}` : `@${cleanPath}/`) : `@${cleanPath}`\n const label = item.isDirectory ? (item.name.endsWith('/') ? item.name : `${item.name}/`) : item.name\n\n const reference = {\n source: 'reference',\n ref: mention,\n label,\n appearance: item.isDirectory ? 'folder' : 'file',\n clipboardText: mention,\n }\n\n const text = shell.projection?.detectText || ''\n let caret = typeof shell.projection?.caret === 'number' ? shell.projection.caret : text.length\n let start = caret\n const end = caret\n\n // 智能消除:若当前光标前是 '@',回退一个字符将其吃掉替换\n if (start > 0 && text[start - 1] === '@') {\n start = start - 1\n }\n\n const span = {\n draftRev: shell.rev,\n start,\n end,\n }\n\n // 优先调用原生 shell.insertReference 插入 Chip Tag\n if (typeof shell.insertReference === 'function') {\n const ok = shell.insertReference(reference, span)\n if (ok) return true\n }\n\n // 备用:尝试通过 session actx 派发事件\n const actx = shell.deps?.actx\n if (actx && typeof actx.bail === 'function') {\n const ok = actx.bail(actx, 'slash/input-insert-reference', { reference, span })\n if (ok === true) return true\n }\n } catch (err) {\n console.debug('[dsh-workspace-files] 插入原生 Chip 异常:', err)\n }\n return false\n}\n\n/**\n * 将引用文本注入到 DSH 当前会话的主输入框。\n * 兼容 DSH 官方基于 Lexical 的 ComposerContentEditable (div[data-composer-input])\n * 以及传统的 textarea / input,并自动消除用户手动输入的冗余 '@'。\n */\nfunction insertMentionToComposer(mentionText: string): boolean {\n if (typeof document === 'undefined') return false\n\n // 1. 查找 DSH 官方输入框(Lexical contenteditable 容器优先)\n const candidates = [\n document.querySelector<HTMLElement>('[data-composer-input=\"true\"]'),\n document.querySelector<HTMLElement>('[data-composer-input]'),\n document.querySelector<HTMLElement>('[data-composer-card] [contenteditable=\"true\"]'),\n document.querySelector<HTMLElement>('[contenteditable=\"true\"][role=\"textbox\"]'),\n document.querySelector<HTMLTextAreaElement>('textarea:not([readonly]):not(.dsh-files-search-input)'),\n ].filter(Boolean) as HTMLElement[]\n\n const target = candidates[0]\n if (!target) return false\n\n target.focus()\n\n // 策略 A: contenteditable (DSH 官方 Lexical 编辑器)\n if (target.getAttribute('contenteditable') === 'true' || target.isContentEditable) {\n const sel = window.getSelection()\n if (sel) {\n let isInTarget = false\n if (sel.rangeCount > 0) {\n const anchor = sel.anchorNode\n if (anchor && (anchor === target || target.contains(anchor))) {\n isInTarget = true\n }\n }\n if (!isInTarget) {\n const range = document.createRange()\n range.selectNodeContents(target)\n range.collapse(false) // 光标定位到文本最末尾\n sel.removeAllRanges()\n sel.addRange(range)\n } else {\n // 智能消除:若光标前一个字符是已键入的 '@',将其纳入选区进行覆盖替换,避免出现 '@@file'\n const range = sel.getRangeAt(0)\n if (range.collapsed && range.startContainer.nodeType === Node.TEXT_NODE) {\n const nodeText = range.startContainer.textContent || ''\n const offset = range.startOffset\n if (offset > 0 && nodeText[offset - 1] === '@') {\n range.setStart(range.startContainer, offset - 1)\n sel.removeAllRanges()\n sel.addRange(range)\n }\n }\n }\n }\n\n // 原生 execCommand('insertText') 会直接触发 Lexical 的 input/beforeinput 事件流并更新 React 状态\n let success = false\n try {\n success = document.execCommand('insertText', false, mentionText)\n } catch {}\n\n if (!success) {\n try {\n const evt = new InputEvent('beforeinput', {\n bubbles: true,\n cancelable: true,\n inputType: 'insertText',\n data: mentionText,\n })\n target.dispatchEvent(evt)\n success = true\n } catch {}\n }\n\n return success\n }\n\n // 策略 B: 普通 textarea / input\n if (target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement) {\n let start = target.selectionStart ?? target.value.length\n const end = target.selectionEnd ?? target.value.length\n const prev = target.value\n\n // 智能消除:若前面紧随 '@',覆盖它\n if (start > 0 && prev[start - 1] === '@') {\n start = start - 1\n }\n\n let success = false\n try {\n target.selectionStart = start\n target.selectionEnd = end\n success = document.execCommand('insertText', false, mentionText)\n } catch {}\n\n if (!success) {\n const next = prev.slice(0, start) + mentionText + prev.slice(end)\n const proto = target instanceof HTMLTextAreaElement ? window.HTMLTextAreaElement.prototype : window.HTMLInputElement.prototype\n const setter = Object.getOwnPropertyDescriptor(proto, 'value')?.set\n if (setter) {\n setter.call(target, next)\n } else {\n target.value = next\n }\n\n target.selectionStart = target.selectionEnd = start + mentionText.length\n target.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: mentionText }))\n target.dispatchEvent(new Event('change', { bubbles: true }))\n success = true\n }\n return success\n }\n\n return false\n}\n\nasync function call<T = any>(method: string, payload: Record<string, unknown> = {}): Promise<T> {\n let response: Response | null = await fetch(`/dsh-workspace-files/api/${method}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n }).catch(() => null)\n\n if (!response || !response.ok) {\n response = await fetch(`/sidebar/api/${method}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n }).catch(() => null)\n }\n\n if (!response) {\n throw new Error('网络请求失败:无法连接到文件服务')\n }\n\n const envelope = (await response.json().catch(() => null)) as {\n ok?: boolean\n value?: T\n error?: { message?: string }\n } | null\n\n if (!response.ok || envelope?.ok !== true || envelope.value === undefined) {\n throw new Error(envelope?.error?.message ?? `HTTP ${response.status}`)\n }\n return envelope.value\n}\n\n/* ── CSS Styles ── */\nfunction GlobalFilesStyle(): JSX.Element {\n return (\n <style>{`\n.dsh-files-root {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n background: var(--dsw-alias-bg-base, #ffffff);\n color: var(--dsw-alias-label-primary, #17233c);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n font-size: 12px;\n line-height: 1.4;\n overflow: hidden;\n position: relative;\n}\n\n/* ── Header ── */\n.dsh-files-header {\n flex: none;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.18));\n}\n.dsh-files-header-info {\n flex: 1;\n min-width: 0;\n}\n.dsh-files-title-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-files-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--dsw-alias-label-primary, inherit);\n}\n.dsh-files-stats-badge {\n font-size: 10px;\n font-weight: 500;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));\n padding: 1px 6px;\n border-radius: 99px;\n}\n.dsh-files-root-path {\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin-top: 1px;\n}\n\n/* ── Toolbar & Search ── */\n.dsh-files-toolbar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 8px 6px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.15));\n background: var(--dsw-alias-bg-base, #ffffff);\n}\n.dsh-files-search-wrap {\n position: relative;\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n}\n.dsh-files-search-icon {\n position: absolute;\n left: 7px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n pointer-events: none;\n display: flex;\n}\n.dsh-files-search-input {\n box-sizing: border-box;\n width: 100%;\n height: 25px;\n padding: 0 22px 0 26px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));\n border-radius: 4px;\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.06));\n color: inherit;\n font-size: 11.5px;\n outline: none;\n transition: all 0.15s ease;\n}\n.dsh-files-search-input:focus {\n background: var(--dsw-alias-bg-base, #ffffff);\n border-color: var(--dsw-alias-brand-primary, #4b70e2);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 15%, transparent);\n}\n.dsh-files-clear-btn {\n position: absolute;\n right: 5px;\n border: none;\n background: transparent;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n cursor: pointer;\n padding: 2px;\n display: flex;\n}\n.dsh-files-clear-btn:hover {\n color: var(--dsw-alias-label-primary, inherit);\n}\n.dsh-files-toolbar-btns {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n.dsh-files-tool-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n cursor: pointer;\n transition: all 0.12s ease;\n}\n.dsh-files-tool-btn:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary, inherit);\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));\n}\n.dsh-files-tool-btn.is-active {\n color: var(--dsw-alias-brand-primary, #4b70e2);\n background: var(--dsw-alias-interactive-bg-active, rgba(75,112,226,.15));\n}\n.dsh-files-tool-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n/* ── Tree Body ── */\n.dsh-files-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 4px 0;\n}\n.dsh-files-dir-block {\n display: flex;\n flex-direction: column;\n}\n.dsh-files-dir-row {\n display: flex;\n align-items: center;\n gap: 6px;\n height: 26px;\n padding-right: 8px;\n cursor: pointer;\n user-select: none;\n position: relative;\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n transition: background 0.12s ease;\n}\n.dsh-files-dir-row:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));\n color: var(--dsw-alias-label-primary, inherit);\n}\n.dsh-files-chevron {\n font-size: 10px;\n transition: transform 0.15s ease;\n display: inline-block;\n opacity: 0.8;\n}\n.dsh-files-chevron[data-collapsed='true'] {\n transform: rotate(-90deg);\n}\n.dsh-files-folder-icon {\n display: flex;\n}\n.dsh-files-folder-name {\n flex: 1;\n min-width: 0;\n font-weight: 500;\n font-size: 12px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-files-count-badge {\n font-size: 10px;\n font-weight: 600;\n padding: 0 5px;\n border-radius: 99px;\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n}\n\n/* ── File Row ── */\n.dsh-files-row {\n display: flex;\n align-items: center;\n gap: 6px;\n height: 26px;\n padding-right: 8px;\n cursor: pointer;\n user-select: none;\n position: relative;\n transition: background 0.12s ease;\n}\n.dsh-files-row:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));\n}\n.dsh-files-name {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-primary, inherit);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-files-size {\n font-size: 10px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n flex-shrink: 0;\n margin-right: 4px;\n}\n\n/* ── Hover Actions on Rows ── */\n.dsh-files-row-actions {\n display: none;\n align-items: center;\n gap: 3px;\n flex-shrink: 0;\n}\n.dsh-files-row:hover .dsh-files-row-actions,\n.dsh-files-dir-row:hover .dsh-files-row-actions,\n.dsh-files-flat-row:hover .dsh-files-row-actions {\n display: flex;\n}\n.dsh-files-row:hover .dsh-files-size,\n.dsh-files-dir-row:hover .dsh-files-count-badge,\n.dsh-files-flat-row:hover .dsh-files-size {\n display: none;\n}\n\n/* ── Flat Search Result List ── */\n.dsh-files-search-container {\n display: flex;\n flex-direction: column;\n}\n.dsh-files-search-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 12px;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 4%, transparent);\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.15));\n}\n.dsh-files-search-count {\n font-weight: 500;\n}\n.dsh-files-view-toggle-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));\n background: var(--dsw-alias-container-bg, var(--dsw-alias-bg-base, #ffffff));\n color: var(--dsw-alias-brand-primary, #4b70e2);\n cursor: pointer;\n font-size: 10.5px;\n font-weight: 500;\n padding: 2px 7px;\n border-radius: 4px;\n transition: all 0.12s ease;\n}\n.dsh-files-view-toggle-btn:hover {\n background: var(--dsw-alias-brand-primary, #4b70e2);\n color: #ffffff;\n border-color: var(--dsw-alias-brand-primary, #4b70e2);\n}\n.dsh-files-flat-list {\n padding: 4px 0;\n}\n.dsh-files-flat-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 12px;\n cursor: pointer;\n user-select: none;\n position: relative;\n transition: background 0.12s ease;\n min-height: 32px;\n}\n.dsh-files-flat-row:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));\n}\n.dsh-files-flat-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.dsh-files-flat-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.dsh-files-flat-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n}\n.dsh-files-flat-name {\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary, inherit);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-files-flat-parent {\n font-size: 10.5px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n opacity: 0.8;\n}\n.dsh-files-jump-hint {\n font-size: 10px;\n color: var(--dsw-alias-brand-primary, #4b70e2);\n opacity: 0;\n transition: opacity 0.12s ease;\n margin-right: 6px;\n font-weight: 500;\n white-space: nowrap;\n}\n.dsh-files-flat-row:hover .dsh-files-jump-hint {\n opacity: 0.85;\n}\n.dsh-files-flat-row.is-directory:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 6%, transparent);\n}\n.dsh-files-action-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n height: 20px;\n padding: 0 5px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));\n border-radius: 3px;\n background: var(--dsw-alias-container-bg, var(--dsw-alias-bg-base, #ffffff));\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n cursor: pointer;\n transition: all 0.12s ease;\n}\n.dsh-files-action-btn:hover {\n color: var(--dsw-alias-label-primary, inherit);\n border-color: var(--dsw-alias-border-l3, rgba(118,137,166,.4));\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.12));\n}\n.dsh-files-action-at {\n color: var(--dsw-alias-brand-primary, #4b70e2);\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 30%, transparent);\n background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 8%, transparent);\n}\n.dsh-files-action-at:hover {\n color: #ffffff;\n background: var(--dsw-alias-brand-primary, #4b70e2);\n border-color: var(--dsw-alias-brand-primary, #4b70e2);\n}\n.dsh-files-action-at-text {\n font-size: 10px;\n font-weight: 600;\n}\n\n/* ── Highlight & Toast ── */\n.dsh-files-highlight {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 25%, transparent);\n color: var(--dsw-alias-brand-primary, #4b70e2);\n font-weight: 600;\n border-radius: 2px;\n padding: 0 1px;\n}\n.dsh-files-toast {\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: var(--dsw-alias-label-primary, #17233c);\n color: var(--dsw-alias-bg-base, #ffffff);\n font-size: 11px;\n border-radius: 99px;\n box-shadow: 0 4px 16px rgba(0,0,0,.25);\n animation: dsh-files-fade-in 0.15s ease;\n z-index: 100;\n pointer-events: none;\n white-space: nowrap;\n}\n@keyframes dsh-files-fade-in {\n from { opacity: 0; transform: translate(-50%, 6px); }\n to { opacity: 1; transform: translate(-50%, 0); }\n}\n\n/* ── Empty & Centered ── */\n.dsh-files-centered {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 180px;\n gap: 10px;\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n}\n.dsh-files-spinner {\n width: 18px;\n height: 18px;\n border: 2px solid var(--dsw-alias-border-l2, rgba(118,137,166,.3));\n border-top-color: var(--dsw-alias-brand-primary, #4b70e2);\n border-radius: 50%;\n animation: dsh-files-spin 0.8s linear infinite;\n}\n@keyframes dsh-files-spin {\n to { transform: rotate(360deg); }\n}\n.dsh-files-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 36px 16px;\n text-align: center;\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n}\n.dsh-files-empty-icon {\n margin-bottom: 8px;\n opacity: 0.6;\n}\n.dsh-files-empty-title {\n font-weight: 600;\n font-size: 13px;\n margin-bottom: 4px;\n}\n.dsh-files-empty-detail {\n font-size: 11.5px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n}\n.dsh-files-banner-error {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 12px;\n font-size: 11.5px;\n color: var(--dsw-alias-state-error-primary, #e34c59);\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #e34c59) 10%, transparent);\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.2));\n}\n.dsh-files-banner-close {\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n`}</style>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["useState","useRef","useCallback","useMemo"],"sources":["../src/client/icons.tsx","../src/client/index.tsx"],"sourcesContent":["import type { JSX } from 'react'\n\nexport function IconFolder({ size = 15, open = false }: { size?: number; open?: boolean }): JSX.Element {\n if (open) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0, color: 'var(--dsw-alias-brand-primary, #4b70e2)' }}>\n <path d=\"M1.5 3.5A1.5 1.5 0 013 2h3l1.5 2H13a1.5 1.5 0 011.5 1.5v1H2.5l-1 7.5A1.5 1.5 0 003 15h10.5a1.5 1.5 0 001.5-1.5L14 6.5H2.5\" fill=\"currentColor\" fillOpacity=\"0.18\" />\n </svg>\n )\n }\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0, color: 'var(--dsw-alias-brand-primary, #4b70e2)' }}>\n <path d=\"M1.75 1A1.75 1.75 0 000 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0016 13.25v-8.5A1.75 1.75 0 0014.25 3H7.5a.25.25 0 01-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75z\" />\n </svg>\n )\n}\n\nexport function IconSearch({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"7\" cy=\"7\" r=\"5\" />\n <line x1=\"11\" y1=\"11\" x2=\"14.5\" y2=\"14.5\" />\n </svg>\n )\n}\n\nexport function IconAt({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path fillRule=\"evenodd\" d=\"M8 1a7 7 0 106.914 8.093.75.75 0 00-1.488-.186A5.5 5.5 0 1113.5 8c0 .64-.207 1.2-.6 1.597-.39.395-.94.653-1.65.653-.61 0-1.156-.25-1.5-.67-.344.42-.89.67-1.5.67A2.25 2.25 0 016 8a2.25 2.25 0 012.25-2.25c.61 0 1.156.25 1.5.67.344-.42.89-.67 1.5-.67.71 0 1.26.258 1.65.653.393.397.6 1.057.6 1.847A7.001 7.001 0 018 1zm0 5.75A1.25 1.25 0 108 9.25 1.25 1.25 0 008 6.75z\" />\n </svg>\n )\n}\n\nexport function IconCopy({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path d=\"M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z\" />\n <path d=\"M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z\" />\n </svg>\n )\n}\n\nexport function IconExpandAll({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 2 8 6 12 2\" />\n <polyline points=\"4 8 8 12 12 8\" />\n </svg>\n )\n}\n\nexport function IconCollapseAll({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 6 8 2 12 6\" />\n <polyline points=\"4 12 8 8 12 8\" />\n </svg>\n )\n}\n\nexport function IconRefresh({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path fillRule=\"evenodd\" d=\"M8 2.5a5.5 5.5 0 105.006 3.238.75.75 0 011.378-.592A7 7 0 118 1v1.5a.75.75 0 01-1.28.53L4.47 1.28a.75.75 0 010-1.06l2.25-1.75A.75.75 0 018-.75V1a7 7 0 010 1.5z\" />\n </svg>\n )\n}\n\nexport function IconClose({ size = 12 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path d=\"M3.72 3.72a.75.75 0 011.06 0L8 6.94l3.22-3.22a.75.75 0 111.06 1.06L9.06 8l3.22 3.22a.75.75 0 11-1.06 1.06L8 9.06l-3.22 3.22a.75.75 0 01-1.06-1.06L6.94 8 3.72 4.78a.75.75 0 010-1.06z\" />\n </svg>\n )\n}\n\nexport function IconCheck({ size = 12 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path fillRule=\"evenodd\" d=\"M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z\" />\n </svg>\n )\n}\n\nexport function FileGlyphIcon({ filename, size = 14 }: { filename: string; size?: number }): JSX.Element {\n const ext = filename.split('.').pop()?.toLowerCase() || ''\n\n // Color tokens\n let color = 'var(--dsw-alias-label-tertiary, #8c9ba5)'\n let badge = ''\n\n if (ext === 'ts' || ext === 'tsx') {\n color = '#3178c6'\n badge = ext === 'tsx' ? 'TSX' : 'TS'\n } else if (ext === 'js' || ext === 'jsx' || ext === 'mjs' || ext === 'cjs') {\n color = '#f7df1e'\n badge = 'JS'\n } else if (ext === 'json') {\n color = '#cbcb41'\n badge = '{}'\n } else if (ext === 'md' || ext === 'markdown') {\n color = '#42a5f5'\n badge = 'M↓'\n } else if (ext === 'drawio' || ext === 'dio') {\n color = '#f08705'\n badge = 'D'\n } else if (ext === 'css' || ext === 'scss' || ext === 'less') {\n color = '#42a5f5'\n badge = '#'\n } else if (ext === 'html' || ext === 'htm') {\n color = '#e44d26'\n badge = '<>'\n } else if (ext === 'py') {\n color = '#3776ab'\n badge = 'PY'\n } else if (ext === 'png' || ext === 'jpg' || ext === 'jpeg' || ext === 'svg' || ext === 'gif' || ext === 'webp') {\n color = '#26a69a'\n badge = 'IMG'\n } else if (ext === 'yml' || ext === 'yaml') {\n color = '#cb171e'\n badge = 'Y'\n }\n\n return (\n <span\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: size,\n height: size,\n fontSize: 9,\n fontWeight: 700,\n fontFamily: 'monospace',\n color,\n flexShrink: 0,\n }}\n title={filename}\n >\n {badge || '•'}\n </span>\n )\n}\n\nexport function IconList({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M2.5 12a.5.5 0 01.5-.5h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4a.5.5 0 01.5-.5h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4a.5.5 0 01.5-.5h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5z\" />\n </svg>\n )\n}\n\nexport function IconTree({ size = 13 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M2 3h4v4H2zM10 9h4v4h-4zM4 7v6h6\" />\n </svg>\n )\n}\n\nexport function IconChevronDown({ size = 14 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n )\n}\n\nexport function IconExplorer({ size = 12 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"currentColor\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path d=\"M1.75 2A1.75 1.75 0 000 3.75v8.5C0 13.216.784 14 1.75 14h12.5A1.75 1.75 0 0016 12.25v-6.5A1.75 1.75 0 0014.25 4H7.5a.25.25 0 01-.2-.1l-.9-1.2C6.07 2.26 5.55 2 5 2H1.75zM1.5 5.5h13v6.75a.25.25 0 01-.25.25H1.75a.25.25 0 01-.25-.25V5.5z\" />\n </svg>\n )\n}\n\nexport function IconExternalApp({ size = 12 }: { size?: number }): JSX.Element {\n return (\n <svg width={size} height={size} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.35\" strokeLinecap=\"round\" strokeLinejoin=\"round\" style={{ display: 'inline-block', verticalAlign: 'middle', flexShrink: 0 }}>\n <path d=\"M12.5 9.5v3.25a1.25 1.25 0 01-1.25 1.25H3.25A1.25 1.25 0 012 12.75V4.75A1.25 1.25 0 013.25 3.5H6.5\" />\n <polyline points=\"10 2 14 2 14 6\" />\n <line x1=\"6.5\" y1=\"9.5\" x2=\"13.5\" y2=\"2.5\" />\n </svg>\n )\n}\n\n\n","/**\n * Browser entry for the enhanced workspace files explorer plugin.\n * Overrides DSH official 'files' tab using 'priority: extension'.\n */\nimport type { Context } from '@deepseek-ai/cordis'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n FileGlyphIcon,\n IconAt,\n IconCheck,\n IconChevronDown,\n IconClose,\n IconCollapseAll,\n IconCopy,\n IconExpandAll,\n IconExplorer,\n IconExternalApp,\n IconFolder,\n IconList,\n IconRefresh,\n IconSearch,\n IconTree,\n} from './icons.js'\n\nexport const inject = ['slots', 'sidebarRightTabs']\n\n/** 构建时由 tsdown define 注入,避免卡片上的版本号与 package.json 漂移。 */\ndeclare const __PLUGIN_VERSION__: string\n\nlet globalCtx: Context | null = null\n\nconst OFFICIAL_FILES_TAB_ID = '@civilization/dsh-workspace-files'\n\nexport interface FileItem {\n name: string\n path: string\n isDirectory: boolean\n size?: number\n mtime?: number\n children?: FileItem[]\n}\n\nexport interface WorkspaceFilesResult {\n root: string\n items: FileItem[]\n totalFiles: number\n totalDirs: number\n}\n\nfunction FolderGuideGlyph({ size = 20, className }: { size?: number; className?: string }) {\n return (\n <span className={className} style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>\n <IconFolder size={size} />\n </span>\n )\n}\n\nfunction WorkspaceFilesTabTitle({ useTabInfo }: any): JSX.Element {\n const info = useTabInfo ? useTabInfo() : null\n const title = info?.tab?.title || '文件'\n return (\n <>\n <IconFolder size={15} />\n <span>{title}</span>\n </>\n )\n}\n\nfunction WorkspaceFilesTabBody(props: any): JSX.Element {\n const { sessionId, useSessions, useTabInfo } = props\n const tabInfo = useTabInfo ? useTabInfo() : null\n const tabActions = tabInfo?.tab?.actions\n\n const sessionCwd = useSessions ? useSessions((sessions: any) => sessions?.byId?.[sessionId]?.cwd) : undefined\n\n return (\n <WorkspaceFilesView\n sessionId={sessionId}\n cwd={sessionCwd}\n onOpenFile={(filePath: string) => {\n if (tabActions?.openResource && sessionId) {\n const normalized = filePath.replace(/\\\\/g, '/').replace(/^\\.?\\//, '')\n tabActions.openResource(`dsh-resource://file/session/${encodeURIComponent(sessionId)}/${encodeURIComponent(normalized)}`)\n }\n }}\n />\n )\n}\n\nexport function apply(ctx: Context): void {\n globalCtx = ctx\n const sidebarRightTabs = (ctx as any).sidebarRightTabs\n const slots = (ctx as any).slots\n\n if (sidebarRightTabs && slots) {\n // 关键:kind: 'files', priority: 'extension'(Rank 3 > builtin 2),完美接管官方文件标签页\n ctx.effect(() => sidebarRightTabs.register({\n id: OFFICIAL_FILES_TAB_ID,\n kind: 'files',\n priority: 'extension',\n title: () => '文件',\n guide: [{\n order: 10,\n title: () => '文件',\n description: () => '浏览、搜索与一键引用项目文件',\n icon: FolderGuideGlyph,\n }],\n }), 'dsh-workspace-files: override official files tab')\n\n ctx.effect(() => slots.inject('sidebar.right.pane.tab', () => slots.register({\n name: 'sidebar.right.pane.tab',\n key: OFFICIAL_FILES_TAB_ID,\n }, WorkspaceFilesTabBody)), 'dsh-workspace-files: official tab body')\n\n ctx.effect(() => slots.inject('sidebar.right.pane.tab.title', () => slots.register({\n name: 'sidebar.right.pane.tab.title',\n key: OFFICIAL_FILES_TAB_ID,\n }, WorkspaceFilesTabTitle)), 'dsh-workspace-files: official tab title')\n }\n\n // 设置中心“插件”页的自定义卡片:DSH 0.2.x 用 settings.plugins.tab(list 槽)承载\n // 各插件自己的配置视图,注册需要 id/order/label;旧版的 settings.plugin.item 槽与\n // settingsScope 服务在 0.2.0 已不存在。\n if (slots) {\n ctx.effect(() => slots.inject('settings.plugins.tab', () => slots.register({\n name: 'settings.plugins.tab',\n id: 'workspace-files',\n order: 20,\n label: () => '工作区文件',\n }, WorkspaceFilesSettingsCard)), 'dsh-workspace-files: settings card')\n }\n}\n\n/* ── Workspace Files Configuration Store ── */\nexport interface WorkspaceFilesConfig {\n maxDepth: number\n showHidden: boolean\n}\n\nconst CONFIG_STORAGE_KEY = 'dsh_workspace_files_config'\n\nexport function loadWorkspaceFilesConfig(): WorkspaceFilesConfig {\n try {\n const raw = typeof localStorage !== 'undefined' ? localStorage.getItem(CONFIG_STORAGE_KEY) : null\n if (raw) {\n const parsed = JSON.parse(raw)\n return {\n maxDepth: typeof parsed.maxDepth === 'number' && parsed.maxDepth > 0 ? parsed.maxDepth : 16,\n showHidden: Boolean(parsed.showHidden),\n }\n }\n } catch {}\n return { maxDepth: 16, showHidden: false }\n}\n\nexport function saveWorkspaceFilesConfig(cfg: WorkspaceFilesConfig): void {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(CONFIG_STORAGE_KEY, JSON.stringify(cfg))\n }\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent('dsh-workspace-files:config-change', { detail: cfg }))\n }\n fetch('/dsh-workspace-files/api/config.set', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(cfg),\n }).catch(() => {})\n } catch {}\n}\n\nfunction ensureSettingsStyle() {\n if (typeof document === 'undefined') return\n const id = 'dsh-workspace-files-settings-style'\n if (document.getElementById(id)) return\n const style = document.createElement('style')\n style.id = id\n style.textContent = `\n.dsh-wf-card {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n background: var(--dsw-alias-bg-layer-3, #fff);\n border-radius: 12px;\n list-style: none;\n transition: border-color .16s, background .16s;\n box-sizing: border-box;\n}\n.dsh-wf-card-open {\n background: var(--dsw-alias-bg-layer-2, #f7f8fa);\n border-color: var(--dsw-alias-label-dimmed, #c8ccd4);\n}\n.dsh-wf-header {\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n background: 0 0;\n border: 0;\n border-radius: 12px;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n display: flex;\n}\n.dsh-wf-head-text {\n flex-direction: column;\n flex: 1;\n gap: 4px;\n min-width: 0;\n display: flex;\n}\n.dsh-wf-name {\n color: var(--dsw-alias-label-primary, #1f2328);\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-wf-version {\n font-size: 12px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n}\n.dsh-wf-desc {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 13px;\n line-height: 1.5;\n}\n.dsh-wf-chevron {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n flex: none;\n transition: transform .16s ease-in-out;\n display: inline-flex;\n}\n.dsh-wf-chevron-open {\n transform: rotate(180deg);\n}\n.dsh-wf-body {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n margin: 0 16px;\n padding: 8px 0 12px;\n}\n.dsh-wf-row {\n align-items: center;\n gap: 16px;\n padding: 12px 0;\n display: flex;\n justify-content: space-between;\n}\n.dsh-wf-row + .dsh-wf-row {\n border-top: 1px solid var(--dsw-alias-border-l2, rgba(118, 137, 166, 0.12));\n}\n.dsh-wf-label-box {\n flex-direction: column;\n flex: 1;\n gap: 3px;\n min-width: 0;\n display: flex;\n}\n.dsh-wf-label {\n font-size: 13.5px;\n font-weight: 550;\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n.dsh-wf-hint {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-size: 12px;\n line-height: 18px;\n}\n.dsh-wf-ctrl {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-wf-seg {\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n gap: 2px;\n padding: 2px;\n display: inline-flex;\n background: var(--dsw-alias-bg-layer-1, rgba(255, 255, 255, 0.05));\n}\n.dsh-wf-seg-btn {\n font: inherit;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n background: 0 0;\n border: none;\n border-radius: 6px;\n padding: 4px 10px;\n font-size: 12px;\n line-height: 18px;\n transition: all 0.15s;\n}\n.dsh-wf-seg-btn:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n.dsh-wf-seg-active {\n background: var(--dsw-alias-bg-layer-3, #eef0f4);\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n font-weight: 600;\n box-shadow: 0 1px 2px rgba(0,0,0,0.05);\n}\n.dsh-wf-input {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2, #d1d5db);\n background: var(--dsw-alias-bg-layer-3, #fff);\n width: 64px;\n text-align: center;\n color: var(--dsw-alias-label-primary, #1f2328);\n font: inherit;\n border-radius: 7px;\n padding: 4px 6px;\n font-size: 12.5px;\n line-height: 18px;\n}\n.dsh-wf-input:focus {\n border-color: var(--dsw-alias-brand-primary, #4f6ef7);\n outline: 2px solid color-mix(in srgb, var(--dsw-alias-brand-primary, #4f6ef7) 18%, transparent);\n}\n.dsh-wf-toggle {\n position: relative;\n display: inline-block;\n width: 40px;\n height: 22px;\n cursor: pointer;\n}\n.dsh-wf-toggle input {\n opacity: 0;\n width: 0;\n height: 0;\n position: absolute;\n}\n.dsh-wf-toggle-track {\n position: absolute;\n top: 0; left: 0; right: 0; bottom: 0;\n background-color: var(--dsw-alias-border-l2, #ccc);\n transition: .2s cubic-bezier(.4, 0, .2, 1);\n border-radius: 22px;\n}\n.dsh-wf-toggle input:checked + .dsh-wf-toggle-track {\n background-color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n.dsh-wf-toggle-thumb {\n position: absolute;\n height: 16px;\n width: 16px;\n left: 3px;\n bottom: 3px;\n background-color: white;\n transition: .2s cubic-bezier(.4, 0, .2, 1);\n border-radius: 50%;\n box-shadow: 0 1px 3px rgba(0,0,0,0.2);\n}\n.dsh-wf-toggle input:checked + .dsh-wf-toggle-track .dsh-wf-toggle-thumb {\n transform: translateX(18px);\n}\n.dsh-wf-footer {\n margin-top: 8px;\n padding-top: 10px;\n border-top: 1px solid var(--dsw-alias-border-l2, rgba(118, 137, 166, 0.12));\n display: flex;\n align-items: center;\n justify-content: space-between;\n}\n.dsh-wf-saved-hint {\n font-size: 11.5px;\n color: var(--dsw-alias-state-success-primary, #10b981);\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.dsh-wf-btn-reset {\n background: transparent;\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 6px;\n padding: 3px 10px;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n cursor: pointer;\n transition: all 0.15s;\n}\n.dsh-wf-btn-reset:hover {\n background: var(--dsw-alias-bg-layer-2, rgba(255,255,255,0.08));\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n`\n document.head.appendChild(style)\n}\n\nexport function WorkspaceFilesSettingsCard(): JSX.Element {\n const [open, setOpen] = useState(false)\n const [config, setConfig] = useState<WorkspaceFilesConfig>(() => loadWorkspaceFilesConfig())\n const [savedTick, setSavedTick] = useState(false)\n\n useEffect(() => {\n ensureSettingsStyle()\n }, [])\n\n const updateConfig = (patch: Partial<WorkspaceFilesConfig>) => {\n const next = { ...config, ...patch }\n setConfig(next)\n saveWorkspaceFilesConfig(next)\n setSavedTick(true)\n setTimeout(() => setSavedTick(false), 2000)\n }\n\n const handleDepthSelect = (depth: number) => {\n updateConfig({ maxDepth: depth })\n }\n\n const handleDepthInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n const val = parseInt(e.target.value, 10)\n if (!isNaN(val) && val >= 1 && val <= 100) {\n updateConfig({ maxDepth: val })\n }\n }\n\n const handleToggleHidden = () => {\n updateConfig({ showHidden: !config.showHidden })\n }\n\n const handleReset = () => {\n const def = { maxDepth: 16, showHidden: false }\n setConfig(def)\n saveWorkspaceFilesConfig(def)\n setSavedTick(true)\n setTimeout(() => setSavedTick(false), 2000)\n }\n\n return (\n <div className={open ? 'dsh-wf-card dsh-wf-card-open' : 'dsh-wf-card'}>\n <button\n type=\"button\"\n className=\"dsh-wf-header\"\n aria-expanded={open}\n onClick={() => setOpen(!open)}\n >\n <div className=\"dsh-wf-head-text\">\n <div className=\"dsh-wf-name\">\n <span>工作区文件</span>\n <span className=\"dsh-wf-version\">v{__PLUGIN_VERSION__}</span>\n </div>\n <div className=\"dsh-wf-desc\">\n 浏览与检索工作区文件树,支持递归目录扫描与一键引用。\n </div>\n </div>\n <span className={open ? 'dsh-wf-chevron dsh-wf-chevron-open' : 'dsh-wf-chevron'}>\n <IconChevronDown size={14} />\n </span>\n </button>\n\n {open && (\n <div className=\"dsh-wf-body\">\n <div className=\"dsh-wf-row\">\n <div className=\"dsh-wf-label-box\">\n <div className=\"dsh-wf-label\">目录扫描最大深度</div>\n <div className=\"dsh-wf-hint\">\n 工作区递归扫描的最大目录层级(默认 16,范围 1~100)。若工程目录较深可适当调大。\n </div>\n </div>\n <div className=\"dsh-wf-ctrl\">\n <div className=\"dsh-wf-seg\">\n {[8, 16, 32, 64].map((d) => (\n <button\n key={d}\n type=\"button\"\n className={config.maxDepth === d ? 'dsh-wf-seg-btn dsh-wf-seg-active' : 'dsh-wf-seg-btn'}\n onClick={() => handleDepthSelect(d)}\n >\n {d}\n </button>\n ))}\n </div>\n <input\n type=\"number\"\n min=\"1\"\n max=\"100\"\n className=\"dsh-wf-input\"\n value={config.maxDepth}\n onChange={handleDepthInput}\n title=\"自定义深度 (1-100)\"\n />\n </div>\n </div>\n\n <div className=\"dsh-wf-row\">\n <div className=\"dsh-wf-label-box\">\n <div className=\"dsh-wf-label\">默认显示隐藏文件</div>\n <div className=\"dsh-wf-hint\">\n 打开文件树时是否默认展示以点开头的隐藏文件或文件夹(如 .gitignore, .env 等)。\n </div>\n </div>\n <div className=\"dsh-wf-ctrl\">\n <label className=\"dsh-wf-toggle\">\n <input\n type=\"checkbox\"\n checked={config.showHidden}\n onChange={handleToggleHidden}\n />\n <span className=\"dsh-wf-toggle-track\">\n <span className=\"dsh-wf-toggle-thumb\" />\n </span>\n </label>\n </div>\n </div>\n\n <div className=\"dsh-wf-footer\">\n <div>\n {savedTick ? (\n <span className=\"dsh-wf-saved-hint\">\n <IconCheck size={12} />\n <span>已保存设置</span>\n </span>\n ) : (\n <span style={{ fontSize: 11, color: 'var(--dsw-alias-label-tertiary, #8b93a1)' }}>\n 设置改动即时生效并同步至工作区文件树\n </span>\n )}\n </div>\n <button\n type=\"button\"\n className=\"dsh-wf-btn-reset\"\n onClick={handleReset}\n >\n 恢复默认\n </button>\n </div>\n </div>\n )}\n </div>\n )\n}\n\n/* ── Main Workspace Files View ── */\nfunction WorkspaceFilesView({\n sessionId,\n cwd,\n onOpenFile,\n}: {\n sessionId?: string\n cwd?: string\n onOpenFile: (path: string) => void\n}): JSX.Element {\n const [data, setData] = useState<WorkspaceFilesResult | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [query, setQuery] = useState('')\n const [toast, setToast] = useState<string | null>(null)\n const [expandedPaths, setExpandedPaths] = useState<Set<string>>(() => new Set())\n const [activeConfig, setActiveConfig] = useState<WorkspaceFilesConfig>(() => loadWorkspaceFilesConfig())\n const [showHidden, setShowHidden] = useState(() => loadWorkspaceFilesConfig().showHidden)\n\n const toastTimer = useRef<number | null>(null)\n\n const showToastMsg = useCallback((msg: string) => {\n setToast(msg)\n if (toastTimer.current) window.clearTimeout(toastTimer.current)\n toastTimer.current = window.setTimeout(() => setToast(null), 2000)\n }, [])\n\n useEffect(() => {\n const handleCfgChange = (e: any) => {\n if (e.detail) {\n setActiveConfig(e.detail)\n setShowHidden(Boolean(e.detail.showHidden))\n }\n }\n window.addEventListener('dsh-workspace-files:config-change', handleCfgChange)\n return () => window.removeEventListener('dsh-workspace-files:config-change', handleCfgChange)\n }, [])\n\n const loadTree = useCallback(async (quiet = false, forceRefresh = false) => {\n if (!quiet) setLoading(true)\n setError(null)\n try {\n const res = await call<WorkspaceFilesResult>('files.tree', {\n sessionId,\n cwd,\n showHidden,\n maxDepth: activeConfig.maxDepth,\n forceRefresh,\n })\n setData(res)\n\n // 默认折叠,并从 localStorage 恢复已记录的展开状态\n setExpandedPaths(prev => {\n if (prev.size > 0) return prev\n const stored = loadStoredExpandedPaths(res.root || cwd)\n if (stored !== null) return stored\n // 默认全部关闭,不展开任何目录\n return new Set<string>()\n })\n } catch (err: any) {\n setError(err?.message || '无法加载文件列表')\n } finally {\n if (!quiet) setLoading(false)\n }\n }, [sessionId, cwd, showHidden, activeConfig.maxDepth])\n\n useEffect(() => {\n void loadTree()\n }, [loadTree])\n\n const handleToggleExpand = (path: string) => {\n setExpandedPaths(prev => {\n const next = new Set(prev)\n if (next.has(path)) next.delete(path)\n else next.add(path)\n saveStoredExpandedPaths(data?.root || cwd, next)\n return next\n })\n }\n\n const handleExpandAll = () => {\n if (!data) return\n const all = new Set<string>()\n function collect(items: FileItem[]) {\n for (const it of items) {\n if (it.isDirectory) {\n all.add(it.path)\n if (it.children) collect(it.children)\n }\n }\n }\n collect(data.items)\n setExpandedPaths(all)\n saveStoredExpandedPaths(data.root || cwd, all)\n }\n\n const handleCollapseAll = () => {\n const empty = new Set<string>()\n setExpandedPaths(empty)\n saveStoredExpandedPaths(data?.root || cwd, empty)\n }\n\n // 搜索时点击文件夹:跳回树形视图并展开该目录及全部祖先路径,自动平滑定位\n const handleJumpToFolderInTree = (dirPath: string) => {\n const parts = dirPath.split('/')\n const toExpand: string[] = []\n let acc = ''\n for (const p of parts) {\n if (!p) continue\n acc = acc ? `${acc}/${p}` : p\n toExpand.push(acc)\n }\n\n setExpandedPaths(prev => {\n const next = new Set(prev)\n for (const p of toExpand) {\n next.add(p)\n }\n saveStoredExpandedPaths(data?.root || cwd, next)\n return next\n })\n\n // 退出搜索状态回到树形视图\n setQuery('')\n showToastMsg(`已定位并展开目录: ${dirPath}/`)\n\n // 平滑滚动定位到该目录节点\n setTimeout(() => {\n try {\n const el = document.querySelector(`[data-tree-path=\"${dirPath}\"]`)\n if (el) {\n el.scrollIntoView({ block: 'center', behavior: 'smooth' })\n }\n } catch {}\n }, 60)\n }\n\n // 复制相对路径\n const handleCopyPath = (e: React.MouseEvent, path: string) => {\n e.stopPropagation()\n void navigator.clipboard.writeText(path).then(() => {\n showToastMsg(`已复制路径: ${path}`)\n })\n }\n\n // 一键 @ 引用到当前对话框输入框(优先插入官方原生交互式 Chip 胶囊)\n const handleMention = (e: React.MouseEvent, itemOrPath: string | FileItem) => {\n e.stopPropagation()\n const itemObj: FileItem = typeof itemOrPath === 'string'\n ? { name: itemOrPath.split('/').pop() || itemOrPath, path: itemOrPath, isDirectory: false }\n : itemOrPath\n\n const mentionText = formatMentionText(itemObj.path, itemObj.isDirectory)\n\n // 1. 优先尝试向会话输入框插入官方原生 ReferenceChipNode 胶囊卡片\n let inserted = false\n try {\n inserted = tryInsertNativeReferenceChip(globalCtx, sessionId, itemObj)\n } catch (err) {\n console.warn('[dsh-workspace-files] 原生 Chip 插入失败:', err)\n }\n\n // 2. 若原生 Chip 插入未成功,无缝降级为规范纯文本插入\n if (!inserted) {\n try {\n inserted = insertMentionToComposer(mentionText)\n } catch (err) {\n console.warn('[dsh-workspace-files] 降级纯文本插入失败:', err)\n }\n }\n\n // 写入剪贴板作为双重保障\n const displayName = itemObj.isDirectory ? `${itemObj.name}/` : itemObj.name\n void navigator.clipboard.writeText(mentionText.trim()).then(() => {\n if (inserted) {\n showToastMsg(`已引用${itemObj.isDirectory ? '目录' : '文件'}: ${displayName}`)\n } else {\n showToastMsg(`已复制引用: ${mentionText.trim()}`)\n }\n })\n }\n\n // 在文件资源管理器中定位/打开\n const handleRevealInExplorer = (e: React.MouseEvent, item: FileItem) => {\n e.stopPropagation()\n fetch('/dsh-workspace-files/api/files.open', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n action: 'reveal',\n path: item.path,\n isDirectory: Boolean(item.isDirectory),\n sessionId,\n cwd,\n }),\n })\n .then(res => res.json())\n .then(data => {\n if (data.ok) {\n showToastMsg(`已在资源管理器中显示: ${item.name}`)\n } else {\n showToastMsg(`打开失败: ${data.error?.message || '未知错误'}`)\n }\n })\n .catch(err => {\n showToastMsg(`请求失败: ${err?.message || String(err)}`)\n })\n }\n\n // 用系统默认应用打开\n const handleOpenDefaultApp = (e: React.MouseEvent, item: FileItem) => {\n e.stopPropagation()\n fetch('/dsh-workspace-files/api/files.open', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n action: 'openDefault',\n path: item.path,\n isDirectory: Boolean(item.isDirectory),\n sessionId,\n cwd,\n }),\n })\n .then(res => res.json())\n .then(data => {\n if (data.ok) {\n showToastMsg(`已启动系统应用打开: ${item.name}`)\n } else {\n showToastMsg(`打开失败: ${data.error?.message || '未知错误'}`)\n }\n })\n .catch(err => {\n showToastMsg(`请求失败: ${err?.message || String(err)}`)\n })\n }\n\n const [searchViewMode, setSearchViewMode] = useState<'flat' | 'tree'>('flat')\n const [searchExpandedPaths, setSearchExpandedPaths] = useState<Set<string>>(() => new Set())\n\n // 过滤树与扁平结果\n const { filteredTreeItems, flatSearchResults } = useMemo(() => {\n if (!data) return { filteredTreeItems: [], flatSearchResults: [] }\n const q = query.trim().toLowerCase()\n if (!q) return { filteredTreeItems: data.items, flatSearchResults: [] }\n\n // 扁平结果列表\n const flat: Array<{ item: FileItem; parentDir: string }> = []\n function traverseFlat(items: FileItem[], parentDir: string) {\n for (const it of items) {\n const match = it.name.toLowerCase().includes(q) || it.path.toLowerCase().includes(q)\n if (match) {\n flat.push({ item: it, parentDir })\n }\n if (it.isDirectory && it.children) {\n traverseFlat(it.children, it.path)\n }\n }\n }\n traverseFlat(data.items, '')\n\n // 树形过滤集合\n function filterNode(node: FileItem): FileItem | null {\n const selfMatch = node.name.toLowerCase().includes(q) || node.path.toLowerCase().includes(q)\n if (node.isDirectory) {\n const filteredChildren: FileItem[] = []\n for (const child of node.children || []) {\n const matchedChild = filterNode(child)\n if (matchedChild) filteredChildren.push(matchedChild)\n }\n if (selfMatch || filteredChildren.length > 0) {\n return { ...node, children: filteredChildren }\n }\n return null\n }\n return selfMatch ? node : null\n }\n\n const tree: FileItem[] = []\n for (const rootNode of data.items) {\n const matched = filterNode(rootNode)\n if (matched) tree.push(matched)\n }\n\n return { filteredTreeItems: tree, flatSearchResults: flat }\n }, [data, query])\n\n // 搜索关键字变化时,自动展开匹配的目录树节点,并允许用户后续自由折叠/展开\n useEffect(() => {\n if (!query.trim() || !data) return\n const q = query.trim().toLowerCase()\n const autoExpand = new Set<string>()\n function collect(items: FileItem[]) {\n for (const it of items) {\n if (it.isDirectory) {\n const selfMatch = it.name.toLowerCase().includes(q) || it.path.toLowerCase().includes(q)\n const childMatch = it.children?.some(c => c.name.toLowerCase().includes(q) || c.path.toLowerCase().includes(q))\n if (selfMatch || childMatch) autoExpand.add(it.path)\n if (it.children) collect(it.children)\n }\n }\n }\n collect(data.items)\n setSearchExpandedPaths(autoExpand)\n }, [query, data])\n\n const isSearchActive = Boolean(query.trim())\n\n return (\n <div className=\"dsh-files-root\">\n <GlobalFilesStyle />\n\n {/* Header */}\n <header className=\"dsh-files-header\">\n <div className=\"dsh-files-header-info\">\n <div className=\"dsh-files-title-row\">\n <span className=\"dsh-files-title\">文件</span>\n {data && (\n <span className=\"dsh-files-stats-badge\">\n {data.totalFiles} 文件 · {data.totalDirs} 目录\n </span>\n )}\n </div>\n <div className=\"dsh-files-root-path\" title={data?.root || cwd}>\n {data?.root || cwd || '当前会话没有工作目录'}\n </div>\n </div>\n </header>\n\n {/* Search & Actions Toolbar */}\n <div className=\"dsh-files-toolbar\">\n <div className=\"dsh-files-search-wrap\">\n <span className=\"dsh-files-search-icon\"><IconSearch size={13} /></span>\n <input\n type=\"text\"\n className=\"dsh-files-search-input\"\n placeholder=\"搜索文件 (支持路径筛选)...\"\n value={query}\n onChange={e => setQuery(e.target.value)}\n onKeyDown={e => {\n if (e.key === 'Escape') setQuery('')\n }}\n />\n {query && (\n <button\n type=\"button\"\n className=\"dsh-files-clear-btn\"\n onClick={() => setQuery('')}\n title=\"清除搜索\"\n >\n <IconClose size={12} />\n </button>\n )}\n </div>\n\n <div className=\"dsh-files-toolbar-btns\">\n {isSearchActive ? (\n <button\n type=\"button\"\n className=\"dsh-files-tool-btn is-active\"\n onClick={() => setSearchViewMode(searchViewMode === 'flat' ? 'tree' : 'flat')}\n title={searchViewMode === 'flat' ? '当前为扁平列表,点击切换为树形视图' : '当前为树形视图,点击切换为扁平列表'}\n >\n {searchViewMode === 'flat' ? <IconTree size={13} /> : <IconList size={13} />}\n </button>\n ) : (\n <>\n <button\n type=\"button\"\n className=\"dsh-files-tool-btn\"\n onClick={handleExpandAll}\n title=\"全部展开\"\n >\n <IconExpandAll size={13} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-tool-btn\"\n onClick={handleCollapseAll}\n title=\"全部折叠\"\n >\n <IconCollapseAll size={13} />\n </button>\n </>\n )}\n\n <button\n type=\"button\"\n className={`dsh-files-tool-btn ${showHidden ? 'is-active' : ''}`}\n onClick={() => setShowHidden(!showHidden)}\n title={showHidden ? '隐藏点号开头的文件' : '显示点号开头的文件'}\n >\n <span style={{ fontSize: 11, fontWeight: 700 }}>.*</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-tool-btn\"\n onClick={() => void loadTree(false, true)}\n disabled={loading}\n title=\"刷新文件树\"\n >\n <IconRefresh size={13} />\n </button>\n </div>\n </div>\n\n {/* Error Banner */}\n {error && (\n <div className=\"dsh-files-banner-error\">\n <span>{error}</span>\n <button type=\"button\" className=\"dsh-files-banner-close\" onClick={() => setError(null)}>\n <IconClose size={12} />\n </button>\n </div>\n )}\n\n {/* Tree / Search Results Content */}\n <div className=\"dsh-files-body\">\n {loading && !data ? (\n <div className=\"dsh-files-centered\">\n <div className=\"dsh-files-spinner\" />\n <span>加载文件…</span>\n </div>\n ) : isSearchActive && flatSearchResults.length === 0 ? (\n <div className=\"dsh-files-empty\">\n <div className=\"dsh-files-empty-icon\"><IconFolder size={26} /></div>\n <div className=\"dsh-files-empty-title\">未搜索到匹配的文件</div>\n <div className=\"dsh-files-empty-detail\">请尝试更换搜索关键字,或按 Esc 清除搜索。</div>\n </div>\n ) : !isSearchActive && (!data || data.items.length === 0) ? (\n <div className=\"dsh-files-empty\">\n <div className=\"dsh-files-empty-icon\"><IconFolder size={26} /></div>\n <div className=\"dsh-files-empty-title\">工作区为空</div>\n <div className=\"dsh-files-empty-detail\">当前工作目录下暂无可显示的文件。</div>\n </div>\n ) : isSearchActive && searchViewMode === 'flat' ? (\n /* ── 扁平搜索结果列表 ── */\n <div className=\"dsh-files-search-container\">\n <div className=\"dsh-files-search-header\">\n <span className=\"dsh-files-search-count\">\n 找到 {flatSearchResults.length} 个匹配项\n {flatSearchResults.length > 150 ? '(展示前 150 项)' : ''}\n </span>\n <button\n type=\"button\"\n className=\"dsh-files-view-toggle-btn\"\n onClick={() => setSearchViewMode('tree')}\n title=\"切换为可折叠的树形视图\"\n >\n <IconTree size={12} />\n <span>切为树形</span>\n </button>\n </div>\n <div className=\"dsh-files-flat-list\">\n {flatSearchResults.slice(0, 150).map(({ item, parentDir }) => (\n <div\n key={item.path}\n className={`dsh-files-flat-row ${item.isDirectory ? 'is-directory' : ''}`}\n onClick={() => {\n if (item.isDirectory) {\n handleJumpToFolderInTree(item.path)\n } else {\n onOpenFile(item.path)\n }\n }}\n title={item.isDirectory ? `点击退出搜索并定位展开目录: ${item.path}/` : `点击预览打开文件: ${item.path}`}\n >\n <span className=\"dsh-files-flat-icon\">\n {item.isDirectory ? <IconFolder size={14} /> : <FileGlyphIcon filename={item.name} size={14} />}\n </span>\n <div className=\"dsh-files-flat-info\">\n <div className=\"dsh-files-flat-top\">\n <span className=\"dsh-files-flat-name\">\n <HighlightText text={item.name} query={query} />\n {item.isDirectory && '/'}\n </span>\n {item.size !== undefined && (\n <span className=\"dsh-files-size\">{formatFileSize(item.size)}</span>\n )}\n {item.isDirectory && (\n <span className=\"dsh-files-jump-hint\">跳回展开 ›</span>\n )}\n </div>\n {parentDir && (\n <div className=\"dsh-files-flat-parent\" title={parentDir}>\n {parentDir}\n </div>\n )}\n </div>\n <div className=\"dsh-files-row-actions\">\n <button\n type=\"button\"\n className=\"dsh-files-action-btn dsh-files-action-at\"\n onClick={e => handleMention(e, item)}\n title={`一键 @ 引用此${item.isDirectory ? '目录' : '文件'}到当前会话`}\n >\n <IconAt size={13} />\n <span className=\"dsh-files-action-at-text\">@引用</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => handleRevealInExplorer(e, item)}\n title={`在文件资源管理器中显示此${item.isDirectory ? '目录' : '文件'}`}\n >\n <IconExplorer size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => handleOpenDefaultApp(e, item)}\n title={`用系统默认应用打开此${item.isDirectory ? '目录' : '文件'}`}\n >\n <IconExternalApp size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => handleCopyPath(e, item.path)}\n title=\"复制相对路径\"\n >\n <IconCopy size={12} />\n </button>\n </div>\n </div>\n ))}\n {flatSearchResults.length > 150 && (\n <div style={{ padding: '10px 14px', fontSize: 11, textAlign: 'center', color: 'var(--dsw-alias-label-tertiary, #8b93a1)', borderTop: '1px dashed var(--dsw-alias-border-l2, #e5e7eb)' }}>\n 匹配项较多,已限制展示前 150 项以保证流畅度,请输入更详细关键字\n </div>\n )}\n </div>\n </div>\n ) : (\n /* ── 树形视图(普通模式或搜索树模式) ── */\n <div className=\"dsh-files-tree\">\n {isSearchActive && (\n <div className=\"dsh-files-search-header\">\n <span className=\"dsh-files-search-count\">树形匹配(自由折叠/展开)</span>\n <button\n type=\"button\"\n className=\"dsh-files-view-toggle-btn\"\n onClick={() => setSearchViewMode('flat')}\n title=\"切换为扁平搜索结果列表\"\n >\n <IconList size={12} />\n <span>切为列表</span>\n </button>\n </div>\n )}\n {filteredTreeItems.map(item => (\n <FileTreeNode\n key={item.path}\n item={item}\n depth={0}\n query={query}\n isSearchMode={isSearchActive}\n expandedPaths={isSearchActive ? searchExpandedPaths : expandedPaths}\n onToggleExpand={(path: string) => {\n if (isSearchActive) {\n setSearchExpandedPaths(prev => {\n const next = new Set(prev)\n if (next.has(path)) next.delete(path)\n else next.add(path)\n return next\n })\n } else {\n handleToggleExpand(path)\n }\n }}\n onOpenFile={onOpenFile}\n onMention={handleMention}\n onCopyPath={handleCopyPath}\n onRevealInExplorer={handleRevealInExplorer}\n onOpenDefaultApp={handleOpenDefaultApp}\n />\n ))}\n </div>\n )}\n </div>\n\n {/* Toast Notification */}\n {toast && (\n <div className=\"dsh-files-toast\">\n <IconCheck size={12} />\n <span>{toast}</span>\n </div>\n )}\n </div>\n )\n}\n\n/* ── Tree Node Component ── */\nfunction FileTreeNode(props: {\n item: FileItem\n depth: number\n query: string\n isSearchMode: boolean\n expandedPaths: Set<string>\n onToggleExpand: (path: string) => void\n onOpenFile: (path: string) => void\n onMention: (e: React.MouseEvent, item: FileItem) => void\n onCopyPath: (e: React.MouseEvent, path: string) => void\n onRevealInExplorer: (e: React.MouseEvent, item: FileItem) => void\n onOpenDefaultApp: (e: React.MouseEvent, item: FileItem) => void\n}): JSX.Element {\n const {\n item,\n depth,\n query,\n isSearchMode,\n expandedPaths,\n onToggleExpand,\n onOpenFile,\n onMention,\n onCopyPath,\n onRevealInExplorer,\n onOpenDefaultApp,\n } = props\n const isExpanded = expandedPaths.has(item.path)\n\n if (item.isDirectory) {\n const childCount = item.children?.length ?? 0\n return (\n <div className=\"dsh-files-dir-block\">\n <div\n className=\"dsh-files-dir-row\"\n data-tree-path={item.path}\n style={{ paddingLeft: `${depth * 14 + 10}px` }}\n onClick={() => onToggleExpand(item.path)}\n >\n <span className=\"dsh-files-chevron\" data-collapsed={!isExpanded ? 'true' : undefined}>▾</span>\n <span className=\"dsh-files-folder-icon\">\n <IconFolder size={14} open={isExpanded} />\n </span>\n <span className=\"dsh-files-folder-name\" title={item.path}>\n <HighlightText text={item.name} query={query} />\n </span>\n <span className=\"dsh-files-count-badge\">{childCount}</span>\n\n <div className=\"dsh-files-row-actions\">\n <button\n type=\"button\"\n className=\"dsh-files-action-btn dsh-files-action-at\"\n onClick={e => onMention(e, item)}\n title=\"一键 @ 引用此目录到当前会话\"\n >\n <IconAt size={13} />\n <span className=\"dsh-files-action-at-text\">@引用</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onRevealInExplorer(e, item)}\n title=\"在文件资源管理器中打开此目录\"\n >\n <IconExplorer size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onOpenDefaultApp(e, item)}\n title=\"用系统默认应用打开此目录\"\n >\n <IconExternalApp size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onCopyPath(e, item.path)}\n title=\"复制目录路径\"\n >\n <IconCopy size={12} />\n </button>\n </div>\n </div>\n {isExpanded && item.children && (\n <div className=\"dsh-files-children\">\n {item.children.map(child => (\n <FileTreeNode\n key={child.path}\n item={child}\n depth={depth + 1}\n query={query}\n isSearchMode={isSearchMode}\n expandedPaths={expandedPaths}\n onToggleExpand={onToggleExpand}\n onOpenFile={onOpenFile}\n onMention={onMention}\n onCopyPath={onCopyPath}\n onRevealInExplorer={onRevealInExplorer}\n onOpenDefaultApp={onOpenDefaultApp}\n />\n ))}\n </div>\n )}\n </div>\n )\n }\n\n // File item row\n return (\n <div\n className=\"dsh-files-row\"\n data-tree-path={item.path}\n style={{ paddingLeft: `${depth * 14 + 10}px` }}\n onClick={() => onOpenFile(item.path)}\n title={`点击打开: ${item.path}`}\n >\n <FileGlyphIcon filename={item.name} size={14} />\n <span className=\"dsh-files-name\">\n <HighlightText text={item.name} query={query} />\n </span>\n\n {item.size !== undefined && (\n <span className=\"dsh-files-size\" title={`大小: ${item.size} 字节`}>\n {formatFileSize(item.size)}\n </span>\n )}\n\n {/* Row Hover Actions */}\n <div className=\"dsh-files-row-actions\">\n <button\n type=\"button\"\n className=\"dsh-files-action-btn dsh-files-action-at\"\n onClick={e => onMention(e, item)}\n title=\"一键 @ 引用此文件到当前会话\"\n >\n <IconAt size={13} />\n <span className=\"dsh-files-action-at-text\">@引用</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onRevealInExplorer(e, item)}\n title=\"在文件资源管理器中显示此文件\"\n >\n <IconExplorer size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onOpenDefaultApp(e, item)}\n title=\"用系统默认应用打开此文件\"\n >\n <IconExternalApp size={12} />\n </button>\n <button\n type=\"button\"\n className=\"dsh-files-action-btn\"\n onClick={e => onCopyPath(e, item.path)}\n title=\"复制相对路径\"\n >\n <IconCopy size={12} />\n </button>\n </div>\n </div>\n )\n}\n\n/* ── Helpers ── */\nfunction HighlightText({ text, query }: { text: string; query: string }): JSX.Element {\n const q = query.trim().toLowerCase()\n if (!q) return <span>{text}</span>\n const index = text.toLowerCase().indexOf(q)\n if (index === -1) return <span>{text}</span>\n\n const before = text.slice(0, index)\n const match = text.slice(index, index + q.length)\n const after = text.slice(index + q.length)\n\n return (\n <span>\n {before}\n <mark className=\"dsh-files-highlight\">{match}</mark>\n {after}\n </span>\n )\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n const kb = bytes / 1024\n if (kb < 1024) return `${kb.toFixed(1)} KB`\n const mb = kb / 1024\n return `${mb.toFixed(1)} MB`\n}\n\n/**\n * 按照 DSH 官方规范格式化引用路径:\n * - 纯路径无空格:@path\n * - 路径含空格:@\"path\"\n * - 目录末尾保留斜杠:@folder/ 或 @\"folder/\"\n */\nfunction formatMentionText(path: string, isDirectory = false): string {\n const cleanPath = path.replace(/\\\\/g, '/').replace(/^\\.?\\//, '')\n const finalPath = isDirectory ? (cleanPath.endsWith('/') ? cleanPath : `${cleanPath}/`) : cleanPath\n if (/\\s/u.test(finalPath)) {\n return `@\"${finalPath}\" `\n }\n return `@${finalPath} `\n}\n\nfunction getStorageKey(workspaceRoot?: string): string {\n const safe = (workspaceRoot || 'default').replace(/[^a-zA-Z0-9_-]/g, '_')\n return `dsh_files_expanded_${safe}`\n}\n\nfunction loadStoredExpandedPaths(workspaceRoot?: string): Set<string> | null {\n if (typeof window === 'undefined' || !window.localStorage) return null\n try {\n const raw = window.localStorage.getItem(getStorageKey(workspaceRoot))\n if (!raw) return null\n const list = JSON.parse(raw)\n if (Array.isArray(list)) return new Set<string>(list)\n } catch {}\n return null\n}\n\nfunction saveStoredExpandedPaths(workspaceRoot: string | undefined, paths: Set<string>): void {\n if (typeof window === 'undefined' || !window.localStorage) return\n try {\n window.localStorage.setItem(getStorageKey(workspaceRoot), JSON.stringify(Array.from(paths)))\n } catch {}\n}\n\n/**\n * 从当前 DOM 的 React Fiber 树或 Cordis RootContext 中提取当前活跃输入框的 SessionInputShell 实例\n */\nfunction findComposerShell(ctx: Context | null, sessionId?: string): any {\n // 1. 优先从 DOM 的 React Fiber 提取(直接命中当前活跃输入框的组件 props)\n try {\n const composerDom = document.querySelector<HTMLElement>(\n '[data-composer-input=\"true\"], [data-composer-input], [data-composer-card], div[role=\"textbox\"][contenteditable=\"true\"]'\n )\n if (composerDom) {\n const fiberKey = Object.keys(composerDom).find(k => k.startsWith('__reactFiber') || k.startsWith('__reactInternalInstance'))\n if (fiberKey) {\n let curr = (composerDom as any)[fiberKey]\n let depth = 0\n while (curr && depth < 25) {\n const p = curr.memoizedProps\n if (p) {\n if (p.keyboard && typeof p.keyboard.insertReference === 'function') {\n return p.keyboard\n }\n if (p.shell && typeof p.shell.insertReference === 'function') {\n return p.shell\n }\n }\n curr = curr.return\n depth++\n }\n }\n }\n } catch (e) {\n console.debug('[dsh-workspace-files] 从 Fiber 查找 keyboard 失败:', e)\n }\n\n // 2. 从 Cordis RootContext 查找\n if (ctx) {\n try {\n const root: any = (ctx as any).root || ctx\n const conversation = root.conversation || root.get?.('conversation') || (window as any).__dsh_conversation\n const inputService = conversation?.input || root['conversation.input'] || root.get?.('conversation.input')\n if (inputService) {\n if (sessionId) {\n const s = inputService.shell?.(sessionId) || inputService.shells?.get?.(sessionId)\n if (s) return s\n }\n if (inputService.shells instanceof Map && inputService.shells.size > 0) {\n const values = Array.from(inputService.shells.values())\n return values[values.length - 1]\n }\n }\n } catch (e) {\n console.debug('[dsh-workspace-files] 从 RootContext 查找 shell 失败:', e)\n }\n }\n\n return null\n}\n\n/**\n * 尝试向会话输入框插入原生的 ReferenceChipNode(官方胶囊 Tag 卡片)\n */\nfunction tryInsertNativeReferenceChip(ctx: Context | null, sessionId: string | undefined, item: FileItem): boolean {\n if (typeof document === 'undefined') return false\n try {\n // 聚焦输入框\n const composerDom = document.querySelector<HTMLElement>(\n '[data-composer-input=\"true\"], [data-composer-input], [data-composer-card] [contenteditable=\"true\"], div[role=\"textbox\"][contenteditable=\"true\"]'\n )\n if (composerDom) composerDom.focus()\n\n const shell = findComposerShell(ctx, sessionId)\n if (!shell) {\n return false\n }\n\n const cleanPath = item.path.replace(/\\\\/g, '/').replace(/^\\.?\\//, '')\n const mention = item.isDirectory ? (cleanPath.endsWith('/') ? `@${cleanPath}` : `@${cleanPath}/`) : `@${cleanPath}`\n const label = item.isDirectory ? (item.name.endsWith('/') ? item.name : `${item.name}/`) : item.name\n\n const reference = {\n source: 'reference',\n ref: mention,\n label,\n appearance: item.isDirectory ? 'folder' : 'file',\n clipboardText: mention,\n }\n\n const text = shell.projection?.detectText || ''\n let caret = typeof shell.projection?.caret === 'number' ? shell.projection.caret : text.length\n let start = caret\n const end = caret\n\n // 智能消除:若当前光标前是 '@',回退一个字符将其吃掉替换\n if (start > 0 && text[start - 1] === '@') {\n start = start - 1\n }\n\n const span = {\n draftRev: shell.rev,\n start,\n end,\n }\n\n // 优先调用原生 shell.insertReference 插入 Chip Tag\n if (typeof shell.insertReference === 'function') {\n const ok = shell.insertReference(reference, span)\n if (ok) return true\n }\n\n // 备用:尝试通过 session actx 派发事件\n const actx = shell.deps?.actx\n if (actx && typeof actx.bail === 'function') {\n const ok = actx.bail(actx, 'slash/input-insert-reference', { reference, span })\n if (ok === true) return true\n }\n } catch (err) {\n console.debug('[dsh-workspace-files] 插入原生 Chip 异常:', err)\n }\n return false\n}\n\n/**\n * 将引用文本注入到 DSH 当前会话的主输入框。\n * 兼容 DSH 官方基于 Lexical 的 ComposerContentEditable (div[data-composer-input])\n * 以及传统的 textarea / input,并自动消除用户手动输入的冗余 '@'。\n */\nfunction insertMentionToComposer(mentionText: string): boolean {\n if (typeof document === 'undefined') return false\n\n // 1. 查找 DSH 官方输入框(Lexical contenteditable 容器优先)\n const candidates = [\n document.querySelector<HTMLElement>('[data-composer-input=\"true\"]'),\n document.querySelector<HTMLElement>('[data-composer-input]'),\n document.querySelector<HTMLElement>('[data-composer-card] [contenteditable=\"true\"]'),\n document.querySelector<HTMLElement>('[contenteditable=\"true\"][role=\"textbox\"]'),\n document.querySelector<HTMLTextAreaElement>('textarea:not([readonly]):not(.dsh-files-search-input)'),\n ].filter(Boolean) as HTMLElement[]\n\n const target = candidates[0]\n if (!target) return false\n\n target.focus()\n\n // 策略 A: contenteditable (DSH 官方 Lexical 编辑器)\n if (target.getAttribute('contenteditable') === 'true' || target.isContentEditable) {\n const sel = window.getSelection()\n if (sel) {\n let isInTarget = false\n if (sel.rangeCount > 0) {\n const anchor = sel.anchorNode\n if (anchor && (anchor === target || target.contains(anchor))) {\n isInTarget = true\n }\n }\n if (!isInTarget) {\n const range = document.createRange()\n range.selectNodeContents(target)\n range.collapse(false) // 光标定位到文本最末尾\n sel.removeAllRanges()\n sel.addRange(range)\n } else {\n // 智能消除:若光标前一个字符是已键入的 '@',将其纳入选区进行覆盖替换,避免出现 '@@file'\n const range = sel.getRangeAt(0)\n if (range.collapsed && range.startContainer.nodeType === Node.TEXT_NODE) {\n const nodeText = range.startContainer.textContent || ''\n const offset = range.startOffset\n if (offset > 0 && nodeText[offset - 1] === '@') {\n range.setStart(range.startContainer, offset - 1)\n sel.removeAllRanges()\n sel.addRange(range)\n }\n }\n }\n }\n\n // 原生 execCommand('insertText') 会直接触发 Lexical 的 input/beforeinput 事件流并更新 React 状态\n let success = false\n try {\n success = document.execCommand('insertText', false, mentionText)\n } catch {}\n\n if (!success) {\n try {\n const evt = new InputEvent('beforeinput', {\n bubbles: true,\n cancelable: true,\n inputType: 'insertText',\n data: mentionText,\n })\n target.dispatchEvent(evt)\n success = true\n } catch {}\n }\n\n return success\n }\n\n // 策略 B: 普通 textarea / input\n if (target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement) {\n let start = target.selectionStart ?? target.value.length\n const end = target.selectionEnd ?? target.value.length\n const prev = target.value\n\n // 智能消除:若前面紧随 '@',覆盖它\n if (start > 0 && prev[start - 1] === '@') {\n start = start - 1\n }\n\n let success = false\n try {\n target.selectionStart = start\n target.selectionEnd = end\n success = document.execCommand('insertText', false, mentionText)\n } catch {}\n\n if (!success) {\n const next = prev.slice(0, start) + mentionText + prev.slice(end)\n const proto = target instanceof HTMLTextAreaElement ? window.HTMLTextAreaElement.prototype : window.HTMLInputElement.prototype\n const setter = Object.getOwnPropertyDescriptor(proto, 'value')?.set\n if (setter) {\n setter.call(target, next)\n } else {\n target.value = next\n }\n\n target.selectionStart = target.selectionEnd = start + mentionText.length\n target.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: mentionText }))\n target.dispatchEvent(new Event('change', { bubbles: true }))\n success = true\n }\n return success\n }\n\n return false\n}\n\nasync function call<T = any>(method: string, payload: Record<string, unknown> = {}): Promise<T> {\n let response: Response | null = await fetch(`/dsh-workspace-files/api/${method}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n }).catch(() => null)\n\n if (!response || !response.ok) {\n response = await fetch(`/sidebar/api/${method}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n }).catch(() => null)\n }\n\n if (!response) {\n throw new Error('网络请求失败:无法连接到文件服务')\n }\n\n const envelope = (await response.json().catch(() => null)) as {\n ok?: boolean\n value?: T\n error?: { message?: string }\n } | null\n\n if (!response.ok || envelope?.ok !== true || envelope.value === undefined) {\n throw new Error(envelope?.error?.message ?? `HTTP ${response.status}`)\n }\n return envelope.value\n}\n\n/* ── CSS Styles ── */\nfunction GlobalFilesStyle(): JSX.Element {\n return (\n <style>{`\n.dsh-files-root {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n box-sizing: border-box;\n background: var(--dsw-alias-bg-base, #ffffff);\n color: var(--dsw-alias-label-primary, #17233c);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n font-size: 12px;\n line-height: 1.4;\n overflow: hidden;\n position: relative;\n}\n\n/* ── Header ── */\n.dsh-files-header {\n flex: none;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.18));\n}\n.dsh-files-header-info {\n flex: 1;\n min-width: 0;\n}\n.dsh-files-title-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.dsh-files-title {\n font-weight: 600;\n font-size: 13px;\n color: var(--dsw-alias-label-primary, inherit);\n}\n.dsh-files-stats-badge {\n font-size: 10px;\n font-weight: 500;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));\n padding: 1px 6px;\n border-radius: 99px;\n}\n.dsh-files-root-path {\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin-top: 1px;\n}\n\n/* ── Toolbar & Search ── */\n.dsh-files-toolbar {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 8px 6px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.15));\n background: var(--dsw-alias-bg-base, #ffffff);\n}\n.dsh-files-search-wrap {\n position: relative;\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: center;\n}\n.dsh-files-search-icon {\n position: absolute;\n left: 7px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n pointer-events: none;\n display: flex;\n}\n.dsh-files-search-input {\n box-sizing: border-box;\n width: 100%;\n height: 25px;\n padding: 0 22px 0 26px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));\n border-radius: 4px;\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.06));\n color: inherit;\n font-size: 11.5px;\n outline: none;\n transition: all 0.15s ease;\n}\n.dsh-files-search-input:focus {\n background: var(--dsw-alias-bg-base, #ffffff);\n border-color: var(--dsw-alias-brand-primary, #4b70e2);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 15%, transparent);\n}\n.dsh-files-clear-btn {\n position: absolute;\n right: 5px;\n border: none;\n background: transparent;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n cursor: pointer;\n padding: 2px;\n display: flex;\n}\n.dsh-files-clear-btn:hover {\n color: var(--dsw-alias-label-primary, inherit);\n}\n.dsh-files-toolbar-btns {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n.dsh-files-tool-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 4px;\n background: transparent;\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n cursor: pointer;\n transition: all 0.12s ease;\n}\n.dsh-files-tool-btn:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary, inherit);\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));\n}\n.dsh-files-tool-btn.is-active {\n color: var(--dsw-alias-brand-primary, #4b70e2);\n background: var(--dsw-alias-interactive-bg-active, rgba(75,112,226,.15));\n}\n.dsh-files-tool-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n/* ── Tree Body ── */\n.dsh-files-body {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overflow-x: hidden;\n padding: 4px 0;\n}\n.dsh-files-dir-block {\n display: flex;\n flex-direction: column;\n}\n.dsh-files-dir-row {\n display: flex;\n align-items: center;\n gap: 6px;\n height: 26px;\n padding-right: 8px;\n cursor: pointer;\n user-select: none;\n position: relative;\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n transition: background 0.12s ease;\n}\n.dsh-files-dir-row:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));\n color: var(--dsw-alias-label-primary, inherit);\n}\n.dsh-files-chevron {\n font-size: 10px;\n transition: transform 0.15s ease;\n display: inline-block;\n opacity: 0.8;\n}\n.dsh-files-chevron[data-collapsed='true'] {\n transform: rotate(-90deg);\n}\n.dsh-files-folder-icon {\n display: flex;\n}\n.dsh-files-folder-name {\n flex: 1;\n min-width: 0;\n font-weight: 500;\n font-size: 12px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-files-count-badge {\n font-size: 10px;\n font-weight: 600;\n padding: 0 5px;\n border-radius: 99px;\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n}\n\n/* ── File Row ── */\n.dsh-files-row {\n display: flex;\n align-items: center;\n gap: 6px;\n height: 26px;\n padding-right: 8px;\n cursor: pointer;\n user-select: none;\n position: relative;\n transition: background 0.12s ease;\n}\n.dsh-files-row:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));\n}\n.dsh-files-name {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-primary, inherit);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-files-size {\n font-size: 10px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n flex-shrink: 0;\n margin-right: 4px;\n}\n\n/* ── Hover Actions on Rows ── */\n.dsh-files-row-actions {\n display: none;\n align-items: center;\n gap: 3px;\n flex-shrink: 0;\n}\n.dsh-files-row:hover .dsh-files-row-actions,\n.dsh-files-dir-row:hover .dsh-files-row-actions,\n.dsh-files-flat-row:hover .dsh-files-row-actions {\n display: flex;\n}\n.dsh-files-row:hover .dsh-files-size,\n.dsh-files-dir-row:hover .dsh-files-count-badge,\n.dsh-files-flat-row:hover .dsh-files-size {\n display: none;\n}\n\n/* ── Flat Search Result List ── */\n.dsh-files-search-container {\n display: flex;\n flex-direction: column;\n}\n.dsh-files-search-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 12px;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 4%, transparent);\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.15));\n}\n.dsh-files-search-count {\n font-weight: 500;\n}\n.dsh-files-view-toggle-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));\n background: var(--dsw-alias-container-bg, var(--dsw-alias-bg-base, #ffffff));\n color: var(--dsw-alias-brand-primary, #4b70e2);\n cursor: pointer;\n font-size: 10.5px;\n font-weight: 500;\n padding: 2px 7px;\n border-radius: 4px;\n transition: all 0.12s ease;\n}\n.dsh-files-view-toggle-btn:hover {\n background: var(--dsw-alias-brand-primary, #4b70e2);\n color: #ffffff;\n border-color: var(--dsw-alias-brand-primary, #4b70e2);\n}\n.dsh-files-flat-list {\n padding: 4px 0;\n}\n.dsh-files-flat-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 12px;\n cursor: pointer;\n user-select: none;\n position: relative;\n transition: background 0.12s ease;\n min-height: 32px;\n}\n.dsh-files-flat-row:hover {\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));\n}\n.dsh-files-flat-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n.dsh-files-flat-info {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n.dsh-files-flat-top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 6px;\n}\n.dsh-files-flat-name {\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary, inherit);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.dsh-files-flat-parent {\n font-size: 10.5px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n opacity: 0.8;\n}\n.dsh-files-jump-hint {\n font-size: 10px;\n color: var(--dsw-alias-brand-primary, #4b70e2);\n opacity: 0;\n transition: opacity 0.12s ease;\n margin-right: 6px;\n font-weight: 500;\n white-space: nowrap;\n}\n.dsh-files-flat-row:hover .dsh-files-jump-hint {\n opacity: 0.85;\n}\n.dsh-files-flat-row.is-directory:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 6%, transparent);\n}\n.dsh-files-action-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 3px;\n height: 20px;\n padding: 0 5px;\n border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));\n border-radius: 3px;\n background: var(--dsw-alias-container-bg, var(--dsw-alias-bg-base, #ffffff));\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n cursor: pointer;\n transition: all 0.12s ease;\n}\n.dsh-files-action-btn:hover {\n color: var(--dsw-alias-label-primary, inherit);\n border-color: var(--dsw-alias-border-l3, rgba(118,137,166,.4));\n background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.12));\n}\n.dsh-files-action-at {\n color: var(--dsw-alias-brand-primary, #4b70e2);\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 30%, transparent);\n background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 8%, transparent);\n}\n.dsh-files-action-at:hover {\n color: #ffffff;\n background: var(--dsw-alias-brand-primary, #4b70e2);\n border-color: var(--dsw-alias-brand-primary, #4b70e2);\n}\n.dsh-files-action-at-text {\n font-size: 10px;\n font-weight: 600;\n}\n\n/* ── Highlight & Toast ── */\n.dsh-files-highlight {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 25%, transparent);\n color: var(--dsw-alias-brand-primary, #4b70e2);\n font-weight: 600;\n border-radius: 2px;\n padding: 0 1px;\n}\n.dsh-files-toast {\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: var(--dsw-alias-label-primary, #17233c);\n color: var(--dsw-alias-bg-base, #ffffff);\n font-size: 11px;\n border-radius: 99px;\n box-shadow: 0 4px 16px rgba(0,0,0,.25);\n animation: dsh-files-fade-in 0.15s ease;\n z-index: 100;\n pointer-events: none;\n white-space: nowrap;\n}\n@keyframes dsh-files-fade-in {\n from { opacity: 0; transform: translate(-50%, 6px); }\n to { opacity: 1; transform: translate(-50%, 0); }\n}\n\n/* ── Empty & Centered ── */\n.dsh-files-centered {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 180px;\n gap: 10px;\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n}\n.dsh-files-spinner {\n width: 18px;\n height: 18px;\n border: 2px solid var(--dsw-alias-border-l2, rgba(118,137,166,.3));\n border-top-color: var(--dsw-alias-brand-primary, #4b70e2);\n border-radius: 50%;\n animation: dsh-files-spin 0.8s linear infinite;\n}\n@keyframes dsh-files-spin {\n to { transform: rotate(360deg); }\n}\n.dsh-files-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 36px 16px;\n text-align: center;\n color: var(--dsw-alias-label-secondary, #6f7f9b);\n}\n.dsh-files-empty-icon {\n margin-bottom: 8px;\n opacity: 0.6;\n}\n.dsh-files-empty-title {\n font-weight: 600;\n font-size: 13px;\n margin-bottom: 4px;\n}\n.dsh-files-empty-detail {\n font-size: 11.5px;\n color: var(--dsw-alias-label-tertiary, #8c9ba5);\n}\n.dsh-files-banner-error {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 12px;\n font-size: 11.5px;\n color: var(--dsw-alias-state-error-primary, #e34c59);\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #e34c59) 10%, transparent);\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.2));\n}\n.dsh-files-banner-close {\n border: none;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n`}</style>\n )\n}\n"],"mappings":"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"}
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { exec, spawn } from "node:child_process";
2
- import { isAbsolute, join, relative, resolve } from "node:path";
1
+ import { spawn } from "node:child_process";
2
+ import { isAbsolute, join, relative, resolve, sep } from "node:path";
3
3
  import Schema from "@deepseek-ai/schemastery";
4
4
  import { promises } from "node:fs";
5
5
  //#region src/files.ts
@@ -181,6 +181,30 @@ function writeJson(res, status, body) {
181
181
  });
182
182
  res.end(data);
183
183
  }
184
+ /**
185
+ * 拒绝工作区之外的目标:files.open 的 path 来自请求体,必须是工作区内的相对/绝对路径,
186
+ * 否则模型或页面脚本可以借宿主进程去打开任意本地路径。
187
+ */
188
+ function assertInsideWorkspace(cwd, fullPath) {
189
+ const root = resolve(cwd);
190
+ const target = resolve(fullPath);
191
+ const rel = relative(root, target);
192
+ if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) throw new Error("Path must stay inside the workspace.");
193
+ }
194
+ /**
195
+ * 启动系统文件管理器/默认应用。spawn 在命令不存在时会 emit 'error',
196
+ * 没有监听器就会变成未捕获异常拖垮宿主进程,因此这里必须兜住。
197
+ */
198
+ function launch(command, args) {
199
+ const child = spawn(command, args, {
200
+ detached: true,
201
+ stdio: "ignore"
202
+ });
203
+ child.on("error", (err) => {
204
+ console.warn(`[dsh-workspace-files] failed to launch ${command}:`, err?.message || String(err));
205
+ });
206
+ child.unref();
207
+ }
184
208
  function resolveCwd(ctx, body) {
185
209
  if (body.cwd?.trim()) return body.cwd.trim();
186
210
  if (body.root?.trim()) return body.root.trim();
@@ -198,20 +222,6 @@ function apply(ctx, config = {}) {
198
222
  maxDepth: typeof config?.maxDepth === "number" && config.maxDepth > 0 ? config.maxDepth : 16,
199
223
  showHidden: Boolean(config?.showHidden)
200
224
  };
201
- if (ctx.inject) ctx.inject(["settings"], (scopedCtx) => {
202
- try {
203
- const scope = scopedCtx.settings?.register(SETTINGS_NS, Config, { base: liveConfig });
204
- const applyChange = () => {
205
- const current = scope?.get?.();
206
- if (typeof current?.maxDepth === "number") liveConfig.maxDepth = current.maxDepth;
207
- if (typeof current?.showHidden === "boolean") liveConfig.showHidden = current.showHidden;
208
- };
209
- applyChange();
210
- scope?.watch?.(applyChange);
211
- } catch (err) {
212
- console.warn("[dsh-workspace-files] failed to register settings scope:", err);
213
- }
214
- });
215
225
  const webServer = ctx.webServer;
216
226
  if (!webServer) return;
217
227
  const handleRpc = async (req, res, prefix) => {
@@ -261,37 +271,17 @@ function apply(ctx, config = {}) {
261
271
  return;
262
272
  }
263
273
  const fullPath = isAbsolute(rawPath) ? rawPath : resolve(cwd, rawPath);
274
+ assertInsideWorkspace(cwd, fullPath);
264
275
  const action = body.action || "reveal";
265
276
  const isDirectory = Boolean(body.isDirectory);
266
277
  if (process.platform === "win32") {
267
278
  const winPath = fullPath.replace(/\//g, "\\");
268
- if (action === "reveal") {
269
- if (isDirectory) spawn("explorer.exe", [winPath], {
270
- detached: true,
271
- stdio: "ignore"
272
- }).unref();
273
- else spawn("explorer.exe", [`/select,${winPath}`], {
274
- detached: true,
275
- stdio: "ignore"
276
- }).unref();
277
- } else exec(`start "" "${winPath.replace(/"/g, "\\\"")}"`, { windowsHide: true });
279
+ launch("explorer.exe", action === "reveal" && !isDirectory ? [`/select,${winPath}`] : [winPath]);
278
280
  } else if (process.platform === "darwin") {
279
- if (action === "reveal") spawn("open", [isDirectory ? fullPath : "-R", fullPath], {
280
- detached: true,
281
- stdio: "ignore"
282
- }).unref();
283
- else spawn("open", [fullPath], {
284
- detached: true,
285
- stdio: "ignore"
286
- }).unref();
287
- } else if (action === "reveal") spawn("xdg-open", [isDirectory ? fullPath : resolve(fullPath, "..")], {
288
- detached: true,
289
- stdio: "ignore"
290
- }).unref();
291
- else spawn("xdg-open", [fullPath], {
292
- detached: true,
293
- stdio: "ignore"
294
- }).unref();
281
+ if (action === "reveal") launch("open", [isDirectory ? fullPath : "-R", fullPath]);
282
+ else launch("open", [fullPath]);
283
+ } else if (action === "reveal") launch("xdg-open", [isDirectory ? fullPath : resolve(fullPath, "..")]);
284
+ else launch("xdg-open", [fullPath]);
295
285
  writeJson(res, 200, { ok: true });
296
286
  } catch (err) {
297
287
  writeJson(res, 500, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@civilization/dsh-workspace-files",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Enhanced workspace file tree explorer with fuzzy search and @-mention for DeepSeek Harness.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -24,6 +24,9 @@ import {
24
24
 
25
25
  export const inject = ['slots', 'sidebarRightTabs']
26
26
 
27
+ /** 构建时由 tsdown define 注入,避免卡片上的版本号与 package.json 漂移。 */
28
+ declare const __PLUGIN_VERSION__: string
29
+
27
30
  let globalCtx: Context | null = null
28
31
 
29
32
  const OFFICIAL_FILES_TAB_ID = '@civilization/dsh-workspace-files'
@@ -115,28 +118,16 @@ export function apply(ctx: Context): void {
115
118
  }, WorkspaceFilesTabTitle)), 'dsh-workspace-files: official tab title')
116
119
  }
117
120
 
118
- // 注入设置中心“插件配置”卡片(命名空间必须为 workspace-files,与 Host settings 服务注册一致)
119
- const registerSettingsCard = (targetCtx: any) => {
120
- if (!targetCtx?.slots) return
121
- targetCtx.effect?.(() => targetCtx.slots.inject('settings.plugin.item', function* () {
122
- yield targetCtx.slots.register({
123
- name: 'settings.plugin.item',
124
- key: 'workspace-files',
125
- }, WorkspaceFilesSettingsCard)
126
- yield targetCtx.slots.register({
127
- name: 'settings.plugin.item',
128
- key: '@civilization/dsh-workspace-files',
129
- }, WorkspaceFilesSettingsCard)
130
- }), 'dsh-workspace-files: settings card')
131
- }
132
-
121
+ // 设置中心“插件”页的自定义卡片:DSH 0.2.x 用 settings.plugins.tab(list 槽)承载
122
+ // 各插件自己的配置视图,注册需要 id/order/label;旧版的 settings.plugin.item 槽与
123
+ // settingsScope 服务在 0.2.0 已不存在。
133
124
  if (slots) {
134
- registerSettingsCard(ctx)
135
- }
136
- if ((ctx as any).inject) {
137
- (ctx as any).inject(['settingsScope'], (scoped: any) => {
138
- registerSettingsCard(scoped)
139
- })
125
+ ctx.effect(() => slots.inject('settings.plugins.tab', () => slots.register({
126
+ name: 'settings.plugins.tab',
127
+ id: 'workspace-files',
128
+ order: 20,
129
+ label: () => '工作区文件',
130
+ }, WorkspaceFilesSettingsCard)), 'dsh-workspace-files: settings card')
140
131
  }
141
132
  }
142
133
 
@@ -453,7 +444,7 @@ export function WorkspaceFilesSettingsCard(): JSX.Element {
453
444
  <div className="dsh-wf-head-text">
454
445
  <div className="dsh-wf-name">
455
446
  <span>工作区文件</span>
456
- <span className="dsh-wf-version">v0.3.0</span>
447
+ <span className="dsh-wf-version">v{__PLUGIN_VERSION__}</span>
457
448
  </div>
458
449
  <div className="dsh-wf-desc">
459
450
  浏览与检索工作区文件树,支持递归目录扫描与一键引用。
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { exec, spawn } from 'node:child_process'
2
- import { isAbsolute, resolve } from 'node:path'
1
+ import { spawn } from 'node:child_process'
2
+ import { isAbsolute, relative, resolve, sep } from 'node:path'
3
3
  import type { Context } from '@deepseek-ai/cordis'
4
4
  import Schema from '@deepseek-ai/schemastery'
5
5
  import { scanWorkspaceTree } from './files.js'
@@ -79,6 +79,30 @@ function writeJson(res: any, status: number, body: any): void {
79
79
  res.end(data)
80
80
  }
81
81
 
82
+ /**
83
+ * 拒绝工作区之外的目标:files.open 的 path 来自请求体,必须是工作区内的相对/绝对路径,
84
+ * 否则模型或页面脚本可以借宿主进程去打开任意本地路径。
85
+ */
86
+ function assertInsideWorkspace(cwd: string, fullPath: string): void {
87
+ const root = resolve(cwd)
88
+ const target = resolve(fullPath)
89
+ const rel = relative(root, target)
90
+ const escaped = rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)
91
+ if (escaped) throw new Error('Path must stay inside the workspace.')
92
+ }
93
+
94
+ /**
95
+ * 启动系统文件管理器/默认应用。spawn 在命令不存在时会 emit 'error',
96
+ * 没有监听器就会变成未捕获异常拖垮宿主进程,因此这里必须兜住。
97
+ */
98
+ function launch(command: string, args: string[]): void {
99
+ const child = spawn(command, args, { detached: true, stdio: 'ignore' })
100
+ child.on('error', (err: any) => {
101
+ console.warn(`[dsh-workspace-files] failed to launch ${command}:`, err?.message || String(err))
102
+ })
103
+ child.unref()
104
+ }
105
+
82
106
  function resolveCwd(ctx: Context, body: Record<string, any>): string {
83
107
  if (body.cwd?.trim()) return body.cwd.trim()
84
108
  if (body.root?.trim()) return body.root.trim()
@@ -107,25 +131,9 @@ export function apply(ctx: Context, config: Config = {}): void {
107
131
  showHidden: Boolean(config?.showHidden),
108
132
  }
109
133
 
110
- // 关键:向 Host 的 settings 服务注册 settings namespace,使设置面板的前端控制器能够枚举到此插件卡片
111
- if ((ctx as any).inject) {
112
- (ctx as any).inject(['settings'], (scopedCtx: any) => {
113
- try {
114
- const scope = scopedCtx.settings?.register(SETTINGS_NS, Config, {
115
- base: liveConfig,
116
- })
117
- const applyChange = () => {
118
- const current = scope?.get?.()
119
- if (typeof current?.maxDepth === 'number') liveConfig.maxDepth = current.maxDepth
120
- if (typeof current?.showHidden === 'boolean') liveConfig.showHidden = current.showHidden
121
- }
122
- applyChange()
123
- scope?.watch?.(applyChange)
124
- } catch (err) {
125
- console.warn('[dsh-workspace-files] failed to register settings scope:', err)
126
- }
127
- })
128
- }
134
+ // 设置表单由 DSH 从本插件导出的 Config schema 自动生成(Host 侧 settings.describe()),
135
+ // 无需也不存在插件侧的 settings.register():DSH 的 settings 服务只提供
136
+ // describe/update/replace/mutate/configure,namespace 就是 profile 里的 entry id。
129
137
 
130
138
  const webServer = (ctx as any).webServer
131
139
  if (!webServer) return
@@ -167,31 +175,26 @@ export function apply(ctx: Context, config: Config = {}): void {
167
175
  }
168
176
 
169
177
  const fullPath = isAbsolute(rawPath) ? rawPath : resolve(cwd, rawPath)
178
+ assertInsideWorkspace(cwd, fullPath)
170
179
  const action = body.action || 'reveal'
171
180
  const isDirectory = Boolean(body.isDirectory)
172
181
 
173
182
  if (process.platform === 'win32') {
174
183
  const winPath = fullPath.replace(/\//g, '\\')
175
- if (action === 'reveal') {
176
- if (isDirectory) {
177
- spawn('explorer.exe', [winPath], { detached: true, stdio: 'ignore' }).unref()
178
- } else {
179
- spawn('explorer.exe', [`/select,${winPath}`], { detached: true, stdio: 'ignore' }).unref()
180
- }
181
- } else {
182
- exec(`start "" "${winPath.replace(/"/g, '\\"')}"`, { windowsHide: true })
183
- }
184
+ // explorer.exe 自己解析路径,不再经过 cmd.exe 的字符串拼接,避免 & | ^ 等注入
185
+ const args = action === 'reveal' && !isDirectory ? [`/select,${winPath}`] : [winPath]
186
+ launch('explorer.exe', args)
184
187
  } else if (process.platform === 'darwin') {
185
188
  if (action === 'reveal') {
186
- spawn('open', [isDirectory ? fullPath : '-R', fullPath], { detached: true, stdio: 'ignore' }).unref()
189
+ launch('open', [isDirectory ? fullPath : '-R', fullPath])
187
190
  } else {
188
- spawn('open', [fullPath], { detached: true, stdio: 'ignore' }).unref()
191
+ launch('open', [fullPath])
189
192
  }
190
193
  } else {
191
194
  if (action === 'reveal') {
192
- spawn('xdg-open', [isDirectory ? fullPath : resolve(fullPath, '..')], { detached: true, stdio: 'ignore' }).unref()
195
+ launch('xdg-open', [isDirectory ? fullPath : resolve(fullPath, '..')])
193
196
  } else {
194
- spawn('xdg-open', [fullPath], { detached: true, stdio: 'ignore' }).unref()
197
+ launch('xdg-open', [fullPath])
195
198
  }
196
199
  }
197
200