dsh-plugin 1.6.1 → 1.6.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["DSH_PLUGIN_CMD_RE","SORT_DEFAULT_DIR","useState","useRef","useMemo","useState","useState","useCallback","useState","useRef","h","modalStyles","headerStyles","h","styles","h","styles","useMemo","h","styles","h","styles","h","styles","h","styles","h","styles","useState","h","Fragment","styles","h","styles","SegBtn","h","styles","Fragment","useState","useRef","h","styles","useRef","h","styles","h","Fragment","h","styles","h","styles","useState","useMemo","useState","h","styles","modal","h","styles","useState","useRef","h","styles","useState","useRef","useCallback","h","styles","h","view","useState","useRef","useCallback","styles","useState","h","styles","view","useState","useRef","useCallback","h","styles","h","styles","useState","useRef","dropdownStyles","modalStyles","useState","useRef","h","styles","modalStyles","h"],"sources":["../src/client/locales.ts","../src/server/services/install/release-target.ts","../src/client/logic/install-command.ts","../src/client/logic/constants.ts","../src/client/logic/ensure-plugin-css.ts","../src/client/data/host.ts","../src/client/logic/normalize.ts","../src/client/data/catalog.ts","../src/client/data/hub.ts","../src/client/logic/installed.ts","../src/client/hooks/useCatalog.ts","../src/client/logic/failures.ts","../src/client/logic/urls.ts","../src/client/hooks/useLanguage.ts","../src/client/hooks/useSettings.ts","../src/client/hooks/useTaskQueue.ts","../src/client/components/ui/icons.tsx","../src/client/components/modals/ProgressView.tsx","../src/client/components/modals/modals.tsx","../src/client/logic/renderMarkdown.ts","../src/client/components/modals/AboutModal.tsx","../src/client/components/modals/HubUpdateModal.tsx","../src/client/logic/format.ts","../src/client/components/modals/InstalledDetailModal.tsx","../src/client/components/modals/ConfirmDialog.tsx","../src/client/components/modals/NotificationsModal.tsx","../src/client/components/layout/CatalogHeader.tsx","../src/client/components/layout/CategoryTabs.tsx","../src/client/components/layout/CatalogControls.tsx","../src/client/hooks/useIncrementalList.ts","../src/client/components/catalog/PluginCard.tsx","../src/client/components/catalog/CatalogList.tsx","../src/client/components/views/MarketView.tsx","../src/client/components/layout/SectionTabs.tsx","../src/client/components/views/InstalledView.tsx","../src/client/components/views/CustomInstallView.tsx","../src/client/components/ui/Toggle.tsx","../src/client/components/ui/Dropdown.tsx","../src/client/components/views/DiagnosticsView.tsx","../src/client/components/modals/LogsModal.tsx","../src/client/components/modals/LogsPathModal.tsx","../src/client/components/views/LogsView.tsx","../src/client/components/views/SettingsView.tsx","../src/client/components/PluginHubSection.tsx","../src/client/index.tsx"],"sourcesContent":["/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * zh/en dictionaries for the DSH Plugin Hub settings section.\n */\nexport const zh = {\n nav: '插件市场',\n title: 'DSH Plugin Hub',\n // 收录/精选数量由组件从官网 /api/stats.json 实时拉取填充({total}/{verified}),不写死\n tagline: 'DSH Plugin 插件市场:面向 DeepSeek Harness 插件收录平台,人工审验、来源可溯,免费安装',\n adBadge: '推荐',\n // 紫色广告横幅:突出数量(显眼)+ 更新节奏,与 tagline 职责分开、不重复\n ad: 'DSH Plugin 插件市场:收录 {total} 款插件,{verified} 款人工精选验证,每日更新',\n search: '搜索插件名称、描述、标签…',\n all: '全部',\n sortStars: 'Star',\n sortForks: 'Fork',\n sortUpdated: '最近更新',\n sortNewest: '最新收录',\n sortAria: '插件排序方式',\n openHint: '打开 dsh-plugin.org',\n toggleLangHint: '切换界面语言',\n fork: 'Fork',\n loading: '正在加载插件数据…',\n failed: '插件数据加载失败',\n // 目录拉不出来时的精准提示:按「是否配置了代理」区分,引导排查网络 / 代理\n failedDescNoProxy: '你的网络似乎不通,无法获取插件目录数据。请检查网络连接后重试;或点击右上角按钮在浏览器中打开插件市场。',\n failedDescProxy: '你的网络似乎不通,或设置里的 HTTP 代理地址不可达,无法获取插件目录数据。请检查代理设置与网络连接后重试;或点击右上角按钮在浏览器中打开插件市场。',\n retry: '重试',\n install: '安装',\n // AI 识别可能需要命令行辅助的插件(webInstallable=false):仍可尝试一键安装,失败时复制命令去 dsh 终端\n cliOnlyHint: '此插件可能需命令行辅助,失败时复制上方命令到 dsh 终端',\n failedCopyHint: '安装失败。请复制上方安装命令到 dsh 终端手动执行(原生依赖构建脚本可能需要人工放行,如 pnpm approve-builds)',\n toastCopied: '安装命令已复制,去 dsh 终端粘贴即可安装',\n installed: '已安装',\n // 一级导航:插件市场 / 已安装 / 自定义安装 / 设置\n viewMarket: '插件市场',\n viewInstalled: '已安装',\n viewCustom: '自定义安装',\n viewSettings: '设置',\n viewMarketHint: '浏览与发现插件',\n viewInstalledHint: '管理已安装插件',\n viewCustomHint: '手动安装 NPM 包或 GitHub 源码',\n viewSettingsHint: '网络通道与偏好设置',\n // 已安装视图\n installedEmpty: '还没有安装插件',\n installedEmptyDesc: '可以去「自定义安装」,手动安装 NPM 包或 GitHub 源码',\n npmInstallLabel: 'NPM 包 / 命令',\n npmInstallPlaceholder: 'npm install <包名> 或直接输包名',\n npmInstallExample: '支持原生命令:npm install lodash、npm i lodash、pnpm add @scope/pkg',\n npmInstallExample2: '全局安装 CLI:npm install -g @scope/cli;或直接输入包名 lodash',\n npmInstallInvalid: '请输入 npm 包名(如 lodash、@scope/pkg),或原生安装命令(如 npm install lodash、npm i lodash、pnpm add @scope/pkg、npm install -g @scope/cli)',\n gitInstallLabel: 'GitHub 源码',\n gitInstallPlaceholder: '输入仓库地址',\n gitInstallExample: '例如:owner/repo 或 https://github.com/owner/repo',\n gitInstallInvalid: '请输入 GitHub 仓库地址,例如:owner/repo 或 https://github.com/owner/repo',\n dshCmdLabel: 'DeepSeek Harness 命令',\n dshCmdPlaceholder: '粘贴官方 dsh plugin 命令',\n dshCmdInsertHubUpdate: '插入更新命令',\n // 示例/校验文案里的 profile 用运行时当前宿主 profile 渲染({profile} 占位符),\n // 不写死 web —— 桌面端当前 profile 是 desktop,照抄写死的 web 会装进宿主永不加载的档\n dshCmdExample: '例如:dsh plugin --profile {profile} add github:owner/repo,或 dsh plugin --profile {profile} update dsh-plugin',\n dshCmdInvalid: '请输入官方 dsh plugin 命令(--profile 必填,支持 add / update)。例如:dsh plugin --profile {profile} update dsh-plugin',\n installHelp: '帮助',\n helpModalTitle: '支持的命令格式',\n npmInstallHelp: 'lodash、@scope/pkg\\t直接输入包名\\nnpm install lodash\\nnpm i lodash\\npnpm add @scope/pkg\\npnpm i @scope/pkg\\nnpm install -g @scope/cli\\t全局安装 CLI 工具,不进「已安装」列表',\n gitInstallHelp: 'owner/repo\\nhttps://github.com/owner/repo\\ngithub:owner/repo\\ngit+https://github.com/owner/repo.git\\ngit@github.com:owner/repo.git',\n dshCmdHelp: 'dsh plugin --profile {profile} add <目标>\\t安装\\ndsh plugin --profile {profile} update <目标>\\t更新已安装目标到最新版本\\ndsh plugin --profile={profile} add <目标>\\ndsh plugin --profile={profile} update <目标>\\n\\t--profile 必填(此处已填当前 profile),官方 CLI 无 -p 简写;<目标> 可为 npm 包名或 github:owner/repo;卸载请用「已安装」列表',\n globalNpmHint: '将全局安装 CLI 工具(npm install -g),不会出现在「已安装」列表,无需重启宿主',\n installCliBtn: '安装',\n // 安装通道关闭(安全信任开关关掉后,对应卡片禁用并引导去设置打开)\n channelDisabledHint: '该安装通道已关闭,请在「设置 → 安全信任」中打开开关',\n goToSettings: '前往设置',\n // 自定义安装视图:独立一级导航,说明文字\n customViewDesc: '手动安装目录外的 NPM 包、GitHub 源码,或粘贴官方 dsh plugin 命令。装完的条目会出现在「已安装」列表,并标记为自定义安装。',\n customLabel: '自定义安装',\n installedSearch: '搜索已安装的插件…',\n installedFilterCatalog: '目录插件',\n hubInstall: '插件市场',\n hubInstallHint: '来自插件市场收录的目录插件',\n manualInstall: '手动安装',\n manualInstallHint: '非目录收录,通过命令行手动安装',\n filterByLabel: '来源',\n sortByLabel: '排序',\n sortName: '名称',\n sortInstalledAt: '最近',\n detailTitle: '插件详情',\n detailCategory: '分类',\n detailStats: '仓库统计',\n statusLabel: '安装状态',\n statusRunning: '运行中',\n statusPending: '待重启',\n exampleLabel: 'DeepSeek Harness 内置示例项目',\n exampleHint: 'DeepSeek Harness 内置示例项目:不是插件市场的 dsh 插件,宿主不会加载它,无需重启',\n restart: '重启',\n installedVersionLabel: '已安装版本',\n catalogLatest: '目录最新',\n installPath: '安装路径',\n copyPath: '复制路径',\n openFolder: '在文件夹中显示',\n openFolderFail: '无法打开文件夹,请复制路径手动打开',\n revealFolder: '在 Finder 中显示',\n installedAtLabel: '安装时间',\n lastUpdatedLabel: '最后更新',\n detailCatalog: '查看详情',\n packageName: '包名',\n versionUpHint: '发现新版本 v{from} → v{to},点击「更新」原位覆盖重装',\n // 设置视图:更新与通道 / 安全与信任 / 诊断 / 系统日志\n settingsUpdate: '更新设置',\n settingsUpdateDesc: '更新检查方式与安装走到的网络通道',\n settingsCheckOnStart: '启动时检查更新',\n settingsCheckOnStartDesc: '打开插件市场时检查已安装插件是否有新版,发现更新会提示',\n settingsProxy: 'HTTP 代理',\n settingsProxyDesc: 'npm / git / 目录数据请求统一走该代理;留空直连',\n // 代理连通性实时探测:输入停笔后提示检测结果(不通仍可保存,先填地址后开代理也合法)\n proxyCheckChecking: '正在测试该代理地址…',\n proxyCheckOk: '测试可达,安装与目录请求将统一走该代理',\n proxyCheckFail: '此地址测试不通,仍可保存;请确认代理已开启、地址与端口无误',\n // 失败细分原因:Windows Schannel 必须取到证书吊销信息,取不到即中断握手 —— 不是代理地址不通\n proxyCheckRevocation: '证书吊销检查受阻(Windows Schannel 取不到 CRL/OCSP),握手被中断;属本机 TLS 环境问题,非代理地址不通',\n settingsMirror: 'npm 镜像源',\n settingsMirrorDesc: '默认跟随本机 npm 配置;官方源慢可换国内镜像',\n mirrorNone: '未配置(跟随本机 npm 配置)',\n mirrorOfficial: '官方源 registry.npmjs.org',\n mirrorNpmmirror: '阿里云 npmmirror',\n mirrorTencent: '腾讯云镜像',\n mirrorTsinghua: '清华大学 TUNA 镜像',\n settingsSecurity: '安全信任',\n settingsSecurityDesc: '命令行安装的三个通道开关:NPM 包、GitHub 源码与 DSH 命令',\n settingsEnableNpm: '启用 NPM 安装',\n settingsEnableNpmDesc: '允许通过命令行安装 npm 包;关闭后输入包名安装会被拦截',\n settingsEnableGit: '启用 GitHub 源码安装',\n settingsEnableGitDesc: '允许通过命令行安装 GitHub 源码;关闭后输入仓库地址安装会被拦截',\n settingsEnableDsh: '启用 DSH 命令安装',\n settingsEnableDshDesc: '允许通过命令行粘贴 dsh plugin 命令安装;关闭后命令输入会被禁用',\n settingsDiagnostics: '系统诊断',\n settingsDiagnosticsDesc: '检测 npm 源 / GitHub / 目录站点等安装通道的连通状态',\n settingsLogs: '系统日志',\n settingsLogsDesc: '本地记录的安装 / 卸载 / 设置变更与诊断结果,可导出全文排查问题',\n logsHeadHint: '记录安装、卸载、设置变更与诊断结果,保留最近 2000 条',\n logsRefresh: '刷新日志',\n logsExport: '导出日志',\n logsLoading: '正在读取日志…',\n logsEmpty: '暂无日志记录',\n logsLoadFail: '读取日志失败,请稍后重试',\n // 系统日志查看器弹窗:内置窗口分页加载,按类别 × 级别筛选\n logModalTitle: '日志查看器',\n logViewerOpen: '打开日志查看器',\n logViewerDesc: '内置窗口直接查看本地日志,按类型与级别筛选,可定位安装 / 卸载 / 更新时的不兼容点',\n logPathLabel: '日志文件',\n logOpenFile: '打开文件',\n logOpenFileTip: '在系统文件管理器中定位日志文件',\n logOpenFileFail: '打开失败,请在文件管理器中手动定位',\n logClearAll: '清空所有日志',\n logClearConfirmTitle: '清空所有日志?',\n logClearConfirmDesc: '将删除全部日志记录,且不可恢复。',\n logClearing: '正在清空…',\n logClearAllTip: '清空全部日志记录',\n logClearFailed: '清空失败,请重试',\n logPathSettingTitle: '日志存放位置',\n logPathSettingDesc: '默认存于宿主配置目录,可填目录或 .log 文件路径改存别处',\n logPathPlaceholder: '留空恢复默认',\n logPathReset: '恢复默认',\n logPathResetHint: '文本框显示当前生效位置',\n logPathSave: '保存',\n logPathSaving: '保存中…',\n logPathSaved: '已保存,新日志将写入该位置',\n logPathSaveFail: '保存失败:该位置不可写或不可用',\n logPathChange: '修改',\n logPathBrowse: '选择目录…',\n logPathBrowseFail: '选择目录不可用,请手动输入路径',\n logCatAll: '全部类型',\n logCatInstall: '安装',\n logCatUninstall: '卸载',\n logCatUpdate: '更新',\n logCatDiagnostics: '诊断',\n logCatSettings: '设置',\n logCatSystem: '系统',\n logLvAll: '全部级别',\n logLvError: '错误',\n logLvWarn: '警告',\n logLvSuccess: '成功',\n logLvInfo: '信息',\n logLvDebug: '调试',\n logSearchPlaceholder: '搜索事件或描述…',\n logLoadMore: '加载更多',\n logNoMore: '已加载全部,共 {n} 条',\n logCount: '共 {n} 条',\n logEmptyFilter: '没有符合条件的日志',\n settingsDiagFail: '不可达',\n // 系统诊断通道列表:一键全量诊断 + 一行一个,可点重测\n diagNpm: 'npm 源',\n // 诊断页 npm 行:未配置镜像时的展示(探测目标仍为官方源,代表本机无配置时的回退)\n diagNpmUnset: '未配置(跟随本机 npm 配置)',\n diagGithub: 'GitHub',\n diagCatalog: '目录站点',\n diagCatalogTarget: '插件市场',\n diagProxy: 'HTTP 代理',\n diagOk: 'OK',\n diagChecking: '检测中…',\n diagIdle: '未检测',\n diagRecheck: '点击重测该通道',\n diagRunAll: '立即诊断',\n diagHeadHint: '共 {n} 个通道,点击任意一行可单独重测',\n diagSummaryRunning: '正在检测通道…',\n diagSummaryOk: '全部通道正常',\n diagSummaryFail: '存在不可达通道,点击对应行可重测',\n // 失败细分原因:Windows Schannel 必须取到证书吊销信息才能握手,取不到即中断(易被误当成网络不通)\n diagFailRevocation: '证书校验受阻',\n diagFailRevocationHint: '系统 curl 取不到证书吊销信息(Windows Schannel 必需 CRL/OCSP),TLS 握手被中断 —— 这不是网络不通,npm/git 可能照常可用。升级 curl 到 7.70+ 可自动按「尽力而为」处理,或换一个能访问吊销服务的网络。',\n settingsEnvSnapshot: '系统版本',\n settingsEnvSnapshotDesc: '复制宿主版本与系统信息,提交 Issue 时粘贴到正文便于复现',\n settingsEnvCopy: '复制',\n // 恢复默认:一级菜单 + 独立设置卡片\n settingsReset: '恢复默认',\n settingsResetDesc: '更新策略、镜像源、代理与安全限制一次性恢复为出厂默认值',\n settingsResetDetail: '恢复更新策略、镜像源、代理与安全限制为出厂默认值',\n settingsResetRun: '恢复默认',\n settingsResetConfirm: '确认恢复',\n settingsResetConfirmDetail: '确定要恢复默认设置吗?更新策略、镜像源、代理与安全限制将全部回到出厂默认值。',\n // 更新通知(通知中心条目标题)\n updateNoticeTitle: '发现新版本',\n updateNoticeGo: '去更新',\n ignoreUpdateRun: '忽略本次更新',\n ignoreUpdateConfirmTitle: '忽略本次更新?',\n ignoreUpdateConfirmDetail: '忽略后本次版本不再提醒;待插件发布下一个新版本时,会再次通知你。',\n ignoreUpdateConfirm: '确认忽略',\n uninstall: '卸载',\n uninstalling: '卸载中…',\n uninstallTitle: '确认卸载?',\n uninstallDesc: '将从当前环境卸载该插件。',\n uninstallDone: '卸载成功',\n uninstallFail: '卸载失败,请稍后重试',\n uninstallResultTitle: '卸载完成',\n uninstallResultDesc: '插件已从当前环境移除。',\n confirmTitle: '确认安装',\n confirmDesc: '安装前请前往插件仓库仔细阅读源码,确认可信后再安装',\n confirmPlugin: '插件',\n confirmSource: '来源',\n confirmCommand: '安装命令',\n copyInstallCommand: '复制安装命令',\n copyCmdLabel: '复制',\n copyUninstallCommand: '复制卸载命令',\n cancelUninstall: '取消卸载',\n uninstallConfirm: '确认卸载',\n installNow: '直接安装',\n installing: '安装中…',\n installDone: '安装成功',\n // 更新成功(通知中心区分安装/更新):更新 = 已安装目标覆盖重装到最新,与首次安装不同语义\n updateDone: '更新成功',\n installResultTitle: '插件安装成功',\n installResultDesc: '',\n // 更新语义:已安装插件点「更新」走同一条 add 命令原位覆盖重装,弹窗文案区分安装/更新\n confirmUpdateTitle: '确认更新',\n updateNow: '直接更新',\n updating: '更新中…',\n queuedUpdateTitle: '已加入更新排队',\n updateResultTitle: '更新完成',\n updateResultDesc: '插件已更新到最新版本。',\n installFail: '安装失败',\n requestTimeout: '请求超时:无法访问 GitHub 或网络不稳定,请稍后重试',\n confirmCancel: '取消',\n doneBtn: '完成',\n // 结果视图:部分插件需重启后才挂载,提供「立即重启 / 稍后重启」选择\n restartNow: '立即重启',\n restartLater: '稍后重启',\n restarting: '正在重启…',\n restartHint: '重启会中断正在进行的安装/卸载任务,其进度将丢失。部分插件(如插件市场、顶层 bundle)需重启后才会生效。',\n done: '完成',\n // 待重启:装完没重启的插件常驻提醒,直到宿主真正重启\n restartPendingHint: '安装成功,重启后生效',\n restartPendingHintUninstall: '卸载成功,重启后移除',\n sectionPendingRestart: '待重启',\n sectionInProgress: '进行中',\n // 通知中心:安装/卸载任务成败的持久记录(工具栏铃铛入口按钮打开)\n notifications: '通知',\n notificationsHint: '查看安装/卸载/更新通知',\n notificationsDesc: '安装、卸载任务与更新提醒都会记录在这里,即使错过提示也能随时回来查看。',\n notificationsEmpty: '暂无通知记录',\n notificationsClear: '清空通知',\n notificationsClearConfirmTitle: '清空所有通知?',\n notificationsClearConfirmDesc: '将删除全部通知记录,且不可恢复。',\n removeNotification: '删除这条通知',\n removeNotificationConfirmTitle: '删除这条通知?',\n removeNotificationConfirmDesc: '该通知将被移除,且不可恢复。',\n // 串行队列:安装/卸载弹窗内可后台关闭,排队任务自动串行执行\n queuedTitle: '已加入安装排队',\n queuedUninstallTitle: '已加入卸载排队',\n queuedHint: '已加入排队,前序任务完成后将自动开始,可关闭本窗口继续浏览。',\n cancelTask: '取消任务',\n cancelling: '正在取消…',\n errorTitle: '操作失败',\n errorTitleInstall: '安装失败',\n errorTitleUninstall: '卸载失败',\n // 更新失败(通知中心区分安装/更新):更新目标覆盖重装失败,与首次安装失败不同语义\n errorTitleUpdate: '更新失败',\n errorPlugin: '插件',\n errorClose: '知道了',\n errorCopy: '复制错误信息',\n errCopied: '错误信息已复制',\n failCopy: '复制完整错误信息',\n failIssueHint: '带着错误日志去作者仓库一键提交 Issue(正文含官网收录链接)',\n failIssueBig: '一键提交 BUG 到 GitHub Issue 为开源作贡献',\n // prepare 构建脚本实际执行失败(git 分发缺子模块/构建产物):插件打包分发问题,应提 Issue\n failPrepareHint: '该插件安装时的构建脚本执行失败(git 分发常缺失子模块或构建产物),属插件打包分发问题。请向作者仓库提交 Issue 反馈。',\n // 安装前预检 / 装后校验拦截([packaging]):git 分发缺构建产物、入口文件不存在 = 插件未适配官方默认安装方式\n failPackagingHint: '该插件不支持官方默认安装方式:其 git 分发缺少构建产物(package.json 声明的入口文件在仓库中不存在),说明作者未适配官方安装流程。请到作者仓库提交 Issue 反馈,请其提交构建产物或发布 npm 版。',\n // 原生依赖构建脚本被 pnpm 默认拦截(如 node-pty 的 ERR_PNPM_IGNORED_BUILDS):只影响带原生模块的插件,属插件依赖打包问题,应提 Issue\n failIgnoredBuild: '该插件或其依赖需要执行构建脚本,被 pnpm 的安全白名单(allowBuilds)默认拦截导致安装失败(如原生模块 node-pty、或 git 安装时插件的 prepare 脚本)—— 其他插件不受影响,属该插件的依赖/打包问题。建议向作者仓库一键反馈,请作者改用预编译版本(如 node-pty-prebuilt-multiarch)或移除安装期构建。',\n // npm arborist 内部崩溃(edgesOut)+ 本机 npm 版本过低:npm 自身已知缺陷,不是插件问题,升级 npm 即可\n failNpmTooLow: '怀疑本机 npm 版本过低:npm 解析插件依赖时内部崩溃(这是 npm 自身的已知缺陷,不是插件问题)。请升级 npm 后重试:npm install -g npm@latest',\n failNpmTooLowV: '本机 npm 版本过低(当前 v{v}):npm 解析插件依赖时内部崩溃(这是 npm 自身的已知缺陷,不是插件问题)。请升级 npm 后重试:npm install -g npm@latest',\n // 安装前连通性预检 / 安装日志里的连接失败([network] / git fetch 超时 / DNS / TLS):本机网络或代理问题,不是插件问题,不引导提 Issue\n failNetworkHint: '安装前检测到网络不通:无法连接到安装源(可能是断网、DNS 解析失败、被防火墙拦截,或代理配置有问题)。这不是插件本身的问题 —— 请检查网络连接,或到「设置」里确认 HTTP 代理配置,再到「系统诊断」运行一次连通性检测,然后重试。',\n // 网络失败弹窗里的「无法访问 …」醒目行:直接告诉用户具体哪个地址连不上({url} 为提取的不可达地址)\n failNetworkRegistryHint: '你的 npm/pnpm 源(registry)被配置为 {host},插件包需从该源下载但失败了。这通常是内网/自定义源没有同步该包(或需要内网认证)—— 请把 npm/pnpm 的 registry 指回官方源 https://registry.npmjs.org(或确认此源可访问该包)后重试。',\n failNetworkTarget: '无法访问 {url} —— 你的网络连接不通',\n // 「去系统诊断」直达按钮:网络不通提示下方的品牌实底按钮,跳到设置 → 系统诊断跑连通性检测\n failNetworkRunDiag: '去系统诊断检测网络',\n // 请求来源没通过本地 hub 服务校验(服务端 403 untrusted origin):请求根本没进安装流程,\n // 与插件无关 —— 引导从本机地址重新打开市场,不引导提 Issue\n failOriginRejectedHint: '这次安装请求没有通过插件市场的来源校验,被本地服务直接拒绝,所以安装根本没有开始 —— 与插件本身无关。通常是因为市场页面不是从本机地址打开的(比如用了局域网 IP),或宿主页面的来源未被识别。请从本机的插件市场地址(localhost)重新打开页面后重试;桌面端用户重启一次宿主即可。若重启宿主后仍然失败,说明当前 dsh-plugin 版本与宿主不兼容,请用以下命令把市场升级到最新版,再重启一次宿主:dsh plugin --profile {profile} add dsh-plugin@latest。',\n failDshMissingHint: '系统找不到 dsh 命令(dsh 未加入系统 PATH),无法调用安装器执行安装。请确认 DeepSeek Harness 已正确安装、dsh 已加入 PATH(或重新安装),然后重试。这不是插件本身的问题。',\n failGitMissingHint: '系统找不到 git 命令(Git 未安装或未加入系统 PATH),无法从 GitHub 源安装插件。请先安装 Git(如 git-scm.com/downloads)或把 git 加入 PATH,重启 DSH 后重试。这不是插件本身的问题。',\n failPnpmMissingHint: '安装器找到了 dsh,但系统里没有 pnpm 命令(dsh 用它来管理 profile 插件)。请先安装 pnpm(如 npm install -g pnpm),确认 pnpm 已加入 PATH 后重试。这不是插件本身的问题。',\n failNpmMissingHint: '系统找不到 npm 命令(npm 未安装或未加入系统 PATH),无法执行全局安装。请先安装 Node.js(自带 npm),确认 npm 已加入 PATH 后重试。这不是插件本身的问题。',\n failPnpmStoreHint: '安装器调用 pnpm 时报「store 位置不匹配」(ERR_PNPM_UNEXPECTED_STORE):你的 profile 目录里旧插件依赖是用另一个大版本的 pnpm 生成的,当前 pnpm 出于安全不认旧目录,导致任何插件装进该 profile 都会失败。请删除该 profile 目录下的 node_modules 与 pnpm-lock.yaml(可先到「系统日志」或 ~/.dsh/profiles/<profile>/hub.log 查看完整报错),再重新安装。这不是插件本身的问题。',\n failPnpmUnusedPatchHint: '安装器调用 pnpm 时报「有些补丁没有被使用」(ERR_PNPM_UNUSED_PATCH):你的 profile 里留着一条指向旧版本 dsh-plugin 的补丁声明(例如 dsh-plugin@1.4.2),而本次安装解析到的版本已经不是它,pnpm 出于安全直接中止整次安装,因此任何插件都装不进来。这不是插件本身的问题——请在 profile 目录(~/.dsh/profiles/<profile>)的 pnpm-workspace.yaml(pnpm 11 及以上)或 package.json 的 pnpm.patchedDependencies(pnpm 10)里删除该 dsh-plugin 补丁条目后重试。',\n // 404 依赖:点名 registry 上不存在的那个包(取不到包名时跳过这行),再给删除条目的指引\n failPnpmMissingDepTarget: '{pkg} 在 npm registry 上不存在(404)',\n failPnpmMissingDepHint: '安装器调用 pnpm 时报「包不存在」(ERR_PNPM_FETCH_404):你的 profile 里留着一条指向 registry 上未发布包的依赖,pnpm 每次解析依赖都会先卡在它上面,因此任何插件都装不进来。这不是插件本身的问题——请在 profile 目录(~/.dsh/profiles/<profile>)的 package.json 里删除该依赖条目(同时删掉对应的 pnpm-lock.yaml 条目或整个锁文件)后重试。',\n failFileLockedHint: '安装过程中 pnpm 无法替换 profile 里的文件:有程序正占用着它(Windows 常见报错 os error 32「另一个程序正在使用此文件」)。通常是 DeepSeek Harness 自身或杀毒软件的实时扫描持有文件句柄。这不是插件本身的问题——请完全退出 DeepSeek Harness(Windows 可在任务管理器确认进程已结束,必要时临时关闭杀毒软件实时防护)后重试。',\n failAccessDeniedHint: '安装过程中 pnpm 写入 profile 里的文件被系统拒绝访问(Windows 常见报错 os error 5「拒绝访问」,英文为 Access is denied;Node 下的 EPERM / EACCES 同理)。常见原因是该文件或目录正被其他进程占用、文件带只读属性、目录权限受限,或杀毒软件实时防护拦截了写入——这与「文件正被占用」(os error 32)同属本机文件系统问题,任何插件装进该目录都会一样失败,不是插件本身的问题。请完全退出 DeepSeek Harness(Windows 可在任务管理器确认进程已结束,必要时临时关闭杀毒软件实时防护)后重试;若仍然失败,请检查 profile 目录及其文件是否被设为只读,并以管理员身份重新运行。',\n failFsUnavailableHint: '安装过程中 pnpm 无法把文件写进本机磁盘(这类报错与装哪个插件无关,任何插件装在同一目录都会失败,不是插件本身的问题)。请按报错对号入座:① 磁盘空间不足(ENOSPC / no space left on device,Windows 为 os error 112)——请清理 profile 所在磁盘的剩余空间后重试;② 磁盘或挂载点只读、带写保护(EROFS / read-only file system,Windows 为 os error 19)——请确认 profile 目录所在磁盘可写(外接盘/U 盘、带写保护的移动盘或只读挂载的分区都会触发),必要时把插件目录换到系统盘的可写位置;③ 进程可用的文件句柄被耗尽(EMFILE / ENFILE / too many open files)——请关闭占用大量文件的程序并重启 DeepSeek Harness 后重试。',\n failPnpmWorkspaceHint: '安装器调用 pnpm 时报「不能把依赖装到 workspace 根目录」(ERR_PNPM_ADDING_TO_ROOT):你的 profile 目录被 pnpm 视为 workspace 根目录,而本次安装命令没有声明在根目录操作,pnpm 直接拒绝执行,因此任何插件装进来都会失败。这不是插件本身的问题——可在 profile 目录(~/.dsh/profiles/<profile>)的 .npmrc 里加一行 ignore-workspace-root-check=true 后重试,或把 DeepSeek Harness 升级到最新版再试。',\n failPnpmTarballIntegrityHint: 'pnpm 报 ERR_PNPM_MISSING_TARBALL_INTEGRITY:锁文件中的 tarball 条目没有校验值,无法验证下载的包。先查看完整日志,完全退出 DeepSeek Harness,并检查、备份当前 profile 的 package.json、pnpm-lock.yaml 和 pnpm-workspace.yaml。确认依赖来源后,将 pnpm-lock.yaml 改名保留,再通过同一 DSH 安装器安装适配当前宿主版本的插件,重新生成锁文件。重建会重新解析 profile 依赖,请核对新旧版本;保持完整性校验开启。',\n failPnpmPolicyHint: '安装器调用 pnpm 时被其供应链安全策略拦截——装任何插件都会撞墙,不是插件本身的问题。分两种情况处理:① 提示「Minimum release age」(ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION):包发布还不满 24 小时,pnpm 11 出于安全会拒收这种刚发布的新包。可在 pnpm 配置(pnpm-workspace.yaml)里加 minimumReleaseAge: 0 豁免,或等满 24 小时后重试。② 提示「untrusted origin」(ERR_PNPM_UNTRUSTED_ORIGIN):依赖来源不被本机 pnpm 信任,通常是该 profile 里之前用 github: 或非官方 npm 源装过插件,锁文件记录了不受信任的来源。请删除该 profile 目录下的 node_modules 与 pnpm-lock.yaml 后重新安装(可先到「系统日志」或 ~/.dsh/profiles/<profile>/hub.log 查看完整报错)。',\n // minimumReleaseAge 专属:从报错里算出确切的可重试时刻({time}),让用户知道「何时能再装」,\n // 而不是笼统地让等 24 小时(见 issue #121)\n failPnpmReleaseAgeHint: '安装器调用 pnpm 时被其供应链安全策略拦住了,任何插件装进这个 profile 都会先撞上它——与插件本身无关。原因是这个包发布还不满 24 小时,pnpm 11 出于安全会拒收刚发布的新包,这段时间内该 profile 的安装与卸载都会被拦下。可重试时间:{time}(即该包发布满 24 小时后)。如确需立刻安装,可在 profile 目录(~/.dsh/profiles/<profile>)的 pnpm-workspace.yaml 里加 minimumReleaseAge: 0 豁免,但这会放宽整个 profile 的供应链保护。',\n // 自定义安装三卡片入口的渠道名(报错/日志溯源:本次安装从哪个入口发起)\n installChannelNpm: 'NPM 包',\n installChannelGit: 'GitHub 源码',\n installChannelDsh: 'DSH 命令',\n // 报错/通知中心的入口溯源行:前缀在错误正文顶部,精准指出自定义安装是从哪张卡片发起的\n installEntryLine: '安装入口:{c}。',\n reportIssue: '去插件仓库提交 Issue',\n detail: '打开详情',\n noResult: '没有找到匹配的插件',\n noResultDesc: '换个关键词试试,或前往网站浏览全部插件。',\n today: '今天更新',\n daysAgo: '更新于 {days} 天前',\n monthsAgo: '更新于 {months} 个月前',\n yearsAgo: '更新于 {years} 年前',\n pluginsTotal: '结果 {n} 条插件',\n // 分类按钮不带数量,选中分类后在列表头部显示筛选结果数\n filterResults: '结果 {n} 条插件',\n more: '还有 {n} 个插件,去网站查看全部',\n browseAll: '浏览全部 {n} 个插件',\n verified: '已验证',\n // 版本与更新:有 release 比版本号;无 release 的仓库比仓库最近更新时间(有新提交即提示更新)\n version: '版本',\n update: '可更新',\n updateAvailable: '有更新',\n updateAvailableHint: '检测到更新:有版本号的仓库比对版本号,无版本号的仓库比对仓库最近更新时间',\n hubUpdateHint: '检测到 DSH Plugin Hub 新版本,点击查看更新内容并更新',\n hubUpdateTitle: 'DSH Plugin Hub 有新版本',\n hubUpdateDesc: 'v{version} 已发布,点击下方按钮即可更新,完成后需重启宿主生效。',\n hubUpdatePublished: '发布于',\n hubUpdateNotes: '更新记录',\n hubUpdateLater: '稍后再说',\n versionHint: '查看版本信息与更新记录',\n hubCurrentTitle: '当前版本',\n hubCurrentDesc: '你正在使用 v{version},已是最新版本。',\n hubUpToDate: '已是最新版本',\n // 头部「关注我们」弹窗:平台介绍 + 用户反馈群二维码(内容由 Worker /about Markdown 推送,非写死)\n followUs: '关注我们',\n aboutTitle: '关注我们',\n aboutDesc: '了解 DSH Plugin Hub 是做什么的,加入用户反馈群随时交流。',\n aboutEmpty: '内容暂未发布,敬请期待。',\n aboutUpdated: '更新于',\n empty: '该分类暂无插件',\n dataFrom: '数据源 api.dsh-plugin.org · 每日人工更新',\n}\n\nexport const en = {\n nav: 'Plugin Hub',\n title: 'DSH Plugin Hub',\n // Plugin counts are filled from the live /api/stats.json ({total}/{verified}), never hardcoded\n tagline: 'DSH Plugin Hub: a human-verified, free marketplace for DeepSeek Harness plugins',\n adBadge: 'Featured',\n ad: 'DSH Plugin Hub: {total} plugins indexed, {verified} human-verified, updated daily',\n search: 'Search plugins by name, description, tags…',\n all: 'All',\n sortStars: 'Stars',\n sortForks: 'Forks',\n sortUpdated: 'Recently updated',\n sortNewest: 'Newest added',\n sortAria: 'Plugin sort order',\n openHint: 'Open dsh-plugin.org',\n toggleLangHint: 'Switch language',\n githubHint: 'View source on GitHub',\n fork: 'Fork',\n loading: 'Loading plugin data…',\n failed: 'Failed to load plugin data',\n // Precise hints when the catalog cannot load: distinguished by whether a proxy is configured\n failedDescNoProxy: 'Your network seems unreachable, so the plugin catalog could not be loaded. Please check your connection and retry; or open the hub in your browser with the button above.',\n failedDescProxy: 'Your network seems unreachable, or the HTTP proxy in Settings is unreachable, so the plugin catalog could not be loaded. Please check the proxy address and your connection, then retry; or open the hub in your browser with the button above.',\n retry: 'Retry',\n install: 'Install',\n // AI-flagged plugins that may need command-line help (webInstallable=false): one-click install still allowed,\n // on failure the user is guided to copy the command into the dsh terminal\n cliOnlyHint: 'This plugin may need command-line help; if it fails, copy the command above and run it in your dsh terminal',\n failedCopyHint: 'Install failed. Copy the command above and run it manually in your dsh terminal (native build scripts may need manual approval, e.g. pnpm approve-builds)',\n toastCopied: 'Install command copied — paste it in your dsh terminal',\n installed: 'Installed',\n // Primary navigation: Market / Installed / Custom / Settings\n viewMarket: 'Market',\n viewInstalled: 'Installed',\n viewCustom: 'Custom',\n viewSettings: 'Settings',\n viewMarketHint: 'Browse and discover plugins',\n viewInstalledHint: 'Manage installed plugins',\n viewCustomHint: 'Install npm packages or GitHub sources manually',\n viewSettingsHint: 'Network sources and preferences',\n // Installed view\n installedEmpty: 'No plugins installed yet',\n installedEmptyDesc: 'Go to Custom to add an npm package or GitHub source manually',\n npmInstallLabel: 'npm package / command',\n npmInstallPlaceholder: 'npm install <pkg> or a bare package name',\n npmInstallExample: 'Native commands: npm install lodash, npm i lodash, pnpm add @scope/pkg',\n npmInstallExample2: 'Global CLI: npm install -g @scope/cli; or just type a package name like lodash',\n npmInstallInvalid: 'Enter an npm package name (e.g. lodash, @scope/pkg), or a native install command (e.g. npm install lodash, npm i lodash, pnpm add @scope/pkg, npm install -g @scope/cli)',\n gitInstallLabel: 'GitHub source',\n gitInstallPlaceholder: 'Repository address',\n gitInstallExample: 'e.g. owner/repo or https://github.com/owner/repo',\n gitInstallInvalid: 'Enter a GitHub repository address, e.g. owner/repo or https://github.com/owner/repo',\n dshCmdLabel: 'DeepSeek Harness command',\n dshCmdPlaceholder: 'Paste an official dsh plugin command',\n dshCmdInsertHubUpdate: 'Insert update command',\n dshCmdExample: 'e.g. dsh plugin --profile {profile} add github:owner/repo, or dsh plugin --profile {profile} update dsh-plugin',\n dshCmdInvalid: 'Paste an official dsh plugin command (--profile required, add / update), e.g. dsh plugin --profile {profile} update dsh-plugin',\n installHelp: 'Help',\n helpModalTitle: 'Supported command formats',\n npmInstallHelp: 'lodash or @scope/pkg\\tjust type the package name\\nnpm install lodash\\nnpm i lodash\\npnpm add @scope/pkg\\npnpm i @scope/pkg\\nnpm install -g @scope/cli\\tinstalls the CLI globally, not shown in Installed',\n gitInstallHelp: 'owner/repo\\nhttps://github.com/owner/repo\\ngithub:owner/repo\\ngit+https://github.com/owner/repo.git\\ngit@github.com:owner/repo.git',\n dshCmdHelp: 'dsh plugin --profile {profile} add <target>\\tinstall\\ndsh plugin --profile {profile} update <target>\\tupdate an installed target to the latest version\\ndsh plugin --profile={profile} add <target>\\ndsh plugin --profile={profile} update <target>\\n\\t--profile is required (prefilled with the current profile here) and there is no -p shorthand; <target> can be an npm package or github:owner/repo; uninstall from the Installed list',\n globalNpmHint: 'This installs CLI tools globally (npm install -g). They won\\'t appear in Installed and no host restart is needed.',\n installCliBtn: 'Install',\n // Install channel disabled (security-trust toggle off → card disabled, guides to settings)\n channelDisabledHint: 'This install channel is disabled — enable it in Settings → Security & Trust',\n goToSettings: 'Go to Settings',\n // Custom install view: standalone top-level section, description text\n customViewDesc: 'Manually install an npm package, a GitHub source, or paste an official dsh plugin command. Finished installs appear in Installed, marked as custom.',\n customLabel: 'Custom install',\n installedSearch: 'Search installed plugins…',\n installedFilterCatalog: 'Catalog',\n hubInstall: 'Hub',\n hubInstallHint: 'From the plugin hub catalog',\n manualInstall: 'Manual',\n manualInstallHint: 'Not from the catalog — installed via the command line',\n filterByLabel: 'Source',\n sortByLabel: 'Sort',\n sortName: 'Name',\n sortInstalledAt: 'Recent',\n detailTitle: 'Plugin details',\n detailCategory: 'Category',\n detailStats: 'Repo stats',\n statusLabel: 'Status',\n statusRunning: 'Running',\n statusPending: 'Restart pending',\n exampleLabel: 'DeepSeek Harness built-in example',\n exampleHint: 'DeepSeek Harness built-in example — not a marketplace dsh plugin, the host does not load it, no restart needed',\n restart: 'Restart',\n installedVersionLabel: 'Installed version',\n catalogLatest: 'latest in catalog',\n installPath: 'Install path',\n copyPath: 'Copy path',\n openFolder: 'Show in folder',\n openFolderFail: 'Could not open the folder — copy the path instead',\n revealFolder: 'Show in Finder',\n installedAtLabel: 'Installed at',\n lastUpdatedLabel: 'Last updated',\n detailCatalog: 'View details',\n packageName: 'Package',\n versionUpHint: 'v{from} → v{to} available — Update reinstalls in place',\n // Settings view: Updates & Sources / Security & Trust / Diagnostics / System Logs\n settingsUpdate: 'Update Settings',\n settingsUpdateDesc: 'Update checks and the network channels used for installs',\n settingsCheckOnStart: 'Check for updates on startup',\n settingsCheckOnStartDesc: 'Check installed plugins for new versions when the hub opens; you will be notified when updates are found',\n settingsAutoInstall: 'Auto-install updates',\n settingsAutoInstallDesc: 'Install detected updates in the background without asking (a host restart applies them)',\n settingsProxy: 'HTTP proxy',\n settingsProxyDesc: 'Route npm, git and catalog requests through this proxy; leave empty to connect directly',\n // Live proxy reachability probe: reported after the user stops typing (an unreachable\n // address can still be saved — users may fill it in before actually starting the proxy)\n proxyCheckChecking: 'Testing this proxy address…',\n proxyCheckOk: 'Reachable — installs and catalog requests will route through it',\n proxyCheckFail: 'Unreachable, but you can still save it; make sure the proxy is running and the address and port are correct',\n // Failure reason: Windows Schannel aborts the handshake when revocation info (CRL/OCSP) is unreachable — not a bad proxy address\n proxyCheckRevocation: 'Certificate revocation check blocked (Windows Schannel could not fetch CRL/OCSP), so the handshake was aborted — a local TLS issue, not a bad proxy address',\n settingsMirror: 'npm mirror',\n settingsMirrorDesc: 'Unset by default — follows local npm config; pick a domestic mirror if slow',\n mirrorNone: 'Unset (follow local npm config)',\n mirrorOfficial: 'Official registry.npmjs.org',\n mirrorNpmmirror: 'Alibaba npmmirror',\n mirrorTencent: 'Tencent Cloud mirror',\n mirrorTsinghua: 'Tsinghua TUNA mirror',\n settingsSecurity: 'Security & Trust',\n settingsSecurityDesc: 'Toggles for the three command-line install channels: npm packages, GitHub sources and DSH commands',\n settingsEnableNpm: 'Enable npm installs',\n settingsEnableNpmDesc: 'Allow installing npm packages from the command line; turning this off rejects package-name installs',\n settingsEnableGit: 'Enable GitHub source installs',\n settingsEnableGitDesc: 'Allow installing from GitHub sources on the command line; turning this off rejects repository-address installs',\n settingsEnableDsh: 'Enable DSH command installs',\n settingsEnableDshDesc: 'Allow pasting a dsh plugin command to install; turning this off disables the command input',\n settingsDiagnostics: 'System Diagnostics',\n settingsDiagnosticsDesc: 'Check the connectivity of install channels: npm registry, GitHub and the catalog site',\n settingsLogs: 'System Logs',\n settingsLogsDesc: 'Local record of installs / uninstalls, settings changes and diagnostics — export the full log to troubleshoot',\n logsHeadHint: 'Records installs, uninstalls, settings changes and diagnostics; keeps the latest 2,000 entries',\n logsRefresh: 'Refresh log',\n logsExport: 'Export log',\n logsLoading: 'Reading log…',\n logsEmpty: 'No log entries yet',\n logsLoadFail: 'Failed to read the log; try again later',\n // Log-viewer dialog: a built-in window that loads the log in pages, filterable by type × level\n logModalTitle: 'Log viewer',\n logViewerOpen: 'Open log viewer',\n logViewerDesc: 'View the local log in a built-in window; filter by type and level to pinpoint install / uninstall / update incompatibilities',\n logPathLabel: 'Log file',\n logOpenFile: 'Reveal',\n logOpenFileTip: 'Reveal the log file in your system file manager',\n logOpenFileFail: 'Could not open; locate the file manually',\n logClearAll: 'Clear all logs',\n logClearConfirmTitle: 'Clear all logs?',\n logClearConfirmDesc: 'All log entries will be deleted. This cannot be undone.',\n logClearing: 'Clearing…',\n logClearAllTip: 'Delete all log entries',\n logClearFailed: 'Failed to clear; try again',\n logPathSettingTitle: 'Log Location',\n logPathSettingDesc: 'Stored in the host config directory by default — set a directory or a .log file path to store elsewhere',\n logPathPlaceholder: 'Leave empty for default',\n logPathReset: 'Reset to default',\n logPathResetHint: 'The field shows the location currently in use',\n logPathSave: 'Save',\n logPathSaving: 'Saving…',\n logPathSaved: 'Saved — new logs will be written there',\n logPathSaveFail: 'Could not save: the location is not writable',\n logPathChange: 'Change',\n logPathBrowse: 'Browse…',\n logPathBrowseFail: 'Folder picker unavailable — type the path manually',\n logCatAll: 'All types',\n logCatInstall: 'Install',\n logCatUninstall: 'Uninstall',\n logCatUpdate: 'Update',\n logCatDiagnostics: 'Diagnostics',\n logCatSettings: 'Settings',\n logCatSystem: 'System',\n logLvAll: 'All levels',\n logLvError: 'Error',\n logLvWarn: 'Warn',\n logLvSuccess: 'Success',\n logLvInfo: 'Info',\n logLvDebug: 'Debug',\n logSearchPlaceholder: 'Search event or message…',\n logLoadMore: 'Load more',\n logNoMore: 'All loaded · {n} total',\n logCount: '{n} entries',\n logEmptyFilter: 'No matching log entries',\n settingsDiagFail: 'Unreachable',\n // System diagnostics channel list: one-click full check + one row per channel, click to re-probe\n diagNpm: 'npm registry',\n // Diagnostics npm row: shown when no mirror is configured (probe still targets the official registry, the fallback)\n diagNpmUnset: 'Unset (follow local npm config)',\n diagGithub: 'GitHub',\n diagCatalog: 'Catalog site',\n diagCatalogTarget: 'Plugin marketplace',\n diagProxy: 'HTTP proxy',\n diagOk: 'OK',\n diagChecking: 'Checking…',\n diagIdle: 'Not checked',\n diagRecheck: 'Click to re-check this channel',\n diagRunAll: 'Run diagnostics',\n diagHeadHint: '{n} channels — click any row to re-check it alone',\n diagSummaryRunning: 'Checking channels…',\n diagSummaryOk: 'All channels reachable',\n diagSummaryFail: 'Unreachable channel(s) — click a row to re-check',\n // Failure reason: Windows Schannel aborts the handshake when revocation info (CRL/OCSP) is unreachable (easily mistaken for a network outage)\n diagFailRevocation: 'Cert check blocked',\n diagFailRevocationHint: 'The system curl cannot fetch certificate revocation info (CRL/OCSP, required by Windows Schannel), so the TLS handshake is aborted — this is not a network outage, and npm/git may still work. curl 7.70+ downgrades the check to best-effort, or switch to a network that can reach the revocation service.',\n settingsEnvSnapshot: 'System version',\n settingsEnvSnapshotDesc: 'Copy host version and system info for pasting into issue reports',\n settingsEnvCopy: 'Copy',\n // Restore defaults: first-level menu + its own settings card\n settingsReset: 'Restore Defaults',\n settingsResetDesc: 'Restore update policy, npm mirror, proxy and security restrictions to factory defaults in one go',\n settingsResetDetail: 'Reset update policy, npm mirror, proxy and security restrictions to factory defaults',\n settingsResetRun: 'Restore Defaults',\n settingsResetConfirm: 'Restore Defaults',\n settingsResetConfirmDetail: 'Reset all settings to factory defaults? Update policy, npm mirror, proxy and security restrictions will be cleared.',\n // Update notice (notification center item title)\n updateNoticeTitle: 'Update available',\n updateNoticeGo: 'Update',\n ignoreUpdateRun: 'Ignore this update',\n ignoreUpdateConfirmTitle: 'Ignore this update?',\n ignoreUpdateConfirmDetail: 'This version will no longer notify you. You will be alerted again when the next version is released.',\n ignoreUpdateConfirm: 'Ignore',\n uninstall: 'Uninstall',\n uninstalling: 'Removing…',\n uninstallTitle: 'Confirm uninstall?',\n uninstallDesc: 'The plugin will be removed from this environment.',\n uninstallDone: 'Uninstalled',\n uninstallFail: 'Removal failed — try again',\n uninstallResultTitle: 'Removed',\n uninstallResultDesc: 'The plugin has been removed from this environment.',\n confirmTitle: 'Confirm install',\n confirmDesc: 'Review the plugin repository source code carefully before installing.',\n confirmPlugin: 'Plugin',\n confirmSource: 'Source',\n confirmCommand: 'Command',\n copyInstallCommand: 'Copy install command',\n copyCmdLabel: 'Copy',\n copyUninstallCommand: 'Copy uninstall command',\n cancelUninstall: 'Cancel uninstall',\n uninstallConfirm: 'Confirm uninstall',\n installNow: 'Install',\n installing: 'Installing…',\n installDone: 'Installed',\n // Updated (notification center distinguishes install/update): update = in-place reinstall to latest\n updateDone: 'Updated',\n installResultTitle: 'Plugin installed successfully',\n installResultDesc: '',\n // Update semantics: the \"update\" action re-runs add in place — copy differentiates install vs update\n confirmUpdateTitle: 'Confirm update',\n updateNow: 'Update',\n updating: 'Updating…',\n queuedUpdateTitle: 'Queued for update…',\n updateResultTitle: 'Updated',\n updateResultDesc: 'The plugin has been updated to the latest version.',\n installFail: 'Install failed — copy the command instead',\n requestTimeout: 'Request timed out: GitHub may be unreachable or the network is unstable — try again later',\n confirmCancel: 'Cancel',\n doneBtn: 'Done',\n // Result view: some plugins need a restart to mount — offer restart now / later\n restartNow: 'Restart now',\n restartLater: 'Later',\n restarting: 'Restarting…',\n restartHint: 'Restarting interrupts any in-progress install / uninstall task — its progress will be lost. Some plugins (such as plugin markets / top-level bundles) only take effect after a restart.',\n done: 'Done',\n restartPendingHint: 'Installed — takes effect after restart',\n restartPendingHintUninstall: 'Removed — cleaned up after restart',\n sectionPendingRestart: 'Pending restart',\n sectionInProgress: 'In progress',\n // 通知中心:安装/卸载任务成败的持久记录(工具栏铃铛入口按钮打开)\n notifications: 'Notifications',\n notificationsHint: 'View install/remove/update notifications',\n notificationsDesc: 'Every install, remove and update notice is logged here — even if you missed the prompt, you can always check back.',\n notificationsEmpty: 'No notifications yet',\n notificationsClear: 'Clear notifications',\n notificationsClearConfirmTitle: 'Clear all notifications?',\n notificationsClearConfirmDesc: 'All notification records will be deleted. This cannot be undone.',\n removeNotification: 'Remove this notification',\n removeNotificationConfirmTitle: 'Remove this notification?',\n removeNotificationConfirmDesc: 'This notification will be removed. This cannot be undone.',\n queuedTitle: 'Queued…',\n queuedUninstallTitle: 'Queued for removal…',\n queuedHint: 'Queued — starts automatically after earlier tasks finish. You may close this window.',\n cancelTask: 'Cancel task',\n cancel: 'Cancel',\n cancelling: 'Cancelling…',\n errorTitle: 'Operation failed',\n errorTitleInstall: 'Install failed',\n errorTitleUninstall: 'Removal failed',\n // Update failed (notification center distinguishes install/update): update target reinstall failed\n errorTitleUpdate: 'Update failed',\n errorPlugin: 'Plugin',\n errorClose: 'Got it',\n errorCopy: 'Copy error',\n errCopied: 'Error copied',\n failCopy: 'Copy full log',\n failIssueHint: 'Open a pre-filled issue on the author repo with this error log (includes catalog links)',\n failIssueBig: 'Report this bug to GitHub — contribute to open source',\n // prepare script actually failed (git tarball misses submodules/build output): a packaging issue of the plugin itself — file an issue\n failPrepareHint: 'This plugin failed while running its build scripts during install (git tarballs often miss submodules or build output). This is a packaging issue of the plugin itself — please report it to the author repository.',\n // Pre-install / post-install guard hit ([packaging]): git distribution lacks build output, entry file missing = not adapted to the official default install method\n failPackagingHint: 'This plugin does not support the official default install method: its git distribution lacks the build output (the entry file declared in package.json is not in the repository), so it has not been adapted to the official install flow. Please file an Issue on the author\\'s repo asking for committed build output or an npm release.',\n // native-module build scripts ignored by pnpm by default (e.g. node-pty, ERR_PNPM_IGNORED_BUILDS): only affects plugins with native deps — a dependency/packaging issue of the plugin itself, file an issue\n failIgnoredBuild: 'This plugin (or its dependencies) needs to run build scripts, which pnpm blocks by default via its allowBuilds allowlist, so the install fails (e.g. native modules like node-pty, or the plugin\\'s own prepare script on git installs) — other plugins are unaffected. This is a dependency/packaging issue of the plugin itself. Please report it to the author repository and ask the author to ship a prebuilt variant (e.g. node-pty-prebuilt-multiarch) or drop install-time builds.',\n failNpmTooLow: 'Your local npm may be too old: npm crashed internally while resolving the plugin\\'s dependencies (a known npm bug — not a plugin issue). Please upgrade npm and retry: npm install -g npm@latest',\n failNpmTooLowV: 'Your local npm is too old (v{v}): npm crashed internally while resolving the plugin\\'s dependencies (a known npm bug — not a plugin issue). Please upgrade npm and retry: npm install -g npm@latest',\n // Pre-install connectivity probe / connection failure in the install log ([network] / git fetch timeout / DNS / TLS): a local network or proxy issue, not a plugin issue — no issue link\n failNetworkHint: 'The network could not be reached before install: the install source is unreachable (offline, DNS failure, firewall block, or a misconfigured proxy). This is not a problem with the plugin itself — please check your connection, confirm the HTTP proxy in Settings, run a connectivity check under System Diagnostics, then retry.',\n // Prominent \"cannot reach …\" line in the network-failure dialog: shows the exact unreachable address ({url})\n failNetworkRegistryHint: 'Your npm/pnpm registry is set to {host}, and the package tarball could not be downloaded from it. This usually means a private/internal mirror that has not synced the package (or requires intranet auth) — point the registry back to https://registry.npmjs.org (or make sure this source can serve the package), then retry.',\n failNetworkTarget: 'Cannot reach {url} — your network connection is down',\n // Diagnostics shortcut button under the network-down hint: jumps to Settings → System Diagnostics\n failNetworkRunDiag: 'Run a network diagnostic',\n // The request origin did not pass the local hub service check (403 untrusted origin): the request\n // never reached the install flow — nothing to do with the plugin, so point at the local address\n // and do not offer an issue link\n failOriginRejectedHint: 'This install request did not pass the marketplace origin check and was rejected by the local service, so the install never started — this is not about the plugin itself. It usually means the marketplace page was not opened from a local address (for example a LAN IP), or the host page origin was not recognized. Reopen the marketplace from localhost and retry; on the desktop app, restart the host once. If it still fails after restarting the host, your dsh-plugin version is incompatible with the host — upgrade the marketplace with dsh plugin --profile {profile} add dsh-plugin@latest, then restart the host again.',\n failDshMissingHint: 'The dsh command could not be found (it is not on the system PATH), so the installer could not run. Please make sure DeepSeek Harness is installed correctly and dsh is on your PATH (or reinstall it), then retry. This is not a problem with the plugin itself.',\n failGitMissingHint: 'The git command could not be found (Git is not installed or not on the system PATH), so GitHub-source plugins cannot be installed. Please install Git (e.g. from git-scm.com/downloads) or add git to your PATH, restart DSH, then retry. This is not a problem with the plugin itself.',\n failPnpmMissingHint: 'The installer found dsh, but pnpm is missing on this machine (dsh uses it to manage profile plugins). Please install pnpm first (e.g. npm install -g pnpm), make sure it is on your PATH, then retry. This is not a problem with the plugin itself.',\n failNpmMissingHint: 'The npm command could not be found (npm is not installed or not on the system PATH), so a global install cannot run. Please install Node.js (which bundles npm), make sure npm is on your PATH, then retry. This is not a problem with the plugin itself.',\n failPnpmStoreHint: 'pnpm reported an unexpected store location (ERR_PNPM_UNEXPECTED_STORE): the profile directory was previously set up with a different major version of pnpm, and the current pnpm refuses to reuse it — no plugin can be installed into that profile. Delete node_modules and pnpm-lock.yaml under the profile directory (see System Logs or ~/.dsh/profiles/<profile>/hub.log for the full output), then reinstall. This is not a problem with the plugin itself.',\n failPnpmUnusedPatchHint: 'pnpm reported that some patches were not used (ERR_PNPM_UNUSED_PATCH): your profile still holds a patch entry for an older dsh-plugin version (for example dsh-plugin@1.4.2), while this install resolved a different version, so pnpm aborts the whole install for safety — no plugin can be installed into that profile. This is not a problem with the plugin itself. Remove that dsh-plugin patch entry from pnpm-workspace.yaml (pnpm 11+) or from pnpm.patchedDependencies in package.json (pnpm 10) inside the profile directory (~/.dsh/profiles/<profile>), then retry.',\n // Missing dependency: name the package that 404'd (the line is skipped when it cannot be parsed),\n // then give the removal instructions\n failPnpmMissingDepTarget: '{pkg} was not found on the npm registry (404)',\n failPnpmMissingDepHint: 'pnpm reported that a package does not exist on the npm registry (ERR_PNPM_FETCH_404): your profile keeps a dependency on a package that was never published, and pnpm hits it every time it resolves dependencies — no plugin can be installed into that profile. This is not a problem with the plugin itself. Remove that dependency from package.json inside the profile directory (~/.dsh/profiles/<profile>) — along with its entry in pnpm-lock.yaml, or the lockfile itself — then retry.',\n failFileLockedHint: 'During install, pnpm could not replace a file inside the profile because another program is holding it (on Windows this shows as os error 32, \"the process cannot access the file because it is being used by another process\"). Usually DeepSeek Harness itself or a real-time antivirus scan holds the handle. This is not a problem with the plugin itself — fully quit DeepSeek Harness (on Windows, confirm in Task Manager that the process has ended, and temporarily disable real-time antivirus protection if needed), then retry.',\n failAccessDeniedHint: 'During install, Windows denied pnpm access to a file inside the profile (this shows as os error 5, \"Access is denied\"; on Node the equivalent codes are EPERM / EACCES). Typical causes: the file or directory is held by another process, the file is marked read-only, the directory permissions are restricted, or a real-time antivirus scan blocked the write. This is the same class of local file-system problem as a locked file (os error 32) — no plugin can be installed into that directory, so it is not a problem with the plugin itself. Fully quit DeepSeek Harness (on Windows, confirm in Task Manager that the process has ended, and temporarily disable real-time antivirus protection if needed), then retry. If it still fails, check whether the profile directory or its files are read-only and run as administrator.',\n failFsUnavailableHint: 'During install, pnpm could not write files to the local disk — this has nothing to do with which plugin you are installing: any plugin installed into the same directory would fail the same way, so it is not a problem with the plugin itself. Match the error you see: ① Out of space (ENOSPC / no space left on device, os error 112 on Windows) — free up space on the drive that holds the profile and retry. ② Read-only or write-protected volume (EROFS / read-only file system, os error 19 on Windows) — make sure the drive holding the profile directory is writable (external or USB drives, write-protected media, and read-only mounts all trigger this); move the plugin directory to a writable location on the system drive if needed. ③ File handles exhausted (EMFILE / ENFILE / too many open files) — close programs that hold many files open, restart DeepSeek Harness, then retry.',\n failPnpmWorkspaceHint: 'pnpm refused to add the dependency to the workspace root (ERR_PNPM_ADDING_TO_ROOT): the profile directory is treated as a pnpm workspace root, and this install command did not declare that it operates at the root, so pnpm rejected it outright — no plugin can be installed into that profile. This is not a problem with the plugin itself. Add `ignore-workspace-root-check=true` to the `.npmrc` inside the profile directory (~/.dsh/profiles/<profile>) and retry, or upgrade DeepSeek Harness and try again.',\n failPnpmTarballIntegrityHint: 'pnpm reported ERR_PNPM_MISSING_TARBALL_INTEGRITY: a tarball entry in the lockfile has no checksum to verify the downloaded package. Read the full log, fully quit DeepSeek Harness, and inspect and back up package.json, pnpm-lock.yaml and pnpm-workspace.yaml in the affected profile. Once the dependency sources are verified, rename pnpm-lock.yaml to preserve it, then use the same DSH installer to install a plugin version compatible with the host and regenerate the lockfile. This resolves profile dependencies again: compare the old and new versions, and keep integrity checks enabled.',\n failPnpmPolicyHint: 'The installer was blocked by pnpm supply-chain security policy — every plugin install would hit the same wall, so this is not a problem with the plugin itself. Two cases: ① \"Minimum release age\" (ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION): the package was published less than 24 hours ago, and pnpm 11 refuses freshly-published packages for safety. Add minimumReleaseAge: 0 to your pnpm config (pnpm-workspace.yaml) to opt out, or wait until the 24 hours have passed and retry. ② \"untrusted origin\" (ERR_PNPM_UNTRUSTED_ORIGIN): a dependency source is not trusted by this machine, usually because plugins were previously installed via github: or a non-official npm registry, so the lockfile records an untrusted source. Delete node_modules and pnpm-lock.yaml under the profile directory (see System Logs or ~/.dsh/profiles/<profile>/hub.log for the full output), then reinstall.',\n // minimumReleaseAge only: compute the exact retry time ({time}) from the error so the user knows\n // when installs will work again, instead of the vague \"wait 24 hours\" (see issue #121)\n failPnpmReleaseAgeHint: 'The installer was blocked by pnpm supply-chain security policy, and every plugin installed into this profile would hit the same wall — this is not a problem with the plugin itself. The package was published less than 24 hours ago, and pnpm 11 refuses freshly-published packages for safety, so both installs and removals are blocked for this profile in the meantime. Retry after: {time} (i.e. 24 hours after the package was published). If you must install right now, add minimumReleaseAge: 0 to pnpm-workspace.yaml inside the profile directory (~/.dsh/profiles/<profile>) to opt out, but that loosens supply-chain protection for the whole profile.',\n // Custom install entry channel names (the three cards) — used in error/log traceability\n installChannelNpm: 'NPM package',\n installChannelGit: 'GitHub source',\n installChannelDsh: 'DSH command',\n // Entry traceability line prefixed at the top of the error text: which card initiated this install\n installEntryLine: 'Install entry: {c}.',\n reportIssue: 'Report an Issue to the plugin repo',\n detail: 'Open details',\n noResult: 'No plugins match your search',\n noResultDesc: 'Try another keyword, or browse all plugins on the website.',\n today: 'updated today',\n daysAgo: 'updated {days}d ago',\n monthsAgo: 'updated {months}mo ago',\n yearsAgo: 'updated {years}y ago',\n pluginsTotal: 'Results: {n} plugins',\n // Category chips carry no counts; the filtered result count shows in the list header\n filterResults: 'Results: {n} plugins',\n more: '{n} more on the website',\n browseAll: 'Browse all {n} plugins',\n verified: 'Verified',\n // Version & updates: repos with a release are compared by tag; repos without one by last push time (new commits → update)\n version: 'Version',\n update: 'Update',\n updateAvailable: 'Update available',\n updateAvailableHint: 'An update was detected: repos with a release are compared by tag, repos without one by last push time',\n hubUpdateHint: 'A new DSH Plugin Hub version is available — click to view the changelog and update',\n hubUpdateTitle: 'A new DSH Plugin Hub version is available',\n hubUpdateDesc: 'v{version} has been released — click below to update, then restart the host to apply it.',\n hubUpdatePublished: 'Published',\n hubUpdateNotes: \"What's new\",\n hubUpdateLater: 'Later',\n versionHint: 'View version info and changelog',\n hubCurrentTitle: 'Current version',\n hubCurrentDesc: 'You are on v{version} — this is the latest version.',\n hubUpToDate: 'Up to date',\n // Header \"Follow us\" modal: platform intro + user feedback group QR (content pushed via Worker /about Markdown)\n followUs: 'Follow us',\n aboutTitle: 'Follow us',\n aboutDesc: 'Learn what DSH Plugin Hub does and join our user feedback group.',\n aboutEmpty: 'Content not published yet — stay tuned.',\n aboutUpdated: 'Updated',\n empty: 'No plugins in this category yet',\n dataFrom: 'Data from api.dsh-plugin.org · curated daily',\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 预构建 GitHub release 安装目标(目录权威命令 → 可安装直链)。\n * 部分插件(如 loopx)把构建产物发布成 GitHub release 的 .tgz,仓库 HEAD 反而是\n * monorepo 根、走 git 直装会因缺入口文件失败;目录下发的权威安装命令直接指向该\n * release 包。这里把「目录命令」解析成安全的 release 目标,供客户端选路与服务端\n * 校验共用(单一事实来源,避免两端口径漂移)。\n *\n * 只接受固定形态的 HTTPS `github.com/<owner>/<repo>/releases/download/<tag>/<asset>.tgz`:\n * 目录命令是展示数据、绝非 shell 代码,绝不执行命令文本;跨仓跳转、外部主机、凭据、\n * 移动的 latest 链接、query/fragment、多余 CLI 参数与 shell 片段一律拒绝。\n */\n\n/** release 包目标及其所属仓库身份(owner/repo);非法返回 null。 */\nexport interface GithubReleaseTarget {\n /** 规范化后的安装目标(HTTPS 直链) */\n target: string\n /** 该直链所属仓库(owner/repo):供已装态读回、队列去重与展示身份复用 */\n repo: string\n}\n\n/** 目录权威命令:`dsh plugin --profile <p> add|update <target>`(与 profile.ts installTargetOf 同口径)。 */\nconst DSH_PLUGIN_CMD_RE = /^dsh[ \\t]+plugin[ \\t]+--profile(?:[ \\t]+|=)[A-Za-z0-9_-]+[ \\t]+(?:add|update)[ \\t]+(.+)$/i\n\n/** 固定形态的 release .tgz 直链:主机、路径段与扩展名全部锁死。 */\nconst RELEASE_URL_RE = /^https:\\/\\/github\\.com\\/([A-Za-z0-9._-]+)\\/([A-Za-z0-9._-]+)\\/releases\\/download\\/([A-Za-z0-9._+-]+)\\/([A-Za-z0-9._+-]+\\.tgz)$/\n\n/**\n * 解析一个 release 安装目标。\n * @param value - 目录命令(`dsh plugin --profile web add <url>`)或裸直链。\n * @returns 命中返回 `{ target, repo }`,否则 null。\n */\nexport function githubReleaseTarget(value: string): GithubReleaseTarget | null {\n const input = typeof value === 'string' ? value.trim() : ''\n if (input === '') return null\n const command = DSH_PLUGIN_CMD_RE.exec(input)\n const raw = command !== null ? command[1].trim() : input\n const match = RELEASE_URL_RE.exec(raw)\n if (match === null) return null\n // 拒绝 `.` / `..` 路径段,杜绝借路径穿越跳出 release 目录\n if (match.slice(1).some((part) => part === '.' || part === '..')) return null\n return { target: raw, repo: `${match[1]}/${match[2]}` }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Install target/command helpers: decide the install channel (npm package\n * vs prebuilt GitHub release vs explicit-HTTPS GitHub), build the display\n * command and normalize a raw install spec back to its owner/repo identity.\n */\nimport type { HubPlugin } from '../types.ts'\nimport { githubReleaseTarget } from '../../server/services/install/release-target.ts'\n\n/** Backend attempts are chronological; report the last executed command before a display fallback.\n * These prefixes are the task queue's recorded command shapes, never commands to execute here.\n */\nexport function executedCommandOf(command?: string, attempts?: string[]): string | undefined {\n if (attempts === undefined) return command\n return attempts.slice().reverse().find((attempt) =>\n /^dsh plugin --profile(?:=| )\\S+ (?:add|remove|update) \\S/.test(attempt)\n || /^npm install -g \\S/.test(attempt))\n}\n\n/**\n * 安装通道决策(用户无感知):目录探测到 npm 包名 → 用 npm 包名安装\n * (走 npm registry tarball,更快、与 GitHub 网络无关);其次用「同仓库」的权威\n * release 包直链(仓库 HEAD 往往是 monorepo 根、装不上,release .tgz 才是完整产物);\n * 都没有 → git 直装。\n * 返回值 target 即传给后端 /install 的安装目标(npm 包名 / release URL / owner/repo)。\n */\nexport function installTargetOf(p: HubPlugin): { target: string; via: 'npm' | 'release' | 'github' } {\n const pkg = (p.source?.npmPackage ?? '').trim()\n const repo = (p.source?.repo ?? '').trim()\n if (pkg && repo) return { target: pkg, via: 'npm' }\n // 目录下发的权威命令若是「同仓库」的固定 release 直链,改走该预构建包;\n // 跨仓 / 非法 release 目标不采信,退回 git 直装。\n const release = githubReleaseTarget(p.install?.githubCommand ?? '')\n if (release !== null && repo !== '' && release.repo.toLowerCase() === repo.toLowerCase()) {\n return { target: release.target, via: 'release' }\n }\n return { target: repo, via: 'github' }\n}\n\n/** 展示用安装命令(复制/弹窗):目录下发的权威命令优先(CLI-only 插件如 dsh-tui\n * 需专属 profile(--profile dsh-tui),无法从 repo/npm 包名推断,必须用官方命令);\n * 常规插件无目录命令时按通道回退生成:npm 显示包名,git 显示显式 HTTPS URL。 */\nexport function installCommandOf(p: HubPlugin, withProfile = false): string {\n const { target, via } = installTargetOf(p)\n if (via === 'npm') {\n const cmd = p.install?.command\n if (cmd) return cmd\n } else {\n // release 与 git 通道共用目录下发的 githubCommand(git+ 显式 HTTPS 或 release 直链)\n const cmd = p.install?.githubCommand\n if (cmd) return cmd\n }\n const prefix = `dsh plugin${withProfile ? ' --profile web' : ''} add `\n if (via === 'npm' || via === 'release') return `${prefix}${target}`\n return `${prefix}git+https://github.com/${target}.git`\n}\n\n/** Normalize a task/install target to its owner/repo display identity. */\nexport function repoFromInstallTarget(value: string): string {\n const input = value.trim()\n // release 直链(预构建 .tgz)走同一条身份归一化:解析出所属仓库,已装态/更新信号才能\n // 认回目录条目;仅接受固定形态直链,跨仓/非法目标不接受,继续走下面的常规解析。\n const release = githubReleaseTarget(input)\n if (release !== null) return release.repo\n if (/^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$/.test(input)) return input\n const patterns = [\n /^github:([^/]+)\\/([^/]+)$/i,\n /^(?:git\\+)?https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?(?:[?#].*)?$/i,\n /^(?:git\\+)?ssh:\\/\\/(?:git@)?github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?(?:[?#].*)?$/i,\n /^git@github\\.com:([^/]+)\\/([^/]+?)(?:\\.git)?(?:[?#].*)?$/i,\n ]\n for (const pattern of patterns) {\n const match = pattern.exec(input)\n if (match !== null) return `${match[1]}/${match[2]}`\n }\n return value\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Constants: site URLs, category metadata and sort keys. Pure data — no\n * side effects, no network — so every consumer shares one definition.\n */\nimport type { LocaleId } from '../types.ts'\n\n/** 插件市场官网地址。 */\nexport const SITE_URL = 'https://dsh-plugin.org/'\n\n/** 插件市场源码仓库:头部右上角 GitHub 图标的跳转地址 */\nexport const GITHUB_URL = 'https://github.com/dshplugin/dsh-plugin-hub'\n\n/** Hub 自身在目录数据里的仓库标识:头部版本号旁的「可更新」徽标按它定位自己。 */\nexport const HUB_REPO = 'dshplugin/dsh-plugin-hub'\n\n/**\n * Hub 自我更新版本控制(接口中心 Pages:api.dsh-plugin.org,静态 JSON 发布)。\n * 发新版 = 在 api-center 的 releases/ 写发版记录 + 重新部署,hub.json 随之更新,\n * 所有已装用户的「可更新」徽标即可见,不经过主站目录数据管道。\n * 响应:{ version: string | null, publishedAt: string | null, notes: string | {zh,en} | null }\n */\nexport const HUB_UPDATE_URL = 'https://api.dsh-plugin.org/hub.json'\n\n/** 接口中心「关注我们」内容(静态 JSON,由 api-center 的 about.md 构建生成,Markdown)。 */\nexport const HUB_ABOUT_URL = 'https://api.dsh-plugin.org/about.json'\n\n/** 构建时由 tsdown 从 package.json 注入的插件版本号(见 tsdown.config.ts define)。 */\ndeclare const __PLUGIN_VERSION__: string\n\n/**\n * 插件当前版本号,供头部标题展示「DSH Plugin Hub v0.1.1」。\n * tsdown 构建时用 define 把 __PLUGIN_VERSION__ 替换成 package.json 的版本号;\n * node --test 直接 import 本模块时该标识符不存在,typeof 守卫兜底为空串。\n */\nexport const PLUGIN_VERSION: string =\n typeof __PLUGIN_VERSION__ === 'string' ? __PLUGIN_VERSION__ : ''\n\nexport const CATEGORY_ORDER = [\n 'interface', 'session', 'memory', 'tools', 'agent', 'workflow',\n 'integration', 'model', 'dev', 'knowledge', 'fun',\n]\n\n/** 分类标签按界面语言取词;未知 key 原样返回。 */\nexport function categoryLabel(\n map: Record<string, { zh: string; en: string }>,\n key: string,\n lang: LocaleId,\n): string {\n return map[key]?.[lang] ?? key\n}\n\nexport const CATEGORY_LABELS: Record<string, { zh: string; en: string }> = {\n interface: { zh: '界面与体验', en: 'UI & Experience' },\n session: { zh: '会话与消息', en: 'Sessions & Messages' },\n memory: { zh: '记忆与上下文', en: 'Memory & Context' },\n tools: { zh: '工具与能力', en: 'Tools & Capabilities' },\n agent: { zh: '技能与智能体', en: 'Skills & Agents' },\n workflow: { zh: '工作流与自动化', en: 'Workflow & Automation' },\n integration: { zh: '集成与连接', en: 'Integrations & Connections' },\n model: { zh: '模型与推理', en: 'Models & Reasoning' },\n dev: { zh: '开发与运维', en: 'Development & Operations' },\n knowledge: { zh: '数据与知识', en: 'Data & Knowledge' },\n fun: { zh: '娱乐', en: 'Entertainment' },\n}\n\n/** 分类 Tab 的紧凑标签(英文模式空间受限时使用)。 */\nexport const CATEGORY_SHORT_LABELS: Record<string, { zh: string; en: string }> = {\n interface: { zh: '界面体验', en: 'UI Exp' },\n session: { zh: '会话消息', en: 'Sessions' },\n memory: { zh: '记忆上下文', en: 'Memory' },\n tools: { zh: '工具能力', en: 'Tools' },\n agent: { zh: '技能智能体', en: 'Agents' },\n workflow: { zh: '工作流', en: 'Workflow' },\n integration: { zh: '集成连接', en: 'Integrations' },\n model: { zh: '模型推理', en: 'Models' },\n dev: { zh: '开发运维', en: 'Dev' },\n knowledge: { zh: '数据知识', en: 'Knowledge' },\n fun: { zh: '娱乐', en: 'Fun' },\n}\n\nexport const SORTS = ['sortStars', 'sortForks', 'sortUpdated', 'sortNewest'] as const\nexport type SortKey = (typeof SORTS)[number]\n","/**\n * Self-heal missing plugin CSS tags.\n *\n * CSS injection is a one-shot side effect of the bundle factory (guarded by\n * \"tag already present\"). When the host restarts the page survives, but the\n * host HMR chain may remove the <style data-plugin> tags while the in-memory\n * module cache still holds the old factory — so the factory never re-runs and\n * the styles never come back until some interaction triggers a reload.\n *\n * The tsdown `dsh-css-modules-inline` build plugin registers every module's\n * { tagId, css } into the global list `__DSH_PLUGIN_CSS__` at factory time.\n * This helper compares that list against the live DOM and re-injects any\n * missing tags, turning the \"click around to fix it\" self-heal into an\n * automatic one on mount / view switch.\n */\n\ninterface PluginCssEntry {\n tagId: string\n css: string\n}\n\ndeclare global {\n interface Window {\n __DSH_PLUGIN_CSS__?: PluginCssEntry[]\n }\n}\n\n/** Re-inject any registered stylesheet that is missing from the DOM. Idempotent. */\nexport function ensurePluginCss(): void {\n if (typeof document === 'undefined') return\n const registry = window.__DSH_PLUGIN_CSS__\n if (!registry || registry.length === 0) return\n for (const { tagId, css } of registry) {\n const selector = 'style[data-plugin-css=' + JSON.stringify(tagId) + ']'\n if (document.querySelector(selector) !== null) continue\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-plugin'\n tag.dataset.pluginCss = tagId\n tag.textContent = css\n document.head.appendChild(tag)\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Host repository: the local routes served by the DSH harness (installed\n * plugin table + environment snapshot). A host without the plugin's server\n * routes degrades to null / empty tables instead of throwing.\n */\nimport type { EnvInfo } from '../types.ts'\nimport type { InstalledVersionSignal } from '../logic/installed.ts'\n\nexport interface HostInstalled {\n installed: Record<string, string>\n versions: Record<string, InstalledVersionSignal>\n /** 每个依赖在系统上的安装目录(profile/node_modules/<包名>),宿主未提供为 null */\n paths: Record<string, string> | null\n /** 已加载进运行中 loader 的包名(官方 ctx.loader.entries() 对账):装完未重启的新插件不在其中 */\n loaded: string[] | null\n /** 真正的 dsh 插件包名(包内声明 dsh 配置 / 在 profile bundles 清单):非 dsh 插件(如官方示例仓库)装上也不会被宿主加载,不提示待重启 */\n dshCapable: string[] | null\n}\n\n/** 当前 profile 已安装插件表(npm 包名 -> manifest spec)+ 安装时记录的目录信号 + 安装路径 + 运行状态。 */\nexport async function fetchInstalled(): Promise<HostInstalled | null> {\n try {\n const res = await fetch('/dsh-plugin-hub/installed', { cache: 'no-store' })\n if (!res.ok) return null\n const data = await res.json() as {\n installed?: Record<string, string>\n versions?: Record<string, InstalledVersionSignal>\n paths?: Record<string, string>\n loaded?: string[]\n dshCapable?: string[]\n }\n return {\n installed: data.installed ?? {},\n versions: data.versions ?? {},\n paths: data.paths ?? null,\n loaded: data.loaded ?? null,\n dshCapable: data.dshCapable ?? null,\n }\n } catch {\n return null\n }\n}\n\nlet envPromise: Promise<EnvInfo | null> | null = null\n\n/** 在系统文件管理器里定位并打开已安装插件的目录(服务端 spawn open,跨平台);失败返回 false。 */\nexport async function revealInstallFolder(name: string): Promise<boolean> {\n try {\n const res = await fetch('/dsh-plugin-hub/open-path', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ name }),\n cache: 'no-store',\n })\n return res.ok\n } catch {\n return false\n }\n}\n\n/** 在系统文件管理器里定位日志文件(服务端 spawn open,跨平台);失败返回 false。 */\nexport async function openLogFile(): Promise<boolean> {\n try {\n const res = await fetch('/dsh-plugin-hub/open-log', {\n method: 'POST',\n cache: 'no-store',\n })\n return res.ok\n } catch {\n return false\n }\n}\n\n/**\n * 系统目录选择器:弹原生文件夹对话框让用户挑日志存放目录(服务端 spawn\n * osascript / FolderBrowserDialog / zenity);选中返回绝对路径,取消或\n * 平台不支持(无 osascript / zenity)时返回 null。\n */\nexport async function chooseLogDir(): Promise<string | null> {\n try {\n const res = await fetch('/dsh-plugin-hub/choose-log-dir', {\n method: 'POST',\n cache: 'no-store',\n })\n if (!res.ok) return null\n const data = await res.json() as { path?: string }\n return typeof data.path === 'string' && data.path !== '' ? data.path : null\n } catch {\n return null\n }\n}\n\n/**\n * 宿主机器环境快照(/dsh-plugin-hub/env):提交 bug 时拼进 issue 正文。\n * 懒加载 + 模块级缓存:环境在会话期间不会变化;拉取失败降级为 null\n * (issue 链接照常生成,只是少环境段)。\n */\nexport function getEnv(): Promise<EnvInfo | null> {\n envPromise ??= fetch('/dsh-plugin-hub/env', { cache: 'no-store' })\n .then((res) => (res.ok ? (res.json() as Promise<EnvInfo>) : null))\n .catch(() => null)\n return envPromise\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Normalizer: maps the online API's short-key payload (s/o/n/vr/c/t/f/d/r/v/u/a/sg/fk)\n * to HubPlugin so rendering only ever sees one shape.\n */\nimport type { HubPlugin } from '../types.ts'\n\nexport function normalize(raw: Record<string, unknown>): HubPlugin {\n if (typeof raw.s === 'string') {\n return {\n slug: raw.s,\n ownerSlug: typeof raw.o === 'string' ? raw.o : undefined,\n displayName: typeof raw.n === 'string' ? raw.n : undefined,\n version: typeof raw.vr === 'string' ? raw.vr : undefined,\n category: typeof raw.c === 'string' ? raw.c : undefined,\n topics: Array.isArray(raw.t) ? (raw.t as string[]) : undefined,\n features: Array.isArray(raw.f) ? (raw.f as string[]) : undefined,\n description: typeof raw.d === 'string' ? raw.d : undefined,\n // source 双形态:字符串 repo,或 { repo, npmPackage } 对象\n source: typeof raw.r === 'string'\n ? { repo: raw.r }\n : raw.r !== null && typeof raw.r === 'object'\n ? {\n repo: typeof (raw.r as { repo?: unknown }).repo === 'string' ? (raw.r as { repo: string }).repo : undefined,\n npmPackage: typeof (raw.r as { npmPackage?: unknown }).npmPackage === 'string' ? (raw.r as { npmPackage: string }).npmPackage : undefined,\n }\n : undefined,\n // 安装信息:wi 仅在 false 时下发(缺省视为 true 可一键安装);\n // ic/igc = 目录下发的权威安装命令(npm/git 通道各一条,CLI-only 插件如 dsh-tui 必须用)\n install: raw.wi === false || typeof raw.ic === 'string' || typeof raw.igc === 'string'\n ? {\n webInstallable: raw.wi === false ? false : undefined,\n command: typeof raw.ic === 'string' ? raw.ic : undefined,\n githubCommand: typeof raw.igc === 'string' ? raw.igc : undefined,\n }\n : undefined,\n compatibility: typeof raw.v === 'string' ? { status: raw.v } : undefined,\n dates: {\n repoUpdatedAt: typeof raw.u === 'string' ? raw.u : undefined,\n addedAt: typeof raw.a === 'string' ? raw.a : undefined,\n },\n stats: {\n stargazers_count: typeof raw.sg === 'number' ? raw.sg : undefined,\n forks_count: typeof raw.fk === 'number' ? raw.fk : undefined,\n },\n }\n }\n return raw as unknown as HubPlugin\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Catalog repository: fetches the plugin directory and the collection stats\n * from the online API and normalizes them. Components never see URLs or\n * fetch — the repository is the only place that knows where data lives.\n */\nimport type { HubPlugin, LocaleId } from '../types.ts'\nimport { normalize } from '../logic/normalize.ts'\n\n// 目录/统计数据经服务端 /catalog 代理路由获取(curl 子进程注入设置里的代理),\n// 与 npm / git 安装通道同一代理口径 —— 浏览器不直连 api.dsh-plugin.org。\nconst PROXY_BASE = '/dsh-plugin-hub/catalog'\nconst PLUGINS_URL = (lang: LocaleId) => `${PROXY_BASE}?lang=${lang}`\nconst STATS_URL = `${PROXY_BASE}?stats=1`\n\nasync function fetchJson(url: string, signal?: AbortSignal): Promise<unknown> {\n const res = await fetch(url, { cache: 'no-store', signal })\n if (!res.ok) throw new Error(String(res.status))\n return res.json()\n}\n\n/** 目录插件列表(在线 API 已只返回 verified;过滤与排序由上层负责)。\n * signal 可选:宿主重启/代理抖动导致请求挂起时,上层可中止旧请求释放连接。 */\nexport async function fetchCatalog(lang: LocaleId, signal?: AbortSignal): Promise<HubPlugin[]> {\n const data = await fetchJson(PLUGINS_URL(lang), signal)\n return (Array.isArray(data) ? data : []).map((item) => normalize(item as Record<string, unknown>))\n}\n\n/** 收录/精选统计(/api/stats.json);字段不完整返回 null。 */\nexport async function fetchStats(signal?: AbortSignal): Promise<{ total: number; verified: number } | null> {\n const s = await fetchJson(STATS_URL, signal) as { total?: number; verified?: number }\n if (s && typeof s.total === 'number' && typeof s.verified === 'number') {\n return { total: s.total, verified: s.verified }\n }\n return null\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Hub meta repository: the Cloudflare Worker endpoints behind the self-update\n * check and the \"About us\" content. Failures degrade to null — the caller\n * decides how to fall back (no badge, placeholder copy), never throws.\n */\nimport type { HubAboutInfo, HubUpdateInfo } from '../types.ts'\nimport { HUB_ABOUT_URL, HUB_UPDATE_URL } from '../logic/constants.ts'\n\n/** 版本接口是 Pages 静态文件,默认带 CDN 缓存(Cache-Control: public, max-age=43200,\n * 即 12 小时),客户端 no-store 管不到 CDN 边缘,会拿到旧公告。\n * 静态资产请求免费且无限,因此所有版本检查一律带时间戳 query:URL 每次不同 →\n * CDN 缓存 key 不同 → 强制回源拉到最新公告,无任何配额顾虑。 */\nfunction busted(url: string): string {\n const sep = url.includes('?') ? '&' : '?'\n return `${url}${sep}_t=${Date.now()}`\n}\n\n/** Worker 版本控制中心:最新版本 + Markdown 变更记录;不可用返回 null。 */\nexport async function fetchHubUpdate(): Promise<HubUpdateInfo | null> {\n try {\n const res = await fetch(busted(HUB_UPDATE_URL), { cache: 'no-store' })\n if (!res.ok) return null\n const data = await res.json() as HubUpdateInfo | null\n if (!data) return null\n const version = typeof data.version === 'string' && data.version.length > 0 ? data.version : null\n if (version === null) return null\n return { version, publishedAt: data.publishedAt ?? null, notes: data.notes ?? null }\n } catch {\n return null\n }\n}\n\n/** Worker「关注我们」内容(平台介绍 + 反馈群二维码,Markdown);未推送返回 null。 */\nexport async function fetchHubAbout(): Promise<HubAboutInfo | null> {\n try {\n const res = await fetch(busted(HUB_ABOUT_URL), { cache: 'no-store' })\n if (!res.ok) return null\n const data = await res.json() as HubAboutInfo | null\n if (!data || data.content === null || data.content === undefined) return null\n const content = typeof data.content === 'string' || typeof data.content === 'object' ? data.content : null\n if (content === null) return null\n return { content, updatedAt: data.updatedAt ?? null }\n } catch {\n return null\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Installed-plugin model (pure logic, zero React/UI dependencies).\n *\n * Merges the local installed table (from the host's `/installed` route:\n * npm name → manifest spec) with the catalog projection into a single\n * `InstalledItem` view-model consumed by the Installed view. Also hosts the\n * install matching / update detection used by the market view, so both\n * views share one source of truth.\n */\nimport type { HubPlugin } from '../types.ts'\nimport { HUB_REPO } from './constants.ts'\nimport { repoFromInstallTarget } from './install-command.ts'\n\n/** 安装时记录的目录信号(versions 表项)。 */\nexport interface InstalledVersionSignal {\n version: string\n updatedAt: string\n installedAt?: string\n npmPackage?: string\n}\n\n/** 已安装项统一模型:目录元数据 + 宿主运行时信息的合并视图(驱动「已安装」tab)。 */\nexport interface InstalledItem {\n /** npm 包名(profile 依赖 key) */\n name: string\n /** manifest spec(github:owner/repo、git+https://…、或 npm 版本号) */\n spec: string\n /** 目录里匹配到的插件;目录外/未收录的安装为 null */\n plugin: HubPlugin | null\n /** 仓库身份(owner/repo);纯 npm 安装无法识别时为 null */\n repo: string | null\n /** 安装到系统上的路径(profile/node_modules/<包名>);宿主未提供为 null */\n installPath: string | null\n /** 安装时记录的目录版本(无记录为 null) */\n installedVersion: string | null\n /** 安装时间(ISO,无记录为 null) */\n installedAt: string | null\n /** 目录当前最新版本(仓库无 release 为 null) */\n catalogVersion: string | null\n /** 是否有可用更新(有版本比版本,无版本比仓库更新时间) */\n hasUpdate: boolean\n /** 是否已加载进运行中 loader(官方 ctx.loader 对账);false = 已安装但未挂载(装完未重启) */\n loaded: boolean\n /** 是否真正的 dsh 插件(包内声明 dsh 配置 / 在 profile bundles 清单):\n * 非 dsh 插件(如 GitHub 官方示例仓库)装上也不会被宿主加载,不提示「待重启」 */\n dshCapable: boolean\n}\n\n/** 安装时记录的目录信号(按仓库小写 key 查表)。 */\nfunction signalOf(repo: string | null, versions: Record<string, InstalledVersionSignal>): InstalledVersionSignal | null {\n if (!repo) return null\n return versions[repo.toLowerCase()] ?? null\n}\n\n/** 插件是否已安装:匹配 Git spec 中的 owner/repo,或 npm 通道安装的依赖包名;命中返回 npm 包名。 */\nexport function installedNameOf(\n plugin: HubPlugin,\n installed: Record<string, string>,\n versions: Record<string, InstalledVersionSignal>,\n): string | null {\n const repo = plugin.source?.repo\n if (!repo) return null\n const needle = repo.toLowerCase()\n for (const [name, spec] of Object.entries(installed)) {\n if (repoFromInstallTarget(spec).toLowerCase() === needle) return name\n }\n // npm 通道安装:profile 依赖 key 直接是 npm 包名。包名来源两处——目录数据(npmPackage),\n // 或服务端 npm 优先反查持久化的映射(versions[repo].npmPackage,覆盖组织 scope 与 GitHub\n // 用户名不一致、目录未下发包名的场景);命中任一并依赖 key 真实存在即视为已安装。\n // 只认 npm 安装的依赖(spec 无法解析出仓库身份):git/本地安装的依赖身份由仓库匹配决定,\n // 包名同名不代表同仓库——否则「git 装 A 仓库」会被「npm 包名同名但仓库不同」的目录条目\n // 误认领成已安装(假阳性),installedItems 里出现同 key 双条目,排序一变化就渲染出幽灵行。\n const pkg = ((plugin.source?.npmPackage || versions[repo.toLowerCase()]?.npmPackage) ?? '').toLowerCase()\n if (pkg) {\n for (const [name, spec] of Object.entries(installed)) {\n if (isRepoLike(repoFromInstallTarget(spec))) continue\n if (name.toLowerCase() === pkg) return name\n }\n }\n return null\n}\n\n/** 该插件安装时记录的目录版本(无记录/未安装 → null)。 */\nexport function installedVersionOf(plugin: HubPlugin, versions: Record<string, InstalledVersionSignal>): string | null {\n const repo = plugin.source?.repo\n if (!repo) return null\n return versions[repo.toLowerCase()]?.version ?? null\n}\n\n/**\n * 是否有更新:仅对已安装插件有意义。\n * 双信号判定——有 release 版本的比版本;无版本(repo 不打 tag)的比仓库最近更新时间\n * (repoUpdatedAt,ISO 字符串字典序 = 时间序),更新时间变新说明有新提交。\n */\nexport function hasUpdateOf(\n plugin: HubPlugin,\n installed: Record<string, string>,\n versions: Record<string, InstalledVersionSignal>,\n): boolean {\n if (installedNameOf(plugin, installed, versions) === null) return false\n const repo = plugin.source?.repo\n if (!repo) return false\n const rec = versions[repo.toLowerCase()]\n if (!rec) return false\n if (plugin.version) return plugin.version !== rec.version\n const current = plugin.dates?.repoUpdatedAt\n return Boolean(current && rec.updatedAt && current > rec.updatedAt)\n}\n\n/** 依赖 spec 能否解析出仓库身份(owner/repo 形态才算)。 */\nfunction isRepoLike(value: string): boolean {\n return /^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$/.test(value)\n}\n\n/**\n * 提 Issue 的仓库身份解析:失败目标可能是 owner/repo 也可能是 npm 包名(含 @scope/pkg、\n * 可带 @version,如 dsh-plugin、@scope/pkg@1.2.3)。\n * - 目标本身就能解析出 owner/repo → 直接用;\n * - npm 包名 → 反查仓库身份:先查已安装表(该包名的条目若带仓库身份即命中),再查目录插件\n * (source.npmPackage 与包名一致,取目录收录的仓库身份)。\n * 反查到才返回,查不到返回 null —— 调用方据此不显示「一键提 Issue」按钮,避免把 Issue\n * 提到错误的地址(别人发的 npm 包名不是 GitHub 仓库,直接拼 github.com/<包名> 是打不开的)。\n */\nexport function issueRepoOf(\n target: string,\n installedItems: InstalledItem[],\n plugins: HubPlugin[] | null,\n): string | null {\n const input = target.trim()\n if (!input) return null\n const parsed = repoFromInstallTarget(input)\n if (isRepoLike(parsed)) return parsed\n const pkg = parsed.replace(/@[^@]*$/, '').toLowerCase()\n // 已安装表:包名命中的条目(目录收录条目直接带仓库身份;自定义安装按 github: spec 解析)\n for (const item of installedItems) {\n if (item.name.toLowerCase() !== pkg) continue\n if (item.repo) return item.repo\n const repo = repoFromInstallTarget(item.spec)\n if (isRepoLike(repo)) return repo\n }\n // 目录插件:npmPackage 与包名一致 → 用目录收录的仓库身份\n for (const p of plugins ?? []) {\n const pkgName = (p.source?.npmPackage ?? '').trim()\n if (pkgName !== '' && pkgName.toLowerCase() === pkg && p.source?.repo) return p.source.repo\n }\n return null\n}\n\n/** 已安装项 → 弹窗可用的伪插件对象:卸载确认弹窗只读名称/来源行,\n * 自定义安装(目录外)没有完整目录数据,用它把 InstalledItem 适配成 HubPlugin。 */\nexport function pluginOfItem(item: InstalledItem): HubPlugin {\n return {\n slug: item.name,\n displayName: item.plugin?.displayName ?? item.name,\n source: item.repo ? { repo: item.repo } : undefined,\n description: item.plugin?.description,\n }\n}\n\n/**\n * Hub 自身(本插件 dsh-plugin)的识别:三维互证,杜绝误伤同名第三方包。\n * 1) 依赖 key 固定为 `dsh-plugin`(本插件 npm 包名);\n * 2) spec 为 `file:`/`link:` 本地链接(hub 以 file: 安装进宿主);\n * 3) 或 spec 解析出的仓库身份就是自营仓库 `dshplugin/dsh-plugin-hub`。\n * 命中即视为宿主内置本体:永不出现在「自定义安装」里,卸载接口也早已对\n * 它 400 拒绝(服务端多维防线之一)——显示出来只会让用户误点卸载。\n */\nfunction isHubSelf(name: string, spec: string): boolean {\n if (name !== 'dsh-plugin') return false\n if (spec.startsWith('file:') || spec.startsWith('link:')) return true\n const repo = repoFromInstallTarget(spec)\n if (isRepoLike(repo) && repo.toLowerCase() === HUB_REPO.toLowerCase()) return true\n // npm 通道覆盖重装 hub 自身后,file:/link: 本地链接会被替换成 registry 版本号/范围\n // (如 1.3.0、^1.3.0)——依赖 key `dsh-plugin` 在 npm 上唯一属于本插件(不存在第三方\n // 同名包),版本号形态与仓库身份同样视为 hub 自身:命令窗口「自己装自己」成功后,\n // 条目仍不进已安装列表(卸载接口对它的 400 拒绝是服务端最后一道防线)。\n return !isRepoLike(repo)\n}\n\n/**\n * 构建已安装项列表:目录插件按命中关系合并(拥有完整元数据),\n * 剩余未认领的依赖 key 归为自定义安装(目录外,仅运行时信息)。\n */\nexport function installedItemsOf(\n plugins: HubPlugin[] | null,\n installed: Record<string, string>,\n versions: Record<string, InstalledVersionSignal>,\n paths: Record<string, string> | null,\n loadedNames: string[] | null,\n dshCapableNames: string[] | null,\n): InstalledItem[] {\n const items: InstalledItem[] = []\n // 已被目录条目认领的依赖 key:同一依赖只归属一个目录条目(React key 必须唯一,\n // 否则同名双条目排序一变化就渲染出幽灵行);剩余未认领的归自定义安装。\n const claimed = new Set<string>()\n // 目录匹配:遍历目录插件,命中 installedNameOf 即视为已安装并合并元数据\n for (const p of plugins ?? []) {\n const name = installedNameOf(p, installed, versions)\n if (name === null || claimed.has(name)) continue\n claimed.add(name)\n const repo = p.source?.repo ?? null\n const rec = signalOf(repo, versions)\n items.push({\n name,\n spec: installed[name],\n plugin: p,\n repo,\n installPath: paths?.[name] ?? null,\n installedVersion: rec?.version ?? null,\n installedAt: rec?.installedAt ?? null,\n catalogVersion: p.version ?? null,\n hasUpdate: hasUpdateOf(p, installed, versions),\n loaded: loadedNames?.includes(name) ?? false,\n dshCapable: dshCapableNames?.includes(name) ?? false,\n })\n }\n // 自定义安装:依赖表里没被任何目录插件认领的条目(命令行安装的目录外插件)\n for (const [name, spec] of Object.entries(installed)) {\n if (claimed.has(name)) continue\n // Hub 自身(本插件 dsh-plugin)由宿主内置加载,不是可管理的插件:永不进已安装列表,\n // 避免出现在「自定义安装」里被误点卸载(服务端卸载接口对它的 400 拒绝是最后一道防线)\n if (isHubSelf(name, spec)) continue\n const parsed = repoFromInstallTarget(spec)\n const repo = isRepoLike(parsed) ? parsed : null\n const rec = signalOf(repo, versions)\n items.push({\n name,\n spec,\n plugin: null,\n repo,\n installPath: paths?.[name] ?? null,\n installedVersion: rec?.version ?? null,\n installedAt: rec?.installedAt ?? null,\n catalogVersion: null,\n // 目录外没有目录信号可比,无法判断是否有更新\n hasUpdate: false,\n loaded: loadedNames?.includes(name) ?? false,\n dshCapable: dshCapableNames?.includes(name) ?? false,\n })\n }\n return items\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Catalog data + view state for the Plugin Hub section.\n *\n * Owns the online-data pipeline (live fetch from api.dsh-plugin.org), the local\n * installed-plugin table, and the filter/search/sort/install-status view\n * state, exposing the derived visible list and per-category counts.\n */\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport type { HubPlugin, LocaleId } from '../types.ts'\nimport { HUB_REPO, PLUGIN_VERSION } from '../logic/constants.ts'\nimport type { HubAboutInfo, HubUpdateInfo } from '../types.ts'\nimport type { SortKey } from '../logic/constants.ts'\nimport { fetchCatalog, fetchStats } from '../data/catalog.ts'\nimport { fetchHubAbout, fetchHubUpdate } from '../data/hub.ts'\nimport { fetchInstalled } from '../data/host.ts'\nimport {\n hasUpdateOf, installedItemsOf, installedNameOf, installedVersionOf,\n} from '../logic/installed.ts'\nimport type { InstalledItem, InstalledVersionSignal } from '../logic/installed.ts'\n\n/** 插件市场自身仓库:DSH Plugin Hub 不显示在目录里(自己不进自己的插件列表) */\nconst SELF_REPO = 'dshplugin/dsh-plugin-hub'\n\n/** 市场各排序的默认方向:全部按倒序(Star/Fork 多、更新/收录近的在前) */\nconst SORT_DEFAULT_DIR: Record<SortKey, 'asc' | 'desc'> = {\n sortStars: 'desc', sortForks: 'desc', sortUpdated: 'desc', sortNewest: 'desc',\n}\n\nexport function useCatalog(lang: LocaleId) {\n /** 目录插件(仅保留人工验证通过的条目) */\n const [plugins, setPlugins] = useState<HubPlugin[] | null>(null)\n /** Hub 自身目录条目(dshplugin/dsh-plugin-hub):目录过滤会排除自身(不进插件列表),\n * 此处单独保留,供头部「可更新」徽标 → 「直接更新」覆盖重装使用。 */\n const [hubPlugin, setHubPlugin] = useState<HubPlugin | null>(null)\n /** 收录/精选统计(官网 /api/stats.json 实时拉取) */\n const [stats, setStats] = useState<{ total: number; verified: number } | null>(null)\n const [failed, setFailed] = useState(false)\n const [reloadKey, setReloadKey] = useState(0)\n const [category, setCategory] = useState('all')\n const [query, setQuery] = useState('')\n const [sort, setSort] = useState<SortKey>('sortStars')\n /** 当前排序方向:点同一个排序按钮切换 正序/倒序;点新排序用该排序的默认方向(与已安装视图一致) */\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')\n /** 目录加载「超时自动强制刷新」重试计数:宿主重启/代理未就绪时请求可能长时间挂起,\n * 界面停在「正在加载插件数据…」假死 —— 超时自动重拉,最多自动重试 2 次后转失败态;\n * 用户手动刷新(reload)时清零重新计数。 */\n const loadRetriesRef = useRef(0)\n /** 目录加载超时阈值:超过即判定挂起,强制刷新一次(服务端代理 curl 上限 20s,客户端 12s 先兜底) */\n const LOAD_TIMEOUT_MS = 12000\n /** 挂起后最多自动重试次数:避免代理持续不通时无限循环刷新(每次重试仍 12s,2 次后转失败界面可手动重试) */\n const MAX_LOAD_RETRIES = 2\n\n /** 点击排序按钮:同一按钮切换正/倒序,新按钮用默认方向 */\n function toggleSort(key: SortKey) {\n if (key === sort) setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))\n else { setSort(key); setSortDir(SORT_DEFAULT_DIR[key]) }\n }\n /**\n * 强制刷新 Hub 版本与「关注我们」信息:点击头部版本号/徽标时触发。\n * 挂载期的 useEffect 只在进入/reload 时拉一次,发版后已打开的界面点版本号\n * 仍显示旧数据;此处重新拉接口中心,最新版本与变更记录点击即见。\n * 失败静默为 null(弹窗兜底展示当前版本号),与挂载期拉取口径一致。\n */\n const refreshHub = async () => {\n // 版本接口已恒带时间戳绕过 CDN,手动/自动拉取都能拿到最新公告\n const [info, about] = await Promise.all([fetchHubUpdate(), fetchHubAbout()])\n setHubUpdateInfo(info)\n setHubAboutInfo(about)\n }\n\n /** 当前 profile 已安装插件:npm 包名 -> manifest spec(来自宿主本地路由) */\n const [installed, setInstalled] = useState<Record<string, string>>({})\n /** 安装时记录的目录信号:repo(小写) -> { version, updatedAt }(来自宿主本地路由);\n * npmPackage 为 npm 优先通道反查命中的包名映射(目录数据未下发时客户端靠它把依赖 key 匹配回仓库) */\n const [versions, setVersions] = useState<Record<string, InstalledVersionSignal>>({})\n /** 每个依赖在系统上的安装目录(profile/node_modules/<包名>),详情视图展示用 */\n const [installPaths, setInstallPaths] = useState<Record<string, string> | null>(null)\n /** 已加载进运行中 loader 的包名(官方 ctx.loader 对账):装完未重启的新插件不在其中 */\n const [loadedNames, setLoadedNames] = useState<string[] | null>(null)\n /** 真正的 dsh 插件包名(包内声明 dsh 配置 / 在 profile bundles 清单):非 dsh 插件不提示「待重启」 */\n const [dshCapableNames, setDshCapableNames] = useState<string[] | null>(null)\n /** Hub 自我更新信息:来自接口中心 Pages(api.dsh-plugin.org),与目录数据解耦 */\n const [hubUpdateInfo, setHubUpdateInfo] = useState<HubUpdateInfo | null>(null)\n /** 头部「关注我们」弹窗内容(平台介绍 + 反馈群二维码):来自接口中心 /about,Markdown 推送非写死 */\n const [hubAboutInfo, setHubAboutInfo] = useState<HubAboutInfo | null>(null)\n\n // 拉取目录 + 统计。在线 API 已只返回 verified;再过滤一次,保证只展示人工验证通过的插件。\n useEffect(() => {\n let cancelled = false\n // 本次加载是否已收尾(成功或失败):超时定时器只对「还在加载中」生效\n let settled = false\n // 中止控制器:请求挂起时(宿主重启/代理抖动)超时自动重试会换新请求,\n // 旧请求在此中止释放连接,避免挂起堆积\n const controller = new AbortController()\n setPlugins(null)\n setHubPlugin(null)\n setStats(null)\n setFailed(false)\n // 此处只拉目录与统计;hub 自身版本由独立 Worker 版本控制中心提供(见 fetchHubUpdate)。\n const load = () => Promise.all([fetchCatalog(lang, controller.signal), fetchStats(controller.signal)])\n load()\n .then(([list, stats]) => {\n if (cancelled) return\n settled = true\n // 插件市场不显示自己:DSH Plugin Hub 从目录里排除自身条目,\n // 防止「自己出现在自己的插件列表里、还能自己安装自己」;统计计数同步减 1 保持与列表一致。\n // 目录数据已排除自身,此处再兜底过滤一次,防旧快照仍含自身条目。\n const hadSelf = list.some((p) => p.source?.repo === SELF_REPO)\n // 过滤前单独保留 hub 自身条目:它不进目录列表,但「可更新」徽标的直接更新需要它作为重装目标\n setHubPlugin(list.find((p) => p.source?.repo === SELF_REPO) ?? null)\n setPlugins(list.filter((p) => p.compatibility?.status === 'verified' && p.source?.repo !== SELF_REPO))\n if (stats) {\n setStats(hadSelf\n ? { total: stats.total - 1, verified: stats.verified - 1 }\n : { total: stats.total, verified: stats.verified })\n }\n })\n .catch(() => {\n if (cancelled) return\n settled = true\n setFailed(true)\n })\n // 加载超时兜底:宿主刚重启/代理未就绪时目录请求可能长时间挂起,界面停在「正在加载插件数据…」\n // 像假死。超过阈值未收尾 → 强制刷新列表(重拉一次,最多 MAX_LOAD_RETRIES 次自动重试),\n // 重试仍失败 → 转失败界面(显示「重试」按钮,手动刷新时计数清零重新开始)。\n const timer = window.setTimeout(() => {\n if (cancelled || settled) return\n if (loadRetriesRef.current < MAX_LOAD_RETRIES) {\n loadRetriesRef.current += 1\n setReloadKey((k) => k + 1)\n } else {\n setFailed(true)\n }\n }, LOAD_TIMEOUT_MS)\n return () => {\n cancelled = true\n window.clearTimeout(timer)\n controller.abort()\n }\n // lang 必须进依赖:切换界面语言要重新拉对应语言的数据文件,\n // 否则英文模式仍停留在 plugins.zh.json,描述/名称全是中文\n }, [reloadKey, lang])\n\n /** 刷新当前 profile 已安装插件表;宿主未挂本地路由时静默降级为空表。 */\n const refreshInstalled = async () => {\n const data = await fetchInstalled()\n if (data === null) return\n setInstalled(data.installed)\n setVersions(data.versions)\n setInstallPaths(data.paths)\n setLoadedNames(data.loaded)\n setDshCapableNames(data.dshCapable)\n }\n\n // 首次进入拉取已安装表(依赖宿主 webServer 服务)\n useEffect(() => { refreshInstalled() }, [])\n\n // Hub 自身版本检查走独立 Worker(版本控制中心):发新版后写一次 Worker KV,\n // 所有已装用户立即看到「可更新」+ Markdown 变更记录,不经过主站目录数据管道。\n // 失败静默降级为 null(徽标不出现,不影响目录本身加载)。\n useEffect(() => {\n let cancelled = false\n void fetchHubUpdate().then((info) => { if (!cancelled) setHubUpdateInfo(info) })\n return () => { cancelled = true }\n }, [reloadKey])\n\n // 「关注我们」内容走同一套 Worker:作者写好 Markdown(平台介绍 + 反馈群二维码)推送 /admin/about,\n // 客户端下次进入拉 /about 即可看到最新,非写死。失败静默为 null(弹窗展示兜底文案,不阻塞)。\n useEffect(() => {\n let cancelled = false\n void fetchHubAbout().then((info) => { if (!cancelled) setHubAboutInfo(info) })\n return () => { cancelled = true }\n }, [reloadKey])\n\n /** 插件是否已安装:匹配 Git spec 中的 owner/repo,或 npm 通道安装的依赖包名;命中返回 npm 包名。 */\n const installedName = (p: HubPlugin): string | null => installedNameOf(p, installed, versions)\n\n /** 该插件安装时记录的目录版本(无记录/未安装 → null)。 */\n const installedVersion = (p: HubPlugin): string | null => installedVersionOf(p, versions)\n\n /**\n * 是否有更新:仅对已安装插件有意义。\n * 双信号判定——有 release 版本的比版本;无版本(repo 不打 tag)的比仓库最近更新时间\n * (repoUpdatedAt,ISO 字符串字典序 = 时间序),更新时间变新说明有新提交。\n */\n const hasUpdate = (p: HubPlugin): boolean => hasUpdateOf(p, installed, versions)\n\n /** 已安装项统一列表(目录元数据 + 运行时信息合并):驱动「已安装」tab。 */\n const installedItems = useMemo<InstalledItem[]>(\n () => installedItemsOf(plugins, installed, versions, installPaths, loadedNames, dshCapableNames),\n [plugins, installed, versions, installPaths, loadedNames, dshCapableNames],\n )\n\n /**\n * Hub 自身是否有可用更新:Hub 就是当前运行的应用(始终已安装,无需 installedName 命中)。\n * 以 Worker 版本控制中心返回的「最新版本」为准,与当前运行的版本号比对——\n * 构建时注入的 PLUGIN_VERSION 是运行 bundle 的真实版本;测试/异常场景缺失时\n * 回退到安装时记录的版本。版本号不等即新版(版本号只在发版时变更,绝无降级场景)。\n *\n * 另加 pnpm 供应链安全门槛:新版本发布还不满 24 小时(+30 分钟缓冲)时,pnpm 会静默\n * 回退到旧版本,此时若提示「可更新」用户点了也更新不到。publishedAt 由接口中心按 npm\n * registry 真实发布时间下发(同源),据此判断最准。\n */\n const hubHasUpdate = (() => {\n if (!hubUpdateInfo) return false\n const current = PLUGIN_VERSION || versions[HUB_REPO]?.version || null\n if (current === null || hubUpdateInfo.version === current) return false\n const publishedAt = hubUpdateInfo.publishedAt\n if (publishedAt) {\n const publishedMs = Date.parse(publishedAt)\n if (!Number.isNaN(publishedMs)) {\n // 24 小时 + 30 分钟缓冲(防网络/CDN 边缘时间偏差)\n const MIN_RELEASE_AGE_MS = 24 * 60 * 60 * 1000 + 30 * 60 * 1000\n if (Date.now() - publishedMs < MIN_RELEASE_AGE_MS) return false\n }\n }\n return true\n })()\n\n /** 当前分类下的插件(「全部」时为整个目录)。 */\n const categoryPlugins = useMemo(() => {\n if (!plugins) return []\n if (category === 'all') return plugins\n return plugins.filter((p) => p.category === category)\n }, [plugins, category])\n\n const visible = useMemo(() => {\n if (!plugins) return []\n const q = query.trim().toLowerCase()\n const list = plugins.filter((p) => {\n if (category !== 'all' && p.category !== category) return false\n if (!q) return true\n return (\n (p.displayName ?? '').toLowerCase().includes(q) ||\n (p.description ?? '').toLowerCase().includes(q) ||\n (p.topics ?? []).some((topic) => topic.toLowerCase().includes(q))\n )\n })\n const dir = sortDir === 'asc' ? 1 : -1\n return [...list].sort((a, b) => {\n // 比较器统一用「升序写法」再乘 dir:desc 时 dir=-1 翻成降序(Star/Fork 最多、更新/收录最近在前)\n if (sort === 'sortStars') return ((a.stats?.stargazers_count ?? 0) - (b.stats?.stargazers_count ?? 0)) * dir\n if (sort === 'sortForks') return ((a.stats?.forks_count ?? 0) - (b.stats?.forks_count ?? 0)) * dir\n if (sort === 'sortNewest') return (a.dates?.addedAt ?? '').localeCompare(b.dates?.addedAt ?? '') * dir\n return (a.dates?.repoUpdatedAt ?? '').localeCompare(b.dates?.repoUpdatedAt ?? '') * dir\n })\n }, [plugins, category, query, sort, sortDir, installed])\n\n /** Per-category plugin counts shown on the category chips. */\n const categoryCounts = useMemo(() => {\n const counts: Record<string, number> = {}\n for (const p of plugins ?? []) {\n if (p.category) counts[p.category] = (counts[p.category] ?? 0) + 1\n }\n return counts\n }, [plugins])\n\n return {\n plugins,\n hubPlugin,\n stats,\n failed,\n reload: () => { loadRetriesRef.current = 0; setReloadKey((k) => k + 1) },\n installed,\n installedItems,\n installedName,\n installedVersion,\n hasUpdate,\n hubHasUpdate,\n hubUpdateInfo,\n hubAboutInfo,\n refreshHub,\n refreshInstalled,\n category,\n setCategory,\n query,\n setQuery,\n sort,\n sortDir,\n toggleSort,\n visible,\n total: plugins?.length ?? 0,\n categoryCounts,\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Failure classification, issue-body summarization and persistent\n * install/remove notifications.\n *\n * Every settled task is recorded two ways: the server-side system log\n * (hub.log) and a client-side localStorage record that feeds the\n * notification center — so a result is never lost even when the dialog\n * was dismissed or nobody was watching the progress strip.\n */\nexport interface NotificationRecord {\n id: number\n kind: 'install' | 'uninstall' | 'update'\n /** true = 成功(轻量记录);false = 失败(message 携带完整错误日志) */\n ok: boolean\n /** owner/repo(可能为空:请求层失败但拿不到仓库时) */\n repo: string\n /** 实际动作(install/update/uninstall):成功/失败通知据此区分「安装成功」与「更新成功」。\n * 缺省按 kind 兜底(历史记录可能没有该字段)。更新提醒(kind='update')不用此字段。 */\n action?: 'install' | 'update' | 'uninstall'\n /** 失败时的完整错误日志;成功记录为空串 */\n message: string\n /** 更新提醒:目录里的新版本号(展示用;其余通知省略) */\n version?: string\n /** 实际执行的安装/卸载命令(issue 预填时如实展示);历史记录可能缺失 */\n command?: string\n /** 尝试过的安装方式(npm registry 反查 + 实际执行命令,按先后顺序):失败提 Issue 时贴给作者,便于反推正确的 npm 包名 */\n attempts?: string[]\n /** 结束时间(epoch ms) */\n at: number\n}\n\nconst KEY = 'gro.ngilp-hsd.failure-records'\nconst MAX = 50\n\n/** 运行时 localStorage 访问:类型上不依赖 DOM lib(Node 测试环境也能编译),浏览器里取 window。 */\nconst storage = (): Storage | undefined =>\n (globalThis as { localStorage?: Storage }).localStorage\n\n/** 读取本地通知记录(损坏/不可用时返回空列表,不抛错)。列表最新在前,全部保留,只由「清空」按钮手动移除。 */\nexport function loadNotifications(): NotificationRecord[] {\n try {\n const raw = storage()?.getItem(KEY)\n if (!raw) return []\n const list = JSON.parse(raw) as unknown\n if (!Array.isArray(list)) return []\n return list\n .filter((r): r is NotificationRecord =>\n !!r && typeof r === 'object' && typeof (r as { message?: unknown }).message === 'string')\n // ok 字段缺省时按失败渲染\n .map((r) => ({ ...r, ok: r.ok === true }))\n } catch {\n return []\n }\n}\n\nfunction save(list: NotificationRecord[]): void {\n try {\n storage()?.setItem(KEY, JSON.stringify(list))\n } catch {\n /* storage full / unavailable:仅保留内存态,界面仍可查看 */\n }\n}\n\n/** 追加一条通知记录并持久化,返回更新后的完整列表(最新在前,超上限裁剪)。\n * 每次成功/失败都各自留痕:同一插件的安装/卸载记录都完整保留、只由「清空」按钮手动移除,\n * 不会因后续操作被自动覆盖清除。 */\nexport function addNotification(record: Omit<NotificationRecord, 'id' | 'at'>): NotificationRecord[] {\n const prev = loadNotifications()\n let id = Date.now()\n while (prev.some((r) => r.id === id)) id += 1\n const next = [{ ...record, id, at: id }, ...prev].slice(0, MAX)\n save(next)\n return next\n}\n\n/** 记录一次失败:携带完整错误日志,供通知中心查看/复制/提 Issue。 */\nexport function addFailure(record: Omit<NotificationRecord, 'id' | 'at' | 'ok'>): NotificationRecord[] {\n return addNotification({ ...record, ok: false })\n}\n\n/** 记录一次成功:轻量记录,不带日志。 */\nexport function addSuccess(record: Omit<NotificationRecord, 'id' | 'at' | 'ok' | 'message'>): NotificationRecord[] {\n return addNotification({ ...record, ok: true, message: '' })\n}\n\n/** 记录一条「发现新版本」更新提醒:成功类轻量记录,携带目录新版本号供通知中心展示。\n * 同一插件同一新版本已在通知中心时跳过:宿主重载会重新触发启动检查,不更新时\n * 通知里已有的提醒保持单条,不重复追加。 */\nexport function addUpdateNotice(record: Omit<NotificationRecord, 'id' | 'at' | 'ok' | 'message'>): NotificationRecord[] {\n const prev = loadNotifications()\n const dup = prev.some((r) =>\n r.kind === 'update' && r.repo === record.repo && (r.version ?? undefined) === (record.version ?? undefined))\n if (dup) return prev\n return addNotification({ ...record, ok: true, message: '' })\n}\n\n/** 已忽略的更新提醒持久化 key:`owner/repo@version` 字符串数组。 */\nconst IGNORE_KEY = 'gro.ngilp-hsd.ignored-updates'\n\n/** 读取已忽略的更新提醒(`owner/repo@version` 字符串集合);损坏/不可用时返回空集合。 */\nexport function loadIgnoredUpdates(): Set<string> {\n try {\n const raw = storage()?.getItem(IGNORE_KEY)\n if (!raw) return new Set()\n const list = JSON.parse(raw) as unknown\n if (!Array.isArray(list)) return new Set()\n return new Set(list.filter((x): x is string => typeof x === 'string'))\n } catch {\n return new Set()\n }\n}\n\nfunction saveIgnoredUpdates(ignored: Set<string>): void {\n try {\n storage()?.setItem(IGNORE_KEY, JSON.stringify([...ignored]))\n } catch {\n /* storage full / unavailable:仅保留内存态 */\n }\n}\n\n/** 忽略某插件本次更新(repo+version 持久化入忽略集):本次版本不再提醒,直到下一个新版本发布。 */\nexport function ignoreUpdate(repo: string, version?: string): Set<string> {\n const next = loadIgnoredUpdates()\n next.add(`${repo}@${version ?? ''}`)\n saveIgnoredUpdates(next)\n return next\n}\n\n/** 移除某插件某版本的更新提醒记录(忽略本次更新时一并清理通知),返回更新后的列表。 */\nexport function removeUpdateNotice(repo: string, version?: string): NotificationRecord[] {\n const next = loadNotifications().filter((r) =>\n !(r.kind === 'update' && r.repo === repo && (r.version ?? undefined) === (version ?? undefined)))\n save(next)\n return next\n}\n\n/** 清空全部通知记录,返回空列表。 */\nexport function clearNotifications(): NotificationRecord[] {\n save([])\n return []\n}\n\n/** 按 id 删除单条通知记录,返回更新后的列表(仅移除该条,不影响其余记录)。 */\nexport function removeNotification(id: number): NotificationRecord[] {\n const next = loadNotifications().filter((r) => r.id !== id)\n save(next)\n return next\n}\n\nexport type FailureKind = 'npmTooOld' | 'dshMissing' | 'gitMissing' | 'pnpmMissing' | 'npmMissing' | 'pnpmStore' | 'pnpmWorkspace' | 'originRejected' | 'pnpmPolicy' | 'pnpmUnusedPatch' | 'pnpmMissingDep' | 'fileLocked' | 'accessDenied' | 'fsUnavailable' | 'pnpmIgnoredBuild' | 'pluginPrepare' | 'network' | 'repo'\n\n/** Match the pnpm error code, not a generic mention of checksum or integrity. */\nfunction missingTarballIntegrity(message: string): boolean {\n return /\\bERR_PNPM_MISSING_TARBALL_INTEGRITY\\b/.test(message)\n}\n\n/** pnpm 拒收「刚发布」包时,报错里带着发布时间;这里从报错文本算出「发布满 24h」的可重试时刻(UTC,分钟精度)。 */\nexport function releaseAgeRetryAfter(message: string): string | null {\n const match = /published at (\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z)/.exec(message)\n if (match === null) return null\n const published = Date.parse(match[1])\n if (Number.isNaN(published)) return null\n return `${new Date(published + 24 * 60 * 60 * 1000).toISOString().slice(0, 16)}Z`\n}\n\n/**\n * The same policy subtype selects recovery copy in live and saved failures.\n * minimumReleaseAge 只有在能算出可重试时刻时才走专属文案(给出确切的「何时可再试」),\n * 算不出时退回通用文案,避免出现「预计可重试时间:」后接空值的残缺句子。\n */\nexport function pnpmPolicyHintOf(message: string): 'failPnpmTarballIntegrityHint' | 'failPnpmReleaseAgeHint' | 'failPnpmPolicyHint' {\n if (missingTarballIntegrity(message)) return 'failPnpmTarballIntegrityHint'\n if (/ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION|Minimum release age/i.test(message)\n && releaseAgeRetryAfter(message) !== null) {\n return 'failPnpmReleaseAgeHint'\n }\n return 'failPnpmPolicyHint'\n}\n\n/** 与 pnpmPolicyHintOf 配套的文案参数:release-age 场景给出可重试时刻({time})。 */\nexport function pnpmPolicyHintParams(message: string): Record<string, string> {\n return { time: releaseAgeRetryAfter(message) ?? '' }\n}\n\n/**\n * 失败归类:把安装输出归到具体成因,供弹窗文案、是否引导提 Issue 与 issue 预填原因使用。\n * 分界是「本机环境问题」(装任何插件都会同样失败 → 不引导提 Issue)与\n * 「插件分发/依赖问题」(只影响这个插件 → 引导去仓库提 Issue);各分支的判定顺序有依赖,\n * 原因见 classifyFailure 内注释。\n *\n * 本机环境问题:\n * - npmTooOld:本机 npm 版本过低或自身缺陷 —— npm arborist 解 peer 依赖时抛 `edgesOut`\n * (build-ideal-tree.js 内部报错),或服务端已核实版本低于阈值并打了 `[npm-too-low]` 标记\n * → 引导升级 npm\n * - dshMissing:安装器 spawn 的 `dsh` 命令找不到(Windows cmd「不是内部或外部命令」/ POSIX\n * 「command not found」/ spawn ENOENT)→ 提示检查 PATH / 重装 DSH\n * - gitMissing:安装器调用 `git` 时找不到可执行文件(Windows cmd「'git' is not recognized」/\n * POSIX「git: command not found」/ spawn ENOENT)→ 提示安装 Git / 加入 PATH\n * - pnpmMissing:dsh 存在但调用的 `pnpm` 找不到(dsh 报 `pnpm not found on PATH` / POSIX\n * 「pnpm: command not found」/ spawn ENOENT)—— dsh 用 pnpm 管理 profile 插件\n * → 提示安装 / 开启 pnpm\n * - npmMissing:全局 npm 安装通道(`npm install -g …`)spawn 的 `npm` 命令找不到,形态同上\n * → 提示安装 npm(Node.js 自带)/ 加入 PATH\n * - pnpmStore:pnpm 报 store / virtual store 位置不匹配(`ERR_PNPM_UNEXPECTED_STORE` /\n * `ERR_PNPM_UNEXPECTED_VIRTUAL_STORE` / `Unexpected store location`)—— profile 目录里的依赖\n * 是另一个大版本的 pnpm 生成的(或 profile 目录被复制/移动、virtual-store-dir 配置变化),\n * 当前 pnpm 出于安全不认 → 提示清理 profile 依赖目录后用当前 pnpm 重建\n * - pnpmWorkspace:pnpm 拒绝在 workspace 根目录下安装(`ERR_PNPM_ADDING_TO_ROOT`)—— profile\n * 目录含 pnpm-workspace.yaml 即被 pnpm 视为 workspace 根,宿主调 `pnpm add` 时未声明在根\n * 操作(缺 `-w`/`--workspace-root`),整条命令被拒 → 提示在 profile 的 .npmrc 里加\n * `ignore-workspace-root-check=true` 或升级宿主\n * - originRejected:请求的来源没通过本地 hub 服务的校验(服务端 403,正文是裸的\n * `untrusted origin`)—— 请求在进入安装流程前就被拒,与 pnpm 无关;常见于用非 localhost 的\n * 地址(如局域网 IP)打开市场页面,或宿主页面的 origin 未被识别 → 提示从本机地址打开市场后重试\n * - pnpmPolicy:pnpm 的供应链安全策略拒绝安装(缺少 tarball integrity、`ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION` /\n * `Minimum release age` —— 锁文件里包的发布时间还不满 24 小时被拒;`untrusted origin` ——\n * 依赖来源未被本机 pnpm 信任)→ 提示按子场景给解法(发布未满 24 小时 → `minimumReleaseAge: 0`\n * 豁免或等满 24 小时;untrusted origin → 删除 profile 的 node_modules + pnpm-lock.yaml 清掉\n * 不受信任来源后重装)\n * - pnpmUnusedPatch:profile 里留着指向旧版本 dsh-plugin 的 patch 声明,本次安装解析到的版本\n * 已经不是它(`ERR_PNPM_UNUSED_PATCH` / `The following patches were not used: dsh-plugin@1.4.2`)\n * —— pnpm 发现补丁没被用上即中止整次安装 → 提示删掉该条目后重试\n * - pnpmMissingDep:profile 里留着一条指向 registry 上不存在的包的依赖,pnpm 解析时收到 404\n * (`ERR_PNPM_FETCH_404` / `Not Found - 404`)—— 该 profile 的任何安装都会先卡在这条依赖上\n * → 提示按包名删掉该条目后重试(404 的包通常不是正在安装的插件,故不引导提 Issue)\n * - fileLocked:pnpm 无法替换 profile 里被其他进程占用的文件(Windows `os error 32`\n * 「另一个程序正在使用此文件」/ `EBUSY` / `resource busy or locked`)—— 通常是宿主进程或\n * 杀毒软件实时扫描持有句柄 → 提示完全退出宿主后重试\n * - accessDenied:pnpm 在 profile 里替换文件时被系统拒绝写入(Windows `os error 5`\n * 「拒绝访问」= ERROR_ACCESS_DENIED / Node 的 `EPERM` `EACCES` / `Access is denied`)——\n * 文件/目录被其他进程占用、只读属性、目录 ACL 受限,或杀毒软件实时防护拦截写入\n * → 提示退出宿主 / 关杀软后重试,仍失败则检查只读属性并以管理员身份运行\n * - fsUnavailable:本机文件系统层面根本写不进去 —— 磁盘/分区空间耗尽(`ENOSPC` /\n * `no space left on device`,Windows 为 `os error 112`)、目标分卷或挂载点为只读\n * (`EROFS` / `read-only file system`,Windows 写保护为 `os error 19`)、进程可用的文件句柄\n * 被耗尽(`EMFILE` / `ENFILE` / `too many open files`),都发生在 pnpm 落盘阶段\n * → 提示按报错代码对号入座(清空间 / 换可写目录 / 重启宿主释放句柄)\n * - network:安装前连通性预检拦截(服务端 `[network]` 标记)、底层连接失败\n * (ERR_PNPM_GIT_FETCH_FAILED / ETIMEDOUT / DNS 解析 / TLS 握手 / 代理拒绝),或\n * registry tarball 拉取失败(`fetch failed` / `GET …/-/…tgz error (n)` —— 常见于本机\n * npm/pnpm 的 registry 被指向内网/自定义源,该源取不到包),或界面请求压根没送达宿主服务\n * (浏览器 fetch 的 `Failed to fetch` —— 宿主未就绪/正在重启,或本地代理拦了回环地址)\n * → 提示检查网络,registry 指向自定义源时给出换源指引\n *\n * 插件分发/依赖问题(引导去仓库提 Issue):\n * - pnpmIgnoredBuild:插件自身或依赖的构建脚本被 pnpm 安全白名单(allowBuilds)默认拦截\n * (`ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED` / `ERR_PNPM_IGNORED_BUILDS`)—— 只影响带安装期\n * 构建的插件 → 建议改用预编译版本或关闭安装期构建\n * - pluginPrepare:插件的 prepare/构建脚本实际执行失败(git tarball 常因缺失子模块或构建产物\n * 导致),或装后校验发现 package.json 声明的入口文件不在发布物里(服务端 `[packaging]` 标记)\n * —— 属插件打包/分发问题\n * - repo:其余失败,默认按插件仓库问题处理\n */\nexport function classifyFailure(message: string): FailureKind {\n // npm 内部崩溃(edgesOut)或服务端 [npm-too-low] 标记:是本机 npm 版本过低/自身缺陷,\n // 不是插件问题 —— 必须最先判,否则该报错会被外层 ERR_PNPM_PREPARE_PACKAGE 吞成\n // 「插件打包分发问题」,误导用户去提 Issue\n if (/\\[npm-too-low\\]|edgesOut/i.test(message)) return 'npmTooOld'\n // 找不到 pnpm 命令(dsh 报 `pnpm not found on PATH` —— dsh 用它管理 profile 插件 /\n // POSIX「pnpm: command not found」/ spawn pnpm ENOENT / Windows cmd 中英文报错):\n // 本机缺 pnpm。必须在 dshMissing 之前 —— dshMissing 正则含裸「command not found」,\n // 会把 `pnpm: command not found` 吞成「dsh 缺失」,误引导用户去装 DSH\n if (/\\[pnpm-missing\\]|pnpm not found|pnpm: command not found|spawn pnpm ENOENT|'pnpm' 不是内部或外部命令|\"pnpm\" 不是内部或外部命令|pnpm['\"]?\\s*is not recognized/i.test(message)) return 'pnpmMissing'\n // 找不到 git 命令(服务端 [git-missing] 标记 / Windows cmd 中英文「'git' is not recognized」/\n // POSIX「git: command not found」/ spawn git ENOENT):本机 Git 未安装或不在 PATH。\n // 必须在 dshMissing 之前 —— dshMissing 正则含裸「is not recognized / command not found」,\n // 会把 git 缺失('git' is not recognized as an internal or external command)吞成「dsh 缺失」,\n // 误导用户去装 DSH\n if (/\\[git-missing\\]|spawn git ENOENT|'git' 不是内部或外部命令|\"git\" 不是内部或外部命令|git['\"]?\\s*is not recognized|git: command not found/i.test(message)) return 'gitMissing'\n // 找不到 npm 命令(全局 npm 安装通道 `npm install -g` spawn 的 npm 缺失 / Windows cmd 中英文\n // 「'npm' is not recognized」/ POSIX「npm: command not found」/ spawn npm ENOENT):本机 npm 未安装\n // 或不在 PATH,不是插件问题。必须在 dshMissing 之前 —— dshMissing 正则含裸「is not recognized /\n // command not found」,会把 npm 缺失('npm' is not recognized)吞成「dsh 缺失」,误导用户去装 DSH\n if (/\\[npm-missing\\]|spawn npm ENOENT|'npm' 不是内部或外部命令|\"npm\" 不是内部或外部命令|npm['\"]?\\s*is not recognized|npm: command not found/i.test(message)) return 'npmMissing'\n // 找不到 dsh 命令(服务端 [dsh-missing] 标记 —— 乱码免疫:Windows cmd 中文版输出 GBK,\n // 经 UTF-8 解码成乱码无法匹配原文,故服务端在 spawn 前用 which/where 探测并打 ASCII 标记;\n // 其余形态:Windows cmd「不是内部或外部命令」/ POSIX「command not found」/\n // node spawn ENOENT):是本机 DSH 未正确安装或不在 PATH —— 必须先判,\n // 否则会被外层 \"Command failed\" 吞成「插件打包问题」,误导用户去提 Issue\n if (/\\[dsh-missing\\]|不是内部或外部命令|is not recognized as an internal or external command|command not found|spawn dsh ENOENT/i.test(message)) return 'dshMissing'\n // pnpm 大版本/虚拟 store 位置不一致(ERR_PNPM_UNEXPECTED_STORE / ERR_PNPM_UNEXPECTED_VIRTUAL_STORE /\n // Unexpected store location):profile 目录里的依赖是另一个大版本 pnpm 生成的(或 profile 目录\n // 被复制/移动、virtual-store-dir 配置变化导致 virtual store 位置不匹配),当前 pnpm 出于安全\n // 不认 —— 任何插件装进该 profile 都会同样失败 → 提示清理依赖目录用当前 pnpm 重建。\n // 必须在 pnpmMissing 之后 —— pnpm 在(能跑起来报错),不是「找不到命令」。\n if (/ERR_PNPM_UNEXPECTED_(VIRTUAL_)?STORE|Unexpected (virtual )?store location/i.test(message)) return 'pnpmStore'\n // pnpm 拒绝在 workspace 根目录下安装(ERR_PNPM_ADDING_TO_ROOT):profile 目录被视为\n // pnpm workspace 根,宿主调 pnpm add 时没声明在根操作(缺 -w/--workspace-root),\n // pnpm 直接整条命令拒绝 —— 本机 profile/宿主调用方式问题,任何插件都装不上\n if (/ERR_PNPM_ADDING_TO_ROOT|add the dependency to the workspace root/i.test(message)) return 'pnpmWorkspace'\n // 本地 hub 服务的来源校验拒绝了请求(服务端 403,正文恰好是 `untrusted origin`):\n // 请求在 requireTrustedPost 就被拦下,压根没进入安装流程,与 pnpm 无关。\n // 必须放在 pnpmPolicy 之前 —— 后者正则含同名裸文本,会把这条吞成「pnpm 供应链策略」,\n // 并建议用户删掉 profile 的 node_modules + pnpm-lock.yaml(无效且具破坏性)。\n // 用「整行以它结尾」来区隔 pnpm 的真实报错:pnpm 的形态后面一定跟着 dsh 的上下文\n // (如 `untrusted origin\\ndsh: pnpm failed in profile directory …`),不会被本规则命中\n if (/(^|\\n)untrusted origin\\s*$/.test(message)) return 'originRejected'\n // pnpm 供应链安全策略拦截(缺少 tarball 校验值 / minimumReleaseAge 拒收「刚发布」的包 /\n // untrusted origin 来源不受信任):pnpm 在、也连得上,纯粹是本机策略不放行 ——\n // 装任何「新发布/非信任来源」的插件都会同样失败。\n // 必须在 pnpmIgnoredBuild 之前 —— 该策略优先于「构建脚本被白名单拦截」,且两者都不引导提 Issue。\n if (missingTarballIntegrity(message) || /ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION|Minimum release age|untrusted origin/i.test(message)) return 'pnpmPolicy'\n // profile 里留着指向旧版本 dsh-plugin 的 patch 声明(ERR_PNPM_UNUSED_PATCH /\n // `The following patches were not used: dsh-plugin@1.4.2`):本机 pnpm 配置与本次解析到的版本\n // 对不上,pnpm 出于安全直接中止整次安装 —— 任何插件都装不进来 → 提示删条目后重试。\n // 必须在兜底之前,否则被归成「插件侧失败」引导去提 Issue。\n if (/ERR_PNPM_UNUSED_PATCH|patches were not used/i.test(message)) return 'pnpmUnusedPatch'\n // profile 里的文件被其他进程占用,pnpm 无法替换(Windows `os error 32`\n // 「另一个程序正在使用此文件,进程无法访问」/ EBUSY / resource busy or locked)——\n // 通常是宿主进程或杀毒软件实时扫描持有句柄;`os error 32` 用 ASCII 特征,中文原文乱码也能命中\n // → 提示完全退出宿主后重试\n if (/os error 32|EBUSY|resource busy or locked|being used by another process/i.test(message)) return 'fileLocked'\n // profile 里的文件/目录被系统拒绝写入(Windows `os error 5`「拒绝访问」= ERROR_ACCESS_DENIED /\n // Node 的 EPERM、EACCES / 英文 `Access is denied`):占用、只读属性、目录 ACL 或杀软拦截,\n // 任何插件都装不上。`os error 5` 只认 ASCII 特征 —— 中文原文经 GBK→UTF-8 解码会残缺,\n // 不能依赖「拒绝访问」四个字\n if (/os error 5\\b|ERROR_ACCESS_DENIED|\\bEPERM\\b|\\bEACCES\\b|access is denied/i.test(message)) return 'accessDenied'\n // 本机文件系统层面根本写不进去:空间耗尽(ENOSPC / no space left on device / Windows os error 112)、\n // 目标盘或挂载点只读(EROFS / read-only file system / Windows 写保护 os error 19)、\n // 文件句柄耗尽(EMFILE / ENFILE / too many open files)。都在 pnpm 落盘阶段发生,\n // 空间不足、盘只读或句柄不够时任何插件都装不进来,不是插件问题 ——\n // 必须在 network / prepare 之前判:磁盘满时 pnpm 会在日志尾部混着重试与超时特征,\n // 先判网络会把「本机磁盘写不进去」误报成「你的网络不通」\n if (/os error 112\\b|os error 19\\b|ERROR_DISK_FULL|ERROR_WRITE_PROTECT|\\bENOSPC\\b|\\bEROFS\\b|\\bEMFILE\\b|\\bENFILE\\b|no space left on device|read-only file system|too many open files/i.test(message)) return 'fsUnavailable'\n // 构建脚本被 pnpm 白名单(allowBuilds)拦截:插件的 prepare 脚本或依赖里的原生模块构建\n // 被默认拒绝(ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED / ERR_PNPM_IGNORED_BUILDS)。\n // 这类错误出现即说明 pnpm 已成功 fetch 到 tarball(网络是通的),主因是插件构建脚本\n // 被拦 —— 必须在 network 判定之前:日志尾部常混着重试残留的连接失败特征\n // (ETIMEDOUT / Failed to connect 等),若先判网络会把「插件分发问题」误报成「你的网络不通」。\n if (/ERR_PNPM_IGNORED_BUILDS|Ignored build scripts:|ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED/i.test(message)) return 'pnpmIgnoredBuild'\n // 网络问题(服务端 [network] 标记,或安装日志里的连接失败特征:git fetch 失败、\n // 连接超时/拒绝/重置、DNS 解析失败、TLS/SSL 握手失败,或 registry tarball 拉取失败\n // —— `fetch failed` / `GET https://…/-/…tgz error (n)` 是 pnpm 下载包文件时的网络层失败,\n // 常见于本机 npm/pnpm registry 被指向内网/自定义源而取不到包)—— 是本机网络/代理/源\n // 配置问题,不是插件问题。必须在 prepare/Command failed 判定之前:git fetch 失败常被\n // 外层包成 \"Command failed: git fetch ...\",先按网络特征归类才不会误判成插件问题。\n // 404 类「目标不存在」不含这些特征,仍归 repo(那是仓库/包的问题)。\n // 注意:fetch failed 只在 pnpm 拉取阶段出现;prepare/构建已跑起来(tarball 到手)的\n // 插件问题不带此特征,不会误伤(allowBuilds 拦截在上一分支先判)。\n // `Failed to fetch` 是浏览器 fetch 的 TypeError(词序与 Node 的 fetch failed 相反):界面\n // 请求根本没送达宿主服务(宿主未就绪/正在重启、本地代理拦了回环地址)。\n if (/\\[network\\]|ERR_PNPM_GIT_FETCH_FAILED|ETIMEDOUT|ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN|EPIPE|EHOSTUNREACH|ENETUNREACH|getaddrinfo|Could not connect|Could not resolve host|Network unreachable|Failed to connect|socket hang up|CERT_HAS_EXPIRED|SSL certificate problem|\\bTLS\\b|\\bSSL\\b|fetch failed|failed to fetch|\\bGET https?:\\/\\/\\S+\\.tgz\\s+error \\(\\d+\\)/i.test(message)) return 'network'\n // 装后校验拦截(服务端 verifyInstalledEntry 标记):入口文件缺失 = git 分发缺构建产物,\n // 与 pluginPrepare 同类(插件打包/分发问题),引导去仓库提 Issue\n if (/\\[packaging\\]|entry file missing/i.test(message)) return 'pluginPrepare'\n // 依赖在 registry 上不存在(`ERR_PNPM_FETCH_404` / `Not Found - 404`):pnpm 连得上 registry,\n // 是被明确告知「这个包不存在」—— 属于 profile 的本地依赖问题,不是插件问题。profile 里留着\n // 一条指向未发布包的依赖条目时,该 profile 的**任何**安装都会先卡在这条依赖上。\n // 必须在 pluginPrepare 之前判定:此时宿主尾部只有通用的 `dsh: plugin command failed`,\n // 落到下面会被当成构建失败。\n // (两个形态:pnpm 的 `[ERR_PNPM_FETCH_404] GET <url>: Not Found - 404` 与 npm 的\n // `npm error 404 Not Found - GET <url> - Not found`)\n if (/ERR_PNPM_FETCH_404|404 Not Found|Not Found - 404/i.test(message)) return 'pnpmMissingDep'\n // 再判 prepare 实际执行失败:只有构建脚本真的跑挂了才是插件问题。\n // `Command failed` 区分大小写 —— 只匹配 pnpm 包装出的报错,不匹配宿主那句小写的\n // `dsh: plugin command failed`(那只是「这条命令失败了」的通用说明)。\n if (/ERR_PNPM_PREPARE_PACKAGE|ELIFECYCLE|prepare-guard/i.test(message) || /Command failed/.test(message)) return 'pluginPrepare'\n // 其余失败(含 git prepare 被 pnpm 白名单拦截):当前通道装不上 = 插件分发/依赖的问题,一律提 Issue\n return 'repo'\n}\n\n/** 从服务端 `[npm-too-low]` 标记行提取本机 npm 版本(如 `[npm-too-low] npm@11.3.0` → \"11.3.0\");\n * 历史记录无标记时返回 null,前端据此决定提示文案是否带具体版本。 */\nexport function npmTooLowVersion(message: string): string | null {\n const m = message.match(/\\[npm-too-low\\]\\s*npm@(\\d+\\.\\d+\\.\\d+)/i)\n return m ? m[1] : null\n}\n\n/** 核心行特征:错误代码 / 生命周期脚本失败 / prepare 失败 / 描述性报错(子模块缺失、找不到等)/ 退出与宿主提示信息。 */\nconst CORE_LINE_RE = /ERR_[A-Z_]+|ELIFECYCLE|Command failed|prepare-guard|Failed to prepare|exit code|\\bprepare\\b|pnpm failed in profile|git-hosted plugins build|submodule|not found|cannot find|no such|unable to|fatal|missing|error/i\n/** pnpm 的 peer 依赖告警行(`missing peer …` / `Issues with peer dependencies found` /\n * `Peer dependencies that should be installed`):宿主提供的 peer(@deepseek-ai/*、react、\n * dsh-client-* 等,DSH profile 用 autoInstallPeers:false 不自动装)缺失是无害噪音,与插件本身\n * 无关 —— 抓核心错误时必须跳过,否则会被 CORE_LINE_RE 的 `missing` 分支误抓、淹没真正的\n * 错误码(如 git 源的 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED),让 issue 正文只剩一堆 peer WARN。 */\nconst PEER_WARN_RE = /missing peer|issues with peer dependencies|peer dependencies that should be installed/i\n/** 提交 issue 时正文里错误摘要的上限字符数。GitHub 请求行上限 8192 字节,\n * 固定模板与 URL 编码开销约 1~2K,核心错误(以 ASCII 日志为主)可安全带到 ~5K;\n * 仍超长时 pluginIssueUrl 会逐档缩小核心预算,最终 URL 不会超限。 */\nexport const MAX_CORE_CHARS = 5000\n/** 摘要里单行上限:允许构建 key 等长行也被截短。 */\nconst MAX_LINE_CHARS = 400\n\n/**\n * 核心错误收集器:从完整安装输出里挑出真正说明问题的行(错误代码、构建脚本失败、\n * 退出与宿主提示),去重后拼接,单行与总量都截断 —— 只把「重点 + 原因」带进 issue 正文,\n * 避免完整日志塞进 URL 导致请求过长。无关键行时退化为「头部 + 尾部」快照。\n * maxChars 可由调用方按最终 URL 长度收紧(pluginIssueUrl 超限时逐档缩小)。\n */\nexport function summarizeError(message: string, maxChars: number = MAX_CORE_CHARS): string {\n const seen = new Set<string>()\n const core: string[] = []\n for (const raw of message.split(/\\r?\\n/)) {\n const line = raw.trim()\n if (!line || PEER_WARN_RE.test(line) || !CORE_LINE_RE.test(line)) continue\n const short = line.length > MAX_LINE_CHARS ? `${line.slice(0, MAX_LINE_CHARS)}…` : line\n if (!seen.has(short)) {\n seen.add(short)\n core.push(short)\n }\n }\n let out: string\n if (core.length === 0) {\n // 无关键行时退化为「头部 + 尾部」快照:优先保尾部完整,头部按预算压缩,总长不超上限\n const tail = message.trimEnd().slice(-1000)\n const sep = '\\n…\\n'\n const headBudget = Math.max(maxChars - tail.length - sep.length, 0)\n const head = message.slice(0, 500).trim()\n out = `${head.length > headBudget ? head.slice(0, headBudget) : head}${sep}${tail}`\n } else {\n out = core.join('\\n')\n }\n return out.length > maxChars ? `${out.slice(0, maxChars)}\\n… (truncated)` : out\n}\n\n/** 提取首个错误代码(如 ERR_PNPM_PREPARE_PACKAGE),无则 null。\n * 代码里可能含数字(ERR_PNPM_FETCH_404 / ERR_PNPM_EBADPLATFORM_...),字符类需带上 0-9,\n * 否则会被截断成 `ERR_PNPM_FETCH_`。 */\nexport function coreErrorCode(message: string): string | null {\n const m = message.match(/\\[?ERR_[A-Z0-9_]+\\]?/)\n return m ? m[0].replace(/^\\[|\\]$/g, '') : null\n}\n\n/** 提取「registry 上不存在的包名」:从 404 行(`ERR_PNPM_FETCH_404 GET <registry>/<pkg>: Not Found - 404`)\n * 里取请求路径中的包名(含 scope,如 `@scope/name`);非 404 或提取不到返回 null。 */\nexport function missingRegistryPackageOf(message: string): string | null {\n for (const line of message.split(/\\r?\\n/)) {\n if (!/ERR_PNPM_FETCH_404|404/.test(line)) continue\n const m = line.match(/GET\\s+https?:\\/\\/[^\\s/]+\\/((?:@[^/\\s:]+\\/)?[^/\\s:]+)/)\n if (m) return m[1]\n }\n return null\n}\n\n/**\n * 从网络类失败消息里提取「具体连不上的地址」,供弹窗精准提示(你的网络无法访问什么)。\n * 优先取服务端 [network] 预检消息括号里的探测地址(中文「(…)」/ 英文「(…)」),\n * 否则取消息里出现的第一个 URL(git fetch 的仓库地址、registry 域名等)。\n * 提取不到返回 null —— 调用方据此跳过地址行。\n */\nexport function unreachableTargetOf(message: string): string | null {\n // [network] 预检消息:`无法连接到 GitHub(https://github.com/)` / `cannot reach the npm registry (https://registry.npmjs.org/)`\n const paren = message.match(/[((](https?:\\/\\/[^\\s'\"`<>()+]+)[))]/)\n if (paren) return paren[1]\n // 其余网络失败(git fetch / npm 连接失败):取第一个 URL,去掉行尾标点\n const url = message.match(/https?:\\/\\/[^\\s'\"`<>()()]+/)\n return url ? url[0].replace(/[.,;:))\\]]+$/, '') : null\n}\n\n/** npm registry 的官方/常见公开镜像主机名:tarball 从这里下载属正常配置,\n * 失败按「网络不通」提示即可,不需要额外的换源指引。 */\nconst PUBLIC_REGISTRY_HOSTS = new Set([\n 'registry.npmjs.org',\n 'registry.yarnpkg.com',\n 'registry.npmmirror.com',\n 'mirrors.cloud.tencent.com',\n 'mirrors.huaweicloud.com',\n])\n\n/**\n * 网络类失败消息里,判断是否「npm/pnpm 的 registry 被指向了内网/自定义源导致拉包失败」。\n * pnpm 下载包文件的 URL 形如 `<registry>/<pkg>/-/<pkg>-<ver>.tgz`(路径含 `/-/`);\n * 若该 tarball 的主机不属于官方/常见公开镜像,说明本机 registry 被配成了私有/内网源\n * (如公司 Artifactory)—— 常因源未同步该包、需内网认证或网络策略拦截而失败。\n * 返回该主机名供前端给出「检查 registry 配置」的精准提示;官方/公开源或提取不到返回 null,\n * 调用方按通用网络问题提示即可。\n */\nexport function registryHostOf(message: string): string | null {\n const m = message.match(/https?:\\/\\/([^/\\s]+)\\/[^\\s'\"`<>]*\\/-\\/[^\\s'\"`<>]+/)\n if (!m) return null\n const host = m[1].replace(/:\\d+$/, '')\n return PUBLIC_REGISTRY_HOSTS.has(host) ? null : host\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * URL builders: catalog detail pages, plugin site links and the pre-filled\n * GitHub issue URL used by the failure modal. Pure functions — the issue\n * URL stays within GitHub's 8192-byte request limit.\n */\nimport type { EnvInfo, HubPlugin, LocaleId } from '../types.ts'\nimport { GITHUB_URL, PLUGIN_VERSION, SITE_URL } from './constants.ts'\nimport { MAX_CORE_CHARS, classifyFailure, coreErrorCode, pnpmPolicyHintOf, summarizeError } from './failures.ts'\nimport { executedCommandOf } from './install-command.ts'\nimport type { FailureKind } from './failures.ts'\n\n/** dsh-plugin.org 中文页挂在 /zh/ 前缀下,英文在根路径。 */\nexport function langPathOf(lang: LocaleId): string {\n return lang === 'zh' ? 'zh/' : ''\n}\n\n/** 官网链接统一携带 `?ref=hub` 来源参数:统计有多少访问是从插件商城跳转而来。\n * 所有「从商城跳官网」的链接(详情页/首页)都应经由此函数拼接,避免来源参数散落各处。 */\nexport function siteUrl(path: string): string {\n return `${SITE_URL}${path}?ref=hub`\n}\n\n/**\n * 官网详情页两级路径:/plugins/{ownerSlug}/{slug};\n * 缺 ownerSlug 时从 repo 推导(卡片详情按钮与弹窗来源行共用)。\n */\nexport function pluginDetailUrl(plugin: HubPlugin, langPath: string): string {\n const repo = plugin.source?.repo ?? ''\n return siteUrl(`${langPath}plugins/${plugin.ownerSlug ?? repo.split('/')[0]?.toLowerCase() ?? ''}/${plugin.slug}`)\n}\n\n/**\n * 失败弹窗里仓库地址的跳转目标:官网详情页(含插件收录信息),\n * 与 issue 正文的 Catalog 链接同一形式(单级 /plugins/{repo})。\n */\nexport function pluginSiteUrl(repo: string): string {\n return siteUrl(`plugins/${repo}`)\n}\n\n/** 按失败类型给出简洁的错误原因标题(对外用英文):\n * 标题直接点明问题出在哪一侧(构建白名单/分发物/本机 npm/网络/插件侧),\n * 让作者与用户扫一眼列表就能分流,而不是笼统的 Install/Remove 动作词。 */\nfunction reasonTitleOf(kind: FailureKind): string {\n switch (kind) {\n case 'npmTooOld': return 'npm too old to install'\n case 'dshMissing': return 'dsh command not found on the user machine'\n case 'pnpmMissing': return 'pnpm command not found on the user machine'\n case 'pnpmStore': return 'pnpm store version mismatch on the user machine'\n case 'pnpmWorkspace': return 'pnpm workspace-root check blocked the install on the user machine'\n case 'originRejected': return 'request origin rejected by the local service on the user machine'\n case 'pnpmPolicy': return 'pnpm supply-chain policy blocked the install on the user machine'\n case 'pnpmUnusedPatch': return 'stale pnpm patch entry on the user machine'\n case 'pnpmMissingDep': return 'dependency not found on the npm registry on the user machine'\n case 'fileLocked': return 'file locked by another process on the user machine'\n case 'accessDenied': return 'file write access denied on the user machine'\n case 'fsUnavailable': return 'local file system unavailable on the user machine'\n case 'pnpmIgnoredBuild': return 'build scripts blocked by pnpm allowlist'\n case 'pluginPrepare': return 'plugin distribution incomplete'\n case 'network': return 'network failure on the user side'\n default: return 'plugin install failed'\n }\n}\n\n/**\n * 一键反馈 GitHub Issue 的预填链接:标题带「来自 dsh-plugin.org」标识 + 错误原因,\n * 正文只带核心信息 —— 原因判定 + 关键错误代码 + 尝试过的安装方式 + 宿主机器环境快照 +\n * 错误核心摘要(完整日志太长,塞进 URL 会被 GitHub 以「request URL too long」拒绝,\n * 故只收集重点)。错误弹窗、失败记录共用此逻辑。\n * env 取不到时为 null,链接照常生成、只是少环境段。\n * attempts(尝试过的安装方式,npm 反查 + 实际执行命令):作者看到我们查过/试过的命令,\n * 组织 scope 与 GitHub 用户名不一致时也能直接指认正确的 npm 包名。\n */\nexport function pluginIssueUrl(repo: string, message: string, env?: EnvInfo | null, command?: string, attempts?: string[]): string {\n // 原因判定:按失败类型归类,便于作者判断问题是否出在插件侧。\n // [packaging](预检/装后校验拦截)单独列:无论走 npm 还是 git 通道,都是分发物不完整\n // (package.json 声明的入口文件在发布物里缺失),作者照此补齐即可。\n const kind = classifyFailure(message)\n const executed = executedCommandOf(command, attempts)\n // 标题 = 错误原因(非动作词),让 issue 列表一眼可分流\n const title = `[dsh-plugin.org | dsh-plugin-hub] ${reasonTitleOf(kind)}: ${repo}`\n const reason = /\\[packaging\\]/i.test(message)\n ? 'plugin distribution is incomplete — the entry file declared in package.json is missing from the published package (github tarball or npm package); please commit build output or publish a complete package'\n : kind === 'network'\n ? 'network connectivity issue on the user side (DNS, proxy, firewall, or a blocked connection)'\n : kind === 'pluginPrepare'\n ? 'plugin prepare/build script failed during install (packaging/distribution issue)'\n : kind === 'pnpmIgnoredBuild'\n ? 'plugin depends on a native module whose build script pnpm blocks by default (use a prebuilt variant)'\n : kind === 'originRejected'\n ? 'the request never reached the install flow — the local service rejected its origin (local environment issue)'\n : kind === 'pnpmPolicy'\n ? pnpmPolicyHintOf(message) === 'failPnpmTarballIntegrityHint'\n ? 'pnpm rejected a lockfile entry without tarball integrity; inspect and back up the profile lockfile before resolving it again, keeping integrity checks enabled'\n : 'the pnpm supply-chain policy on the user machine blocked the install (minimum release age for freshly published packages / untrusted origin)'\n : kind === 'pnpmUnusedPatch'\n ? 'the profile keeps a pnpm patch entry for an older dsh-plugin version, so pnpm aborted the install (local config issue)'\n : kind === 'fileLocked'\n ? 'a file in the profile is locked by another process on the user machine (local environment issue)'\n : kind === 'accessDenied'\n ? 'the system denied write access to a file in the profile on the user machine (local environment issue)'\n : kind === 'fsUnavailable'\n ? 'the local file system could not accept the write — no space left, read-only volume, or too many open file handles on the user machine (local environment issue)'\n : 'plugin-side install failure'\n const code = coreErrorCode(message)\n // 按给定核心摘要预算构建完整预填 URL(含 URL 编码);预算可调,供超长时逐档缩小\n const build = (coreChars: number): string => {\n const body = [\n '## Summary',\n `- Cause: ${reason}`,\n ...(code ? [`- Key error: \\`${code}\\``] : []),\n '',\n // 来源说明:标题(链官网)+ 一句来源(链仓库)+ 实际执行的安装命令(含 --profile)与执行结果,链接由常量动态拼接\n `## [DSH Plugin 插件市场](${SITE_URL}) · 安装 Plugin 失败错误信息`,\n `本错误信息由 [dsh-plugin-hub](${GITHUB_URL}) 插件市场的安装程序自动生成,随本次安装失败一并提交。`,\n `- 实际执行的安装命令:${executed ? `\\`${executed}\\`` : 'unknown (no executed command recorded)'}`,\n `- 执行结果:安装失败,未能安装该插件。`,\n // 尝试过的安装方式(npm 反查 + 实际执行命令,按先后顺序):作者据此反推正确的\n // npm 包名 —— 组织 scope 与 GitHub 用户名不一致时仅凭仓库名猜不到,作者看到我们\n // 查过/试过的命令就能直接指认\n ...(attempts && attempts.length > 0\n ? ['', '## Attempted install channels(已尝试的安装方式)', ...attempts.map((a) => `- ${a}`)]\n : []),\n // [packaging] 场景:说明两种官方安装通道(npm 包 / git 直装),当前插件在对应通道下分发不完整\n ...(/\\[packaging\\]/i.test(message)\n ? [\n '',\n '## 安装方式说明',\n 'DSH 插件支持两种官方安装通道:`dsh plugin add <npm-package>`(npm 分发,需发布完整构建产物)与 `dsh plugin add git+https://github.com/owner/repo.git`(Git 直装,仓库需提交构建产物或在 package.json 提供 `prepare` 脚本)。当前插件的分发物缺少 package.json 声明的入口文件,请按所用通道补齐后重新发布。',\n ]\n : []),\n '',\n '## Environment',\n `- Plugin: \\`${repo}\\``,\n // 宿主机器环境快照:便于作者本地复现;某字段缺失时如实写 unknown,不编造\n ...(env\n ? [\n `- DSH: ${env.dshVersion ? `v${env.dshVersion}` : 'unknown'}`,\n `- Plugin Hub: v${PLUGIN_VERSION}`,\n `- Node: ${env.nodeVersion}`,\n // 工具链版本:pnpm/npm/git —— 排查 ERR_PNPM_UNEXPECTED_STORE(store 大版本不匹配)\n // 这类环境问题,作者一眼就能对号入座;探测不到如实写 unknown\n `- pnpm: ${env.pnpmVersion ? `v${env.pnpmVersion}` : 'unknown'}`,\n `- npm: ${env.npmVersion ? `v${env.npmVersion}` : 'unknown'}`,\n `- git: ${env.gitVersion ? `v${env.gitVersion}` : 'unknown'}`,\n `- OS: ${env.platform} ${env.arch} (${env.release})`,\n `- Profile: \\`${env.profile}\\``,\n `- DSH Home: \\`${env.dshHome}\\``,\n // 完整安装日志所在(正文受 URL 长度限制只能带摘要,完整日志在 hub.log,可复制/附加给作者)\n `- Full log: \\`~/.dsh/profiles/${env.profile}/hub.log\\` (paste or attach for the full output)`,\n ]\n : []),\n // 该插件在插件市场的收录位置(详情页链接)\n `- Catalog: [${pluginSiteUrl(repo)}](${pluginSiteUrl(repo)})`,\n '',\n '## Error (core)',\n '',\n '```',\n // 核心错误收集器:只挑关键行(错误代码/构建失败/退出信息),去重截断,URL 才不至于超长\n summarizeError(message, coreChars),\n '```',\n '',\n '---',\n // 底部署名:报错来自内置在 DeepSeek Harness 里的 dsh-plugin-hub 安装程序\n `This error was produced by the [dsh-plugin-hub](${GITHUB_URL}) installer bundled with DeepSeek Harness.`,\n ].join('\\n')\n return `https://github.com/${repo}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`\n }\n // GitHub 请求行上限 8192 字节:先用宽松预算(最多 ~5K 核心错误)构建,超长再逐档缩小,保证最终 URL 不超限\n const MAX_URL_CHARS = 7600\n let url = build(MAX_CORE_CHARS)\n if (url.length > MAX_URL_CHARS) {\n for (const budget of [4000, 2500, 1400, 800, 400]) {\n url = build(budget)\n if (url.length <= MAX_URL_CHARS) break\n }\n }\n return url\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Language state for the section: the Hub shares the host (system) locale —\n * the header language toggle writes the host locale preference via setLocale,\n * so the host chrome (left sidebar, settings dialog) and the Hub panel switch\n * together instead of drifting apart. Exposes the localized dictionary lookup\n * `t()` plus the zh/en language flag and the /zh/ URL path prefix.\n */\nimport { useEffect, useState } from 'react'\nimport type { LocaleId, SectionProps } from '../types.ts'\nimport { en, zh } from '../locales.ts'\nimport { langPathOf } from '../logic/urls.ts'\n\nexport function useLanguage(locale: SectionProps['locale']) {\n // 界面语言 = 宿主(系统)语言:右上角按钮切换时直接写入宿主 locale 偏好,\n // 宿主左侧菜单/设置弹窗与 Hub 面板一起切换,不存在 Hub 内部语言与宿主语言脱节的情况。\n // subscribe 订阅宿主语言变化并触发重渲染,保证 Hub 界面随时跟随宿主。\n const [, setRev] = useState(0)\n useEffect(() => locale.subscribe(() => setRev((r) => r + 1)), [locale])\n const lang: LocaleId = locale.getSnapshot().active\n const langKey: LocaleId = lang === 'en' ? 'en' : 'zh'\n // dsh-plugin.org keeps zh pages under the /zh/ prefix; en is the root.\n const langPath = langPathOf(lang)\n\n // 界面语言跟随宿主(系统)locale;宿主的 t() 绑定宿主 locale,\n // 这里基于本地字典自建翻译函数,与宿主 locale 保持一致。\n // (settings.section 的导航 label 仍在 apply 里用宿主 t(),跟随宿主语言。)\n const dict: Record<string, string> = langKey === 'en' ? en : zh\n const t = (key: string, params?: Record<string, string | number>): string => {\n const raw = dict[key] ?? key\n return params ? raw.replace(/\\{(\\w+)\\}/g, (_, k) => String(params[k] ?? '')) : raw\n }\n\n return {\n lang,\n langKey,\n langPath,\n t,\n toggleLang: () => locale.setLocale(lang === 'en' ? 'zh' : 'en'),\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Hub settings state: loaded once from the host's local /settings route\n * (persisted at ~/.dsh/profiles/<profile>/hub-settings.json), updated\n * optimistically. Every change POSTs the patch immediately so a toggled\n * switch survives a reload; a host without the server routes falls back to\n * the defaults and keeps working (settings simply do not persist).\n */\nimport { useCallback, useEffect, useState } from 'react'\n\nexport interface HubSettings {\n /** 启动时检查目录插件更新,发现可更新时在通知中心提示(安装不自动进行) */\n checkUpdatesOnStart: boolean\n /** HTTP(S) 代理地址,用于 npm / git / 目录请求(空串 = 直连) */\n proxy: string\n /** npm 镜像源 registry 地址(空串 = 未配置,跟随用户本机 npm 配置,不注入任何 registry) */\n npmRegistry: string\n /** 启用命令行安装 NPM 包(默认开) */\n enableNpmInstall: boolean\n /** 启用命令行安装 GitHub 源码(默认开) */\n enableGitInstall: boolean\n /** 启用命令行粘贴 dsh plugin 命令安装(默认开) */\n enableDshInstall: boolean\n /** 日志存放位置覆盖(空串 = 默认 ~/.dsh/profiles/<profile>/hub.log) */\n logPath: string\n}\n\nexport const DEFAULT_SETTINGS: HubSettings = {\n checkUpdatesOnStart: true,\n proxy: '',\n npmRegistry: '',\n enableNpmInstall: true,\n enableGitInstall: true,\n enableDshInstall: true,\n logPath: '',\n}\n\nasync function loadRemote(): Promise<HubSettings> {\n try {\n const res = await fetch('/dsh-plugin-hub/settings', { cache: 'no-store' })\n if (!res.ok) throw new Error(`settings ${res.status}`)\n const data = await res.json() as Partial<HubSettings>\n return { ...DEFAULT_SETTINGS, ...data }\n } catch {\n return DEFAULT_SETTINGS\n }\n}\n\nexport function useSettings() {\n const [settings, setSettings] = useState<HubSettings>(DEFAULT_SETTINGS)\n /** 服务端配置是否已加载:更新策略等启动期逻辑须等真实值,避免用默认值误触发 */\n const [ready, setReady] = useState(false)\n\n useEffect(() => {\n let alive = true\n void loadRemote().then((s) => {\n if (!alive) return\n setSettings(s)\n setReady(true)\n })\n return () => { alive = false }\n }, [])\n\n /** 部分更新:本地立即生效(乐观),同时 POST 持久化;持久化失败静默(本次会话仍生效)。 */\n const update = useCallback((patch: Partial<HubSettings>) => {\n setSettings((prev) => ({ ...prev, ...patch }))\n void fetch('/dsh-plugin-hub/settings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch),\n cache: 'no-store',\n }).catch(() => { /* 宿主未挂路由:仅本次会话生效 */ })\n }, [])\n\n /** 重置为默认设置:本地立即回默认,同时通知服务端删除设置文件;失败静默。 */\n const reset = useCallback(() => {\n setSettings({ ...DEFAULT_SETTINGS })\n void fetch('/dsh-plugin-hub/settings/reset', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: '{}',\n cache: 'no-store',\n }).catch(() => { /* 宿主未挂路由:仅本次会话回默认 */ })\n }, [])\n\n return { settings, ready, update, reset }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Background install/remove task queue for the Plugin Hub.\n *\n * Mirrors the server-side FIFO active queue by polling /active, settles\n * vanished tasks against /status, and exposes the queue actions (install,\n * uninstall, cancel) plus the modal task lookups used by the dialogs.\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { HubPlugin, InstallChannel, LocaleId, Translate } from '../types.ts'\nimport { executedCommandOf, installCommandOf, installTargetOf, repoFromInstallTarget } from '../logic/install-command.ts'\nimport type { InstalledItem } from '../logic/installed.ts'\n\n/** 安装/卸载请求超时(ms):服务端 preflight + npm 反查可能耗时(各自都有超时,合计约 20~30s),\n * 给足余量;超时主动中止,避免服务端 preflight 网络挂起时前端永久卡「安装中 0%」。 */\nconst REQUEST_TIMEOUT_MS = 60_000\n\n/** 客户端任务队列项:镜像服务端 active 任务(running 在前、pending 在后)。 */\nexport interface QueueTask {\n id: number\n kind: 'install' | 'uninstall'\n /** 展示目标:owner/repo(安装)或 npm 包名(卸载) */\n target: string\n /** 插件中文简介(入队时从插件数据带过来,轮询合并时保留):展示在仓库名下方,标识排队中的插件 */\n desc?: string\n /** 所属插件仓库(owner/repo):失败时错误弹窗据此提供「去仓库反馈」入口;卸载为 null */\n repo: string | null\n /** 自定义安装入口渠道(NPM 包 / GitHub 源码 / DSH 命令三张卡片):失败时错误/通知精准\n * 溯源「从哪个入口发起」;目录插件安装无此字段(非自定义入口)。 */\n channel?: InstallChannel\n /** 实际动作(add/update/remove):成功通知据此区分「安装成功」与「更新成功」。\n * 服务端 /active 带回真实动作;本地乐观入队按 update 标记推断。 */\n action?: 'add' | 'update' | 'remove'\n /** 安装时的目录信号快照(版本 + 仓库更新时间):任务成功后在本地记录,供「有更新」比对 */\n version?: string\n updatedAt?: string\n /** pending 排队中 / running 执行中 / cancelling 取消中(客户端乐观过渡态) */\n status: 'pending' | 'running' | 'cancelling'\n progress: number\n lines: string[]\n /** 乐观入队条目:点击安装后立即显示「正在安装中」,等 POST 响应回来再换成真实任务 id。\n * 服务端还没登记(preflight 中),轮询合并/消失检测都必须跳过,避免被当作已结束任务收尾。 */\n optimistic?: boolean\n /** 实际执行的安装命令(npm/git 通道随插件数据决定):失败时 issue 预填如实展示 */\n command?: string\n /** 尝试过的安装方式(npm registry 反查 + 实际执行命令,按先后顺序):失败时 issue 预填一并贴给作者 */\n attempts?: string[]\n /** 完成结果是否需要重启才生效(服务端任务终态带出;默认 true 保持老行为:弹窗给重启选项)。\n * 卸载时 loader 已即时移除 → false,结果视图只显示「完成」;true 时弹窗给「稍后重启/立即重启」,\n * 通知中心待重启条目(服务端登记)同步常驻,直到用户点「立即重启」。 */\n needsRestart: boolean\n}\n\n/** 客户端待重启项:镜像服务端内存列表 + 本地补齐的展示信息(简介/版本)。 */\nexport interface PendingRestart {\n /** owner/repo(展示用,已从安装目标归一化) */\n target: string\n /** 待重启语义:install 装完等挂载 / uninstall 卸完等清理 */\n kind: 'install' | 'uninstall'\n at: number\n desc?: string\n version?: string\n}\n\nexport interface TaskQueueOptions {\n t: Translate\n /** 界面语言(zh/en):随安装请求带给服务端,网络预检等错误消息按用户语言提示 */\n langKey?: LocaleId\n refreshInstalled: () => void\n /** 任务成功完成:viaModal 表示任务对应当前打开弹窗(弹窗切结果视图),否则走 Toast;repo 供成功通知记录;\n * needsRestart 表示该任务完成后是否仍需宿主重启(结果视图据此给「重启 / 仅完成」)。\n * update 表示实际执行的是更新(覆盖重装)而非首次安装:通知中心据此显示「更新成功」而非「安装成功」。 */\n onInstallDone: (viaModal: boolean, repo: string | null, needsRestart: boolean, update?: boolean) => void\n onUninstallDone: (viaModal: boolean, repo: string | null, needsRestart: boolean) => void\n /** 任务失败:完整输出或兜底文案 + 所属插件仓库 + 操作类型(安装/卸载)+ 实际执行的安装命令(issue 预填用,可缺省)+ 尝试过的安装方式(npm 反查/执行命令,可缺省)+ 是否更新。 */\n onError: (message: string, repo: string | null, kind: 'install' | 'uninstall', command?: string, attempts?: string[], update?: boolean) => void\n /** 当前打开的安装/卸载弹窗插件:用于在弹窗内匹配进行中的任务。 */\n installPlugin: HubPlugin | null\n /** 当前打开的自定义安装(命令行)确认弹窗目标:与应用商店同一弹窗机制,匹配进行中的 custom 安装任务。 */\n installCustomTarget?: string | null\n /** 当前打开的全局 npm 安装(`npm install -g <pkgs>`)确认弹窗身份(包列表空格拼接):\n * 匹配服务端登记的全局安装任务(target = 包列表 join(' '))。 */\n installGlobalTarget?: string | null\n uninstallPlugin: HubPlugin | null\n /** 已安装视图发起的卸载目标(npm 包名):目录插件走 uninstallPlugin,自定义安装走包名直卸。 */\n uninstallName: string | null\n installedName: (p: HubPlugin) => string | null\n /** 待重启项展示信息补齐:按 owner/repo 从插件目录解析简介/版本;找不到返回 null。 */\n resolvePending: (repo: string) => { desc?: string; version?: string } | null\n}\n\n/** 入口渠道的 i18n key:NPM 包 / GitHub 源码 / DSH 命令。 */\nconst channelKeyOf = (channel: InstallChannel): string =>\n channel === 'git' ? 'installChannelGit' : channel === 'dsh' ? 'installChannelDsh' : 'installChannelNpm'\n\n/** 失败消息的入口溯源前缀:自定义安装(带渠道)在错误正文顶部精准指出从哪张卡片发起;\n * 目录插件安装(无渠道)返回 null,错误正文保持原样。 */\nconst entryLineOf = (t: Translate, channel: InstallChannel | undefined): string | null =>\n channel ? t('installEntryLine', { c: t(channelKeyOf(channel)) }) : null\n\nexport function useTaskQueue(opts: TaskQueueOptions) {\n const {\n t, langKey, refreshInstalled, onInstallDone, onUninstallDone, onError,\n installPlugin, installCustomTarget, installGlobalTarget, uninstallPlugin, uninstallName, installedName, resolvePending,\n } = opts\n const [queue, setQueue] = useState<QueueTask[]>([])\n const queueRef = useRef<QueueTask[]>([])\n /** 待重启列表(服务端内存态 + 本地展示信息补齐);与 queue 一样以 ref 为唯一事实来源。 */\n const [pendingRestarts, setPendingRestarts] = useState<PendingRestart[]>([])\n const pendingRef = useRef<PendingRestart[]>([])\n /** 本次会话内安装成功插件的展示信息(目标 → 简介/版本):轮询合并待重启列表时补齐,刷新后由 resolvePending 兜底。 */\n const pendingInfoRef = useRef<Map<string, { desc?: string; version?: string }>>(new Map())\n /** 保持最新的 resolvePending:轮询闭包捕获的是调用那一刻的目录状态,目录晚加载时也能补齐。 */\n const resolvePendingRef = useRef(resolvePending)\n resolvePendingRef.current = resolvePending\n /** 当前打开弹窗所对应的任务 id:该任务完成时弹窗切换为结果视图 */\n const modalTaskRef = useRef<number | null>(null)\n /** 已开始收尾但尚未结束的任务 id(服务端 /active 已消失 → 查 /status 中):并发轮询时跳过,避免重复收尾 */\n const settlingRef = useRef<Set<number>>(new Set())\n /** 轮询定时器句柄(队列清空/组件卸载时清理) */\n const pollRef = useRef<number | null>(null)\n /** 请求在途的目标集合(同步防重):双击安装/卸载时第二击直接忽略。\n * 本地队列任务要等 fetch 返回后才入队,仅靠 queueRef 检查拦不住请求窗口内的重复点击。 */\n const submittingRef = useRef<Set<string>>(new Set())\n /** 乐观入队临时 id 计数器:递减产生唯一负数,与服务端自增正数 id 永不冲突。 */\n const tempIdRef = useRef(0)\n /** 请求在途标记:弹窗据此禁用确认按钮,避免等待响应期间被再次点击。 */\n const [submitting, setSubmitting] = useState(false)\n\n /** 停止后台任务轮询(任务结束或组件卸载时清理)。 */\n const stopPoll = () => {\n if (pollRef.current !== null) {\n window.clearInterval(pollRef.current)\n pollRef.current = null\n }\n }\n\n /** 队列与待重启都清空才停轮询:待重启期间持续轮询,宿主一重启(内存列表清空)立刻感知并消失。 */\n const maybeStopPoll = () => {\n if (queueRef.current.length === 0 && pendingRef.current.length === 0) stopPoll()\n }\n\n // 组件卸载时兜底清理轮询定时器\n useEffect(() => stopPoll, [])\n\n /** 更新队列(同步镜像到 ref:queueRef 是唯一事实来源,state 只负责触发渲染,\n * 避免依赖 React updater 的异步调度时序导致 gone/stopPoll/防重复入队读到旧值)。 */\n const applyQueue = (updater: (prev: QueueTask[]) => QueueTask[]) => {\n const next = updater(queueRef.current)\n queueRef.current = next\n setQueue(next)\n }\n\n /** 解析服务端待重启列表(安装目标归一化为 owner/repo,与安装任务对齐)。 */\n const parsePendingRestarts = (value: unknown): PendingRestart[] => {\n if (!Array.isArray(value)) return []\n const out: PendingRestart[] = []\n for (const x of value) {\n if (typeof x !== 'object' || x === null) continue\n const target = (x as { target?: unknown }).target\n if (typeof target !== 'string' || target === '') continue\n const at = (x as { at?: unknown }).at\n out.push({\n target: repoFromInstallTarget(target),\n kind: (x as { kind?: unknown }).kind === 'uninstall' ? 'uninstall' : 'install',\n at: typeof at === 'number' ? at : 0,\n })\n }\n return out\n }\n\n /** 合并服务端待重启列表:保留已有展示信息,缺失时用会话内记录 / 目录解析补齐。 */\n const applyPending = (raw: PendingRestart[]) => {\n const prev = pendingRef.current\n const next = raw.map((p) => {\n const old = prev.find((q) => q.target === p.target)\n if (old?.desc !== undefined) return { ...p, desc: old.desc, version: old.version }\n const info = pendingInfoRef.current.get(p.target) ?? resolvePendingRef.current?.(p.target) ?? null\n return info ? { ...p, desc: info.desc, version: info.version } : p\n })\n pendingRef.current = next\n setPendingRestarts(next)\n }\n\n /** 向宿主记录某插件的安装时目录信号(version + updatedAt);version 为空时清除记录(卸载)。 */\n const syncInstalledVersion = async (repo: string | null, version: string | undefined, updatedAt: string | undefined) => {\n if (!repo) return\n try {\n await fetch('/dsh-plugin-hub/installed-version', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ repo, version: version ?? null, updatedAt }),\n })\n } catch {\n // 宿主未挂本地路由:静默忽略,仅本机展示受影响\n }\n }\n\n /** 后台任务结束(active 中消失后查终态确认):完成 → 刷新安装表 + 结果视图/toast;失败 → 完整错误弹窗 */\n const finishQueueTask = (ok: boolean, q: QueueTask, lines: string[]) => {\n applyQueue((prev) => prev.filter((x) => x.id !== q.id))\n if (ok) {\n refreshInstalled()\n if (q.kind === 'uninstall') {\n // 卸载成功:清掉本地版本记录\n void syncInstalledVersion(q.repo, undefined, undefined)\n onUninstallDone(modalTaskRef.current === q.id, q.repo, q.needsRestart)\n } else {\n // 安装成功:记录安装时的目录信号(版本 + 仓库更新时间),供「有更新」比对;\n // 同时缓存展示信息,待重启列表(服务端已登记)合并时直接补齐简介/版本\n void syncInstalledVersion(q.repo, q.version, q.updatedAt)\n pendingInfoRef.current.set(q.target, { desc: q.desc, version: q.version })\n onInstallDone(modalTaskRef.current === q.id, q.repo, q.needsRestart, q.action === 'update')\n }\n } else {\n // 失败:完整展示全部输出行(最新在前,逆序为日志阅读顺序),不裁剪\n const rawDetail = lines.length > 0\n ? [...lines].reverse().join('\\n')\n : q.kind === 'uninstall' ? t('uninstallFail') : t('installFail')\n // 自定义安装(带入口渠道):错误正文顶部精准提示「从哪张卡片发起」,目录安装保持原样\n const entry = entryLineOf(t, q.channel)\n onError(entry ? `${entry}\\n${rawDetail}` : rawDetail, q.repo, q.kind, executedCommandOf(q.command, q.attempts), q.attempts, q.action === 'update')\n }\n maybeStopPoll()\n }\n\n /** 卸载成功收尾前的进度过渡:任务已在服务端结束,但保留本地展示,\n * 让进度条在 ~2.4s 内缓缓跑到 100% 再切结果/Toast,给用户一个交互过程,\n * 而不是命令一执行进度条就一闪消失。 */\n const settleDone = (q: QueueTask, lines: string[]) => {\n // 收尾动画期间停止轮询:任务已从服务端 /active 消失,无需再查;\n // 停掉可避免 pollQueue 的 gone 检测把它当「再消失一次」而重复收尾\n stopPoll()\n const from = Math.min(q.progress, 90) // 起点最多 90,给进度条留出跑满的缓冲空间\n const steps = 20\n const stepMs = 120 // 20 步 × 120ms = 2.4s\n let step = 0\n // 动画期间固定显示「卸载中」:任务实已结束,但进度在跑,与「排队中」文案更协调\n applyQueue((prev) => prev.map((x) => (x.id === q.id ? { ...x, status: 'running' as const } : x)))\n const timer = window.setInterval(() => {\n step += 1\n const progress = Math.round(from + (100 - from) * (step / steps))\n applyQueue((prev) => prev.map((x) => (x.id === q.id ? { ...x, progress } : x)))\n if (step >= steps) {\n window.clearInterval(timer)\n finishQueueTask(true, q, lines)\n // 队列若还有其它已在排队/执行的任务,恢复轮询继续盯;已清空则自然停住\n if (queueRef.current.length > 0) pollQueue()\n }\n }, stepMs)\n }\n\n /** 任务在 /active 中消失 = 已结束:查 /status 拿终态并收尾(cancelled 静默移除)。 */\n const settleTask = async (q: QueueTask) => {\n let status = 'failed'\n let lines: string[] = []\n let attempts: string[] | undefined\n try {\n const res = await fetch(`/dsh-plugin-hub/status?task=${q.id}`, { cache: 'no-store' })\n if (res.ok) {\n const data = await res.json() as { task?: { status?: string; lines?: string[]; attempts?: string[]; needsRestart?: unknown } }\n const task = data.task\n if (task !== undefined) {\n status = task.status ?? 'failed'\n lines = task.lines ?? []\n attempts = Array.isArray(task.attempts) ? task.attempts : undefined\n // 终态带出的「是否需要重启」覆盖本地(服务端 done 时按 loader 即时移除情况设置)\n const needsRestart = typeof task.needsRestart === 'boolean' ? task.needsRestart : q.needsRestart\n if (status === 'done') {\n const settled = { ...q, needsRestart }\n // 卸载成功走进度过渡动画;安装成功直接收尾\n if (q.kind === 'uninstall') settleDone(settled, lines)\n else finishQueueTask(true, settled, lines)\n return\n }\n if (status === 'failed') {\n // 服务端终态带出的尝试记录覆盖本地:以实际执行为准\n finishQueueTask(false, { ...q, attempts }, lines)\n return\n }\n }\n }\n } catch { /* 服务端不可达:按失败处理 */ }\n applyQueue((prev) => prev.filter((x) => x.id !== q.id)) // cancelled / 未知\n maybeStopPoll()\n }\n\n /** 轮询整个队列:合并服务端 /active(running 在前、pending 在后),\n * 消失的任务查终态收尾;队列清空即停止轮询。 */\n const pollQueue = () => {\n stopPoll()\n pollRef.current = window.setInterval(async () => {\n try {\n const res = await fetch('/dsh-plugin-hub/active', { cache: 'no-store' })\n if (!res.ok) throw new Error(`active ${res.status}`)\n const data = await res.json() as {\n tasks?: { id?: unknown; action?: unknown; target?: unknown; status?: unknown; progress?: unknown; lines?: unknown; attempts?: unknown; needsRestart?: unknown; installChannel?: unknown }[]\n pendingRestarts?: unknown\n }\n const active = (data.tasks ?? []).filter((a) => typeof a.id === 'number')\n const byId = new Map(active.map((a) => [a.id as number, a]))\n // 先捕获旧队列:gone 是「旧队列里服务端已消失的任务」的差集,必须在 applyQueue 更新前取\n const prevQueue = queueRef.current\n // 待重启列表同步(服务端内存态:宿主重启后自然变空,这里随之清空 UI)\n applyPending(parsePendingRestarts(data.pendingRestarts))\n // 合并:running 在前、pending 在后(与服务端一致),新出现任务补入队列\n applyQueue((prev) => {\n const next: QueueTask[] = []\n for (const a of active) {\n const id = a.id as number\n const prevTask = prev.find((q) => q.id === id)\n const isRemove = a.action === 'remove'\n next.push({\n id,\n kind: isRemove ? 'uninstall' : 'install',\n target: typeof a.target === 'string' ? repoFromInstallTarget(a.target) : (prevTask?.target ?? ''),\n desc: prevTask?.desc,\n repo: prevTask?.repo ?? (isRemove ? null : (typeof a.target === 'string' ? repoFromInstallTarget(a.target) : null)),\n // 安装时快照的目录信号:轮询合并时保留,任务成功后记录到本地\n version: prevTask?.version,\n updatedAt: prevTask?.updatedAt,\n status: a.status === 'running' ? 'running' : 'pending',\n progress: typeof a.progress === 'number' ? a.progress : prevTask?.progress ?? 0,\n lines: Array.isArray(a.lines) ? (a.lines as string[]) : (prevTask?.lines ?? []),\n attempts: Array.isArray(a.attempts) ? (a.attempts as string[]) : (prevTask?.attempts ?? []),\n needsRestart: typeof a.needsRestart === 'boolean' ? a.needsRestart : (prevTask?.needsRestart ?? true),\n // 入口渠道:本地乐观入队已带;服务端 /active 也带回(刷新恢复用),服务端优先\n channel: (a.installChannel === 'npm' || a.installChannel === 'git' || a.installChannel === 'dsh')\n ? a.installChannel\n : prevTask?.channel,\n })\n }\n // 保留乐观条目:服务端尚未登记(preflight 中),无真实 id,不能因 active 缺它就被合并吞掉\n const keepOpt = prev.filter((q) => q.optimistic && !next.some((x) => x.id === q.id))\n if (keepOpt.length > 0) next.push(...keepOpt)\n // 保留「已从服务端消失、但尚未收尾」的任务:收尾(settleTask)负责移除。\n // 若在这里提前摘除,卸载/安装完成的那一瞬队列会先变空,弹窗闪回「确认」态\n // (busy=false 且未 done),表现为「卸载中 → 卸载 → 卸载完成」的中间回退。\n const keepGone = prev.filter((q) =>\n !byId.has(q.id) && !next.some((x) => x.id === q.id) && q.status !== 'cancelling' && !q.optimistic)\n if (keepGone.length > 0) next.push(...keepGone)\n return next\n })\n // 本地有、服务端已消失 → 已结束:逐个查终态收尾\n // (cancelling 是客户端乐观过渡态,交给 cancelTask 的定时移除,不在轮询里提前收敛;\n // optimistic 是点击后尚未登记的占位,服务端 /status 查不到,跳过免误判成失败;\n // settling 是上一轮已开始收尾的任务,并发轮询直接跳过,避免重复收尾)\n const gone = prevQueue.filter((q) =>\n !byId.has(q.id) && q.status !== 'cancelling' && !q.optimistic && !settlingRef.current.has(q.id))\n for (const q of gone) {\n // 防御:同 id 任务可能已被上一轮收尾移除(极端时序下轮询合并出的重复条目),跳过避免重复收尾\n if (!queueRef.current.some((x) => x.id === q.id)) continue\n settlingRef.current.add(q.id)\n try { await settleTask(q) } finally { settlingRef.current.delete(q.id) }\n }\n } catch {\n // 服务端暂不可达:静默等待下一轮\n }\n }, 600)\n }\n\n // 刷新后恢复任务队列与待重启列表:任务注册表在服务端内存里,只要宿主进程没重启就还在;\n // 重新拉取 /active(数组)继续轮询,界面上显示「进行中」状态条,可展开查看实时输出。\n useEffect(() => {\n let cancelled = false\n const restore = async () => {\n try {\n const res = await fetch('/dsh-plugin-hub/active', { cache: 'no-store' })\n if (!res.ok) return\n const data = await res.json() as {\n tasks?: { id?: unknown; action?: unknown; target?: unknown; status?: unknown; progress?: unknown; lines?: unknown; attempts?: unknown; needsRestart?: unknown; displayTarget?: unknown; installChannel?: unknown }[]\n pendingRestarts?: unknown\n }\n if (cancelled) return\n // 待重启:装完没重启的持久提醒,刷新页面也要恢复\n applyPending(parsePendingRestarts(data.pendingRestarts))\n const items: QueueTask[] = (data.tasks ?? [])\n .filter((a) => typeof a.id === 'number')\n .map((a) => {\n const isRemove = a.action === 'remove'\n // 服务端任务的 target:显式 HTTPS Git URL(安装)/ npm 包名(npm 安装/卸载)。\n // 恢复展示统一用 displayTarget(owner/repo,服务端固定传):npm 安装时 target 是包名,\n // 直接展示会让用户看到「安装方式」的内部细节,违背无感知原则;卸载保持包名(匹配已装表)。\n const display = typeof (a as { displayTarget?: unknown }).displayTarget === 'string' ? repoFromInstallTarget((a as { displayTarget: string }).displayTarget) : ''\n const fallback = typeof a.target === 'string' ? repoFromInstallTarget(a.target) : ''\n return {\n id: a.id as number,\n kind: (isRemove ? 'uninstall' : 'install') as 'install' | 'uninstall',\n target: isRemove ? fallback : (display || fallback),\n repo: isRemove ? null : (display || fallback),\n action: (a.action === 'add' || a.action === 'update' || a.action === 'remove') ? a.action : 'add',\n status: a.status === 'running' ? 'running' : 'pending',\n progress: typeof a.progress === 'number' ? a.progress : 0,\n lines: Array.isArray(a.lines) ? (a.lines as string[]) : [],\n attempts: Array.isArray((a as { attempts?: unknown }).attempts) ? ((a as { attempts: string[] }).attempts) : [],\n needsRestart: typeof (a as { needsRestart?: unknown }).needsRestart === 'boolean' ? (a as { needsRestart: boolean }).needsRestart : true,\n // 服务端登记的入口渠道:自定义安装刷新后也能精准溯源(目录安装无此字段)\n channel: (a.installChannel === 'npm' || a.installChannel === 'git' || a.installChannel === 'dsh') ? a.installChannel : undefined,\n }\n })\n if (items.length > 0 || pendingRef.current.length > 0) {\n applyQueue((prev) => [...prev, ...items.filter((n) => !prev.some((p) => p.id === n.id))])\n // 刷新后恢复的任务同样保持折叠:摘要条提示进行中,点开才看明细/日志\n pollQueue()\n }\n } catch { /* host without the plugin's server routes */ }\n }\n void restore()\n return () => { cancelled = true }\n }, [])\n\n /** 弹窗动作:直接安装。请求宿主本地路由,任务进入服务端队列(FIFO),弹窗内实时显示进度。 */\n /** 安装入队核心:目录插件(catalog,后端走目录白名单)与命令行安装(custom,\n * 受安全开关控制)共用。队列条目一律用仓库名(repo)展示/防重,只有发给后端的\n * 实际安装目标(target)随通道变化(npm 包名 / github: 源)。 */\n const submitInstall = async (input: {\n /** 发给后端的实际安装目标:npm 包名或 github: 源(服务端再决定最终通道) */\n target: string\n /** 队列展示与防重用的仓库名 */\n repo: string\n desc?: string\n version?: string\n updatedAt?: string\n command: string\n source: 'catalog' | 'custom'\n /** 更新已安装目标(放行 add 覆盖重装) */\n update?: boolean\n /** 全局 npm 安装包列表(`npm install -g <pkgs>`):非空时服务端执行全局安装,不进任何 profile */\n globalNpm?: string[]\n /** 自定义安装入口渠道(NPM 包 / GitHub 源码 / DSH 命令卡片):随请求上报服务端落日志,\n * 失败弹窗/通知据此精准溯源「从哪个入口发起」;目录安装不传。 */\n channel?: InstallChannel\n }) => {\n // 防重复入队:同一目标已在排队/执行中则忽略\n if (queueRef.current.some((q) => q.kind === 'install' && q.target === input.repo)) return\n // 请求在途防重:任务要等响应回来才进本地队列,这之前再次点击(双击)直接忽略\n if (submittingRef.current.has(input.repo)) return\n submittingRef.current.add(input.repo)\n // 乐观入队:点击安装立即显示「正在安装中」,不等 POST 响应。\n // 服务端 /install 会先跑预检(preflight,可能耗时数秒)再入队,若等响应才入队列,\n // 用户点完安装立刻去看任务会看不到 —— 只有刷新后 restore 才拉回来。\n // 用负临时 id 占位,响应回来换成真实 task id;失败/出错则移除该占位。\n tempIdRef.current -= 1\n const tempId = tempIdRef.current\n modalTaskRef.current = tempId\n applyQueue((prev) => [...prev, {\n id: tempId, kind: 'install', target: input.repo, repo: input.repo, desc: input.desc,\n version: input.version, updatedAt: input.updatedAt,\n status: 'running', progress: 0, lines: [], optimistic: true,\n command: input.command,\n channel: input.channel,\n action: input.update ? 'update' : 'add',\n // 服务端登记后 /active 会带回真实尝试记录(npm 反查 + 执行命令),先占位空列表\n attempts: [], needsRestart: true,\n }])\n setSubmitting(true)\n const controller = new AbortController()\n const timeout = window.setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n try {\n const res = await fetch('/dsh-plugin-hub/install', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n repo: input.target,\n display: input.repo,\n source: input.source,\n mode: input.update ? 'update' : undefined,\n // 界面语言带给服务端:网络预检等错误消息按用户当前语言返回(中文界面给中文,英文界面给英文)\n ...(langKey ? { lang: langKey } : {}),\n // 自定义安装入口渠道(三张卡片之一):服务端日志/报错提示据此溯源\n ...(input.channel ? { installChannel: input.channel } : {}),\n ...(input.globalNpm && input.globalNpm.length > 0 ? { globalNpm: input.globalNpm } : {}),\n }),\n signal: controller.signal,\n })\n const data = await res.json() as { ok?: boolean; task?: number; error?: string; attempts?: string[] }\n if (!data.ok || typeof data.task !== 'number') {\n // 请求层失败(重复安装 409 / 参数错误 / 安全开关 403 等):移除乐观条目 + 完整错误弹窗\n applyQueue((prev) => prev.filter((x) => x.id !== tempId))\n // 同步 400(如预检拦截)服务端会附上已尝试的安装方式,issue 预填一并展示;\n // 用 || 而非 ?? :error 为空字符串时回退 HTTP 状态,避免复制出来是空白。\n // 自定义安装(带入口渠道):错误正文顶部精准提示「从哪张卡片发起」\n const entry = entryLineOf(t, input.channel)\n const msg = data.error || `HTTP ${res.status}`\n onError(entry ? `${entry}\\n${msg}` : msg, input.repo, 'install', input.command, data.attempts)\n return\n }\n const taskId = data.task\n modalTaskRef.current = taskId\n // 用真实任务 id 替换乐观占位,解除 optimistic 标记(此后归正常收尾/轮询处理)\n applyQueue((prev) => prev.map((x) => (x.id === tempId\n ? { ...x, id: taskId, optimistic: undefined }\n : x)))\n // 提前缓存展示信息:安装成功后服务端登记待重启,轮询合并时不用等目录解析\n pendingInfoRef.current.set(input.repo, { desc: input.desc, version: input.version })\n // 摘要条常驻顶部(含实时进度),明细面板保持折叠,想看时再点开\n pollQueue()\n } catch (err) {\n // 网络异常:移除乐观条目 + 兜底错误弹窗(附上底层原因,避免只剩一句笼统的「安装失败」)\n applyQueue((prev) => prev.filter((x) => x.id !== tempId))\n const aborted = (err as { name?: string } | null)?.name === 'AbortError'\n const reason = aborted\n ? t('requestTimeout')\n : err instanceof Error && err.message ? err.message : String(err ?? '')\n // 自定义安装(带入口渠道):错误正文顶部精准提示「从哪张卡片发起」\n const entry = entryLineOf(t, input.channel)\n const msg = reason ? `${t('installFail')} — ${reason}` : t('installFail')\n onError(entry ? `${entry}\\n${msg}` : msg, input.repo, 'install', input.command)\n } finally {\n window.clearTimeout(timeout)\n submittingRef.current.delete(input.repo)\n setSubmitting(false)\n }\n }\n\n /** 目录插件安装:通道由目录数据(npmPackage)决定,走 catalog 白名单。 */\n const installNow = async (p: HubPlugin, opts?: { update?: boolean }) => {\n const repo = p.source?.repo ?? ''\n if (!repo) return\n // 安装通道决策(用户无感知):有 npm 包名 → 走 npm;否则 git 直装。\n const { target } = installTargetOf(p)\n if (!target) return\n await submitInstall({\n target,\n repo,\n desc: p.description,\n version: p.version,\n updatedAt: p.dates?.repoUpdatedAt,\n command: installCommandOf(p, true),\n source: 'catalog',\n update: opts?.update,\n })\n }\n\n /** 命令行安装:用户手输 npm 包名或 GitHub 地址,走 custom 源(受安全开关控制)。\n * update=true 时对已安装目标放行覆盖重装(与目录插件「更新」同一语义)。\n * channel=入口渠道(NPM 包 / GitHub 源码 / DSH 命令卡片):上报服务端落日志,\n * 失败弹窗/通知据此精准溯源。\n * 队列展示/防重一律用归一化身份(owner/repo 或 npm 包名):与服务端 /active 合并、\n * 弹窗目标匹配同口径,npm 包名透传不受影响。 */\n const installCustom = async (raw: string, opts?: { update?: boolean; channel?: InstallChannel }) => {\n const target = raw.trim()\n if (!target) return\n const repo = repoFromInstallTarget(target)\n await submitInstall({\n target,\n repo,\n command: `pnpm add ${target}`,\n source: 'custom',\n update: opts?.update,\n channel: opts?.channel,\n })\n }\n\n /** 全局 npm 安装(官方 README 的 `npm install -g <pkgs>`):不进任何 profile、无需宿主重启。\n * 队列展示/防重用包列表空格拼接的身份(与服务端 target 同口径);入口渠道固定为 npm(NPM 包卡片)。 */\n const installGlobalNpm = async (pkgs: string[], opts?: { update?: boolean; channel?: InstallChannel }) => {\n const list = (pkgs ?? []).map((p) => p.trim()).filter((p) => p !== '')\n if (list.length === 0) return\n const identity = list.join(' ')\n await submitInstall({\n target: identity,\n repo: identity,\n command: `npm install -g ${identity}`,\n source: 'custom',\n globalNpm: list,\n update: opts?.update,\n channel: opts?.channel ?? 'npm',\n })\n }\n\n /** 卸载入队核心:按 npm 包名直卸(目录插件与自定义安装共用,弹窗进度匹配同源)。 */\n const enqueueUninstall = async (name: string, repo: string | null, desc?: string) => {\n if (!name) return\n if (queueRef.current.some((q) => q.kind === 'uninstall' && q.target === name)) return\n // 请求在途防重:与安装一致,响应回来前再次点击直接忽略\n if (submittingRef.current.has(name)) return\n submittingRef.current.add(name)\n setSubmitting(true)\n const controller = new AbortController()\n const timeout = window.setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n try {\n const res = await fetch('/dsh-plugin-hub/uninstall', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ name, repo: repo ?? undefined }),\n signal: controller.signal,\n })\n const data = await res.json() as { ok?: boolean; task?: number; error?: string }\n if (!data.ok || typeof data.task !== 'number') {\n onError(data.error || `HTTP ${res.status}`, repo, 'uninstall')\n return\n }\n const taskId = data.task\n modalTaskRef.current = taskId\n applyQueue((prev) => [...prev, { id: taskId, kind: 'uninstall', target: name, desc, repo, status: 'pending', progress: 0, lines: [], needsRestart: true }])\n // 摘要条常驻顶部(含实时进度),明细面板保持折叠,想看时再点开\n pollQueue()\n } catch (err) {\n // 网络异常:附上底层原因,避免只剩一句笼统的「卸载失败」\n const aborted = (err as { name?: string } | null)?.name === 'AbortError'\n const reason = aborted\n ? t('requestTimeout')\n : err instanceof Error && err.message ? err.message : String(err ?? '')\n onError(reason ? `${t('uninstallFail')} — ${reason}` : t('uninstallFail'), repo, 'uninstall')\n } finally {\n window.clearTimeout(timeout)\n submittingRef.current.delete(name)\n setSubmitting(false)\n }\n }\n\n /** 弹窗动作:直接卸载(目录插件入口)。与安装同一队列机制,弹窗内实时显示进度。 */\n const uninstallNow = async (p: HubPlugin) => {\n const name = installedName(p)\n if (!name) return\n await enqueueUninstall(name, p.source?.repo ?? null, p.description)\n }\n\n /** 已安装视图动作:按已安装项卸载(覆盖目录外自定义安装,无目录数据也能卸)。 */\n const uninstallItem = async (item: InstalledItem) => {\n await enqueueUninstall(item.name, item.repo, item.plugin?.description)\n }\n\n /** 取消任务:排队中立即出队,执行中终止子进程;先标记「正在取消」短暂过渡后再移除。 */\n const cancelTask = async (id: number) => {\n if (modalTaskRef.current === id) modalTaskRef.current = null\n // 乐观标记「正在取消」,给用户一个可见反馈,而不是瞬间消失\n applyQueue((prev) => prev.map((q) => (q.id === id ? { ...q, status: 'cancelling' as const } : q)))\n try {\n await fetch('/dsh-plugin-hub/cancel', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n })\n } catch { /* 服务端不可达:仍按取消处理,稍后移除 */ }\n // 短暂展示「正在取消」后移除;队列清空则停止轮询\n window.setTimeout(() => {\n applyQueue((prev) => prev.filter((x) => x.id !== id))\n maybeStopPoll()\n }, 700)\n }\n\n /** 打开新弹窗前清空任务匹配:避免旧任务 id 误匹配到新弹窗。 */\n const clearModalTask = () => { modalTaskRef.current = null }\n\n // 弹窗对应任务:优先当前弹窗发起任务,其次按目标匹配(重新打开弹窗 / 目标已在队列时也能展示实时进度)\n // 目录插件按 source.repo 匹配;命令行安装(custom)按归一化后的仓库身份/包名匹配;\n // 全局 npm 安装按包列表身份(空格拼接)匹配;\n // 排除 cancelling:取消中的任务不再关联到弹窗,弹窗回到「确认」态可重新操作\n const installModalTarget = installPlugin?.source?.repo\n ?? (installCustomTarget ? repoFromInstallTarget(installCustomTarget) : null)\n ?? installGlobalTarget ?? null\n const installModalTask = (installPlugin || installCustomTarget || installGlobalTarget)\n ? (queue.find((q) => q.id === modalTaskRef.current && q.kind === 'install' && q.status !== 'cancelling')\n ?? queue.find((q) => q.kind === 'install' && q.target === installModalTarget && q.status !== 'cancelling')\n ?? null)\n : null\n const uninstallModalTask = (uninstallPlugin || uninstallName)\n ? (queue.find((q) => q.id === modalTaskRef.current && q.status !== 'cancelling')\n ?? queue.find((q) => q.kind === 'uninstall' && q.target === (uninstallName ?? installedName(uninstallPlugin!) ?? '') && q.status !== 'cancelling')\n ?? null)\n : null\n\n return {\n queue,\n pendingRestarts,\n installModalTask,\n uninstallModalTask,\n submitting,\n installNow,\n installCustom,\n installGlobalNpm,\n uninstallNow,\n uninstallItem,\n cancelTask,\n clearModalTask,\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Inline SVG icons used across the client. Icons inherit currentColor so\n * they adapt to themes and disabled states automatically.\n */\nimport { createElement as h } from 'react'\nimport headerStyles from '../../styles/Header.module.css'\nimport modalStyles from '../../styles/Modal.module.css'\n\n/** 弹窗右上角关闭按钮图标:内联 SVG 十字(stroke 继承 currentColor),随按钮禁用态一起变淡。 */\nexport function CloseIcon() {\n return h('svg', {\n className: modalStyles.modalCloseIcon,\n viewBox: '0 0 16 16',\n width: 14,\n height: 14,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M3 3l10 10M13 3L3 13',\n stroke: 'currentColor',\n strokeWidth: 1.6,\n strokeLinecap: 'round',\n }))\n}\n\n/** 来源链接图标:链节(stroke 继承 currentColor),弹窗里官网收录地址旁提示「可点击跳转」。 */\nexport function LinkIcon() {\n return h('svg', {\n className: modalStyles.linkIcon,\n viewBox: '0 0 24 24',\n width: 13,\n height: 13,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71',\n stroke: 'currentColor',\n strokeWidth: 1.8,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',\n stroke: 'currentColor',\n strokeWidth: 1.8,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }))\n}\n\n/** 帮助图标:圆圈 + 问号(stroke 继承 currentColor),自定义安装卡片标题旁的「帮助」按钮用。 */\nexport function HelpIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 13,\n height: 13,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('circle', {\n cx: 8, cy: 8, r: 6.3,\n stroke: 'currentColor', strokeWidth: 1.4,\n }),\n h('path', {\n d: 'M6.3 6.5a1.9 1.9 0 1 1 2.7 1.7c-.7.3-1 .8-1 1.4',\n stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round',\n }),\n h('circle', { cx: 8, cy: 11.6, r: 0.95, fill: 'currentColor' }),\n )\n}\n\n/** 品牌 logo 图标:蓝紫渐变圆角方块 + 白色拼图块(2x2 错落),标题左侧的品牌标识。 */\nexport function LogoIcon() {\n return h('svg', {\n className: headerStyles.logoIcon,\n viewBox: '0 0 24 24',\n width: 20,\n height: 20,\n 'aria-hidden': 'true',\n },\n h('defs', null,\n h('linearGradient', { id: 'dshLogoGrad', x1: '0', y1: '0', x2: '1', y2: '1' },\n h('stop', { offset: '0%', stopColor: '#4f46e5' }),\n h('stop', { offset: '100%', stopColor: '#7c3aed' }),\n ),\n ),\n h('rect', { x: 1, y: 1, width: 22, height: 22, rx: 6, fill: 'url(#dshLogoGrad)' }),\n h('rect', { x: 5.5, y: 5.5, width: 5.5, height: 5.5, rx: 1.5, fill: '#ffffff' }),\n h('rect', { x: 13, y: 5.5, width: 5.5, height: 5.5, rx: 1.5, fill: '#ffffff', opacity: 0.55 }),\n h('rect', { x: 5.5, y: 13, width: 5.5, height: 5.5, rx: 1.5, fill: '#ffffff', opacity: 0.55 }),\n h('rect', { x: 13, y: 13, width: 5.5, height: 5.5, rx: 1.5, fill: '#ffffff' }),\n )\n}\n\n/** GitHub 图标:官方 GitHub Mark(octocat),fill 继承 currentColor,头部右上角源码链接用。 */\nexport function GitHubIcon() {\n return h('svg', {\n className: headerStyles.githubIcon,\n viewBox: '0 0 24 24',\n width: 18,\n height: 18,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12',\n }))\n}\n\n/** 复制图标:双层矩形(stroke 继承 currentColor),手动命令旁的复制按钮用。 */\nexport function CopyIcon() {\n return h('svg', {\n className: headerStyles.copyIcon,\n viewBox: '0 0 16 16',\n width: 12,\n height: 12,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('rect', {\n x: 5.5, y: 5.5, width: 7, height: 7, rx: 1.5,\n stroke: 'currentColor', strokeWidth: 1.4,\n }),\n h('path', {\n d: 'M10.5 5.5v-2a1.5 1.5 0 0 0-1.5-1.5H4.5A1.5 1.5 0 0 0 3 3.5v4A1.5 1.5 0 0 0 4.5 9h1',\n stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round',\n }),\n )\n}\n\n/** 文件夹图标(Material folder):「在文件夹中显示」按钮用,fill 继承 currentColor。 */\nexport function FolderIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 13,\n height: 13,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z',\n }))\n}\n\n/** 下拉箭头图标:向下 V 形(stroke 继承 currentColor),下拉按钮触发器右侧提示可展开。 */\nexport function ChevronDownIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 12,\n height: 12,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M3.5 5.5L8 10l4.5-4.5',\n stroke: 'currentColor',\n strokeWidth: 1.6,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }))\n}\n\n/** 排序方向小箭头:正序(up) 朝上 / 倒序(down) 朝下,随 currentColor 着色,仅当前排序按钮显示 */\nexport function SortArrowIcon({ up }: { up: boolean }) {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 10,\n height: 10,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: up ? 'M4 9.5L8 5.5l4 4' : 'M4 6.5L8 10.5l4-4',\n stroke: 'currentColor',\n strokeWidth: 1.8,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }))\n}\n\n/** 插件市场图标:店面货架(stroke 继承 currentColor),一级导航「插件市场」tab 用。 */\nexport function MarketIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M4 10L5.6 4.5h12.8L20 10',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M4 10a2.2 2.2 0 0 0 4.4 0 2.2 2.2 0 0 0 4.4 0 2.2 2.2 0 0 0 4.4 0',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M5 13v6.5A1.5 1.5 0 0 0 6.5 21h11a1.5 1.5 0 0 0 1.5-1.5V13',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 自定义安装图标:终端窗口 + 提示符(stroke 继承 currentColor),一级导航「自定义安装」tab 用。 */\nexport function TerminalIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('rect', {\n x: 3, y: 4.5, width: 18, height: 15, rx: 2.5,\n stroke: 'currentColor', strokeWidth: 1.8,\n }),\n h('path', {\n d: 'M6.8 9.2l3.4 2.8-3.4 2.8',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M12.5 14.8h4.5',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round',\n }),\n )\n}\n\n/** 已安装图标:插件包(圆角方盒 + 盒盖线)+ 对勾(stroke 继承 currentColor),一级导航「已安装」tab 用。 */\nexport function InstalledIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('rect', {\n x: 4.5, y: 6.5, width: 15, height: 13, rx: 2.5,\n stroke: 'currentColor', strokeWidth: 1.8,\n }),\n h('path', {\n d: 'M4.5 11h15',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round',\n }),\n h('path', {\n d: 'M9.2 15.2l2.1 2.1 3.6-4',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 通知铃铛图标:实心铃铛(fill 继承 currentColor),采用 Material 官方 notifications 路径,一级导航通知中心入口用。 */\nexport function BellIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 15,\n height: 15,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z',\n }))\n}\n\n/** 设置图标:实心齿轮(fill 继承 currentColor),采用 Material 官方 settings 路径,齿形清晰、辨识度高。 */\nexport function SettingsIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94L14.4 2.81c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41L9.25 5.35C8.66 5.59 8.12 5.92 7.63 6.29L5.24 5.33c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.22-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61L19.14 12.94zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z',\n }))\n}\n\n/** 更新与通道图标:循环同步箭头(fill 继承 currentColor),采用 Material 官方 sync 路径,设置左侧导航「更新与通道」用。 */\nexport function UpdatesIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 15,\n height: 15,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z',\n }))\n}\n\n/** 安全与信任图标:盾牌 + 对勾(stroke 继承 currentColor),设置左侧导航「安全与信任」用。 */\nexport function SecurityIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 15,\n height: 15,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M8 1.8L13.8 3.8v4.3c0 3.5-2.2 6.3-5.8 7.6-3.6-1.3-5.8-4.1-5.8-7.6V3.8L8 1.8z',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M5.6 8.1l1.7 1.7 3.2-3.4',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 诊断图标:心跳脉冲线(stroke 继承 currentColor),设置左侧导航「诊断」用。 */\nexport function DiagnosticsIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 15,\n height: 15,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M1.6 8h3l1.9-4.2 2.9 8.4 1.9-4.2h3.1',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 恢复默认图标:逆时针还原箭头(stroke 继承 currentColor),设置左侧导航「恢复默认」用。 */\nexport function ResetIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 15,\n height: 15,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M3 5.2A5.6 5.6 0 1 1 2.4 9.6',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M2.6 2.6v2.6h2.6',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 确认弹窗图标类型:普通确认 = 问号;危险操作 = 垃圾桶 / 警告三角 / 还原箭头 */\nexport type ConfirmIconType = 'question' | 'trash' | 'warning' | 'reset'\n\n/** 确认弹窗图标:圆形徽标 + 白色图形 —— 普通确认(安装/更新/重启/忽略)蓝底白问号;\n * 危险操作(清空/删除/卸载/重置)红底白动作图形。居中放在弹窗标题下方,一眼区分确认类型。 */\nexport function ConfirmIcon({ type }: { type: ConfirmIconType }) {\n const danger = type !== 'question'\n const glyphs = type === 'trash'\n ? [\n h('path', {\n d: 'M4.5 6.5h15M9.5 6.5V4.8a1.3 1.3 0 0 1 1.3-1.3h2.4a1.3 1.3 0 0 1 1.3 1.3v1.7',\n stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M6.2 6.5l.7 12.2a1.5 1.5 0 0 0 1.5 1.3h7.2a1.5 1.5 0 0 0 1.5-1.3l.7-12.2',\n stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', { d: 'M10 10.2v6M14 10.2v6', stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round' }),\n ]\n : type === 'warning'\n ? [\n h('path', {\n d: 'M12 4.2l8.5 14.3a1 1 0 0 1-.87 1.5H4.37a1 1 0 0 1-.87-1.5L12 4.2z',\n stroke: '#ffffff', strokeWidth: 1.9, strokeLinejoin: 'round',\n }),\n h('path', { d: 'M12 9.6v4.5', stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round' }),\n h('circle', { cx: 12, cy: 16.7, r: 1.05, fill: '#ffffff' }),\n ]\n : type === 'reset'\n ? [\n h('path', { d: 'M4.5 7.8A8.4 8.4 0 1 1 3.6 14.4', stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round' }),\n h('path', { d: 'M3.9 3.9v3.9h3.9', stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round', strokeLinejoin: 'round' }),\n ]\n : [\n h('path', {\n d: 'M9.5 9.2a2.6 2.6 0 1 1 3.7 2.38c-.84.38-1.2.95-1.2 1.72',\n stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round',\n }),\n h('circle', { cx: 12, cy: 16.4, r: 1.1, fill: '#ffffff' }),\n ]\n return h('div', {\n className: danger ? `${modalStyles.confirmIcon} ${modalStyles.confirmIconDanger}` : modalStyles.confirmIcon,\n 'aria-hidden': 'true',\n },\n h('svg', { viewBox: '0 0 24 24', width: 22, height: 22, fill: 'none' }, ...glyphs),\n )\n}\n\n/** 系统日志图标:文档纸 + 三行文字(stroke 继承 currentColor),设置左侧导航「系统日志」用。 */\nexport function LogsIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 15,\n height: 15,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M4.2 1.8h4.8l2.8 2.8v9.6H4.2z',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M9 1.8v2.8h2.8',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M5.6 9.2h4.8M5.6 11.2h4.8',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round',\n }))\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Inline progress block shared by the install and uninstall dialogs:\n * a real percentage bar (server-estimated, client-polled). No live terminal\n * window — pnpm emits nothing during git clone/build, so a log pane would be\n * empty for most of the run; failures surface their full output in ErrorModal.\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { TaskState } from '../../types.ts'\n\nexport function ProgressView({ task }: { task: TaskState }) {\n return h('div', { className: styles.progress },\n h('div', { className: styles.progressHead },\n h('span', { className: styles.progressText }, `${Math.round(task.progress)}%`),\n ),\n h('div', { className: styles.progressTrack },\n h('div', {\n className: task.status === 'failed' ? `${styles.progressFill} ${styles.progressFillFail}` : styles.progressFill,\n style: { width: `${task.progress}%` },\n }),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Dialog layer for the Plugin Hub: the install-confirm dialog, the uninstall\n * dialog and the global toast. Both dialogs lock themselves while a mutation\n * or restart is running, then switch to a result view offering an immediate\n * restart or a \"later\" deferral.\n */\nimport { createElement as h } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { EnvInfo, HubPlugin, TaskState, ToastState, Translate } from '../../types.ts'\nimport { CloseIcon, ConfirmIcon, CopyIcon, LinkIcon } from '../ui/icons.tsx'\nimport { ProgressView } from './ProgressView.tsx'\nimport { installCommandOf } from '../../logic/install-command.ts'\nimport { pluginDetailUrl, pluginIssueUrl, pluginSiteUrl } from '../../logic/urls.ts'\nimport { classifyFailure, missingRegistryPackageOf, npmTooLowVersion, pnpmPolicyHintOf, pnpmPolicyHintParams, unreachableTargetOf, registryHostOf } from '../../logic/failures.ts'\n\n/** 完成结果视图:绿色对勾 + 标题/描述;\n * needsRestart=true(插件需重启才生效)→ 「稍后重启 / 立即重启」按钮对,点稍后重启后\n * 通知中心待重启条目常驻(服务端登记,内存态),直到用户点「立即重启」真正重启后才消失;\n * needsRestart=false(卸载已即时生效)→ 仅「完成」关闭。 */\nfunction ResultView({\n title, desc, t, restarting, needsRestart, onRestart, onClose,\n}: {\n title: string\n desc: string\n t: Translate\n restarting: boolean\n needsRestart: boolean\n onRestart: () => void\n onClose: () => void\n}) {\n return h('div', { className: styles.result },\n h('div', { className: styles.resultCheck },\n h('svg', {\n className: styles.resultCheckIcon,\n viewBox: '0 0 16 16',\n width: 20,\n height: 20,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M2.5 8.5l3.5 3.5 7.5-7.5',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n })),\n ),\n h('div', { className: styles.resultTitle }, title),\n desc ? h('div', { className: styles.resultDesc }, desc) : null,\n needsRestart\n ? h('div', null, [\n h('div', { className: styles.resultRestarting }, restarting ? t('restarting') : t('restartHint')),\n h('div', { className: styles.modalActions },\n h('button', { className: styles.restartLater, onClick: onClose, disabled: restarting }, t('restartLater')),\n h('button', { className: styles.restartNowWarning, onClick: onRestart, disabled: restarting },\n restarting ? t('restarting') : t('restartNow')),\n ),\n ])\n : h('div', { className: styles.modalActions },\n h('button', { className: styles.restartNow, onClick: onClose }, t('done'))),\n )\n}\n\nexport interface InstallModalProps {\n /** 目录插件(有完整元数据);命令行安装(custom)传 null 走 customTarget 模式 */\n plugin: HubPlugin | null\n /** 命令行安装目标(无目录元数据):提供时按裸目标展示确认/进度/结果,命令条显示 pnpm add <target> */\n customTarget?: string\n /** 全局 npm 安装(官方 README 的 `npm install -g <pkgs>`):提供时按包列表展示确认/进度/结果,\n * 命令条显示 npm install -g <pkgs> —— 装的是系统级 CLI 工具,不进插件列表、无需重启 */\n globalNpm?: string[]\n done: boolean\n task: TaskState | null\n t: Translate\n langPath: string\n restarting: boolean\n /** 已安装插件的覆盖更新(走同一条 add 命令原位重装,文案区分安装/更新) */\n update: boolean\n /** 仅命令行插件(webInstallable=false):不提供一键安装,只展示命令供复制到 dsh 终端 */\n cliOnly: boolean\n /** 安装请求在途(fetch 等待响应):此时任务尚未入队,需禁用确认按钮防止二次点击 */\n submitting: boolean\n /** 完成结果是否需重启才生效:true → 「稍后重启 / 立即重启」;false → 仅「完成」 */\n needsRestart: boolean\n onClose: () => void\n onCopy: () => void\n onInstall: () => void\n onRestart: () => void\n}\n\n/**\n * 信任确认弹窗:安装进入后台队列后弹窗仍可关闭(任务继续),\n * 只在本任务执行中展示实时进度;完成后切换为结果视图,与卸载一致。\n * 目录插件与命令行安装(customTarget 模式)共用同一套确认/进度/结果流程。\n */\nexport function InstallModal(props: InstallModalProps) {\n const { plugin, customTarget, globalNpm, done, task, t, langPath, restarting, submitting, update, cliOnly, needsRestart, onClose, onCopy, onInstall, onRestart } = props\n const busy = submitting || (task !== null && (task.status === 'pending' || task.status === 'running'))\n // 进行中标题带上插件名(中文「XX 插件安装中」;英文状态词在前更自然),并用状态色区分;\n // 命令行安装无插件元数据 → 直接用输入的目标展示;全局 npm 安装 → 包列表空格拼接\n const name = customTarget ?? (globalNpm !== undefined && globalNpm.length > 0 ? globalNpm.join(' ') : undefined) ?? plugin?.displayName ?? plugin?.slug ?? ''\n const busyTitle = (label: string) => langPath === 'zh/' ? `${name} 插件${label}` : `${label} ${name}`\n const title = busy\n ? task && task.status === 'pending'\n ? busyTitle(update ? t('queuedUpdateTitle') : t('queuedTitle'))\n : busyTitle(update ? t('updating') : t('installing'))\n : done\n ? update ? t('updateResultTitle') : t('installResultTitle')\n : update ? t('confirmUpdateTitle') : t('confirmTitle')\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: styles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', {\n className: busy\n ? `${styles.modalTitle} ${task && task.status === 'pending' ? styles.modalTitleQueued : styles.modalTitleBusy}`\n : styles.modalTitle,\n }, title),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: () => onClose(),\n }, h(CloseIcon)),\n ),\n done\n // 安装完成:结果视图(成功即生效,仅「完成」关闭);更新时标题/描述区分语义\n ? h(ResultView, {\n title: update ? t('updateResultTitle') : t('installResultTitle'),\n desc: update ? t('updateResultDesc') : t('installResultDesc'),\n t,\n restarting,\n needsRestart,\n onRestart,\n onClose,\n })\n // 确认/进行中:来源行 + 安装命令 + 实时进度 + 操作按钮\n : h('div', { className: styles.modalBody },\n // 安装/更新确认态:品牌蓝问号图标,一眼识别这是确认询问\n !busy ? h('div', { className: styles.confirmIconWrap },\n h(ConfirmIcon, { type: 'question' }),\n ) : null,\n h('div', { className: styles.trustHint }, t('confirmDesc')),\n h('div', { className: styles.modalRow },\n h('span', { className: styles.modalLabel }, t('confirmPlugin')),\n h('span', { className: styles.modalValue, title: name }, name),\n ),\n plugin?.source?.repo ? h('div', { className: styles.modalRow },\n h('span', { className: styles.modalLabel }, t('confirmSource')),\n // 来源仓库:可点击跳转官网收录详情页(新窗口打开)\n h('a', {\n className: styles.modalLink,\n href: pluginDetailUrl(plugin, langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: plugin.source.repo,\n }, h(LinkIcon), plugin.source.repo),\n ) : null,\n // 手动命令条:整条点击即复制,右侧再放一个显式复制按钮;\n // 命令行安装(无目录数据)直接展示 pnpm add <target>;全局 npm 安装展示 npm install -g <pkgs>\n h('div', {\n className: styles.modalCmd,\n onClick: onCopy,\n title: t('copyInstallCommand'),\n role: 'button',\n tabIndex: 0,\n },\n h('span', { className: styles.modalCmdText },\n globalNpm !== undefined && globalNpm.length > 0\n ? `npm install -g ${globalNpm.join(' ')}`\n : customTarget ? `pnpm add ${customTarget}` : installCommandOf(plugin!)),\n h('span', { className: styles.modalCmdCopy }, h(CopyIcon), t('copyCmdLabel')),\n ),\n // 全局 npm 安装说明:装的是系统级 CLI 工具,不进插件列表、无需重启宿主\n globalNpm !== undefined && globalNpm.length > 0\n ? h('div', { className: styles.cliOnlyHint }, t('globalNpmHint'))\n : null,\n // AI 识别可能需要命令行辅助的插件(webInstallable=false):提示但不拦截,仍允许尝试一键安装\n cliOnly ? h('div', { className: styles.cliOnlyHint }, t('cliOnlyHint')) : null,\n task && task.status === 'pending' ? h('div', { className: styles.queuedHint }, t('queuedHint')) : null,\n task ? h(ProgressView, { task }) : null,\n // 安装失败:引导用户复制上方命令到 dsh 终端手动安装(如 node-pty 等原生依赖构建脚本需人工放行)\n task && task.status === 'failed' ? h('div', { className: styles.failedCopyHint }, t('failedCopyHint')) : null,\n h('div', { className: styles.modalActions },\n h('button', {\n className: styles.modalCopy,\n disabled: busy,\n onClick: onCopy,\n }, t('copyInstallCommand')),\n h('button', {\n className: styles.modalInstall,\n disabled: busy,\n onClick: onInstall,\n }, busy\n ? (task && task.status === 'pending'\n ? (update ? t('queuedUpdateTitle') : t('queuedTitle'))\n : (update ? t('updating') : t('installing')))\n : (update ? t('updateNow') : t('installNow'))),\n ),\n ),\n ),\n )\n}\n\nexport interface UninstallModalProps {\n plugin: HubPlugin\n done: boolean\n task: TaskState | null\n t: Translate\n langPath: string\n restarting: boolean\n /** 卸载请求在途(fetch 等待响应):此时任务尚未入队,需禁用确认按钮防止二次点击 */\n submitting: boolean\n /** 完成结果是否需重启才生效:true → 「稍后重启 / 立即重启」;false(loader 已即时移除)→ 仅「完成」 */\n needsRestart: boolean\n onClose: () => void\n onCancel: () => void\n onCopyCommand: () => void\n onConfirm: () => void\n onRestart: () => void\n}\n\n/** 卸载确认弹窗:确认/进行中(后台队列,可关闭);完成后切换为结果视图(成功即生效,仅「完成」关闭)。 */\nexport function UninstallModal(props: UninstallModalProps) {\n const { plugin, done, task, t, langPath, restarting, submitting, needsRestart, onClose, onCancel, onCopyCommand, onConfirm, onRestart } = props\n const busy = submitting || (task !== null && (task.status === 'pending' || task.status === 'running'))\n // 进行中标题带上插件名,与安装弹窗一致,并用状态色区分\n const name = plugin.displayName ?? plugin.slug\n const busyTitle = (label: string) => langPath === 'zh/' ? `${name} 插件${label}` : `${label} ${name}`\n const title = busy\n ? task && task.status === 'pending' ? busyTitle(t('queuedUninstallTitle')) : busyTitle(t('uninstalling'))\n : done ? t('uninstallResultTitle') : t('uninstallTitle')\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: styles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', {\n className: busy\n // 注意 task 判空:submitting(请求在途)时任务尚未入队,task 为 null,不能直接解引用\n ? `${styles.modalTitle} ${task !== null && task.status === 'pending' ? styles.modalTitleQueued : styles.modalTitleBusy}`\n : styles.modalTitle,\n }, title),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: () => onClose(),\n }, h(CloseIcon)),\n ),\n done\n // 卸载完成:结果视图(成功即生效,仅「完成」关闭)\n ? h(ResultView, {\n title: t('uninstallResultTitle'),\n desc: t('uninstallResultDesc'),\n t,\n restarting,\n needsRestart,\n onRestart,\n onClose,\n })\n // 确认/进行中:来源行 + 实时进度 + 操作按钮\n : h('div', { className: styles.modalBody },\n // 卸载确认态:红色垃圾桶图标,删除类危险操作\n !busy ? h('div', { className: styles.confirmIconWrap },\n h(ConfirmIcon, { type: 'trash' }),\n ) : null,\n h('div', { className: styles.modalDesc }, t('uninstallDesc')),\n h('div', { className: styles.modalRow },\n h('span', { className: styles.modalLabel }, t('confirmPlugin')),\n h('span', { className: styles.modalValue, title: plugin.displayName ?? plugin.slug },\n plugin.displayName ?? plugin.slug),\n ),\n // 显示仓库来源:github 用户名 + 仓库名,让用户确认卸载的是哪一个仓库\n plugin.source?.repo ? h('div', { className: styles.modalRow },\n h('span', { className: styles.modalLabel }, t('confirmSource')),\n // 来源仓库:可点击跳转官网收录详情页(新窗口打开)\n h('a', {\n className: styles.modalLink,\n href: pluginDetailUrl(plugin, langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: plugin.source.repo,\n }, h(LinkIcon), plugin.source.repo),\n ) : null,\n task && task.status === 'pending' ? h('div', { className: styles.queuedHint }, t('queuedHint')) : null,\n task ? h(ProgressView, { task }) : null,\n h('div', { className: styles.modalActions },\n // 复制卸载命令:万一直接卸载失败,可去终端手动执行\n h('button', {\n className: styles.modalCopy,\n disabled: busy,\n onClick: onCopyCommand,\n }, t('copyUninstallCommand')),\n // 确认框语义:取消动作需明确指向「卸载」,避免歧义\n h('button', {\n className: styles.modalCancel,\n onClick: onCancel,\n }, t('cancelUninstall')),\n h('button', {\n className: styles.uninstallConfirm,\n disabled: busy,\n onClick: onConfirm,\n }, busy ? (task && task.status === 'pending' ? t('queuedUninstallTitle') : t('uninstalling')) : t('uninstallConfirm')),\n ),\n ),\n ),\n )\n}\n\n/** 预填插件仓库的 GitHub Issue 链接:标题带插件名,正文附完整错误信息,方便用户一键反馈。 */\n/** 安装/卸载失败弹窗:布局与失败记录一致(类型徽标 + 仓库超链接 + 隐蔽复制按钮),报错完整展示,底部一键提交 Issue。 */\nexport function ErrorModal({ message, repo, kind, command, attempts, t, env, onCopy, onClose, onRunDiagnostics }: {\n message: string\n repo: string | null\n kind: 'install' | 'uninstall'\n command?: string\n /** 尝试过的安装方式(npm 反查 + 实际执行命令):issue 预填一并贴给作者,便于反推正确的 npm 包名 */\n attempts?: string[]\n t: Translate\n env: EnvInfo | null\n onCopy: (text: string) => void\n onClose: () => void\n /** 网络不通时的「去系统诊断」直达按钮:跳到设置 → 系统诊断跑连通性检测(由宿主提供) */\n onRunDiagnostics?: () => void\n}) {\n // 失败归类:当前安装通道(npm/git)装不上 = 插件分发/依赖的问题,一律引导提 Issue\n const failureKind = classifyFailure(message)\n // 服务端 [npm-too-low] 标记里带的本机 npm 版本(无标记为 null,提示文案降级为「怀疑」)\n const npmVersion = npmTooLowVersion(message)\n // 复制完整错误:实际执行/尝试过的安装命令(如有)+ 完整错误正文。\n // 只复制 message 会丢上下文 —— 命令行安装输入的目标、执行过的命令都在 command/attempts 里,\n // 光拷一句「unsupported install target」出去没人看得懂\n const copyText = [\n ...(command ? [command] : []),\n ...(attempts ?? []),\n message,\n ].join('\\n')\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: styles.errorModal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n // 标题按操作类型明确区分:安装失败 / 卸载失败\n h('div', { className: styles.errorTitle }, kind === 'install' ? t('errorTitleInstall') : t('errorTitleUninstall')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n // 与失败记录一致的布局:类型徽标 + 仓库超链接 + 顶部隐蔽复制按钮\n h('div', { className: styles.failRow },\n h('div', { className: styles.failHead },\n h('span', {\n className: kind === 'install' ? styles.failKindInstall : styles.failKindUninstall,\n }, kind === 'install' ? t('install') : t('uninstall')),\n // 仓库地址(用户名/仓库)统一显示为可点击超链接,跳转到官网详情页(含插件收录信息),而非直接跳 GitHub\n repo ? h('a', {\n className: styles.failRepo,\n href: pluginSiteUrl(repo),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: repo,\n }, repo) : null,\n // 复制按钮放最上面、浅灰隐蔽;报错正文不允许鼠标选择复制,只能点这里\n h('button', { className: styles.errorCopySoft, onClick: () => onCopy(copyText) }, t('errorCopy')),\n ),\n // 报错信息完整展示(可滚动),比失败记录的预览看得更多\n h('pre', { className: styles.errorBox }, message),\n // npm 内部崩溃(edgesOut)+ 本机 npm 版本过低:npm 自身已知缺陷,不是插件问题 ——\n // 直接给升级指引,不引导提 Issue(提了也是 npm 的问题,插件作者无法修复)\n failureKind === 'npmTooOld'\n ? h('div', { className: styles.failPrepareHint },\n t(npmVersion ? 'failNpmTooLowV' : 'failNpmTooLow', npmVersion ? { v: npmVersion } : undefined))\n : failureKind === 'dshMissing'\n // 找不到 dsh 命令(Win「不是内部或外部命令」/ POSIX「command not found」/ spawn ENOENT):\n // 本机 DeepSeek Harness 未正确安装或 dsh 不在 PATH,不是插件问题 —— 直接给环境修复指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failDshMissingHint'))\n : failureKind === 'gitMissing'\n // 找不到 git 命令(Win「'git' is not recognized」/ POSIX「git: command not found」/ spawn ENOENT):\n // 本机 Git 未安装或不在 PATH,不是插件问题 —— 直接给环境修复指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failGitMissingHint'))\n : failureKind === 'pnpmMissing'\n // 找到了 dsh 但缺 pnpm(dsh 用它管理 profile 插件;dsh 报 pnpm not found on PATH):\n // 本机缺 pnpm,不是插件问题 —— 给安装指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failPnpmMissingHint'))\n : failureKind === 'npmMissing'\n // 全局 npm 安装通道 spawn 的 npm 找不到(Win「'npm' is not recognized」/ POSIX\n // 「npm: command not found」/ spawn ENOENT):本机 npm 未安装或不在 PATH —— 给安装指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failNpmMissingHint'))\n : failureKind === 'pnpmWorkspace'\n // pnpm 拒绝把依赖装到 workspace 根目录(ERR_PNPM_ADDING_TO_ROOT):宿主在 profile 目录\n // 调 pnpm add 时未声明在根操作,任何插件都会失败,不是插件问题 ——\n // 给 .npmrc 豁免指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failPnpmWorkspaceHint'))\n : failureKind === 'pnpmStore'\n // pnpm 存在但 store 大版本不匹配(ERR_PNPM_UNEXPECTED_STORE):profile 目录的依赖是\n // 另一大版本 pnpm 装的,当前 pnpm 不认,任何插件装进该 profile 都会失败 ——\n // 给清理重建指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failPnpmStoreHint'))\n : failureKind === 'pnpmPolicy'\n // pnpm 11 供应链安全策略拦截(minimumReleaseAge 拒收发布太新的包 / untrusted origin):\n // 本机 pnpm 策略不放行,装任何「刚发布/新来源」插件都撞墙 —— 给豁免指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t(pnpmPolicyHintOf(message), pnpmPolicyHintParams(message)))\n : failureKind === 'pnpmUnusedPatch'\n // profile 里留着指向旧版本 dsh-plugin 的补丁声明(ERR_PNPM_UNUSED_PATCH):pnpm 发现\n // 补丁没被用上就中止整次安装,任何插件都装不进来 —— 给删除条目的指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failPnpmUnusedPatchHint'))\n : failureKind === 'pnpmMissingDep'\n // profile 里留着指向 registry 上不存在(404)的包的依赖:pnpm 连得上 registry,\n // 是被明确告知包不存在 —— 该 profile 的任何安装都会先卡在这条依赖上,与本次要装的\n // 插件无关 → 点名缺失的包 + 删除条目指引,不引导提 Issue\n ? h('div', null, [\n (() => {\n const pkg = missingRegistryPackageOf(message)\n return pkg ? h('div', { className: styles.failNetworkTarget }, t('failPnpmMissingDepTarget', { pkg })) : null\n })(),\n h('div', { className: styles.failPrepareHint }, t('failPnpmMissingDepHint')),\n ])\n : failureKind === 'fileLocked'\n // profile 里的文件被其他进程占用(Windows os error 32):pnpm 无法替换被占用的文件,\n // 通常是宿主或杀毒软件持有句柄 —— 给退出宿主的指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failFileLockedHint'))\n : failureKind === 'accessDenied'\n // profile 里的文件被系统拒绝写入(Windows os error 5「拒绝访问」/ EPERM / EACCES):\n // 占用、只读属性、目录 ACL 或杀软拦截 —— 同样给退出宿主/检查权限的指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failAccessDeniedHint'))\n : failureKind === 'fsUnavailable'\n // 本机磁盘写不进去(ENOSPC / EROFS / EMFILE 及 Windows os error 112、19):\n // 空间不足、盘只读、句柄耗尽,任何插件都装不进来 —— 按子场景给指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failFsUnavailableHint'))\n : failureKind === 'originRejected'\n // 请求来源没通过本地 hub 服务的校验(服务端 403 untrusted origin):请求根本没进\n // 安装流程,与插件无关 —— 引导从本机地址重新打开市场,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failOriginRejectedHint', { profile: env?.profile ?? '<profile>' }))\n : failureKind === 'network'\n // 安装前预检 / 安装日志里的连接失败([network] / git fetch 超时 / DNS / TLS):\n // 是本机网络不通或代理有问题,不是插件问题 —— 提示检查网络 + 直达「系统诊断」,\n // 不引导提 Issue\n ? h('div', null, [\n // 「无法访问 …」醒目行:精准告诉用户具体哪个地址连不上(消息里取不到地址就跳过这行)\n (() => { const target = unreachableTargetOf(message); return target ? h('div', { className: styles.failNetworkTarget }, t('failNetworkTarget', { url: target })) : null })(),\n // registry 被指向内网/自定义源(tarball 从非官方源下载失败):直接给出换源指引,\n // 否则用户外网是通的会困惑「为什么连不上」\n (() => { const host = registryHostOf(message); return host ? h('div', { className: styles.failPrepareHint }, t('failNetworkRegistryHint', { host })) : null })(),\n h('div', { className: styles.failPrepareHint }, t('failNetworkHint')),\n onRunDiagnostics ? h('button', {\n className: styles.failDiagBtn,\n onClick: onRunDiagnostics,\n }, t('failNetworkRunDiag')) : null,\n ])\n : failureKind === 'pluginPrepare' || failureKind === 'pnpmIgnoredBuild'\n ? h('div', null, [\n // [packaging](预检/装后校验拦截:git 分发缺产物)与\n // prepare 构建脚本实际执行失败 / 原生依赖构建被 pnpm 拦截:都是插件打包分发问题 —— 先说明原因,按钮在下方提交\n h('div', { className: styles.failPrepareHint }, failureKind === 'pnpmIgnoredBuild'\n ? t('failIgnoredBuild')\n : /\\[packaging\\]/i.test(message) ? t('failPackagingHint') : t('failPrepareHint')),\n repo ? h('a', {\n className: styles.failBigIssue,\n href: pluginIssueUrl(repo, message, env, command, attempts),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('failIssueHint'),\n }, t('failIssueBig')) : null,\n ])\n : repo ? h('a', {\n className: styles.failBigIssue,\n href: pluginIssueUrl(repo, message, env, command, attempts),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('failIssueHint'),\n }, t('failIssueBig')) : null,\n ),\n h('div', { className: styles.modalActions },\n h('button', { className: styles.restartLater, onClick: onClose }, t('errorClose')),\n ),\n ),\n ),\n )\n}\n\n/** 全局反馈 Toast:复制成功(反色)/ 安装完成(反色)/ 安装失败(红色)/ 卸载结果 */\nexport function Toast({ toast, t }: { toast: ToastState; t: Translate }) {\n const text = toast.kind === 'copied' ? t('toastCopied')\n : toast.kind === 'errCopied' ? t('errCopied')\n : toast.kind === 'done' ? t('installDone')\n : toast.kind === 'fail' ? t('installFail')\n : toast.kind === 'removed' ? t('uninstallDone')\n : toast.kind === 'revealFail' ? t('openFolderFail')\n : t('uninstallFail')\n const fail = toast.kind === 'fail' || toast.kind === 'removeFail' || toast.kind === 'revealFail'\n return h('div', {\n key: toast.id,\n className: fail ? `${styles.toast} ${styles.toastFail}` : styles.toast,\n }, text)\n}\n\n/** 待重启确认弹窗:已安装列表行内「重启」按钮点击后弹出,\n * 与通知中心待重启条目同一交互(说明 + 稍后重启 / 立即重启),\n * 避免行内按钮误触直接触发宿主重启。 */\nexport function RestartConfirmModal({ t, restarting, onClose, onRestartNow }: {\n t: Translate\n restarting: boolean\n onClose: () => void\n onRestartNow: () => void\n}) {\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) onClose() },\n },\n h('div', { className: styles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('sectionPendingRestart')),\n h('button', {\n className: styles.modalClose,\n type: 'button',\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n // 重启确认:红色警告三角 —— 重启会中断正在进行的安装/卸载任务,风险提示\n h('div', { className: styles.confirmIconWrap },\n h(ConfirmIcon, { type: 'warning' }),\n ),\n h('div', { className: styles.failPrepareHint }, t('restartHint')),\n h('div', { className: styles.modalActions },\n h('button', {\n className: styles.restartLater,\n type: 'button',\n disabled: restarting,\n onClick: onClose,\n }, t('restartLater')),\n h('button', {\n className: styles.restartNowWarning,\n type: 'button',\n disabled: restarting,\n onClick: onRestartNow,\n }, restarting ? t('restarting') : t('restartNow')),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 轻量 Markdown 渲染器:仅用于 Hub 自我更新的变更记录(Worker 下发的 notes)。\n *\n * 内容由插件作者自己编写、属可信内容,但渲染端仍先整体 HTML 转义,再按\n * Markdown 语法输出结构,杜绝任何未转义的原始 HTML 注入;链接仅放行 http(s)。\n *\n * 支持:标题(#~####)、有序/无序列表、代码块(```)、行内代码、加粗、斜体、\n * 链接、图片(![alt](url),如反馈群二维码)、引用(>)、段落;其余语法一律按\n * 纯文本处理,不引入外部依赖。图片仅放行 http(s),限定最大宽度不撑破弹窗。\n */\n\n/** HTML 转义:所有文本先进这里,再进入结构变换,保证输出里没有未转义的用户输入。 */\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n}\n\n/** 行内变换:链接 / 加粗 / 斜体 / 行内代码(代码先占位保护,最后还原)。 */\nfunction inline(s: string): string {\n let out = escapeHtml(s)\n // 行内代码先占位:避免其中的 * [ ] 被后续链接/加粗/斜体规则破坏\n const codeSpans: string[] = []\n out = out.replace(/`([^`]+)`/g, (_m, code) => {\n codeSpans.push(String(code))\n return `\\u0000${codeSpans.length - 1}\\u0000`\n })\n // 图片 ![alt](url):仅放行 http(s),用于展示反馈群二维码等;limited by CSS\n // 文件名为 dsh-plugin-user-group-qr 前缀的视为用户反馈群二维码,固定 100×100 不撑破弹窗。\n out = out.replace(/!\\[([^\\]]*)\\]\\(([^)\\s]+)\\)/g, (m, alt, url) => {\n const src = String(url)\n if (!/^https?:\\/\\//i.test(src) || /[\\u0000]/.test(src)) return m\n if (/\\/dsh-plugin-user-group-qr[^/]*$/i.test(src)) {\n return `<img src=\"${src}\" alt=\"${String(alt)}\" width=\"100\" height=\"100\" loading=\"lazy\">`\n }\n return `<img src=\"${src}\" alt=\"${String(alt)}\" loading=\"lazy\">`\n })\n // 链接 [text](url):仅放行 http(s),新窗口打开\n out = out.replace(/\\[([^\\]]+)\\]\\(([^)\\s]+)\\)/g, (m, text, url) =>\n /^https?:\\/\\//i.test(String(url)) && !/[\\u0000]/.test(String(url))\n ? `<a href=\"${String(url)}\" target=\"_blank\" rel=\"noopener noreferrer\">${String(text)}</a>`\n : m,\n )\n out = out.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>')\n out = out.replace(/(^|[^*])\\*([^*]+)\\*/g, '$1<em>$2</em>')\n return out.replace(/\\u0000(\\d+)\\u0000/g, (_m, idx) => `<code>${codeSpans[Number(idx)]}</code>`)\n}\n\n/** 把变更记录 Markdown 渲染为安全的 HTML 字符串(由弹窗用 dangerouslySetInnerHTML 注入)。 */\nexport function renderMarkdown(md: string): string {\n const lines = md.replace(/\\r\\n?/g, '\\n').split('\\n')\n const blocks: string[] = []\n let i = 0\n while (i < lines.length) {\n const line = lines[i]\n // 围栏代码块\n if (/^\\s*```/.test(line)) {\n const buf: string[] = []\n i++\n while (i < lines.length && !/^\\s*```/.test(lines[i])) {\n buf.push(lines[i])\n i++\n }\n i++ // 跳过闭合围栏\n blocks.push(`<pre><code>${escapeHtml(buf.join('\\n'))}</code></pre>`)\n continue\n }\n // 空行:段落分隔符\n if (line.trim() === '') {\n i++\n continue\n }\n // 标题:# 到 #### 映射为 h2~h5(弹窗标题用 modalTitle,不与其冲突)\n const heading = line.match(/^(#{1,4})\\s+(.*)/)\n if (heading) {\n const level = heading[1].length + 1\n blocks.push(`<h${level}>${inline(heading[2])}</h${level}>`)\n i++\n continue\n }\n // 有序 / 无序列表(连续收集为一个列表块)\n if (/^\\s*[-*+]\\s+/.test(line) || /^\\s*\\d+[.)]\\s+/.test(line)) {\n const ordered = /^\\s*\\d+[.)]\\s+/.test(line)\n const items: string[] = []\n while (i < lines.length && (/^\\s*[-*+]\\s+/.test(lines[i]) || /^\\s*\\d+[.)]\\s+/.test(lines[i]))) {\n items.push(`<li>${inline(lines[i].replace(/^\\s*[-*+]|\\s*\\d+[.)]\\s*/, '').trim())}</li>`)\n i++\n }\n blocks.push(`<${ordered ? 'ol' : 'ul'}>${items.join('')}</${ordered ? 'ol' : 'ul'}>`)\n continue\n }\n // 引用\n if (/^\\s*>\\s?/.test(line)) {\n const buf: string[] = []\n while (i < lines.length && /^\\s*>\\s?/.test(lines[i])) {\n buf.push(inline(lines[i].replace(/^\\s*>\\s?/, '')))\n i++\n }\n blocks.push(`<blockquote>${buf.join('<br>')}</blockquote>`)\n continue\n }\n // 普通段落:收集连续非空、非特殊开头的行\n const buf: string[] = []\n while (\n i < lines.length\n && lines[i].trim() !== ''\n && !/^\\s*```/.test(lines[i])\n && !/^#{1,4}\\s+/.test(lines[i])\n && !/^\\s*([-*+]|\\d+[.)])\\s+/.test(lines[i])\n ) {\n buf.push(inline(lines[i]))\n i++\n }\n blocks.push(`<p>${buf.join('<br>')}</p>`)\n }\n return blocks.join('')\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 头部「关注我们」弹窗:介绍 DSH Plugin Hub 的功能定位 + 用户反馈群二维码。\n * 内容以 Markdown 形式由 dsh-update Worker 的 /about 接口下发(key = hub:about),\n * 客户端按接口返回渲染,不内置固定文案。\n * 图片(反馈群二维码)经 renderMarkdown 的 ![](url) 语法嵌入,居中、最大高度受控。\n */\nimport { createElement as h, useMemo } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { HubAboutInfo } from '../../types.ts'\nimport type { LocaleId, Translate } from '../../types.ts'\nimport { renderMarkdown } from '../../logic/renderMarkdown.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\n\n/**\n * 反馈群二维码 URL 恒定(每次换码都是同名覆盖,文件名不变),浏览器 / CDN 会按\n * URL 缓存旧图。这里在渲染前给二维码 URL 实时拼一个新的时间戳,强制每次打开\n * 「关注我们」都回源拉取最新图片,无需重新构建 / 部署接口中心。\n * 匹配规则与 renderMarkdown 的二维码识别保持一致(dsh-plugin-user-group-qr 前缀)。\n */\nfunction bustQrCache(md: string, ts: number): string {\n return md.replace(\n /(!\\[[^\\]]*\\]\\()([^)\\s]*dsh-plugin-user-group-qr[^)\\s]*)/g,\n (_m, pre, url) => `${pre}${String(url).split('?')[0]}?v=${ts}`,\n )\n}\n\nexport function AboutModal({ info, lang, t, onClose }: {\n info: HubAboutInfo | null\n lang: LocaleId\n t: Translate\n onClose: () => void\n}) {\n // 内容:字符串直接使用;{zh,en} 对象按界面语言取,缺哪种补哪种,全缺则展示兜底文案。\n // Worker 未推送(info 为 null / content 为空)时弹窗仍能打开,显示「暂未发布」而非报错。\n const contentRaw = info\n ? typeof info.content === 'string'\n ? info.content\n : info.content && typeof info.content === 'object'\n ? lang === 'en'\n ? (info.content.en ?? info.content.zh ?? '')\n : (info.content.zh ?? info.content.en ?? '')\n : ''\n : ''\n // 每次打开弹窗(组件重新挂载)生成一个时间戳,用于二维码破缓存;\n // 同一次打开内保持稳定,避免父组件重渲染导致图片被反复重载。\n const qrTs = useMemo(() => Date.now(), [])\n const contentHtml = contentRaw.trim() ? renderMarkdown(bustQrCache(contentRaw, qrTs)) : null\n // 更新时间:ISO 字符串转本地可读格式;非法值静默隐藏\n let updated: string | null = null\n if (info?.updatedAt) {\n const d = new Date(info.updatedAt)\n if (!Number.isNaN(d.getTime())) {\n updated = d.toLocaleString(lang === 'en' ? 'en-US' : 'zh-CN')\n }\n }\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.modal} ${styles.aboutModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('aboutTitle')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: () => onClose(),\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalDesc }, t('aboutDesc')),\n contentHtml\n ? h('div', {\n className: styles.aboutContent,\n dangerouslySetInnerHTML: { __html: contentHtml },\n })\n : h('div', { className: styles.aboutContent }, t('aboutEmpty')),\n updated\n ? h('div', { className: styles.aboutMeta }, `${t('aboutUpdated')} ${updated}`)\n : null,\n h('div', { className: styles.modalActions },\n h('button', { className: styles.modalInstall, onClick: onClose }, t('doneBtn')),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Hub 版本信息 / 自我更新说明弹窗:\n * - 有更新(hasUpdate=true):标题「有新版本」,展示新版本号、发布时间与 Worker 下发的\n * Markdown 变更记录(renderMarkdown 渲染,双语言按界面语言取 {zh,en} 对象),\n * 按钮「稍后再说 / 直接更新」,确认后进入安装弹窗执行覆盖重装。\n * - 无更新(hasUpdate=false):标题「当前版本」,展示当前版本信息与更新记录,已是最新。\n * 点击头部版本号(或「可更新」徽标)打开 —— 无论有无更新都能看到更新内容。\n */\nimport { createElement as h } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { HubUpdateInfo } from '../../types.ts'\nimport type { LocaleId, Translate } from '../../types.ts'\nimport { renderMarkdown } from '../../logic/renderMarkdown.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\n\nexport function HubUpdateModal({ info, lang, t, hasUpdate, onProceed, onClose }: {\n info: HubUpdateInfo\n lang: LocaleId\n t: Translate\n /** 是否有可用更新:有则显示「直接更新」,无则显示「已是最新」 */\n hasUpdate: boolean\n /** 点「直接更新」:关闭本弹窗,进入安装弹窗的更新流程 */\n onProceed: () => void\n onClose: () => void\n}) {\n // 变更记录:字符串直接使用;{zh,en} 对象按界面语言取,缺哪种补哪种,全缺则不出记录区\n const notesRaw = typeof info.notes === 'string'\n ? info.notes\n : info.notes && typeof info.notes === 'object'\n ? lang === 'en'\n ? (info.notes.en ?? info.notes.zh ?? '')\n : (info.notes.zh ?? info.notes.en ?? '')\n : ''\n const notesHtml = notesRaw.trim() ? renderMarkdown(notesRaw) : null\n // 发布时间:ISO 字符串转本地可读格式;非法值静默隐藏\n let published: string | null = null\n if (info.publishedAt) {\n const d = new Date(info.publishedAt)\n if (!Number.isNaN(d.getTime())) {\n published = d.toLocaleString(lang === 'en' ? 'en-US' : 'zh-CN')\n }\n }\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.modal} ${styles.hubUpdateModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t(hasUpdate ? 'hubUpdateTitle' : 'hubCurrentTitle')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: () => onClose(),\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalDesc },\n t(hasUpdate ? 'hubUpdateDesc' : 'hubCurrentDesc', { version: info.version })),\n h('div', { className: styles.hubUpdateMeta },\n h('span', { className: styles.hubUpdateMetaItem }, `${t('version')} ${info.version}`),\n published\n ? h('span', { className: styles.hubUpdateMetaItem }, `${t('hubUpdatePublished')} ${published}`)\n : null,\n ),\n notesHtml\n ? h('div', {\n className: styles.hubUpdateNotes,\n dangerouslySetInnerHTML: { __html: notesHtml },\n })\n : null,\n h('div', { className: styles.modalActions },\n hasUpdate\n ? [\n h('button', { className: styles.restartLater, onClick: onClose }, t('hubUpdateLater')),\n h('button', { className: styles.modalInstall, onClick: onProceed }, t('updateNow')),\n ]\n : h('button', { className: styles.modalInstall, onClick: onClose }, t('hubUpToDate')),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Presentation formatters shared across the catalog list and the cards.\n */\nimport type { Translate } from '../types.ts'\n\n/** 星数/分支数的紧凑展示:<1k 原样;千级 1.2k;十万级取整。 */\nexport function fmtStars(count?: number): string {\n if (!count || count <= 0) return '0'\n if (count < 1000) return String(count)\n const k = count / 1000\n return `${k >= 100 ? Math.round(k) : k.toFixed(1).replace(/\\.0$/, '')}k`\n}\n\n/** 相对时间:今天 / N 天前 / N 个月前 / N 年前。 */\nexport function relTime(iso: string | undefined, t: Translate): string {\n if (!iso) return ''\n const days = Math.floor((Date.now() - new Date(iso).getTime()) / 86400000)\n if (days <= 0) return t('today')\n if (days < 30) return t('daysAgo', { days })\n if (days < 365) return t('monthsAgo', { months: Math.floor(days / 30) })\n return t('yearsAgo', { years: Math.floor(days / 365) })\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Installed-plugin detail dialog: opens from the Installed view (row click\n * or the detail button) and shows everything we know about an installed\n * entry — the catalog metadata (category, catalog entry, stars/forks,\n * latest version) merged with the host runtime facts (install path, installed\n * version, install time, last update). Update / uninstall actions are\n * offered from here too, mirroring the row actions.\n */\nimport { createElement as h } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { LocaleId, Translate } from '../../types.ts'\nimport type { InstalledItem } from '../../logic/installed.ts'\nimport { CATEGORY_LABELS, categoryLabel } from '../../logic/constants.ts'\nimport { pluginDetailUrl } from '../../logic/urls.ts'\nimport { fmtStars } from '../../logic/format.ts'\nimport { CloseIcon, CopyIcon, FolderIcon, LinkIcon } from '../ui/icons.tsx'\n\n/** ISO 安装时间 → 本地可读;非法值返回 null(行内不显示)。 */\nfunction fmtDate(iso: string | null, lang: LocaleId): string | null {\n if (!iso) return null\n const d = new Date(iso)\n return Number.isNaN(d.getTime()) ? null : d.toLocaleString(lang === 'en' ? 'en-US' : 'zh-CN')\n}\n\nexport function InstalledDetailModal({ item, t, lang, langPath, onClose, onUpdate, onUninstall, onCopyPath, onReveal }: {\n item: InstalledItem\n t: Translate\n lang: LocaleId\n langPath: string\n onClose: () => void\n /** 更新:仅目录插件且有更新时展示(点击后关闭详情、走安装确认弹窗的更新语义) */\n onUpdate: (item: InstalledItem) => void\n onUninstall: (item: InstalledItem) => void\n /** 复制安装路径:成功提示由调用方 toast 反馈 */\n onCopyPath: (path: string) => void\n /** 在系统文件管理器里定位安装目录(服务端 spawn open):失败提示由调用方 toast 反馈 */\n onReveal: (item: InstalledItem) => void\n}) {\n const p = item.plugin\n const name = p?.displayName ?? item.name\n const installedAt = fmtDate(item.installedAt, lang)\n // 最后更新:目录插件取仓库最近提交时间(live 数据);自定义安装无目录信号\n const lastUpdated = fmtDate(p?.dates?.repoUpdatedAt ?? null, lang)\n const hasUpdate = item.hasUpdate && item.plugin !== null\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.modal} ${styles.detailModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, name),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n // 描述:目录收录的插件简介\n p?.description ? h('div', { className: styles.modalDesc }, p.description) : null,\n // 有可用更新:醒目提示条(版本号存在时给出升级路径)\n hasUpdate\n ? h('div', { className: styles.detailUpdateHint },\n item.installedVersion && item.catalogVersion\n ? t('versionUpHint', { from: item.installedVersion, to: item.catalogVersion })\n : t('updateAvailableHint'))\n : null,\n // 详情信息网格:分类 / 状态 / 版本 / 收录入口 / 包名 / 统计 / 安装路径 / 安装时间 / 最后更新\n h('div', { className: styles.detailGrid },\n p?.category\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('detailCategory')),\n h('span', { className: styles.detailValue },\n categoryLabel(CATEGORY_LABELS, p.category, lang)))\n : null,\n h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('statusLabel')),\n h('span', { className: styles.detailValue },\n h('span', {\n className: item.loaded ? styles.detailStatusRunning : styles.detailStatusPending,\n 'aria-hidden': 'true',\n }),\n h('span', { className: styles.detailStatusText },\n item.loaded ? t('statusRunning') : t('statusPending')))),\n item.installedVersion\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('installedVersionLabel')),\n h('span', { className: styles.detailValue },\n h('span', { className: styles.detailMono }, item.installedVersion),\n // 目录有更新版本且与已装版本不同:给出「→ 目录最新」\n item.catalogVersion && item.catalogVersion !== item.installedVersion\n ? h('span', { className: styles.detailArrow },\n '\\u2192', h('span', { className: styles.detailMono }, item.catalogVersion),\n h('span', { className: styles.detailDim }, t('catalogLatest')))\n : null))\n : null,\n // 收录入口:仓库名 → 官网详情页(目录插件跳收录页;自定义安装回退到 GitHub 仓库)\n item.repo\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('detailCatalog')),\n h('a', {\n className: styles.detailLink,\n href: p ? pluginDetailUrl(p, langPath) : `https://github.com/${item.repo}`,\n target: '_blank',\n rel: 'noopener noreferrer',\n title: item.repo,\n }, h(LinkIcon), item.repo))\n : null,\n item.plugin?.source?.npmPackage\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('packageName')),\n h('span', { className: styles.detailValue },\n h('span', { className: styles.detailMono }, item.plugin.source.npmPackage)))\n : null,\n p?.stats && (p.stats.stargazers_count ?? 0) > 0\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('detailStats')),\n h('span', { className: styles.detailValue },\n h('span', { className: styles.detailStars }, '\\u2605 ', fmtStars(p.stats.stargazers_count)),\n h('span', { className: styles.detailDim }, t('fork'), ' ', fmtStars(p.stats.forks_count))))\n : null,\n item.installPath\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('installPath')),\n h('div', { className: styles.detailPath },\n // 整条点击复制路径(等宽文本省略号)\n h('span', {\n className: styles.detailPathText,\n title: t('copyPath'),\n onClick: () => onCopyPath(item.installPath!),\n }, item.installPath),\n h('span', { className: styles.detailPathActions },\n h('button', {\n className: styles.detailPathBtn,\n type: 'button',\n title: t('copyPath'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onCopyPath(item.installPath!)\n },\n }, h(CopyIcon)),\n h('button', {\n className: styles.detailPathBtn,\n type: 'button',\n title: t('openFolder'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onReveal(item)\n },\n }, h(FolderIcon)),\n )))\n : null,\n installedAt\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('installedAtLabel')),\n h('span', { className: styles.detailValue }, installedAt))\n : null,\n // 最后更新时间:与安装时间成对展示(目录插件才有)\n lastUpdated\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('lastUpdatedLabel')),\n h('span', { className: styles.detailValue }, lastUpdated))\n : null,\n ),\n ),\n // 底部操作:完成 / 更新 / 卸载(复制路径与打开文件夹已在路径行内)\n h('div', { className: styles.modalActions },\n h('button', {\n className: styles.restartLater,\n onClick: onClose,\n }, t('done')),\n hasUpdate\n ? h('button', {\n className: styles.modalInstall,\n onClick: () => onUpdate(item),\n }, t('update'))\n : null,\n h('button', {\n className: styles.uninstallConfirm,\n onClick: () => onUninstall(item),\n }, t('uninstall')),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Generic confirm dialog — the single entry point for every \"are you sure?\"\n * question in the app. Rule: any question must be a modal dialog, never an\n * in-button double-click.\n *\n * The icon in the middle tells the type at a glance: a blue question mark\n * for routine confirmations (install / update / restart / ignore), a red\n * action glyph for destructive ones (clear / delete / uninstall / reset).\n */\nimport { createElement as h } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { Translate } from '../../types.ts'\nimport { CloseIcon, ConfirmIcon, type ConfirmIconType } from '../ui/icons.tsx'\n\n/** 通用确认弹窗:标题 + 类型图标 + 描述 + 取消/确认按钮。\n * type='question' → 蓝问号 + 品牌蓝确认按钮;危险类型 → 红图形 + 红色确认按钮。 */\nexport function ConfirmDialog({ type, title, desc, confirmLabel, cancelLabel, busy, busyLabel, t, onConfirm, onCancel }: {\n type: ConfirmIconType\n title: string\n desc?: string\n confirmLabel: string\n cancelLabel?: string\n /** 确认动作在途:禁用按钮防止二次点击 */\n busy?: boolean\n /** 在途时确认按钮文案(如「清空中…」);缺省沿用 confirmLabel */\n busyLabel?: string\n t: Translate\n onConfirm: () => void\n onCancel: () => void\n}) {\n const danger = type !== 'question'\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) onCancel() },\n },\n h('div', { className: styles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, title),\n h('button', {\n className: styles.modalClose,\n type: 'button',\n 'aria-label': t('errorClose'),\n onClick: onCancel,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n h('div', { className: styles.confirmIconWrap },\n h(ConfirmIcon, { type }),\n ),\n desc ? h('div', { className: styles.modalDesc }, desc) : null,\n h('div', { className: styles.modalActions },\n h('button', {\n className: styles.restartLater,\n type: 'button',\n disabled: busy,\n onClick: onCancel,\n }, cancelLabel ?? t('confirmCancel')),\n h('button', {\n className: danger ? styles.dangerConfirm : styles.confirmPrimary,\n type: 'button',\n disabled: busy,\n onClick: onConfirm,\n }, busy && busyLabel ? busyLabel : confirmLabel),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Notification-center dialog: a persistent log of every settled install /\n * remove task — successes and failures alike.\n *\n * Records are written to localStorage at settle time (see logic/failures.ts),\n * so a result is never lost even when the dialog was dismissed or the user\n * was away. Each entry carries a circular status badge (green check for\n * success, red cross for failure) with white glyph and message text;\n * failures keep their copy / fix / file-an-issue actions. Opened from the\n * header entry button (after the Settings tab).\n */\nimport { createElement as h, useState } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { EnvInfo, Translate } from '../../types.ts'\nimport type { NotificationRecord } from '../../logic/failures.ts'\nimport { classifyFailure, missingRegistryPackageOf, npmTooLowVersion, pnpmPolicyHintOf, pnpmPolicyHintParams, unreachableTargetOf, registryHostOf } from '../../logic/failures.ts'\nimport type { PendingRestart, QueueTask } from '../../hooks/useTaskQueue.ts'\nimport { pluginIssueUrl, pluginSiteUrl } from '../../logic/urls.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\nimport { ConfirmDialog } from './ConfirmDialog.tsx'\n\n/** 记录时间完整展示:YYYY-MM-DD HH:mm:ss(每条通知都带精确到秒的时间戳)。 */\nfunction fmtTime(at: number): string {\n const d = new Date(at)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`\n}\n\n/** 圆形状态徽标内的白色图形:成功为对勾、失败为叉。 */\nfunction BadgeGlyph({ ok }: { ok: boolean }) {\n return h('svg', {\n className: styles.noticeBadgeIcon,\n viewBox: '0 0 16 16',\n width: 12,\n height: 12,\n fill: 'none',\n 'aria-hidden': 'true',\n }, ok\n ? h('path', {\n d: 'M3 8.5l3.5 3.5 6.5-6.5',\n stroke: '#ffffff',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n })\n : h('path', {\n d: 'M4 4l8 8M12 4L4 12',\n stroke: '#ffffff',\n strokeWidth: 2,\n strokeLinecap: 'round',\n }))\n}\n\nexport function NotificationsModal({ records, tasks, pendingRestarts, t, env, onClose, onCopy, onClear, onRemove, onUpdate, onIgnoreUpdate, cancelTask, restarting, onRestart, onRunDiagnostics, resolveRepo }: {\n records: NotificationRecord[]\n /** 进行中的安装/卸载任务(实时进度,与队列弹窗同一数据源) */\n tasks: QueueTask[]\n /** 待重启插件:装完没重启的常驻提醒 */\n pendingRestarts: PendingRestart[]\n t: Translate\n env: EnvInfo | null\n onClose: () => void\n onCopy: (text: string) => void\n onClear: () => void\n /** 删除单条通知记录 */\n onRemove: (id: number) => void\n /** 更新提醒通知点击:跳去该插件的更新确认弹窗 */\n onUpdate: (repo: string) => void\n /** 更新提醒「忽略本次更新」:先弹确认,确认后本次版本不再提醒,下一个新版本再通知 */\n onIgnoreUpdate: (repo: string, version?: string) => void\n cancelTask: (id: number) => void\n restarting: boolean\n onRestart: () => void\n /** 网络不通时的「去系统诊断」直达按钮:跳到设置 → 系统诊断跑连通性检测(由宿主提供) */\n onRunDiagnostics?: () => void\n /** 失败记录 repo 反查:npm 包名(历史记录存的是裸包名)反查成 owner/repo 再显示/提 Issue;\n * 查不到返回 null,按钮与仓库链接一并隐藏(防提到错误仓库)。不传则按记录原样展示。 */\n resolveRepo?: (repo: string) => string | null\n}) {\n // 危险操作确认:清空全部 / 删除单条都必须先弹独立确认框(垃圾桶图标),禁止按钮内直接生效\n const [confirmClear, setConfirmClear] = useState(false)\n const [confirmRemoveId, setConfirmRemoveId] = useState<number | null>(null)\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: styles.errorModal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('notifications')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n h('div', { className: styles.errorHint }, t('notificationsDesc')),\n // 进行中的安装/卸载任务实时进度也进通知中心:与队列弹窗同一套行结构,\n // 关掉任务弹窗后仍可在这里盯着进度;待重启插件可在此直接触发重启\n (tasks.length > 0 || pendingRestarts.length > 0)\n ? h('div', null, [\n pendingRestarts.length > 0\n ? h('div', { className: styles.queueSection },\n h('div', { className: styles.queueSectionTitle }, t('sectionPendingRestart')),\n pendingRestarts.map((p) => h('div', { key: `restart-${p.target}`, className: styles.queueRow },\n h('div', { className: styles.queueRowHead },\n h('span', {\n className: `${styles.failKind} ${p.kind === 'uninstall' ? styles.failKindUninstall : styles.failKindInstall}`,\n }, p.kind === 'uninstall' ? t('uninstall') : t('install')),\n h('span', { className: styles.queueRowTarget, title: p.target }, p.target),\n ),\n p.desc ? h('div', { className: styles.queueRowDesc, title: p.desc }, p.desc) : null,\n h('div', { className: styles.queueRowBody },\n h('span', { className: styles.pendingRowStatus },\n p.kind === 'uninstall' ? t('restartPendingHintUninstall') : t('restartPendingHint')),\n h('span', { className: styles.pendingRowActions },\n h('button', {\n className: styles.restartLater,\n disabled: restarting,\n onClick: onClose,\n }, t('restartLater')),\n h('button', {\n className: styles.restartNow,\n disabled: restarting,\n onClick: onRestart,\n }, restarting ? t('restarting') : t('restartNow')),\n ),\n ),\n )),\n )\n : null,\n tasks.length > 0\n ? h('div', { className: styles.queueSection },\n h('div', { className: styles.queueSectionTitle }, t('sectionInProgress')),\n tasks.map((q) => h('div', { key: q.id, className: styles.queueRow },\n h('div', { className: styles.queueRowHead },\n h('span', {\n className: `${styles.failKind} ${q.kind === 'install' ? styles.failKindInstall : styles.failKindUninstall}`,\n }, q.kind === 'install' ? t('install') : t('uninstall')),\n h('span', { className: styles.queueRowTarget, title: q.target }, q.target),\n h('button', {\n className: styles.stripCancel,\n disabled: q.status === 'cancelling',\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); cancelTask(q.id) },\n }, t('cancelTask')),\n ),\n q.desc ? h('div', { className: styles.queueRowDesc, title: q.desc }, q.desc) : null,\n h('div', { className: styles.queueRowBody },\n h('span', { className: styles.queueRowStatus },\n q.status === 'running'\n ? (q.kind === 'install' ? t('installing') : t('uninstalling'))\n : q.status === 'cancelling'\n ? t('cancelling')\n : (q.kind === 'install' ? t('queuedTitle') : t('queuedUninstallTitle'))),\n h('div', { className: `${styles.progressTrack} ${styles.queueRowTrack}` },\n h('div', { className: styles.progressFill, style: { width: `${q.progress}%` } }),\n ),\n h('span', { className: styles.queueRowPct }, `${q.progress}%`),\n ),\n )),\n )\n : null,\n ])\n : null,\n records.length === 0\n ? h('div', { className: styles.failEmpty }, t('notificationsEmpty'))\n : h('div', { className: styles.noticeList },\n records.map((r) => {\n const isUpdate = r.kind === 'update'\n // 展示用仓库:历史记录存的可能是裸 npm 包名,反查成 owner/repo 才显示/提 Issue;\n // 查不到为空 → 仓库链接与提 Issue 按钮都不渲染\n const shownRepo = resolveRepo ? (resolveRepo(r.repo) ?? '') : r.repo\n return h('div', {\n key: r.id,\n // 更新提醒:整行可点击直达更新确认弹窗;install/uninstall 记录维持原交互\n className: r.ok\n ? `${styles.noticeRow} ${styles.noticeRowOk}${isUpdate ? ` ${styles.noticeRowUpdate}` : ''}`\n : styles.noticeRow,\n ...(isUpdate ? { onClick: () => onUpdate(r.repo), title: t('updateNoticeGo') } : {}),\n },\n h('div', { className: styles.noticeRowMain },\n h('div', {\n className: r.ok ? styles.noticeBadgeOk : styles.noticeBadgeFail,\n }, h(BadgeGlyph, { ok: r.ok })),\n h('div', { className: styles.noticeMain },\n h('div', { className: styles.noticeHead },\n h('span', {\n className: r.ok ? styles.noticeTextOk : styles.noticeTextFail,\n }, r.ok\n ? (isUpdate\n ? t('updateNoticeTitle')\n : (r.action === 'update' ? t('updateDone') : (r.kind === 'install' ? t('installDone') : t('uninstallDone'))))\n : (r.action === 'update'\n ? t('errorTitleUpdate')\n : (r.kind === 'install' ? t('errorTitleInstall') : t('errorTitleUninstall')))),\n // 更新提醒:新版本号紧随标题展示;repo 为纯文本(整行点击即去更新,不跳官网外链)\n isUpdate && r.version\n ? h('span', { className: styles.noticeVersion, title: r.version }, `v${r.version}`)\n : null,\n r.repo\n ? (isUpdate\n ? h('span', { className: styles.failRepo, title: r.repo }, r.repo)\n : shownRepo\n ? h('a', {\n className: styles.failRepo,\n // 跳转到官网详情页(含插件收录信息),不在通知弹窗直接跳 GitHub\n href: pluginSiteUrl(shownRepo),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: shownRepo,\n }, shownRepo)\n // 反查不到仓库身份(如命令行安装的裸 npm 包名):回退显示记录里的原始值,\n // 保证通知永不只剩一句「安装/更新成功」没有名字 —— 只是不给官网外链(查不到不敢乱跳)\n : h('span', { className: styles.failRepo, title: r.repo }, r.repo))\n : null,\n !r.ok && h('button', {\n className: styles.failCopy,\n onClick: () => onCopy(r.message),\n }, t('failCopy')),\n // 成功通知:时间戳在行右侧,与图标/文字垂直居中,卡片保持单行内容\n r.ok\n ? h('span', {\n className: styles.noticeTime,\n title: new Date(r.at).toLocaleString(),\n }, fmtTime(r.at))\n : null,\n // 更新提醒:行尾「去更新」按钮直达更新确认弹窗(整行也可点击)\n isUpdate\n ? h('button', {\n className: styles.noticeUpdateGo,\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onUpdate(r.repo) },\n }, t('updateNoticeGo'))\n : null,\n // 更新提醒:「忽略本次更新」按钮 —— 先弹确认,确认后本次版本不再提醒\n isUpdate\n ? h('button', {\n className: styles.noticeIgnore,\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onIgnoreUpdate(r.repo, r.version) },\n }, t('ignoreUpdateRun'))\n : null,\n // 每条通知右侧的删除按钮:先弹确认框,确认后移除这一条\n h('button', {\n className: styles.noticeRemove,\n 'aria-label': t('removeNotification'),\n title: t('removeNotification'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); setConfirmRemoveId(r.id) },\n }, h(CloseIcon)),\n ),\n // 每条失败记录是一个独立卡片:头部(状态/仓库/时间/复制完整日志)→ 修复或提 Issue 动作。\n // 卡片不展示错误日志预览,完整日志靠「复制完整日志」按钮带走,避免每条卡片被日志撑高\n !r.ok && (() => {\n const kind = classifyFailure(r.message)\n if (kind === 'npmTooOld') {\n // npm 内部崩溃(edgesOut)+ 本机 npm 版本过低:npm 自身已知缺陷,不是插件问题 ——\n // 直接给升级指引,不引导提 Issue\n const v = npmTooLowVersion(r.message)\n return h('div', { className: styles.failPrepareHint },\n t(v ? 'failNpmTooLowV' : 'failNpmTooLow', v ? { v } : undefined))\n }\n if (kind === 'dshMissing') {\n // 找不到 dsh 命令(Win「不是内部或外部命令」/ POSIX「command not found」/ spawn ENOENT):\n // 本机 DeepSeek Harness 未正确安装或 dsh 不在 PATH,不是插件问题 —— 直接给环境修复指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failDshMissingHint'))\n }\n if (kind === 'gitMissing') {\n // 找不到 git 命令(Win「'git' is not recognized」/ POSIX「git: command not found」/ spawn ENOENT):\n // 本机 Git 未安装或不在 PATH,不是插件问题 —— 直接给环境修复指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failGitMissingHint'))\n }\n if (kind === 'pnpmMissing') {\n // 找到了 dsh 但缺 pnpm(dsh 用它管理 profile 插件;dsh 报 pnpm not found on PATH):\n // 本机缺 pnpm,不是插件问题 —— 给安装指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failPnpmMissingHint'))\n }\n if (kind === 'npmMissing') {\n // 全局 npm 安装通道 spawn 的 npm 找不到:本机 npm 未安装或不在 PATH ——\n // 给安装指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failNpmMissingHint'))\n }\n if (kind === 'pnpmWorkspace') {\n // pnpm 拒绝把依赖装到 workspace 根目录(ERR_PNPM_ADDING_TO_ROOT):宿主在 profile\n // 目录调 pnpm add 未声明在根操作,任何插件都会失败 ——\n // 给 .npmrc 豁免指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failPnpmWorkspaceHint'))\n }\n if (kind === 'pnpmStore') {\n // pnpm 存在但 store 大版本不匹配(ERR_PNPM_UNEXPECTED_STORE):profile 目录的依赖是\n // 另一大版本 pnpm 装的,当前 pnpm 不认,任何插件装进该 profile 都会失败 ——\n // 给清理重建指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failPnpmStoreHint'))\n }\n if (kind === 'pnpmPolicy') {\n // pnpm 11 供应链安全策略拦截(minimumReleaseAge 拒收发布太新的包 / untrusted origin):\n // 本机 pnpm 策略不放行,装任何「刚发布/新来源」插件都撞墙 —— 给豁免指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t(pnpmPolicyHintOf(r.message), pnpmPolicyHintParams(r.message)))\n }\n if (kind === 'pnpmUnusedPatch') {\n // profile 里留着指向旧版本 dsh-plugin 的补丁声明(ERR_PNPM_UNUSED_PATCH):pnpm\n // 发现补丁没被用上就中止安装,任何插件都装不进来 —— 不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failPnpmUnusedPatchHint'))\n }\n if (kind === 'pnpmMissingDep') {\n // profile 里留着指向 registry 上不存在(404)的包的依赖:pnpm 连得上 registry,\n // 是被明确告知包不存在 —— 该 profile 的任何安装都会先卡在这条依赖上,与本次要装的\n // 插件无关 → 点名缺失的包 + 删除条目指引,不引导提 Issue\n const pkg = missingRegistryPackageOf(r.message)\n return h('div', null, [\n pkg ? h('div', { className: styles.failNetworkTarget }, t('failPnpmMissingDepTarget', { pkg })) : null,\n h('div', { className: styles.failPrepareHint }, t('failPnpmMissingDepHint')),\n ])\n }\n if (kind === 'fileLocked') {\n // profile 里的文件被其他进程占用(Windows os error 32):通常是宿主或杀毒软件\n // 持有句柄 —— 给出完全退出宿主的指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failFileLockedHint'))\n }\n if (kind === 'accessDenied') {\n // profile 里的文件被系统拒绝写入(Windows os error 5「拒绝访问」/ EPERM / EACCES):\n // 占用、只读属性、目录 ACL 或杀软拦截 —— 给退出宿主 + 检查权限的指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failAccessDeniedHint'))\n }\n if (kind === 'fsUnavailable') {\n // 本机磁盘写不进去(ENOSPC / EROFS / EMFILE 及 Windows os error 112、19):\n // 空间不足、盘只读、句柄耗尽,任何插件都装不进来 —— 按子场景给指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failFsUnavailableHint'))\n }\n if (kind === 'originRejected') {\n // 请求来源没通过本地 hub 服务的校验(服务端 403 untrusted origin):请求根本没进\n // 安装流程,与插件无关 —— 引导从本机地址重新打开市场,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failOriginRejectedHint', { profile: env?.profile ?? '<profile>' }))\n }\n if (kind === 'network') {\n // 安装前预检 / 安装日志里的连接失败([network] / git fetch 超时 / DNS / TLS):\n // 是本机网络不通或代理有问题,不是插件问题 —— 提示检查网络 + 直达「系统诊断」,\n // 不引导提 Issue\n return h('div', null, [\n // 「无法访问 …」醒目行:精准告诉用户具体哪个地址连不上(消息里取不到地址就跳过这行)\n (() => { const target = unreachableTargetOf(r.message); return target ? h('div', { className: styles.failNetworkTarget }, t('failNetworkTarget', { url: target })) : null })(),\n // registry 被指向内网/自定义源(tarball 从非官方源下载失败):直接给出换源指引,\n // 否则用户外网是通的会困惑「为什么连不上」\n (() => { const host = registryHostOf(r.message); return host ? h('div', { className: styles.failPrepareHint }, t('failNetworkRegistryHint', { host })) : null })(),\n h('div', { className: styles.failPrepareHint }, t('failNetworkHint')),\n onRunDiagnostics ? h('button', {\n className: styles.failDiagBtn,\n onClick: onRunDiagnostics,\n }, t('failNetworkRunDiag')) : null,\n ])\n }\n if (kind === 'pluginPrepare' || kind === 'pnpmIgnoredBuild') {\n // [packaging](预检/装后校验拦截:git 分发缺产物)与\n // prepare 构建脚本实际执行失败 / 原生依赖构建被 pnpm 拦截:都是插件打包分发问题 —— 先说明原因,按钮在下方提交\n return h('div', null, [\n h('div', { className: styles.failPrepareHint }, kind === 'pnpmIgnoredBuild'\n ? t('failIgnoredBuild')\n : /\\[packaging\\]/i.test(r.message) ? t('failPackagingHint') : t('failPrepareHint')),\n r.repo && shownRepo ? h('a', {\n className: styles.failBigIssue,\n href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('failIssueHint'),\n }, t('failIssueBig')) : null,\n ])\n }\n return r.repo && shownRepo ? h('a', {\n className: styles.failBigIssue,\n href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('failIssueHint'),\n }, t('failIssueBig')) : null\n })(),\n ),\n ),\n // 失败通知:时间戳保留独立底部行(右下角);成功通知已并入头部行右侧\n !r.ok\n ? h('div', { className: styles.noticeFoot },\n h('span', {\n className: styles.noticeTime,\n title: new Date(r.at).toLocaleString(),\n }, fmtTime(r.at)),\n )\n : null,\n )\n }),\n ),\n h('div', { className: styles.modalActions },\n records.length > 0 ? h('button', {\n className: styles.failClear,\n onClick: () => setConfirmClear(true),\n }, t('notificationsClear')) : null,\n h('button', { className: styles.restartNow, onClick: onClose }, t('errorClose')),\n ),\n ),\n ),\n // 清空全部通知确认弹窗:独立弹出框(垃圾桶图标,危险操作),确认后才真正清空\n confirmClear && h(ConfirmDialog, {\n type: 'trash',\n title: t('notificationsClearConfirmTitle'),\n desc: t('notificationsClearConfirmDesc'),\n confirmLabel: t('notificationsClear'),\n t,\n onConfirm: () => { setConfirmClear(false); onClear() },\n onCancel: () => setConfirmClear(false),\n }),\n // 删除单条通知确认弹窗:独立弹出框(垃圾桶图标),确认后才移除\n confirmRemoveId !== null && h(ConfirmDialog, {\n type: 'trash',\n title: t('removeNotificationConfirmTitle'),\n desc: t('removeNotificationConfirmDesc'),\n confirmLabel: t('removeNotification'),\n t,\n onConfirm: () => { onRemove(confirmRemoveId); setConfirmRemoveId(null) },\n onCancel: () => setConfirmRemoveId(null),\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Section header: brand title row (H1 + open-site button) + tagline, followed\n * by the purple ad banner that promotes the catalog stats.\n */\nimport { createElement as h, Fragment } from 'react'\nimport styles from '../../styles/Header.module.css'\nimport type { Translate } from '../../types.ts'\nimport { GITHUB_URL, PLUGIN_VERSION } from '../../logic/constants.ts'\nimport { siteUrl } from '../../logic/urls.ts'\nimport { GitHubIcon, LogoIcon } from '../ui/icons.tsx'\n\nexport function CatalogHeader({ t, langPath, statsTotal, statsVerified, onToggleLang, hubUpdate, onVersionClick, onAboutClick }: {\n t: Translate\n langPath: string\n statsTotal: number\n statsVerified: number\n onToggleLang: () => void\n /** Hub 自身是否有可用更新:有则版本号后紧跟红色「可更新」徽标(整体一个可点入口) */\n hubUpdate: boolean\n /** 点击版本号(含红色徽标,同一入口):无论有无更新都打开更新记录弹窗 */\n onVersionClick: () => void\n /** 点击「关注我们」:打开平台介绍 + 用户反馈群二维码弹窗 */\n onAboutClick: () => void\n}) {\n return h(Fragment, null,\n h('div', { className: styles.header },\n // 第一行:logo + 标题(官网链接)与 GitHub 源码图标同行,GitHub 顶到标题行末尾\n h('div', { className: styles.headerTitleRow },\n h('a', {\n className: styles.brandTitle,\n href: siteUrl(langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('openHint'),\n 'aria-label': t('openHint'),\n },\n h(LogoIcon),\n h('h1', { className: styles.title }, t('title')),\n ),\n // 版本号:紧跟标题「DSH Plugin Hub」之后,常驻可点入口(<a> 内不能嵌套按钮,故从官网链接里移出放在旁边)。\n // 点击打开更新记录弹窗 —— 有更新看新版本内容,无更新看当前版本内容。\n // 有更新时版本号后直接跟一个红色「可更新」徽标(同一按钮内,不分开成两个元素),静态显示不闪烁。\n h('button', {\n className: styles.versionBtn,\n type: 'button',\n onClick: onVersionClick,\n title: t(hubUpdate ? 'hubUpdateHint' : 'versionHint'),\n 'aria-label': t(hubUpdate ? 'hubUpdateHint' : 'versionHint'),\n },\n `v${PLUGIN_VERSION}`,\n hubUpdate && h('span', { className: styles.hubUpdateBadge }, t('update')),\n ),\n // 右侧控件组:语言切换 + GitHub 源码图标(独立链接,brandTitle 是官网 <a> 不能嵌套),\n // 一起 space-between 顶到标题行最右\n h('div', { className: styles.headerRight },\n // 语言切换:按钮文字始终显示「要切到的语言」,点击即切,无需图标\n h('button', {\n className: styles.langBtn,\n type: 'button',\n onClick: onToggleLang,\n title: t('toggleLangHint'),\n 'aria-label': t('toggleLangHint'),\n }, langPath === 'zh/' ? 'EN' : '中文'),\n // 「关注我们」:点击打开平台介绍 + 用户反馈群二维码弹窗\n h('button', {\n className: styles.aboutBtn,\n type: 'button',\n onClick: onAboutClick,\n title: t('aboutDesc'),\n 'aria-label': t('aboutTitle'),\n }, t('followUs')),\n // GitHub 源码图标:独立链接(brandTitle 是官网 <a> 不能嵌套),放在控件组最后\n h('a', {\n className: styles.githubLink,\n href: GITHUB_URL,\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('githubHint'),\n 'aria-label': t('githubHint'),\n }, h(GitHubIcon)),\n ),\n ),\n // 第二行:副标题仍是官网链接,点击跳 dsh-plugin.org\n h('a', {\n className: styles.taglineLink,\n href: siteUrl(langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('openHint'),\n },\n h('div', { className: styles.tagline }, t('tagline', { total: statsTotal, verified: statsVerified })),\n ),\n ),\n h('a', {\n className: styles.adBanner,\n href: siteUrl(langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n },\n h('span', { className: styles.adBadge }, t('adBadge')),\n h('span', { className: styles.adText }, t('ad', { total: statsTotal, verified: statsVerified })),\n h('span', { className: styles.adArrow }, '\\u2197')),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Category tabs: an \"all\" chip followed by one chip per catalog category.\n * The \"all\" chip carries the total plugin count; the per-category chips\n * carry no counts so their widths stay uniform.\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/Header.module.css'\nimport type { LocaleId } from '../../types.ts'\nimport { CATEGORY_ORDER, CATEGORY_SHORT_LABELS, categoryLabel } from '../../logic/constants.ts'\n\nexport function CategoryTabs({ category, setCategory, allLabel, totalCount, langKey }: {\n category: string\n setCategory: (value: string) => void\n allLabel: string\n totalCount: number\n langKey: LocaleId\n}) {\n return h('div', { className: styles.tabs },\n // 第一个按钮固定为「全部」:展示全部分类,直接显示插件总数;\n // 其余分类按钮不带数量,保持排版整齐\n h('button', {\n key: 'all',\n className: category === 'all' ? styles.tabActive : styles.tab,\n onClick: () => setCategory('all'),\n },\n allLabel,\n h('span', { className: styles.tabCount }, totalCount)),\n CATEGORY_ORDER.map((id) => h('button', {\n key: id,\n className: category === id ? styles.tabActive : styles.tab,\n onClick: () => setCategory(id),\n },\n categoryLabel(CATEGORY_SHORT_LABELS, id, langKey))),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Toolbar above the market list:\n * row 1 — full-width search input;\n * row 2 — result count on the left, sort segmented control on the right\n * (mirrors the Installed view: clicking the same sort toggles\n * ascending/descending, a new sort uses its default order; the active\n * button shows an up/down arrow for the current direction).\n */\nimport { createElement as h, Fragment } from 'react'\nimport type { FormEvent, ReactNode } from 'react'\nimport styles from '../../styles/Header.module.css'\nimport type { Translate } from '../../types.ts'\nimport { SORTS } from '../../logic/constants.ts'\nimport type { SortKey } from '../../logic/constants.ts'\nimport { SortArrowIcon } from '../ui/icons.tsx'\n\n/** 单选按钮组中的一个按钮(segmented control,与已安装视图排序按钮同款) */\nfunction SegBtn({ active, onClick, label, icon }: {\n active: boolean\n onClick: () => void\n label: string\n icon?: ReactNode\n}) {\n return h('button', {\n type: 'button',\n className: active ? `${styles.segBtn} ${styles.segBtnActive}` : styles.segBtn,\n 'aria-pressed': active,\n onClick,\n }, label, icon)\n}\n\nexport function CatalogControls({ query, setQuery, sort, sortDir, toggleSort, t, resultText }: {\n query: string\n setQuery: (value: string) => void\n sort: SortKey\n /** 当前排序方向:决定激活排序按钮上的箭头朝上(正序)/朝下(倒序) */\n sortDir: 'asc' | 'desc'\n toggleSort: (value: SortKey) => void\n t: Translate\n resultText: string | null\n}) {\n return h(Fragment, null,\n // 第一行:搜索框占满整行(搜插件名称、描述、标签)\n h('div', { className: styles.searchRow },\n h('input', {\n className: styles.search,\n type: 'search',\n placeholder: t('search'),\n value: query,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) =>\n setQuery((e.target as HTMLInputElement).value),\n }),\n ),\n // 第二行:左侧筛选结果数「结果 N 条插件」(数字等宽预留 5 位不跳动),\n // 右侧排序按钮组(与已安装视图同款 segmented control,激活按钮带正/倒序箭头)\n h('div', { className: styles.controls },\n resultText ? h('span', { className: styles.resultSeg },\n ...resultText.split(/(\\d+)/).map((part, i) =>\n /^\\d+$/.test(part)\n ? h('span', { key: i, className: styles.resultCount }, part)\n : part)) : null,\n h('div', { className: styles.sortGroup },\n h('span', { className: styles.segLabel }, t('sortByLabel')),\n h('div', { className: styles.segGroup, role: 'radiogroup', 'aria-label': t('sortAria') },\n SORTS.map((key) => SegBtn({\n active: sort === key,\n onClick: () => toggleSort(key),\n label: t(key),\n icon: sort === key ? h(SortArrowIcon, { up: sortDir === 'asc' }) : null,\n })),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Incremental list: renders only the first batch of a (potentially huge)\n * result set and appends the next batch whenever the end sentinel scrolls\n * into view, so the plugin market never mounts thousands of cards at once.\n * The items reference is the list identity — category / search / sort\n * changes produce a new array, which resets the window to the first batch.\n */\nimport { useEffect, useRef, useState } from 'react'\n\n/** 首批渲染条数 & 每次滚到底追加的增量(单卡约 80px 高,100 条已远超一屏) */\nconst PAGE_SIZE = 100\n/** 哨兵进入视口底部前 800px 就提前加载下一批,滚到底时无感知衔接 */\nconst PRELOAD_MARGIN = '800px 0px'\n\nexport function useIncrementalList<T>(items: T[]) {\n const [limit, setLimit] = useState(PAGE_SIZE)\n const sentinelRef = useRef<HTMLDivElement | null>(null)\n\n // 筛选/分类/排序变化 → items 引用变化 → 窗口重置回首批\n useEffect(() => {\n setLimit(PAGE_SIZE)\n }, [items])\n\n // 哨兵进入视口(含预加载区)→ 追加下一批;已全部渲染则不再观察\n useEffect(() => {\n const el = sentinelRef.current\n if (!el || limit >= items.length) return\n const io = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) setLimit((cur) => Math.min(cur + PAGE_SIZE, items.length))\n }\n }, { rootMargin: PRELOAD_MARGIN })\n io.observe(el)\n return () => io.disconnect()\n }, [items.length, limit])\n\n return {\n shown: items.slice(0, limit),\n hasMore: limit < items.length,\n sentinelRef,\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * One plugin card in the catalog list: name/category/verified badge,\n * description + topics, star/fork/date stats, and the detail/install/\n * uninstall actions.\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/List.module.css'\nimport type { HubPlugin, LocaleId, Translate } from '../../types.ts'\nimport { CATEGORY_LABELS, categoryLabel } from '../../logic/constants.ts'\nimport { pluginDetailUrl } from '../../logic/urls.ts'\nimport { fmtStars, relTime } from '../../logic/format.ts'\n\nexport function PluginCard({ plugin: p, copied, installedName, installedVersion, hasUpdate, t, langKey, langPath, onInstall, onUninstall }: {\n plugin: HubPlugin\n copied: string | null\n installedName: (p: HubPlugin) => string | null\n /** 已安装版本号(安装时从目录信号记录;无 release 的仓库为空,无版本号可展示) */\n installedVersion: (p: HubPlugin) => string | null\n /** 已安装且目录有更新(有版本比版本、无版本比仓库更新时间) */\n hasUpdate: (p: HubPlugin) => boolean\n t: Translate\n langKey: LocaleId\n langPath: string\n /** 第二个参数标记「更新」(已安装目标的覆盖安装):按钮/弹窗据此走更新语义 */\n onInstall: (p: HubPlugin, opts?: { update?: boolean }) => void\n onUninstall: (p: HubPlugin) => void\n}) {\n const repo = p.source?.repo ?? ''\n const isCopied = copied === repo\n const pkg = installedName(p)\n const isInstalled = pkg !== null\n const update = hasUpdate(p)\n // 版本号展示:已安装 → 当前已装版本(最能反映用户状态);未安装 → 目录最新版本\n const versionShown = isInstalled ? installedVersion(p) : p.version\n\n return h('div', { className: styles.card },\n h('div', { className: styles.cardMain },\n h('div', { className: styles.cardHead },\n h('div', { className: styles.cardTitle, title: p.description ?? '' }, p.displayName ?? p.slug),\n // 版本号紧跟插件名称:有版本才显示(无 release 的仓库不展示版本号)\n versionShown ? h('span', { className: styles.versionBadge, title: t('version') }, versionShown) : null,\n // 已安装且有更新:醒目提示(有 release 比版本号、无 release 比仓库最近更新时间)\n update ? h('span', { className: styles.updateBadge, title: t('updateAvailableHint') }, t('updateAvailable')) : null,\n p.category ? h('span', { className: styles.categoryBadge }, categoryLabel(CATEGORY_LABELS, p.category, langKey)) : null,\n p.compatibility?.status === 'verified'\n ? h('span', { className: styles.verified }, t('verified'))\n : null,\n ),\n // 描述始终显示:站点英文数据缺翻译时 description 回退成中文也照常展示 ——\n // 描述是了解插件的第一入口,语言不一致也不该省略。\n p.description ? h('p', { className: styles.desc }, p.description) : null,\n (p.topics?.length ?? 0) > 0\n ? h('div', { className: styles.topics },\n p.topics!.slice(0, 3).map((topic) => h('span', { key: topic, className: styles.topic }, topic)),\n )\n : null,\n ),\n h('div', { className: styles.cardSide },\n h('div', { className: styles.stats },\n h('span', { className: styles.star }, '\\u2605 ', fmtStars(p.stats?.stargazers_count)),\n h('span', { className: styles.fork }, t('fork'), ' ', fmtStars(p.stats?.forks_count)),\n h('span', { className: styles.date }, relTime(p.dates?.repoUpdatedAt, t)),\n ),\n repo\n ? h('div', { className: styles.actions },\n // 查看详情:未安装/已安装都始终显示,跳转官网详情页\n h('a', {\n className: styles.detailBtn,\n // 两级路径:/plugins/{ownerSlug}/{slug};缺 ownerSlug 时从 repo 推导\n href: pluginDetailUrl(p, langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: p.slug,\n }, t('detail')),\n isInstalled\n // 已安装且有更新:按钮变「可更新」,点击直接覆盖安装(安装完成自动记录新版本)\n ? (update\n ? h('button', {\n className: styles.installBtnUpdate,\n title: t('updateAvailableHint'),\n onClick: () => onInstall(p, { update: true }),\n }, t('update'))\n : h('button', {\n className: styles.installBtnInstalled,\n disabled: true,\n title: t('installed'),\n }, t('installed')))\n // 未安装:按钮恒为「安装」,点击先弹信任确认;AI 识别为「可能需要命令行辅助」\n // 的插件(webInstallable=false)不拦截,允许尝试一键安装,弹窗内会给出提示与\n // 复制命令通道,安装失败时引导去 dsh 终端手动执行\n : h('button', {\n className: isCopied ? styles.installBtnCopied : styles.installBtn,\n // 文字恒定避免按钮宽度变化导致卡片跳动;点击先弹信任确认,\n // 弹窗内可选择复制命令或直接安装\n onClick: () => onInstall(p),\n }, t('install')),\n isInstalled\n // 已安装:卸载按钮(危险色),保留明确状态语义\n ? h('button', {\n className: styles.uninstallBtn,\n onClick: () => onUninstall(p),\n }, t('uninstall'))\n : null,\n )\n : null,\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Catalog list: the scrollable container with the loading / failed / empty\n * states, the plugin cards, and the count footer. Resets scroll position when\n * the category or install-status filter changes so the replaced content is\n * not mistaken for a no-op update.\n */\nimport { createElement as h, useEffect, useRef } from 'react'\nimport styles from '../../styles/List.module.css'\nimport type { HubPlugin, LocaleId, Translate } from '../../types.ts'\nimport { siteUrl } from '../../logic/urls.ts'\nimport { useIncrementalList } from '../../hooks/useIncrementalList.ts'\nimport { PluginCard } from './PluginCard.tsx'\n\nexport function CatalogList({ plugins, failed, visible, total, t, langPath, reload, category, copied, installedName, installedVersion, hasUpdate, langKey, onInstall, onUninstall, hasProxy, onOpenDiagnostics }: {\n plugins: HubPlugin[] | null\n failed: boolean\n visible: HubPlugin[]\n total: number\n t: Translate\n langPath: string\n reload: () => void\n category: string\n copied: string | null\n installedName: (p: HubPlugin) => string | null\n installedVersion: (p: HubPlugin) => string | null\n hasUpdate: (p: HubPlugin) => boolean\n langKey: LocaleId\n onInstall: (p: HubPlugin, opts?: { update?: boolean }) => void\n onUninstall: (p: HubPlugin) => void\n /** 设置里是否配置了 HTTP 代理:目录拉不出来时据此精准提示(网络不通 vs 代理不可达) */\n hasProxy: boolean\n /** 「去系统诊断检测网络」直达:跳到设置 → 系统诊断自动跑连通性检测 */\n onOpenDiagnostics: () => void\n}) {\n /** 列表滚动容器:分类/搜索切换后列表内容替换但 scrollTop 保留,会让用户误以为列表没更新,需重置回顶部 */\n const listRef = useRef<HTMLDivElement | null>(null)\n /** 增量渲染:全量目录太大(4400+),只渲染首批,滚动接近底部时自动追加下一批 */\n const { shown, hasMore, sentinelRef } = useIncrementalList(visible)\n\n useEffect(() => {\n listRef.current?.scrollTo({ top: 0 })\n }, [category])\n\n return h('div', { className: styles.body },\n h('div', { ref: listRef, className: styles.list },\n plugins === null && !failed && h('div', { className: styles.state }, t('loading')),\n failed && h('div', { className: styles.state },\n h('div', { className: styles.stateTitle }, t('failed')),\n // 精准提示:配了代理 → 提示代理可能不可达;没配 → 直接提示网络不通\n h('div', { className: styles.stateDesc }, t(hasProxy ? 'failedDescProxy' : 'failedDescNoProxy')),\n h('div', { className: styles.stateActions },\n h('button', { className: styles.retryBtn, onClick: () => reload() }, t('retry')),\n h('button', { className: styles.diagBtn, onClick: onOpenDiagnostics }, t('failNetworkRunDiag')),\n ),\n ),\n plugins !== null && !failed && visible.length === 0 && h('div', { className: styles.state },\n h('div', { className: styles.stateTitle }, t('noResult')),\n h('div', { className: styles.stateDesc }, t('noResultDesc')),\n ),\n plugins !== null && !failed && shown.map((p) => h(PluginCard, {\n // 唯一 key:数据重构后同一 slug 可能对应多个作者仓库,仅用 slug 会撞 key,\n // 导致切换分类时 React 复用旧 DOM、列表不刷新。\n key: p.ownerSlug ? `${p.ownerSlug}/${p.slug}` : p.slug,\n plugin: p,\n copied,\n installedName,\n installedVersion,\n hasUpdate,\n t,\n langKey,\n langPath,\n onInstall,\n onUninstall,\n })),\n // 滚动加载哨兵:透明 1px 元素,进入视口即触发下一批渲染(加载是纯追加,无需按钮)\n hasMore && h('div', { ref: sentinelRef, className: styles.moreSentinel, 'aria-hidden': 'true' }),\n ),\n plugins !== null && !failed && h('div', { className: styles.footer },\n h('a', {\n className: styles.footLink,\n href: siteUrl(langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n }, t('browseAll', { n: total })),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Market view: the browse experience for the catalog — category tabs,\n * search/sort/install-state controls and the plugin list. Owns nothing;\n * it wires catalog state (query/sort/filter/category) to the small\n * presentational components so PluginHubSection stays free of view internals.\n */\nimport { createElement as h, Fragment } from 'react'\nimport type { HubPlugin, LocaleId } from '../../types.ts'\nimport type { useCatalog } from '../../hooks/useCatalog.ts'\nimport { CategoryTabs } from '../layout/CategoryTabs.tsx'\nimport { CatalogControls } from '../layout/CatalogControls.tsx'\nimport { CatalogList } from '../catalog/CatalogList.tsx'\n\ntype CatalogState = ReturnType<typeof useCatalog>\n\nexport function MarketView({ catalog, t, langPath, langKey, copied, resultText, onInstall, onUninstall, hasProxy, onOpenDiagnostics }: {\n catalog: CatalogState\n t: (key: string, params?: Record<string, string | number>) => string\n langPath: string\n langKey: LocaleId\n copied: string | null\n resultText: string | null\n onInstall: (p: HubPlugin, opts?: { update?: boolean }) => void\n onUninstall: (p: HubPlugin) => void\n hasProxy: boolean\n onOpenDiagnostics: () => void\n}) {\n return h(Fragment, null,\n // 分类行保持原位原样:全部 + 各分类 chips\n h(CategoryTabs, {\n category: catalog.category,\n setCategory: catalog.setCategory,\n allLabel: t('all'),\n totalCount: catalog.total,\n langKey,\n }),\n h(CatalogControls, {\n query: catalog.query,\n setQuery: catalog.setQuery,\n sort: catalog.sort,\n sortDir: catalog.sortDir,\n toggleSort: catalog.toggleSort,\n t,\n resultText,\n }),\n h(CatalogList, {\n plugins: catalog.plugins,\n failed: catalog.failed,\n visible: catalog.visible,\n total: catalog.total,\n t,\n langPath,\n reload: catalog.reload,\n category: catalog.category,\n copied,\n installedName: catalog.installedName,\n installedVersion: catalog.installedVersion,\n hasUpdate: catalog.hasUpdate,\n langKey,\n onInstall,\n onUninstall,\n hasProxy,\n onOpenDiagnostics,\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Primary navigation: a compact segmented control switching between the\n * four top-level sections — Market (browse), Installed (manage), Custom\n * (manual command installs) and Settings (network sources & preferences).\n * Kept visually distinct from the category chips so the hierarchy reads:\n * section → category → plugin.\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/SectionTabs.module.css'\nimport { BellIcon, InstalledIcon, MarketIcon, SettingsIcon, TerminalIcon } from '../ui/icons.tsx'\n\nexport type SectionView = 'market' | 'installed' | 'custom' | 'settings'\n\nconst ORDER: Array<{ id: SectionView; labelKey: string; hintKey: string; Icon: () => ReturnType<typeof h> }> = [\n { id: 'market', labelKey: 'viewMarket', hintKey: 'viewMarketHint', Icon: MarketIcon },\n { id: 'installed', labelKey: 'viewInstalled', hintKey: 'viewInstalledHint', Icon: InstalledIcon },\n { id: 'custom', labelKey: 'viewCustom', hintKey: 'viewCustomHint', Icon: TerminalIcon },\n { id: 'settings', labelKey: 'viewSettings', hintKey: 'viewSettingsHint', Icon: SettingsIcon },\n]\n\nexport function SectionTabs({ view, setView, installedCount, t, noticeCount, onOpenNotifications }: {\n view: SectionView\n setView: (value: SectionView) => void\n installedCount: number\n t: (key: string) => string\n /** 通知中心红圈计数(记录 + 进行中任务 + 待重启);0 时不显示徽标 */\n noticeCount: number\n /** 点击打开通知中心 */\n onOpenNotifications: () => void\n}) {\n return h('div', { className: styles.root, role: 'tablist' },\n ORDER.map(({ id, labelKey, hintKey, Icon }) => h('button', {\n key: id,\n role: 'tab',\n 'aria-selected': view === id,\n title: t(hintKey),\n className: view === id ? styles.tabActive : styles.tab,\n onClick: () => setView(id),\n },\n h('span', { className: styles.tabIcon }, h(Icon)),\n t(labelKey),\n id === 'installed' && installedCount > 0\n ? h('span', { className: view === id ? styles.tabCountActive : styles.tabCount }, installedCount)\n : null)),\n // 通知入口:设置在最后一个 tab 后边,靠右对齐 —— 铃铛 + 红底白字计数(内联跟在铃铛后,不悬浮)\n h('button', {\n type: 'button',\n className: styles.noticeBtn,\n onClick: onOpenNotifications,\n title: t('notificationsHint'),\n 'aria-label': t('notificationsHint'),\n },\n h('span', { className: styles.noticeIcon }, h(BellIcon)),\n noticeCount > 0 ? h('span', { className: styles.noticeCount }, noticeCount > 99 ? '99+' : String(noticeCount)) : null),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Installed view: manages the plugins installed into the current profile.\n * Follows the mainstream extension-manager pattern (VSCode Installed tab) —\n * a searchable, sortable list of installed entries that mixes catalog\n * plugins (full metadata) and custom command installs (outside the catalog,\n * only runtime info, tagged with a custom badge). The toolbar carries a\n * search box plus two segmented radio-button groups: source filter\n * (all / catalog / custom) and sort (name / recently installed / stars / forks).\n * Each row carries restart (when pending), update and uninstall actions\n * and opens a detail modal with the full install metadata.\n *\n * Pure presentational: owns only local search/sort state; the InstalledItem\n * model arrives from the catalog hook and actions bubble up via callbacks.\n */\nimport { createElement as h, useMemo, useState } from 'react'\nimport type { FormEvent, MouseEvent, ReactNode } from 'react'\nimport styles from '../../styles/InstalledView.module.css'\nimport type { LocaleId, Translate } from '../../types.ts'\nimport type { InstalledItem } from '../../logic/installed.ts'\nimport { CATEGORY_LABELS, categoryLabel } from '../../logic/constants.ts'\nimport { SortArrowIcon } from '../ui/icons.tsx'\n\nconst INSTALLED_SORTS = ['sortName', 'sortInstalledAt', 'sortStars', 'sortForks'] as const\ntype InstalledSortKey = (typeof INSTALLED_SORTS)[number]\n\n/** 各排序的默认方向:名称按字母正序,最近安装 / Star / Fork 按数值倒序 */\nconst SORT_DEFAULT_DIR: Record<InstalledSortKey, 'asc' | 'desc'> = {\n sortName: 'asc', sortInstalledAt: 'desc', sortStars: 'desc', sortForks: 'desc',\n}\n\n/** 已安装列表的来源筛选:全部 / 目录收录 / 自定义安装 */\ntype SourceFilter = 'all' | 'catalog' | 'custom'\n\n/** 单选按钮组中的一个按钮(segmented control,与排序/来源筛选共用);\n 可带尾随图标(排序按钮激活时显示当前方向箭头) */\nfunction SegBtn({ active, onClick, label, icon }: {\n active: boolean\n onClick: () => void\n label: string\n icon?: ReactNode\n}) {\n return h('button', {\n type: 'button',\n className: active ? `${styles.segBtn} ${styles.segBtnActive}` : styles.segBtn,\n 'aria-pressed': active,\n onClick,\n }, label, icon)\n}\n\nfunction InstalledRow({ item, t, langKey, canReveal, revealLabel, onOpenDetail, onReveal, onUpdate, onUninstall, onRestart }: {\n item: InstalledItem\n t: Translate\n langKey: LocaleId\n /** 系统文件管理器可定位安装目录的平台(macOS / Linux):行内显示打开目录按钮 */\n canReveal: boolean\n /** 打开目录按钮文案(macOS = 在 Finder 中显示,Linux = 在文件夹中显示) */\n revealLabel: string\n onOpenDetail: (item: InstalledItem) => void\n /** 在系统文件管理器里定位安装目录(macOS Finder / Linux 文件管理器) */\n onReveal: (item: InstalledItem) => void\n onUpdate: (item: InstalledItem) => void\n onUninstall: (item: InstalledItem) => void\n /** 重启宿主:仅待重启(装完未挂载)条目展示,重启后该插件才生效 */\n onRestart: () => void\n}) {\n const name = item.plugin?.displayName ?? item.name\n const repo = item.repo\n const category = item.plugin?.category\n const desc = item.plugin?.description\n // 命令行安装进来的插件没有目录元数据(plugin === null):列表里打「自定义安装」标签区分\n const isCustom = item.plugin === null\n return h('li', {\n className: styles.row,\n onClick: () => onOpenDetail(item),\n role: 'button',\n tabIndex: 0,\n title: t('detail'),\n onKeyDown: (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onOpenDetail(item)\n }\n },\n },\n // 第一行:状态点 + 名称/版本/更新徽标 + 行尾来源标签列 + 右侧固定操作按钮组\n h('div', { className: styles.rowTitleLine },\n // 运行状态点:绿 = 已加载进 loader;橙 = 待重启(装完未挂载的 dsh 插件);\n // 灰 = 非 dsh 插件(如官方示例项目,宿主不加载,无需重启)\n h('span', {\n className: item.loaded ? styles.statusDot\n : item.dshCapable ? `${styles.statusDot} ${styles.statusPending}`\n : `${styles.statusDot} ${styles.statusInactive}`,\n title: item.loaded ? t('statusRunning')\n : item.dshCapable ? t('statusPending')\n : t('exampleHint'),\n 'aria-label': item.loaded ? t('statusRunning')\n : item.dshCapable ? t('statusPending')\n : t('exampleHint'),\n }),\n // 主信息:名称 + 已装版本 + 有更新徽标(flex 撑满,超长省略)\n h('div', { className: styles.rowMain },\n h('span', { className: styles.rowTitle }, name),\n item.installedVersion\n ? h('span', { className: styles.versionBadge, title: t('installedVersionLabel') }, item.installedVersion)\n : null,\n item.hasUpdate\n ? h('span', { className: styles.updateBadge, title: t('updateAvailableHint') }, t('updateAvailable'))\n : null,\n ),\n // 来源标签列(行尾、操作按钮前,右对齐固定):目录插件 →「插件市场」(品牌色),\n // 命令行安装 →「手动安装」(琥珀色);两词 4 字等宽,所有条目标签同列对齐\n h('span', {\n className: isCustom\n ? `${styles.rowSourceTag} ${styles.rowSourceTagManual}`\n : `${styles.rowSourceTag} ${styles.rowSourceTagHub}`,\n title: isCustom ? t('manualInstallHint') : t('hubInstallHint'),\n }, isCustom ? t('manualInstall') : t('hubInstall')),\n // 行操作:重启(dsh 插件待重启时)/ 详情 / 更新(有更新时)/ 卸载 —— 按钮点击不触发行打开详情\n h('div', { className: styles.rowActions },\n // 装完未挂载的 dsh 插件:给「重启」入口,点了宿主重启后插件即生效;非 dsh 插件不提示(重启无用)\n !item.loaded && item.dshCapable\n ? h('button', {\n className: styles.rowRestart,\n type: 'button',\n title: t('restartPendingHint'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onRestart() },\n }, t('restart'))\n : null,\n // 支持文件管理器定位的平台(macOS / Linux):行内该位改为打开安装目录按钮;\n // 行点击本身即打开详情弹窗,故不支持的平台(如 Windows)不显示此按钮\n canReveal\n ? h('button', {\n className: styles.rowDetail,\n type: 'button',\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onReveal(item) },\n }, revealLabel)\n : null,\n item.hasUpdate && item.plugin\n ? h('button', {\n className: styles.rowUpdate,\n type: 'button',\n title: t('updateAvailableHint'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onUpdate(item) },\n }, t('update'))\n : null,\n h('button', {\n className: styles.rowUninstall,\n type: 'button',\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onUninstall(item) },\n }, t('uninstall')),\n ),\n ),\n // 示例项目徽标单独一行(非 dsh 插件):标签较长也能完整显示,不挤压名称行\n !item.dshCapable\n ? h('div', { className: styles.exampleRow },\n h('span', { className: styles.exampleBadge, title: t('exampleHint') }, t('exampleLabel')),\n )\n : null,\n // 第二行:仓库 · 分类(与名称左对齐缩进,独立成行不再挤压名称)\n repo || category\n ? h('div', { className: styles.rowMeta },\n item.repo ? h('span', { className: styles.rowRepo }, item.repo) : null,\n category ? h('span', { className: styles.rowCategory },\n categoryLabel(CATEGORY_LABELS, category, langKey)) : null,\n )\n : null,\n // 第三行(仅目录插件):简介单独一行展示,超长以省略号收尾\n desc ? h('div', { className: styles.rowDesc, title: desc }, desc) : null,\n )\n}\n\n/** 行列表:单个已安装列表(自定义安装与目录插件混排,靠徽标区分)。 */\nfunction RowList({ items, t, langKey, canReveal, revealLabel, onOpenDetail, onReveal, onUpdate, onUninstall, onRestart }: {\n items: InstalledItem[]\n t: Translate\n langKey: LocaleId\n canReveal: boolean\n revealLabel: string\n onOpenDetail: (item: InstalledItem) => void\n onReveal: (item: InstalledItem) => void\n onUpdate: (item: InstalledItem) => void\n onUninstall: (item: InstalledItem) => void\n onRestart: () => void\n}) {\n return h('ul', { className: styles.list },\n items.map((item) => h(InstalledRow, {\n key: item.name,\n item,\n t,\n langKey,\n canReveal,\n revealLabel,\n onOpenDetail,\n onReveal,\n onUpdate,\n onUninstall,\n onRestart,\n })),\n )\n}\n\nexport function InstalledView({ items, t, langKey, platform, onOpenDetail, onReveal, onUpdate, onUninstall, onRestart }: {\n items: InstalledItem[]\n t: Translate\n langKey: LocaleId\n /** 宿主系统平台(node process.platform):支持文件管理器定位(macOS / Linux)时行内显示打开目录按钮 */\n platform: string\n onOpenDetail: (item: InstalledItem) => void\n onReveal: (item: InstalledItem) => void\n /** 更新:仅目录插件且有更新时触发(自定义安装无目录信号可比) */\n onUpdate: (item: InstalledItem) => void\n onUninstall: (item: InstalledItem) => void\n /** 重启宿主:待重启条目行内按钮触发(装完未挂载的插件重启后生效) */\n onRestart: () => void\n}) {\n const [query, setQuery] = useState('')\n /** 默认按「最近安装」排序(最新在前);点其他排序按钮用该排序的默认方向(Star/Fork 最多在前、名称正序) */\n const [sort, setSort] = useState<InstalledSortKey>('sortInstalledAt')\n /** 当前排序方向:点同一个排序按钮切换 正/倒序;点新排序用该排序的默认方向 */\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')\n /** 已安装列表的来源筛选:全部 / 目录收录 / 自定义安装(单选按钮组) */\n const [sourceFilter, setSourceFilter] = useState<SourceFilter>('all')\n\n /** 点击排序按钮:同一按钮切换正/倒序,新按钮用默认方向 */\n function pickSort(key: InstalledSortKey) {\n if (key === sort) setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))\n else { setSort(key); setSortDir(SORT_DEFAULT_DIR[key]) }\n }\n\n // 搜索 + 排序后的展示列表:搜索命中名称/包名/仓库/描述;排序支持名称/最近安装/Star/Fork\n const list = useMemo(() => {\n const q = query.trim().toLowerCase()\n const filtered = items.filter((item) => {\n if (!q) return true\n return (item.plugin?.displayName ?? item.name).toLowerCase().includes(q)\n || item.name.toLowerCase().includes(q)\n || (item.repo ?? '').toLowerCase().includes(q)\n || (item.plugin?.description ?? '').toLowerCase().includes(q)\n })\n const dir = sortDir === 'asc' ? 1 : -1\n return [...filtered].sort((a, b) => {\n if (sort === 'sortName') return (a.plugin?.displayName ?? a.name).localeCompare(b.plugin?.displayName ?? b.name) * dir\n // Star / Fork:目录插件按数量比较(正/倒序随 dir);自定义安装(无目录数据,stats 缺失)永远排最后\n if (sort === 'sortStars' || sort === 'sortForks') {\n const metric = sort === 'sortStars' ? 'stargazers_count' : 'forks_count'\n const sa = a.plugin?.stats?.[metric]\n const sb = b.plugin?.stats?.[metric]\n if (sa == null && sb == null) return 0\n if (sa == null) return 1\n if (sb == null) return -1\n return (sa - sb) * dir\n }\n // 最近安装:按安装时间比较;无安装时间记录的永远排最后\n const av = a.installedAt ?? ''\n const bv = b.installedAt ?? ''\n if (av === bv) return 0\n if (av === '') return 1\n if (bv === '') return -1\n return av.localeCompare(bv) * dir\n })\n }, [items, query, sort, sortDir])\n\n const catalogItems = list.filter((item) => item.plugin !== null)\n const customItems = list.filter((item) => item.plugin === null)\n // 已安装列表:搜索 + 排序后,再按来源筛选(全部 / 目录收录 / 自定义安装)\n const filtered = sourceFilter === 'all' ? list\n : sourceFilter === 'catalog' ? catalogItems : customItems\n\n // 行列表公共参数:macOS 文案特指 Finder,Windows / Linux 用通用「在文件夹中显示」\n const rowListProps = {\n t, langKey,\n canReveal: platform === 'darwin' || platform === 'win32' || platform === 'linux',\n revealLabel: platform === 'darwin' ? t('revealFolder') : t('openFolder'),\n onOpenDetail, onReveal, onUpdate, onUninstall, onRestart,\n }\n\n // 工具栏:第一行搜索框撑满,第二行来源筛选按钮组 + 排序按钮组(单选按钮组形态)\n const listToolbar = h('div', { className: styles.toolbar },\n h('div', { className: styles.searchWrap },\n h('input', {\n className: styles.searchInput,\n type: 'search',\n placeholder: t('installedSearch'),\n value: query,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) =>\n setQuery((e.target as HTMLInputElement).value),\n }),\n ),\n h('div', { className: styles.segRow },\n h('span', { className: styles.segLabel }, t('filterByLabel')),\n h('div', { className: styles.segGroup, role: 'radiogroup', 'aria-label': t('filterByLabel') },\n SegBtn({ active: sourceFilter === 'all', onClick: () => setSourceFilter('all'), label: t('all') }),\n SegBtn({ active: sourceFilter === 'catalog', onClick: () => setSourceFilter('catalog'), label: t('installedFilterCatalog') }),\n SegBtn({ active: sourceFilter === 'custom', onClick: () => setSourceFilter('custom'), label: t('customLabel') }),\n ),\n h('span', { className: styles.segLabel }, t('sortByLabel')),\n h('div', { className: styles.segGroup, role: 'radiogroup', 'aria-label': t('sortAria') },\n INSTALLED_SORTS.map((key) => SegBtn({\n active: sort === key,\n onClick: () => pickSort(key),\n label: t(key),\n icon: sort === key ? h(SortArrowIcon, { up: sortDir === 'asc' }) : null,\n })),\n ),\n ),\n )\n\n return h('div', { className: styles.root },\n listToolbar,\n // 筛选后的列表;一个都没装 → 引导空态,搜索/筛选无结果 → 无结果空态\n filtered.length === 0\n ? items.length === 0\n ? h('div', { className: styles.empty },\n h('div', { className: styles.emptyTitle }, t('installedEmpty')),\n h('div', { className: styles.emptyDesc }, t('installedEmptyDesc')),\n )\n : h('div', { className: styles.empty },\n h('div', { className: styles.emptyTitle }, t('noResult')),\n h('div', { className: styles.emptyDesc }, t('noResultDesc')),\n )\n : h(RowList, { items: filtered, ...rowListProps }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Custom install view: a standalone top-level section for manually\n * installing npm packages or GitHub sources outside the catalog. Three\n * installer cards, one per channel — npm package (bare name or a full\n * npm/pnpm install command, including the official global `npm install -g`),\n * GitHub source and the official `dsh plugin ... add <target>` command —\n * each with a placeholder example above the input and its own format check.\n * The cards stay separate so a user never has to guess which format goes\n * where. Finished installs surface in the Installed view, marked as custom.\n *\n * Pure presentational: owns only the three local input/error states; the\n * actual install (custom source, gated by the security toggles) bubbles up\n * via onInstallCustom.\n */\nimport { createElement as h, useState } from 'react'\nimport type { FormEvent, MouseEvent } from 'react'\nimport styles from '../../styles/CustomInstallView.module.css'\nimport modal from '../../styles/Modal.module.css'\nimport type { InstallChannel, Translate } from '../../types.ts'\nimport { CloseIcon, HelpIcon } from '../ui/icons.tsx'\n\n/* —— 自定义安装输入预检 ——\n * 提交前校验「输入是否符合该通道格式」,识别不了的输入不发请求,就地提示推荐格式。\n * 三个通道严格分开:npm 框认裸包名或完整 npm/pnpm 安装命令(含全局 `npm install -g`),\n * git 框只认 GitHub 地址,命令框只认官方 `dsh plugin --profile <name> <add|update> <target>`\n * (--profile 必填,无 -p 简写;update = 更新已安装目标到最新)。\n * 这里只做格式校验,真正归一化/安装由服务端完成。 */\n\n/** GitHub 地址(带前缀形态):github:、https://github.com/、git+https://github.com/、git@github.com: */\nconst GITHUB_URL_RE = /^(?:github:|https?:\\/\\/github\\.com\\/|git\\+https?:\\/\\/github\\.com\\/|git@github\\.com:)([A-Za-z0-9._-]+)\\/([A-Za-z0-9._-]+?)(?:\\.git)?$/\n/** 裸 owner/repo(npm 包名只有 @scope/pkg 才带斜杠,无 @ 前缀的 a/b 一定是 GitHub 仓库) */\nconst GITHUB_BARE_RE = /^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$/\n/** npm 包名(含 @scope/pkg) */\nconst NPM_PACKAGE_RE = /^(?:@[a-z0-9._-]+\\/)?[a-z0-9._-]+$/\n\n/** DSH 命令行前缀(官方唯一形式 `dsh plugin --profile <name> <add|update> <target>`)—— 提取其中的动作与目标。\n * 官方 CLI(apps/cli/src/args.ts,commander):--profile 为必填长选项(无 -p 简写,省略即报错),\n * 支持 `--profile=<name>` 等号形式;命令大小写不敏感。update = 已安装目标覆盖更新到最新;\n * remove 不走这里(卸载由「已安装」列表的卸载按钮执行,命令框不认卸载动词)。\n * 与 server 端 installTargetOf 口径一致。 */\nconst DSH_PLUGIN_CMD_RE = /^dsh\\s+plugin\\s+--profile(?:\\s+|=)\\S+\\s+(add|update)\\s+(.+)$/i\n\n/** npm 全局安装命令(官方 README 格式,如 `npm install -g @deepseek-ai/dsh @deepseek-harness-tui/dsh-tui`)——\n * 提取 -g 之后的包列表;任一包名非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 口径一致。 */\nconst NPM_GLOBAL_CMD_RE = /^npm\\s+(?:install|i)\\s+(?:-g|--global)\\s+(.+)$/i\n\n/** 常规 npm/pnpm 安装命令(装进当前 profile,如 `npm install lodash`、`pnpm add @scope/pkg`)——\n * 提取命令后的包列表;包列表在 splitPackages 里逐个校验。 */\nconst NPM_INSTALL_CMD_RE = /^(?:npm\\s+(?:install|i)|pnpm\\s+(?:add|i|install))\\s+(.+)$/i\n\n/** 解析 DSH 命令:返回 { action, target };非官方命令返回 null(交给格式错误提示)。 */\nfunction parseDshCommand(raw: string): { action: 'add' | 'update'; target: string } | null {\n const input = raw.trim()\n const match = DSH_PLUGIN_CMD_RE.exec(input)\n if (match === null) return null\n return { action: match[1].toLowerCase() as 'add' | 'update', target: match[2].trim() }\n}\n\n/** 空格分隔的包列表:逐个按 npm 包名语法校验 + 拒绝以 - 开头的 token(npm 会把 --xxx 当参数而非包名),\n * 任一非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 同口径。 */\nfunction splitPackages(raw: string): string[] | null {\n const packages = raw.trim().split(/\\s+/).filter((p) => p !== '')\n if (packages.length === 0 || packages.some((p) => !NPM_PACKAGE_RE.test(p) || p.startsWith('-'))) return null\n return packages\n}\n\n/** NPM 框输入解析结果:\n * - pkg:裸包名或常规安装命令(npm install / npm i / pnpm add / pnpm i),提取单个安装目标;\n * - global:官方全局安装命令(npm install -g <pkgs>),提取包列表走全局通道。 */\ntype NpmInputParse =\n | { kind: 'pkg'; target: string }\n | { kind: 'global'; pkgs: string[] }\n\nfunction parseNpmInput(raw: string): NpmInputParse | null {\n const input = raw.trim()\n // 裸包名(含 @scope/pkg)\n if (NPM_PACKAGE_RE.test(input)) return { kind: 'pkg', target: input }\n // 官方全局安装 npm install -g <pkgs>(装系统级 CLI 工具)\n const global = NPM_GLOBAL_CMD_RE.exec(input)\n if (global !== null) {\n const pkgs = splitPackages(global[1])\n if (pkgs !== null) return { kind: 'global', pkgs }\n return null\n }\n // 常规安装命令 npm install <pkgs> / pnpm add <pkgs> —— 装进当前 profile,一次一个包\n const install = NPM_INSTALL_CMD_RE.exec(input)\n if (install !== null) {\n const pkgs = splitPackages(install[1])\n if (pkgs !== null && pkgs.length === 1) return { kind: 'pkg', target: pkgs[0] }\n return null\n }\n return null\n}\n\nfunction isGitHubInput(raw: string): boolean {\n const input = raw.trim()\n return GITHUB_URL_RE.test(input) || GITHUB_BARE_RE.test(input)\n}\n\n/** 卡片标题旁的「帮助」弹窗:三块卡片各自的标题与格式清单语言包 key。 */\nconst HELP_CARDS = {\n npm: { titleKey: 'npmInstallLabel', contentKey: 'npmInstallHelp' },\n git: { titleKey: 'gitInstallLabel', contentKey: 'gitInstallHelp' },\n cmd: { titleKey: 'dshCmdLabel', contentKey: 'dshCmdHelp' },\n} as const\n\ntype HelpTarget = keyof typeof HELP_CARDS\n\nexport function CustomInstallView({ t, onInstallCustom, enableNpm, enableGit, enableDsh, onOpenSettings, profile }: {\n t: Translate\n /** 命令行安装:输入 npm 包名 / npm、pnpm 安装命令 / GitHub 地址 / dsh plugin 命令即装\n * (custom 源,受安全设置开关控制)。installChannel 必填 = 入口渠道(三张卡片之一):\n * 服务端日志/报错提示据此溯源「从哪个入口发起」;opts.globalNpm 表示官方 npm 全局安装\n * 命令(npm install -g),附带解析出的包列表(仍属 NPM 包入口)。 */\n onInstallCustom: (raw: string, opts: { installChannel: InstallChannel; globalNpm?: string[] }) => void\n /** 安全信任三通道开关:关掉后对应输入卡片禁用(不提交),并引导去设置打开 */\n enableNpm: boolean\n enableGit: boolean\n enableDsh: boolean\n /** 引导去「设置 → 安全信任」打开被关闭的通道开关 */\n onOpenSettings: () => void\n /** 当前 dsh profile 名(宿主 /env 快照):一键插入的更新命令用它拼 --profile */\n profile: string\n}) {\n /** 自定义安装:NPM 包输入与格式错误('' = 无错误) */\n const [npmQuery, setNpmQuery] = useState('')\n const [npmError, setNpmError] = useState('')\n /** 自定义安装:GitHub 源码输入与格式错误('' = 无错误) */\n const [gitQuery, setGitQuery] = useState('')\n const [gitError, setGitError] = useState('')\n /** 自定义安装:DSH 命令输入与格式错误('' = 无错误) */\n const [cmdQuery, setCmdQuery] = useState('')\n const [cmdError, setCmdError] = useState('')\n /** 卡片标题旁「帮助」弹窗:null = 未打开;'npm' | 'git' | 'cmd' = 打开对应卡片的格式清单 */\n const [helpFor, setHelpFor] = useState<HelpTarget | null>(null)\n\n /** 通道关闭提示行:开关关掉后替代示例与输入行,引导去设置打开 */\n const channelOffRow = h('div', { className: styles.channelOff },\n h('span', { className: styles.channelOffText }, t('channelDisabledHint')),\n h('button', {\n type: 'button',\n className: styles.channelOffBtn,\n onClick: onOpenSettings,\n }, t('goToSettings')),\n )\n\n // 三个通道分开校验 —— 识别不了的输入不发请求,就地提示推荐写法。\n // NPM 框认裸包名或完整 npm/pnpm 命令(含全局 npm install -g,走 globalNpm 通道);\n // 命令框只认官方 dsh plugin 命令,提交时剥成裸目标发给服务端。\n const submitNpm = () => {\n const raw = npmQuery.trim()\n if (!raw) return\n const parsed = parseNpmInput(raw)\n if (parsed === null) { setNpmError(t('npmInstallInvalid')); return }\n if (parsed.kind === 'global') {\n onInstallCustom(raw, { installChannel: 'npm', globalNpm: parsed.pkgs })\n } else {\n onInstallCustom(parsed.target, { installChannel: 'npm' })\n }\n setNpmQuery('')\n setNpmError('')\n }\n const submitGit = () => {\n const target = gitQuery.trim()\n if (!target) return\n if (!isGitHubInput(target)) { setGitError(t('gitInstallInvalid')); return }\n onInstallCustom(target, { installChannel: 'git' })\n setGitQuery('')\n setGitError('')\n }\n const submitCmd = () => {\n const raw = cmdQuery.trim()\n if (!raw) return\n const parsed = parseDshCommand(raw)\n if (parsed === null) { setCmdError(t('dshCmdInvalid', { profile })); return }\n // add / update 统一走安装流程:目标已安装时弹窗自动转「更新」覆盖重装(服务端 mode=update 放行),\n // 未安装时即为普通安装 —— 粘贴 `dsh plugin --profile web update dsh-plugin` 这类命令即可更新到最新\n onInstallCustom(parsed.target, { installChannel: 'dsh' })\n setCmdQuery('')\n setCmdError('')\n }\n /** 一键插入 DSH Plugin Hub 自身的更新命令:按当前 profile 拼官方命令填进输入框,用户确认后提交 */\n const insertHubUpdate = () => {\n setCmdQuery(`dsh plugin --profile ${profile} update dsh-plugin`)\n setCmdError('')\n }\n\n return h('div', { className: styles.root },\n // 页面说明:独立一级导航,交代「装完去哪看」\n h('p', { className: styles.desc }, t('customViewDesc')),\n // 三块卡片(一行一个):label + 文本框上方示例 + 输入行 + 错误区;\n // 安全信任开关关掉对应通道时,卡片禁用并显示「前往设置」提示行\n h('div', { className: styles.installCards },\n // NPM 包:输入包名或原生 npm/pnpm 安装命令即装(含官方全局 npm install -g)\n h('div', { className: enableNpm ? styles.installCard : `${styles.installCard} ${styles.installCardDisabled}` },\n h('div', { className: styles.installCardHead },\n h('span', { className: styles.installLabel }, t('npmInstallLabel')),\n // 标题旁帮助:点开该卡片的格式清单弹窗\n h('button', {\n type: 'button',\n className: styles.installHelpBtn,\n title: t('installHelp'),\n 'aria-label': t('installHelp'),\n onClick: () => setHelpFor('npm'),\n }, h(HelpIcon)),\n ),\n !enableNpm\n ? channelOffRow\n : [\n // 文本框上方的示例:把支持的原生命令模式写清楚(两行)\n h('div', { className: styles.installExample },\n t('npmInstallExample'), h('br'), t('npmInstallExample2')),\n h('div', { className: styles.installRow },\n h('input', {\n className: npmError ? `${styles.installInput} ${styles.installInputError}` : styles.installInput,\n type: 'text',\n placeholder: t('npmInstallPlaceholder'),\n value: npmQuery,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) => {\n setNpmQuery((e.target as HTMLInputElement).value)\n // 重新输入即清掉格式错误提示\n setNpmError('')\n },\n onKeyDown: (e: KeyboardEvent) => { if (e.key === 'Enter') submitNpm() },\n }),\n h('button', {\n className: styles.installBtn,\n type: 'button',\n disabled: npmQuery.trim() === '',\n onClick: submitNpm,\n }, t('installCliBtn')),\n ),\n // 格式错误:识别不了的包名就地说明,并给出推荐写法\n npmError ? h('div', { className: styles.installError }, npmError) : null,\n ],\n ),\n // GitHub 源码:输入仓库地址即装\n h('div', { className: enableGit ? styles.installCard : `${styles.installCard} ${styles.installCardDisabled}` },\n h('div', { className: styles.installCardHead },\n h('span', { className: styles.installLabel }, t('gitInstallLabel')),\n h('button', {\n type: 'button',\n className: styles.installHelpBtn,\n title: t('installHelp'),\n 'aria-label': t('installHelp'),\n onClick: () => setHelpFor('git'),\n }, h(HelpIcon)),\n ),\n !enableGit\n ? channelOffRow\n : [\n h('div', { className: styles.installExample }, t('gitInstallExample')),\n h('div', { className: styles.installRow },\n h('input', {\n className: gitError ? `${styles.installInput} ${styles.installInputError}` : styles.installInput,\n type: 'text',\n placeholder: t('gitInstallPlaceholder'),\n value: gitQuery,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) => {\n setGitQuery((e.target as HTMLInputElement).value)\n setGitError('')\n },\n onKeyDown: (e: KeyboardEvent) => { if (e.key === 'Enter') submitGit() },\n }),\n h('button', {\n className: styles.installBtn,\n type: 'button',\n disabled: gitQuery.trim() === '',\n onClick: submitGit,\n }, t('installCliBtn')),\n ),\n gitError ? h('div', { className: styles.installError }, gitError) : null,\n ],\n ),\n // 命令卡片:粘贴官方 dsh plugin 命令即装/即更新 —— 只认完整命令\n // (--profile 必填,可含 = 等号,动词 add/update,剥成裸目标走安装流程)\n h('div', { className: enableDsh ? styles.installCard : `${styles.installCard} ${styles.installCardDisabled}` },\n h('div', { className: styles.installCardHead },\n h('span', { className: styles.installLabel }, t('dshCmdLabel')),\n h('button', {\n type: 'button',\n className: styles.installHelpBtn,\n title: t('installHelp'),\n 'aria-label': t('installHelp'),\n onClick: () => setHelpFor('cmd'),\n }, h(HelpIcon)),\n // 一键插入 Hub 自身的更新命令:按当前 profile 拼 `dsh plugin --profile <p> update dsh-plugin`\n // 填入输入框(命令卡片被安全开关禁用时不显示,插入后也提交不了)\n enableDsh\n ? h('button', {\n type: 'button',\n className: styles.installInsertBtn,\n onClick: insertHubUpdate,\n }, t('dshCmdInsertHubUpdate'))\n : null,\n ),\n !enableDsh\n ? channelOffRow\n : [\n h('div', { className: styles.installExample }, t('dshCmdExample', { profile })),\n h('div', { className: styles.installRow },\n h('input', {\n className: cmdError ? `${styles.installInput} ${styles.installInputError}` : styles.installInput,\n type: 'text',\n placeholder: t('dshCmdPlaceholder'),\n value: cmdQuery,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) => {\n setCmdQuery((e.target as HTMLInputElement).value)\n setCmdError('')\n },\n onKeyDown: (e: KeyboardEvent) => { if (e.key === 'Enter') submitCmd() },\n }),\n h('button', {\n className: styles.installBtn,\n type: 'button',\n disabled: cmdQuery.trim() === '',\n onClick: submitCmd,\n }, t('installCliBtn')),\n ),\n cmdError ? h('div', { className: styles.installError }, cmdError) : null,\n ],\n ),\n ),\n // 帮助弹窗:点卡片标题旁的问号打开 —— 宽窗(720px)把该通道支持的命令格式整行展示,防止折行\n helpFor !== null\n ? h('div', {\n className: modal.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) setHelpFor(null) },\n },\n h('div', { className: `${modal.errorModal} ${modal.helpModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: modal.modalHead },\n h('div', { className: modal.modalTitle }, `${t(HELP_CARDS[helpFor].titleKey)} · ${t('helpModalTitle')}`),\n h('button', {\n className: modal.modalClose,\n 'aria-label': t('errorClose'),\n onClick: () => setHelpFor(null),\n }, h(CloseIcon)),\n ),\n h('div', { className: modal.modalBody },\n // 格式清单:一行一条;`命令\\t说明` 的说明跟在命令后,纯说明行以 \\t 开头\n h('div', { className: styles.helpBody },\n t(HELP_CARDS[helpFor].contentKey, { profile }).split('\\n').map((line, i) => {\n const [cmd, note] = line.split('\\t')\n return h('div', { key: i, className: styles.helpLine },\n cmd !== '' ? h('span', { className: styles.helpCmd }, cmd) : null,\n note !== undefined ? h('span', { className: styles.helpNote }, note) : null,\n )\n }),\n ),\n ),\n ),\n )\n : null,\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Compact switch used by the settings rows. Native-button based so it is\n * keyboard focusable and announces state via aria-checked; styling driven\n * by the --hub-* tokens (on = brand fill, off = neutral track).\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/Toggle.module.css'\n\nexport function Toggle({ checked, onChange, title, disabled }: {\n checked: boolean\n onChange: (next: boolean) => void\n title?: string\n disabled?: boolean\n}) {\n return h('button', {\n type: 'button',\n role: 'switch',\n 'aria-checked': checked,\n disabled,\n title,\n className: checked ? styles.toggleOn : styles.toggle,\n onClick: () => onChange(!checked),\n }, h('span', { className: styles.knob }))\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Button-style dropdown (native <select> replacement).\n *\n * The trigger is a compact toolbar button — hairline border + subtle grey\n * fill + current value + chevron — so it sits naturally next to the other\n * toolbar buttons and takes a single slot of horizontal space. Clicking\n * outside or pressing Esc closes the panel; options get a hover fill and\n * the active one a brand highlight, all driven by the --hub-* tokens.\n */\nimport { createElement as h, useEffect, useRef, useState } from 'react'\nimport type { JSX } from 'react'\nimport styles from '../../styles/Dropdown.module.css'\nimport { ChevronDownIcon } from './icons.tsx'\n\nexport interface DropdownOption<T extends string> {\n value: T\n label: string\n /** 可选计数徽标(如「已安装 12」) */\n count?: number\n}\n\ninterface DropdownProps<T extends string> {\n value: T\n options: DropdownOption<T>[]\n onChange: (value: T) => void\n title?: string\n /** 额外挂到根节点上的类名(如 margin 微调) */\n className?: string\n}\n\nexport function Dropdown<T extends string>({ value, options, onChange, title, className }: DropdownProps<T>): JSX.Element {\n const [open, setOpen] = useState(false)\n const rootRef = useRef<HTMLDivElement | null>(null)\n\n // 面板展开时:点面板外部或按 Esc 关闭。\n useEffect(() => {\n if (!open) return\n const onDoc = (e: MouseEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false)\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n document.addEventListener('mousedown', onDoc)\n document.addEventListener('keydown', onKey)\n return () => {\n document.removeEventListener('mousedown', onDoc)\n document.removeEventListener('keydown', onKey)\n }\n }, [open])\n\n const current = options.find((o) => o.value === value)\n\n return h('div', {\n className: className ? `${styles.dropdown} ${className}` : styles.dropdown,\n ref: rootRef,\n },\n h('button', {\n className: styles.dropdownBtn,\n type: 'button',\n title,\n 'aria-haspopup': 'listbox',\n 'aria-expanded': open,\n onClick: () => setOpen((v) => !v),\n },\n h('span', { className: styles.dropdownLabel }, current?.label ?? value),\n h('span', { className: open ? styles.dropdownArrowOpen : styles.dropdownArrow }, h(ChevronDownIcon)),\n ),\n open && h('div', { className: styles.dropdownPanel, role: 'listbox' },\n options.map((o) => h('button', {\n key: o.value,\n type: 'button',\n role: 'option',\n 'aria-selected': o.value === value,\n className: o.value === value ? styles.dropdownItemActive : styles.dropdownItem,\n onClick: () => {\n onChange(o.value)\n setOpen(false)\n },\n },\n h('span', { className: styles.dropdownItemLabel }, o.label),\n typeof o.count === 'number'\n ? h('span', { className: o.value === value ? styles.dropdownCountActive : styles.dropdownCount }, o.count)\n : null,\n )),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * System diagnostics list: one row per connectivity channel (npm registry /\n * GitHub API / catalog site), each with a live status badge — 200 OK in\n * green, Unreachable in red, Checking… while probing. The list runs\n * automatically when the page opens; every row is a button that re-probes\n * just that channel, so a click always yields visible feedback\n * (row pulses → badge flips → latency refreshes).\n */\nimport { createElement as h, useCallback, useEffect, useRef, useState } from 'react'\nimport styles from '../../styles/DiagnosticsView.module.css'\nimport type { EnvInfo, Translate } from '../../types.ts'\nimport { PLUGIN_VERSION } from '../../logic/constants.ts'\n\ntype ProbeKey = 'npm' | 'github' | 'catalog' | 'proxy'\n\n/** 系统版本文本:提交 Issue 时粘贴到正文,方便作者复现。 */\nfunction formatEnv(env: EnvInfo): string {\n return [\n `DSH Plugin Hub ${PLUGIN_VERSION}`,\n `DSH ${env.dshVersion ?? 'unknown'}`,\n `Node ${env.nodeVersion}`,\n `${env.platform} ${env.arch} (${env.release})`,\n `Profile ${env.profile}`,\n env.dshHome ? `Home ${env.dshHome}` : '',\n ].filter(Boolean).join('\\n')\n}\n\ninterface RowState {\n key: ProbeKey\n /** 目标地址展示(registry 地址 / github.com / dsh-plugin.org) */\n display: string\n nameKey: string\n status: 'idle' | 'running' | 'ok' | 'fail'\n ms: number | null\n statusCode: number | null\n /** 失败细分原因:'tlsRevocation' = 证书吊销检查受阻(本机 TLS 环境问题,不是网络不通) */\n reason?: string | null\n}\n\nconst INITIAL_ROWS: RowState[] = [\n // npm 行 display 初始置空:设置里未配置镜像时显示「未配置(跟随本机)」,探测结果回来再用服务端 display 覆盖\n { key: 'npm', display: '', nameKey: 'diagNpm', status: 'idle', ms: null, statusCode: null },\n { key: 'github', display: 'github.com', nameKey: 'diagGithub', status: 'idle', ms: null, statusCode: null },\n { key: 'catalog', display: '', nameKey: 'diagCatalog', status: 'idle', ms: null, statusCode: null },\n]\n\nexport function DiagnosticsView({ t, env, proxy, onCopy }: {\n t: Translate\n env: EnvInfo | null\n /** 设置里配置的 HTTP 代理地址;留空(未配置)不显示代理行 */\n proxy: string\n onCopy: (text: string) => void\n}) {\n // 代理行仅在配置了 HTTP 代理时出现:用该代理探测 github.com,验证「代理能不能把请求带出去」。\n // 未配置(留空直连)没有可验证的代理,不渲染这一行,避免无意义的诊断项。\n const [rows, setRows] = useState<RowState[]>(() => {\n const base = INITIAL_ROWS.map((r) => ({ ...r }))\n if (proxy.trim() !== '') {\n base.push({ key: 'proxy', display: proxy.trim(), nameKey: 'diagProxy', status: 'idle', ms: null, statusCode: null })\n }\n return base\n })\n /** 当前探测请求:重测/卸载时 abort 旧请求,避免乱序结果覆盖 */\n const runningRef = useRef<AbortController | null>(null)\n\n const patchRows = (key: ProbeKey | undefined, patch: Partial<RowState>) => {\n setRows((prev) => prev.map((r) => (key === undefined || r.key === key ? { ...r, ...patch } : r)))\n }\n\n /** 探测:key 缺省 = 全量串行;传 key = 只重测该通道 */\n const run = useCallback((key?: ProbeKey) => {\n runningRef.current?.abort()\n const controller = new AbortController()\n runningRef.current = controller\n patchRows(key, { status: 'running', ms: null, statusCode: null, reason: null })\n\n void (async () => {\n try {\n const res = await fetch('/dsh-plugin-hub/diagnostics', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: key === undefined ? '{}' : JSON.stringify({ key }),\n cache: 'no-store',\n signal: controller.signal,\n })\n if (!res.ok || res.body === null) throw new Error(`http ${res.status}`)\n const reader = res.body.getReader()\n const decoder = new TextDecoder()\n let buf = ''\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buf += decoder.decode(value, { stream: true })\n let nl = buf.indexOf('\\n')\n while (nl !== -1) {\n const raw = buf.slice(0, nl).trim()\n buf = buf.slice(nl + 1)\n if (raw !== '') {\n const ev = JSON.parse(raw) as { type?: string; key?: string; ms?: number | null; status?: number | null; display?: string; reason?: string | null }\n if (ev.type === 'ok' || ev.type === 'fail') {\n patchRows(ev.key as ProbeKey, {\n status: ev.type === 'ok' ? 'ok' : 'fail',\n ms: typeof ev.ms === 'number' ? ev.ms : null,\n statusCode: typeof ev.status === 'number' ? ev.status : null,\n // 服务端带出实际使用的源地址(配置镜像 → 镜像地址;未配置 → 空串)\n display: typeof ev.display === 'string' ? ev.display : '',\n // 失败细分原因:证书吊销受阻时给对症提示,而非笼统「不可达」\n reason: typeof ev.reason === 'string' ? ev.reason : null,\n })\n }\n }\n nl = buf.indexOf('\\n')\n }\n }\n } catch {\n // 连接本地服务失败:该项标记失败(被新请求 abort 的旧请求直接忽略)\n if (controller.signal.aborted) return\n patchRows(key, { status: 'fail', ms: null, statusCode: null })\n }\n })()\n }, [])\n\n // 进入页面自动全量探测一轮;卸载时中断\n useEffect(() => {\n run()\n return () => runningRef.current?.abort()\n }, [run])\n\n const anyRunning = rows.some((r) => r.status === 'running')\n const allOk = !anyRunning && rows.every((r) => r.status === 'ok')\n const anyFail = !anyRunning && rows.some((r) => r.status === 'fail')\n\n return h('div', { className: styles.panel },\n // 最顶部:系统版本 —— 复制当前宿主版本与系统信息,提 Issue 时粘贴到正文便于复现\n h('div', { className: styles.envRow },\n h('div', { className: styles.envLabel },\n h('div', { className: styles.envTitle }, t('settingsEnvSnapshot')),\n h('div', { className: styles.envDesc }, t('settingsEnvSnapshotDesc')),\n ),\n h('button', {\n type: 'button',\n className: styles.envCopyBtn,\n disabled: env === null,\n onClick: () => { if (env) onCopy(formatEnv(env)) },\n }, t('settingsEnvCopy')),\n ),\n // 头部:右侧「立即诊断」按钮,点击全量重测所有通道\n h('div', { className: styles.head },\n h('span', { className: styles.headHint }, t('diagHeadHint', { n: rows.length })),\n h('button', {\n type: 'button',\n className: styles.runBtn,\n disabled: anyRunning,\n onClick: () => run(),\n }, t('diagRunAll')),\n ),\n rows.map((r) => {\n // 证书吊销检查受阻:badge 与悬浮提示都换成对症文案,避免用户朝「网络不通」方向排查\n const revokeBlocked = r.status === 'fail' && r.reason === 'tlsRevocation'\n const badge = r.status === 'running'\n ? h('span', { className: `${styles.badge} ${styles.badgeRunning}` }, t('diagChecking'))\n : r.status === 'ok'\n ? h('span', { className: `${styles.badge} ${styles.badgeOk}` },\n r.statusCode !== null ? `HTTP ${r.statusCode} ${t('diagOk')}` : t('diagOk'))\n : r.status === 'fail'\n ? h('span', { className: `${styles.badge} ${styles.badgeFail}` },\n revokeBlocked ? t('diagFailRevocation') : t('settingsDiagFail'))\n : h('span', { className: `${styles.badge} ${styles.badgeIdle}` }, t('diagIdle'))\n return h('button', {\n key: r.key,\n type: 'button',\n className: styles.row,\n disabled: r.status === 'running',\n onClick: () => run(r.key),\n title: revokeBlocked ? t('diagFailRevocationHint') : t('diagRecheck'),\n },\n h('span', { className: styles.name }, t(r.nameKey)),\n // npm 行未配置镜像:display 为空 → 显示「未配置(跟随本机)」,不误导成官方源;\n // 目录站点行不暴露域名/API 地址,固定显示「插件市场」这一友好称呼\n h('span', { className: styles.display },\n r.key === 'catalog' ? t('diagCatalogTarget') : (r.display !== '' ? r.display : t('diagNpmUnset'))),\n h('span', { className: styles.meta }, r.status === 'ok' && r.ms !== null ? `${r.ms} ms` : ''),\n badge,\n )\n }),\n // 底部总览:全部通过 / 存在异常 / 检测中,汇总整体状态\n h('div', {\n className: `${styles.summary} ${anyRunning ? styles.summaryRunning : allOk ? styles.summaryOk : styles.summaryFail}`,\n }, anyRunning ? t('diagSummaryRunning') : allOk ? t('diagSummaryOk') : t('diagSummaryFail')),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Built-in log viewer dialog: no external software needed — the app opens\n * its own window and loads the local system log (JSONL at\n * ~/.dsh/profiles/<profile>/hub.log) straight from the server, one page at\n * a time.\n *\n * Every line is categorized twice: a function area (install / uninstall /\n * update / diagnostics / settings / system) and a severity level (debug /\n * info / success / warn / error). Filtering on both axes lets you target,\n * say, only install errors — so the exact incompatible step of an install\n * (or uninstall) is easy to spot. Search narrows by event code or message.\n *\n * Server pagination: GET /dsh-plugin-hub/logs?offset=&limit=&category=\n * &level=&query= → { entries, total, hasMore, path }. The footer shows the\n * real file location and reveals it in the system file manager.\n */\nimport { createElement as h, useCallback, useEffect, useRef, useState } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport view from '../../styles/LogsView.module.css'\nimport type { Translate } from '../../types.ts'\nimport { openLogFile } from '../../data/host.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\nimport { ConfirmDialog } from './ConfirmDialog.tsx'\n\n/** 与服务端 /logs 返回的 LogEntry 对齐的客户端投影。 */\nexport interface LogEntryView {\n /** 毫秒时间戳 */\n at: number\n level: 'debug' | 'info' | 'success' | 'warn' | 'error'\n category: 'install' | 'uninstall' | 'update' | 'diagnostics' | 'settings' | 'system'\n /** 机器可读事件码,如 install.start */\n event: string\n message: string\n}\n\nexport type LogCategoryFilter = 'all' | LogEntryView['category']\nexport type LogLevelFilter = 'all' | LogEntryView['level']\n\nconst PAGE = 100\n\n/** 类别筛选标签:值 → 语言包 key(弹窗内 chip 与行内类别徽章共用)。 */\nconst CAT_LABEL: Record<LogEntryView['category'], string> = {\n install: 'logCatInstall',\n uninstall: 'logCatUninstall',\n update: 'logCatUpdate',\n diagnostics: 'logCatDiagnostics',\n settings: 'logCatSettings',\n system: 'logCatSystem',\n}\n\nconst CAT_FILTERS: Array<{ value: LogCategoryFilter; key: string }> = [\n { value: 'all', key: 'logCatAll' },\n { value: 'install', key: 'logCatInstall' },\n { value: 'uninstall', key: 'logCatUninstall' },\n { value: 'update', key: 'logCatUpdate' },\n { value: 'diagnostics', key: 'logCatDiagnostics' },\n { value: 'settings', key: 'logCatSettings' },\n { value: 'system', key: 'logCatSystem' },\n]\n\nconst LEVEL_FILTERS: Array<{ value: LogLevelFilter; key: string }> = [\n { value: 'all', key: 'logLvAll' },\n { value: 'error', key: 'logLvError' },\n { value: 'warn', key: 'logLvWarn' },\n { value: 'success', key: 'logLvSuccess' },\n { value: 'info', key: 'logLvInfo' },\n { value: 'debug', key: 'logLvDebug' },\n]\n\n/** 级别徽章文案:弹窗 chip 与行内级别徽章共用同一语言包 key。 */\nconst LEVEL_LABEL: Record<LogEntryView['level'], string> = {\n debug: 'logLvDebug',\n info: 'logLvInfo',\n success: 'logLvSuccess',\n warn: 'logLvWarn',\n error: 'logLvError',\n}\n\n/** 时间:YYYY-MM-DD HH:mm:ss(每条都精确到秒)。 */\nexport function fmtLogTime(at: number): string {\n const d = new Date(at)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`\n}\n\n/** 导出文件名时间戳:2026-08-24_21-35-00。 */\nfunction fmtFileStamp(at: number): string {\n const d = new Date(at)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}_${pad(d.getHours())}-${pad(d.getMinutes())}-${pad(d.getSeconds())}`\n}\n\n/** 单条日志行:时间 + 级别徽章 + 类别徽章 + 事件码 + 描述。查看器弹窗与设置页预览共用。 */\nexport function LogEntryRow({ e, t }: { e: LogEntryView; t: Translate }) {\n return h('div', { className: view.entry, title: e.message },\n h('span', { className: view.time }, fmtLogTime(e.at)),\n h('span', { className: `${view.badge} ${view[`badge${e.level}`]}` }, t(LEVEL_LABEL[e.level])),\n h('span', { className: `${view.catBadge} ${view[`cat${e.category}`]}` }, t(CAT_LABEL[e.category])),\n h('span', { className: view.event }, e.event),\n h('span', { className: view.message }, e.message),\n )\n}\n\nexport function LogsModal({ t, onClose }: {\n t: Translate\n onClose: () => void\n}) {\n const [category, setCategory] = useState<LogCategoryFilter>('all')\n const [level, setLevel] = useState<LogLevelFilter>('all')\n const [query, setQuery] = useState('')\n const [entries, setEntries] = useState<LogEntryView[]>([])\n const [total, setTotal] = useState(0)\n const [hasMore, setHasMore] = useState(false)\n const [path, setPath] = useState('')\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState(false)\n const [opening, setOpening] = useState(false)\n const [openFailed, setOpenFailed] = useState(false)\n const [showClearConfirm, setShowClearConfirm] = useState(false)\n const [clearing, setClearing] = useState(false)\n const [clearFailed, setClearFailed] = useState(false)\n const offsetRef = useRef(0)\n\n /** 拉一页:过滤参数取当前 state,偏移量由调用方给出。 */\n const fetchPage = useCallback(async (offset: number): Promise<{ entries: LogEntryView[]; total: number; hasMore: boolean; path: string } | null> => {\n try {\n const qs = new URLSearchParams({ offset: String(offset), limit: String(PAGE) })\n if (category !== 'all') qs.set('category', category)\n if (level !== 'all') qs.set('level', level)\n const q = query.trim()\n if (q !== '') qs.set('query', q)\n const res = await fetch(`/dsh-plugin-hub/logs?${qs.toString()}`, { cache: 'no-store' })\n if (!res.ok) return null\n return await res.json() as { entries: LogEntryView[]; total: number; hasMore: boolean; path: string }\n } catch {\n return null\n }\n }, [category, level, query])\n\n /** 从第一页重新加载(换筛选/搜索时)。 */\n const reload = useCallback(async () => {\n setLoading(true)\n const data = await fetchPage(0)\n if (data === null) {\n setError(true)\n setLoading(false)\n return\n }\n offsetRef.current = data.entries.length\n setEntries(data.entries)\n setTotal(data.total)\n setHasMore(data.hasMore)\n if (data.path !== '') setPath(data.path)\n setError(false)\n setLoading(false)\n }, [fetchPage])\n\n /** 追加下一页(「加载更多」)。 */\n const loadMore = useCallback(async () => {\n if (loading) return\n setLoading(true)\n const data = await fetchPage(offsetRef.current)\n if (data === null) {\n setError(true)\n setLoading(false)\n return\n }\n offsetRef.current += data.entries.length\n setEntries((prev) => [...prev, ...data.entries])\n setTotal(data.total)\n setHasMore(data.hasMore)\n setLoading(false)\n }, [fetchPage, loading])\n\n // 首次进入 + 类别/级别/搜索变化(搜索 280ms 防抖)都重查第一页\n const first = useRef(true)\n useEffect(() => {\n if (first.current) {\n first.current = false\n void reload()\n return\n }\n const id = window.setTimeout(() => { void reload() }, 280)\n return () => window.clearTimeout(id)\n }, [reload])\n\n /** 在系统文件管理器中定位日志文件(服务端 spawn open)。 */\n const openFile = async () => {\n if (opening) return\n setOpening(true)\n setOpenFailed(false)\n const ok = await openLogFile()\n setOpening(false)\n if (!ok) setOpenFailed(true)\n }\n\n /** 清空所有日志:确认弹窗(独立弹出框,垃圾桶图标)确认后执行。 */\n const doClear = async () => {\n setClearing(true)\n try {\n const res = await fetch('/dsh-plugin-hub/clear-log', { method: 'POST', cache: 'no-store' })\n if (!res.ok) {\n setClearFailed(true)\n return\n }\n await reload()\n } catch {\n setClearFailed(true)\n } finally {\n setClearing(false)\n setShowClearConfirm(false)\n }\n }\n\n /** 导出:拼纯文本 → Blob → 触发浏览器下载 .log 文件 */\n const exportFile = () => {\n const text = entries.map((e) => `[${fmtLogTime(e.at)}] [${e.level}] [${e.category}] [${e.event}] ${e.message}`).join('\\n')\n if (text === '') return\n const blob = new Blob([text], { type: 'text/plain;charset=utf-8' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `dsh-plugin-hub-log-${fmtFileStamp(Date.now())}.log`\n document.body.appendChild(a)\n a.click()\n a.remove()\n URL.revokeObjectURL(url)\n }\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.errorModal} ${styles.logModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('logModalTitle')),\n h('div', { className: view.headActions },\n h('button', {\n type: 'button',\n className: view.clearBtn,\n disabled: clearing,\n title: t('logClearAllTip'),\n onClick: () => setShowClearConfirm(true),\n }, t('logClearAll')),\n ),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n // 类别筛选行:安装/卸载/更新… 功能域区分\n h('div', { className: view.filterBar },\n CAT_FILTERS.map((f) => h('button', {\n key: f.value,\n type: 'button',\n className: category === f.value ? `${view.filterChip} ${view.filterChipActive}` : view.filterChip,\n onClick: () => setCategory(f.value),\n }, t(f.key))),\n ),\n // 级别筛选行 + 搜索框:按级别区分报错与正常,便于针对性排查\n h('div', { className: view.filterBar },\n LEVEL_FILTERS.map((f) => h('button', {\n key: f.value,\n type: 'button',\n className: level === f.value ? `${view.filterChip} ${view.filterChipActive}` : view.filterChip,\n onClick: () => setLevel(f.value),\n }, t(f.key))),\n h('div', { className: view.search },\n h('input', {\n className: view.searchInput,\n type: 'search',\n value: query,\n placeholder: t('logSearchPlaceholder'),\n 'aria-label': t('logSearchPlaceholder'),\n onChange: (e) => setQuery((e.target as HTMLInputElement).value),\n }),\n ),\n ),\n h('div', { className: view.logList },\n error\n ? h('div', { className: view.empty }, t('logsLoadFail'))\n : loading && entries.length === 0\n ? h('div', { className: view.empty }, t('logsLoading'))\n : entries.length === 0\n ? h('div', { className: view.empty }, t('logEmptyFilter'))\n : entries.map((e, i) => h(LogEntryRow, { key: `${e.at}-${i}`, e, t })),\n // 分页:还有就「加载更多」,拉完了给个总数收尾\n entries.length > 0 && (hasMore\n ? h('button', {\n type: 'button',\n className: view.more,\n disabled: loading,\n onClick: () => void loadMore(),\n }, loading ? t('logsLoading') : t('logLoadMore'))\n : h('div', { className: view.moreEnd }, t('logNoMore', { n: total }))),\n ),\n ),\n // 底部:日志真实路径 + 打开文件 / 导出日志\n h('div', { className: view.foot },\n h('span', { className: view.footPath, title: path },\n `${t('logPathLabel')}: ${path === '' ? '…' : path}`),\n clearFailed\n ? h('span', { className: view.footFail }, t('logClearFailed'))\n : openFailed\n ? h('span', { className: view.footFail }, t('logOpenFileFail'))\n : h('span', { className: view.footCount }, t('logCount', { n: total })),\n h('div', { className: view.footActions },\n h('button', {\n type: 'button',\n className: view.btn,\n disabled: opening || path === '',\n title: t('logOpenFileTip'),\n onClick: () => void openFile(),\n }, t('logOpenFile')),\n h('button', {\n type: 'button',\n className: view.btn,\n disabled: entries.length === 0,\n onClick: exportFile,\n }, t('logsExport')),\n ),\n ),\n ),\n // 清空日志确认弹窗:独立弹出框(垃圾桶图标,危险操作),确认后才真正清空\n showClearConfirm && h(ConfirmDialog, {\n type: 'trash',\n title: t('logClearConfirmTitle'),\n desc: t('logClearConfirmDesc'),\n confirmLabel: t('logClearAll'),\n busy: clearing,\n busyLabel: t('logClearing'),\n t,\n onConfirm: () => void doClear(),\n onCancel: () => setShowClearConfirm(false),\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 日志存放位置弹窗:设置页不内联长表单(挡视线),点「修改」弹窗编辑。\n * 两种输入方式并存 —— 手输目录 / .log 文件路径,或点「选择目录」调系统\n * 原生文件夹对话框(服务端 spawn osascript / FolderBrowserDialog / zenity)。\n * 文本框预填当前生效位置,目录选择器也从该位置打开 —— 默认地址是动态的\n * (随用户主目录/平台变化,如 ~/.dsh/profiles/<profile>/hub.log),必须实时展示。\n * 留空或点「恢复默认」= 回到默认;保存前服务端预验证可写。\n */\nimport { createElement as h, useEffect, useState } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport view from '../../styles/LogsView.module.css'\nimport type { Translate } from '../../types.ts'\nimport { chooseLogDir } from '../../data/host.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\n\nexport function LogsPathModal({ t, defaultPath, currentPath, onSaved, onClose }: {\n t: Translate\n /** 真正默认位置(服务端动态算出的 ~/.dsh/profiles/<profile>/hub.log),跨机器/平台不同 */\n defaultPath: string\n /** 当前生效的真实路径(可能已被自定义覆盖) */\n currentPath: string\n /** 保存成功回调(写入设置;父级据此刷新生效路径与日志列表) */\n onSaved: (value: string) => void\n onClose: () => void\n}) {\n // 打开即显示当前生效位置 —— 用户一眼看到日志现在存在哪,也方便在此基础上微调\n const [draft, setDraft] = useState(currentPath)\n const [saving, setSaving] = useState(false)\n const [fail, setFail] = useState(false)\n const [browsing, setBrowsing] = useState(false)\n const [browseFail, setBrowseFail] = useState(false)\n\n // Esc 关闭:与其它弹窗交互一致\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [onClose])\n\n /** 保存:空串 = 回默认;填回默认位置同样按「未自定义」处理(设置里保持干净)。\n * 服务端预建目录验证可写,失败给出反馈。 */\n const save = async () => {\n if (saving) return\n setSaving(true)\n setFail(false)\n try {\n const value = draft.trim()\n const normalized = value === '' || value === defaultPath ? '' : value\n const res = await fetch('/dsh-plugin-hub/settings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ logPath: normalized }),\n cache: 'no-store',\n })\n if (!res.ok) {\n setFail(true)\n return\n }\n // 保存成功即关:主界面路径行随即刷新为新位置,本身就是反馈\n onSaved(normalized)\n onClose()\n } catch {\n setFail(true)\n } finally {\n setSaving(false)\n }\n }\n\n /** 选择目录:系统对话框从默认位置打开,选中路径回填输入框(仍可手改)。 */\n const browse = async () => {\n if (browsing) return\n setBrowsing(true)\n setBrowseFail(false)\n const picked = await chooseLogDir()\n setBrowsing(false)\n if (picked !== null) {\n setDraft(picked)\n setFail(false)\n } else {\n setBrowseFail(true)\n }\n }\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: { target: unknown; currentTarget: unknown }) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.modal} ${styles.modalWide}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('logPathSettingTitle')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n h('div', { className: view.pathDialog },\n h('div', { className: view.pathDialogDesc }, t('logPathSettingDesc')),\n // 手输路径 + 系统目录选择器两条路并行\n h('div', { className: view.pathDialogRow },\n h('input', {\n type: 'text',\n className: view.pathDraft,\n value: draft,\n placeholder: t('logPathPlaceholder'),\n spellCheck: false,\n onChange: (e: { currentTarget: HTMLInputElement }) => {\n setDraft(e.currentTarget.value)\n setFail(false)\n setBrowseFail(false)\n },\n }),\n h('button', {\n type: 'button',\n className: view.btn,\n disabled: browsing,\n title: t('logPathBrowse'),\n onClick: () => void browse(),\n }, browsing ? t('logPathSaving') : t('logPathBrowse')),\n ),\n // 提示 + 「恢复默认」:提示左、动作右,一行内不挤\n h('div', { className: view.pathDialogReset },\n h('span', { className: view.pathDialogHint }, t('logPathResetHint')),\n h('button', {\n type: 'button',\n className: view.linkBtn,\n onClick: () => {\n setDraft(defaultPath)\n setFail(false)\n setBrowseFail(false)\n },\n }, t('logPathReset')),\n ),\n browseFail && h('div', { className: view.footFail }, t('logPathBrowseFail')),\n fail && h('div', { className: view.footFail }, t('logPathSaveFail')),\n h('div', { className: view.pathDialogFoot },\n h('button', {\n type: 'button',\n className: view.btn,\n disabled: saving,\n onClick: onClose,\n }, t('confirmCancel')),\n h('button', {\n type: 'button',\n className: `${view.btn} ${view.btnPrimary}`,\n disabled: saving,\n onClick: () => void save(),\n }, saving ? t('logPathSaving') : t('logPathSave')),\n ),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 系统日志入口视图:不在这里堆全文,而是给出「打开日志查看器」窗口入口 +\n * 日志文件真实路径(可一键在系统文件管理器中定位)+ 最近若干条预览。\n * 完整阅读/筛选/分页在 LogsModal 内置查看器弹窗里完成 —— 无需借助任何\n * 外部软件,点击即弹出自己的窗口加载本地 JSONL 日志。\n */\nimport { createElement as h, useCallback, useEffect, useRef, useState } from 'react'\nimport styles from '../../styles/LogsView.module.css'\nimport type { Translate } from '../../types.ts'\nimport { openLogFile } from '../../data/host.ts'\nimport { LogsModal, LogEntryRow, fmtLogTime, type LogEntryView } from '../modals/LogsModal.tsx'\nimport { LogsPathModal } from '../modals/LogsPathModal.tsx'\n\n/** 设置页预览条数:只放最近一小段,给用户快速感观,完整内容进查看器。 */\nconst PREVIEW = 12\n\nexport function LogsView({ t, logPath, onLogPathSaved }: {\n t: Translate\n /** 设置里已保存的日志位置覆盖(空串 = 默认位置) */\n logPath: string\n /** 保存自定义日志位置(写入设置,服务端同时预建目录验证可写) */\n onLogPathSaved: (value: string) => void\n}) {\n const [entries, setEntries] = useState<LogEntryView[]>([])\n const [path, setPath] = useState('')\n // 真正默认位置(~/.dsh/profiles/<profile>/hub.log,跨机器/平台动态):弹窗「恢复默认」用\n const [defaultPath, setDefaultPath] = useState('')\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState(false)\n const [open, setOpen] = useState(false)\n const [opening, setOpening] = useState(false)\n const [openFailed, setOpenFailed] = useState(false)\n // 日志存放位置弹窗:点「修改」打开,手输或选目录\n const [showPathModal, setShowPathModal] = useState(false)\n const mountedRef = useRef(true)\n\n const load = useCallback(async () => {\n setLoading(true)\n try {\n const res = await fetch('/dsh-plugin-hub/logs', { cache: 'no-store' })\n if (!res.ok) throw new Error(`http ${res.status}`)\n const data = await res.json() as { entries: LogEntryView[]; path: string; defaultPath?: string }\n if (mountedRef.current) {\n setEntries(data.entries)\n if (data.path !== '') setPath(data.path)\n if (data.defaultPath !== undefined) setDefaultPath(data.defaultPath)\n setError(false)\n }\n } catch {\n if (mountedRef.current) setError(true)\n } finally {\n if (mountedRef.current) setLoading(false)\n }\n }, [])\n\n useEffect(() => {\n mountedRef.current = true\n void load()\n return () => { mountedRef.current = false }\n }, [load])\n\n /** 导出:拼纯文本 → Blob → 触发浏览器下载 .log 文件 */\n const exportFile = () => {\n const text = entries.map((e) => `[${fmtLogTime(e.at)}] [${e.level}] [${e.category}] [${e.event}] ${e.message}`).join('\\n')\n if (text === '') return\n const blob = new Blob([text], { type: 'text/plain;charset=utf-8' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'dsh-plugin-hub-log.log'\n document.body.appendChild(a)\n a.click()\n a.remove()\n URL.revokeObjectURL(url)\n }\n\n /** 在系统文件管理器中定位日志文件。 */\n const openFile = async () => {\n if (opening) return\n setOpening(true)\n setOpenFailed(false)\n const ok = await openLogFile()\n setOpening(false)\n if (!ok) setOpenFailed(true)\n }\n\n const preview = entries.slice(0, PREVIEW)\n return h('div', { className: styles.panel },\n h('div', { className: styles.head },\n h('span', { className: styles.headHint }, t('logsHeadHint')),\n h('div', { className: styles.actions },\n h('button', {\n type: 'button',\n className: styles.btn,\n onClick: () => setOpen(true),\n }, t('logViewerOpen')),\n h('button', { type: 'button', className: styles.btn, disabled: entries.length === 0, onClick: exportFile }, t('logsExport')),\n h('button', { type: 'button', className: styles.btn, disabled: loading, onClick: () => void load() }, t('logsRefresh')),\n ),\n ),\n // 日志存放位置:一行展示真实路径 + 「修改」弹窗编辑(手输 / 选目录)+ 一键定位文件\n h('div', { className: styles.pathRow },\n h('span', { className: styles.pathLabel }, t('logPathSettingTitle')),\n h('span', { className: styles.pathText, title: path }, path === '' ? '…' : path),\n openFailed && h('span', { className: styles.footFail }, t('logOpenFileFail')),\n h('button', {\n type: 'button',\n className: styles.btn,\n onClick: () => setShowPathModal(true),\n }, t('logPathChange')),\n h('button', {\n type: 'button',\n className: styles.btn,\n disabled: opening || path === '',\n title: t('logOpenFileTip'),\n onClick: () => void openFile(),\n }, t('logOpenFile')),\n ),\n error\n ? h('div', { className: styles.empty }, t('logsLoadFail'))\n : loading && entries.length === 0\n ? h('div', { className: styles.empty }, t('logsLoading'))\n : entries.length === 0\n ? h('div', { className: styles.empty }, t('logsEmpty'))\n : h('div', { className: styles.list },\n preview.map((e, i) => h('button', {\n key: `${e.at}-${i}`,\n type: 'button',\n className: styles.previewRow,\n onClick: () => setOpen(true),\n title: t('logViewerOpen'),\n }, h(LogEntryRow, { e, t }))),\n ),\n open && h(LogsModal, { t, onClose: () => setOpen(false) }),\n showPathModal && h(LogsPathModal, {\n t,\n defaultPath,\n currentPath: path,\n onSaved: (v: string) => {\n onLogPathSaved(v)\n void load() // 刷新生效路径与最近日志(新位置若已写入则立即可见)\n },\n onClose: () => setShowPathModal(false),\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Settings view: desktop-settings navigation — a fixed left sidebar lists\n * the sections (icon + label, click to switch), the right pane shows the\n * active section's rows. New settings only add rows, new areas only add a\n * sidebar entry.\n *\n * Sections mirror what the local server actually enforces:\n * Updates & Sources — startup update check / npm mirror / HTTP proxy\n * (all wired into the install command path)\n * Security & Trust — restricted custom installs (server 403 gate)\n * Diagnostics — live connectivity probe + environment snapshot\n * Logs — system log viewer + storage location\n */\nimport { createElement as h, useEffect, useRef, useState } from 'react'\nimport type { ChangeEvent, MouseEvent, ReactNode } from 'react'\nimport styles from '../../styles/SettingsView.module.css'\nimport dropdownStyles from '../../styles/Dropdown.module.css'\nimport modalStyles from '../../styles/Modal.module.css'\nimport { Toggle } from '../ui/Toggle.tsx'\nimport { Dropdown } from '../ui/Dropdown.tsx'\nimport { DiagnosticsView } from './DiagnosticsView.tsx'\nimport { LogsView } from './LogsView.tsx'\nimport {\n CloseIcon, ConfirmIcon, DiagnosticsIcon, LogsIcon, ResetIcon, SecurityIcon, UpdatesIcon,\n} from '../ui/icons.tsx'\nimport type { EnvInfo, Translate } from '../../types.ts'\nimport type { HubSettings } from '../../hooks/useSettings.ts'\n\n/** 设置分组导航 key:顺序即展示顺序。导出供外部(如错误弹窗「去系统诊断」)跳转指定分组。 */\nexport type SettingsSection = 'updates' | 'security' | 'diagnostics' | 'logs' | 'reset'\n\n/** npm 镜像源预设:空串 = 未配置(跟随用户本机 npm 配置,本插件不注入任何 registry)。\n * 只提供常见国内顶级镜像下拉,不做自定义输入 —— 想用其它镜像直接在 ~/.npmrc 配置即可。 */\nconst MIRROR_PRESETS: Array<{ value: string; labelKey: string }> = [\n { value: '', labelKey: 'mirrorNone' },\n { value: 'https://registry.npmjs.org', labelKey: 'mirrorOfficial' },\n { value: 'https://registry.npmmirror.com', labelKey: 'mirrorNpmmirror' },\n { value: 'https://mirrors.cloud.tencent.com/npm/', labelKey: 'mirrorTencent' },\n { value: 'https://mirrors.tuna.tsinghua.edu.cn/npm/', labelKey: 'mirrorTsinghua' },\n]\n\n/** 左侧导航:顺序即展示顺序;labelKey 是分组标题,icon 是行内小图标。 */\nconst NAV: Array<{ key: SettingsSection; labelKey: string; icon: () => ReturnType<typeof h> }> = [\n { key: 'updates', labelKey: 'settingsUpdate', icon: UpdatesIcon },\n { key: 'security', labelKey: 'settingsSecurity', icon: SecurityIcon },\n { key: 'diagnostics', labelKey: 'settingsDiagnostics', icon: DiagnosticsIcon },\n { key: 'logs', labelKey: 'settingsLogs', icon: LogsIcon },\n { key: 'reset', labelKey: 'settingsReset', icon: ResetIcon },\n]\n\n/** 设置行:默认标签左控件右;stack=true 时控件独占一行(文本框整行显示),hairline 分隔。 */\nfunction SettingRow({ title, desc, children, stack = false }: {\n title: string\n desc?: string\n children: ReactNode\n stack?: boolean\n}) {\n return h('div', { className: stack ? styles.settingRowStack : styles.settingRow },\n h('div', { className: styles.settingLabel },\n h('div', { className: styles.settingTitle }, title),\n desc ? h('div', { className: styles.settingDesc }, desc) : null,\n ),\n h('div', { className: stack ? styles.settingControlStack : styles.settingControl }, children),\n )\n}\n\nexport function SettingsView({ t, settings, update, reset, env, onCopy, openSection, onConsumedOpenSection }: {\n t: Translate\n settings: HubSettings\n update: (patch: Partial<HubSettings>) => void\n reset: () => void\n env: EnvInfo | null\n onCopy: (text: string) => void\n /** 外部跳转信号(如错误弹窗「去系统诊断」):非空时切到对应分组,消费后通过 onConsumedOpenSection 清空 */\n openSection?: SettingsSection | null\n onConsumedOpenSection?: () => void\n}) {\n /** 当前激活的分组:左侧导航点击切换,右侧只渲染这一组 */\n const [section, setSection] = useState<SettingsSection>('updates')\n /** 恢复默认确认弹窗:点按钮先弹窗询问,确认后才真正 reset(不做两段式按钮) */\n const [resetConfirm, setResetConfirm] = useState(false)\n\n // 外部跳转(错误弹窗「去系统诊断」→ 设置 → 系统诊断):切到对应分组并清空信号,避免下次进入设置被强制带跳\n useEffect(() => {\n if (!openSection) return\n setSection(openSection)\n onConsumedOpenSection?.()\n }, [openSection, onConsumedOpenSection])\n\n // —— HTTP 代理连通性:输入停笔后防抖实时探测(服务端 /proxy-check 用该代理打 github.com)。\n // 结果只作提示、绝不阻断保存 —— 用户可能是先填地址后开代理,保存后再去开代理完全合法。\n const [proxyProbe, setProxyProbe] = useState<'idle' | 'checking' | 'ok' | 'fail'>('idle')\n // 失败细分原因(如 'tlsRevocation'):证书吊销受阻时提示「不是代理地址不通」,避免误导排查方向\n const [proxyProbeReason, setProxyProbeReason] = useState<string | null>(null)\n const proxyProbeTimer = useRef<number | null>(null)\n const proxyProbeSeq = useRef(0)\n // 卸载时清掉未触发的防抖计时器,避免卸载后 setState\n useEffect(() => () => {\n if (proxyProbeTimer.current !== null) window.clearTimeout(proxyProbeTimer.current)\n proxyProbeSeq.current += 1\n }, [])\n // 设置被外部重置(恢复默认/清空代理)时同步清掉探测状态,避免残留过期的「不通」提示\n useEffect(() => {\n if (settings.proxy === '') { setProxyProbe('idle'); setProxyProbeReason(null) }\n }, [settings.proxy])\n\n const probeProxyNow = (value: string) => {\n const v = value.trim()\n if (v === '') { setProxyProbe('idle'); setProxyProbeReason(null); return }\n const seq = ++proxyProbeSeq.current\n setProxyProbe('checking')\n setProxyProbeReason(null)\n void fetch('/dsh-plugin-hub/proxy-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ proxy: v }),\n cache: 'no-store',\n }).then((res) => res.json())\n .then((data: { ok?: boolean; reason?: string | null }) => {\n if (seq !== proxyProbeSeq.current) return\n setProxyProbe(data.ok ? 'ok' : 'fail')\n setProxyProbeReason(typeof data.reason === 'string' ? data.reason : null)\n })\n .catch(() => {\n if (seq !== proxyProbeSeq.current) return\n setProxyProbe('fail')\n setProxyProbeReason(null)\n })\n }\n\n const onProxyChange = (e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n // 保存照常:留空直连、填了就走该代理(先填后开代理也允许,仅提示不通)\n update({ proxy: value })\n if (proxyProbeTimer.current !== null) window.clearTimeout(proxyProbeTimer.current)\n // 停笔 700ms 再探测,避免每敲一个字符都发请求\n proxyProbeTimer.current = window.setTimeout(() => probeProxyNow(value), 700)\n }\n const onMirrorChange = (value: string) => update({ npmRegistry: value })\n\n /** 每个分组的页面副标题(导航标题之上再补一句说明,保持桌面设置质感) */\n const pageDesc: Record<SettingsSection, string> = {\n updates: t('settingsUpdateDesc'),\n security: t('settingsSecurityDesc'),\n diagnostics: t('settingsDiagnosticsDesc'),\n logs: t('settingsLogsDesc'),\n reset: t('settingsResetDesc'),\n }\n const activeNav = NAV.find((n) => n.key === section) ?? NAV[0]\n\n // —— 各分组的设置卡片(一页一个 card,内部一行一设置) ——\n\n const updatesCard = h('div', { className: styles.card },\n h(SettingRow, {\n title: t('settingsCheckOnStart'),\n desc: t('settingsCheckOnStartDesc'),\n children: h(Toggle, {\n checked: settings.checkUpdatesOnStart,\n onChange: (v) => update({ checkUpdatesOnStart: v }),\n title: t('settingsCheckOnStart'),\n }),\n }),\n // npm 镜像源:预设下拉(默认未配置跟随本机),选国内顶级镜像可加速安装;\n // 不做自定义输入,其它镜像写在 ~/.npmrc 即可被天然尊重。\n // 独占一行(同代理文本框):标签在上、下拉在下整行展开,长描述不会挤压控件\n h(SettingRow, {\n title: t('settingsMirror'),\n desc: t('settingsMirrorDesc'),\n stack: true,\n children: h(Dropdown, {\n value: settings.npmRegistry,\n options: MIRROR_PRESETS.map((m) => ({ value: m.value, label: t(m.labelKey) })),\n onChange: onMirrorChange,\n title: t('settingsMirror'),\n className: `${styles.controlDropdown} ${dropdownStyles.dropdownFill}`,\n }),\n }),\n // 代理地址:文本框独占一行,整行输入,便于粘贴长代理地址;停笔后实时探测连通性,\n // 不通仅提示(可保存)—— 用户可能先填地址后开代理\n h(SettingRow, {\n title: t('settingsProxy'),\n desc: t('settingsProxyDesc'),\n stack: true,\n children: h('div', { className: styles.proxyControl },\n h('input', {\n className: styles.textInput,\n type: 'text',\n value: settings.proxy,\n placeholder: 'http://127.0.0.1:7890',\n spellCheck: false,\n onChange: onProxyChange,\n }),\n proxyProbe === 'checking'\n ? h('div', { className: styles.proxyHint }, t('proxyCheckChecking'))\n : proxyProbe === 'ok'\n ? h('div', { className: `${styles.proxyHint} ${styles.proxyHintOk}` }, t('proxyCheckOk'))\n : proxyProbe === 'fail'\n ? h('div', { className: `${styles.proxyHint} ${styles.proxyHintFail}` },\n proxyProbeReason === 'tlsRevocation' ? t('proxyCheckRevocation') : t('proxyCheckFail'))\n : null,\n ),\n }),\n )\n\n const securityCard = h('div', { className: styles.card },\n // 安全与信任:命令行安装的三个通道开关(NPM 包 / GitHub 源码 / DSH 命令)——\n // 服务端按通道门禁 403 拦截(npm 目标吃 enableNpmInstall、git 目标吃 enableGitInstall),\n // DSH 命令框为纯客户端通道:关掉后命令输入卡片禁用并引导去设置打开;\n // 目录内收录的插件安装不受影响(默认全部开启)\n h(SettingRow, {\n title: t('settingsEnableNpm'),\n desc: t('settingsEnableNpmDesc'),\n children: h(Toggle, {\n checked: settings.enableNpmInstall,\n onChange: (v) => update({ enableNpmInstall: v }),\n title: t('settingsEnableNpm'),\n }),\n }),\n h(SettingRow, {\n title: t('settingsEnableGit'),\n desc: t('settingsEnableGitDesc'),\n children: h(Toggle, {\n checked: settings.enableGitInstall,\n onChange: (v) => update({ enableGitInstall: v }),\n title: t('settingsEnableGit'),\n }),\n }),\n h(SettingRow, {\n title: t('settingsEnableDsh'),\n desc: t('settingsEnableDshDesc'),\n children: h(Toggle, {\n checked: settings.enableDshInstall,\n onChange: (v) => update({ enableDshInstall: v }),\n title: t('settingsEnableDsh'),\n }),\n }),\n )\n\n const diagnosticsCard = h('div', { className: styles.card },\n // 系统版本(最顶部)+ 通道状态列表:进入页面自动探测一轮,整行可点击重测单项,实时反馈\n h(DiagnosticsView, { t, env, proxy: settings.proxy, onCopy }),\n )\n\n const logsCard = h('div', { className: styles.card },\n // 系统日志列表:操作记录(安装/卸载/设置/诊断),可刷新/复制/导出,点击弹窗查看;\n // 日志存放位置可设置(留空用默认),改动会写入设置并立即生效\n h(LogsView, {\n t,\n logPath: settings.logPath,\n onLogPathSaved: (v: string) => update({ logPath: v }),\n }),\n )\n\n const resetCard = h('div', { className: styles.card },\n h(SettingRow, {\n title: t('settingsReset'),\n desc: t('settingsResetDetail'),\n children: h('button', {\n type: 'button',\n className: styles.resetBtn,\n onClick: () => setResetConfirm(true),\n }, t('settingsResetRun')),\n }),\n )\n\n return h('div', { className: styles.root },\n // 左侧导航:固定宽度菜单栏,图标 + 名称,点击切换右侧内容\n h('nav', { className: styles.sidebar, 'aria-label': t('viewSettings') },\n NAV.map((item) => h('button', {\n key: item.key,\n type: 'button',\n className: section === item.key ? styles.navItemActive : styles.navItem,\n onClick: () => setSection(item.key),\n 'aria-current': section === item.key ? 'page' : undefined,\n title: t(item.labelKey),\n },\n h('span', { className: styles.navIcon }, h(item.icon)),\n h('span', { className: styles.navLabel }, t(item.labelKey)),\n )),\n ),\n // 右侧内容:只渲染当前分组,独立滚动\n h('div', { className: styles.content },\n h('div', { className: styles.pageHeader },\n h('div', { className: styles.pageTitle }, t(activeNav.labelKey)),\n h('div', { className: styles.pageDesc }, pageDesc[section]),\n ),\n section === 'updates' ? updatesCard\n : section === 'security' ? securityCard\n : section === 'diagnostics' ? diagnosticsCard\n : section === 'logs' ? logsCard\n : resetCard,\n ),\n // 恢复默认确认弹窗:点「恢复默认」先弹窗确认,确认后才真正 reset(替代两段式按钮)\n resetConfirm && h('div', {\n className: modalStyles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) setResetConfirm(false) },\n },\n h('div', { className: modalStyles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: modalStyles.modalHead },\n h('div', { className: modalStyles.modalTitle }, t('settingsReset')),\n h('button', {\n className: modalStyles.modalClose,\n type: 'button',\n 'aria-label': t('errorClose'),\n onClick: () => setResetConfirm(false),\n }, h(CloseIcon)),\n ),\n h('div', { className: modalStyles.modalBody },\n // 恢复默认 = 破坏性操作:红色警告三角图标,醒目提示风险\n h('div', { className: modalStyles.confirmIconWrap },\n h(ConfirmIcon, { type: 'warning' }),\n ),\n h('div', { className: modalStyles.failPrepareHint }, t('settingsResetConfirmDetail')),\n h('div', { className: modalStyles.modalActions },\n h('button', {\n className: modalStyles.restartLater,\n type: 'button',\n onClick: () => setResetConfirm(false),\n }, t('cancel')),\n h('button', {\n className: modalStyles.restartNowWarning,\n type: 'button',\n onClick: () => { setResetConfirm(false); reset() },\n }, t('settingsResetConfirm')),\n ),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Plugin Hub section: wires the catalog data pipeline, the background task\n * queue and the feedback state together. Data/queue logic lives in hooks/,\n * rendering is delegated to the small presentational components in this\n * folder; it hosts the dialogs/toast and the section-level copy actions.\n */\nimport { createElement as h, useEffect, useRef, useState } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../styles/Header.module.css'\nimport modalStyles from '../styles/Modal.module.css'\nimport type { EnvInfo, HubPlugin, InstallChannel, SectionProps, ToastState } from '../types.ts'\nimport { installCommandOf, repoFromInstallTarget } from '../logic/install-command.ts'\nimport { PLUGIN_VERSION } from '../logic/constants.ts'\nimport { ensurePluginCss } from '../logic/ensure-plugin-css.ts'\nimport { getEnv, revealInstallFolder } from '../data/host.ts'\nimport { useCatalog } from '../hooks/useCatalog.ts'\nimport { useLanguage } from '../hooks/useLanguage.ts'\nimport { useSettings } from '../hooks/useSettings.ts'\nimport { useTaskQueue } from '../hooks/useTaskQueue.ts'\nimport { ErrorModal, InstallModal, RestartConfirmModal, UninstallModal, Toast } from './modals/modals.tsx'\nimport { AboutModal } from './modals/AboutModal.tsx'\nimport { HubUpdateModal } from './modals/HubUpdateModal.tsx'\nimport { InstalledDetailModal } from './modals/InstalledDetailModal.tsx'\nimport { NotificationsModal } from './modals/NotificationsModal.tsx'\nimport { addFailure, addSuccess, addUpdateNotice, clearNotifications, ignoreUpdate, loadIgnoredUpdates, loadNotifications, removeNotification, removeUpdateNotice } from '../logic/failures.ts'\nimport type { NotificationRecord } from '../logic/failures.ts'\nimport { CatalogHeader } from './layout/CatalogHeader.tsx'\nimport { MarketView } from './views/MarketView.tsx'\nimport { SectionTabs } from './layout/SectionTabs.tsx'\nimport type { SectionView } from './layout/SectionTabs.tsx'\nimport { InstalledView } from './views/InstalledView.tsx'\nimport { CustomInstallView } from './views/CustomInstallView.tsx'\nimport { SettingsView } from './views/SettingsView.tsx'\nimport type { SettingsSection } from './views/SettingsView.tsx'\nimport { CloseIcon, ConfirmIcon } from './ui/icons.tsx'\nimport type { InstalledItem } from '../logic/installed.ts'\nimport { issueRepoOf, pluginOfItem } from '../logic/installed.ts'\n\nexport function PluginHubSection({ t: _hostT, locale }: SectionProps) {\n const { lang, langKey, langPath, t, toggleLang } = useLanguage(locale)\n const catalog = useCatalog(lang)\n /** 设置状态:服务端 hub-settings.json 持久化,本地乐观更新即时生效 */\n const { settings: hubSettings, ready: settingsReady, update: updateSettings, reset: resetSettings } = useSettings()\n\n /** 一级导航:插件市场 / 已安装 / 自定义安装 / 设置 */\n const [view, setView] = useState<SectionView>('market')\n /** 外部跳转设置分组的一次性信号(错误弹窗「去系统诊断」→ 设置 → 系统诊断):\n * 传给 SettingsView 消费后即清空,避免下次进设置被强制带跳 */\n const [settingsSection, setSettingsSection] = useState<SettingsSection | null>(null)\n /** 网络不通提示的「去系统诊断」直达:关掉所有弹窗(错误/通知/安装确认进度等,\n * 否则 InstallModal 失败后仍停驻原地盖住设置页)→ 切到设置页 → 切到系统诊断分组(自动跑连通性检测) */\n const openDiagnostics = () => {\n setErrorMsg(null)\n setShowNotifications(false)\n setConfirmPlugin(null)\n setConfirmCustomTarget(null)\n setConfirmGlobalNpm(null)\n setUninstallPlugin(null)\n setUninstallItem(null)\n setDetailItem(null)\n setShowHubUpdate(false)\n setShowAbout(false)\n setIgnoreTarget(null)\n setShowRestartConfirm(false)\n setView('settings')\n setSettingsSection('diagnostics')\n }\n\n /** 全局反馈 Toast:{id} 用于重复触发时重新走入场动画,kind 决定文案与配色 */\n const [toast, setToast] = useState<ToastState | null>(null)\n /** 复制反馈:记录刚复制安装命令的仓库,按钮短暂切换为「已复制」样式 */\n const [copied, setCopied] = useState<string | null>(null)\n /** 信任确认弹窗:记录待安装的插件,确认后才执行复制 */\n const [confirmPlugin, setConfirmPlugin] = useState<HubPlugin | null>(null)\n /** 弹窗动作是否为「更新」:已安装插件点「更新」→ 走同一条 add 命令原位覆盖重装,文案区分安装/更新 */\n const [confirmIsUpdate, setConfirmIsUpdate] = useState(false)\n /** 命令行安装确认弹窗:记录待安装的裸目标(npm 包名 / GitHub 地址,DSH 命令已剥成裸目标)——\n * 与应用商店同一套确认/进度/结果弹窗,提供时 plugin 传 null 走 customTarget 模式 */\n const [confirmCustomTarget, setConfirmCustomTarget] = useState<string | null>(null)\n /** 自定义安装入口渠道(三张卡片之一):随确认弹窗记录,提交时上报服务端,\n * 报错/日志据此精准溯源「从哪个入口发起」(npm 全局安装固定为 'npm') */\n const [confirmCustomChannel, setConfirmCustomChannel] = useState<InstallChannel | null>(null)\n /** 全局 npm 安装确认弹窗(官方 `npm install -g <pkgs>`):记录原始命令 + 解析出的包列表,\n * 走与应用商店同一套确认/进度/结果弹窗(plugin 传 null,InstallModal 走 globalNpm 模式) */\n const [confirmGlobalNpm, setConfirmGlobalNpm] = useState<{ raw: string; pkgs: string[] } | null>(null)\n /** Hub 自我更新说明弹窗:点「可更新」徽标先展示版本 + Markdown 变更记录,确认后再进安装弹窗 */\n const [showHubUpdate, setShowHubUpdate] = useState(false)\n /** 「关注我们」弹窗:GitHub 图标后按钮点击打开,展示平台介绍 + 用户反馈群二维码(Worker /about 推送) */\n const [showAbout, setShowAbout] = useState(false)\n /** 卸载确认弹窗:记录待卸载的插件(目录内) */\n const [uninstallPlugin, setUninstallPlugin] = useState<HubPlugin | null>(null)\n /** 卸载确认弹窗:记录待卸载的已安装项(自定义安装无目录数据,按包名直卸) */\n const [uninstallItem, setUninstallItem] = useState<InstalledItem | null>(null)\n /** 已安装详情弹窗:记录当前查看的已安装项(行点击 / 详情按钮打开) */\n const [detailItem, setDetailItem] = useState<InstalledItem | null>(null)\n /** 待重启确认弹窗:已安装列表行内「重启」先弹「立即重启 / 稍后重启」确认(与通知中心一致),\n * 确认后才真正触发宿主重启,避免误触 */\n const [showRestartConfirm, setShowRestartConfirm] = useState(false)\n /** 安装/卸载完成后的结果视图:停留弹窗内,点「完成」关闭 */\n const [installDone, setInstallDone] = useState(false)\n const [uninstallDone, setUninstallDone] = useState(false)\n /** 结果视图是否给「立即重启」:服务端任务终态带出(卸载时 loader 已即时移除 → false 只给「完成」;\n * true 时通知中心待重启条目同步常驻,直到用户点「立即重启」真正重启后才消失) */\n const [installNeedsRestart, setInstallNeedsRestart] = useState(true)\n const [uninstallNeedsRestart, setUninstallNeedsRestart] = useState(true)\n /** 结果视图「立即重启」:请求宿主重启后进入等待,服务回来后整页刷新 */\n const [restarting, setRestarting] = useState(false)\n /** 操作失败完整信息 + 所属插件仓库 + 失败类型(决定弹窗标题「安装失败/卸载失败」)+ 实际执行的安装命令 + 尝试过的安装方式(issue 预填用) */\n const [errorMsg, setErrorMsg] = useState<{ message: string; repo: string | null; kind: 'install' | 'uninstall'; command?: string; attempts?: string[] } | null>(null)\n /** 通知中心记录:localStorage 持久化,每次安装/卸载任务成败都留痕(启动时读回) */\n const [notifications, setNotifications] = useState<NotificationRecord[]>(() => loadNotifications())\n /** 通知中心弹窗:一级导航「设置」tab 后边的铃铛入口按钮打开 */\n const [showNotifications, setShowNotifications] = useState(false)\n /** 「忽略本次更新」确认弹窗:{ repo, version };null = 关闭 */\n const [ignoreTarget, setIgnoreTarget] = useState<{ repo: string; version?: string } | null>(null)\n /** 宿主机器环境快照:提交 bug 的 issue 正文附带;取不到为 null(链接少环境段,不阻塞) */\n const [env, setEnv] = useState<EnvInfo | null>(null)\n useEffect(() => {\n let alive = true\n void getEnv().then((info) => { if (alive) setEnv(info) })\n return () => { alive = false }\n }, [])\n\n // 样式自愈:宿主重启/热更可能移除 <style> 标签而模块缓存未失效(factory 不重跑、CSS 不回来)。\n // 挂载与每次切换视图时比对全局 CSS 清单,把缺失的样式补注入回去 —— 用户无需再手动点击恢复。\n useEffect(() => { ensurePluginCss() }, [view])\n\n const queue = useTaskQueue({\n t,\n // 界面语言带给服务端:网络预检等错误消息按用户语言提示(中文界面给中文,英文界面给英文)\n langKey,\n refreshInstalled: catalog.refreshInstalled,\n onInstallDone: (viaModal, repo, needsRestart, update) => {\n setInstallNeedsRestart(needsRestart)\n if (viaModal) setInstallDone(true)\n else setToast({ id: Date.now(), kind: 'done' })\n // 安装成功也写入通知记录:通知中心里成功与失败都能看到。\n // action 区分「安装成功」与「更新成功」(更新 = 覆盖重装,同一执行通道)\n setNotifications(addSuccess({ kind: 'install', action: update ? 'update' : 'install', repo: repo ?? '' }))\n },\n onUninstallDone: (viaModal, repo, needsRestart) => {\n setUninstallNeedsRestart(needsRestart)\n if (viaModal) setUninstallDone(true)\n else setToast({ id: Date.now(), kind: 'removed' })\n setNotifications(addSuccess({ kind: 'uninstall', repo: repo ?? '' }))\n },\n onError: (message, repo, kind, command, attempts, update) => {\n // 提 Issue 目标先反查仓库身份:npm 包名能在已安装表/目录里反查到 owner/repo 才保留,\n // 反查不到置 null —— 错误弹窗据此不显示「一键提 Issue」按钮(防提到错误仓库)\n const issueRepo = issueRepoOf(repo ?? '', catalog.installedItems, catalog.plugins)\n setErrorMsg({ message, repo: issueRepo, kind, command, attempts })\n // 失败自动写入通知记录:任务在后台结束时没人盯着也能留痕。\n // 存原始 repo(可能只是裸包名)而非反查结果 —— 反查只服务于提 Issue,\n // 通知中心的展示反查由 NotificationsModal 做、查不到会回退显示原始值,\n // 若这里就丢掉原始值,通知里会连名字都看不到;action 区分「安装失败/更新失败」\n setNotifications(addFailure({ kind, action: update ? 'update' : 'install', repo: repo ?? '', message, command, attempts }))\n },\n installPlugin: confirmPlugin,\n installCustomTarget: confirmCustomTarget,\n installGlobalTarget: confirmGlobalNpm ? confirmGlobalNpm.pkgs.join(' ') : null,\n uninstallPlugin,\n uninstallName: uninstallItem ? uninstallItem.name : null,\n installedName: catalog.installedName,\n // 待重启项展示信息补齐:从目录按 owner/repo 解析插件简介/版本(找不到返回 null,行内只显示仓库名)\n resolvePending: (repo) => {\n const p = catalog.plugins?.find((x) => x.source?.repo === repo)\n return p ? { desc: p.description, version: p.version } : null\n },\n })\n\n /** 补齐更新提醒:把「当前有更新但通知中心还没有」的插件补写进通知(repo+version 去重)。\n * 返回本次实际新增的条数(0 = 无可更新或全部已提示过)。启动检查与打开通知中心共用,\n * 保证通知中心始终反映可更新状态:同一版本只一条、清空/删除后重开恢复、更新完成后消失。 */\n const syncUpdateNotices = (): number => {\n const updatable = catalog.installedItems.filter((i) => i.hasUpdate && i.plugin)\n if (updatable.length === 0) return 0\n const known = new Set(loadIgnoredUpdates())\n // 已忽略(repo+version 持久化)与通知中心已有的更新提醒都不再补写:\n // 忽略本次版本后不再提醒,直到下一个新版本(version 变化)才重新提示\n for (const r of loadNotifications()) {\n if (r.kind === 'update') known.add(`${r.repo}@${r.version ?? ''}`)\n }\n const fresh = updatable.filter((item) =>\n item.repo !== null && !known.has(`${item.repo}@${item.catalogVersion ?? ''}`))\n if (fresh.length === 0) return 0\n for (const item of fresh) {\n if (item.repo) addUpdateNotice({ kind: 'update', repo: item.repo, version: item.catalogVersion ?? undefined })\n }\n setNotifications(loadNotifications())\n return fresh.length\n }\n\n // 启动更新策略:目录数据与设置都就绪后触发一次 —— 开启「启动时检查更新」→ 发现可更新插件\n // 即写入通知中心(每条一条,点击可去更新),不弹窗打扰,由通知中心红点提示。\n // 绝不自动安装:是否更新完全由用户决定。\n // ref 守卫保证只跑一次,后续目录刷新/设置变化不会重复打扰。\n const startupCheckedRef = useRef(false)\n useEffect(() => {\n if (startupCheckedRef.current) return\n if (!settingsReady || catalog.plugins === null || catalog.failed) return\n startupCheckedRef.current = true\n if (!hubSettings.checkUpdatesOnStart) return\n syncUpdateNotices()\n }, [settingsReady, hubSettings, catalog.plugins, catalog.failed, catalog.installedItems, queue])\n\n // 信任/卸载/更新说明弹窗打开时按 Esc 关闭;任务进入后台队列后可随时关闭(任务继续)\n useEffect(() => {\n if (!confirmPlugin && !confirmCustomTarget && !confirmGlobalNpm && !uninstallPlugin && !uninstallItem && !detailItem && !showHubUpdate && !showAbout && !showNotifications && !ignoreTarget) return\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setConfirmPlugin(null)\n setConfirmCustomTarget(null)\n setConfirmCustomChannel(null)\n setConfirmGlobalNpm(null)\n setUninstallPlugin(null)\n setUninstallItem(null)\n setDetailItem(null)\n setUninstallDone(false)\n setShowHubUpdate(false)\n setShowAbout(false)\n setShowNotifications(false)\n setIgnoreTarget(null)\n }\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [confirmPlugin, confirmCustomTarget, uninstallPlugin, uninstallItem, detailItem, showHubUpdate, showAbout, showNotifications, ignoreTarget])\n\n // Toast 统一自动消失\n useEffect(() => {\n if (!toast) return\n const timer = window.setTimeout(() => setToast(null), 2400)\n return () => window.clearTimeout(timer)\n }, [toast])\n\n /** 复制文本到剪贴板,返回是否成功(Clipboard API + 隐藏 textarea 兜底)。 */\n const doCopy = async (text: string): Promise<boolean> => {\n try {\n await navigator.clipboard.writeText(text)\n return true\n } catch {\n // Clipboard API unavailable (permissions/iframe) — fall back to the\n // legacy hidden-textarea trick, which works in any context.\n const ta = document.createElement('textarea')\n ta.value = text\n ta.style.position = 'fixed'\n ta.style.opacity = '0'\n document.body.appendChild(ta)\n ta.select()\n let ok = false\n try {\n ok = document.execCommand('copy')\n } catch {\n ok = false\n }\n document.body.removeChild(ta)\n return ok\n }\n }\n\n /** 命令行安装目标是否已安装(与服务端 already 判定同口径):GitHub 地址按仓库身份匹配\n * (归一化后比对已装项的 repo/spec),npm 包名按依赖 key 直查。命中 → 弹窗转「更新」语义\n * (mode=update 放行覆盖重装),避免重复点击撞 409 报错。 */\n const customTargetInstalled = (raw: string): boolean => {\n const target = raw.trim()\n if (!target) return false\n const repo = repoFromInstallTarget(target)\n const isRepo = /^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$/.test(repo)\n if (isRepo) {\n const needle = repo.toLowerCase()\n return catalog.installedItems.some((i) =>\n (i.repo !== null && i.repo.toLowerCase() === needle) ||\n repoFromInstallTarget(i.spec).toLowerCase() === needle)\n }\n // npm 包名(可带 @version):剥掉版本号后同时查已安装列表与原始依赖表。\n // Hub 自身(file:/link: 安装)被 installedItems 刻意排除(防误卸载),列表里查不到,\n // 但依赖表真实存在——补齐后「命令窗口重装 hub 自身」也能转「更新」语义,不再撞 already installed\n const pkg = repo.replace(/@[^@]*$/, '').toLowerCase()\n return catalog.installedItems.some((i) => i.name.toLowerCase() === pkg) ||\n Object.keys(catalog.installed).some((k) => k.toLowerCase() === pkg)\n }\n\n /** 弹窗动作一:复制安装命令到剪贴板,引导去终端粘贴执行(npm 通道显示包名命令)。 */\n const copyCommand = async (p: HubPlugin) => {\n const repo = p.source?.repo ?? ''\n const ok = await doCopy(installCommandOf(p))\n if (ok) {\n setCopied(repo)\n setToast({ id: Date.now(), kind: 'copied' })\n window.setTimeout(() => setCopied((cur) => (cur === repo ? null : cur)), 1600)\n }\n setConfirmPlugin(null)\n }\n\n /** 卸载弹窗动作:复制卸载命令,万一直接卸载失败可去终端手动执行。\n * 自定义安装(无目录数据)按已安装项包名直卸,同样给复制通道。 */\n const copyUninstallCommand = async () => {\n const name = uninstallItem ? uninstallItem.name : (uninstallPlugin ? catalog.installedName(uninstallPlugin) : null)\n if (!name) return\n const ok = await doCopy(`dsh plugin remove ${name}`)\n if (ok) setToast({ id: Date.now(), kind: 'copied' })\n }\n\n /** 详情弹窗动作:在系统文件管理器里定位安装目录;服务端失败给 toast 提示。 */\n const revealFolder = async (item: InstalledItem) => {\n const ok = await revealInstallFolder(item.name)\n if (!ok) setToast({ id: Date.now(), kind: 'revealFail' })\n }\n\n /** 「立即重启」:POST 同源 /restart,宿主进程自杀重启;随后轮询服务恢复后整页刷新。 */\n const requestRestart = async () => {\n if (restarting) return\n setRestarting(true)\n try {\n // 响应可能在宿主进程被 kill 前返回,也可能直接断连 —— 两种都属正常\n await fetch('/dsh-plugin-hub/restart', { method: 'POST' })\n } catch {\n /* 服务已终止,无需处理 */\n }\n // 轮询同源端点,服务恢复后整页 reload(让新挂载的 bundle 完全初始化)\n let attempts = 0\n const poll = async () => {\n attempts += 1\n try {\n const res = await fetch('/dsh-plugin-hub/active', { method: 'GET', cache: 'no-store' })\n if (res.ok) {\n window.location.reload()\n return\n }\n } catch {\n /* 服务尚未恢复 */\n }\n if (attempts < 60) {\n window.setTimeout(poll, 1000)\n } else {\n setRestarting(false)\n setToast({ id: Date.now(), kind: 'fail' })\n }\n }\n window.setTimeout(poll, 1200)\n }\n\n const { total, installedName, installedVersion, hasUpdate } = catalog\n // 统计数字:官网 /api/stats.json 优先;拉取失败时用已加载列表兜底,避免展示 undefined。\n const statsTotal = catalog.stats?.total ?? total\n const statsVerified = catalog.stats?.verified ?? 0\n\n const count = catalog.visible.length\n\n // Hub 自身条目(目录数据里的 dshplugin/dsh-plugin-hub):头部「可更新」徽标的更新目标。\n // useCatalog 在过滤目录(自身不进插件列表)前单独保留该条目;目录可能尚未加载(此时为 null,徽标不渲染)。\n const hubEntry = catalog.hubPlugin\n\n return h('div', { className: styles.root },\n h(CatalogHeader, {\n t,\n langPath,\n statsTotal,\n statsVerified,\n onToggleLang: toggleLang,\n // Hub 自身版本信息入口:版本号常驻可点(无更新也看得到当前版本更新内容),\n // 有可用更新时版本号后紧跟红色「可更新」徽标(同一入口),点击都打开同一个更新说明弹窗。\n // 有更新弹窗显示新版本 + Markdown 变更记录,点「直接更新」进安装弹窗覆盖重装。\n hubUpdate: catalog.hubHasUpdate,\n // 点击版本号/徽标:先强制刷新拉取最新版本信息(发版后点击即见新版本),再打开弹窗\n onVersionClick: () => {\n void catalog.refreshHub().then(() => setShowHubUpdate(true))\n },\n onAboutClick: () => setShowAbout(true),\n }),\n // 一级导航行:tab 占满左侧,通知入口靠右(「设置」tab 后边,右对齐)\n h('div', { className: styles.tabsRow },\n // 「已安装」徽标 = 目录插件 + 自定义安装总数(installedItems 已排除 hub 自身)\n h(SectionTabs, {\n view,\n setView,\n installedCount: catalog.installedItems.length,\n t,\n // 通知中心入口:红圈徽标 = 记录数 + 进行中任务 + 待重启(有动静才醒目)\n noticeCount: notifications.length + queue.queue.length + queue.pendingRestarts.length,\n onOpenNotifications: () => {\n // 打开弹窗时补齐更新提醒(受「启动时检查更新」开关约束):同一版本只一条,\n // 清空/删除后重开仍恢复,直到插件更新完成才消失\n if (hubSettings.checkUpdatesOnStart) syncUpdateNotices()\n setShowNotifications(true)\n },\n }),\n ),\n view === 'market'\n ? h(MarketView, {\n catalog,\n t,\n langPath,\n langKey,\n copied,\n // 列表头部「筛选出 N 条」:分类/搜索/安装状态筛选后的结果数;全部视图且未筛选时显示总数\n resultText: catalog.plugins === null || catalog.failed\n ? null\n : catalog.category === 'all' && count === total\n ? t('pluginsTotal', { n: count })\n : t('filterResults', { n: count }),\n onInstall: (p, opts) => {\n setInstallDone(false)\n setConfirmIsUpdate(opts?.update ?? false)\n // 与卸载一致:重置弹窗关联任务,避免新弹窗误匹配到进行中的任务而禁用安装按钮\n queue.clearModalTask()\n setConfirmPlugin(p)\n },\n onUninstall: (p) => {\n setUninstallDone(false)\n queue.clearModalTask()\n setUninstallPlugin(p)\n },\n // 目录加载失败时的精准提示:设置里配了代理 → 提示代理不可达;没配 → 提示网络不通\n hasProxy: (hubSettings.proxy ?? '').trim() !== '',\n // 「去系统诊断检测网络」直达(复用网络失败弹窗的同一跳转:关弹窗 → 设置 → 系统诊断自动跑连通性检测)\n onOpenDiagnostics: openDiagnostics,\n })\n : view === 'installed'\n ? h(InstalledView, {\n items: catalog.installedItems,\n langKey,\n t,\n // 支持系统文件管理器定位的平台(macOS / Linux)上,行内「打开详情」替换为\n // 打开安装目录按钮(行点击本身即打开详情弹窗);Windows 不支持则按钮不显示\n platform: env?.platform ?? '',\n // 行点击 / 详情按钮:打开已安装详情弹窗(完整元数据 + 运行时信息)\n onOpenDetail: (item) => setDetailItem(item),\n onReveal: (item) => { void revealFolder(item) },\n // 更新:已安装视图的「更新」= 目录插件覆盖重装,与市场列表内更新同一流程\n onUpdate: (item) => {\n if (!item.plugin) return\n setDetailItem(null)\n setInstallDone(false)\n setConfirmIsUpdate(true)\n queue.clearModalTask()\n setConfirmPlugin(item.plugin)\n },\n // 卸载:目录插件与自定义安装统一按已安装项走卸载确认弹窗(自定义无目录数据,按包名直卸)\n onUninstall: (item) => {\n setDetailItem(null)\n setUninstallDone(false)\n queue.clearModalTask()\n setUninstallItem(item)\n },\n // 重启:待重启条目行内按钮 → 先弹「立即重启 / 稍后重启」确认(与通知中心一致),确认后才触发宿主重启\n onRestart: () => setShowRestartConfirm(true),\n })\n : view === 'custom'\n ? h(CustomInstallView, {\n t,\n // 命令行安装:与应用商店同一套确认/进度/结果弹窗 —— 输入 npm 包名 / GitHub 地址 /\n // dsh plugin 命令即装(custom 源,受安全设置三开关控制)。点安装先弹确认窗,\n // 确认后走队列安装(实时进度 + 成功结果视图);目标已安装 → 弹窗转「更新」覆盖重装,\n // 不会撞「already installed」报错。\n // 安全信任开关关掉对应通道 → 卡片禁用并提示去设置打开(onOpenSettings 跳到设置页)。\n enableNpm: hubSettings.enableNpmInstall,\n enableGit: hubSettings.enableGitInstall,\n enableDsh: hubSettings.enableDshInstall,\n onOpenSettings: () => setView('settings'),\n // 当前 profile:一键插入的 Hub 更新命令用它拼 --profile\n profile: env?.profile ?? 'web',\n onInstallCustom: (raw, opts) => {\n const target = raw.trim()\n if (!target) return\n setInstallDone(false)\n // 与目录安装一致:重置弹窗关联任务,避免新弹窗误匹配到进行中的任务\n queue.clearModalTask()\n // 官方全局 npm 安装(npm install -g <pkgs>):弹窗走 globalNpm 模式(系统级 CLI 工具,\n // 不进插件列表,不做「已安装→更新」判定 —— npm install -g 对已装包是原位覆盖更新,天然幂等)\n if (opts?.globalNpm && opts.globalNpm.length > 0) {\n setConfirmCustomTarget(null)\n setConfirmCustomChannel(null)\n setConfirmIsUpdate(false)\n setConfirmGlobalNpm({ raw, pkgs: opts.globalNpm })\n return\n }\n setConfirmGlobalNpm(null)\n // 记录入口渠道:报错/日志据此精准提示「从哪张卡片发起的安装」(NPM 包 / GitHub 源码 / DSH 命令)\n setConfirmCustomChannel(opts.installChannel)\n setConfirmIsUpdate(customTargetInstalled(target))\n setConfirmCustomTarget(target)\n },\n })\n : h(SettingsView, {\n t,\n settings: hubSettings,\n update: updateSettings,\n reset: resetSettings,\n env,\n onCopy: (text: string) => {\n doCopy(text)\n setToast({ id: Date.now(), kind: 'copied' })\n },\n // 网络不通提示「去系统诊断」→ 设置页并切到系统诊断分组(DiagnosticsView 挂载即自动跑探测)\n openSection: settingsSection,\n onConsumedOpenSection: () => setSettingsSection(null),\n }),\n // Hub 版本信息弹窗:版本号/徽标点击打开 —— 有更新显示新版本 + 变更记录 + 「直接更新」,\n // 无更新显示当前版本 + 记录 + 「已是最新」。Worker 拉取失败时兜底展示当前版本号。\n showHubUpdate && h(HubUpdateModal, {\n info: catalog.hubUpdateInfo ?? { version: PLUGIN_VERSION },\n lang,\n t,\n hasUpdate: catalog.hubHasUpdate,\n onClose: () => setShowHubUpdate(false),\n onProceed: () => {\n setShowHubUpdate(false)\n // 与列表内更新同一流程:覆盖重装 dsh-plugin + 结果视图「立即重启」\n if (hubEntry) {\n setInstallDone(false)\n setConfirmIsUpdate(true)\n queue.clearModalTask()\n setConfirmPlugin(hubEntry)\n }\n },\n }),\n // 「关注我们」弹窗:GitHub 图标后按钮点击打开 —— 平台介绍 + 用户反馈群二维码,\n // 内容由 dsh-update Worker 的 /about 接口以 Markdown 形式推送,作者随时可改,非写死。\n // Worker 未推送(info 为 null)时弹窗仍能打开并展示兜底文案,不影响其他功能。\n showAbout && h(AboutModal, {\n info: catalog.hubAboutInfo ?? null,\n lang,\n t,\n onClose: () => setShowAbout(false),\n }),\n // 安装/卸载任务通知中心:本地持久化的成败清单,随时可回来查看/复制/清空;\n // 进行中的任务(实时进度)与待重启插件也一并展示,关掉任务弹窗后仍可盯着\n showNotifications && h(NotificationsModal, {\n records: notifications,\n tasks: queue.queue,\n pendingRestarts: queue.pendingRestarts,\n t,\n env,\n onClose: () => setShowNotifications(false),\n onCopy: (text) => {\n doCopy(text)\n setToast({ id: Date.now(), kind: 'errCopied' })\n },\n onClear: () => setNotifications(clearNotifications()),\n onRemove: (id: number) => setNotifications(removeNotification(id)),\n // 更新提醒通知:点击直接进该插件的更新确认弹窗(与已安装列表「更新」同一流程)\n onUpdate: (repo: string) => {\n const plugin = catalog.installedItems.find((i) => i.repo === repo)?.plugin\n if (!plugin) return\n setShowNotifications(false)\n setInstallDone(false)\n setConfirmIsUpdate(true)\n queue.clearModalTask()\n setConfirmPlugin(plugin)\n },\n // 更新提醒「忽略本次更新」:先弹确认弹窗,确认后该版本不再提醒(持久化),直到下一个新版本\n onIgnoreUpdate: (repo: string, version?: string) => setIgnoreTarget({ repo, version }),\n cancelTask: queue.cancelTask,\n restarting,\n onRestart: () => setShowRestartConfirm(true),\n // 网络不通记录的「去系统诊断」直达:关通知中心 → 设置 → 系统诊断\n onRunDiagnostics: openDiagnostics,\n // 失败记录仓库反查:历史记录可能存的是裸 npm 包名,反查成 owner/repo 才显示仓库链接\n // 与提 Issue 按钮;查不到则隐藏(防提到错误仓库)\n resolveRepo: (repo: string) => issueRepoOf(repo, catalog.installedItems, catalog.plugins),\n }),\n // 「忽略本次更新」确认弹窗:确认后该版本写入忽略集(持久化)并从通知中心移除,\n // 本次版本不再提醒,直到插件发布下一个新版本\n ignoreTarget && h('div', {\n className: modalStyles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) setIgnoreTarget(null) },\n },\n h('div', { className: modalStyles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: modalStyles.modalHead },\n h('div', { className: modalStyles.modalTitle }, t('ignoreUpdateConfirmTitle')),\n h('button', {\n className: modalStyles.modalClose,\n type: 'button',\n 'aria-label': t('errorClose'),\n onClick: () => setIgnoreTarget(null),\n }, h(CloseIcon)),\n ),\n h('div', { className: modalStyles.modalBody },\n // 忽略更新确认:品牌蓝问号图标,普通确认\n h('div', { className: modalStyles.confirmIconWrap },\n h(ConfirmIcon, { type: 'question' }),\n ),\n h('div', { className: modalStyles.failPrepareHint }, t('ignoreUpdateConfirmDetail')),\n h('div', { className: modalStyles.modalActions },\n h('button', {\n className: modalStyles.restartLater,\n type: 'button',\n onClick: () => setIgnoreTarget(null),\n }, t('confirmCancel')),\n h('button', {\n className: modalStyles.restartNow,\n type: 'button',\n onClick: () => {\n ignoreUpdate(ignoreTarget.repo, ignoreTarget.version)\n setNotifications(removeUpdateNotice(ignoreTarget.repo, ignoreTarget.version))\n setIgnoreTarget(null)\n },\n }, t('ignoreUpdateConfirm')),\n ),\n ),\n ),\n ),\n // 安装确认弹窗:锁定/进度/结果视图逻辑收敛在 modals.tsx;更新与安装同入口,仅标记 update\n confirmPlugin && h(InstallModal, {\n plugin: confirmPlugin,\n done: installDone,\n task: queue.installModalTask,\n t,\n langPath,\n restarting,\n update: confirmIsUpdate,\n // 仅命令行插件(webInstallable=false):弹窗只展示命令供复制,不提供一键安装\n cliOnly: confirmPlugin.install?.webInstallable === false,\n submitting: queue.submitting,\n needsRestart: installNeedsRestart,\n onClose: () => setConfirmPlugin(null),\n onCopy: () => copyCommand(confirmPlugin),\n onInstall: () => queue.installNow(confirmPlugin, confirmIsUpdate ? { update: true } : undefined),\n // 重启:结果视图「立即重启」也会中断进行中的任务 → 先弹重启确认弹窗\n onRestart: () => setShowRestartConfirm(true),\n }),\n // 命令行安装确认弹窗:与目录安装同一套确认/进度/结果流程(plugin 传 null 走 customTarget 模式)。\n // 已安装目标 → update 标记,确认后走覆盖重装(服务端 mode=update 放行),不再 409 报错。\n confirmCustomTarget && h(InstallModal, {\n plugin: null,\n customTarget: confirmCustomTarget,\n done: installDone,\n task: queue.installModalTask,\n t,\n langPath,\n restarting,\n update: confirmIsUpdate,\n cliOnly: false,\n submitting: queue.submitting,\n needsRestart: installNeedsRestart,\n onClose: () => {\n setInstallDone(false)\n setConfirmCustomTarget(null)\n setConfirmCustomChannel(null)\n },\n onCopy: () => {\n doCopy(`pnpm add ${confirmCustomTarget}`)\n setToast({ id: Date.now(), kind: 'copied' })\n },\n onInstall: () => void queue.installCustom(confirmCustomTarget, {\n update: confirmIsUpdate,\n // 入口渠道(NPM 包 / GitHub 源码 / DSH 命令卡片):上报服务端,报错/日志据此溯源\n channel: confirmCustomChannel ?? 'npm',\n }),\n onRestart: () => setShowRestartConfirm(true),\n }),\n // 全局 npm 安装确认弹窗(官方 `npm install -g <pkgs>`):与应用商店同一套确认/进度/结果流程。\n // 装的是系统级 CLI 工具(如 @deepseek-ai/dsh),不进任何 profile、无需宿主重启;\n // 服务端任务终态 needsRestart=false → 结果视图仅「完成」。\n confirmGlobalNpm && h(InstallModal, {\n plugin: null,\n globalNpm: confirmGlobalNpm.pkgs,\n done: installDone,\n task: queue.installModalTask,\n t,\n langPath,\n restarting,\n update: false,\n cliOnly: false,\n submitting: queue.submitting,\n needsRestart: installNeedsRestart,\n onClose: () => {\n setInstallDone(false)\n setConfirmGlobalNpm(null)\n setConfirmCustomChannel(null)\n },\n onCopy: () => {\n doCopy(`npm install -g ${confirmGlobalNpm.pkgs.join(' ')}`)\n setToast({ id: Date.now(), kind: 'copied' })\n },\n onInstall: () => void queue.installGlobalNpm(confirmGlobalNpm.pkgs, { channel: 'npm' }),\n onRestart: () => setShowRestartConfirm(true),\n }),\n // 卸载确认弹窗:确认/进度/结果视图逻辑收敛在 modals.tsx。\n // 已安装视图的自定义安装(目录外)没有完整目录数据,按已安装项伪插件适配后走同一弹窗\n (uninstallPlugin || uninstallItem) && h(UninstallModal, {\n plugin: uninstallPlugin ?? pluginOfItem(uninstallItem!),\n done: uninstallDone,\n task: queue.uninstallModalTask,\n t,\n langPath,\n restarting,\n submitting: queue.submitting,\n needsRestart: uninstallNeedsRestart,\n onClose: () => {\n setUninstallDone(false)\n setUninstallPlugin(null)\n setUninstallItem(null)\n },\n onCancel: () => {\n setUninstallPlugin(null)\n setUninstallItem(null)\n },\n onCopyCommand: copyUninstallCommand,\n onConfirm: () => {\n if (uninstallItem) void queue.uninstallItem(uninstallItem)\n else if (uninstallPlugin) void queue.uninstallNow(uninstallPlugin)\n },\n onRestart: () => setShowRestartConfirm(true),\n }),\n // 已安装详情弹窗:目录元数据 + 宿主运行时信息的完整展示,操作(更新/卸载/复制路径)由此发起\n detailItem && h(InstalledDetailModal, {\n item: detailItem,\n t,\n lang: langKey,\n langPath,\n onClose: () => setDetailItem(null),\n onUpdate: (item) => {\n if (!item.plugin) return\n setDetailItem(null)\n setInstallDone(false)\n setConfirmIsUpdate(true)\n queue.clearModalTask()\n setConfirmPlugin(item.plugin)\n },\n onUninstall: (item) => {\n setDetailItem(null)\n setUninstallDone(false)\n queue.clearModalTask()\n setUninstallItem(item)\n },\n onCopyPath: (path) => {\n doCopy(path)\n setToast({ id: Date.now(), kind: 'copied' })\n },\n onReveal: (item) => { void revealFolder(item) },\n }),\n toast && h(Toast, { toast, t }),\n // 操作失败:完整错误弹窗(重复安装、CLI 失败、请求错误等),可复制并去插件仓库反馈\n errorMsg && h(ErrorModal, {\n message: errorMsg.message,\n repo: errorMsg.repo,\n kind: errorMsg.kind,\n command: errorMsg.command,\n attempts: errorMsg.attempts,\n t,\n env,\n onCopy: (text: string) => {\n doCopy(text)\n setToast({ id: Date.now(), kind: 'errCopied' })\n },\n // 网络不通错误的「去系统诊断」直达:关错误弹窗 → 设置 → 系统诊断\n onRunDiagnostics: openDiagnostics,\n onClose: () => setErrorMsg(null),\n }),\n // 待重启确认弹窗:已安装列表行内「重启」按钮点击后弹出,稍后重启 / 立即重启\n showRestartConfirm && h(RestartConfirmModal, {\n t,\n restarting,\n onClose: () => setShowRestartConfirm(false),\n onRestartNow: () => {\n setShowRestartConfirm(false)\n void requestRestart()\n },\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * dsh-plugin client entry: wires the Plugin Hub into the host settings via\n * the module-loader bundle (see tsdown.config.ts). All UI logic lives in\n * PluginHubSection; this file only performs the cordis apply wiring.\n */\nimport { createElement as h } from 'react'\nimport type { HubClientContext } from './types.ts'\nimport { en, zh } from './locales.ts'\nimport { PluginHubSection } from './components/PluginHubSection.tsx'\nimport './styles/tokens.module.css'\n\nconst NS = 'dsh-plugin'\n\nexport const name = NS\nexport const inject = ['slots', 'locale']\n\nexport function apply(ctx: HubClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), `${NS}: dictionaries`)\n const t = ctx.locale.bind(NS)\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: NS,\n order: 60,\n label: () => t('nav'),\n locale: NS,\n inject: () => ({ t, locale: ctx.locale }),\n }, () => h(PluginHubSection, { t, locale: ctx.locale })))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["DSH_PLUGIN_CMD_RE","SORT_DEFAULT_DIR","useState","useRef","useMemo","useState","useState","useCallback","useState","useRef","h","modalStyles","headerStyles","h","styles","h","styles","useMemo","h","styles","h","styles","h","styles","h","styles","h","styles","useState","h","Fragment","styles","h","styles","SegBtn","h","styles","Fragment","useState","useRef","h","styles","useRef","h","styles","h","Fragment","h","styles","h","styles","useState","useMemo","useState","h","styles","modal","h","styles","useState","useRef","h","styles","useState","useRef","useCallback","h","styles","h","view","useState","useRef","useCallback","styles","useState","h","styles","view","useState","useRef","useCallback","h","styles","h","styles","useState","useRef","dropdownStyles","modalStyles","useState","useRef","h","styles","modalStyles","h"],"sources":["../src/client/locales.ts","../src/server/services/install/release-target.ts","../src/client/logic/install-command.ts","../src/client/logic/constants.ts","../src/client/logic/ensure-plugin-css.ts","../src/client/data/host.ts","../src/client/logic/normalize.ts","../src/client/data/catalog.ts","../src/client/data/hub.ts","../src/client/logic/installed.ts","../src/client/hooks/useCatalog.ts","../src/client/logic/failures.ts","../src/client/logic/urls.ts","../src/client/hooks/useLanguage.ts","../src/client/hooks/useSettings.ts","../src/client/hooks/useTaskQueue.ts","../src/client/components/ui/icons.tsx","../src/client/components/modals/ProgressView.tsx","../src/client/components/modals/modals.tsx","../src/client/logic/renderMarkdown.ts","../src/client/components/modals/AboutModal.tsx","../src/client/components/modals/HubUpdateModal.tsx","../src/client/logic/format.ts","../src/client/components/modals/InstalledDetailModal.tsx","../src/client/components/modals/ConfirmDialog.tsx","../src/client/components/modals/NotificationsModal.tsx","../src/client/components/layout/CatalogHeader.tsx","../src/client/components/layout/CategoryTabs.tsx","../src/client/components/layout/CatalogControls.tsx","../src/client/hooks/useIncrementalList.ts","../src/client/components/catalog/PluginCard.tsx","../src/client/components/catalog/CatalogList.tsx","../src/client/components/views/MarketView.tsx","../src/client/components/layout/SectionTabs.tsx","../src/client/components/views/InstalledView.tsx","../src/client/components/views/CustomInstallView.tsx","../src/client/components/ui/Toggle.tsx","../src/client/components/ui/Dropdown.tsx","../src/client/components/views/DiagnosticsView.tsx","../src/client/components/modals/LogsModal.tsx","../src/client/components/modals/LogsPathModal.tsx","../src/client/components/views/LogsView.tsx","../src/client/components/views/SettingsView.tsx","../src/client/components/PluginHubSection.tsx","../src/client/index.tsx"],"sourcesContent":["/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * zh/en dictionaries for the DSH Plugin Hub settings section.\n */\nexport const zh = {\n nav: '插件市场',\n title: 'DSH Plugin Hub',\n // 收录/精选数量由组件从官网 /api/stats.json 实时拉取填充({total}/{verified}),不写死\n tagline: 'DSH Plugin 插件市场:面向 DeepSeek Harness 插件收录平台,人工审验、来源可溯,免费安装',\n adBadge: '推荐',\n // 紫色广告横幅:突出数量(显眼)+ 更新节奏,与 tagline 职责分开、不重复\n ad: 'DSH Plugin 插件市场:收录 {total} 款插件,{verified} 款人工精选验证,每日更新',\n search: '搜索插件名称、描述、标签…',\n all: '全部',\n sortStars: 'Star',\n sortForks: 'Fork',\n sortUpdated: '最近更新',\n sortNewest: '最新收录',\n sortAria: '插件排序方式',\n openHint: '打开 dsh-plugin.org',\n toggleLangHint: '切换界面语言',\n fork: 'Fork',\n loading: '正在加载插件数据…',\n failed: '插件数据加载失败',\n // 目录拉不出来时的精准提示:按「是否配置了代理」区分,引导排查网络 / 代理\n failedDescNoProxy: '你的网络似乎不通,无法获取插件目录数据。请检查网络连接后重试;或点击右上角按钮在浏览器中打开插件市场。',\n failedDescProxy: '你的网络似乎不通,或设置里的 HTTP 代理地址不可达,无法获取插件目录数据。请检查代理设置与网络连接后重试;或点击右上角按钮在浏览器中打开插件市场。',\n retry: '重试',\n install: '安装',\n // AI 识别可能需要命令行辅助的插件(webInstallable=false):仍可尝试一键安装,失败时复制命令去 dsh 终端\n cliOnlyHint: '此插件可能需命令行辅助,失败时复制上方命令到 dsh 终端',\n failedCopyHint: '安装失败。请复制上方安装命令到 dsh 终端手动执行(原生依赖构建脚本可能需要人工放行,如 pnpm approve-builds)',\n toastCopied: '安装命令已复制,去 dsh 终端粘贴即可安装',\n installed: '已安装',\n // 一级导航:插件市场 / 已安装 / 自定义安装 / 设置\n viewMarket: '插件市场',\n viewInstalled: '已安装',\n viewCustom: '自定义安装',\n viewSettings: '设置',\n viewMarketHint: '浏览与发现插件',\n viewInstalledHint: '管理已安装插件',\n viewCustomHint: '手动安装 NPM 包或 GitHub 源码',\n viewSettingsHint: '网络通道与偏好设置',\n // 已安装视图\n installedEmpty: '还没有安装插件',\n installedEmptyDesc: '可以去「自定义安装」,手动安装 NPM 包或 GitHub 源码',\n npmInstallLabel: 'NPM 包 / 命令',\n npmInstallPlaceholder: 'npm install <包名> 或直接输包名',\n npmInstallExample: '支持原生命令:npm install lodash、npm i lodash、pnpm add @scope/pkg',\n npmInstallExample2: '全局安装 CLI:npm install -g @scope/cli;或直接输入包名 lodash',\n npmInstallInvalid: '请输入 npm 包名(如 lodash、@scope/pkg),或原生安装命令(如 npm install lodash、npm i lodash、pnpm add @scope/pkg、npm install -g @scope/cli)',\n gitInstallLabel: 'GitHub 源码',\n gitInstallPlaceholder: '输入仓库地址',\n gitInstallExample: '例如:owner/repo 或 https://github.com/owner/repo',\n gitInstallInvalid: '请输入 GitHub 仓库地址,例如:owner/repo 或 https://github.com/owner/repo',\n dshCmdLabel: 'DeepSeek Harness 命令',\n dshCmdPlaceholder: '粘贴官方 dsh plugin 命令',\n dshCmdInsertHubUpdate: '插入更新命令',\n // 示例/校验文案里的 profile 用运行时当前宿主 profile 渲染({profile} 占位符),\n // 不写死 web —— 桌面端当前 profile 是 desktop,照抄写死的 web 会装进宿主永不加载的档\n dshCmdExample: '例如:dsh plugin --profile {profile} add github:owner/repo,或 dsh plugin --profile {profile} update dsh-plugin',\n dshCmdInvalid: '请输入官方 dsh plugin 命令(--profile 必填,支持 add / update)。例如:dsh plugin --profile {profile} update dsh-plugin',\n installHelp: '帮助',\n helpModalTitle: '支持的命令格式',\n npmInstallHelp: 'lodash、@scope/pkg\\t直接输入包名\\nnpm install lodash\\nnpm i lodash\\npnpm add @scope/pkg\\npnpm i @scope/pkg\\nnpm install -g @scope/cli\\t全局安装 CLI 工具,不进「已安装」列表',\n gitInstallHelp: 'owner/repo\\nhttps://github.com/owner/repo\\ngithub:owner/repo\\ngit+https://github.com/owner/repo.git\\ngit@github.com:owner/repo.git',\n dshCmdHelp: 'dsh plugin --profile {profile} add <目标>\\t安装\\ndsh plugin --profile {profile} update <目标>\\t更新已安装目标到最新版本\\ndsh plugin --profile={profile} add <目标>\\ndsh plugin --profile={profile} update <目标>\\n\\t--profile 必填(此处已填当前 profile),官方 CLI 无 -p 简写;<目标> 可为 npm 包名或 github:owner/repo;卸载请用「已安装」列表',\n globalNpmHint: '将全局安装 CLI 工具(npm install -g),不会出现在「已安装」列表,无需重启宿主',\n installCliBtn: '安装',\n // 安装通道关闭(安全信任开关关掉后,对应卡片禁用并引导去设置打开)\n channelDisabledHint: '该安装通道已关闭,请在「设置 → 安全信任」中打开开关',\n goToSettings: '前往设置',\n // 自定义安装视图:独立一级导航,说明文字\n customViewDesc: '手动安装目录外的 NPM 包、GitHub 源码,或粘贴官方 dsh plugin 命令。装完的条目会出现在「已安装」列表,并标记为自定义安装。',\n customLabel: '自定义安装',\n installedSearch: '搜索已安装的插件…',\n installedFilterCatalog: '目录插件',\n hubInstall: '插件市场',\n hubInstallHint: '来自插件市场收录的目录插件',\n manualInstall: '手动安装',\n manualInstallHint: '非目录收录,通过命令行手动安装',\n filterByLabel: '来源',\n sortByLabel: '排序',\n sortName: '名称',\n sortInstalledAt: '最近',\n detailTitle: '插件详情',\n detailCategory: '分类',\n detailStats: '仓库统计',\n statusLabel: '安装状态',\n statusRunning: '运行中',\n statusPending: '待重启',\n exampleLabel: 'DeepSeek Harness 内置示例项目',\n exampleHint: 'DeepSeek Harness 内置示例项目:不是插件市场的 dsh 插件,宿主不会加载它,无需重启',\n restart: '重启',\n installedVersionLabel: '已安装版本',\n catalogLatest: '目录最新',\n installPath: '安装路径',\n copyPath: '复制路径',\n openFolder: '在文件夹中显示',\n openFolderFail: '无法打开文件夹,请复制路径手动打开',\n revealFolder: '在 Finder 中显示',\n installedAtLabel: '安装时间',\n lastUpdatedLabel: '最后更新',\n detailCatalog: '查看详情',\n packageName: '包名',\n versionUpHint: '发现新版本 v{from} → v{to},点击「更新」原位覆盖重装',\n // 设置视图:更新与通道 / 安全与信任 / 诊断 / 系统日志\n settingsUpdate: '更新设置',\n settingsUpdateDesc: '更新检查方式与安装走到的网络通道',\n settingsCheckOnStart: '启动时检查更新',\n settingsCheckOnStartDesc: '打开插件市场时检查已安装插件是否有新版,发现更新会提示',\n settingsProxy: 'HTTP 代理',\n settingsProxyDesc: 'npm / git / 目录数据请求统一走该代理;留空直连',\n // 代理连通性实时探测:输入停笔后提示检测结果(不通仍可保存,先填地址后开代理也合法)\n proxyCheckChecking: '正在测试该代理地址…',\n proxyCheckOk: '测试可达,安装与目录请求将统一走该代理',\n proxyCheckFail: '此地址测试不通,仍可保存;请确认代理已开启、地址与端口无误',\n // 失败细分原因:Windows Schannel 必须取到证书吊销信息,取不到即中断握手 —— 不是代理地址不通\n proxyCheckRevocation: '证书吊销检查受阻(Windows Schannel 取不到 CRL/OCSP),握手被中断;属本机 TLS 环境问题,非代理地址不通',\n settingsMirror: 'npm 镜像源',\n settingsMirrorDesc: '默认跟随本机 npm 配置;官方源慢可换国内镜像',\n mirrorNone: '未配置(跟随本机 npm 配置)',\n mirrorOfficial: '官方源 registry.npmjs.org',\n mirrorNpmmirror: '阿里云 npmmirror',\n mirrorTencent: '腾讯云镜像',\n mirrorTsinghua: '清华大学 TUNA 镜像',\n settingsSecurity: '安全信任',\n settingsSecurityDesc: '命令行安装的三个通道开关:NPM 包、GitHub 源码与 DSH 命令',\n settingsEnableNpm: '启用 NPM 安装',\n settingsEnableNpmDesc: '允许通过命令行安装 npm 包;关闭后输入包名安装会被拦截',\n settingsEnableGit: '启用 GitHub 源码安装',\n settingsEnableGitDesc: '允许通过命令行安装 GitHub 源码;关闭后输入仓库地址安装会被拦截',\n settingsEnableDsh: '启用 DSH 命令安装',\n settingsEnableDshDesc: '允许通过命令行粘贴 dsh plugin 命令安装;关闭后命令输入会被禁用',\n settingsDiagnostics: '系统诊断',\n settingsDiagnosticsDesc: '检测 npm 源 / GitHub / 目录站点等安装通道的连通状态',\n settingsLogs: '系统日志',\n settingsLogsDesc: '本地记录的安装 / 卸载 / 设置变更与诊断结果,可导出全文排查问题',\n logsHeadHint: '记录安装、卸载、设置变更与诊断结果,保留最近 2000 条',\n logsRefresh: '刷新日志',\n logsExport: '导出日志',\n logsLoading: '正在读取日志…',\n logsEmpty: '暂无日志记录',\n logsLoadFail: '读取日志失败,请稍后重试',\n // 系统日志查看器弹窗:内置窗口分页加载,按类别 × 级别筛选\n logModalTitle: '日志查看器',\n logViewerOpen: '打开日志查看器',\n logViewerDesc: '内置窗口直接查看本地日志,按类型与级别筛选,可定位安装 / 卸载 / 更新时的不兼容点',\n logPathLabel: '日志文件',\n logOpenFile: '打开文件',\n logOpenFileTip: '在系统文件管理器中定位日志文件',\n logOpenFileFail: '打开失败,请在文件管理器中手动定位',\n logClearAll: '清空所有日志',\n logClearConfirmTitle: '清空所有日志?',\n logClearConfirmDesc: '将删除全部日志记录,且不可恢复。',\n logClearing: '正在清空…',\n logClearAllTip: '清空全部日志记录',\n logClearFailed: '清空失败,请重试',\n logPathSettingTitle: '日志存放位置',\n logPathSettingDesc: '默认存于宿主配置目录,可填目录或 .log 文件路径改存别处',\n logPathPlaceholder: '留空恢复默认',\n logPathReset: '恢复默认',\n logPathResetHint: '文本框显示当前生效位置',\n logPathSave: '保存',\n logPathSaving: '保存中…',\n logPathSaved: '已保存,新日志将写入该位置',\n logPathSaveFail: '保存失败:该位置不可写或不可用',\n logPathChange: '修改',\n logPathBrowse: '选择目录…',\n logPathBrowseFail: '选择目录不可用,请手动输入路径',\n logCatAll: '全部类型',\n logCatInstall: '安装',\n logCatUninstall: '卸载',\n logCatUpdate: '更新',\n logCatDiagnostics: '诊断',\n logCatSettings: '设置',\n logCatSystem: '系统',\n logLvAll: '全部级别',\n logLvError: '错误',\n logLvWarn: '警告',\n logLvSuccess: '成功',\n logLvInfo: '信息',\n logLvDebug: '调试',\n logSearchPlaceholder: '搜索事件或描述…',\n logLoadMore: '加载更多',\n logNoMore: '已加载全部,共 {n} 条',\n logCount: '共 {n} 条',\n logEmptyFilter: '没有符合条件的日志',\n settingsDiagFail: '不可达',\n // 系统诊断通道列表:一键全量诊断 + 一行一个,可点重测\n diagNpm: 'npm 源',\n // 诊断页 npm 行:未配置镜像时的展示(探测目标仍为官方源,代表本机无配置时的回退)\n diagNpmUnset: '未配置(跟随本机 npm 配置)',\n diagGithub: 'GitHub',\n diagCatalog: '目录站点',\n diagCatalogTarget: '插件市场',\n diagProxy: 'HTTP 代理',\n diagOk: 'OK',\n diagChecking: '检测中…',\n diagIdle: '未检测',\n diagRecheck: '点击重测该通道',\n diagRunAll: '立即诊断',\n diagHeadHint: '共 {n} 个通道,点击任意一行可单独重测',\n diagSummaryRunning: '正在检测通道…',\n diagSummaryOk: '全部通道正常',\n diagSummaryFail: '存在不可达通道,点击对应行可重测',\n // 失败细分原因:Windows Schannel 必须取到证书吊销信息才能握手,取不到即中断(易被误当成网络不通)\n diagFailRevocation: '证书校验受阻',\n diagFailRevocationHint: '系统 curl 取不到证书吊销信息(Windows Schannel 必需 CRL/OCSP),TLS 握手被中断 —— 这不是网络不通,npm/git 可能照常可用。升级 curl 到 7.70+ 可自动按「尽力而为」处理,或换一个能访问吊销服务的网络。',\n settingsEnvSnapshot: '系统版本',\n settingsEnvSnapshotDesc: '复制宿主版本与系统信息,提交 Issue 时粘贴到正文便于复现',\n settingsEnvCopy: '复制',\n // 恢复默认:一级菜单 + 独立设置卡片\n settingsReset: '恢复默认',\n settingsResetDesc: '更新策略、镜像源、代理与安全限制一次性恢复为出厂默认值',\n settingsResetDetail: '恢复更新策略、镜像源、代理与安全限制为出厂默认值',\n settingsResetRun: '恢复默认',\n settingsResetConfirm: '确认恢复',\n settingsResetConfirmDetail: '确定要恢复默认设置吗?更新策略、镜像源、代理与安全限制将全部回到出厂默认值。',\n // 更新通知(通知中心条目标题)\n updateNoticeTitle: '发现新版本',\n updateNoticeGo: '去更新',\n ignoreUpdateRun: '忽略本次更新',\n ignoreUpdateConfirmTitle: '忽略本次更新?',\n ignoreUpdateConfirmDetail: '忽略后本次版本不再提醒;待插件发布下一个新版本时,会再次通知你。',\n ignoreUpdateConfirm: '确认忽略',\n uninstall: '卸载',\n uninstalling: '卸载中…',\n uninstallTitle: '确认卸载?',\n uninstallDesc: '将从当前环境卸载该插件。',\n uninstallDone: '卸载成功',\n uninstallFail: '卸载失败,请稍后重试',\n uninstallResultTitle: '卸载完成',\n uninstallResultDesc: '插件已从当前环境移除。',\n confirmTitle: '确认安装',\n confirmDesc: '安装前请前往插件仓库仔细阅读源码,确认可信后再安装',\n confirmPlugin: '插件',\n confirmSource: '来源',\n confirmCommand: '安装命令',\n copyInstallCommand: '复制安装命令',\n copyCmdLabel: '复制',\n copyUninstallCommand: '复制卸载命令',\n cancelUninstall: '取消卸载',\n uninstallConfirm: '确认卸载',\n installNow: '直接安装',\n installing: '安装中…',\n installDone: '安装成功',\n // 更新成功(通知中心区分安装/更新):更新 = 已安装目标覆盖重装到最新,与首次安装不同语义\n updateDone: '更新成功',\n installResultTitle: '插件安装成功',\n installResultDesc: '',\n // 更新语义:已安装插件点「更新」走同一条 add 命令原位覆盖重装,弹窗文案区分安装/更新\n confirmUpdateTitle: '确认更新',\n updateNow: '直接更新',\n updating: '更新中…',\n queuedUpdateTitle: '已加入更新排队',\n updateResultTitle: '更新完成',\n updateResultDesc: '插件已更新到最新版本。',\n installFail: '安装失败',\n requestTimeout: '请求超时:无法访问 GitHub 或网络不稳定,请稍后重试',\n confirmCancel: '取消',\n doneBtn: '完成',\n // 结果视图兜底:仅当「刷新解决不了」时(热挂载失败 / 非 dsh 插件 / 更新)才出现单个「立即重启」;\n // 关闭弹窗即视为「稍后」,不再单独给「稍后重启」按钮\n restartNow: '立即重启',\n restarting: '正在重启…',\n restartHint: '重启会中断正在进行的安装/卸载任务,其进度将丢失。部分插件(如插件市场、顶层 bundle)需重启后才会生效。',\n // 桌面端宿主归应用壳管、插件重启不了它:点「立即重启」时改提示用户退出重开\n toastRestartDesktop: '桌面端的宿主由应用管理,请在应用菜单(或托盘)选择退出后重新打开,重启后生效',\n // 装完即生效:插件已热挂进运行中 loader,结果弹窗关闭时自动刷新页面(无需用户点按钮)\n reloadHint: '插件已加载,关闭本窗口后会自动刷新页面生效。',\n toastInstalledLive: '安装成功,已立即生效',\n toastInstalledReload: '安装成功,正在自动刷新页面…',\n done: '完成',\n // 待重启:装完没重启的插件常驻提醒,直到宿主真正重启\n restartPendingHint: '安装成功,重启后生效',\n restartPendingHintUninstall: '卸载成功,重启后移除',\n sectionPendingRestart: '待重启',\n sectionInProgress: '进行中',\n // 通知中心:安装/卸载任务成败的持久记录(工具栏铃铛入口按钮打开)\n notifications: '通知',\n notificationsHint: '查看安装/卸载/更新通知',\n notificationsDesc: '安装、卸载任务与更新提醒都会记录在这里,即使错过提示也能随时回来查看。',\n notificationsEmpty: '暂无通知记录',\n notificationsClear: '清空通知',\n notificationsClearConfirmTitle: '清空所有通知?',\n notificationsClearConfirmDesc: '将删除全部通知记录,且不可恢复。',\n removeNotification: '删除这条通知',\n removeNotificationConfirmTitle: '删除这条通知?',\n removeNotificationConfirmDesc: '该通知将被移除,且不可恢复。',\n // 串行队列:安装/卸载弹窗内可后台关闭,排队任务自动串行执行\n queuedTitle: '已加入安装排队',\n queuedUninstallTitle: '已加入卸载排队',\n queuedHint: '已加入排队,前序任务完成后将自动开始,可关闭本窗口继续浏览。',\n cancelTask: '取消任务',\n cancelling: '正在取消…',\n errorTitle: '操作失败',\n errorTitleInstall: '安装失败',\n errorTitleUninstall: '卸载失败',\n // 更新失败(通知中心区分安装/更新):更新目标覆盖重装失败,与首次安装失败不同语义\n errorTitleUpdate: '更新失败',\n errorPlugin: '插件',\n errorClose: '知道了',\n errorCopy: '复制错误信息',\n errCopied: '错误信息已复制',\n failCopy: '复制完整错误信息',\n failIssueHint: '带着错误日志去作者仓库一键提交 Issue(正文含官网收录链接)',\n failIssueBig: '一键提交 BUG 到 GitHub Issue 为开源作贡献',\n // prepare 构建脚本实际执行失败(git 分发缺子模块/构建产物):插件打包分发问题,应提 Issue\n failPrepareHint: '该插件安装时的构建脚本执行失败(git 分发常缺失子模块或构建产物),属插件打包分发问题。请向作者仓库提交 Issue 反馈。',\n // 安装前预检 / 装后校验拦截([packaging]):git 分发缺构建产物、入口文件不存在 = 插件未适配官方默认安装方式\n failPackagingHint: '该插件不支持官方默认安装方式:其 git 分发缺少构建产物(package.json 声明的入口文件在仓库中不存在),说明作者未适配官方安装流程。请到作者仓库提交 Issue 反馈,请其提交构建产物或发布 npm 版。',\n // 原生依赖构建脚本被 pnpm 默认拦截(如 node-pty 的 ERR_PNPM_IGNORED_BUILDS):只影响带原生模块的插件,属插件依赖打包问题,应提 Issue\n failIgnoredBuild: '该插件或其依赖需要执行构建脚本,被 pnpm 的安全白名单(allowBuilds)默认拦截导致安装失败(如原生模块 node-pty、或 git 安装时插件的 prepare 脚本)—— 其他插件不受影响,属该插件的依赖/打包问题。建议向作者仓库一键反馈,请作者改用预编译版本(如 node-pty-prebuilt-multiarch)或移除安装期构建。',\n // npm arborist 内部崩溃(edgesOut)+ 本机 npm 版本过低:npm 自身已知缺陷,不是插件问题,升级 npm 即可\n failNpmTooLow: '怀疑本机 npm 版本过低:npm 解析插件依赖时内部崩溃(这是 npm 自身的已知缺陷,不是插件问题)。请升级 npm 后重试:npm install -g npm@latest',\n failNpmTooLowV: '本机 npm 版本过低(当前 v{v}):npm 解析插件依赖时内部崩溃(这是 npm 自身的已知缺陷,不是插件问题)。请升级 npm 后重试:npm install -g npm@latest',\n // 安装前连通性预检 / 安装日志里的连接失败([network] / git fetch 超时 / DNS / TLS):本机网络或代理问题,不是插件问题,不引导提 Issue\n failNetworkHint: '安装前检测到网络不通:无法连接到安装源(可能是断网、DNS 解析失败、被防火墙拦截,或代理配置有问题)。这不是插件本身的问题 —— 请检查网络连接,或到「设置」里确认 HTTP 代理配置,再到「系统诊断」运行一次连通性检测,然后重试。',\n // 网络失败弹窗里的「无法访问 …」醒目行:直接告诉用户具体哪个地址连不上({url} 为提取的不可达地址)\n failNetworkRegistryHint: '你的 npm/pnpm 源(registry)被配置为 {host},插件包需从该源下载但失败了。这通常是内网/自定义源没有同步该包(或需要内网认证)—— 请把 npm/pnpm 的 registry 指回官方源 https://registry.npmjs.org(或确认此源可访问该包)后重试。',\n failNetworkTarget: '无法访问 {url} —— 你的网络连接不通',\n // 「去系统诊断」直达按钮:网络不通提示下方的品牌实底按钮,跳到设置 → 系统诊断跑连通性检测\n failNetworkRunDiag: '去系统诊断检测网络',\n // 请求来源没通过本地 hub 服务校验(服务端 403 untrusted origin):请求根本没进安装流程,\n // 与插件无关 —— 引导从本机地址重新打开市场,不引导提 Issue\n failOriginRejectedHint: '这次安装请求没有通过插件市场的来源校验,被本地服务直接拒绝,所以安装根本没有开始 —— 与插件本身无关。通常是因为市场页面不是从本机地址打开的(比如用了局域网 IP),或宿主页面的来源未被识别。请从本机的插件市场地址(localhost)重新打开页面后重试;桌面端用户重启一次宿主即可。若重启宿主后仍然失败,说明当前 dsh-plugin 版本与宿主不兼容,请用以下命令把市场升级到最新版,再重启一次宿主:dsh plugin --profile {profile} add dsh-plugin@latest。',\n failDshMissingHint: '系统找不到 dsh 命令(dsh 未加入系统 PATH),无法调用安装器执行安装。请确认 DeepSeek Harness 已正确安装、dsh 已加入 PATH(或重新安装),然后重试。这不是插件本身的问题。',\n failGitMissingHint: '系统找不到 git 命令(Git 未安装或未加入系统 PATH),无法从 GitHub 源安装插件。请先安装 Git(如 git-scm.com/downloads)或把 git 加入 PATH,重启 DSH 后重试。这不是插件本身的问题。',\n failPnpmMissingHint: '安装器找到了 dsh,但系统里没有 pnpm 命令(dsh 用它来管理 profile 插件)。请先安装 pnpm(如 npm install -g pnpm),确认 pnpm 已加入 PATH 后重试。这不是插件本身的问题。',\n failNpmMissingHint: '系统找不到 npm 命令(npm 未安装或未加入系统 PATH),无法执行全局安装。请先安装 Node.js(自带 npm),确认 npm 已加入 PATH 后重试。这不是插件本身的问题。',\n failPnpmStoreHint: '安装器调用 pnpm 时报「store 位置不匹配」(ERR_PNPM_UNEXPECTED_STORE):你的 profile 目录里旧插件依赖是用另一个大版本的 pnpm 生成的,当前 pnpm 出于安全不认旧目录,导致任何插件装进该 profile 都会失败。请删除该 profile 目录下的 node_modules 与 pnpm-lock.yaml(可先到「系统日志」或 ~/.dsh/profiles/<profile>/hub.log 查看完整报错),再重新安装。这不是插件本身的问题。',\n failPnpmUnusedPatchHint: '安装器调用 pnpm 时报「有些补丁没有被使用」(ERR_PNPM_UNUSED_PATCH):你的 profile 里留着一条指向旧版本 dsh-plugin 的补丁声明(例如 dsh-plugin@1.4.2),而本次安装解析到的版本已经不是它,pnpm 出于安全直接中止整次安装,因此任何插件都装不进来。这不是插件本身的问题——请在 profile 目录(~/.dsh/profiles/<profile>)的 pnpm-workspace.yaml(pnpm 11 及以上)或 package.json 的 pnpm.patchedDependencies(pnpm 10)里删除该 dsh-plugin 补丁条目后重试。',\n // 404 依赖:点名 registry 上不存在的那个包(取不到包名时跳过这行),再给删除条目的指引\n failPnpmMissingDepTarget: '{pkg} 在 npm registry 上不存在(404)',\n failPnpmMissingDepHint: '安装器调用 pnpm 时报「包不存在」(ERR_PNPM_FETCH_404):你的 profile 里留着一条指向 registry 上未发布包的依赖,pnpm 每次解析依赖都会先卡在它上面,因此任何插件都装不进来。这不是插件本身的问题——请在 profile 目录(~/.dsh/profiles/<profile>)的 package.json 里删除该依赖条目(同时删掉对应的 pnpm-lock.yaml 条目或整个锁文件)后重试。',\n failFileLockedHint: '安装过程中 pnpm 无法替换 profile 里的文件:有程序正占用着它(Windows 常见报错 os error 32「另一个程序正在使用此文件」)。通常是 DeepSeek Harness 自身或杀毒软件的实时扫描持有文件句柄。这不是插件本身的问题——请完全退出 DeepSeek Harness(Windows 可在任务管理器确认进程已结束,必要时临时关闭杀毒软件实时防护)后重试。',\n failAccessDeniedHint: '安装过程中 pnpm 写入 profile 里的文件被系统拒绝访问(Windows 常见报错 os error 5「拒绝访问」,英文为 Access is denied;Node 下的 EPERM / EACCES 同理)。常见原因是该文件或目录正被其他进程占用、文件带只读属性、目录权限受限,或杀毒软件实时防护拦截了写入——这与「文件正被占用」(os error 32)同属本机文件系统问题,任何插件装进该目录都会一样失败,不是插件本身的问题。请完全退出 DeepSeek Harness(Windows 可在任务管理器确认进程已结束,必要时临时关闭杀毒软件实时防护)后重试;若仍然失败,请检查 profile 目录及其文件是否被设为只读,并以管理员身份重新运行。',\n failFsUnavailableHint: '安装过程中 pnpm 无法把文件写进本机磁盘(这类报错与装哪个插件无关,任何插件装在同一目录都会失败,不是插件本身的问题)。请按报错对号入座:① 磁盘空间不足(ENOSPC / no space left on device,Windows 为 os error 112)——请清理 profile 所在磁盘的剩余空间后重试;② 磁盘或挂载点只读、带写保护(EROFS / read-only file system,Windows 为 os error 19)——请确认 profile 目录所在磁盘可写(外接盘/U 盘、带写保护的移动盘或只读挂载的分区都会触发),必要时把插件目录换到系统盘的可写位置;③ 进程可用的文件句柄被耗尽(EMFILE / ENFILE / too many open files)——请关闭占用大量文件的程序并重启 DeepSeek Harness 后重试。',\n failPnpmWorkspaceHint: '安装器调用 pnpm 时报「不能把依赖装到 workspace 根目录」(ERR_PNPM_ADDING_TO_ROOT):你的 profile 目录被 pnpm 视为 workspace 根目录,而本次安装命令没有声明在根目录操作,pnpm 直接拒绝执行,因此任何插件装进来都会失败。这不是插件本身的问题——可在 profile 目录(~/.dsh/profiles/<profile>)的 .npmrc 里加一行 ignore-workspace-root-check=true 后重试,或把 DeepSeek Harness 升级到最新版再试。',\n failPnpmTarballIntegrityHint: 'pnpm 报 ERR_PNPM_MISSING_TARBALL_INTEGRITY:锁文件中的 tarball 条目没有校验值,无法验证下载的包。先查看完整日志,完全退出 DeepSeek Harness,并检查、备份当前 profile 的 package.json、pnpm-lock.yaml 和 pnpm-workspace.yaml。确认依赖来源后,将 pnpm-lock.yaml 改名保留,再通过同一 DSH 安装器安装适配当前宿主版本的插件,重新生成锁文件。重建会重新解析 profile 依赖,请核对新旧版本;保持完整性校验开启。',\n failPnpmPolicyHint: '安装器调用 pnpm 时被其供应链安全策略拦截——装任何插件都会撞墙,不是插件本身的问题。分两种情况处理:① 提示「Minimum release age」(ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION):包发布还不满 24 小时,pnpm 11 出于安全会拒收这种刚发布的新包。可在 pnpm 配置(pnpm-workspace.yaml)里加 minimumReleaseAge: 0 豁免,或等满 24 小时后重试。② 提示「untrusted origin」(ERR_PNPM_UNTRUSTED_ORIGIN):依赖来源不被本机 pnpm 信任,通常是该 profile 里之前用 github: 或非官方 npm 源装过插件,锁文件记录了不受信任的来源。请删除该 profile 目录下的 node_modules 与 pnpm-lock.yaml 后重新安装(可先到「系统日志」或 ~/.dsh/profiles/<profile>/hub.log 查看完整报错)。',\n // minimumReleaseAge 专属:从报错里算出确切的可重试时刻({time}),让用户知道「何时能再装」,\n // 而不是笼统地让等 24 小时(见 issue #121)\n failPnpmReleaseAgeHint: '安装器调用 pnpm 时被其供应链安全策略拦住了,任何插件装进这个 profile 都会先撞上它——与插件本身无关。原因是这个包发布还不满 24 小时,pnpm 11 出于安全会拒收刚发布的新包,这段时间内该 profile 的安装与卸载都会被拦下。可重试时间:{time}(即该包发布满 24 小时后)。如确需立刻安装,可在 profile 目录(~/.dsh/profiles/<profile>)的 pnpm-workspace.yaml 里加 minimumReleaseAge: 0 豁免,但这会放宽整个 profile 的供应链保护。',\n // 自定义安装三卡片入口的渠道名(报错/日志溯源:本次安装从哪个入口发起)\n installChannelNpm: 'NPM 包',\n installChannelGit: 'GitHub 源码',\n installChannelDsh: 'DSH 命令',\n // 报错/通知中心的入口溯源行:前缀在错误正文顶部,精准指出自定义安装是从哪张卡片发起的\n installEntryLine: '安装入口:{c}。',\n reportIssue: '去插件仓库提交 Issue',\n detail: '打开详情',\n noResult: '没有找到匹配的插件',\n noResultDesc: '换个关键词试试,或前往网站浏览全部插件。',\n today: '今天更新',\n daysAgo: '更新于 {days} 天前',\n monthsAgo: '更新于 {months} 个月前',\n yearsAgo: '更新于 {years} 年前',\n pluginsTotal: '结果 {n} 条插件',\n // 分类按钮不带数量,选中分类后在列表头部显示筛选结果数\n filterResults: '结果 {n} 条插件',\n more: '还有 {n} 个插件,去网站查看全部',\n browseAll: '浏览全部 {n} 个插件',\n verified: '已验证',\n // 版本与更新:有 release 比版本号;无 release 的仓库比仓库最近更新时间(有新提交即提示更新)\n version: '版本',\n update: '可更新',\n updateAvailable: '有更新',\n updateAvailableHint: '检测到更新:有版本号的仓库比对版本号,无版本号的仓库比对仓库最近更新时间',\n hubUpdateHint: '检测到 DSH Plugin Hub 新版本,点击查看更新内容并更新',\n hubUpdateTitle: 'DSH Plugin Hub 有新版本',\n hubUpdateDesc: 'v{version} 已发布,点击下方按钮即可更新,完成后需重启宿主生效。',\n hubUpdatePublished: '发布于',\n hubUpdateNotes: '更新记录',\n hubUpdateLater: '稍后再说',\n versionHint: '查看版本信息与更新记录',\n hubCurrentTitle: '当前版本',\n hubCurrentDesc: '你正在使用 v{version},已是最新版本。',\n hubUpToDate: '已是最新版本',\n // 头部「关注我们」弹窗:平台介绍 + 用户反馈群二维码(内容由 Worker /about Markdown 推送,非写死)\n followUs: '关注我们',\n aboutTitle: '关注我们',\n aboutDesc: '了解 DSH Plugin Hub 是做什么的,加入用户反馈群随时交流。',\n aboutEmpty: '内容暂未发布,敬请期待。',\n aboutUpdated: '更新于',\n empty: '该分类暂无插件',\n dataFrom: '数据源 api.dsh-plugin.org · 每日人工更新',\n}\n\nexport const en = {\n nav: 'Plugin Hub',\n title: 'DSH Plugin Hub',\n // Plugin counts are filled from the live /api/stats.json ({total}/{verified}), never hardcoded\n tagline: 'DSH Plugin Hub: a human-verified, free marketplace for DeepSeek Harness plugins',\n adBadge: 'Featured',\n ad: 'DSH Plugin Hub: {total} plugins indexed, {verified} human-verified, updated daily',\n search: 'Search plugins by name, description, tags…',\n all: 'All',\n sortStars: 'Stars',\n sortForks: 'Forks',\n sortUpdated: 'Recently updated',\n sortNewest: 'Newest added',\n sortAria: 'Plugin sort order',\n openHint: 'Open dsh-plugin.org',\n toggleLangHint: 'Switch language',\n githubHint: 'View source on GitHub',\n fork: 'Fork',\n loading: 'Loading plugin data…',\n failed: 'Failed to load plugin data',\n // Precise hints when the catalog cannot load: distinguished by whether a proxy is configured\n failedDescNoProxy: 'Your network seems unreachable, so the plugin catalog could not be loaded. Please check your connection and retry; or open the hub in your browser with the button above.',\n failedDescProxy: 'Your network seems unreachable, or the HTTP proxy in Settings is unreachable, so the plugin catalog could not be loaded. Please check the proxy address and your connection, then retry; or open the hub in your browser with the button above.',\n retry: 'Retry',\n install: 'Install',\n // AI-flagged plugins that may need command-line help (webInstallable=false): one-click install still allowed,\n // on failure the user is guided to copy the command into the dsh terminal\n cliOnlyHint: 'This plugin may need command-line help; if it fails, copy the command above and run it in your dsh terminal',\n failedCopyHint: 'Install failed. Copy the command above and run it manually in your dsh terminal (native build scripts may need manual approval, e.g. pnpm approve-builds)',\n toastCopied: 'Install command copied — paste it in your dsh terminal',\n installed: 'Installed',\n // Primary navigation: Market / Installed / Custom / Settings\n viewMarket: 'Market',\n viewInstalled: 'Installed',\n viewCustom: 'Custom',\n viewSettings: 'Settings',\n viewMarketHint: 'Browse and discover plugins',\n viewInstalledHint: 'Manage installed plugins',\n viewCustomHint: 'Install npm packages or GitHub sources manually',\n viewSettingsHint: 'Network sources and preferences',\n // Installed view\n installedEmpty: 'No plugins installed yet',\n installedEmptyDesc: 'Go to Custom to add an npm package or GitHub source manually',\n npmInstallLabel: 'npm package / command',\n npmInstallPlaceholder: 'npm install <pkg> or a bare package name',\n npmInstallExample: 'Native commands: npm install lodash, npm i lodash, pnpm add @scope/pkg',\n npmInstallExample2: 'Global CLI: npm install -g @scope/cli; or just type a package name like lodash',\n npmInstallInvalid: 'Enter an npm package name (e.g. lodash, @scope/pkg), or a native install command (e.g. npm install lodash, npm i lodash, pnpm add @scope/pkg, npm install -g @scope/cli)',\n gitInstallLabel: 'GitHub source',\n gitInstallPlaceholder: 'Repository address',\n gitInstallExample: 'e.g. owner/repo or https://github.com/owner/repo',\n gitInstallInvalid: 'Enter a GitHub repository address, e.g. owner/repo or https://github.com/owner/repo',\n dshCmdLabel: 'DeepSeek Harness command',\n dshCmdPlaceholder: 'Paste an official dsh plugin command',\n dshCmdInsertHubUpdate: 'Insert update command',\n dshCmdExample: 'e.g. dsh plugin --profile {profile} add github:owner/repo, or dsh plugin --profile {profile} update dsh-plugin',\n dshCmdInvalid: 'Paste an official dsh plugin command (--profile required, add / update), e.g. dsh plugin --profile {profile} update dsh-plugin',\n installHelp: 'Help',\n helpModalTitle: 'Supported command formats',\n npmInstallHelp: 'lodash or @scope/pkg\\tjust type the package name\\nnpm install lodash\\nnpm i lodash\\npnpm add @scope/pkg\\npnpm i @scope/pkg\\nnpm install -g @scope/cli\\tinstalls the CLI globally, not shown in Installed',\n gitInstallHelp: 'owner/repo\\nhttps://github.com/owner/repo\\ngithub:owner/repo\\ngit+https://github.com/owner/repo.git\\ngit@github.com:owner/repo.git',\n dshCmdHelp: 'dsh plugin --profile {profile} add <target>\\tinstall\\ndsh plugin --profile {profile} update <target>\\tupdate an installed target to the latest version\\ndsh plugin --profile={profile} add <target>\\ndsh plugin --profile={profile} update <target>\\n\\t--profile is required (prefilled with the current profile here) and there is no -p shorthand; <target> can be an npm package or github:owner/repo; uninstall from the Installed list',\n globalNpmHint: 'This installs CLI tools globally (npm install -g). They won\\'t appear in Installed and no host restart is needed.',\n installCliBtn: 'Install',\n // Install channel disabled (security-trust toggle off → card disabled, guides to settings)\n channelDisabledHint: 'This install channel is disabled — enable it in Settings → Security & Trust',\n goToSettings: 'Go to Settings',\n // Custom install view: standalone top-level section, description text\n customViewDesc: 'Manually install an npm package, a GitHub source, or paste an official dsh plugin command. Finished installs appear in Installed, marked as custom.',\n customLabel: 'Custom install',\n installedSearch: 'Search installed plugins…',\n installedFilterCatalog: 'Catalog',\n hubInstall: 'Hub',\n hubInstallHint: 'From the plugin hub catalog',\n manualInstall: 'Manual',\n manualInstallHint: 'Not from the catalog — installed via the command line',\n filterByLabel: 'Source',\n sortByLabel: 'Sort',\n sortName: 'Name',\n sortInstalledAt: 'Recent',\n detailTitle: 'Plugin details',\n detailCategory: 'Category',\n detailStats: 'Repo stats',\n statusLabel: 'Status',\n statusRunning: 'Running',\n statusPending: 'Restart pending',\n exampleLabel: 'DeepSeek Harness built-in example',\n exampleHint: 'DeepSeek Harness built-in example — not a marketplace dsh plugin, the host does not load it, no restart needed',\n restart: 'Restart',\n installedVersionLabel: 'Installed version',\n catalogLatest: 'latest in catalog',\n installPath: 'Install path',\n copyPath: 'Copy path',\n openFolder: 'Show in folder',\n openFolderFail: 'Could not open the folder — copy the path instead',\n revealFolder: 'Show in Finder',\n installedAtLabel: 'Installed at',\n lastUpdatedLabel: 'Last updated',\n detailCatalog: 'View details',\n packageName: 'Package',\n versionUpHint: 'v{from} → v{to} available — Update reinstalls in place',\n // Settings view: Updates & Sources / Security & Trust / Diagnostics / System Logs\n settingsUpdate: 'Update Settings',\n settingsUpdateDesc: 'Update checks and the network channels used for installs',\n settingsCheckOnStart: 'Check for updates on startup',\n settingsCheckOnStartDesc: 'Check installed plugins for new versions when the hub opens; you will be notified when updates are found',\n settingsAutoInstall: 'Auto-install updates',\n settingsAutoInstallDesc: 'Install detected updates in the background without asking (a host restart applies them)',\n settingsProxy: 'HTTP proxy',\n settingsProxyDesc: 'Route npm, git and catalog requests through this proxy; leave empty to connect directly',\n // Live proxy reachability probe: reported after the user stops typing (an unreachable\n // address can still be saved — users may fill it in before actually starting the proxy)\n proxyCheckChecking: 'Testing this proxy address…',\n proxyCheckOk: 'Reachable — installs and catalog requests will route through it',\n proxyCheckFail: 'Unreachable, but you can still save it; make sure the proxy is running and the address and port are correct',\n // Failure reason: Windows Schannel aborts the handshake when revocation info (CRL/OCSP) is unreachable — not a bad proxy address\n proxyCheckRevocation: 'Certificate revocation check blocked (Windows Schannel could not fetch CRL/OCSP), so the handshake was aborted — a local TLS issue, not a bad proxy address',\n settingsMirror: 'npm mirror',\n settingsMirrorDesc: 'Unset by default — follows local npm config; pick a domestic mirror if slow',\n mirrorNone: 'Unset (follow local npm config)',\n mirrorOfficial: 'Official registry.npmjs.org',\n mirrorNpmmirror: 'Alibaba npmmirror',\n mirrorTencent: 'Tencent Cloud mirror',\n mirrorTsinghua: 'Tsinghua TUNA mirror',\n settingsSecurity: 'Security & Trust',\n settingsSecurityDesc: 'Toggles for the three command-line install channels: npm packages, GitHub sources and DSH commands',\n settingsEnableNpm: 'Enable npm installs',\n settingsEnableNpmDesc: 'Allow installing npm packages from the command line; turning this off rejects package-name installs',\n settingsEnableGit: 'Enable GitHub source installs',\n settingsEnableGitDesc: 'Allow installing from GitHub sources on the command line; turning this off rejects repository-address installs',\n settingsEnableDsh: 'Enable DSH command installs',\n settingsEnableDshDesc: 'Allow pasting a dsh plugin command to install; turning this off disables the command input',\n settingsDiagnostics: 'System Diagnostics',\n settingsDiagnosticsDesc: 'Check the connectivity of install channels: npm registry, GitHub and the catalog site',\n settingsLogs: 'System Logs',\n settingsLogsDesc: 'Local record of installs / uninstalls, settings changes and diagnostics — export the full log to troubleshoot',\n logsHeadHint: 'Records installs, uninstalls, settings changes and diagnostics; keeps the latest 2,000 entries',\n logsRefresh: 'Refresh log',\n logsExport: 'Export log',\n logsLoading: 'Reading log…',\n logsEmpty: 'No log entries yet',\n logsLoadFail: 'Failed to read the log; try again later',\n // Log-viewer dialog: a built-in window that loads the log in pages, filterable by type × level\n logModalTitle: 'Log viewer',\n logViewerOpen: 'Open log viewer',\n logViewerDesc: 'View the local log in a built-in window; filter by type and level to pinpoint install / uninstall / update incompatibilities',\n logPathLabel: 'Log file',\n logOpenFile: 'Reveal',\n logOpenFileTip: 'Reveal the log file in your system file manager',\n logOpenFileFail: 'Could not open; locate the file manually',\n logClearAll: 'Clear all logs',\n logClearConfirmTitle: 'Clear all logs?',\n logClearConfirmDesc: 'All log entries will be deleted. This cannot be undone.',\n logClearing: 'Clearing…',\n logClearAllTip: 'Delete all log entries',\n logClearFailed: 'Failed to clear; try again',\n logPathSettingTitle: 'Log Location',\n logPathSettingDesc: 'Stored in the host config directory by default — set a directory or a .log file path to store elsewhere',\n logPathPlaceholder: 'Leave empty for default',\n logPathReset: 'Reset to default',\n logPathResetHint: 'The field shows the location currently in use',\n logPathSave: 'Save',\n logPathSaving: 'Saving…',\n logPathSaved: 'Saved — new logs will be written there',\n logPathSaveFail: 'Could not save: the location is not writable',\n logPathChange: 'Change',\n logPathBrowse: 'Browse…',\n logPathBrowseFail: 'Folder picker unavailable — type the path manually',\n logCatAll: 'All types',\n logCatInstall: 'Install',\n logCatUninstall: 'Uninstall',\n logCatUpdate: 'Update',\n logCatDiagnostics: 'Diagnostics',\n logCatSettings: 'Settings',\n logCatSystem: 'System',\n logLvAll: 'All levels',\n logLvError: 'Error',\n logLvWarn: 'Warn',\n logLvSuccess: 'Success',\n logLvInfo: 'Info',\n logLvDebug: 'Debug',\n logSearchPlaceholder: 'Search event or message…',\n logLoadMore: 'Load more',\n logNoMore: 'All loaded · {n} total',\n logCount: '{n} entries',\n logEmptyFilter: 'No matching log entries',\n settingsDiagFail: 'Unreachable',\n // System diagnostics channel list: one-click full check + one row per channel, click to re-probe\n diagNpm: 'npm registry',\n // Diagnostics npm row: shown when no mirror is configured (probe still targets the official registry, the fallback)\n diagNpmUnset: 'Unset (follow local npm config)',\n diagGithub: 'GitHub',\n diagCatalog: 'Catalog site',\n diagCatalogTarget: 'Plugin marketplace',\n diagProxy: 'HTTP proxy',\n diagOk: 'OK',\n diagChecking: 'Checking…',\n diagIdle: 'Not checked',\n diagRecheck: 'Click to re-check this channel',\n diagRunAll: 'Run diagnostics',\n diagHeadHint: '{n} channels — click any row to re-check it alone',\n diagSummaryRunning: 'Checking channels…',\n diagSummaryOk: 'All channels reachable',\n diagSummaryFail: 'Unreachable channel(s) — click a row to re-check',\n // Failure reason: Windows Schannel aborts the handshake when revocation info (CRL/OCSP) is unreachable (easily mistaken for a network outage)\n diagFailRevocation: 'Cert check blocked',\n diagFailRevocationHint: 'The system curl cannot fetch certificate revocation info (CRL/OCSP, required by Windows Schannel), so the TLS handshake is aborted — this is not a network outage, and npm/git may still work. curl 7.70+ downgrades the check to best-effort, or switch to a network that can reach the revocation service.',\n settingsEnvSnapshot: 'System version',\n settingsEnvSnapshotDesc: 'Copy host version and system info for pasting into issue reports',\n settingsEnvCopy: 'Copy',\n // Restore defaults: first-level menu + its own settings card\n settingsReset: 'Restore Defaults',\n settingsResetDesc: 'Restore update policy, npm mirror, proxy and security restrictions to factory defaults in one go',\n settingsResetDetail: 'Reset update policy, npm mirror, proxy and security restrictions to factory defaults',\n settingsResetRun: 'Restore Defaults',\n settingsResetConfirm: 'Restore Defaults',\n settingsResetConfirmDetail: 'Reset all settings to factory defaults? Update policy, npm mirror, proxy and security restrictions will be cleared.',\n // Update notice (notification center item title)\n updateNoticeTitle: 'Update available',\n updateNoticeGo: 'Update',\n ignoreUpdateRun: 'Ignore this update',\n ignoreUpdateConfirmTitle: 'Ignore this update?',\n ignoreUpdateConfirmDetail: 'This version will no longer notify you. You will be alerted again when the next version is released.',\n ignoreUpdateConfirm: 'Ignore',\n uninstall: 'Uninstall',\n uninstalling: 'Removing…',\n uninstallTitle: 'Confirm uninstall?',\n uninstallDesc: 'The plugin will be removed from this environment.',\n uninstallDone: 'Uninstalled',\n uninstallFail: 'Removal failed — try again',\n uninstallResultTitle: 'Removed',\n uninstallResultDesc: 'The plugin has been removed from this environment.',\n confirmTitle: 'Confirm install',\n confirmDesc: 'Review the plugin repository source code carefully before installing.',\n confirmPlugin: 'Plugin',\n confirmSource: 'Source',\n confirmCommand: 'Command',\n copyInstallCommand: 'Copy install command',\n copyCmdLabel: 'Copy',\n copyUninstallCommand: 'Copy uninstall command',\n cancelUninstall: 'Cancel uninstall',\n uninstallConfirm: 'Confirm uninstall',\n installNow: 'Install',\n installing: 'Installing…',\n installDone: 'Installed',\n // Updated (notification center distinguishes install/update): update = in-place reinstall to latest\n updateDone: 'Updated',\n installResultTitle: 'Plugin installed successfully',\n installResultDesc: '',\n // Update semantics: the \"update\" action re-runs add in place — copy differentiates install vs update\n confirmUpdateTitle: 'Confirm update',\n updateNow: 'Update',\n updating: 'Updating…',\n queuedUpdateTitle: 'Queued for update…',\n updateResultTitle: 'Updated',\n updateResultDesc: 'The plugin has been updated to the latest version.',\n installFail: 'Install failed — copy the command instead',\n requestTimeout: 'Request timed out: GitHub may be unreachable or the network is unstable — try again later',\n confirmCancel: 'Cancel',\n doneBtn: 'Done',\n // Result-view fallback: the single \"Restart now\" only appears when a refresh cannot help\n // (hot-mount failure / non-dsh plugin / update); closing the modal means \"later\"\n restartNow: 'Restart now',\n restarting: 'Restarting…',\n restartHint: 'Restarting interrupts any in-progress install / uninstall task — its progress will be lost. Some plugins (such as plugin markets / top-level bundles) only take effect after a restart.',\n // Desktop: the app shell owns the host, so plugins cannot restart it — tell the user to quit and reopen\n toastRestartDesktop: 'In the desktop app the host is managed by the app: quit from the app menu (or tray) and open it again — the change takes effect after that restart',\n // Applied without a restart: the install was hot-mounted into the running loader;\n // the page auto-refreshes on close (no manual refresh button)\n reloadHint: 'The plugin is loaded — closing this window will refresh the page automatically.',\n toastInstalledLive: 'Installed — active now',\n toastInstalledReload: 'Installed — refreshing the page automatically…',\n done: 'Done',\n restartPendingHint: 'Installed — takes effect after restart',\n restartPendingHintUninstall: 'Removed — cleaned up after restart',\n sectionPendingRestart: 'Pending restart',\n sectionInProgress: 'In progress',\n // 通知中心:安装/卸载任务成败的持久记录(工具栏铃铛入口按钮打开)\n notifications: 'Notifications',\n notificationsHint: 'View install/remove/update notifications',\n notificationsDesc: 'Every install, remove and update notice is logged here — even if you missed the prompt, you can always check back.',\n notificationsEmpty: 'No notifications yet',\n notificationsClear: 'Clear notifications',\n notificationsClearConfirmTitle: 'Clear all notifications?',\n notificationsClearConfirmDesc: 'All notification records will be deleted. This cannot be undone.',\n removeNotification: 'Remove this notification',\n removeNotificationConfirmTitle: 'Remove this notification?',\n removeNotificationConfirmDesc: 'This notification will be removed. This cannot be undone.',\n queuedTitle: 'Queued…',\n queuedUninstallTitle: 'Queued for removal…',\n queuedHint: 'Queued — starts automatically after earlier tasks finish. You may close this window.',\n cancelTask: 'Cancel task',\n cancel: 'Cancel',\n cancelling: 'Cancelling…',\n errorTitle: 'Operation failed',\n errorTitleInstall: 'Install failed',\n errorTitleUninstall: 'Removal failed',\n // Update failed (notification center distinguishes install/update): update target reinstall failed\n errorTitleUpdate: 'Update failed',\n errorPlugin: 'Plugin',\n errorClose: 'Got it',\n errorCopy: 'Copy error',\n errCopied: 'Error copied',\n failCopy: 'Copy full log',\n failIssueHint: 'Open a pre-filled issue on the author repo with this error log (includes catalog links)',\n failIssueBig: 'Report this bug to GitHub — contribute to open source',\n // prepare script actually failed (git tarball misses submodules/build output): a packaging issue of the plugin itself — file an issue\n failPrepareHint: 'This plugin failed while running its build scripts during install (git tarballs often miss submodules or build output). This is a packaging issue of the plugin itself — please report it to the author repository.',\n // Pre-install / post-install guard hit ([packaging]): git distribution lacks build output, entry file missing = not adapted to the official default install method\n failPackagingHint: 'This plugin does not support the official default install method: its git distribution lacks the build output (the entry file declared in package.json is not in the repository), so it has not been adapted to the official install flow. Please file an Issue on the author\\'s repo asking for committed build output or an npm release.',\n // native-module build scripts ignored by pnpm by default (e.g. node-pty, ERR_PNPM_IGNORED_BUILDS): only affects plugins with native deps — a dependency/packaging issue of the plugin itself, file an issue\n failIgnoredBuild: 'This plugin (or its dependencies) needs to run build scripts, which pnpm blocks by default via its allowBuilds allowlist, so the install fails (e.g. native modules like node-pty, or the plugin\\'s own prepare script on git installs) — other plugins are unaffected. This is a dependency/packaging issue of the plugin itself. Please report it to the author repository and ask the author to ship a prebuilt variant (e.g. node-pty-prebuilt-multiarch) or drop install-time builds.',\n failNpmTooLow: 'Your local npm may be too old: npm crashed internally while resolving the plugin\\'s dependencies (a known npm bug — not a plugin issue). Please upgrade npm and retry: npm install -g npm@latest',\n failNpmTooLowV: 'Your local npm is too old (v{v}): npm crashed internally while resolving the plugin\\'s dependencies (a known npm bug — not a plugin issue). Please upgrade npm and retry: npm install -g npm@latest',\n // Pre-install connectivity probe / connection failure in the install log ([network] / git fetch timeout / DNS / TLS): a local network or proxy issue, not a plugin issue — no issue link\n failNetworkHint: 'The network could not be reached before install: the install source is unreachable (offline, DNS failure, firewall block, or a misconfigured proxy). This is not a problem with the plugin itself — please check your connection, confirm the HTTP proxy in Settings, run a connectivity check under System Diagnostics, then retry.',\n // Prominent \"cannot reach …\" line in the network-failure dialog: shows the exact unreachable address ({url})\n failNetworkRegistryHint: 'Your npm/pnpm registry is set to {host}, and the package tarball could not be downloaded from it. This usually means a private/internal mirror that has not synced the package (or requires intranet auth) — point the registry back to https://registry.npmjs.org (or make sure this source can serve the package), then retry.',\n failNetworkTarget: 'Cannot reach {url} — your network connection is down',\n // Diagnostics shortcut button under the network-down hint: jumps to Settings → System Diagnostics\n failNetworkRunDiag: 'Run a network diagnostic',\n // The request origin did not pass the local hub service check (403 untrusted origin): the request\n // never reached the install flow — nothing to do with the plugin, so point at the local address\n // and do not offer an issue link\n failOriginRejectedHint: 'This install request did not pass the marketplace origin check and was rejected by the local service, so the install never started — this is not about the plugin itself. It usually means the marketplace page was not opened from a local address (for example a LAN IP), or the host page origin was not recognized. Reopen the marketplace from localhost and retry; on the desktop app, restart the host once. If it still fails after restarting the host, your dsh-plugin version is incompatible with the host — upgrade the marketplace with dsh plugin --profile {profile} add dsh-plugin@latest, then restart the host again.',\n failDshMissingHint: 'The dsh command could not be found (it is not on the system PATH), so the installer could not run. Please make sure DeepSeek Harness is installed correctly and dsh is on your PATH (or reinstall it), then retry. This is not a problem with the plugin itself.',\n failGitMissingHint: 'The git command could not be found (Git is not installed or not on the system PATH), so GitHub-source plugins cannot be installed. Please install Git (e.g. from git-scm.com/downloads) or add git to your PATH, restart DSH, then retry. This is not a problem with the plugin itself.',\n failPnpmMissingHint: 'The installer found dsh, but pnpm is missing on this machine (dsh uses it to manage profile plugins). Please install pnpm first (e.g. npm install -g pnpm), make sure it is on your PATH, then retry. This is not a problem with the plugin itself.',\n failNpmMissingHint: 'The npm command could not be found (npm is not installed or not on the system PATH), so a global install cannot run. Please install Node.js (which bundles npm), make sure npm is on your PATH, then retry. This is not a problem with the plugin itself.',\n failPnpmStoreHint: 'pnpm reported an unexpected store location (ERR_PNPM_UNEXPECTED_STORE): the profile directory was previously set up with a different major version of pnpm, and the current pnpm refuses to reuse it — no plugin can be installed into that profile. Delete node_modules and pnpm-lock.yaml under the profile directory (see System Logs or ~/.dsh/profiles/<profile>/hub.log for the full output), then reinstall. This is not a problem with the plugin itself.',\n failPnpmUnusedPatchHint: 'pnpm reported that some patches were not used (ERR_PNPM_UNUSED_PATCH): your profile still holds a patch entry for an older dsh-plugin version (for example dsh-plugin@1.4.2), while this install resolved a different version, so pnpm aborts the whole install for safety — no plugin can be installed into that profile. This is not a problem with the plugin itself. Remove that dsh-plugin patch entry from pnpm-workspace.yaml (pnpm 11+) or from pnpm.patchedDependencies in package.json (pnpm 10) inside the profile directory (~/.dsh/profiles/<profile>), then retry.',\n // Missing dependency: name the package that 404'd (the line is skipped when it cannot be parsed),\n // then give the removal instructions\n failPnpmMissingDepTarget: '{pkg} was not found on the npm registry (404)',\n failPnpmMissingDepHint: 'pnpm reported that a package does not exist on the npm registry (ERR_PNPM_FETCH_404): your profile keeps a dependency on a package that was never published, and pnpm hits it every time it resolves dependencies — no plugin can be installed into that profile. This is not a problem with the plugin itself. Remove that dependency from package.json inside the profile directory (~/.dsh/profiles/<profile>) — along with its entry in pnpm-lock.yaml, or the lockfile itself — then retry.',\n failFileLockedHint: 'During install, pnpm could not replace a file inside the profile because another program is holding it (on Windows this shows as os error 32, \"the process cannot access the file because it is being used by another process\"). Usually DeepSeek Harness itself or a real-time antivirus scan holds the handle. This is not a problem with the plugin itself — fully quit DeepSeek Harness (on Windows, confirm in Task Manager that the process has ended, and temporarily disable real-time antivirus protection if needed), then retry.',\n failAccessDeniedHint: 'During install, Windows denied pnpm access to a file inside the profile (this shows as os error 5, \"Access is denied\"; on Node the equivalent codes are EPERM / EACCES). Typical causes: the file or directory is held by another process, the file is marked read-only, the directory permissions are restricted, or a real-time antivirus scan blocked the write. This is the same class of local file-system problem as a locked file (os error 32) — no plugin can be installed into that directory, so it is not a problem with the plugin itself. Fully quit DeepSeek Harness (on Windows, confirm in Task Manager that the process has ended, and temporarily disable real-time antivirus protection if needed), then retry. If it still fails, check whether the profile directory or its files are read-only and run as administrator.',\n failFsUnavailableHint: 'During install, pnpm could not write files to the local disk — this has nothing to do with which plugin you are installing: any plugin installed into the same directory would fail the same way, so it is not a problem with the plugin itself. Match the error you see: ① Out of space (ENOSPC / no space left on device, os error 112 on Windows) — free up space on the drive that holds the profile and retry. ② Read-only or write-protected volume (EROFS / read-only file system, os error 19 on Windows) — make sure the drive holding the profile directory is writable (external or USB drives, write-protected media, and read-only mounts all trigger this); move the plugin directory to a writable location on the system drive if needed. ③ File handles exhausted (EMFILE / ENFILE / too many open files) — close programs that hold many files open, restart DeepSeek Harness, then retry.',\n failPnpmWorkspaceHint: 'pnpm refused to add the dependency to the workspace root (ERR_PNPM_ADDING_TO_ROOT): the profile directory is treated as a pnpm workspace root, and this install command did not declare that it operates at the root, so pnpm rejected it outright — no plugin can be installed into that profile. This is not a problem with the plugin itself. Add `ignore-workspace-root-check=true` to the `.npmrc` inside the profile directory (~/.dsh/profiles/<profile>) and retry, or upgrade DeepSeek Harness and try again.',\n failPnpmTarballIntegrityHint: 'pnpm reported ERR_PNPM_MISSING_TARBALL_INTEGRITY: a tarball entry in the lockfile has no checksum to verify the downloaded package. Read the full log, fully quit DeepSeek Harness, and inspect and back up package.json, pnpm-lock.yaml and pnpm-workspace.yaml in the affected profile. Once the dependency sources are verified, rename pnpm-lock.yaml to preserve it, then use the same DSH installer to install a plugin version compatible with the host and regenerate the lockfile. This resolves profile dependencies again: compare the old and new versions, and keep integrity checks enabled.',\n failPnpmPolicyHint: 'The installer was blocked by pnpm supply-chain security policy — every plugin install would hit the same wall, so this is not a problem with the plugin itself. Two cases: ① \"Minimum release age\" (ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION): the package was published less than 24 hours ago, and pnpm 11 refuses freshly-published packages for safety. Add minimumReleaseAge: 0 to your pnpm config (pnpm-workspace.yaml) to opt out, or wait until the 24 hours have passed and retry. ② \"untrusted origin\" (ERR_PNPM_UNTRUSTED_ORIGIN): a dependency source is not trusted by this machine, usually because plugins were previously installed via github: or a non-official npm registry, so the lockfile records an untrusted source. Delete node_modules and pnpm-lock.yaml under the profile directory (see System Logs or ~/.dsh/profiles/<profile>/hub.log for the full output), then reinstall.',\n // minimumReleaseAge only: compute the exact retry time ({time}) from the error so the user knows\n // when installs will work again, instead of the vague \"wait 24 hours\" (see issue #121)\n failPnpmReleaseAgeHint: 'The installer was blocked by pnpm supply-chain security policy, and every plugin installed into this profile would hit the same wall — this is not a problem with the plugin itself. The package was published less than 24 hours ago, and pnpm 11 refuses freshly-published packages for safety, so both installs and removals are blocked for this profile in the meantime. Retry after: {time} (i.e. 24 hours after the package was published). If you must install right now, add minimumReleaseAge: 0 to pnpm-workspace.yaml inside the profile directory (~/.dsh/profiles/<profile>) to opt out, but that loosens supply-chain protection for the whole profile.',\n // Custom install entry channel names (the three cards) — used in error/log traceability\n installChannelNpm: 'NPM package',\n installChannelGit: 'GitHub source',\n installChannelDsh: 'DSH command',\n // Entry traceability line prefixed at the top of the error text: which card initiated this install\n installEntryLine: 'Install entry: {c}.',\n reportIssue: 'Report an Issue to the plugin repo',\n detail: 'Open details',\n noResult: 'No plugins match your search',\n noResultDesc: 'Try another keyword, or browse all plugins on the website.',\n today: 'updated today',\n daysAgo: 'updated {days}d ago',\n monthsAgo: 'updated {months}mo ago',\n yearsAgo: 'updated {years}y ago',\n pluginsTotal: 'Results: {n} plugins',\n // Category chips carry no counts; the filtered result count shows in the list header\n filterResults: 'Results: {n} plugins',\n more: '{n} more on the website',\n browseAll: 'Browse all {n} plugins',\n verified: 'Verified',\n // Version & updates: repos with a release are compared by tag; repos without one by last push time (new commits → update)\n version: 'Version',\n update: 'Update',\n updateAvailable: 'Update available',\n updateAvailableHint: 'An update was detected: repos with a release are compared by tag, repos without one by last push time',\n hubUpdateHint: 'A new DSH Plugin Hub version is available — click to view the changelog and update',\n hubUpdateTitle: 'A new DSH Plugin Hub version is available',\n hubUpdateDesc: 'v{version} has been released — click below to update, then restart the host to apply it.',\n hubUpdatePublished: 'Published',\n hubUpdateNotes: \"What's new\",\n hubUpdateLater: 'Later',\n versionHint: 'View version info and changelog',\n hubCurrentTitle: 'Current version',\n hubCurrentDesc: 'You are on v{version} — this is the latest version.',\n hubUpToDate: 'Up to date',\n // Header \"Follow us\" modal: platform intro + user feedback group QR (content pushed via Worker /about Markdown)\n followUs: 'Follow us',\n aboutTitle: 'Follow us',\n aboutDesc: 'Learn what DSH Plugin Hub does and join our user feedback group.',\n aboutEmpty: 'Content not published yet — stay tuned.',\n aboutUpdated: 'Updated',\n empty: 'No plugins in this category yet',\n dataFrom: 'Data from api.dsh-plugin.org · curated daily',\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 预构建 GitHub release 安装目标(目录权威命令 → 可安装直链)。\n * 部分插件(如 loopx)把构建产物发布成 GitHub release 的 .tgz,仓库 HEAD 反而是\n * monorepo 根、走 git 直装会因缺入口文件失败;目录下发的权威安装命令直接指向该\n * release 包。这里把「目录命令」解析成安全的 release 目标,供客户端选路与服务端\n * 校验共用(单一事实来源,避免两端口径漂移)。\n *\n * 只接受固定形态的 HTTPS `github.com/<owner>/<repo>/releases/download/<tag>/<asset>.tgz`:\n * 目录命令是展示数据、绝非 shell 代码,绝不执行命令文本;跨仓跳转、外部主机、凭据、\n * 移动的 latest 链接、query/fragment、多余 CLI 参数与 shell 片段一律拒绝。\n */\n\n/** release 包目标及其所属仓库身份(owner/repo);非法返回 null。 */\nexport interface GithubReleaseTarget {\n /** 规范化后的安装目标(HTTPS 直链) */\n target: string\n /** 该直链所属仓库(owner/repo):供已装态读回、队列去重与展示身份复用 */\n repo: string\n}\n\n/** 目录权威命令:`dsh plugin --profile <p> add|update <target>`(与 profile.ts installTargetOf 同口径)。 */\nconst DSH_PLUGIN_CMD_RE = /^dsh[ \\t]+plugin[ \\t]+--profile(?:[ \\t]+|=)[A-Za-z0-9_-]+[ \\t]+(?:add|update)[ \\t]+(.+)$/i\n\n/** 固定形态的 release .tgz 直链:主机、路径段与扩展名全部锁死。 */\nconst RELEASE_URL_RE = /^https:\\/\\/github\\.com\\/([A-Za-z0-9._-]+)\\/([A-Za-z0-9._-]+)\\/releases\\/download\\/([A-Za-z0-9._+-]+)\\/([A-Za-z0-9._+-]+\\.tgz)$/\n\n/**\n * 解析一个 release 安装目标。\n * @param value - 目录命令(`dsh plugin --profile web add <url>`)或裸直链。\n * @returns 命中返回 `{ target, repo }`,否则 null。\n */\nexport function githubReleaseTarget(value: string): GithubReleaseTarget | null {\n const input = typeof value === 'string' ? value.trim() : ''\n if (input === '') return null\n const command = DSH_PLUGIN_CMD_RE.exec(input)\n const raw = command !== null ? command[1].trim() : input\n const match = RELEASE_URL_RE.exec(raw)\n if (match === null) return null\n // 拒绝 `.` / `..` 路径段,杜绝借路径穿越跳出 release 目录\n if (match.slice(1).some((part) => part === '.' || part === '..')) return null\n return { target: raw, repo: `${match[1]}/${match[2]}` }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Install target/command helpers: decide the install channel (npm package\n * vs prebuilt GitHub release vs explicit-HTTPS GitHub), build the display\n * command and normalize a raw install spec back to its owner/repo identity.\n */\nimport type { HubPlugin } from '../types.ts'\nimport { githubReleaseTarget } from '../../server/services/install/release-target.ts'\n\n/** Backend attempts are chronological; report the last executed command before a display fallback.\n * These prefixes are the task queue's recorded command shapes, never commands to execute here.\n */\nexport function executedCommandOf(command?: string, attempts?: string[]): string | undefined {\n if (attempts === undefined) return command\n return attempts.slice().reverse().find((attempt) =>\n /^dsh plugin --profile(?:=| )\\S+ (?:add|remove|update) \\S/.test(attempt)\n || /^npm install -g \\S/.test(attempt))\n}\n\n/**\n * 安装通道决策(用户无感知):目录探测到 npm 包名 → 用 npm 包名安装\n * (走 npm registry tarball,更快、与 GitHub 网络无关);其次用「同仓库」的权威\n * release 包直链(仓库 HEAD 往往是 monorepo 根、装不上,release .tgz 才是完整产物);\n * 都没有 → git 直装。\n * 返回值 target 即传给后端 /install 的安装目标(npm 包名 / release URL / owner/repo)。\n */\nexport function installTargetOf(p: HubPlugin): { target: string; via: 'npm' | 'release' | 'github' } {\n const pkg = (p.source?.npmPackage ?? '').trim()\n const repo = (p.source?.repo ?? '').trim()\n if (pkg && repo) return { target: pkg, via: 'npm' }\n // 目录下发的权威命令若是「同仓库」的固定 release 直链,改走该预构建包;\n // 跨仓 / 非法 release 目标不采信,退回 git 直装。\n const release = githubReleaseTarget(p.install?.githubCommand ?? '')\n if (release !== null && repo !== '' && release.repo.toLowerCase() === repo.toLowerCase()) {\n return { target: release.target, via: 'release' }\n }\n return { target: repo, via: 'github' }\n}\n\n/** 展示用安装命令(复制/弹窗):目录下发的权威命令优先(CLI-only 插件如 dsh-tui\n * 需专属 profile(--profile dsh-tui),无法从 repo/npm 包名推断,必须用官方命令);\n * 常规插件无目录命令时按通道回退生成:npm 显示包名,git 显示显式 HTTPS URL。 */\nexport function installCommandOf(p: HubPlugin, withProfile = false): string {\n const { target, via } = installTargetOf(p)\n if (via === 'npm') {\n const cmd = p.install?.command\n if (cmd) return cmd\n } else {\n // release 与 git 通道共用目录下发的 githubCommand(git+ 显式 HTTPS 或 release 直链)\n const cmd = p.install?.githubCommand\n if (cmd) return cmd\n }\n const prefix = `dsh plugin${withProfile ? ' --profile web' : ''} add `\n if (via === 'npm' || via === 'release') return `${prefix}${target}`\n return `${prefix}git+https://github.com/${target}.git`\n}\n\n/** Normalize a task/install target to its owner/repo display identity. */\nexport function repoFromInstallTarget(value: string): string {\n const input = value.trim()\n // release 直链(预构建 .tgz)走同一条身份归一化:解析出所属仓库,已装态/更新信号才能\n // 认回目录条目;仅接受固定形态直链,跨仓/非法目标不接受,继续走下面的常规解析。\n const release = githubReleaseTarget(input)\n if (release !== null) return release.repo\n if (/^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$/.test(input)) return input\n const patterns = [\n /^github:([^/]+)\\/([^/]+)$/i,\n /^(?:git\\+)?https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?(?:[?#].*)?$/i,\n /^(?:git\\+)?ssh:\\/\\/(?:git@)?github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?(?:[?#].*)?$/i,\n /^git@github\\.com:([^/]+)\\/([^/]+?)(?:\\.git)?(?:[?#].*)?$/i,\n ]\n for (const pattern of patterns) {\n const match = pattern.exec(input)\n if (match !== null) return `${match[1]}/${match[2]}`\n }\n return value\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Constants: site URLs, category metadata and sort keys. Pure data — no\n * side effects, no network — so every consumer shares one definition.\n */\nimport type { LocaleId } from '../types.ts'\n\n/** 插件市场官网地址。 */\nexport const SITE_URL = 'https://dsh-plugin.org/'\n\n/** 插件市场源码仓库:头部右上角 GitHub 图标的跳转地址 */\nexport const GITHUB_URL = 'https://github.com/dshplugin/dsh-plugin-hub'\n\n/** Hub 自身在目录数据里的仓库标识:头部版本号旁的「可更新」徽标按它定位自己。 */\nexport const HUB_REPO = 'dshplugin/dsh-plugin-hub'\n\n/**\n * Hub 自我更新版本控制(接口中心 Pages:api.dsh-plugin.org,静态 JSON 发布)。\n * 发新版 = 在 api-center 的 releases/ 写发版记录 + 重新部署,hub.json 随之更新,\n * 所有已装用户的「可更新」徽标即可见,不经过主站目录数据管道。\n * 响应:{ version: string | null, publishedAt: string | null, notes: string | {zh,en} | null }\n */\nexport const HUB_UPDATE_URL = 'https://api.dsh-plugin.org/hub.json'\n\n/** 接口中心「关注我们」内容(静态 JSON,由 api-center 的 about.md 构建生成,Markdown)。 */\nexport const HUB_ABOUT_URL = 'https://api.dsh-plugin.org/about.json'\n\n/** 构建时由 tsdown 从 package.json 注入的插件版本号(见 tsdown.config.ts define)。 */\ndeclare const __PLUGIN_VERSION__: string\n\n/**\n * 插件当前版本号,供头部标题展示「DSH Plugin Hub v0.1.1」。\n * tsdown 构建时用 define 把 __PLUGIN_VERSION__ 替换成 package.json 的版本号;\n * node --test 直接 import 本模块时该标识符不存在,typeof 守卫兜底为空串。\n */\nexport const PLUGIN_VERSION: string =\n typeof __PLUGIN_VERSION__ === 'string' ? __PLUGIN_VERSION__ : ''\n\nexport const CATEGORY_ORDER = [\n 'interface', 'session', 'memory', 'tools', 'agent', 'workflow',\n 'integration', 'model', 'dev', 'knowledge', 'fun',\n]\n\n/** 分类标签按界面语言取词;未知 key 原样返回。 */\nexport function categoryLabel(\n map: Record<string, { zh: string; en: string }>,\n key: string,\n lang: LocaleId,\n): string {\n return map[key]?.[lang] ?? key\n}\n\nexport const CATEGORY_LABELS: Record<string, { zh: string; en: string }> = {\n interface: { zh: '界面与体验', en: 'UI & Experience' },\n session: { zh: '会话与消息', en: 'Sessions & Messages' },\n memory: { zh: '记忆与上下文', en: 'Memory & Context' },\n tools: { zh: '工具与能力', en: 'Tools & Capabilities' },\n agent: { zh: '技能与智能体', en: 'Skills & Agents' },\n workflow: { zh: '工作流与自动化', en: 'Workflow & Automation' },\n integration: { zh: '集成与连接', en: 'Integrations & Connections' },\n model: { zh: '模型与推理', en: 'Models & Reasoning' },\n dev: { zh: '开发与运维', en: 'Development & Operations' },\n knowledge: { zh: '数据与知识', en: 'Data & Knowledge' },\n fun: { zh: '娱乐', en: 'Entertainment' },\n}\n\n/** 分类 Tab 的紧凑标签(英文模式空间受限时使用)。 */\nexport const CATEGORY_SHORT_LABELS: Record<string, { zh: string; en: string }> = {\n interface: { zh: '界面体验', en: 'UI Exp' },\n session: { zh: '会话消息', en: 'Sessions' },\n memory: { zh: '记忆上下文', en: 'Memory' },\n tools: { zh: '工具能力', en: 'Tools' },\n agent: { zh: '技能智能体', en: 'Agents' },\n workflow: { zh: '工作流', en: 'Workflow' },\n integration: { zh: '集成连接', en: 'Integrations' },\n model: { zh: '模型推理', en: 'Models' },\n dev: { zh: '开发运维', en: 'Dev' },\n knowledge: { zh: '数据知识', en: 'Knowledge' },\n fun: { zh: '娱乐', en: 'Fun' },\n}\n\nexport const SORTS = ['sortStars', 'sortForks', 'sortUpdated', 'sortNewest'] as const\nexport type SortKey = (typeof SORTS)[number]\n","/**\n * Self-heal missing plugin CSS tags.\n *\n * CSS injection is a one-shot side effect of the bundle factory (guarded by\n * \"tag already present\"). When the host restarts the page survives, but the\n * host HMR chain may remove the <style data-plugin> tags while the in-memory\n * module cache still holds the old factory — so the factory never re-runs and\n * the styles never come back until some interaction triggers a reload.\n *\n * The tsdown `dsh-css-modules-inline` build plugin registers every module's\n * { tagId, css } into the global list `__DSH_PLUGIN_CSS__` at factory time.\n * This helper compares that list against the live DOM and re-injects any\n * missing tags, turning the \"click around to fix it\" self-heal into an\n * automatic one on mount / view switch.\n */\n\ninterface PluginCssEntry {\n tagId: string\n css: string\n}\n\ndeclare global {\n interface Window {\n __DSH_PLUGIN_CSS__?: PluginCssEntry[]\n }\n}\n\n/** Re-inject any registered stylesheet that is missing from the DOM. Idempotent. */\nexport function ensurePluginCss(): void {\n if (typeof document === 'undefined') return\n const registry = window.__DSH_PLUGIN_CSS__\n if (!registry || registry.length === 0) return\n for (const { tagId, css } of registry) {\n const selector = 'style[data-plugin-css=' + JSON.stringify(tagId) + ']'\n if (document.querySelector(selector) !== null) continue\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-plugin'\n tag.dataset.pluginCss = tagId\n tag.textContent = css\n document.head.appendChild(tag)\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Host repository: the local routes served by the DSH harness (installed\n * plugin table + environment snapshot). A host without the plugin's server\n * routes degrades to null / empty tables instead of throwing.\n */\nimport type { EnvInfo } from '../types.ts'\nimport type { InstalledVersionSignal } from '../logic/installed.ts'\n\nexport interface HostInstalled {\n installed: Record<string, string>\n versions: Record<string, InstalledVersionSignal>\n /** 每个依赖在系统上的安装目录(profile/node_modules/<包名>),宿主未提供为 null */\n paths: Record<string, string> | null\n /** 已加载进运行中 loader 的包名(官方 ctx.loader.entries() 对账):装完未重启的新插件不在其中 */\n loaded: string[] | null\n /** 真正的 dsh 插件包名(包内声明 dsh 配置 / 在 profile bundles 清单):非 dsh 插件(如官方示例仓库)装上也不会被宿主加载,不提示待重启 */\n dshCapable: string[] | null\n}\n\n/** 当前 profile 已安装插件表(npm 包名 -> manifest spec)+ 安装时记录的目录信号 + 安装路径 + 运行状态。 */\nexport async function fetchInstalled(): Promise<HostInstalled | null> {\n try {\n const res = await fetch('/dsh-plugin-hub/installed', { cache: 'no-store' })\n if (!res.ok) return null\n const data = await res.json() as {\n installed?: Record<string, string>\n versions?: Record<string, InstalledVersionSignal>\n paths?: Record<string, string>\n loaded?: string[]\n dshCapable?: string[]\n }\n return {\n installed: data.installed ?? {},\n versions: data.versions ?? {},\n paths: data.paths ?? null,\n loaded: data.loaded ?? null,\n dshCapable: data.dshCapable ?? null,\n }\n } catch {\n return null\n }\n}\n\nlet envPromise: Promise<EnvInfo | null> | null = null\n\n/** 在系统文件管理器里定位并打开已安装插件的目录(服务端 spawn open,跨平台);失败返回 false。 */\nexport async function revealInstallFolder(name: string): Promise<boolean> {\n try {\n const res = await fetch('/dsh-plugin-hub/open-path', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ name }),\n cache: 'no-store',\n })\n return res.ok\n } catch {\n return false\n }\n}\n\n/** 在系统文件管理器里定位日志文件(服务端 spawn open,跨平台);失败返回 false。 */\nexport async function openLogFile(): Promise<boolean> {\n try {\n const res = await fetch('/dsh-plugin-hub/open-log', {\n method: 'POST',\n cache: 'no-store',\n })\n return res.ok\n } catch {\n return false\n }\n}\n\n/**\n * 系统目录选择器:弹原生文件夹对话框让用户挑日志存放目录(服务端 spawn\n * osascript / FolderBrowserDialog / zenity);选中返回绝对路径,取消或\n * 平台不支持(无 osascript / zenity)时返回 null。\n */\nexport async function chooseLogDir(): Promise<string | null> {\n try {\n const res = await fetch('/dsh-plugin-hub/choose-log-dir', {\n method: 'POST',\n cache: 'no-store',\n })\n if (!res.ok) return null\n const data = await res.json() as { path?: string }\n return typeof data.path === 'string' && data.path !== '' ? data.path : null\n } catch {\n return null\n }\n}\n\n/**\n * 宿主机器环境快照(/dsh-plugin-hub/env):提交 bug 时拼进 issue 正文。\n * 懒加载 + 模块级缓存:环境在会话期间不会变化;拉取失败降级为 null\n * (issue 链接照常生成,只是少环境段)。\n */\nexport function getEnv(): Promise<EnvInfo | null> {\n envPromise ??= fetch('/dsh-plugin-hub/env', { cache: 'no-store' })\n .then((res) => (res.ok ? (res.json() as Promise<EnvInfo>) : null))\n .catch(() => null)\n return envPromise\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Normalizer: maps the online API's short-key payload (s/o/n/vr/c/t/f/d/r/v/u/a/sg/fk)\n * to HubPlugin so rendering only ever sees one shape.\n */\nimport type { HubPlugin } from '../types.ts'\n\nexport function normalize(raw: Record<string, unknown>): HubPlugin {\n if (typeof raw.s === 'string') {\n return {\n slug: raw.s,\n ownerSlug: typeof raw.o === 'string' ? raw.o : undefined,\n displayName: typeof raw.n === 'string' ? raw.n : undefined,\n version: typeof raw.vr === 'string' ? raw.vr : undefined,\n category: typeof raw.c === 'string' ? raw.c : undefined,\n topics: Array.isArray(raw.t) ? (raw.t as string[]) : undefined,\n features: Array.isArray(raw.f) ? (raw.f as string[]) : undefined,\n description: typeof raw.d === 'string' ? raw.d : undefined,\n // source 双形态:字符串 repo,或 { repo, npmPackage } 对象\n source: typeof raw.r === 'string'\n ? { repo: raw.r }\n : raw.r !== null && typeof raw.r === 'object'\n ? {\n repo: typeof (raw.r as { repo?: unknown }).repo === 'string' ? (raw.r as { repo: string }).repo : undefined,\n npmPackage: typeof (raw.r as { npmPackage?: unknown }).npmPackage === 'string' ? (raw.r as { npmPackage: string }).npmPackage : undefined,\n }\n : undefined,\n // 安装信息:wi 仅在 false 时下发(缺省视为 true 可一键安装);\n // ic/igc = 目录下发的权威安装命令(npm/git 通道各一条,CLI-only 插件如 dsh-tui 必须用)\n install: raw.wi === false || typeof raw.ic === 'string' || typeof raw.igc === 'string'\n ? {\n webInstallable: raw.wi === false ? false : undefined,\n command: typeof raw.ic === 'string' ? raw.ic : undefined,\n githubCommand: typeof raw.igc === 'string' ? raw.igc : undefined,\n }\n : undefined,\n compatibility: typeof raw.v === 'string' ? { status: raw.v } : undefined,\n dates: {\n repoUpdatedAt: typeof raw.u === 'string' ? raw.u : undefined,\n addedAt: typeof raw.a === 'string' ? raw.a : undefined,\n },\n stats: {\n stargazers_count: typeof raw.sg === 'number' ? raw.sg : undefined,\n forks_count: typeof raw.fk === 'number' ? raw.fk : undefined,\n },\n }\n }\n return raw as unknown as HubPlugin\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Catalog repository: fetches the plugin directory and the collection stats\n * from the online API and normalizes them. Components never see URLs or\n * fetch — the repository is the only place that knows where data lives.\n */\nimport type { HubPlugin, LocaleId } from '../types.ts'\nimport { normalize } from '../logic/normalize.ts'\n\n// 目录/统计数据经服务端 /catalog 代理路由获取(curl 子进程注入设置里的代理),\n// 与 npm / git 安装通道同一代理口径 —— 浏览器不直连 api.dsh-plugin.org。\nconst PROXY_BASE = '/dsh-plugin-hub/catalog'\nconst PLUGINS_URL = (lang: LocaleId) => `${PROXY_BASE}?lang=${lang}`\nconst STATS_URL = `${PROXY_BASE}?stats=1`\n\nasync function fetchJson(url: string, signal?: AbortSignal): Promise<unknown> {\n const res = await fetch(url, { cache: 'no-store', signal })\n if (!res.ok) throw new Error(String(res.status))\n return res.json()\n}\n\n/** 目录插件列表(在线 API 已只返回 verified;过滤与排序由上层负责)。\n * signal 可选:宿主重启/代理抖动导致请求挂起时,上层可中止旧请求释放连接。 */\nexport async function fetchCatalog(lang: LocaleId, signal?: AbortSignal): Promise<HubPlugin[]> {\n const data = await fetchJson(PLUGINS_URL(lang), signal)\n return (Array.isArray(data) ? data : []).map((item) => normalize(item as Record<string, unknown>))\n}\n\n/** 收录/精选统计(/api/stats.json);字段不完整返回 null。 */\nexport async function fetchStats(signal?: AbortSignal): Promise<{ total: number; verified: number } | null> {\n const s = await fetchJson(STATS_URL, signal) as { total?: number; verified?: number }\n if (s && typeof s.total === 'number' && typeof s.verified === 'number') {\n return { total: s.total, verified: s.verified }\n }\n return null\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Hub meta repository: the Cloudflare Worker endpoints behind the self-update\n * check and the \"About us\" content. Failures degrade to null — the caller\n * decides how to fall back (no badge, placeholder copy), never throws.\n */\nimport type { HubAboutInfo, HubUpdateInfo } from '../types.ts'\nimport { HUB_ABOUT_URL, HUB_UPDATE_URL } from '../logic/constants.ts'\n\n/** 版本接口是 Pages 静态文件,默认带 CDN 缓存(Cache-Control: public, max-age=43200,\n * 即 12 小时),客户端 no-store 管不到 CDN 边缘,会拿到旧公告。\n * 静态资产请求免费且无限,因此所有版本检查一律带时间戳 query:URL 每次不同 →\n * CDN 缓存 key 不同 → 强制回源拉到最新公告,无任何配额顾虑。 */\nfunction busted(url: string): string {\n const sep = url.includes('?') ? '&' : '?'\n return `${url}${sep}_t=${Date.now()}`\n}\n\n/** Worker 版本控制中心:最新版本 + Markdown 变更记录;不可用返回 null。 */\nexport async function fetchHubUpdate(): Promise<HubUpdateInfo | null> {\n try {\n const res = await fetch(busted(HUB_UPDATE_URL), { cache: 'no-store' })\n if (!res.ok) return null\n const data = await res.json() as HubUpdateInfo | null\n if (!data) return null\n const version = typeof data.version === 'string' && data.version.length > 0 ? data.version : null\n if (version === null) return null\n return { version, publishedAt: data.publishedAt ?? null, notes: data.notes ?? null }\n } catch {\n return null\n }\n}\n\n/** Worker「关注我们」内容(平台介绍 + 反馈群二维码,Markdown);未推送返回 null。 */\nexport async function fetchHubAbout(): Promise<HubAboutInfo | null> {\n try {\n const res = await fetch(busted(HUB_ABOUT_URL), { cache: 'no-store' })\n if (!res.ok) return null\n const data = await res.json() as HubAboutInfo | null\n if (!data || data.content === null || data.content === undefined) return null\n const content = typeof data.content === 'string' || typeof data.content === 'object' ? data.content : null\n if (content === null) return null\n return { content, updatedAt: data.updatedAt ?? null }\n } catch {\n return null\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Installed-plugin model (pure logic, zero React/UI dependencies).\n *\n * Merges the local installed table (from the host's `/installed` route:\n * npm name → manifest spec) with the catalog projection into a single\n * `InstalledItem` view-model consumed by the Installed view. Also hosts the\n * install matching / update detection used by the market view, so both\n * views share one source of truth.\n */\nimport type { HubPlugin } from '../types.ts'\nimport { HUB_REPO } from './constants.ts'\nimport { repoFromInstallTarget } from './install-command.ts'\n\n/** 安装时记录的目录信号(versions 表项)。 */\nexport interface InstalledVersionSignal {\n version: string\n updatedAt: string\n installedAt?: string\n npmPackage?: string\n}\n\n/** 已安装项统一模型:目录元数据 + 宿主运行时信息的合并视图(驱动「已安装」tab)。 */\nexport interface InstalledItem {\n /** npm 包名(profile 依赖 key) */\n name: string\n /** manifest spec(github:owner/repo、git+https://…、或 npm 版本号) */\n spec: string\n /** 目录里匹配到的插件;目录外/未收录的安装为 null */\n plugin: HubPlugin | null\n /** 仓库身份(owner/repo);纯 npm 安装无法识别时为 null */\n repo: string | null\n /** 安装到系统上的路径(profile/node_modules/<包名>);宿主未提供为 null */\n installPath: string | null\n /** 安装时记录的目录版本(无记录为 null) */\n installedVersion: string | null\n /** 安装时间(ISO,无记录为 null) */\n installedAt: string | null\n /** 目录当前最新版本(仓库无 release 为 null) */\n catalogVersion: string | null\n /** 是否有可用更新(有版本比版本,无版本比仓库更新时间) */\n hasUpdate: boolean\n /** 是否已加载进运行中 loader(官方 ctx.loader 对账);false = 已安装但未挂载(装完未重启) */\n loaded: boolean\n /** 是否真正的 dsh 插件(包内声明 dsh 配置 / 在 profile bundles 清单):\n * 非 dsh 插件(如 GitHub 官方示例仓库)装上也不会被宿主加载,不提示「待重启」 */\n dshCapable: boolean\n}\n\n/** 安装时记录的目录信号(按仓库小写 key 查表)。 */\nfunction signalOf(repo: string | null, versions: Record<string, InstalledVersionSignal>): InstalledVersionSignal | null {\n if (!repo) return null\n return versions[repo.toLowerCase()] ?? null\n}\n\n/** 插件是否已安装:匹配 Git spec 中的 owner/repo,或 npm 通道安装的依赖包名;命中返回 npm 包名。 */\nexport function installedNameOf(\n plugin: HubPlugin,\n installed: Record<string, string>,\n versions: Record<string, InstalledVersionSignal>,\n): string | null {\n const repo = plugin.source?.repo\n if (!repo) return null\n const needle = repo.toLowerCase()\n for (const [name, spec] of Object.entries(installed)) {\n if (repoFromInstallTarget(spec).toLowerCase() === needle) return name\n }\n // npm 通道安装:profile 依赖 key 直接是 npm 包名。包名来源两处——目录数据(npmPackage),\n // 或服务端 npm 优先反查持久化的映射(versions[repo].npmPackage,覆盖组织 scope 与 GitHub\n // 用户名不一致、目录未下发包名的场景);命中任一并依赖 key 真实存在即视为已安装。\n // 只认 npm 安装的依赖(spec 无法解析出仓库身份):git/本地安装的依赖身份由仓库匹配决定,\n // 包名同名不代表同仓库——否则「git 装 A 仓库」会被「npm 包名同名但仓库不同」的目录条目\n // 误认领成已安装(假阳性),installedItems 里出现同 key 双条目,排序一变化就渲染出幽灵行。\n const pkg = ((plugin.source?.npmPackage || versions[repo.toLowerCase()]?.npmPackage) ?? '').toLowerCase()\n if (pkg) {\n for (const [name, spec] of Object.entries(installed)) {\n if (isRepoLike(repoFromInstallTarget(spec))) continue\n if (name.toLowerCase() === pkg) return name\n }\n }\n return null\n}\n\n/** 该插件安装时记录的目录版本(无记录/未安装 → null)。 */\nexport function installedVersionOf(plugin: HubPlugin, versions: Record<string, InstalledVersionSignal>): string | null {\n const repo = plugin.source?.repo\n if (!repo) return null\n return versions[repo.toLowerCase()]?.version ?? null\n}\n\n/**\n * 是否有更新:仅对已安装插件有意义。\n * 双信号判定——有 release 版本的比版本;无版本(repo 不打 tag)的比仓库最近更新时间\n * (repoUpdatedAt,ISO 字符串字典序 = 时间序),更新时间变新说明有新提交。\n */\nexport function hasUpdateOf(\n plugin: HubPlugin,\n installed: Record<string, string>,\n versions: Record<string, InstalledVersionSignal>,\n): boolean {\n if (installedNameOf(plugin, installed, versions) === null) return false\n const repo = plugin.source?.repo\n if (!repo) return false\n const rec = versions[repo.toLowerCase()]\n if (!rec) return false\n if (plugin.version) return plugin.version !== rec.version\n const current = plugin.dates?.repoUpdatedAt\n return Boolean(current && rec.updatedAt && current > rec.updatedAt)\n}\n\n/** 依赖 spec 能否解析出仓库身份(owner/repo 形态才算)。 */\nfunction isRepoLike(value: string): boolean {\n return /^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$/.test(value)\n}\n\n/**\n * 提 Issue 的仓库身份解析:失败目标可能是 owner/repo 也可能是 npm 包名(含 @scope/pkg、\n * 可带 @version,如 dsh-plugin、@scope/pkg@1.2.3)。\n * - 目标本身就能解析出 owner/repo → 直接用;\n * - npm 包名 → 反查仓库身份:先查已安装表(该包名的条目若带仓库身份即命中),再查目录插件\n * (source.npmPackage 与包名一致,取目录收录的仓库身份)。\n * 反查到才返回,查不到返回 null —— 调用方据此不显示「一键提 Issue」按钮,避免把 Issue\n * 提到错误的地址(别人发的 npm 包名不是 GitHub 仓库,直接拼 github.com/<包名> 是打不开的)。\n */\nexport function issueRepoOf(\n target: string,\n installedItems: InstalledItem[],\n plugins: HubPlugin[] | null,\n): string | null {\n const input = target.trim()\n if (!input) return null\n const parsed = repoFromInstallTarget(input)\n if (isRepoLike(parsed)) return parsed\n const pkg = parsed.replace(/@[^@]*$/, '').toLowerCase()\n // 已安装表:包名命中的条目(目录收录条目直接带仓库身份;自定义安装按 github: spec 解析)\n for (const item of installedItems) {\n if (item.name.toLowerCase() !== pkg) continue\n if (item.repo) return item.repo\n const repo = repoFromInstallTarget(item.spec)\n if (isRepoLike(repo)) return repo\n }\n // 目录插件:npmPackage 与包名一致 → 用目录收录的仓库身份\n for (const p of plugins ?? []) {\n const pkgName = (p.source?.npmPackage ?? '').trim()\n if (pkgName !== '' && pkgName.toLowerCase() === pkg && p.source?.repo) return p.source.repo\n }\n return null\n}\n\n/** 已安装项 → 弹窗可用的伪插件对象:卸载确认弹窗只读名称/来源行,\n * 自定义安装(目录外)没有完整目录数据,用它把 InstalledItem 适配成 HubPlugin。 */\nexport function pluginOfItem(item: InstalledItem): HubPlugin {\n return {\n slug: item.name,\n displayName: item.plugin?.displayName ?? item.name,\n source: item.repo ? { repo: item.repo } : undefined,\n description: item.plugin?.description,\n }\n}\n\n/**\n * Hub 自身(本插件 dsh-plugin)的识别:三维互证,杜绝误伤同名第三方包。\n * 1) 依赖 key 固定为 `dsh-plugin`(本插件 npm 包名);\n * 2) spec 为 `file:`/`link:` 本地链接(hub 以 file: 安装进宿主);\n * 3) 或 spec 解析出的仓库身份就是自营仓库 `dshplugin/dsh-plugin-hub`。\n * 命中即视为宿主内置本体:永不出现在「自定义安装」里,卸载接口也早已对\n * 它 400 拒绝(服务端多维防线之一)——显示出来只会让用户误点卸载。\n */\nfunction isHubSelf(name: string, spec: string): boolean {\n if (name !== 'dsh-plugin') return false\n if (spec.startsWith('file:') || spec.startsWith('link:')) return true\n const repo = repoFromInstallTarget(spec)\n if (isRepoLike(repo) && repo.toLowerCase() === HUB_REPO.toLowerCase()) return true\n // npm 通道覆盖重装 hub 自身后,file:/link: 本地链接会被替换成 registry 版本号/范围\n // (如 1.3.0、^1.3.0)——依赖 key `dsh-plugin` 在 npm 上唯一属于本插件(不存在第三方\n // 同名包),版本号形态与仓库身份同样视为 hub 自身:命令窗口「自己装自己」成功后,\n // 条目仍不进已安装列表(卸载接口对它的 400 拒绝是服务端最后一道防线)。\n return !isRepoLike(repo)\n}\n\n/**\n * 构建已安装项列表:目录插件按命中关系合并(拥有完整元数据),\n * 剩余未认领的依赖 key 归为自定义安装(目录外,仅运行时信息)。\n */\nexport function installedItemsOf(\n plugins: HubPlugin[] | null,\n installed: Record<string, string>,\n versions: Record<string, InstalledVersionSignal>,\n paths: Record<string, string> | null,\n loadedNames: string[] | null,\n dshCapableNames: string[] | null,\n): InstalledItem[] {\n const items: InstalledItem[] = []\n // 已被目录条目认领的依赖 key:同一依赖只归属一个目录条目(React key 必须唯一,\n // 否则同名双条目排序一变化就渲染出幽灵行);剩余未认领的归自定义安装。\n const claimed = new Set<string>()\n // 目录匹配:遍历目录插件,命中 installedNameOf 即视为已安装并合并元数据\n for (const p of plugins ?? []) {\n const name = installedNameOf(p, installed, versions)\n if (name === null || claimed.has(name)) continue\n claimed.add(name)\n const repo = p.source?.repo ?? null\n const rec = signalOf(repo, versions)\n items.push({\n name,\n spec: installed[name],\n plugin: p,\n repo,\n installPath: paths?.[name] ?? null,\n installedVersion: rec?.version ?? null,\n installedAt: rec?.installedAt ?? null,\n catalogVersion: p.version ?? null,\n hasUpdate: hasUpdateOf(p, installed, versions),\n loaded: loadedNames?.includes(name) ?? false,\n dshCapable: dshCapableNames?.includes(name) ?? false,\n })\n }\n // 自定义安装:依赖表里没被任何目录插件认领的条目(命令行安装的目录外插件)\n for (const [name, spec] of Object.entries(installed)) {\n if (claimed.has(name)) continue\n // Hub 自身(本插件 dsh-plugin)由宿主内置加载,不是可管理的插件:永不进已安装列表,\n // 避免出现在「自定义安装」里被误点卸载(服务端卸载接口对它的 400 拒绝是最后一道防线)\n if (isHubSelf(name, spec)) continue\n const parsed = repoFromInstallTarget(spec)\n const repo = isRepoLike(parsed) ? parsed : null\n const rec = signalOf(repo, versions)\n items.push({\n name,\n spec,\n plugin: null,\n repo,\n installPath: paths?.[name] ?? null,\n installedVersion: rec?.version ?? null,\n installedAt: rec?.installedAt ?? null,\n catalogVersion: null,\n // 目录外没有目录信号可比,无法判断是否有更新\n hasUpdate: false,\n loaded: loadedNames?.includes(name) ?? false,\n dshCapable: dshCapableNames?.includes(name) ?? false,\n })\n }\n return items\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Catalog data + view state for the Plugin Hub section.\n *\n * Owns the online-data pipeline (live fetch from api.dsh-plugin.org), the local\n * installed-plugin table, and the filter/search/sort/install-status view\n * state, exposing the derived visible list and per-category counts.\n */\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport type { HubPlugin, LocaleId } from '../types.ts'\nimport { HUB_REPO, PLUGIN_VERSION } from '../logic/constants.ts'\nimport type { HubAboutInfo, HubUpdateInfo } from '../types.ts'\nimport type { SortKey } from '../logic/constants.ts'\nimport { fetchCatalog, fetchStats } from '../data/catalog.ts'\nimport { fetchHubAbout, fetchHubUpdate } from '../data/hub.ts'\nimport { fetchInstalled } from '../data/host.ts'\nimport {\n hasUpdateOf, installedItemsOf, installedNameOf, installedVersionOf,\n} from '../logic/installed.ts'\nimport type { InstalledItem, InstalledVersionSignal } from '../logic/installed.ts'\n\n/** 插件市场自身仓库:DSH Plugin Hub 不显示在目录里(自己不进自己的插件列表) */\nconst SELF_REPO = 'dshplugin/dsh-plugin-hub'\n\n/** 市场各排序的默认方向:全部按倒序(Star/Fork 多、更新/收录近的在前) */\nconst SORT_DEFAULT_DIR: Record<SortKey, 'asc' | 'desc'> = {\n sortStars: 'desc', sortForks: 'desc', sortUpdated: 'desc', sortNewest: 'desc',\n}\n\nexport function useCatalog(lang: LocaleId) {\n /** 目录插件(仅保留人工验证通过的条目) */\n const [plugins, setPlugins] = useState<HubPlugin[] | null>(null)\n /** Hub 自身目录条目(dshplugin/dsh-plugin-hub):目录过滤会排除自身(不进插件列表),\n * 此处单独保留,供头部「可更新」徽标 → 「直接更新」覆盖重装使用。 */\n const [hubPlugin, setHubPlugin] = useState<HubPlugin | null>(null)\n /** 收录/精选统计(官网 /api/stats.json 实时拉取) */\n const [stats, setStats] = useState<{ total: number; verified: number } | null>(null)\n const [failed, setFailed] = useState(false)\n const [reloadKey, setReloadKey] = useState(0)\n const [category, setCategory] = useState('all')\n const [query, setQuery] = useState('')\n const [sort, setSort] = useState<SortKey>('sortStars')\n /** 当前排序方向:点同一个排序按钮切换 正序/倒序;点新排序用该排序的默认方向(与已安装视图一致) */\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')\n /** 目录加载「超时自动强制刷新」重试计数:宿主重启/代理未就绪时请求可能长时间挂起,\n * 界面停在「正在加载插件数据…」假死 —— 超时自动重拉,最多自动重试 2 次后转失败态;\n * 用户手动刷新(reload)时清零重新计数。 */\n const loadRetriesRef = useRef(0)\n /** 目录加载超时阈值:超过即判定挂起,强制刷新一次(服务端代理 curl 上限 20s,客户端 12s 先兜底) */\n const LOAD_TIMEOUT_MS = 12000\n /** 挂起后最多自动重试次数:避免代理持续不通时无限循环刷新(每次重试仍 12s,2 次后转失败界面可手动重试) */\n const MAX_LOAD_RETRIES = 2\n\n /** 点击排序按钮:同一按钮切换正/倒序,新按钮用默认方向 */\n function toggleSort(key: SortKey) {\n if (key === sort) setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))\n else { setSort(key); setSortDir(SORT_DEFAULT_DIR[key]) }\n }\n /**\n * 强制刷新 Hub 版本与「关注我们」信息:点击头部版本号/徽标时触发。\n * 挂载期的 useEffect 只在进入/reload 时拉一次,发版后已打开的界面点版本号\n * 仍显示旧数据;此处重新拉接口中心,最新版本与变更记录点击即见。\n * 失败静默为 null(弹窗兜底展示当前版本号),与挂载期拉取口径一致。\n */\n const refreshHub = async () => {\n // 版本接口已恒带时间戳绕过 CDN,手动/自动拉取都能拿到最新公告\n const [info, about] = await Promise.all([fetchHubUpdate(), fetchHubAbout()])\n setHubUpdateInfo(info)\n setHubAboutInfo(about)\n }\n\n /** 当前 profile 已安装插件:npm 包名 -> manifest spec(来自宿主本地路由) */\n const [installed, setInstalled] = useState<Record<string, string>>({})\n /** 安装时记录的目录信号:repo(小写) -> { version, updatedAt }(来自宿主本地路由);\n * npmPackage 为 npm 优先通道反查命中的包名映射(目录数据未下发时客户端靠它把依赖 key 匹配回仓库) */\n const [versions, setVersions] = useState<Record<string, InstalledVersionSignal>>({})\n /** 每个依赖在系统上的安装目录(profile/node_modules/<包名>),详情视图展示用 */\n const [installPaths, setInstallPaths] = useState<Record<string, string> | null>(null)\n /** 已加载进运行中 loader 的包名(官方 ctx.loader 对账):装完未重启的新插件不在其中 */\n const [loadedNames, setLoadedNames] = useState<string[] | null>(null)\n /** 真正的 dsh 插件包名(包内声明 dsh 配置 / 在 profile bundles 清单):非 dsh 插件不提示「待重启」 */\n const [dshCapableNames, setDshCapableNames] = useState<string[] | null>(null)\n /** Hub 自我更新信息:来自接口中心 Pages(api.dsh-plugin.org),与目录数据解耦 */\n const [hubUpdateInfo, setHubUpdateInfo] = useState<HubUpdateInfo | null>(null)\n /** 头部「关注我们」弹窗内容(平台介绍 + 反馈群二维码):来自接口中心 /about,Markdown 推送非写死 */\n const [hubAboutInfo, setHubAboutInfo] = useState<HubAboutInfo | null>(null)\n\n // 拉取目录 + 统计。在线 API 已只返回 verified;再过滤一次,保证只展示人工验证通过的插件。\n useEffect(() => {\n let cancelled = false\n // 本次加载是否已收尾(成功或失败):超时定时器只对「还在加载中」生效\n let settled = false\n // 中止控制器:请求挂起时(宿主重启/代理抖动)超时自动重试会换新请求,\n // 旧请求在此中止释放连接,避免挂起堆积\n const controller = new AbortController()\n setPlugins(null)\n setHubPlugin(null)\n setStats(null)\n setFailed(false)\n // 此处只拉目录与统计;hub 自身版本由独立 Worker 版本控制中心提供(见 fetchHubUpdate)。\n const load = () => Promise.all([fetchCatalog(lang, controller.signal), fetchStats(controller.signal)])\n load()\n .then(([list, stats]) => {\n if (cancelled) return\n settled = true\n // 插件市场不显示自己:DSH Plugin Hub 从目录里排除自身条目,\n // 防止「自己出现在自己的插件列表里、还能自己安装自己」;统计计数同步减 1 保持与列表一致。\n // 目录数据已排除自身,此处再兜底过滤一次,防旧快照仍含自身条目。\n const hadSelf = list.some((p) => p.source?.repo === SELF_REPO)\n // 过滤前单独保留 hub 自身条目:它不进目录列表,但「可更新」徽标的直接更新需要它作为重装目标\n setHubPlugin(list.find((p) => p.source?.repo === SELF_REPO) ?? null)\n setPlugins(list.filter((p) => p.compatibility?.status === 'verified' && p.source?.repo !== SELF_REPO))\n if (stats) {\n setStats(hadSelf\n ? { total: stats.total - 1, verified: stats.verified - 1 }\n : { total: stats.total, verified: stats.verified })\n }\n })\n .catch(() => {\n if (cancelled) return\n settled = true\n setFailed(true)\n })\n // 加载超时兜底:宿主刚重启/代理未就绪时目录请求可能长时间挂起,界面停在「正在加载插件数据…」\n // 像假死。超过阈值未收尾 → 强制刷新列表(重拉一次,最多 MAX_LOAD_RETRIES 次自动重试),\n // 重试仍失败 → 转失败界面(显示「重试」按钮,手动刷新时计数清零重新开始)。\n const timer = window.setTimeout(() => {\n if (cancelled || settled) return\n if (loadRetriesRef.current < MAX_LOAD_RETRIES) {\n loadRetriesRef.current += 1\n setReloadKey((k) => k + 1)\n } else {\n setFailed(true)\n }\n }, LOAD_TIMEOUT_MS)\n return () => {\n cancelled = true\n window.clearTimeout(timer)\n controller.abort()\n }\n // lang 必须进依赖:切换界面语言要重新拉对应语言的数据文件,\n // 否则英文模式仍停留在 plugins.zh.json,描述/名称全是中文\n }, [reloadKey, lang])\n\n /** 刷新当前 profile 已安装插件表;宿主未挂本地路由时静默降级为空表。 */\n const refreshInstalled = async () => {\n const data = await fetchInstalled()\n if (data === null) return\n setInstalled(data.installed)\n setVersions(data.versions)\n setInstallPaths(data.paths)\n setLoadedNames(data.loaded)\n setDshCapableNames(data.dshCapable)\n }\n\n // 首次进入拉取已安装表(依赖宿主 webServer 服务)\n useEffect(() => { refreshInstalled() }, [])\n\n // Hub 自身版本检查走独立 Worker(版本控制中心):发新版后写一次 Worker KV,\n // 所有已装用户立即看到「可更新」+ Markdown 变更记录,不经过主站目录数据管道。\n // 失败静默降级为 null(徽标不出现,不影响目录本身加载)。\n useEffect(() => {\n let cancelled = false\n void fetchHubUpdate().then((info) => { if (!cancelled) setHubUpdateInfo(info) })\n return () => { cancelled = true }\n }, [reloadKey])\n\n // 「关注我们」内容走同一套 Worker:作者写好 Markdown(平台介绍 + 反馈群二维码)推送 /admin/about,\n // 客户端下次进入拉 /about 即可看到最新,非写死。失败静默为 null(弹窗展示兜底文案,不阻塞)。\n useEffect(() => {\n let cancelled = false\n void fetchHubAbout().then((info) => { if (!cancelled) setHubAboutInfo(info) })\n return () => { cancelled = true }\n }, [reloadKey])\n\n /** 插件是否已安装:匹配 Git spec 中的 owner/repo,或 npm 通道安装的依赖包名;命中返回 npm 包名。 */\n const installedName = (p: HubPlugin): string | null => installedNameOf(p, installed, versions)\n\n /** 该插件安装时记录的目录版本(无记录/未安装 → null)。 */\n const installedVersion = (p: HubPlugin): string | null => installedVersionOf(p, versions)\n\n /**\n * 是否有更新:仅对已安装插件有意义。\n * 双信号判定——有 release 版本的比版本;无版本(repo 不打 tag)的比仓库最近更新时间\n * (repoUpdatedAt,ISO 字符串字典序 = 时间序),更新时间变新说明有新提交。\n */\n const hasUpdate = (p: HubPlugin): boolean => hasUpdateOf(p, installed, versions)\n\n /** 已安装项统一列表(目录元数据 + 运行时信息合并):驱动「已安装」tab。 */\n const installedItems = useMemo<InstalledItem[]>(\n () => installedItemsOf(plugins, installed, versions, installPaths, loadedNames, dshCapableNames),\n [plugins, installed, versions, installPaths, loadedNames, dshCapableNames],\n )\n\n /**\n * Hub 自身是否有可用更新:Hub 就是当前运行的应用(始终已安装,无需 installedName 命中)。\n * 以 Worker 版本控制中心返回的「最新版本」为准,与当前运行的版本号比对——\n * 构建时注入的 PLUGIN_VERSION 是运行 bundle 的真实版本;测试/异常场景缺失时\n * 回退到安装时记录的版本。版本号不等即新版(版本号只在发版时变更,绝无降级场景)。\n *\n * 另加 pnpm 供应链安全门槛:新版本发布还不满 24 小时(+30 分钟缓冲)时,pnpm 会静默\n * 回退到旧版本,此时若提示「可更新」用户点了也更新不到。publishedAt 由接口中心按 npm\n * registry 真实发布时间下发(同源),据此判断最准。\n */\n const hubHasUpdate = (() => {\n if (!hubUpdateInfo) return false\n const current = PLUGIN_VERSION || versions[HUB_REPO]?.version || null\n if (current === null || hubUpdateInfo.version === current) return false\n const publishedAt = hubUpdateInfo.publishedAt\n if (publishedAt) {\n const publishedMs = Date.parse(publishedAt)\n if (!Number.isNaN(publishedMs)) {\n // 24 小时 + 30 分钟缓冲(防网络/CDN 边缘时间偏差)\n const MIN_RELEASE_AGE_MS = 24 * 60 * 60 * 1000 + 30 * 60 * 1000\n if (Date.now() - publishedMs < MIN_RELEASE_AGE_MS) return false\n }\n }\n return true\n })()\n\n /** 当前分类下的插件(「全部」时为整个目录)。 */\n const categoryPlugins = useMemo(() => {\n if (!plugins) return []\n if (category === 'all') return plugins\n return plugins.filter((p) => p.category === category)\n }, [plugins, category])\n\n const visible = useMemo(() => {\n if (!plugins) return []\n const q = query.trim().toLowerCase()\n const list = plugins.filter((p) => {\n if (category !== 'all' && p.category !== category) return false\n if (!q) return true\n return (\n (p.displayName ?? '').toLowerCase().includes(q) ||\n (p.description ?? '').toLowerCase().includes(q) ||\n (p.topics ?? []).some((topic) => topic.toLowerCase().includes(q))\n )\n })\n const dir = sortDir === 'asc' ? 1 : -1\n return [...list].sort((a, b) => {\n // 比较器统一用「升序写法」再乘 dir:desc 时 dir=-1 翻成降序(Star/Fork 最多、更新/收录最近在前)\n if (sort === 'sortStars') return ((a.stats?.stargazers_count ?? 0) - (b.stats?.stargazers_count ?? 0)) * dir\n if (sort === 'sortForks') return ((a.stats?.forks_count ?? 0) - (b.stats?.forks_count ?? 0)) * dir\n if (sort === 'sortNewest') return (a.dates?.addedAt ?? '').localeCompare(b.dates?.addedAt ?? '') * dir\n return (a.dates?.repoUpdatedAt ?? '').localeCompare(b.dates?.repoUpdatedAt ?? '') * dir\n })\n }, [plugins, category, query, sort, sortDir, installed])\n\n /** Per-category plugin counts shown on the category chips. */\n const categoryCounts = useMemo(() => {\n const counts: Record<string, number> = {}\n for (const p of plugins ?? []) {\n if (p.category) counts[p.category] = (counts[p.category] ?? 0) + 1\n }\n return counts\n }, [plugins])\n\n return {\n plugins,\n hubPlugin,\n stats,\n failed,\n reload: () => { loadRetriesRef.current = 0; setReloadKey((k) => k + 1) },\n installed,\n installedItems,\n installedName,\n installedVersion,\n hasUpdate,\n hubHasUpdate,\n hubUpdateInfo,\n hubAboutInfo,\n refreshHub,\n refreshInstalled,\n category,\n setCategory,\n query,\n setQuery,\n sort,\n sortDir,\n toggleSort,\n visible,\n total: plugins?.length ?? 0,\n categoryCounts,\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Failure classification, issue-body summarization and persistent\n * install/remove notifications.\n *\n * Every settled task is recorded two ways: the server-side system log\n * (hub.log) and a client-side localStorage record that feeds the\n * notification center — so a result is never lost even when the dialog\n * was dismissed or nobody was watching the progress strip.\n */\nexport interface NotificationRecord {\n id: number\n kind: 'install' | 'uninstall' | 'update'\n /** true = 成功(轻量记录);false = 失败(message 携带完整错误日志) */\n ok: boolean\n /** owner/repo(可能为空:请求层失败但拿不到仓库时) */\n repo: string\n /** 实际动作(install/update/uninstall):成功/失败通知据此区分「安装成功」与「更新成功」。\n * 缺省按 kind 兜底(历史记录可能没有该字段)。更新提醒(kind='update')不用此字段。 */\n action?: 'install' | 'update' | 'uninstall'\n /** 失败时的完整错误日志;成功记录为空串 */\n message: string\n /** 更新提醒:目录里的新版本号(展示用;其余通知省略) */\n version?: string\n /** 实际执行的安装/卸载命令(issue 预填时如实展示);历史记录可能缺失 */\n command?: string\n /** 尝试过的安装方式(npm registry 反查 + 实际执行命令,按先后顺序):失败提 Issue 时贴给作者,便于反推正确的 npm 包名 */\n attempts?: string[]\n /** 结束时间(epoch ms) */\n at: number\n}\n\nconst KEY = 'gro.ngilp-hsd.failure-records'\nconst MAX = 50\n\n/** 运行时 localStorage 访问:类型上不依赖 DOM lib(Node 测试环境也能编译),浏览器里取 window。 */\nconst storage = (): Storage | undefined =>\n (globalThis as { localStorage?: Storage }).localStorage\n\n/** 读取本地通知记录(损坏/不可用时返回空列表,不抛错)。列表最新在前,全部保留,只由「清空」按钮手动移除。 */\nexport function loadNotifications(): NotificationRecord[] {\n try {\n const raw = storage()?.getItem(KEY)\n if (!raw) return []\n const list = JSON.parse(raw) as unknown\n if (!Array.isArray(list)) return []\n return list\n .filter((r): r is NotificationRecord =>\n !!r && typeof r === 'object' && typeof (r as { message?: unknown }).message === 'string')\n // ok 字段缺省时按失败渲染\n .map((r) => ({ ...r, ok: r.ok === true }))\n } catch {\n return []\n }\n}\n\nfunction save(list: NotificationRecord[]): void {\n try {\n storage()?.setItem(KEY, JSON.stringify(list))\n } catch {\n /* storage full / unavailable:仅保留内存态,界面仍可查看 */\n }\n}\n\n/** 追加一条通知记录并持久化,返回更新后的完整列表(最新在前,超上限裁剪)。\n * 每次成功/失败都各自留痕:同一插件的安装/卸载记录都完整保留、只由「清空」按钮手动移除,\n * 不会因后续操作被自动覆盖清除。 */\nexport function addNotification(record: Omit<NotificationRecord, 'id' | 'at'>): NotificationRecord[] {\n const prev = loadNotifications()\n let id = Date.now()\n while (prev.some((r) => r.id === id)) id += 1\n const next = [{ ...record, id, at: id }, ...prev].slice(0, MAX)\n save(next)\n return next\n}\n\n/** 记录一次失败:携带完整错误日志,供通知中心查看/复制/提 Issue。 */\nexport function addFailure(record: Omit<NotificationRecord, 'id' | 'at' | 'ok'>): NotificationRecord[] {\n return addNotification({ ...record, ok: false })\n}\n\n/** 记录一次成功:轻量记录,不带日志。 */\nexport function addSuccess(record: Omit<NotificationRecord, 'id' | 'at' | 'ok' | 'message'>): NotificationRecord[] {\n return addNotification({ ...record, ok: true, message: '' })\n}\n\n/** 记录一条「发现新版本」更新提醒:成功类轻量记录,携带目录新版本号供通知中心展示。\n * 同一插件同一新版本已在通知中心时跳过:宿主重载会重新触发启动检查,不更新时\n * 通知里已有的提醒保持单条,不重复追加。 */\nexport function addUpdateNotice(record: Omit<NotificationRecord, 'id' | 'at' | 'ok' | 'message'>): NotificationRecord[] {\n const prev = loadNotifications()\n const dup = prev.some((r) =>\n r.kind === 'update' && r.repo === record.repo && (r.version ?? undefined) === (record.version ?? undefined))\n if (dup) return prev\n return addNotification({ ...record, ok: true, message: '' })\n}\n\n/** 已忽略的更新提醒持久化 key:`owner/repo@version` 字符串数组。 */\nconst IGNORE_KEY = 'gro.ngilp-hsd.ignored-updates'\n\n/** 读取已忽略的更新提醒(`owner/repo@version` 字符串集合);损坏/不可用时返回空集合。 */\nexport function loadIgnoredUpdates(): Set<string> {\n try {\n const raw = storage()?.getItem(IGNORE_KEY)\n if (!raw) return new Set()\n const list = JSON.parse(raw) as unknown\n if (!Array.isArray(list)) return new Set()\n return new Set(list.filter((x): x is string => typeof x === 'string'))\n } catch {\n return new Set()\n }\n}\n\nfunction saveIgnoredUpdates(ignored: Set<string>): void {\n try {\n storage()?.setItem(IGNORE_KEY, JSON.stringify([...ignored]))\n } catch {\n /* storage full / unavailable:仅保留内存态 */\n }\n}\n\n/** 忽略某插件本次更新(repo+version 持久化入忽略集):本次版本不再提醒,直到下一个新版本发布。 */\nexport function ignoreUpdate(repo: string, version?: string): Set<string> {\n const next = loadIgnoredUpdates()\n next.add(`${repo}@${version ?? ''}`)\n saveIgnoredUpdates(next)\n return next\n}\n\n/** 移除某插件某版本的更新提醒记录(忽略本次更新时一并清理通知),返回更新后的列表。 */\nexport function removeUpdateNotice(repo: string, version?: string): NotificationRecord[] {\n const next = loadNotifications().filter((r) =>\n !(r.kind === 'update' && r.repo === repo && (r.version ?? undefined) === (version ?? undefined)))\n save(next)\n return next\n}\n\n/** 清空全部通知记录,返回空列表。 */\nexport function clearNotifications(): NotificationRecord[] {\n save([])\n return []\n}\n\n/** 按 id 删除单条通知记录,返回更新后的列表(仅移除该条,不影响其余记录)。 */\nexport function removeNotification(id: number): NotificationRecord[] {\n const next = loadNotifications().filter((r) => r.id !== id)\n save(next)\n return next\n}\n\nexport type FailureKind = 'npmTooOld' | 'dshMissing' | 'gitMissing' | 'pnpmMissing' | 'npmMissing' | 'pnpmStore' | 'pnpmWorkspace' | 'originRejected' | 'pnpmPolicy' | 'pnpmUnusedPatch' | 'pnpmMissingDep' | 'fileLocked' | 'accessDenied' | 'fsUnavailable' | 'pnpmIgnoredBuild' | 'pluginPrepare' | 'network' | 'repo'\n\n/** Match the pnpm error code, not a generic mention of checksum or integrity. */\nfunction missingTarballIntegrity(message: string): boolean {\n return /\\bERR_PNPM_MISSING_TARBALL_INTEGRITY\\b/.test(message)\n}\n\n/** pnpm 拒收「刚发布」包时,报错里带着发布时间;这里从报错文本算出「发布满 24h」的可重试时刻(UTC,分钟精度)。 */\nexport function releaseAgeRetryAfter(message: string): string | null {\n const match = /published at (\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z)/.exec(message)\n if (match === null) return null\n const published = Date.parse(match[1])\n if (Number.isNaN(published)) return null\n return `${new Date(published + 24 * 60 * 60 * 1000).toISOString().slice(0, 16)}Z`\n}\n\n/**\n * The same policy subtype selects recovery copy in live and saved failures.\n * minimumReleaseAge 只有在能算出可重试时刻时才走专属文案(给出确切的「何时可再试」),\n * 算不出时退回通用文案,避免出现「预计可重试时间:」后接空值的残缺句子。\n */\nexport function pnpmPolicyHintOf(message: string): 'failPnpmTarballIntegrityHint' | 'failPnpmReleaseAgeHint' | 'failPnpmPolicyHint' {\n if (missingTarballIntegrity(message)) return 'failPnpmTarballIntegrityHint'\n if (/ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION|Minimum release age/i.test(message)\n && releaseAgeRetryAfter(message) !== null) {\n return 'failPnpmReleaseAgeHint'\n }\n return 'failPnpmPolicyHint'\n}\n\n/** 与 pnpmPolicyHintOf 配套的文案参数:release-age 场景给出可重试时刻({time})。 */\nexport function pnpmPolicyHintParams(message: string): Record<string, string> {\n return { time: releaseAgeRetryAfter(message) ?? '' }\n}\n\n/**\n * 失败归类:把安装输出归到具体成因,供弹窗文案、是否引导提 Issue 与 issue 预填原因使用。\n * 分界是「本机环境问题」(装任何插件都会同样失败 → 不引导提 Issue)与\n * 「插件分发/依赖问题」(只影响这个插件 → 引导去仓库提 Issue);各分支的判定顺序有依赖,\n * 原因见 classifyFailure 内注释。\n *\n * 本机环境问题:\n * - npmTooOld:本机 npm 版本过低或自身缺陷 —— npm arborist 解 peer 依赖时抛 `edgesOut`\n * (build-ideal-tree.js 内部报错),或服务端已核实版本低于阈值并打了 `[npm-too-low]` 标记\n * → 引导升级 npm\n * - dshMissing:安装器 spawn 的 `dsh` 命令找不到(Windows cmd「不是内部或外部命令」/ POSIX\n * 「command not found」/ spawn ENOENT)→ 提示检查 PATH / 重装 DSH\n * - gitMissing:安装器调用 `git` 时找不到可执行文件(Windows cmd「'git' is not recognized」/\n * POSIX「git: command not found」/ spawn ENOENT)→ 提示安装 Git / 加入 PATH\n * - pnpmMissing:dsh 存在但调用的 `pnpm` 找不到(dsh 报 `pnpm not found on PATH` / POSIX\n * 「pnpm: command not found」/ spawn ENOENT)—— dsh 用 pnpm 管理 profile 插件\n * → 提示安装 / 开启 pnpm\n * - npmMissing:全局 npm 安装通道(`npm install -g …`)spawn 的 `npm` 命令找不到,形态同上\n * → 提示安装 npm(Node.js 自带)/ 加入 PATH\n * - pnpmStore:pnpm 报 store / virtual store 位置不匹配(`ERR_PNPM_UNEXPECTED_STORE` /\n * `ERR_PNPM_UNEXPECTED_VIRTUAL_STORE` / `Unexpected store location`)—— profile 目录里的依赖\n * 是另一个大版本的 pnpm 生成的(或 profile 目录被复制/移动、virtual-store-dir 配置变化),\n * 当前 pnpm 出于安全不认 → 提示清理 profile 依赖目录后用当前 pnpm 重建\n * - pnpmWorkspace:pnpm 拒绝在 workspace 根目录下安装(`ERR_PNPM_ADDING_TO_ROOT`)—— profile\n * 目录含 pnpm-workspace.yaml 即被 pnpm 视为 workspace 根,宿主调 `pnpm add` 时未声明在根\n * 操作(缺 `-w`/`--workspace-root`),整条命令被拒 → 提示在 profile 的 .npmrc 里加\n * `ignore-workspace-root-check=true` 或升级宿主\n * - originRejected:请求的来源没通过本地 hub 服务的校验(服务端 403,正文是裸的\n * `untrusted origin`)—— 请求在进入安装流程前就被拒,与 pnpm 无关;常见于用非 localhost 的\n * 地址(如局域网 IP)打开市场页面,或宿主页面的 origin 未被识别 → 提示从本机地址打开市场后重试\n * - pnpmPolicy:pnpm 的供应链安全策略拒绝安装(缺少 tarball integrity、`ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION` /\n * `Minimum release age` —— 锁文件里包的发布时间还不满 24 小时被拒;`untrusted origin` ——\n * 依赖来源未被本机 pnpm 信任)→ 提示按子场景给解法(发布未满 24 小时 → `minimumReleaseAge: 0`\n * 豁免或等满 24 小时;untrusted origin → 删除 profile 的 node_modules + pnpm-lock.yaml 清掉\n * 不受信任来源后重装)\n * - pnpmUnusedPatch:profile 里留着指向旧版本 dsh-plugin 的 patch 声明,本次安装解析到的版本\n * 已经不是它(`ERR_PNPM_UNUSED_PATCH` / `The following patches were not used: dsh-plugin@1.4.2`)\n * —— pnpm 发现补丁没被用上即中止整次安装 → 提示删掉该条目后重试\n * - pnpmMissingDep:profile 里留着一条指向 registry 上不存在的包的依赖,pnpm 解析时收到 404\n * (`ERR_PNPM_FETCH_404` / `Not Found - 404`)—— 该 profile 的任何安装都会先卡在这条依赖上\n * → 提示按包名删掉该条目后重试(404 的包通常不是正在安装的插件,故不引导提 Issue)\n * - fileLocked:pnpm 无法替换 profile 里被其他进程占用的文件(Windows `os error 32`\n * 「另一个程序正在使用此文件」/ `EBUSY` / `resource busy or locked`)—— 通常是宿主进程或\n * 杀毒软件实时扫描持有句柄 → 提示完全退出宿主后重试\n * - accessDenied:pnpm 在 profile 里替换文件时被系统拒绝写入(Windows `os error 5`\n * 「拒绝访问」= ERROR_ACCESS_DENIED / Node 的 `EPERM` `EACCES` / `Access is denied`)——\n * 文件/目录被其他进程占用、只读属性、目录 ACL 受限,或杀毒软件实时防护拦截写入\n * → 提示退出宿主 / 关杀软后重试,仍失败则检查只读属性并以管理员身份运行\n * - fsUnavailable:本机文件系统层面根本写不进去 —— 磁盘/分区空间耗尽(`ENOSPC` /\n * `no space left on device`,Windows 为 `os error 112`)、目标分卷或挂载点为只读\n * (`EROFS` / `read-only file system`,Windows 写保护为 `os error 19`)、进程可用的文件句柄\n * 被耗尽(`EMFILE` / `ENFILE` / `too many open files`),都发生在 pnpm 落盘阶段\n * → 提示按报错代码对号入座(清空间 / 换可写目录 / 重启宿主释放句柄)\n * - network:安装前连通性预检拦截(服务端 `[network]` 标记)、底层连接失败\n * (ERR_PNPM_GIT_FETCH_FAILED / ETIMEDOUT / DNS 解析 / TLS 握手 / 代理拒绝),或\n * registry tarball 拉取失败(`fetch failed` / `GET …/-/…tgz error (n)` —— 常见于本机\n * npm/pnpm 的 registry 被指向内网/自定义源,该源取不到包),或界面请求压根没送达宿主服务\n * (浏览器 fetch 的 `Failed to fetch` —— 宿主未就绪/正在重启,或本地代理拦了回环地址)\n * → 提示检查网络,registry 指向自定义源时给出换源指引\n *\n * 插件分发/依赖问题(引导去仓库提 Issue):\n * - pnpmIgnoredBuild:插件自身或依赖的构建脚本被 pnpm 安全白名单(allowBuilds)默认拦截\n * (`ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED` / `ERR_PNPM_IGNORED_BUILDS`)—— 只影响带安装期\n * 构建的插件 → 建议改用预编译版本或关闭安装期构建\n * - pluginPrepare:插件的 prepare/构建脚本实际执行失败(git tarball 常因缺失子模块或构建产物\n * 导致),或装后校验发现 package.json 声明的入口文件不在发布物里(服务端 `[packaging]` 标记)\n * —— 属插件打包/分发问题\n * - repo:其余失败,默认按插件仓库问题处理\n */\nexport function classifyFailure(message: string): FailureKind {\n // npm 内部崩溃(edgesOut)或服务端 [npm-too-low] 标记:是本机 npm 版本过低/自身缺陷,\n // 不是插件问题 —— 必须最先判,否则该报错会被外层 ERR_PNPM_PREPARE_PACKAGE 吞成\n // 「插件打包分发问题」,误导用户去提 Issue\n if (/\\[npm-too-low\\]|edgesOut/i.test(message)) return 'npmTooOld'\n // 找不到 pnpm 命令(dsh 报 `pnpm not found on PATH` —— dsh 用它管理 profile 插件 /\n // POSIX「pnpm: command not found」/ spawn pnpm ENOENT / Windows cmd 中英文报错):\n // 本机缺 pnpm。必须在 dshMissing 之前 —— dshMissing 正则含裸「command not found」,\n // 会把 `pnpm: command not found` 吞成「dsh 缺失」,误引导用户去装 DSH\n if (/\\[pnpm-missing\\]|pnpm not found|pnpm: command not found|spawn pnpm ENOENT|'pnpm' 不是内部或外部命令|\"pnpm\" 不是内部或外部命令|pnpm['\"]?\\s*is not recognized/i.test(message)) return 'pnpmMissing'\n // 找不到 git 命令(服务端 [git-missing] 标记 / Windows cmd 中英文「'git' is not recognized」/\n // POSIX「git: command not found」/ spawn git ENOENT):本机 Git 未安装或不在 PATH。\n // 必须在 dshMissing 之前 —— dshMissing 正则含裸「is not recognized / command not found」,\n // 会把 git 缺失('git' is not recognized as an internal or external command)吞成「dsh 缺失」,\n // 误导用户去装 DSH\n if (/\\[git-missing\\]|spawn git ENOENT|'git' 不是内部或外部命令|\"git\" 不是内部或外部命令|git['\"]?\\s*is not recognized|git: command not found/i.test(message)) return 'gitMissing'\n // 找不到 npm 命令(全局 npm 安装通道 `npm install -g` spawn 的 npm 缺失 / Windows cmd 中英文\n // 「'npm' is not recognized」/ POSIX「npm: command not found」/ spawn npm ENOENT):本机 npm 未安装\n // 或不在 PATH,不是插件问题。必须在 dshMissing 之前 —— dshMissing 正则含裸「is not recognized /\n // command not found」,会把 npm 缺失('npm' is not recognized)吞成「dsh 缺失」,误导用户去装 DSH\n if (/\\[npm-missing\\]|spawn npm ENOENT|'npm' 不是内部或外部命令|\"npm\" 不是内部或外部命令|npm['\"]?\\s*is not recognized|npm: command not found/i.test(message)) return 'npmMissing'\n // 找不到 dsh 命令(服务端 [dsh-missing] 标记 —— 乱码免疫:Windows cmd 中文版输出 GBK,\n // 经 UTF-8 解码成乱码无法匹配原文,故服务端在 spawn 前用 which/where 探测并打 ASCII 标记;\n // 其余形态:Windows cmd「不是内部或外部命令」/ POSIX「command not found」/\n // node spawn ENOENT):是本机 DSH 未正确安装或不在 PATH —— 必须先判,\n // 否则会被外层 \"Command failed\" 吞成「插件打包问题」,误导用户去提 Issue\n if (/\\[dsh-missing\\]|不是内部或外部命令|is not recognized as an internal or external command|command not found|spawn dsh ENOENT/i.test(message)) return 'dshMissing'\n // pnpm 大版本/虚拟 store 位置不一致(ERR_PNPM_UNEXPECTED_STORE / ERR_PNPM_UNEXPECTED_VIRTUAL_STORE /\n // Unexpected store location):profile 目录里的依赖是另一个大版本 pnpm 生成的(或 profile 目录\n // 被复制/移动、virtual-store-dir 配置变化导致 virtual store 位置不匹配),当前 pnpm 出于安全\n // 不认 —— 任何插件装进该 profile 都会同样失败 → 提示清理依赖目录用当前 pnpm 重建。\n // 必须在 pnpmMissing 之后 —— pnpm 在(能跑起来报错),不是「找不到命令」。\n if (/ERR_PNPM_UNEXPECTED_(VIRTUAL_)?STORE|Unexpected (virtual )?store location/i.test(message)) return 'pnpmStore'\n // pnpm 拒绝在 workspace 根目录下安装(ERR_PNPM_ADDING_TO_ROOT):profile 目录被视为\n // pnpm workspace 根,宿主调 pnpm add 时没声明在根操作(缺 -w/--workspace-root),\n // pnpm 直接整条命令拒绝 —— 本机 profile/宿主调用方式问题,任何插件都装不上\n if (/ERR_PNPM_ADDING_TO_ROOT|add the dependency to the workspace root/i.test(message)) return 'pnpmWorkspace'\n // 本地 hub 服务的来源校验拒绝了请求(服务端 403,正文恰好是 `untrusted origin`):\n // 请求在 requireTrustedPost 就被拦下,压根没进入安装流程,与 pnpm 无关。\n // 必须放在 pnpmPolicy 之前 —— 后者正则含同名裸文本,会把这条吞成「pnpm 供应链策略」,\n // 并建议用户删掉 profile 的 node_modules + pnpm-lock.yaml(无效且具破坏性)。\n // 用「整行以它结尾」来区隔 pnpm 的真实报错:pnpm 的形态后面一定跟着 dsh 的上下文\n // (如 `untrusted origin\\ndsh: pnpm failed in profile directory …`),不会被本规则命中\n if (/(^|\\n)untrusted origin\\s*$/.test(message)) return 'originRejected'\n // pnpm 供应链安全策略拦截(缺少 tarball 校验值 / minimumReleaseAge 拒收「刚发布」的包 /\n // untrusted origin 来源不受信任):pnpm 在、也连得上,纯粹是本机策略不放行 ——\n // 装任何「新发布/非信任来源」的插件都会同样失败。\n // 必须在 pnpmIgnoredBuild 之前 —— 该策略优先于「构建脚本被白名单拦截」,且两者都不引导提 Issue。\n if (missingTarballIntegrity(message) || /ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION|Minimum release age|untrusted origin/i.test(message)) return 'pnpmPolicy'\n // profile 里留着指向旧版本 dsh-plugin 的 patch 声明(ERR_PNPM_UNUSED_PATCH /\n // `The following patches were not used: dsh-plugin@1.4.2`):本机 pnpm 配置与本次解析到的版本\n // 对不上,pnpm 出于安全直接中止整次安装 —— 任何插件都装不进来 → 提示删条目后重试。\n // 必须在兜底之前,否则被归成「插件侧失败」引导去提 Issue。\n if (/ERR_PNPM_UNUSED_PATCH|patches were not used/i.test(message)) return 'pnpmUnusedPatch'\n // profile 里的文件被其他进程占用,pnpm 无法替换(Windows `os error 32`\n // 「另一个程序正在使用此文件,进程无法访问」/ EBUSY / resource busy or locked)——\n // 通常是宿主进程或杀毒软件实时扫描持有句柄;`os error 32` 用 ASCII 特征,中文原文乱码也能命中\n // → 提示完全退出宿主后重试\n if (/os error 32|EBUSY|resource busy or locked|being used by another process/i.test(message)) return 'fileLocked'\n // profile 里的文件/目录被系统拒绝写入(Windows `os error 5`「拒绝访问」= ERROR_ACCESS_DENIED /\n // Node 的 EPERM、EACCES / 英文 `Access is denied`):占用、只读属性、目录 ACL 或杀软拦截,\n // 任何插件都装不上。`os error 5` 只认 ASCII 特征 —— 中文原文经 GBK→UTF-8 解码会残缺,\n // 不能依赖「拒绝访问」四个字\n if (/os error 5\\b|ERROR_ACCESS_DENIED|\\bEPERM\\b|\\bEACCES\\b|access is denied/i.test(message)) return 'accessDenied'\n // 本机文件系统层面根本写不进去:空间耗尽(ENOSPC / no space left on device / Windows os error 112)、\n // 目标盘或挂载点只读(EROFS / read-only file system / Windows 写保护 os error 19)、\n // 文件句柄耗尽(EMFILE / ENFILE / too many open files)。都在 pnpm 落盘阶段发生,\n // 空间不足、盘只读或句柄不够时任何插件都装不进来,不是插件问题 ——\n // 必须在 network / prepare 之前判:磁盘满时 pnpm 会在日志尾部混着重试与超时特征,\n // 先判网络会把「本机磁盘写不进去」误报成「你的网络不通」\n if (/os error 112\\b|os error 19\\b|ERROR_DISK_FULL|ERROR_WRITE_PROTECT|\\bENOSPC\\b|\\bEROFS\\b|\\bEMFILE\\b|\\bENFILE\\b|no space left on device|read-only file system|too many open files/i.test(message)) return 'fsUnavailable'\n // 构建脚本被 pnpm 白名单(allowBuilds)拦截:插件的 prepare 脚本或依赖里的原生模块构建\n // 被默认拒绝(ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED / ERR_PNPM_IGNORED_BUILDS)。\n // 这类错误出现即说明 pnpm 已成功 fetch 到 tarball(网络是通的),主因是插件构建脚本\n // 被拦 —— 必须在 network 判定之前:日志尾部常混着重试残留的连接失败特征\n // (ETIMEDOUT / Failed to connect 等),若先判网络会把「插件分发问题」误报成「你的网络不通」。\n if (/ERR_PNPM_IGNORED_BUILDS|Ignored build scripts:|ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED/i.test(message)) return 'pnpmIgnoredBuild'\n // 网络问题(服务端 [network] 标记,或安装日志里的连接失败特征:git fetch 失败、\n // 连接超时/拒绝/重置、DNS 解析失败、TLS/SSL 握手失败,或 registry tarball 拉取失败\n // —— `fetch failed` / `GET https://…/-/…tgz error (n)` 是 pnpm 下载包文件时的网络层失败,\n // 常见于本机 npm/pnpm registry 被指向内网/自定义源而取不到包)—— 是本机网络/代理/源\n // 配置问题,不是插件问题。必须在 prepare/Command failed 判定之前:git fetch 失败常被\n // 外层包成 \"Command failed: git fetch ...\",先按网络特征归类才不会误判成插件问题。\n // 404 类「目标不存在」不含这些特征,仍归 repo(那是仓库/包的问题)。\n // 注意:fetch failed 只在 pnpm 拉取阶段出现;prepare/构建已跑起来(tarball 到手)的\n // 插件问题不带此特征,不会误伤(allowBuilds 拦截在上一分支先判)。\n // `Failed to fetch` 是浏览器 fetch 的 TypeError(词序与 Node 的 fetch failed 相反):界面\n // 请求根本没送达宿主服务(宿主未就绪/正在重启、本地代理拦了回环地址)。\n if (/\\[network\\]|ERR_PNPM_GIT_FETCH_FAILED|ETIMEDOUT|ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN|EPIPE|EHOSTUNREACH|ENETUNREACH|getaddrinfo|Could not connect|Could not resolve host|Network unreachable|Failed to connect|socket hang up|CERT_HAS_EXPIRED|SSL certificate problem|\\bTLS\\b|\\bSSL\\b|fetch failed|failed to fetch|\\bGET https?:\\/\\/\\S+\\.tgz\\s+error \\(\\d+\\)/i.test(message)) return 'network'\n // 装后校验拦截(服务端 verifyInstalledEntry 标记):入口文件缺失 = git 分发缺构建产物,\n // 与 pluginPrepare 同类(插件打包/分发问题),引导去仓库提 Issue\n if (/\\[packaging\\]|entry file missing/i.test(message)) return 'pluginPrepare'\n // 依赖在 registry 上不存在(`ERR_PNPM_FETCH_404` / `Not Found - 404`):pnpm 连得上 registry,\n // 是被明确告知「这个包不存在」—— 属于 profile 的本地依赖问题,不是插件问题。profile 里留着\n // 一条指向未发布包的依赖条目时,该 profile 的**任何**安装都会先卡在这条依赖上。\n // 必须在 pluginPrepare 之前判定:此时宿主尾部只有通用的 `dsh: plugin command failed`,\n // 落到下面会被当成构建失败。\n // (两个形态:pnpm 的 `[ERR_PNPM_FETCH_404] GET <url>: Not Found - 404` 与 npm 的\n // `npm error 404 Not Found - GET <url> - Not found`)\n if (/ERR_PNPM_FETCH_404|404 Not Found|Not Found - 404/i.test(message)) return 'pnpmMissingDep'\n // 再判 prepare 实际执行失败:只有构建脚本真的跑挂了才是插件问题。\n // `Command failed` 区分大小写 —— 只匹配 pnpm 包装出的报错,不匹配宿主那句小写的\n // `dsh: plugin command failed`(那只是「这条命令失败了」的通用说明)。\n if (/ERR_PNPM_PREPARE_PACKAGE|ELIFECYCLE|prepare-guard/i.test(message) || /Command failed/.test(message)) return 'pluginPrepare'\n // 其余失败(含 git prepare 被 pnpm 白名单拦截):当前通道装不上 = 插件分发/依赖的问题,一律提 Issue\n return 'repo'\n}\n\n/** 从服务端 `[npm-too-low]` 标记行提取本机 npm 版本(如 `[npm-too-low] npm@11.3.0` → \"11.3.0\");\n * 历史记录无标记时返回 null,前端据此决定提示文案是否带具体版本。 */\nexport function npmTooLowVersion(message: string): string | null {\n const m = message.match(/\\[npm-too-low\\]\\s*npm@(\\d+\\.\\d+\\.\\d+)/i)\n return m ? m[1] : null\n}\n\n/** 核心行特征:错误代码 / 生命周期脚本失败 / prepare 失败 / 描述性报错(子模块缺失、找不到等)/ 退出与宿主提示信息。 */\nconst CORE_LINE_RE = /ERR_[A-Z_]+|ELIFECYCLE|Command failed|prepare-guard|Failed to prepare|exit code|\\bprepare\\b|pnpm failed in profile|git-hosted plugins build|submodule|not found|cannot find|no such|unable to|fatal|missing|error/i\n/** pnpm 的 peer 依赖告警行(`missing peer …` / `Issues with peer dependencies found` /\n * `Peer dependencies that should be installed`):宿主提供的 peer(@deepseek-ai/*、react、\n * dsh-client-* 等,DSH profile 用 autoInstallPeers:false 不自动装)缺失是无害噪音,与插件本身\n * 无关 —— 抓核心错误时必须跳过,否则会被 CORE_LINE_RE 的 `missing` 分支误抓、淹没真正的\n * 错误码(如 git 源的 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED),让 issue 正文只剩一堆 peer WARN。 */\nconst PEER_WARN_RE = /missing peer|issues with peer dependencies|peer dependencies that should be installed/i\n/** 提交 issue 时正文里错误摘要的上限字符数。GitHub 请求行上限 8192 字节,\n * 固定模板与 URL 编码开销约 1~2K,核心错误(以 ASCII 日志为主)可安全带到 ~5K;\n * 仍超长时 pluginIssueUrl 会逐档缩小核心预算,最终 URL 不会超限。 */\nexport const MAX_CORE_CHARS = 5000\n/** 摘要里单行上限:允许构建 key 等长行也被截短。 */\nconst MAX_LINE_CHARS = 400\n\n/**\n * 核心错误收集器:从完整安装输出里挑出真正说明问题的行(错误代码、构建脚本失败、\n * 退出与宿主提示),去重后拼接,单行与总量都截断 —— 只把「重点 + 原因」带进 issue 正文,\n * 避免完整日志塞进 URL 导致请求过长。无关键行时退化为「头部 + 尾部」快照。\n * maxChars 可由调用方按最终 URL 长度收紧(pluginIssueUrl 超限时逐档缩小)。\n */\nexport function summarizeError(message: string, maxChars: number = MAX_CORE_CHARS): string {\n const seen = new Set<string>()\n const core: string[] = []\n for (const raw of message.split(/\\r?\\n/)) {\n const line = raw.trim()\n if (!line || PEER_WARN_RE.test(line) || !CORE_LINE_RE.test(line)) continue\n const short = line.length > MAX_LINE_CHARS ? `${line.slice(0, MAX_LINE_CHARS)}…` : line\n if (!seen.has(short)) {\n seen.add(short)\n core.push(short)\n }\n }\n let out: string\n if (core.length === 0) {\n // 无关键行时退化为「头部 + 尾部」快照:优先保尾部完整,头部按预算压缩,总长不超上限\n const tail = message.trimEnd().slice(-1000)\n const sep = '\\n…\\n'\n const headBudget = Math.max(maxChars - tail.length - sep.length, 0)\n const head = message.slice(0, 500).trim()\n out = `${head.length > headBudget ? head.slice(0, headBudget) : head}${sep}${tail}`\n } else {\n out = core.join('\\n')\n }\n return out.length > maxChars ? `${out.slice(0, maxChars)}\\n… (truncated)` : out\n}\n\n/** 提取首个错误代码(如 ERR_PNPM_PREPARE_PACKAGE),无则 null。\n * 代码里可能含数字(ERR_PNPM_FETCH_404 / ERR_PNPM_EBADPLATFORM_...),字符类需带上 0-9,\n * 否则会被截断成 `ERR_PNPM_FETCH_`。 */\nexport function coreErrorCode(message: string): string | null {\n const m = message.match(/\\[?ERR_[A-Z0-9_]+\\]?/)\n return m ? m[0].replace(/^\\[|\\]$/g, '') : null\n}\n\n/** 提取「registry 上不存在的包名」:从 404 行(`ERR_PNPM_FETCH_404 GET <registry>/<pkg>: Not Found - 404`)\n * 里取请求路径中的包名(含 scope,如 `@scope/name`);非 404 或提取不到返回 null。 */\nexport function missingRegistryPackageOf(message: string): string | null {\n for (const line of message.split(/\\r?\\n/)) {\n if (!/ERR_PNPM_FETCH_404|404/.test(line)) continue\n const m = line.match(/GET\\s+https?:\\/\\/[^\\s/]+\\/((?:@[^/\\s:]+\\/)?[^/\\s:]+)/)\n if (m) return m[1]\n }\n return null\n}\n\n/**\n * 从网络类失败消息里提取「具体连不上的地址」,供弹窗精准提示(你的网络无法访问什么)。\n * 优先取服务端 [network] 预检消息括号里的探测地址(中文「(…)」/ 英文「(…)」),\n * 否则取消息里出现的第一个 URL(git fetch 的仓库地址、registry 域名等)。\n * 提取不到返回 null —— 调用方据此跳过地址行。\n */\nexport function unreachableTargetOf(message: string): string | null {\n // [network] 预检消息:`无法连接到 GitHub(https://github.com/)` / `cannot reach the npm registry (https://registry.npmjs.org/)`\n const paren = message.match(/[((](https?:\\/\\/[^\\s'\"`<>()+]+)[))]/)\n if (paren) return paren[1]\n // 其余网络失败(git fetch / npm 连接失败):取第一个 URL,去掉行尾标点\n const url = message.match(/https?:\\/\\/[^\\s'\"`<>()()]+/)\n return url ? url[0].replace(/[.,;:))\\]]+$/, '') : null\n}\n\n/** npm registry 的官方/常见公开镜像主机名:tarball 从这里下载属正常配置,\n * 失败按「网络不通」提示即可,不需要额外的换源指引。 */\nconst PUBLIC_REGISTRY_HOSTS = new Set([\n 'registry.npmjs.org',\n 'registry.yarnpkg.com',\n 'registry.npmmirror.com',\n 'mirrors.cloud.tencent.com',\n 'mirrors.huaweicloud.com',\n])\n\n/**\n * 网络类失败消息里,判断是否「npm/pnpm 的 registry 被指向了内网/自定义源导致拉包失败」。\n * pnpm 下载包文件的 URL 形如 `<registry>/<pkg>/-/<pkg>-<ver>.tgz`(路径含 `/-/`);\n * 若该 tarball 的主机不属于官方/常见公开镜像,说明本机 registry 被配成了私有/内网源\n * (如公司 Artifactory)—— 常因源未同步该包、需内网认证或网络策略拦截而失败。\n * 返回该主机名供前端给出「检查 registry 配置」的精准提示;官方/公开源或提取不到返回 null,\n * 调用方按通用网络问题提示即可。\n */\nexport function registryHostOf(message: string): string | null {\n const m = message.match(/https?:\\/\\/([^/\\s]+)\\/[^\\s'\"`<>]*\\/-\\/[^\\s'\"`<>]+/)\n if (!m) return null\n const host = m[1].replace(/:\\d+$/, '')\n return PUBLIC_REGISTRY_HOSTS.has(host) ? null : host\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * URL builders: catalog detail pages, plugin site links and the pre-filled\n * GitHub issue URL used by the failure modal. Pure functions — the issue\n * URL stays within GitHub's 8192-byte request limit.\n */\nimport type { EnvInfo, HubPlugin, LocaleId } from '../types.ts'\nimport { GITHUB_URL, PLUGIN_VERSION, SITE_URL } from './constants.ts'\nimport { MAX_CORE_CHARS, classifyFailure, coreErrorCode, pnpmPolicyHintOf, summarizeError } from './failures.ts'\nimport { executedCommandOf } from './install-command.ts'\nimport type { FailureKind } from './failures.ts'\n\n/** dsh-plugin.org 中文页挂在 /zh/ 前缀下,英文在根路径。 */\nexport function langPathOf(lang: LocaleId): string {\n return lang === 'zh' ? 'zh/' : ''\n}\n\n/** 官网链接统一携带 `?ref=hub` 来源参数:统计有多少访问是从插件商城跳转而来。\n * 所有「从商城跳官网」的链接(详情页/首页)都应经由此函数拼接,避免来源参数散落各处。 */\nexport function siteUrl(path: string): string {\n return `${SITE_URL}${path}?ref=hub`\n}\n\n/**\n * 官网详情页两级路径:/plugins/{ownerSlug}/{slug};\n * 缺 ownerSlug 时从 repo 推导(卡片详情按钮与弹窗来源行共用)。\n */\nexport function pluginDetailUrl(plugin: HubPlugin, langPath: string): string {\n const repo = plugin.source?.repo ?? ''\n return siteUrl(`${langPath}plugins/${plugin.ownerSlug ?? repo.split('/')[0]?.toLowerCase() ?? ''}/${plugin.slug}`)\n}\n\n/**\n * 失败弹窗里仓库地址的跳转目标:官网详情页(含插件收录信息),\n * 与 issue 正文的 Catalog 链接同一形式(单级 /plugins/{repo})。\n */\nexport function pluginSiteUrl(repo: string): string {\n return siteUrl(`plugins/${repo}`)\n}\n\n/** 按失败类型给出简洁的错误原因标题(对外用英文):\n * 标题直接点明问题出在哪一侧(构建白名单/分发物/本机 npm/网络/插件侧),\n * 让作者与用户扫一眼列表就能分流,而不是笼统的 Install/Remove 动作词。 */\nfunction reasonTitleOf(kind: FailureKind): string {\n switch (kind) {\n case 'npmTooOld': return 'npm too old to install'\n case 'dshMissing': return 'dsh command not found on the user machine'\n case 'pnpmMissing': return 'pnpm command not found on the user machine'\n case 'pnpmStore': return 'pnpm store version mismatch on the user machine'\n case 'pnpmWorkspace': return 'pnpm workspace-root check blocked the install on the user machine'\n case 'originRejected': return 'request origin rejected by the local service on the user machine'\n case 'pnpmPolicy': return 'pnpm supply-chain policy blocked the install on the user machine'\n case 'pnpmUnusedPatch': return 'stale pnpm patch entry on the user machine'\n case 'pnpmMissingDep': return 'dependency not found on the npm registry on the user machine'\n case 'fileLocked': return 'file locked by another process on the user machine'\n case 'accessDenied': return 'file write access denied on the user machine'\n case 'fsUnavailable': return 'local file system unavailable on the user machine'\n case 'pnpmIgnoredBuild': return 'build scripts blocked by pnpm allowlist'\n case 'pluginPrepare': return 'plugin distribution incomplete'\n case 'network': return 'network failure on the user side'\n default: return 'plugin install failed'\n }\n}\n\n/**\n * 一键反馈 GitHub Issue 的预填链接:标题带「来自 dsh-plugin.org」标识 + 错误原因,\n * 正文只带核心信息 —— 原因判定 + 关键错误代码 + 尝试过的安装方式 + 宿主机器环境快照 +\n * 错误核心摘要(完整日志太长,塞进 URL 会被 GitHub 以「request URL too long」拒绝,\n * 故只收集重点)。错误弹窗、失败记录共用此逻辑。\n * env 取不到时为 null,链接照常生成、只是少环境段。\n * attempts(尝试过的安装方式,npm 反查 + 实际执行命令):作者看到我们查过/试过的命令,\n * 组织 scope 与 GitHub 用户名不一致时也能直接指认正确的 npm 包名。\n */\nexport function pluginIssueUrl(repo: string, message: string, env?: EnvInfo | null, command?: string, attempts?: string[]): string {\n // 原因判定:按失败类型归类,便于作者判断问题是否出在插件侧。\n // [packaging](预检/装后校验拦截)单独列:无论走 npm 还是 git 通道,都是分发物不完整\n // (package.json 声明的入口文件在发布物里缺失),作者照此补齐即可。\n const kind = classifyFailure(message)\n const executed = executedCommandOf(command, attempts)\n // 标题 = 错误原因(非动作词),让 issue 列表一眼可分流\n const title = `[dsh-plugin.org | dsh-plugin-hub] ${reasonTitleOf(kind)}: ${repo}`\n const reason = /\\[packaging\\]/i.test(message)\n ? 'plugin distribution is incomplete — the entry file declared in package.json is missing from the published package (github tarball or npm package); please commit build output or publish a complete package'\n : kind === 'network'\n ? 'network connectivity issue on the user side (DNS, proxy, firewall, or a blocked connection)'\n : kind === 'pluginPrepare'\n ? 'plugin prepare/build script failed during install (packaging/distribution issue)'\n : kind === 'pnpmIgnoredBuild'\n ? 'plugin depends on a native module whose build script pnpm blocks by default (use a prebuilt variant)'\n : kind === 'originRejected'\n ? 'the request never reached the install flow — the local service rejected its origin (local environment issue)'\n : kind === 'pnpmPolicy'\n ? pnpmPolicyHintOf(message) === 'failPnpmTarballIntegrityHint'\n ? 'pnpm rejected a lockfile entry without tarball integrity; inspect and back up the profile lockfile before resolving it again, keeping integrity checks enabled'\n : 'the pnpm supply-chain policy on the user machine blocked the install (minimum release age for freshly published packages / untrusted origin)'\n : kind === 'pnpmUnusedPatch'\n ? 'the profile keeps a pnpm patch entry for an older dsh-plugin version, so pnpm aborted the install (local config issue)'\n : kind === 'fileLocked'\n ? 'a file in the profile is locked by another process on the user machine (local environment issue)'\n : kind === 'accessDenied'\n ? 'the system denied write access to a file in the profile on the user machine (local environment issue)'\n : kind === 'fsUnavailable'\n ? 'the local file system could not accept the write — no space left, read-only volume, or too many open file handles on the user machine (local environment issue)'\n : 'plugin-side install failure'\n const code = coreErrorCode(message)\n // 按给定核心摘要预算构建完整预填 URL(含 URL 编码);预算可调,供超长时逐档缩小\n const build = (coreChars: number): string => {\n const body = [\n '## Summary',\n `- Cause: ${reason}`,\n ...(code ? [`- Key error: \\`${code}\\``] : []),\n '',\n // 来源说明:标题(链官网)+ 一句来源(链仓库)+ 实际执行的安装命令(含 --profile)与执行结果,链接由常量动态拼接\n `## [DSH Plugin 插件市场](${SITE_URL}) · 安装 Plugin 失败错误信息`,\n `本错误信息由 [dsh-plugin-hub](${GITHUB_URL}) 插件市场的安装程序自动生成,随本次安装失败一并提交。`,\n `- 实际执行的安装命令:${executed ? `\\`${executed}\\`` : 'unknown (no executed command recorded)'}`,\n `- 执行结果:安装失败,未能安装该插件。`,\n // 尝试过的安装方式(npm 反查 + 实际执行命令,按先后顺序):作者据此反推正确的\n // npm 包名 —— 组织 scope 与 GitHub 用户名不一致时仅凭仓库名猜不到,作者看到我们\n // 查过/试过的命令就能直接指认\n ...(attempts && attempts.length > 0\n ? ['', '## Attempted install channels(已尝试的安装方式)', ...attempts.map((a) => `- ${a}`)]\n : []),\n // [packaging] 场景:说明两种官方安装通道(npm 包 / git 直装),当前插件在对应通道下分发不完整\n ...(/\\[packaging\\]/i.test(message)\n ? [\n '',\n '## 安装方式说明',\n 'DSH 插件支持两种官方安装通道:`dsh plugin add <npm-package>`(npm 分发,需发布完整构建产物)与 `dsh plugin add git+https://github.com/owner/repo.git`(Git 直装,仓库需提交构建产物或在 package.json 提供 `prepare` 脚本)。当前插件的分发物缺少 package.json 声明的入口文件,请按所用通道补齐后重新发布。',\n ]\n : []),\n '',\n '## Environment',\n `- Plugin: \\`${repo}\\``,\n // 宿主机器环境快照:便于作者本地复现;某字段缺失时如实写 unknown,不编造\n ...(env\n ? [\n `- DSH: ${env.dshVersion ? `v${env.dshVersion}` : 'unknown'}`,\n `- Plugin Hub: v${PLUGIN_VERSION}`,\n `- Node: ${env.nodeVersion}`,\n // 工具链版本:pnpm/npm/git —— 排查 ERR_PNPM_UNEXPECTED_STORE(store 大版本不匹配)\n // 这类环境问题,作者一眼就能对号入座;探测不到如实写 unknown\n `- pnpm: ${env.pnpmVersion ? `v${env.pnpmVersion}` : 'unknown'}`,\n `- npm: ${env.npmVersion ? `v${env.npmVersion}` : 'unknown'}`,\n `- git: ${env.gitVersion ? `v${env.gitVersion}` : 'unknown'}`,\n `- OS: ${env.platform} ${env.arch} (${env.release})`,\n `- Profile: \\`${env.profile}\\``,\n `- DSH Home: \\`${env.dshHome}\\``,\n // 完整安装日志所在(正文受 URL 长度限制只能带摘要,完整日志在 hub.log,可复制/附加给作者)\n `- Full log: \\`~/.dsh/profiles/${env.profile}/hub.log\\` (paste or attach for the full output)`,\n ]\n : []),\n // 该插件在插件市场的收录位置(详情页链接)\n `- Catalog: [${pluginSiteUrl(repo)}](${pluginSiteUrl(repo)})`,\n '',\n '## Error (core)',\n '',\n '```',\n // 核心错误收集器:只挑关键行(错误代码/构建失败/退出信息),去重截断,URL 才不至于超长\n summarizeError(message, coreChars),\n '```',\n '',\n '---',\n // 底部署名:报错来自内置在 DeepSeek Harness 里的 dsh-plugin-hub 安装程序\n `This error was produced by the [dsh-plugin-hub](${GITHUB_URL}) installer bundled with DeepSeek Harness.`,\n ].join('\\n')\n return `https://github.com/${repo}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`\n }\n // GitHub 请求行上限 8192 字节:先用宽松预算(最多 ~5K 核心错误)构建,超长再逐档缩小,保证最终 URL 不超限\n const MAX_URL_CHARS = 7600\n let url = build(MAX_CORE_CHARS)\n if (url.length > MAX_URL_CHARS) {\n for (const budget of [4000, 2500, 1400, 800, 400]) {\n url = build(budget)\n if (url.length <= MAX_URL_CHARS) break\n }\n }\n return url\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Language state for the section: the Hub shares the host (system) locale —\n * the header language toggle writes the host locale preference via setLocale,\n * so the host chrome (left sidebar, settings dialog) and the Hub panel switch\n * together instead of drifting apart. Exposes the localized dictionary lookup\n * `t()` plus the zh/en language flag and the /zh/ URL path prefix.\n */\nimport { useEffect, useState } from 'react'\nimport type { LocaleId, SectionProps } from '../types.ts'\nimport { en, zh } from '../locales.ts'\nimport { langPathOf } from '../logic/urls.ts'\n\nexport function useLanguage(locale: SectionProps['locale']) {\n // 界面语言 = 宿主(系统)语言:右上角按钮切换时直接写入宿主 locale 偏好,\n // 宿主左侧菜单/设置弹窗与 Hub 面板一起切换,不存在 Hub 内部语言与宿主语言脱节的情况。\n // subscribe 订阅宿主语言变化并触发重渲染,保证 Hub 界面随时跟随宿主。\n const [, setRev] = useState(0)\n useEffect(() => locale.subscribe(() => setRev((r) => r + 1)), [locale])\n const lang: LocaleId = locale.getSnapshot().active\n const langKey: LocaleId = lang === 'en' ? 'en' : 'zh'\n // dsh-plugin.org keeps zh pages under the /zh/ prefix; en is the root.\n const langPath = langPathOf(lang)\n\n // 界面语言跟随宿主(系统)locale;宿主的 t() 绑定宿主 locale,\n // 这里基于本地字典自建翻译函数,与宿主 locale 保持一致。\n // (settings.section 的导航 label 仍在 apply 里用宿主 t(),跟随宿主语言。)\n const dict: Record<string, string> = langKey === 'en' ? en : zh\n const t = (key: string, params?: Record<string, string | number>): string => {\n const raw = dict[key] ?? key\n return params ? raw.replace(/\\{(\\w+)\\}/g, (_, k) => String(params[k] ?? '')) : raw\n }\n\n return {\n lang,\n langKey,\n langPath,\n t,\n toggleLang: () => locale.setLocale(lang === 'en' ? 'zh' : 'en'),\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Hub settings state: loaded once from the host's local /settings route\n * (persisted at ~/.dsh/profiles/<profile>/hub-settings.json), updated\n * optimistically. Every change POSTs the patch immediately so a toggled\n * switch survives a reload; a host without the server routes falls back to\n * the defaults and keeps working (settings simply do not persist).\n */\nimport { useCallback, useEffect, useState } from 'react'\n\nexport interface HubSettings {\n /** 启动时检查目录插件更新,发现可更新时在通知中心提示(安装不自动进行) */\n checkUpdatesOnStart: boolean\n /** HTTP(S) 代理地址,用于 npm / git / 目录请求(空串 = 直连) */\n proxy: string\n /** npm 镜像源 registry 地址(空串 = 未配置,跟随用户本机 npm 配置,不注入任何 registry) */\n npmRegistry: string\n /** 启用命令行安装 NPM 包(默认开) */\n enableNpmInstall: boolean\n /** 启用命令行安装 GitHub 源码(默认开) */\n enableGitInstall: boolean\n /** 启用命令行粘贴 dsh plugin 命令安装(默认开) */\n enableDshInstall: boolean\n /** 日志存放位置覆盖(空串 = 默认 ~/.dsh/profiles/<profile>/hub.log) */\n logPath: string\n}\n\nexport const DEFAULT_SETTINGS: HubSettings = {\n checkUpdatesOnStart: true,\n proxy: '',\n npmRegistry: '',\n enableNpmInstall: true,\n enableGitInstall: true,\n enableDshInstall: true,\n logPath: '',\n}\n\nasync function loadRemote(): Promise<HubSettings> {\n try {\n const res = await fetch('/dsh-plugin-hub/settings', { cache: 'no-store' })\n if (!res.ok) throw new Error(`settings ${res.status}`)\n const data = await res.json() as Partial<HubSettings>\n return { ...DEFAULT_SETTINGS, ...data }\n } catch {\n return DEFAULT_SETTINGS\n }\n}\n\nexport function useSettings() {\n const [settings, setSettings] = useState<HubSettings>(DEFAULT_SETTINGS)\n /** 服务端配置是否已加载:更新策略等启动期逻辑须等真实值,避免用默认值误触发 */\n const [ready, setReady] = useState(false)\n\n useEffect(() => {\n let alive = true\n void loadRemote().then((s) => {\n if (!alive) return\n setSettings(s)\n setReady(true)\n })\n return () => { alive = false }\n }, [])\n\n /** 部分更新:本地立即生效(乐观),同时 POST 持久化;持久化失败静默(本次会话仍生效)。 */\n const update = useCallback((patch: Partial<HubSettings>) => {\n setSettings((prev) => ({ ...prev, ...patch }))\n void fetch('/dsh-plugin-hub/settings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(patch),\n cache: 'no-store',\n }).catch(() => { /* 宿主未挂路由:仅本次会话生效 */ })\n }, [])\n\n /** 重置为默认设置:本地立即回默认,同时通知服务端删除设置文件;失败静默。 */\n const reset = useCallback(() => {\n setSettings({ ...DEFAULT_SETTINGS })\n void fetch('/dsh-plugin-hub/settings/reset', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: '{}',\n cache: 'no-store',\n }).catch(() => { /* 宿主未挂路由:仅本次会话回默认 */ })\n }, [])\n\n return { settings, ready, update, reset }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Background install/remove task queue for the Plugin Hub.\n *\n * Mirrors the server-side FIFO active queue by polling /active, settles\n * vanished tasks against /status, and exposes the queue actions (install,\n * uninstall, cancel) plus the modal task lookups used by the dialogs.\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { HubPlugin, InstallChannel, LocaleId, Translate } from '../types.ts'\nimport { executedCommandOf, installCommandOf, installTargetOf, repoFromInstallTarget } from '../logic/install-command.ts'\nimport type { InstalledItem } from '../logic/installed.ts'\n\n/** 安装/卸载请求超时(ms):服务端 preflight + npm 反查可能耗时(各自都有超时,合计约 20~30s),\n * 给足余量;超时主动中止,避免服务端 preflight 网络挂起时前端永久卡「安装中 0%」。 */\nconst REQUEST_TIMEOUT_MS = 60_000\n\n/** 客户端任务队列项:镜像服务端 active 任务(running 在前、pending 在后)。 */\nexport interface QueueTask {\n id: number\n kind: 'install' | 'uninstall'\n /** 展示目标:owner/repo(安装)或 npm 包名(卸载) */\n target: string\n /** 插件中文简介(入队时从插件数据带过来,轮询合并时保留):展示在仓库名下方,标识排队中的插件 */\n desc?: string\n /** 所属插件仓库(owner/repo):失败时错误弹窗据此提供「去仓库反馈」入口;卸载为 null */\n repo: string | null\n /** 自定义安装入口渠道(NPM 包 / GitHub 源码 / DSH 命令三张卡片):失败时错误/通知精准\n * 溯源「从哪个入口发起」;目录插件安装无此字段(非自定义入口)。 */\n channel?: InstallChannel\n /** 实际动作(add/update/remove):成功通知据此区分「安装成功」与「更新成功」。\n * 服务端 /active 带回真实动作;本地乐观入队按 update 标记推断。 */\n action?: 'add' | 'update' | 'remove'\n /** 安装时的目录信号快照(版本 + 仓库更新时间):任务成功后在本地记录,供「有更新」比对 */\n version?: string\n updatedAt?: string\n /** pending 排队中 / running 执行中 / cancelling 取消中(客户端乐观过渡态) */\n status: 'pending' | 'running' | 'cancelling'\n progress: number\n lines: string[]\n /** 乐观入队条目:点击安装后立即显示「正在安装中」,等 POST 响应回来再换成真实任务 id。\n * 服务端还没登记(preflight 中),轮询合并/消失检测都必须跳过,避免被当作已结束任务收尾。 */\n optimistic?: boolean\n /** 实际执行的安装命令(npm/git 通道随插件数据决定):失败时 issue 预填如实展示 */\n command?: string\n /** 尝试过的安装方式(npm registry 反查 + 实际执行命令,按先后顺序):失败时 issue 预填一并贴给作者 */\n attempts?: string[]\n /** 完成结果是否需要重启才生效(服务端任务终态带出)。默认 true 保底:数据缺失时不静默视为已生效。\n * 仅刷新解决不了的兜底场景(热挂载失败 / 非 dsh 插件 / 更新)为 true,结果视图给「立即重启」;\n * 其余(热挂载成功、卸载已即时停用、全局安装)为 false,结果视图仅「完成」。 */\n needsRestart: boolean\n /** 完成结果是否只需刷新页面即生效(插件已热挂进运行中 loader,或卸载后插件面板仍残留在当前页面):\n * true 时关闭结果弹窗 / Toast 消失后由上层自动刷新页面,不给手动刷新按钮。 */\n needsReload?: boolean\n}\n\n/** 客户端待重启项:镜像服务端内存列表 + 本地补齐的展示信息(简介/版本)。 */\nexport interface PendingRestart {\n /** owner/repo(展示用,已从安装目标归一化) */\n target: string\n /** 待重启语义:install 装完等挂载 / uninstall 卸完等清理 */\n kind: 'install' | 'uninstall'\n at: number\n desc?: string\n version?: string\n}\n\nexport interface TaskQueueOptions {\n t: Translate\n /** 界面语言(zh/en):随安装请求带给服务端,网络预检等错误消息按用户语言提示 */\n langKey?: LocaleId\n refreshInstalled: () => void\n /** 任务成功完成:viaModal 表示任务对应当前打开弹窗(弹窗切结果视图),否则走 Toast;repo 供成功通知记录;\n * needsRestart 表示该任务完成后是否仍需宿主重启(结果视图据此给「重启 / 仅完成」);\n * needsReload 表示是否只需刷新页面即生效(热挂载成功、或卸载后插件面板仍残留)。\n * update 表示实际执行的是更新(覆盖重装)而非首次安装:通知中心据此显示「更新成功」而非「安装成功」。 */\n onInstallDone: (viaModal: boolean, repo: string | null, needsRestart: boolean, update?: boolean, needsReload?: boolean) => void\n onUninstallDone: (viaModal: boolean, repo: string | null, needsRestart: boolean, needsReload?: boolean) => void\n /** 任务失败:完整输出或兜底文案 + 所属插件仓库 + 操作类型(安装/卸载)+ 实际执行的安装命令(issue 预填用,可缺省)+ 尝试过的安装方式(npm 反查/执行命令,可缺省)+ 是否更新。 */\n onError: (message: string, repo: string | null, kind: 'install' | 'uninstall', command?: string, attempts?: string[], update?: boolean) => void\n /** 当前打开的安装/卸载弹窗插件:用于在弹窗内匹配进行中的任务。 */\n installPlugin: HubPlugin | null\n /** 当前打开的自定义安装(命令行)确认弹窗目标:与应用商店同一弹窗机制,匹配进行中的 custom 安装任务。 */\n installCustomTarget?: string | null\n /** 当前打开的全局 npm 安装(`npm install -g <pkgs>`)确认弹窗身份(包列表空格拼接):\n * 匹配服务端登记的全局安装任务(target = 包列表 join(' '))。 */\n installGlobalTarget?: string | null\n uninstallPlugin: HubPlugin | null\n /** 已安装视图发起的卸载目标(npm 包名):目录插件走 uninstallPlugin,自定义安装走包名直卸。 */\n uninstallName: string | null\n installedName: (p: HubPlugin) => string | null\n /** 待重启项展示信息补齐:按 owner/repo 从插件目录解析简介/版本;找不到返回 null。 */\n resolvePending: (repo: string) => { desc?: string; version?: string } | null\n}\n\n/** 入口渠道的 i18n key:NPM 包 / GitHub 源码 / DSH 命令。 */\nconst channelKeyOf = (channel: InstallChannel): string =>\n channel === 'git' ? 'installChannelGit' : channel === 'dsh' ? 'installChannelDsh' : 'installChannelNpm'\n\n/** 失败消息的入口溯源前缀:自定义安装(带渠道)在错误正文顶部精准指出从哪张卡片发起;\n * 目录插件安装(无渠道)返回 null,错误正文保持原样。 */\nconst entryLineOf = (t: Translate, channel: InstallChannel | undefined): string | null =>\n channel ? t('installEntryLine', { c: t(channelKeyOf(channel)) }) : null\n\nexport function useTaskQueue(opts: TaskQueueOptions) {\n const {\n t, langKey, refreshInstalled, onInstallDone, onUninstallDone, onError,\n installPlugin, installCustomTarget, installGlobalTarget, uninstallPlugin, uninstallName, installedName, resolvePending,\n } = opts\n const [queue, setQueue] = useState<QueueTask[]>([])\n const queueRef = useRef<QueueTask[]>([])\n /** 待重启列表(服务端内存态 + 本地展示信息补齐);与 queue 一样以 ref 为唯一事实来源。 */\n const [pendingRestarts, setPendingRestarts] = useState<PendingRestart[]>([])\n const pendingRef = useRef<PendingRestart[]>([])\n /** 本次会话内安装成功插件的展示信息(目标 → 简介/版本):轮询合并待重启列表时补齐,刷新后由 resolvePending 兜底。 */\n const pendingInfoRef = useRef<Map<string, { desc?: string; version?: string }>>(new Map())\n /** 保持最新的 resolvePending:轮询闭包捕获的是调用那一刻的目录状态,目录晚加载时也能补齐。 */\n const resolvePendingRef = useRef(resolvePending)\n resolvePendingRef.current = resolvePending\n /** 当前打开弹窗所对应的任务 id:该任务完成时弹窗切换为结果视图 */\n const modalTaskRef = useRef<number | null>(null)\n /** 已开始收尾但尚未结束的任务 id(服务端 /active 已消失 → 查 /status 中):并发轮询时跳过,避免重复收尾 */\n const settlingRef = useRef<Set<number>>(new Set())\n /** 轮询定时器句柄(队列清空/组件卸载时清理) */\n const pollRef = useRef<number | null>(null)\n /** 请求在途的目标集合(同步防重):双击安装/卸载时第二击直接忽略。\n * 本地队列任务要等 fetch 返回后才入队,仅靠 queueRef 检查拦不住请求窗口内的重复点击。 */\n const submittingRef = useRef<Set<string>>(new Set())\n /** 乐观入队临时 id 计数器:递减产生唯一负数,与服务端自增正数 id 永不冲突。 */\n const tempIdRef = useRef(0)\n /** 请求在途标记:弹窗据此禁用确认按钮,避免等待响应期间被再次点击。 */\n const [submitting, setSubmitting] = useState(false)\n\n /** 停止后台任务轮询(任务结束或组件卸载时清理)。 */\n const stopPoll = () => {\n if (pollRef.current !== null) {\n window.clearInterval(pollRef.current)\n pollRef.current = null\n }\n }\n\n /** 队列与待重启都清空才停轮询:待重启期间持续轮询,宿主一重启(内存列表清空)立刻感知并消失。 */\n const maybeStopPoll = () => {\n if (queueRef.current.length === 0 && pendingRef.current.length === 0) stopPoll()\n }\n\n // 组件卸载时兜底清理轮询定时器\n useEffect(() => stopPoll, [])\n\n /** 更新队列(同步镜像到 ref:queueRef 是唯一事实来源,state 只负责触发渲染,\n * 避免依赖 React updater 的异步调度时序导致 gone/stopPoll/防重复入队读到旧值)。 */\n const applyQueue = (updater: (prev: QueueTask[]) => QueueTask[]) => {\n const next = updater(queueRef.current)\n queueRef.current = next\n setQueue(next)\n }\n\n /** 解析服务端待重启列表(安装目标归一化为 owner/repo,与安装任务对齐)。 */\n const parsePendingRestarts = (value: unknown): PendingRestart[] => {\n if (!Array.isArray(value)) return []\n const out: PendingRestart[] = []\n for (const x of value) {\n if (typeof x !== 'object' || x === null) continue\n const target = (x as { target?: unknown }).target\n if (typeof target !== 'string' || target === '') continue\n const at = (x as { at?: unknown }).at\n out.push({\n target: repoFromInstallTarget(target),\n kind: (x as { kind?: unknown }).kind === 'uninstall' ? 'uninstall' : 'install',\n at: typeof at === 'number' ? at : 0,\n })\n }\n return out\n }\n\n /** 合并服务端待重启列表:保留已有展示信息,缺失时用会话内记录 / 目录解析补齐。 */\n const applyPending = (raw: PendingRestart[]) => {\n const prev = pendingRef.current\n const next = raw.map((p) => {\n const old = prev.find((q) => q.target === p.target)\n if (old?.desc !== undefined) return { ...p, desc: old.desc, version: old.version }\n const info = pendingInfoRef.current.get(p.target) ?? resolvePendingRef.current?.(p.target) ?? null\n return info ? { ...p, desc: info.desc, version: info.version } : p\n })\n pendingRef.current = next\n setPendingRestarts(next)\n }\n\n /** 向宿主记录某插件的安装时目录信号(version + updatedAt);version 为空时清除记录(卸载)。 */\n const syncInstalledVersion = async (repo: string | null, version: string | undefined, updatedAt: string | undefined) => {\n if (!repo) return\n try {\n await fetch('/dsh-plugin-hub/installed-version', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ repo, version: version ?? null, updatedAt }),\n })\n } catch {\n // 宿主未挂本地路由:静默忽略,仅本机展示受影响\n }\n }\n\n /** 后台任务结束(active 中消失后查终态确认):完成 → 刷新安装表 + 结果视图/toast;失败 → 完整错误弹窗 */\n const finishQueueTask = (ok: boolean, q: QueueTask, lines: string[]) => {\n applyQueue((prev) => prev.filter((x) => x.id !== q.id))\n if (ok) {\n refreshInstalled()\n if (q.kind === 'uninstall') {\n // 卸载成功:清掉本地版本记录\n void syncInstalledVersion(q.repo, undefined, undefined)\n onUninstallDone(modalTaskRef.current === q.id, q.repo, q.needsRestart, q.needsReload ?? false)\n } else {\n // 安装成功:记录安装时的目录信号(版本 + 仓库更新时间),供「有更新」比对;\n // 同时缓存展示信息,待重启列表(服务端已登记)合并时直接补齐简介/版本\n void syncInstalledVersion(q.repo, q.version, q.updatedAt)\n pendingInfoRef.current.set(q.target, { desc: q.desc, version: q.version })\n onInstallDone(modalTaskRef.current === q.id, q.repo, q.needsRestart, q.action === 'update', q.needsReload ?? false)\n }\n } else {\n // 失败:完整展示全部输出行(最新在前,逆序为日志阅读顺序),不裁剪\n const rawDetail = lines.length > 0\n ? [...lines].reverse().join('\\n')\n : q.kind === 'uninstall' ? t('uninstallFail') : t('installFail')\n // 自定义安装(带入口渠道):错误正文顶部精准提示「从哪张卡片发起」,目录安装保持原样\n const entry = entryLineOf(t, q.channel)\n onError(entry ? `${entry}\\n${rawDetail}` : rawDetail, q.repo, q.kind, executedCommandOf(q.command, q.attempts), q.attempts, q.action === 'update')\n }\n maybeStopPoll()\n }\n\n /** 卸载成功收尾前的进度过渡:任务已在服务端结束,但保留本地展示,\n * 让进度条在 ~2.4s 内缓缓跑到 100% 再切结果/Toast,给用户一个交互过程,\n * 而不是命令一执行进度条就一闪消失。 */\n const settleDone = (q: QueueTask, lines: string[]) => {\n // 收尾动画期间停止轮询:任务已从服务端 /active 消失,无需再查;\n // 停掉可避免 pollQueue 的 gone 检测把它当「再消失一次」而重复收尾\n stopPoll()\n const from = Math.min(q.progress, 90) // 起点最多 90,给进度条留出跑满的缓冲空间\n const steps = 20\n const stepMs = 120 // 20 步 × 120ms = 2.4s\n let step = 0\n // 动画期间固定显示「卸载中」:任务实已结束,但进度在跑,与「排队中」文案更协调\n applyQueue((prev) => prev.map((x) => (x.id === q.id ? { ...x, status: 'running' as const } : x)))\n const timer = window.setInterval(() => {\n step += 1\n const progress = Math.round(from + (100 - from) * (step / steps))\n applyQueue((prev) => prev.map((x) => (x.id === q.id ? { ...x, progress } : x)))\n if (step >= steps) {\n window.clearInterval(timer)\n finishQueueTask(true, q, lines)\n // 队列若还有其它已在排队/执行的任务,恢复轮询继续盯;已清空则自然停住\n if (queueRef.current.length > 0) pollQueue()\n }\n }, stepMs)\n }\n\n /** 任务在 /active 中消失 = 已结束:查 /status 拿终态并收尾(cancelled 静默移除)。 */\n const settleTask = async (q: QueueTask) => {\n let status = 'failed'\n let lines: string[] = []\n let attempts: string[] | undefined\n try {\n const res = await fetch(`/dsh-plugin-hub/status?task=${q.id}`, { cache: 'no-store' })\n if (res.ok) {\n const data = await res.json() as { task?: { status?: string; lines?: string[]; attempts?: string[]; needsRestart?: unknown; needsReload?: unknown } }\n const task = data.task\n if (task !== undefined) {\n status = task.status ?? 'failed'\n lines = task.lines ?? []\n attempts = Array.isArray(task.attempts) ? task.attempts : undefined\n // 终态带出的「是否需要重启 / 是否只需刷新」覆盖本地(服务端 done 时按 loader 热挂/即时移除情况设置)\n const needsRestart = typeof task.needsRestart === 'boolean' ? task.needsRestart : q.needsRestart\n const needsReload = typeof task.needsReload === 'boolean' ? task.needsReload : (q.needsReload ?? false)\n if (status === 'done') {\n const settled = { ...q, needsRestart, needsReload }\n // 卸载成功走进度过渡动画;安装成功直接收尾\n if (q.kind === 'uninstall') settleDone(settled, lines)\n else finishQueueTask(true, settled, lines)\n return\n }\n if (status === 'failed') {\n // 服务端终态带出的尝试记录覆盖本地:以实际执行为准\n finishQueueTask(false, { ...q, attempts }, lines)\n return\n }\n }\n }\n } catch { /* 服务端不可达:按失败处理 */ }\n applyQueue((prev) => prev.filter((x) => x.id !== q.id)) // cancelled / 未知\n maybeStopPoll()\n }\n\n /** 轮询整个队列:合并服务端 /active(running 在前、pending 在后),\n * 消失的任务查终态收尾;队列清空即停止轮询。 */\n const pollQueue = () => {\n stopPoll()\n pollRef.current = window.setInterval(async () => {\n try {\n const res = await fetch('/dsh-plugin-hub/active', { cache: 'no-store' })\n if (!res.ok) throw new Error(`active ${res.status}`)\n const data = await res.json() as {\n tasks?: { id?: unknown; action?: unknown; target?: unknown; status?: unknown; progress?: unknown; lines?: unknown; attempts?: unknown; needsRestart?: unknown; installChannel?: unknown }[]\n pendingRestarts?: unknown\n }\n const active = (data.tasks ?? []).filter((a) => typeof a.id === 'number')\n const byId = new Map(active.map((a) => [a.id as number, a]))\n // 先捕获旧队列:gone 是「旧队列里服务端已消失的任务」的差集,必须在 applyQueue 更新前取\n const prevQueue = queueRef.current\n // 待重启列表同步(服务端内存态:宿主重启后自然变空,这里随之清空 UI)\n applyPending(parsePendingRestarts(data.pendingRestarts))\n // 合并:running 在前、pending 在后(与服务端一致),新出现任务补入队列\n applyQueue((prev) => {\n const next: QueueTask[] = []\n for (const a of active) {\n const id = a.id as number\n const prevTask = prev.find((q) => q.id === id)\n const isRemove = a.action === 'remove'\n next.push({\n id,\n kind: isRemove ? 'uninstall' : 'install',\n target: typeof a.target === 'string' ? repoFromInstallTarget(a.target) : (prevTask?.target ?? ''),\n desc: prevTask?.desc,\n repo: prevTask?.repo ?? (isRemove ? null : (typeof a.target === 'string' ? repoFromInstallTarget(a.target) : null)),\n // 安装时快照的目录信号:轮询合并时保留,任务成功后记录到本地\n version: prevTask?.version,\n updatedAt: prevTask?.updatedAt,\n status: a.status === 'running' ? 'running' : 'pending',\n progress: typeof a.progress === 'number' ? a.progress : prevTask?.progress ?? 0,\n lines: Array.isArray(a.lines) ? (a.lines as string[]) : (prevTask?.lines ?? []),\n attempts: Array.isArray(a.attempts) ? (a.attempts as string[]) : (prevTask?.attempts ?? []),\n needsRestart: typeof a.needsRestart === 'boolean' ? a.needsRestart : (prevTask?.needsRestart ?? true),\n // 入口渠道:本地乐观入队已带;服务端 /active 也带回(刷新恢复用),服务端优先\n channel: (a.installChannel === 'npm' || a.installChannel === 'git' || a.installChannel === 'dsh')\n ? a.installChannel\n : prevTask?.channel,\n })\n }\n // 保留乐观条目:服务端尚未登记(preflight 中),无真实 id,不能因 active 缺它就被合并吞掉\n const keepOpt = prev.filter((q) => q.optimistic && !next.some((x) => x.id === q.id))\n if (keepOpt.length > 0) next.push(...keepOpt)\n // 保留「已从服务端消失、但尚未收尾」的任务:收尾(settleTask)负责移除。\n // 若在这里提前摘除,卸载/安装完成的那一瞬队列会先变空,弹窗闪回「确认」态\n // (busy=false 且未 done),表现为「卸载中 → 卸载 → 卸载完成」的中间回退。\n const keepGone = prev.filter((q) =>\n !byId.has(q.id) && !next.some((x) => x.id === q.id) && q.status !== 'cancelling' && !q.optimistic)\n if (keepGone.length > 0) next.push(...keepGone)\n return next\n })\n // 本地有、服务端已消失 → 已结束:逐个查终态收尾\n // (cancelling 是客户端乐观过渡态,交给 cancelTask 的定时移除,不在轮询里提前收敛;\n // optimistic 是点击后尚未登记的占位,服务端 /status 查不到,跳过免误判成失败;\n // settling 是上一轮已开始收尾的任务,并发轮询直接跳过,避免重复收尾)\n const gone = prevQueue.filter((q) =>\n !byId.has(q.id) && q.status !== 'cancelling' && !q.optimistic && !settlingRef.current.has(q.id))\n for (const q of gone) {\n // 防御:同 id 任务可能已被上一轮收尾移除(极端时序下轮询合并出的重复条目),跳过避免重复收尾\n if (!queueRef.current.some((x) => x.id === q.id)) continue\n settlingRef.current.add(q.id)\n try { await settleTask(q) } finally { settlingRef.current.delete(q.id) }\n }\n } catch {\n // 服务端暂不可达:静默等待下一轮\n }\n }, 600)\n }\n\n // 刷新后恢复任务队列与待重启列表:任务注册表在服务端内存里,只要宿主进程没重启就还在;\n // 重新拉取 /active(数组)继续轮询,界面上显示「进行中」状态条,可展开查看实时输出。\n useEffect(() => {\n let cancelled = false\n const restore = async () => {\n try {\n const res = await fetch('/dsh-plugin-hub/active', { cache: 'no-store' })\n if (!res.ok) return\n const data = await res.json() as {\n tasks?: { id?: unknown; action?: unknown; target?: unknown; status?: unknown; progress?: unknown; lines?: unknown; attempts?: unknown; needsRestart?: unknown; displayTarget?: unknown; installChannel?: unknown }[]\n pendingRestarts?: unknown\n }\n if (cancelled) return\n // 待重启:装完没重启的持久提醒,刷新页面也要恢复\n applyPending(parsePendingRestarts(data.pendingRestarts))\n const items: QueueTask[] = (data.tasks ?? [])\n .filter((a) => typeof a.id === 'number')\n .map((a) => {\n const isRemove = a.action === 'remove'\n // 服务端任务的 target:显式 HTTPS Git URL(安装)/ npm 包名(npm 安装/卸载)。\n // 恢复展示统一用 displayTarget(owner/repo,服务端固定传):npm 安装时 target 是包名,\n // 直接展示会让用户看到「安装方式」的内部细节,违背无感知原则;卸载保持包名(匹配已装表)。\n const display = typeof (a as { displayTarget?: unknown }).displayTarget === 'string' ? repoFromInstallTarget((a as { displayTarget: string }).displayTarget) : ''\n const fallback = typeof a.target === 'string' ? repoFromInstallTarget(a.target) : ''\n return {\n id: a.id as number,\n kind: (isRemove ? 'uninstall' : 'install') as 'install' | 'uninstall',\n target: isRemove ? fallback : (display || fallback),\n repo: isRemove ? null : (display || fallback),\n action: (a.action === 'add' || a.action === 'update' || a.action === 'remove') ? a.action : 'add',\n status: a.status === 'running' ? 'running' : 'pending',\n progress: typeof a.progress === 'number' ? a.progress : 0,\n lines: Array.isArray(a.lines) ? (a.lines as string[]) : [],\n attempts: Array.isArray((a as { attempts?: unknown }).attempts) ? ((a as { attempts: string[] }).attempts) : [],\n needsRestart: typeof (a as { needsRestart?: unknown }).needsRestart === 'boolean' ? (a as { needsRestart: boolean }).needsRestart : true,\n // 服务端登记的入口渠道:自定义安装刷新后也能精准溯源(目录安装无此字段)\n channel: (a.installChannel === 'npm' || a.installChannel === 'git' || a.installChannel === 'dsh') ? a.installChannel : undefined,\n }\n })\n if (items.length > 0 || pendingRef.current.length > 0) {\n applyQueue((prev) => [...prev, ...items.filter((n) => !prev.some((p) => p.id === n.id))])\n // 刷新后恢复的任务同样保持折叠:摘要条提示进行中,点开才看明细/日志\n pollQueue()\n }\n } catch { /* host without the plugin's server routes */ }\n }\n void restore()\n return () => { cancelled = true }\n }, [])\n\n /** 弹窗动作:直接安装。请求宿主本地路由,任务进入服务端队列(FIFO),弹窗内实时显示进度。 */\n /** 安装入队核心:目录插件(catalog,后端走目录白名单)与命令行安装(custom,\n * 受安全开关控制)共用。队列条目一律用仓库名(repo)展示/防重,只有发给后端的\n * 实际安装目标(target)随通道变化(npm 包名 / github: 源)。 */\n const submitInstall = async (input: {\n /** 发给后端的实际安装目标:npm 包名或 github: 源(服务端再决定最终通道) */\n target: string\n /** 队列展示与防重用的仓库名 */\n repo: string\n desc?: string\n version?: string\n updatedAt?: string\n command: string\n source: 'catalog' | 'custom'\n /** 更新已安装目标(放行 add 覆盖重装) */\n update?: boolean\n /** 全局 npm 安装包列表(`npm install -g <pkgs>`):非空时服务端执行全局安装,不进任何 profile */\n globalNpm?: string[]\n /** 自定义安装入口渠道(NPM 包 / GitHub 源码 / DSH 命令卡片):随请求上报服务端落日志,\n * 失败弹窗/通知据此精准溯源「从哪个入口发起」;目录安装不传。 */\n channel?: InstallChannel\n }) => {\n // 防重复入队:同一目标已在排队/执行中则忽略\n if (queueRef.current.some((q) => q.kind === 'install' && q.target === input.repo)) return\n // 请求在途防重:任务要等响应回来才进本地队列,这之前再次点击(双击)直接忽略\n if (submittingRef.current.has(input.repo)) return\n submittingRef.current.add(input.repo)\n // 乐观入队:点击安装立即显示「正在安装中」,不等 POST 响应。\n // 服务端 /install 会先跑预检(preflight,可能耗时数秒)再入队,若等响应才入队列,\n // 用户点完安装立刻去看任务会看不到 —— 只有刷新后 restore 才拉回来。\n // 用负临时 id 占位,响应回来换成真实 task id;失败/出错则移除该占位。\n tempIdRef.current -= 1\n const tempId = tempIdRef.current\n modalTaskRef.current = tempId\n applyQueue((prev) => [...prev, {\n id: tempId, kind: 'install', target: input.repo, repo: input.repo, desc: input.desc,\n version: input.version, updatedAt: input.updatedAt,\n status: 'running', progress: 0, lines: [], optimistic: true,\n command: input.command,\n channel: input.channel,\n action: input.update ? 'update' : 'add',\n // 服务端登记后 /active 会带回真实尝试记录(npm 反查 + 执行命令),先占位空列表\n attempts: [], needsRestart: true,\n }])\n setSubmitting(true)\n const controller = new AbortController()\n const timeout = window.setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n try {\n const res = await fetch('/dsh-plugin-hub/install', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n repo: input.target,\n display: input.repo,\n source: input.source,\n mode: input.update ? 'update' : undefined,\n // 界面语言带给服务端:网络预检等错误消息按用户当前语言返回(中文界面给中文,英文界面给英文)\n ...(langKey ? { lang: langKey } : {}),\n // 自定义安装入口渠道(三张卡片之一):服务端日志/报错提示据此溯源\n ...(input.channel ? { installChannel: input.channel } : {}),\n ...(input.globalNpm && input.globalNpm.length > 0 ? { globalNpm: input.globalNpm } : {}),\n }),\n signal: controller.signal,\n })\n const data = await res.json() as { ok?: boolean; task?: number; error?: string; attempts?: string[] }\n if (!data.ok || typeof data.task !== 'number') {\n // 请求层失败(重复安装 409 / 参数错误 / 安全开关 403 等):移除乐观条目 + 完整错误弹窗\n applyQueue((prev) => prev.filter((x) => x.id !== tempId))\n // 同步 400(如预检拦截)服务端会附上已尝试的安装方式,issue 预填一并展示;\n // 用 || 而非 ?? :error 为空字符串时回退 HTTP 状态,避免复制出来是空白。\n // 自定义安装(带入口渠道):错误正文顶部精准提示「从哪张卡片发起」\n const entry = entryLineOf(t, input.channel)\n const msg = data.error || `HTTP ${res.status}`\n onError(entry ? `${entry}\\n${msg}` : msg, input.repo, 'install', input.command, data.attempts)\n return\n }\n const taskId = data.task\n modalTaskRef.current = taskId\n // 用真实任务 id 替换乐观占位,解除 optimistic 标记(此后归正常收尾/轮询处理)\n applyQueue((prev) => prev.map((x) => (x.id === tempId\n ? { ...x, id: taskId, optimistic: undefined }\n : x)))\n // 提前缓存展示信息:安装成功后服务端登记待重启,轮询合并时不用等目录解析\n pendingInfoRef.current.set(input.repo, { desc: input.desc, version: input.version })\n // 摘要条常驻顶部(含实时进度),明细面板保持折叠,想看时再点开\n pollQueue()\n } catch (err) {\n // 网络异常:移除乐观条目 + 兜底错误弹窗(附上底层原因,避免只剩一句笼统的「安装失败」)\n applyQueue((prev) => prev.filter((x) => x.id !== tempId))\n const aborted = (err as { name?: string } | null)?.name === 'AbortError'\n const reason = aborted\n ? t('requestTimeout')\n : err instanceof Error && err.message ? err.message : String(err ?? '')\n // 自定义安装(带入口渠道):错误正文顶部精准提示「从哪张卡片发起」\n const entry = entryLineOf(t, input.channel)\n const msg = reason ? `${t('installFail')} — ${reason}` : t('installFail')\n onError(entry ? `${entry}\\n${msg}` : msg, input.repo, 'install', input.command)\n } finally {\n window.clearTimeout(timeout)\n submittingRef.current.delete(input.repo)\n setSubmitting(false)\n }\n }\n\n /** 目录插件安装:通道由目录数据(npmPackage)决定,走 catalog 白名单。 */\n const installNow = async (p: HubPlugin, opts?: { update?: boolean }) => {\n const repo = p.source?.repo ?? ''\n if (!repo) return\n // 安装通道决策(用户无感知):有 npm 包名 → 走 npm;否则 git 直装。\n const { target } = installTargetOf(p)\n if (!target) return\n await submitInstall({\n target,\n repo,\n desc: p.description,\n version: p.version,\n updatedAt: p.dates?.repoUpdatedAt,\n command: installCommandOf(p, true),\n source: 'catalog',\n update: opts?.update,\n })\n }\n\n /** 命令行安装:用户手输 npm 包名或 GitHub 地址,走 custom 源(受安全开关控制)。\n * update=true 时对已安装目标放行覆盖重装(与目录插件「更新」同一语义)。\n * channel=入口渠道(NPM 包 / GitHub 源码 / DSH 命令卡片):上报服务端落日志,\n * 失败弹窗/通知据此精准溯源。\n * 队列展示/防重一律用归一化身份(owner/repo 或 npm 包名):与服务端 /active 合并、\n * 弹窗目标匹配同口径,npm 包名透传不受影响。 */\n const installCustom = async (raw: string, opts?: { update?: boolean; channel?: InstallChannel }) => {\n const target = raw.trim()\n if (!target) return\n const repo = repoFromInstallTarget(target)\n await submitInstall({\n target,\n repo,\n command: `pnpm add ${target}`,\n source: 'custom',\n update: opts?.update,\n channel: opts?.channel,\n })\n }\n\n /** 全局 npm 安装(官方 README 的 `npm install -g <pkgs>`):不进任何 profile、无需宿主重启。\n * 队列展示/防重用包列表空格拼接的身份(与服务端 target 同口径);入口渠道固定为 npm(NPM 包卡片)。 */\n const installGlobalNpm = async (pkgs: string[], opts?: { update?: boolean; channel?: InstallChannel }) => {\n const list = (pkgs ?? []).map((p) => p.trim()).filter((p) => p !== '')\n if (list.length === 0) return\n const identity = list.join(' ')\n await submitInstall({\n target: identity,\n repo: identity,\n command: `npm install -g ${identity}`,\n source: 'custom',\n globalNpm: list,\n update: opts?.update,\n channel: opts?.channel ?? 'npm',\n })\n }\n\n /** 卸载入队核心:按 npm 包名直卸(目录插件与自定义安装共用,弹窗进度匹配同源)。 */\n const enqueueUninstall = async (name: string, repo: string | null, desc?: string) => {\n if (!name) return\n if (queueRef.current.some((q) => q.kind === 'uninstall' && q.target === name)) return\n // 请求在途防重:与安装一致,响应回来前再次点击直接忽略\n if (submittingRef.current.has(name)) return\n submittingRef.current.add(name)\n setSubmitting(true)\n const controller = new AbortController()\n const timeout = window.setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n try {\n const res = await fetch('/dsh-plugin-hub/uninstall', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ name, repo: repo ?? undefined }),\n signal: controller.signal,\n })\n const data = await res.json() as { ok?: boolean; task?: number; error?: string }\n if (!data.ok || typeof data.task !== 'number') {\n onError(data.error || `HTTP ${res.status}`, repo, 'uninstall')\n return\n }\n const taskId = data.task\n modalTaskRef.current = taskId\n applyQueue((prev) => [...prev, { id: taskId, kind: 'uninstall', target: name, desc, repo, status: 'pending', progress: 0, lines: [], needsRestart: true }])\n // 摘要条常驻顶部(含实时进度),明细面板保持折叠,想看时再点开\n pollQueue()\n } catch (err) {\n // 网络异常:附上底层原因,避免只剩一句笼统的「卸载失败」\n const aborted = (err as { name?: string } | null)?.name === 'AbortError'\n const reason = aborted\n ? t('requestTimeout')\n : err instanceof Error && err.message ? err.message : String(err ?? '')\n onError(reason ? `${t('uninstallFail')} — ${reason}` : t('uninstallFail'), repo, 'uninstall')\n } finally {\n window.clearTimeout(timeout)\n submittingRef.current.delete(name)\n setSubmitting(false)\n }\n }\n\n /** 弹窗动作:直接卸载(目录插件入口)。与安装同一队列机制,弹窗内实时显示进度。 */\n const uninstallNow = async (p: HubPlugin) => {\n const name = installedName(p)\n if (!name) return\n await enqueueUninstall(name, p.source?.repo ?? null, p.description)\n }\n\n /** 已安装视图动作:按已安装项卸载(覆盖目录外自定义安装,无目录数据也能卸)。 */\n const uninstallItem = async (item: InstalledItem) => {\n await enqueueUninstall(item.name, item.repo, item.plugin?.description)\n }\n\n /** 取消任务:排队中立即出队,执行中终止子进程;先标记「正在取消」短暂过渡后再移除。 */\n const cancelTask = async (id: number) => {\n if (modalTaskRef.current === id) modalTaskRef.current = null\n // 乐观标记「正在取消」,给用户一个可见反馈,而不是瞬间消失\n applyQueue((prev) => prev.map((q) => (q.id === id ? { ...q, status: 'cancelling' as const } : q)))\n try {\n await fetch('/dsh-plugin-hub/cancel', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n })\n } catch { /* 服务端不可达:仍按取消处理,稍后移除 */ }\n // 短暂展示「正在取消」后移除;队列清空则停止轮询\n window.setTimeout(() => {\n applyQueue((prev) => prev.filter((x) => x.id !== id))\n maybeStopPoll()\n }, 700)\n }\n\n /** 打开新弹窗前清空任务匹配:避免旧任务 id 误匹配到新弹窗。 */\n const clearModalTask = () => { modalTaskRef.current = null }\n\n // 弹窗对应任务:优先当前弹窗发起任务,其次按目标匹配(重新打开弹窗 / 目标已在队列时也能展示实时进度)\n // 目录插件按 source.repo 匹配;命令行安装(custom)按归一化后的仓库身份/包名匹配;\n // 全局 npm 安装按包列表身份(空格拼接)匹配;\n // 排除 cancelling:取消中的任务不再关联到弹窗,弹窗回到「确认」态可重新操作\n const installModalTarget = installPlugin?.source?.repo\n ?? (installCustomTarget ? repoFromInstallTarget(installCustomTarget) : null)\n ?? installGlobalTarget ?? null\n const installModalTask = (installPlugin || installCustomTarget || installGlobalTarget)\n ? (queue.find((q) => q.id === modalTaskRef.current && q.kind === 'install' && q.status !== 'cancelling')\n ?? queue.find((q) => q.kind === 'install' && q.target === installModalTarget && q.status !== 'cancelling')\n ?? null)\n : null\n const uninstallModalTask = (uninstallPlugin || uninstallName)\n ? (queue.find((q) => q.id === modalTaskRef.current && q.status !== 'cancelling')\n ?? queue.find((q) => q.kind === 'uninstall' && q.target === (uninstallName ?? installedName(uninstallPlugin!) ?? '') && q.status !== 'cancelling')\n ?? null)\n : null\n\n return {\n queue,\n pendingRestarts,\n installModalTask,\n uninstallModalTask,\n submitting,\n installNow,\n installCustom,\n installGlobalNpm,\n uninstallNow,\n uninstallItem,\n cancelTask,\n clearModalTask,\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Inline SVG icons used across the client. Icons inherit currentColor so\n * they adapt to themes and disabled states automatically.\n */\nimport { createElement as h } from 'react'\nimport headerStyles from '../../styles/Header.module.css'\nimport modalStyles from '../../styles/Modal.module.css'\n\n/** 弹窗右上角关闭按钮图标:内联 SVG 十字(stroke 继承 currentColor),随按钮禁用态一起变淡。 */\nexport function CloseIcon() {\n return h('svg', {\n className: modalStyles.modalCloseIcon,\n viewBox: '0 0 16 16',\n width: 14,\n height: 14,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M3 3l10 10M13 3L3 13',\n stroke: 'currentColor',\n strokeWidth: 1.6,\n strokeLinecap: 'round',\n }))\n}\n\n/** 来源链接图标:链节(stroke 继承 currentColor),弹窗里官网收录地址旁提示「可点击跳转」。 */\nexport function LinkIcon() {\n return h('svg', {\n className: modalStyles.linkIcon,\n viewBox: '0 0 24 24',\n width: 13,\n height: 13,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71',\n stroke: 'currentColor',\n strokeWidth: 1.8,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',\n stroke: 'currentColor',\n strokeWidth: 1.8,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }))\n}\n\n/** 帮助图标:圆圈 + 问号(stroke 继承 currentColor),自定义安装卡片标题旁的「帮助」按钮用。 */\nexport function HelpIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 13,\n height: 13,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('circle', {\n cx: 8, cy: 8, r: 6.3,\n stroke: 'currentColor', strokeWidth: 1.4,\n }),\n h('path', {\n d: 'M6.3 6.5a1.9 1.9 0 1 1 2.7 1.7c-.7.3-1 .8-1 1.4',\n stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round',\n }),\n h('circle', { cx: 8, cy: 11.6, r: 0.95, fill: 'currentColor' }),\n )\n}\n\n/** 品牌 logo 图标:蓝紫渐变圆角方块 + 白色拼图块(2x2 错落),标题左侧的品牌标识。 */\nexport function LogoIcon() {\n return h('svg', {\n className: headerStyles.logoIcon,\n viewBox: '0 0 24 24',\n width: 20,\n height: 20,\n 'aria-hidden': 'true',\n },\n h('defs', null,\n h('linearGradient', { id: 'dshLogoGrad', x1: '0', y1: '0', x2: '1', y2: '1' },\n h('stop', { offset: '0%', stopColor: '#4f46e5' }),\n h('stop', { offset: '100%', stopColor: '#7c3aed' }),\n ),\n ),\n h('rect', { x: 1, y: 1, width: 22, height: 22, rx: 6, fill: 'url(#dshLogoGrad)' }),\n h('rect', { x: 5.5, y: 5.5, width: 5.5, height: 5.5, rx: 1.5, fill: '#ffffff' }),\n h('rect', { x: 13, y: 5.5, width: 5.5, height: 5.5, rx: 1.5, fill: '#ffffff', opacity: 0.55 }),\n h('rect', { x: 5.5, y: 13, width: 5.5, height: 5.5, rx: 1.5, fill: '#ffffff', opacity: 0.55 }),\n h('rect', { x: 13, y: 13, width: 5.5, height: 5.5, rx: 1.5, fill: '#ffffff' }),\n )\n}\n\n/** GitHub 图标:官方 GitHub Mark(octocat),fill 继承 currentColor,头部右上角源码链接用。 */\nexport function GitHubIcon() {\n return h('svg', {\n className: headerStyles.githubIcon,\n viewBox: '0 0 24 24',\n width: 18,\n height: 18,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12',\n }))\n}\n\n/** 复制图标:双层矩形(stroke 继承 currentColor),手动命令旁的复制按钮用。 */\nexport function CopyIcon() {\n return h('svg', {\n className: headerStyles.copyIcon,\n viewBox: '0 0 16 16',\n width: 12,\n height: 12,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('rect', {\n x: 5.5, y: 5.5, width: 7, height: 7, rx: 1.5,\n stroke: 'currentColor', strokeWidth: 1.4,\n }),\n h('path', {\n d: 'M10.5 5.5v-2a1.5 1.5 0 0 0-1.5-1.5H4.5A1.5 1.5 0 0 0 3 3.5v4A1.5 1.5 0 0 0 4.5 9h1',\n stroke: 'currentColor', strokeWidth: 1.4, strokeLinecap: 'round',\n }),\n )\n}\n\n/** 文件夹图标(Material folder):「在文件夹中显示」按钮用,fill 继承 currentColor。 */\nexport function FolderIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 13,\n height: 13,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z',\n }))\n}\n\n/** 下拉箭头图标:向下 V 形(stroke 继承 currentColor),下拉按钮触发器右侧提示可展开。 */\nexport function ChevronDownIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 12,\n height: 12,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M3.5 5.5L8 10l4.5-4.5',\n stroke: 'currentColor',\n strokeWidth: 1.6,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }))\n}\n\n/** 排序方向小箭头:正序(up) 朝上 / 倒序(down) 朝下,随 currentColor 着色,仅当前排序按钮显示 */\nexport function SortArrowIcon({ up }: { up: boolean }) {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 10,\n height: 10,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: up ? 'M4 9.5L8 5.5l4 4' : 'M4 6.5L8 10.5l4-4',\n stroke: 'currentColor',\n strokeWidth: 1.8,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n }))\n}\n\n/** 插件市场图标:店面货架(stroke 继承 currentColor),一级导航「插件市场」tab 用。 */\nexport function MarketIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M4 10L5.6 4.5h12.8L20 10',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M4 10a2.2 2.2 0 0 0 4.4 0 2.2 2.2 0 0 0 4.4 0 2.2 2.2 0 0 0 4.4 0',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M5 13v6.5A1.5 1.5 0 0 0 6.5 21h11a1.5 1.5 0 0 0 1.5-1.5V13',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 自定义安装图标:终端窗口 + 提示符(stroke 继承 currentColor),一级导航「自定义安装」tab 用。 */\nexport function TerminalIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('rect', {\n x: 3, y: 4.5, width: 18, height: 15, rx: 2.5,\n stroke: 'currentColor', strokeWidth: 1.8,\n }),\n h('path', {\n d: 'M6.8 9.2l3.4 2.8-3.4 2.8',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M12.5 14.8h4.5',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round',\n }),\n )\n}\n\n/** 已安装图标:插件包(圆角方盒 + 盒盖线)+ 对勾(stroke 继承 currentColor),一级导航「已安装」tab 用。 */\nexport function InstalledIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('rect', {\n x: 4.5, y: 6.5, width: 15, height: 13, rx: 2.5,\n stroke: 'currentColor', strokeWidth: 1.8,\n }),\n h('path', {\n d: 'M4.5 11h15',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round',\n }),\n h('path', {\n d: 'M9.2 15.2l2.1 2.1 3.6-4',\n stroke: 'currentColor', strokeWidth: 1.8, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 通知铃铛图标:实心铃铛(fill 继承 currentColor),采用 Material 官方 notifications 路径,一级导航通知中心入口用。 */\nexport function BellIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 15,\n height: 15,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z',\n }))\n}\n\n/** 设置图标:实心齿轮(fill 继承 currentColor),采用 Material 官方 settings 路径,齿形清晰、辨识度高。 */\nexport function SettingsIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 16,\n height: 16,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94L14.4 2.81c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41L9.25 5.35C8.66 5.59 8.12 5.92 7.63 6.29L5.24 5.33c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.22-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61L19.14 12.94zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z',\n }))\n}\n\n/** 更新与通道图标:循环同步箭头(fill 继承 currentColor),采用 Material 官方 sync 路径,设置左侧导航「更新与通道」用。 */\nexport function UpdatesIcon() {\n return h('svg', {\n viewBox: '0 0 24 24',\n width: 15,\n height: 15,\n fill: 'currentColor',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z',\n }))\n}\n\n/** 安全与信任图标:盾牌 + 对勾(stroke 继承 currentColor),设置左侧导航「安全与信任」用。 */\nexport function SecurityIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 15,\n height: 15,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M8 1.8L13.8 3.8v4.3c0 3.5-2.2 6.3-5.8 7.6-3.6-1.3-5.8-4.1-5.8-7.6V3.8L8 1.8z',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M5.6 8.1l1.7 1.7 3.2-3.4',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 诊断图标:心跳脉冲线(stroke 继承 currentColor),设置左侧导航「诊断」用。 */\nexport function DiagnosticsIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 15,\n height: 15,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M1.6 8h3l1.9-4.2 2.9 8.4 1.9-4.2h3.1',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 恢复默认图标:逆时针还原箭头(stroke 继承 currentColor),设置左侧导航「恢复默认」用。 */\nexport function ResetIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 15,\n height: 15,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M3 5.2A5.6 5.6 0 1 1 2.4 9.6',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M2.6 2.6v2.6h2.6',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }))\n}\n\n/** 确认弹窗图标类型:普通确认 = 问号;危险操作 = 垃圾桶 / 警告三角 / 还原箭头 */\nexport type ConfirmIconType = 'question' | 'trash' | 'warning' | 'reset'\n\n/** 确认弹窗图标:圆形徽标 + 白色图形 —— 普通确认(安装/更新/重启/忽略)蓝底白问号;\n * 危险操作(清空/删除/卸载/重置)红底白动作图形。居中放在弹窗标题下方,一眼区分确认类型。 */\nexport function ConfirmIcon({ type }: { type: ConfirmIconType }) {\n const danger = type !== 'question'\n const glyphs = type === 'trash'\n ? [\n h('path', {\n d: 'M4.5 6.5h15M9.5 6.5V4.8a1.3 1.3 0 0 1 1.3-1.3h2.4a1.3 1.3 0 0 1 1.3 1.3v1.7',\n stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M6.2 6.5l.7 12.2a1.5 1.5 0 0 0 1.5 1.3h7.2a1.5 1.5 0 0 0 1.5-1.3l.7-12.2',\n stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', { d: 'M10 10.2v6M14 10.2v6', stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round' }),\n ]\n : type === 'warning'\n ? [\n h('path', {\n d: 'M12 4.2l8.5 14.3a1 1 0 0 1-.87 1.5H4.37a1 1 0 0 1-.87-1.5L12 4.2z',\n stroke: '#ffffff', strokeWidth: 1.9, strokeLinejoin: 'round',\n }),\n h('path', { d: 'M12 9.6v4.5', stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round' }),\n h('circle', { cx: 12, cy: 16.7, r: 1.05, fill: '#ffffff' }),\n ]\n : type === 'reset'\n ? [\n h('path', { d: 'M4.5 7.8A8.4 8.4 0 1 1 3.6 14.4', stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round' }),\n h('path', { d: 'M3.9 3.9v3.9h3.9', stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round', strokeLinejoin: 'round' }),\n ]\n : [\n h('path', {\n d: 'M9.5 9.2a2.6 2.6 0 1 1 3.7 2.38c-.84.38-1.2.95-1.2 1.72',\n stroke: '#ffffff', strokeWidth: 1.9, strokeLinecap: 'round',\n }),\n h('circle', { cx: 12, cy: 16.4, r: 1.1, fill: '#ffffff' }),\n ]\n return h('div', {\n className: danger ? `${modalStyles.confirmIcon} ${modalStyles.confirmIconDanger}` : modalStyles.confirmIcon,\n 'aria-hidden': 'true',\n },\n h('svg', { viewBox: '0 0 24 24', width: 22, height: 22, fill: 'none' }, ...glyphs),\n )\n}\n\n/** 系统日志图标:文档纸 + 三行文字(stroke 继承 currentColor),设置左侧导航「系统日志」用。 */\nexport function LogsIcon() {\n return h('svg', {\n viewBox: '0 0 16 16',\n width: 15,\n height: 15,\n fill: 'none',\n 'aria-hidden': 'true',\n },\n h('path', {\n d: 'M4.2 1.8h4.8l2.8 2.8v9.6H4.2z',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M9 1.8v2.8h2.8',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round',\n }),\n h('path', {\n d: 'M5.6 9.2h4.8M5.6 11.2h4.8',\n stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round',\n }))\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Inline progress block shared by the install and uninstall dialogs:\n * a real percentage bar (server-estimated, client-polled). No live terminal\n * window — pnpm emits nothing during git clone/build, so a log pane would be\n * empty for most of the run; failures surface their full output in ErrorModal.\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { TaskState } from '../../types.ts'\n\nexport function ProgressView({ task }: { task: TaskState }) {\n return h('div', { className: styles.progress },\n h('div', { className: styles.progressHead },\n h('span', { className: styles.progressText }, `${Math.round(task.progress)}%`),\n ),\n h('div', { className: styles.progressTrack },\n h('div', {\n className: task.status === 'failed' ? `${styles.progressFill} ${styles.progressFillFail}` : styles.progressFill,\n style: { width: `${task.progress}%` },\n }),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Dialog layer for the Plugin Hub: the install-confirm dialog, the uninstall\n * dialog and the global toast. Both dialogs lock themselves while a mutation\n * is running, then switch to a result view with a single action — \"done\" for\n * the common case (the page refreshes on close so the change applies), or a\n * single \"restart now\" for the rare changes a refresh cannot pick up.\n */\nimport { createElement as h } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { EnvInfo, HubPlugin, TaskState, ToastState, Translate } from '../../types.ts'\nimport { CloseIcon, ConfirmIcon, CopyIcon, LinkIcon } from '../ui/icons.tsx'\nimport { ProgressView } from './ProgressView.tsx'\nimport { installCommandOf } from '../../logic/install-command.ts'\nimport { pluginDetailUrl, pluginIssueUrl, pluginSiteUrl } from '../../logic/urls.ts'\nimport { classifyFailure, missingRegistryPackageOf, npmTooLowVersion, pnpmPolicyHintOf, pnpmPolicyHintParams, unreachableTargetOf, registryHostOf } from '../../logic/failures.ts'\n\n/** 完成结果视图:绿色对勾 + 标题/描述;\n * 终态只有两种:\n * - needsRestart=true(刷新解决不了:热挂载失败 / 非 dsh 插件 / 更新)→ 仅一个「立即重启」\n * 按钮(重启会中断进行中的任务,故仍需用户确认),关闭即放弃;\n * - 其余(含 needsReload=true 的「已热挂载、仅剩客户端 UI」)→ 仅「完成」按钮:关闭结果弹窗时\n * 上层自动刷新页面让插件生效,不再给「稍后/立即刷新」手动选择。 */\nfunction ResultView({\n title, desc, t, restarting, needsRestart, needsReload, onRestart, onClose,\n}: {\n title: string\n desc: string\n t: Translate\n restarting: boolean\n needsRestart: boolean\n /** 仅刷新页面即生效(插件已热挂载):给一句自动刷新说明,按钮仍是「完成」 */\n needsReload?: boolean\n onRestart: () => void\n onClose: () => void\n}) {\n return h('div', { className: styles.result },\n h('div', { className: styles.resultCheck },\n h('svg', {\n className: styles.resultCheckIcon,\n viewBox: '0 0 16 16',\n width: 20,\n height: 20,\n fill: 'none',\n 'aria-hidden': 'true',\n }, h('path', {\n d: 'M2.5 8.5l3.5 3.5 7.5-7.5',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n })),\n ),\n h('div', { className: styles.resultTitle }, title),\n desc ? h('div', { className: styles.resultDesc }, desc) : null,\n needsRestart\n ? h('div', null, [\n h('div', { className: styles.resultRestarting }, restarting ? t('restarting') : t('restartHint')),\n h('div', { className: styles.modalActions },\n h('button', { className: styles.restartNowWarning, onClick: onRestart, disabled: restarting },\n restarting ? t('restarting') : t('restartNow')),\n ),\n ])\n : h('div', null, [\n needsReload ? h('div', { className: styles.resultRestarting }, t('reloadHint')) : null,\n h('div', { className: styles.modalActions },\n h('button', { className: styles.restartNow, onClick: onClose }, t('done'))),\n ]),\n )\n}\n\nexport interface InstallModalProps {\n /** 目录插件(有完整元数据);命令行安装(custom)传 null 走 customTarget 模式 */\n plugin: HubPlugin | null\n /** 命令行安装目标(无目录元数据):提供时按裸目标展示确认/进度/结果,命令条显示 pnpm add <target> */\n customTarget?: string\n /** 全局 npm 安装(官方 README 的 `npm install -g <pkgs>`):提供时按包列表展示确认/进度/结果,\n * 命令条显示 npm install -g <pkgs> —— 装的是系统级 CLI 工具,不进插件列表、无需重启 */\n globalNpm?: string[]\n done: boolean\n task: TaskState | null\n t: Translate\n langPath: string\n restarting: boolean\n /** 已安装插件的覆盖更新(走同一条 add 命令原位重装,文案区分安装/更新) */\n update: boolean\n /** 仅命令行插件(webInstallable=false):不提供一键安装,只展示命令供复制到 dsh 终端 */\n cliOnly: boolean\n /** 安装请求在途(fetch 等待响应):此时任务尚未入队,需禁用确认按钮防止二次点击 */\n submitting: boolean\n /** 完成结果是否需重启才生效:true → 仅给「立即重启」;false → 仅「完成」(关闭即自动刷新) */\n needsRestart: boolean\n /** 完成结果是否只需刷新页面即生效(插件已热挂载):true → 结果视图显示自动刷新说明 */\n needsReload: boolean\n onClose: () => void\n onCopy: () => void\n onInstall: () => void\n onRestart: () => void\n}\n\n/**\n * 信任确认弹窗:安装进入后台队列后弹窗仍可关闭(任务继续),\n * 只在本任务执行中展示实时进度;完成后切换为结果视图,与卸载一致。\n * 目录插件与命令行安装(customTarget 模式)共用同一套确认/进度/结果流程。\n */\nexport function InstallModal(props: InstallModalProps) {\n const { plugin, customTarget, globalNpm, done, task, t, langPath, restarting, submitting, update, cliOnly, needsRestart, needsReload, onClose, onCopy, onInstall, onRestart } = props\n const busy = submitting || (task !== null && (task.status === 'pending' || task.status === 'running'))\n // 进行中标题带上插件名(中文「XX 插件安装中」;英文状态词在前更自然),并用状态色区分;\n // 命令行安装无插件元数据 → 直接用输入的目标展示;全局 npm 安装 → 包列表空格拼接\n const name = customTarget ?? (globalNpm !== undefined && globalNpm.length > 0 ? globalNpm.join(' ') : undefined) ?? plugin?.displayName ?? plugin?.slug ?? ''\n const busyTitle = (label: string) => langPath === 'zh/' ? `${name} 插件${label}` : `${label} ${name}`\n const title = busy\n ? task && task.status === 'pending'\n ? busyTitle(update ? t('queuedUpdateTitle') : t('queuedTitle'))\n : busyTitle(update ? t('updating') : t('installing'))\n : done\n ? update ? t('updateResultTitle') : t('installResultTitle')\n : update ? t('confirmUpdateTitle') : t('confirmTitle')\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: styles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', {\n className: busy\n ? `${styles.modalTitle} ${task && task.status === 'pending' ? styles.modalTitleQueued : styles.modalTitleBusy}`\n : styles.modalTitle,\n }, title),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: () => onClose(),\n }, h(CloseIcon)),\n ),\n done\n // 安装完成:结果视图(成功即生效,仅「完成」关闭);更新时标题/描述区分语义\n ? h(ResultView, {\n title: update ? t('updateResultTitle') : t('installResultTitle'),\n desc: update ? t('updateResultDesc') : t('installResultDesc'),\n t,\n restarting,\n needsRestart,\n needsReload,\n onRestart,\n onClose,\n })\n // 确认/进行中:来源行 + 安装命令 + 实时进度 + 操作按钮\n : h('div', { className: styles.modalBody },\n // 安装/更新确认态:品牌蓝问号图标,一眼识别这是确认询问\n !busy ? h('div', { className: styles.confirmIconWrap },\n h(ConfirmIcon, { type: 'question' }),\n ) : null,\n h('div', { className: styles.trustHint }, t('confirmDesc')),\n h('div', { className: styles.modalRow },\n h('span', { className: styles.modalLabel }, t('confirmPlugin')),\n h('span', { className: styles.modalValue, title: name }, name),\n ),\n plugin?.source?.repo ? h('div', { className: styles.modalRow },\n h('span', { className: styles.modalLabel }, t('confirmSource')),\n // 来源仓库:可点击跳转官网收录详情页(新窗口打开)\n h('a', {\n className: styles.modalLink,\n href: pluginDetailUrl(plugin, langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: plugin.source.repo,\n }, h(LinkIcon), plugin.source.repo),\n ) : null,\n // 手动命令条:整条点击即复制,右侧再放一个显式复制按钮;\n // 命令行安装(无目录数据)直接展示 pnpm add <target>;全局 npm 安装展示 npm install -g <pkgs>\n h('div', {\n className: styles.modalCmd,\n onClick: onCopy,\n title: t('copyInstallCommand'),\n role: 'button',\n tabIndex: 0,\n },\n h('span', { className: styles.modalCmdText },\n globalNpm !== undefined && globalNpm.length > 0\n ? `npm install -g ${globalNpm.join(' ')}`\n : customTarget ? `pnpm add ${customTarget}` : installCommandOf(plugin!)),\n h('span', { className: styles.modalCmdCopy }, h(CopyIcon), t('copyCmdLabel')),\n ),\n // 全局 npm 安装说明:装的是系统级 CLI 工具,不进插件列表、无需重启宿主\n globalNpm !== undefined && globalNpm.length > 0\n ? h('div', { className: styles.cliOnlyHint }, t('globalNpmHint'))\n : null,\n // AI 识别可能需要命令行辅助的插件(webInstallable=false):提示但不拦截,仍允许尝试一键安装\n cliOnly ? h('div', { className: styles.cliOnlyHint }, t('cliOnlyHint')) : null,\n task && task.status === 'pending' ? h('div', { className: styles.queuedHint }, t('queuedHint')) : null,\n task ? h(ProgressView, { task }) : null,\n // 安装失败:引导用户复制上方命令到 dsh 终端手动安装(如 node-pty 等原生依赖构建脚本需人工放行)\n task && task.status === 'failed' ? h('div', { className: styles.failedCopyHint }, t('failedCopyHint')) : null,\n h('div', { className: styles.modalActions },\n h('button', {\n className: styles.modalCopy,\n disabled: busy,\n onClick: onCopy,\n }, t('copyInstallCommand')),\n h('button', {\n className: styles.modalInstall,\n disabled: busy,\n onClick: onInstall,\n }, busy\n ? (task && task.status === 'pending'\n ? (update ? t('queuedUpdateTitle') : t('queuedTitle'))\n : (update ? t('updating') : t('installing')))\n : (update ? t('updateNow') : t('installNow'))),\n ),\n ),\n ),\n )\n}\n\nexport interface UninstallModalProps {\n plugin: HubPlugin\n done: boolean\n task: TaskState | null\n t: Translate\n langPath: string\n restarting: boolean\n /** 卸载请求在途(fetch 等待响应):此时任务尚未入队,需禁用确认按钮防止二次点击 */\n submitting: boolean\n /** 完成结果是否需重启才生效:true(停用失败等刷新解决不了的场景)→ 仅给「立即重启」;\n * false(loader 已即时停用)→ 仅「完成」,关闭即自动刷新页面摘除插件面板 */\n needsRestart: boolean\n /** 卸载的插件带客户端 UI 且已即时停用:面板要刷新页面才摘除 → 结果视图给自动刷新说明 */\n needsReload?: boolean\n onClose: () => void\n onCancel: () => void\n onCopyCommand: () => void\n onConfirm: () => void\n onRestart: () => void\n}\n\n/** 卸载确认弹窗:确认/进行中(后台队列,可关闭);完成后切换为结果视图(成功即生效,仅「完成」关闭)。 */\nexport function UninstallModal(props: UninstallModalProps) {\n const { plugin, done, task, t, langPath, restarting, submitting, needsRestart, needsReload, onClose, onCancel, onCopyCommand, onConfirm, onRestart } = props\n const busy = submitting || (task !== null && (task.status === 'pending' || task.status === 'running'))\n // 进行中标题带上插件名,与安装弹窗一致,并用状态色区分\n const name = plugin.displayName ?? plugin.slug\n const busyTitle = (label: string) => langPath === 'zh/' ? `${name} 插件${label}` : `${label} ${name}`\n const title = busy\n ? task && task.status === 'pending' ? busyTitle(t('queuedUninstallTitle')) : busyTitle(t('uninstalling'))\n : done ? t('uninstallResultTitle') : t('uninstallTitle')\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: styles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', {\n className: busy\n // 注意 task 判空:submitting(请求在途)时任务尚未入队,task 为 null,不能直接解引用\n ? `${styles.modalTitle} ${task !== null && task.status === 'pending' ? styles.modalTitleQueued : styles.modalTitleBusy}`\n : styles.modalTitle,\n }, title),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: () => onClose(),\n }, h(CloseIcon)),\n ),\n done\n // 卸载完成:结果视图(成功即生效,仅「完成」关闭)\n ? h(ResultView, {\n title: t('uninstallResultTitle'),\n desc: t('uninstallResultDesc'),\n t,\n restarting,\n needsRestart,\n needsReload,\n onRestart,\n onClose,\n })\n // 确认/进行中:来源行 + 实时进度 + 操作按钮\n : h('div', { className: styles.modalBody },\n // 卸载确认态:红色垃圾桶图标,删除类危险操作\n !busy ? h('div', { className: styles.confirmIconWrap },\n h(ConfirmIcon, { type: 'trash' }),\n ) : null,\n h('div', { className: styles.modalDesc }, t('uninstallDesc')),\n h('div', { className: styles.modalRow },\n h('span', { className: styles.modalLabel }, t('confirmPlugin')),\n h('span', { className: styles.modalValue, title: plugin.displayName ?? plugin.slug },\n plugin.displayName ?? plugin.slug),\n ),\n // 显示仓库来源:github 用户名 + 仓库名,让用户确认卸载的是哪一个仓库\n plugin.source?.repo ? h('div', { className: styles.modalRow },\n h('span', { className: styles.modalLabel }, t('confirmSource')),\n // 来源仓库:可点击跳转官网收录详情页(新窗口打开)\n h('a', {\n className: styles.modalLink,\n href: pluginDetailUrl(plugin, langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: plugin.source.repo,\n }, h(LinkIcon), plugin.source.repo),\n ) : null,\n task && task.status === 'pending' ? h('div', { className: styles.queuedHint }, t('queuedHint')) : null,\n task ? h(ProgressView, { task }) : null,\n h('div', { className: styles.modalActions },\n // 复制卸载命令:万一直接卸载失败,可去终端手动执行\n h('button', {\n className: styles.modalCopy,\n disabled: busy,\n onClick: onCopyCommand,\n }, t('copyUninstallCommand')),\n // 确认框语义:取消动作需明确指向「卸载」,避免歧义\n h('button', {\n className: styles.modalCancel,\n onClick: onCancel,\n }, t('cancelUninstall')),\n h('button', {\n className: styles.uninstallConfirm,\n disabled: busy,\n onClick: onConfirm,\n }, busy ? (task && task.status === 'pending' ? t('queuedUninstallTitle') : t('uninstalling')) : t('uninstallConfirm')),\n ),\n ),\n ),\n )\n}\n\n/** 预填插件仓库的 GitHub Issue 链接:标题带插件名,正文附完整错误信息,方便用户一键反馈。 */\n/** 安装/卸载失败弹窗:布局与失败记录一致(类型徽标 + 仓库超链接 + 隐蔽复制按钮),报错完整展示,底部一键提交 Issue。 */\nexport function ErrorModal({ message, repo, kind, command, attempts, t, env, onCopy, onClose, onRunDiagnostics }: {\n message: string\n repo: string | null\n kind: 'install' | 'uninstall'\n command?: string\n /** 尝试过的安装方式(npm 反查 + 实际执行命令):issue 预填一并贴给作者,便于反推正确的 npm 包名 */\n attempts?: string[]\n t: Translate\n env: EnvInfo | null\n onCopy: (text: string) => void\n onClose: () => void\n /** 网络不通时的「去系统诊断」直达按钮:跳到设置 → 系统诊断跑连通性检测(由宿主提供) */\n onRunDiagnostics?: () => void\n}) {\n // 失败归类:当前安装通道(npm/git)装不上 = 插件分发/依赖的问题,一律引导提 Issue\n const failureKind = classifyFailure(message)\n // 服务端 [npm-too-low] 标记里带的本机 npm 版本(无标记为 null,提示文案降级为「怀疑」)\n const npmVersion = npmTooLowVersion(message)\n // 复制完整错误:实际执行/尝试过的安装命令(如有)+ 完整错误正文。\n // 只复制 message 会丢上下文 —— 命令行安装输入的目标、执行过的命令都在 command/attempts 里,\n // 光拷一句「unsupported install target」出去没人看得懂\n const copyText = [\n ...(command ? [command] : []),\n ...(attempts ?? []),\n message,\n ].join('\\n')\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: styles.errorModal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n // 标题按操作类型明确区分:安装失败 / 卸载失败\n h('div', { className: styles.errorTitle }, kind === 'install' ? t('errorTitleInstall') : t('errorTitleUninstall')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n // 与失败记录一致的布局:类型徽标 + 仓库超链接 + 顶部隐蔽复制按钮\n h('div', { className: styles.failRow },\n h('div', { className: styles.failHead },\n h('span', {\n className: kind === 'install' ? styles.failKindInstall : styles.failKindUninstall,\n }, kind === 'install' ? t('install') : t('uninstall')),\n // 仓库地址(用户名/仓库)统一显示为可点击超链接,跳转到官网详情页(含插件收录信息),而非直接跳 GitHub\n repo ? h('a', {\n className: styles.failRepo,\n href: pluginSiteUrl(repo),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: repo,\n }, repo) : null,\n // 复制按钮放最上面、浅灰隐蔽;报错正文不允许鼠标选择复制,只能点这里\n h('button', { className: styles.errorCopySoft, onClick: () => onCopy(copyText) }, t('errorCopy')),\n ),\n // 报错信息完整展示(可滚动),比失败记录的预览看得更多\n h('pre', { className: styles.errorBox }, message),\n // npm 内部崩溃(edgesOut)+ 本机 npm 版本过低:npm 自身已知缺陷,不是插件问题 ——\n // 直接给升级指引,不引导提 Issue(提了也是 npm 的问题,插件作者无法修复)\n failureKind === 'npmTooOld'\n ? h('div', { className: styles.failPrepareHint },\n t(npmVersion ? 'failNpmTooLowV' : 'failNpmTooLow', npmVersion ? { v: npmVersion } : undefined))\n : failureKind === 'dshMissing'\n // 找不到 dsh 命令(Win「不是内部或外部命令」/ POSIX「command not found」/ spawn ENOENT):\n // 本机 DeepSeek Harness 未正确安装或 dsh 不在 PATH,不是插件问题 —— 直接给环境修复指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failDshMissingHint'))\n : failureKind === 'gitMissing'\n // 找不到 git 命令(Win「'git' is not recognized」/ POSIX「git: command not found」/ spawn ENOENT):\n // 本机 Git 未安装或不在 PATH,不是插件问题 —— 直接给环境修复指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failGitMissingHint'))\n : failureKind === 'pnpmMissing'\n // 找到了 dsh 但缺 pnpm(dsh 用它管理 profile 插件;dsh 报 pnpm not found on PATH):\n // 本机缺 pnpm,不是插件问题 —— 给安装指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failPnpmMissingHint'))\n : failureKind === 'npmMissing'\n // 全局 npm 安装通道 spawn 的 npm 找不到(Win「'npm' is not recognized」/ POSIX\n // 「npm: command not found」/ spawn ENOENT):本机 npm 未安装或不在 PATH —— 给安装指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failNpmMissingHint'))\n : failureKind === 'pnpmWorkspace'\n // pnpm 拒绝把依赖装到 workspace 根目录(ERR_PNPM_ADDING_TO_ROOT):宿主在 profile 目录\n // 调 pnpm add 时未声明在根操作,任何插件都会失败,不是插件问题 ——\n // 给 .npmrc 豁免指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failPnpmWorkspaceHint'))\n : failureKind === 'pnpmStore'\n // pnpm 存在但 store 大版本不匹配(ERR_PNPM_UNEXPECTED_STORE):profile 目录的依赖是\n // 另一大版本 pnpm 装的,当前 pnpm 不认,任何插件装进该 profile 都会失败 ——\n // 给清理重建指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failPnpmStoreHint'))\n : failureKind === 'pnpmPolicy'\n // pnpm 11 供应链安全策略拦截(minimumReleaseAge 拒收发布太新的包 / untrusted origin):\n // 本机 pnpm 策略不放行,装任何「刚发布/新来源」插件都撞墙 —— 给豁免指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t(pnpmPolicyHintOf(message), pnpmPolicyHintParams(message)))\n : failureKind === 'pnpmUnusedPatch'\n // profile 里留着指向旧版本 dsh-plugin 的补丁声明(ERR_PNPM_UNUSED_PATCH):pnpm 发现\n // 补丁没被用上就中止整次安装,任何插件都装不进来 —— 给删除条目的指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failPnpmUnusedPatchHint'))\n : failureKind === 'pnpmMissingDep'\n // profile 里留着指向 registry 上不存在(404)的包的依赖:pnpm 连得上 registry,\n // 是被明确告知包不存在 —— 该 profile 的任何安装都会先卡在这条依赖上,与本次要装的\n // 插件无关 → 点名缺失的包 + 删除条目指引,不引导提 Issue\n ? h('div', null, [\n (() => {\n const pkg = missingRegistryPackageOf(message)\n return pkg ? h('div', { className: styles.failNetworkTarget }, t('failPnpmMissingDepTarget', { pkg })) : null\n })(),\n h('div', { className: styles.failPrepareHint }, t('failPnpmMissingDepHint')),\n ])\n : failureKind === 'fileLocked'\n // profile 里的文件被其他进程占用(Windows os error 32):pnpm 无法替换被占用的文件,\n // 通常是宿主或杀毒软件持有句柄 —— 给退出宿主的指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failFileLockedHint'))\n : failureKind === 'accessDenied'\n // profile 里的文件被系统拒绝写入(Windows os error 5「拒绝访问」/ EPERM / EACCES):\n // 占用、只读属性、目录 ACL 或杀软拦截 —— 同样给退出宿主/检查权限的指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failAccessDeniedHint'))\n : failureKind === 'fsUnavailable'\n // 本机磁盘写不进去(ENOSPC / EROFS / EMFILE 及 Windows os error 112、19):\n // 空间不足、盘只读、句柄耗尽,任何插件都装不进来 —— 按子场景给指引,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failFsUnavailableHint'))\n : failureKind === 'originRejected'\n // 请求来源没通过本地 hub 服务的校验(服务端 403 untrusted origin):请求根本没进\n // 安装流程,与插件无关 —— 引导从本机地址重新打开市场,不引导提 Issue\n ? h('div', { className: styles.failPrepareHint }, t('failOriginRejectedHint', { profile: env?.profile ?? '<profile>' }))\n : failureKind === 'network'\n // 安装前预检 / 安装日志里的连接失败([network] / git fetch 超时 / DNS / TLS):\n // 是本机网络不通或代理有问题,不是插件问题 —— 提示检查网络 + 直达「系统诊断」,\n // 不引导提 Issue\n ? h('div', null, [\n // 「无法访问 …」醒目行:精准告诉用户具体哪个地址连不上(消息里取不到地址就跳过这行)\n (() => { const target = unreachableTargetOf(message); return target ? h('div', { className: styles.failNetworkTarget }, t('failNetworkTarget', { url: target })) : null })(),\n // registry 被指向内网/自定义源(tarball 从非官方源下载失败):直接给出换源指引,\n // 否则用户外网是通的会困惑「为什么连不上」\n (() => { const host = registryHostOf(message); return host ? h('div', { className: styles.failPrepareHint }, t('failNetworkRegistryHint', { host })) : null })(),\n h('div', { className: styles.failPrepareHint }, t('failNetworkHint')),\n onRunDiagnostics ? h('button', {\n className: styles.failDiagBtn,\n onClick: onRunDiagnostics,\n }, t('failNetworkRunDiag')) : null,\n ])\n : failureKind === 'pluginPrepare' || failureKind === 'pnpmIgnoredBuild'\n ? h('div', null, [\n // [packaging](预检/装后校验拦截:git 分发缺产物)与\n // prepare 构建脚本实际执行失败 / 原生依赖构建被 pnpm 拦截:都是插件打包分发问题 —— 先说明原因,按钮在下方提交\n h('div', { className: styles.failPrepareHint }, failureKind === 'pnpmIgnoredBuild'\n ? t('failIgnoredBuild')\n : /\\[packaging\\]/i.test(message) ? t('failPackagingHint') : t('failPrepareHint')),\n repo ? h('a', {\n className: styles.failBigIssue,\n href: pluginIssueUrl(repo, message, env, command, attempts),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('failIssueHint'),\n }, t('failIssueBig')) : null,\n ])\n : repo ? h('a', {\n className: styles.failBigIssue,\n href: pluginIssueUrl(repo, message, env, command, attempts),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('failIssueHint'),\n }, t('failIssueBig')) : null,\n ),\n h('div', { className: styles.modalActions },\n h('button', { className: styles.restartLater, onClick: onClose }, t('errorClose')),\n ),\n ),\n ),\n )\n}\n\n/** 全局反馈 Toast:复制成功(反色)/ 安装完成(反色)/ 安装失败(红色)/ 卸载结果 */\nexport function Toast({ toast, t }: { toast: ToastState; t: Translate }) {\n const text = toast.kind === 'copied' ? t('toastCopied')\n : toast.kind === 'errCopied' ? t('errCopied')\n : toast.kind === 'done' ? t('installDone')\n : toast.kind === 'fail' ? t('installFail')\n : toast.kind === 'removed' ? t('uninstallDone')\n : toast.kind === 'revealFail' ? t('openFolderFail')\n : toast.kind === 'restartDesktop' ? t('toastRestartDesktop')\n : toast.kind === 'installedLive' ? t('toastInstalledLive')\n : toast.kind === 'installedReload' ? t('toastInstalledReload')\n : t('uninstallFail')\n const fail = toast.kind === 'fail' || toast.kind === 'removeFail' || toast.kind === 'revealFail' || toast.kind === 'restartDesktop'\n return h('div', {\n key: toast.id,\n className: fail ? `${styles.toast} ${styles.toastFail}` : styles.toast,\n }, text)\n}\n\n/** 待重启确认弹窗:已安装列表行内「重启」按钮点击后弹出,\n * 与通知中心待重启条目同一交互(红色警告说明 + 单个「立即重启」),\n * 避免行内按钮误触直接触发宿主重启。 */\nexport function RestartConfirmModal({ t, restarting, onClose, onRestartNow }: {\n t: Translate\n restarting: boolean\n onClose: () => void\n onRestartNow: () => void\n}) {\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) onClose() },\n },\n h('div', { className: styles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('sectionPendingRestart')),\n h('button', {\n className: styles.modalClose,\n type: 'button',\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n // 重启确认:红色警告三角 —— 重启会中断正在进行的安装/卸载任务,风险提示\n h('div', { className: styles.confirmIconWrap },\n h(ConfirmIcon, { type: 'warning' }),\n ),\n h('div', { className: styles.failPrepareHint }, t('restartHint')),\n h('div', { className: styles.modalActions },\n // 关闭本弹窗即视为「稍后」,只保留单个「立即重启」\n h('button', {\n className: styles.restartNowWarning,\n type: 'button',\n disabled: restarting,\n onClick: onRestartNow,\n }, restarting ? t('restarting') : t('restartNow')),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 轻量 Markdown 渲染器:仅用于 Hub 自我更新的变更记录(Worker 下发的 notes)。\n *\n * 内容由插件作者自己编写、属可信内容,但渲染端仍先整体 HTML 转义,再按\n * Markdown 语法输出结构,杜绝任何未转义的原始 HTML 注入;链接仅放行 http(s)。\n *\n * 支持:标题(#~####)、有序/无序列表、代码块(```)、行内代码、加粗、斜体、\n * 链接、图片(![alt](url),如反馈群二维码)、引用(>)、段落;其余语法一律按\n * 纯文本处理,不引入外部依赖。图片仅放行 http(s),限定最大宽度不撑破弹窗。\n */\n\n/** HTML 转义:所有文本先进这里,再进入结构变换,保证输出里没有未转义的用户输入。 */\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\n}\n\n/** 行内变换:链接 / 加粗 / 斜体 / 行内代码(代码先占位保护,最后还原)。 */\nfunction inline(s: string): string {\n let out = escapeHtml(s)\n // 行内代码先占位:避免其中的 * [ ] 被后续链接/加粗/斜体规则破坏\n const codeSpans: string[] = []\n out = out.replace(/`([^`]+)`/g, (_m, code) => {\n codeSpans.push(String(code))\n return `\\u0000${codeSpans.length - 1}\\u0000`\n })\n // 图片 ![alt](url):仅放行 http(s),用于展示反馈群二维码等;limited by CSS\n // 文件名为 dsh-plugin-user-group-qr 前缀的视为用户反馈群二维码,固定 100×100 不撑破弹窗。\n out = out.replace(/!\\[([^\\]]*)\\]\\(([^)\\s]+)\\)/g, (m, alt, url) => {\n const src = String(url)\n if (!/^https?:\\/\\//i.test(src) || /[\\u0000]/.test(src)) return m\n if (/\\/dsh-plugin-user-group-qr[^/]*$/i.test(src)) {\n return `<img src=\"${src}\" alt=\"${String(alt)}\" width=\"100\" height=\"100\" loading=\"lazy\">`\n }\n return `<img src=\"${src}\" alt=\"${String(alt)}\" loading=\"lazy\">`\n })\n // 链接 [text](url):仅放行 http(s),新窗口打开\n out = out.replace(/\\[([^\\]]+)\\]\\(([^)\\s]+)\\)/g, (m, text, url) =>\n /^https?:\\/\\//i.test(String(url)) && !/[\\u0000]/.test(String(url))\n ? `<a href=\"${String(url)}\" target=\"_blank\" rel=\"noopener noreferrer\">${String(text)}</a>`\n : m,\n )\n out = out.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>')\n out = out.replace(/(^|[^*])\\*([^*]+)\\*/g, '$1<em>$2</em>')\n return out.replace(/\\u0000(\\d+)\\u0000/g, (_m, idx) => `<code>${codeSpans[Number(idx)]}</code>`)\n}\n\n/** 把变更记录 Markdown 渲染为安全的 HTML 字符串(由弹窗用 dangerouslySetInnerHTML 注入)。 */\nexport function renderMarkdown(md: string): string {\n const lines = md.replace(/\\r\\n?/g, '\\n').split('\\n')\n const blocks: string[] = []\n let i = 0\n while (i < lines.length) {\n const line = lines[i]\n // 围栏代码块\n if (/^\\s*```/.test(line)) {\n const buf: string[] = []\n i++\n while (i < lines.length && !/^\\s*```/.test(lines[i])) {\n buf.push(lines[i])\n i++\n }\n i++ // 跳过闭合围栏\n blocks.push(`<pre><code>${escapeHtml(buf.join('\\n'))}</code></pre>`)\n continue\n }\n // 空行:段落分隔符\n if (line.trim() === '') {\n i++\n continue\n }\n // 标题:# 到 #### 映射为 h2~h5(弹窗标题用 modalTitle,不与其冲突)\n const heading = line.match(/^(#{1,4})\\s+(.*)/)\n if (heading) {\n const level = heading[1].length + 1\n blocks.push(`<h${level}>${inline(heading[2])}</h${level}>`)\n i++\n continue\n }\n // 有序 / 无序列表(连续收集为一个列表块)\n if (/^\\s*[-*+]\\s+/.test(line) || /^\\s*\\d+[.)]\\s+/.test(line)) {\n const ordered = /^\\s*\\d+[.)]\\s+/.test(line)\n const items: string[] = []\n while (i < lines.length && (/^\\s*[-*+]\\s+/.test(lines[i]) || /^\\s*\\d+[.)]\\s+/.test(lines[i]))) {\n items.push(`<li>${inline(lines[i].replace(/^\\s*[-*+]|\\s*\\d+[.)]\\s*/, '').trim())}</li>`)\n i++\n }\n blocks.push(`<${ordered ? 'ol' : 'ul'}>${items.join('')}</${ordered ? 'ol' : 'ul'}>`)\n continue\n }\n // 引用\n if (/^\\s*>\\s?/.test(line)) {\n const buf: string[] = []\n while (i < lines.length && /^\\s*>\\s?/.test(lines[i])) {\n buf.push(inline(lines[i].replace(/^\\s*>\\s?/, '')))\n i++\n }\n blocks.push(`<blockquote>${buf.join('<br>')}</blockquote>`)\n continue\n }\n // 普通段落:收集连续非空、非特殊开头的行\n const buf: string[] = []\n while (\n i < lines.length\n && lines[i].trim() !== ''\n && !/^\\s*```/.test(lines[i])\n && !/^#{1,4}\\s+/.test(lines[i])\n && !/^\\s*([-*+]|\\d+[.)])\\s+/.test(lines[i])\n ) {\n buf.push(inline(lines[i]))\n i++\n }\n blocks.push(`<p>${buf.join('<br>')}</p>`)\n }\n return blocks.join('')\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 头部「关注我们」弹窗:介绍 DSH Plugin Hub 的功能定位 + 用户反馈群二维码。\n * 内容以 Markdown 形式由 dsh-update Worker 的 /about 接口下发(key = hub:about),\n * 客户端按接口返回渲染,不内置固定文案。\n * 图片(反馈群二维码)经 renderMarkdown 的 ![](url) 语法嵌入,居中、最大高度受控。\n */\nimport { createElement as h, useMemo } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { HubAboutInfo } from '../../types.ts'\nimport type { LocaleId, Translate } from '../../types.ts'\nimport { renderMarkdown } from '../../logic/renderMarkdown.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\n\n/**\n * 反馈群二维码 URL 恒定(每次换码都是同名覆盖,文件名不变),浏览器 / CDN 会按\n * URL 缓存旧图。这里在渲染前给二维码 URL 实时拼一个新的时间戳,强制每次打开\n * 「关注我们」都回源拉取最新图片,无需重新构建 / 部署接口中心。\n * 匹配规则与 renderMarkdown 的二维码识别保持一致(dsh-plugin-user-group-qr 前缀)。\n */\nfunction bustQrCache(md: string, ts: number): string {\n return md.replace(\n /(!\\[[^\\]]*\\]\\()([^)\\s]*dsh-plugin-user-group-qr[^)\\s]*)/g,\n (_m, pre, url) => `${pre}${String(url).split('?')[0]}?v=${ts}`,\n )\n}\n\nexport function AboutModal({ info, lang, t, onClose }: {\n info: HubAboutInfo | null\n lang: LocaleId\n t: Translate\n onClose: () => void\n}) {\n // 内容:字符串直接使用;{zh,en} 对象按界面语言取,缺哪种补哪种,全缺则展示兜底文案。\n // Worker 未推送(info 为 null / content 为空)时弹窗仍能打开,显示「暂未发布」而非报错。\n const contentRaw = info\n ? typeof info.content === 'string'\n ? info.content\n : info.content && typeof info.content === 'object'\n ? lang === 'en'\n ? (info.content.en ?? info.content.zh ?? '')\n : (info.content.zh ?? info.content.en ?? '')\n : ''\n : ''\n // 每次打开弹窗(组件重新挂载)生成一个时间戳,用于二维码破缓存;\n // 同一次打开内保持稳定,避免父组件重渲染导致图片被反复重载。\n const qrTs = useMemo(() => Date.now(), [])\n const contentHtml = contentRaw.trim() ? renderMarkdown(bustQrCache(contentRaw, qrTs)) : null\n // 更新时间:ISO 字符串转本地可读格式;非法值静默隐藏\n let updated: string | null = null\n if (info?.updatedAt) {\n const d = new Date(info.updatedAt)\n if (!Number.isNaN(d.getTime())) {\n updated = d.toLocaleString(lang === 'en' ? 'en-US' : 'zh-CN')\n }\n }\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.modal} ${styles.aboutModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('aboutTitle')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: () => onClose(),\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalDesc }, t('aboutDesc')),\n contentHtml\n ? h('div', {\n className: styles.aboutContent,\n dangerouslySetInnerHTML: { __html: contentHtml },\n })\n : h('div', { className: styles.aboutContent }, t('aboutEmpty')),\n updated\n ? h('div', { className: styles.aboutMeta }, `${t('aboutUpdated')} ${updated}`)\n : null,\n h('div', { className: styles.modalActions },\n h('button', { className: styles.modalInstall, onClick: onClose }, t('doneBtn')),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Hub 版本信息 / 自我更新说明弹窗:\n * - 有更新(hasUpdate=true):标题「有新版本」,展示新版本号、发布时间与 Worker 下发的\n * Markdown 变更记录(renderMarkdown 渲染,双语言按界面语言取 {zh,en} 对象),\n * 按钮「稍后再说 / 直接更新」,确认后进入安装弹窗执行覆盖重装。\n * - 无更新(hasUpdate=false):标题「当前版本」,展示当前版本信息与更新记录,已是最新。\n * 点击头部版本号(或「可更新」徽标)打开 —— 无论有无更新都能看到更新内容。\n */\nimport { createElement as h } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { HubUpdateInfo } from '../../types.ts'\nimport type { LocaleId, Translate } from '../../types.ts'\nimport { renderMarkdown } from '../../logic/renderMarkdown.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\n\nexport function HubUpdateModal({ info, lang, t, hasUpdate, onProceed, onClose }: {\n info: HubUpdateInfo\n lang: LocaleId\n t: Translate\n /** 是否有可用更新:有则显示「直接更新」,无则显示「已是最新」 */\n hasUpdate: boolean\n /** 点「直接更新」:关闭本弹窗,进入安装弹窗的更新流程 */\n onProceed: () => void\n onClose: () => void\n}) {\n // 变更记录:字符串直接使用;{zh,en} 对象按界面语言取,缺哪种补哪种,全缺则不出记录区\n const notesRaw = typeof info.notes === 'string'\n ? info.notes\n : info.notes && typeof info.notes === 'object'\n ? lang === 'en'\n ? (info.notes.en ?? info.notes.zh ?? '')\n : (info.notes.zh ?? info.notes.en ?? '')\n : ''\n const notesHtml = notesRaw.trim() ? renderMarkdown(notesRaw) : null\n // 发布时间:ISO 字符串转本地可读格式;非法值静默隐藏\n let published: string | null = null\n if (info.publishedAt) {\n const d = new Date(info.publishedAt)\n if (!Number.isNaN(d.getTime())) {\n published = d.toLocaleString(lang === 'en' ? 'en-US' : 'zh-CN')\n }\n }\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.modal} ${styles.hubUpdateModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t(hasUpdate ? 'hubUpdateTitle' : 'hubCurrentTitle')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: () => onClose(),\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalDesc },\n t(hasUpdate ? 'hubUpdateDesc' : 'hubCurrentDesc', { version: info.version })),\n h('div', { className: styles.hubUpdateMeta },\n h('span', { className: styles.hubUpdateMetaItem }, `${t('version')} ${info.version}`),\n published\n ? h('span', { className: styles.hubUpdateMetaItem }, `${t('hubUpdatePublished')} ${published}`)\n : null,\n ),\n notesHtml\n ? h('div', {\n className: styles.hubUpdateNotes,\n dangerouslySetInnerHTML: { __html: notesHtml },\n })\n : null,\n h('div', { className: styles.modalActions },\n hasUpdate\n ? [\n h('button', { className: styles.restartLater, onClick: onClose }, t('hubUpdateLater')),\n h('button', { className: styles.modalInstall, onClick: onProceed }, t('updateNow')),\n ]\n : h('button', { className: styles.modalInstall, onClick: onClose }, t('hubUpToDate')),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Presentation formatters shared across the catalog list and the cards.\n */\nimport type { Translate } from '../types.ts'\n\n/** 星数/分支数的紧凑展示:<1k 原样;千级 1.2k;十万级取整。 */\nexport function fmtStars(count?: number): string {\n if (!count || count <= 0) return '0'\n if (count < 1000) return String(count)\n const k = count / 1000\n return `${k >= 100 ? Math.round(k) : k.toFixed(1).replace(/\\.0$/, '')}k`\n}\n\n/** 相对时间:今天 / N 天前 / N 个月前 / N 年前。 */\nexport function relTime(iso: string | undefined, t: Translate): string {\n if (!iso) return ''\n const days = Math.floor((Date.now() - new Date(iso).getTime()) / 86400000)\n if (days <= 0) return t('today')\n if (days < 30) return t('daysAgo', { days })\n if (days < 365) return t('monthsAgo', { months: Math.floor(days / 30) })\n return t('yearsAgo', { years: Math.floor(days / 365) })\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Installed-plugin detail dialog: opens from the Installed view (row click\n * or the detail button) and shows everything we know about an installed\n * entry — the catalog metadata (category, catalog entry, stars/forks,\n * latest version) merged with the host runtime facts (install path, installed\n * version, install time, last update). Update / uninstall actions are\n * offered from here too, mirroring the row actions.\n */\nimport { createElement as h } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { LocaleId, Translate } from '../../types.ts'\nimport type { InstalledItem } from '../../logic/installed.ts'\nimport { CATEGORY_LABELS, categoryLabel } from '../../logic/constants.ts'\nimport { pluginDetailUrl } from '../../logic/urls.ts'\nimport { fmtStars } from '../../logic/format.ts'\nimport { CloseIcon, CopyIcon, FolderIcon, LinkIcon } from '../ui/icons.tsx'\n\n/** ISO 安装时间 → 本地可读;非法值返回 null(行内不显示)。 */\nfunction fmtDate(iso: string | null, lang: LocaleId): string | null {\n if (!iso) return null\n const d = new Date(iso)\n return Number.isNaN(d.getTime()) ? null : d.toLocaleString(lang === 'en' ? 'en-US' : 'zh-CN')\n}\n\nexport function InstalledDetailModal({ item, t, lang, langPath, onClose, onUpdate, onUninstall, onCopyPath, onReveal }: {\n item: InstalledItem\n t: Translate\n lang: LocaleId\n langPath: string\n onClose: () => void\n /** 更新:仅目录插件且有更新时展示(点击后关闭详情、走安装确认弹窗的更新语义) */\n onUpdate: (item: InstalledItem) => void\n onUninstall: (item: InstalledItem) => void\n /** 复制安装路径:成功提示由调用方 toast 反馈 */\n onCopyPath: (path: string) => void\n /** 在系统文件管理器里定位安装目录(服务端 spawn open):失败提示由调用方 toast 反馈 */\n onReveal: (item: InstalledItem) => void\n}) {\n const p = item.plugin\n const name = p?.displayName ?? item.name\n const installedAt = fmtDate(item.installedAt, lang)\n // 最后更新:目录插件取仓库最近提交时间(live 数据);自定义安装无目录信号\n const lastUpdated = fmtDate(p?.dates?.repoUpdatedAt ?? null, lang)\n const hasUpdate = item.hasUpdate && item.plugin !== null\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.modal} ${styles.detailModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, name),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('confirmCancel'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n // 描述:目录收录的插件简介\n p?.description ? h('div', { className: styles.modalDesc }, p.description) : null,\n // 有可用更新:醒目提示条(版本号存在时给出升级路径)\n hasUpdate\n ? h('div', { className: styles.detailUpdateHint },\n item.installedVersion && item.catalogVersion\n ? t('versionUpHint', { from: item.installedVersion, to: item.catalogVersion })\n : t('updateAvailableHint'))\n : null,\n // 详情信息网格:分类 / 状态 / 版本 / 收录入口 / 包名 / 统计 / 安装路径 / 安装时间 / 最后更新\n h('div', { className: styles.detailGrid },\n p?.category\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('detailCategory')),\n h('span', { className: styles.detailValue },\n categoryLabel(CATEGORY_LABELS, p.category, lang)))\n : null,\n h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('statusLabel')),\n h('span', { className: styles.detailValue },\n h('span', {\n className: item.loaded ? styles.detailStatusRunning : styles.detailStatusPending,\n 'aria-hidden': 'true',\n }),\n h('span', { className: styles.detailStatusText },\n item.loaded ? t('statusRunning') : t('statusPending')))),\n item.installedVersion\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('installedVersionLabel')),\n h('span', { className: styles.detailValue },\n h('span', { className: styles.detailMono }, item.installedVersion),\n // 目录有更新版本且与已装版本不同:给出「→ 目录最新」\n item.catalogVersion && item.catalogVersion !== item.installedVersion\n ? h('span', { className: styles.detailArrow },\n '\\u2192', h('span', { className: styles.detailMono }, item.catalogVersion),\n h('span', { className: styles.detailDim }, t('catalogLatest')))\n : null))\n : null,\n // 收录入口:仓库名 → 官网详情页(目录插件跳收录页;自定义安装回退到 GitHub 仓库)\n item.repo\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('detailCatalog')),\n h('a', {\n className: styles.detailLink,\n href: p ? pluginDetailUrl(p, langPath) : `https://github.com/${item.repo}`,\n target: '_blank',\n rel: 'noopener noreferrer',\n title: item.repo,\n }, h(LinkIcon), item.repo))\n : null,\n item.plugin?.source?.npmPackage\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('packageName')),\n h('span', { className: styles.detailValue },\n h('span', { className: styles.detailMono }, item.plugin.source.npmPackage)))\n : null,\n p?.stats && (p.stats.stargazers_count ?? 0) > 0\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('detailStats')),\n h('span', { className: styles.detailValue },\n h('span', { className: styles.detailStars }, '\\u2605 ', fmtStars(p.stats.stargazers_count)),\n h('span', { className: styles.detailDim }, t('fork'), ' ', fmtStars(p.stats.forks_count))))\n : null,\n item.installPath\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('installPath')),\n h('div', { className: styles.detailPath },\n // 整条点击复制路径(等宽文本省略号)\n h('span', {\n className: styles.detailPathText,\n title: t('copyPath'),\n onClick: () => onCopyPath(item.installPath!),\n }, item.installPath),\n h('span', { className: styles.detailPathActions },\n h('button', {\n className: styles.detailPathBtn,\n type: 'button',\n title: t('copyPath'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onCopyPath(item.installPath!)\n },\n }, h(CopyIcon)),\n h('button', {\n className: styles.detailPathBtn,\n type: 'button',\n title: t('openFolder'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onReveal(item)\n },\n }, h(FolderIcon)),\n )))\n : null,\n installedAt\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('installedAtLabel')),\n h('span', { className: styles.detailValue }, installedAt))\n : null,\n // 最后更新时间:与安装时间成对展示(目录插件才有)\n lastUpdated\n ? h('div', { className: styles.detailRow },\n h('span', { className: styles.detailLabel }, t('lastUpdatedLabel')),\n h('span', { className: styles.detailValue }, lastUpdated))\n : null,\n ),\n ),\n // 底部操作:完成 / 更新 / 卸载(复制路径与打开文件夹已在路径行内)\n h('div', { className: styles.modalActions },\n h('button', {\n className: styles.restartLater,\n onClick: onClose,\n }, t('done')),\n hasUpdate\n ? h('button', {\n className: styles.modalInstall,\n onClick: () => onUpdate(item),\n }, t('update'))\n : null,\n h('button', {\n className: styles.uninstallConfirm,\n onClick: () => onUninstall(item),\n }, t('uninstall')),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Generic confirm dialog — the single entry point for every \"are you sure?\"\n * question in the app. Rule: any question must be a modal dialog, never an\n * in-button double-click.\n *\n * The icon in the middle tells the type at a glance: a blue question mark\n * for routine confirmations (install / update / restart / ignore), a red\n * action glyph for destructive ones (clear / delete / uninstall / reset).\n */\nimport { createElement as h } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { Translate } from '../../types.ts'\nimport { CloseIcon, ConfirmIcon, type ConfirmIconType } from '../ui/icons.tsx'\n\n/** 通用确认弹窗:标题 + 类型图标 + 描述 + 取消/确认按钮。\n * type='question' → 蓝问号 + 品牌蓝确认按钮;危险类型 → 红图形 + 红色确认按钮。 */\nexport function ConfirmDialog({ type, title, desc, confirmLabel, cancelLabel, busy, busyLabel, t, onConfirm, onCancel }: {\n type: ConfirmIconType\n title: string\n desc?: string\n confirmLabel: string\n cancelLabel?: string\n /** 确认动作在途:禁用按钮防止二次点击 */\n busy?: boolean\n /** 在途时确认按钮文案(如「清空中…」);缺省沿用 confirmLabel */\n busyLabel?: string\n t: Translate\n onConfirm: () => void\n onCancel: () => void\n}) {\n const danger = type !== 'question'\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) onCancel() },\n },\n h('div', { className: styles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, title),\n h('button', {\n className: styles.modalClose,\n type: 'button',\n 'aria-label': t('errorClose'),\n onClick: onCancel,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n h('div', { className: styles.confirmIconWrap },\n h(ConfirmIcon, { type }),\n ),\n desc ? h('div', { className: styles.modalDesc }, desc) : null,\n h('div', { className: styles.modalActions },\n h('button', {\n className: styles.restartLater,\n type: 'button',\n disabled: busy,\n onClick: onCancel,\n }, cancelLabel ?? t('confirmCancel')),\n h('button', {\n className: danger ? styles.dangerConfirm : styles.confirmPrimary,\n type: 'button',\n disabled: busy,\n onClick: onConfirm,\n }, busy && busyLabel ? busyLabel : confirmLabel),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Notification-center dialog: a persistent log of every settled install /\n * remove task — successes and failures alike.\n *\n * Records are written to localStorage at settle time (see logic/failures.ts),\n * so a result is never lost even when the dialog was dismissed or the user\n * was away. Each entry carries a circular status badge (green check for\n * success, red cross for failure) with white glyph and message text;\n * failures keep their copy / fix / file-an-issue actions. Opened from the\n * header entry button (after the Settings tab).\n */\nimport { createElement as h, useState } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport type { EnvInfo, Translate } from '../../types.ts'\nimport type { NotificationRecord } from '../../logic/failures.ts'\nimport { classifyFailure, missingRegistryPackageOf, npmTooLowVersion, pnpmPolicyHintOf, pnpmPolicyHintParams, unreachableTargetOf, registryHostOf } from '../../logic/failures.ts'\nimport type { PendingRestart, QueueTask } from '../../hooks/useTaskQueue.ts'\nimport { pluginIssueUrl, pluginSiteUrl } from '../../logic/urls.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\nimport { ConfirmDialog } from './ConfirmDialog.tsx'\n\n/** 记录时间完整展示:YYYY-MM-DD HH:mm:ss(每条通知都带精确到秒的时间戳)。 */\nfunction fmtTime(at: number): string {\n const d = new Date(at)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`\n}\n\n/** 圆形状态徽标内的白色图形:成功为对勾、失败为叉。 */\nfunction BadgeGlyph({ ok }: { ok: boolean }) {\n return h('svg', {\n className: styles.noticeBadgeIcon,\n viewBox: '0 0 16 16',\n width: 12,\n height: 12,\n fill: 'none',\n 'aria-hidden': 'true',\n }, ok\n ? h('path', {\n d: 'M3 8.5l3.5 3.5 6.5-6.5',\n stroke: '#ffffff',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n })\n : h('path', {\n d: 'M4 4l8 8M12 4L4 12',\n stroke: '#ffffff',\n strokeWidth: 2,\n strokeLinecap: 'round',\n }))\n}\n\nexport function NotificationsModal({ records, tasks, pendingRestarts, t, env, onClose, onCopy, onClear, onRemove, onUpdate, onIgnoreUpdate, cancelTask, restarting, onRestart, onRunDiagnostics, resolveRepo }: {\n records: NotificationRecord[]\n /** 进行中的安装/卸载任务(实时进度,与队列弹窗同一数据源) */\n tasks: QueueTask[]\n /** 待重启插件:装完没重启的常驻提醒 */\n pendingRestarts: PendingRestart[]\n t: Translate\n env: EnvInfo | null\n onClose: () => void\n onCopy: (text: string) => void\n onClear: () => void\n /** 删除单条通知记录 */\n onRemove: (id: number) => void\n /** 更新提醒通知点击:跳去该插件的更新确认弹窗 */\n onUpdate: (repo: string) => void\n /** 更新提醒「忽略本次更新」:先弹确认,确认后本次版本不再提醒,下一个新版本再通知 */\n onIgnoreUpdate: (repo: string, version?: string) => void\n cancelTask: (id: number) => void\n restarting: boolean\n onRestart: () => void\n /** 网络不通时的「去系统诊断」直达按钮:跳到设置 → 系统诊断跑连通性检测(由宿主提供) */\n onRunDiagnostics?: () => void\n /** 失败记录 repo 反查:npm 包名(历史记录存的是裸包名)反查成 owner/repo 再显示/提 Issue;\n * 查不到返回 null,按钮与仓库链接一并隐藏(防提到错误仓库)。不传则按记录原样展示。 */\n resolveRepo?: (repo: string) => string | null\n}) {\n // 危险操作确认:清空全部 / 删除单条都必须先弹独立确认框(垃圾桶图标),禁止按钮内直接生效\n const [confirmClear, setConfirmClear] = useState(false)\n const [confirmRemoveId, setConfirmRemoveId] = useState<number | null>(null)\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: styles.errorModal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('notifications')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n h('div', { className: styles.errorHint }, t('notificationsDesc')),\n // 进行中的安装/卸载任务实时进度也进通知中心:与队列弹窗同一套行结构,\n // 关掉任务弹窗后仍可在这里盯着进度;待重启插件可在此直接触发重启\n (tasks.length > 0 || pendingRestarts.length > 0)\n ? h('div', null, [\n pendingRestarts.length > 0\n ? h('div', { className: styles.queueSection },\n h('div', { className: styles.queueSectionTitle }, t('sectionPendingRestart')),\n pendingRestarts.map((p) => h('div', { key: `restart-${p.target}`, className: styles.queueRow },\n h('div', { className: styles.queueRowHead },\n h('span', {\n className: `${styles.failKind} ${p.kind === 'uninstall' ? styles.failKindUninstall : styles.failKindInstall}`,\n }, p.kind === 'uninstall' ? t('uninstall') : t('install')),\n h('span', { className: styles.queueRowTarget, title: p.target }, p.target),\n ),\n p.desc ? h('div', { className: styles.queueRowDesc, title: p.desc }, p.desc) : null,\n h('div', { className: styles.queueRowBody },\n h('span', { className: styles.pendingRowStatus },\n p.kind === 'uninstall' ? t('restartPendingHintUninstall') : t('restartPendingHint')),\n h('span', { className: styles.pendingRowActions },\n // 兜底项:刷新解决不了(热挂载失败 / 非 dsh 插件 / 更新)才登记待重启;\n // 关闭本弹窗即视为「稍后」,只在真正需要时给单个「立即重启」\n h('button', {\n className: styles.restartNow,\n disabled: restarting,\n onClick: onRestart,\n }, restarting ? t('restarting') : t('restartNow')),\n ),\n ),\n )),\n )\n : null,\n tasks.length > 0\n ? h('div', { className: styles.queueSection },\n h('div', { className: styles.queueSectionTitle }, t('sectionInProgress')),\n tasks.map((q) => h('div', { key: q.id, className: styles.queueRow },\n h('div', { className: styles.queueRowHead },\n h('span', {\n className: `${styles.failKind} ${q.kind === 'install' ? styles.failKindInstall : styles.failKindUninstall}`,\n }, q.kind === 'install' ? t('install') : t('uninstall')),\n h('span', { className: styles.queueRowTarget, title: q.target }, q.target),\n h('button', {\n className: styles.stripCancel,\n disabled: q.status === 'cancelling',\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); cancelTask(q.id) },\n }, t('cancelTask')),\n ),\n q.desc ? h('div', { className: styles.queueRowDesc, title: q.desc }, q.desc) : null,\n h('div', { className: styles.queueRowBody },\n h('span', { className: styles.queueRowStatus },\n q.status === 'running'\n ? (q.kind === 'install' ? t('installing') : t('uninstalling'))\n : q.status === 'cancelling'\n ? t('cancelling')\n : (q.kind === 'install' ? t('queuedTitle') : t('queuedUninstallTitle'))),\n h('div', { className: `${styles.progressTrack} ${styles.queueRowTrack}` },\n h('div', { className: styles.progressFill, style: { width: `${q.progress}%` } }),\n ),\n h('span', { className: styles.queueRowPct }, `${q.progress}%`),\n ),\n )),\n )\n : null,\n ])\n : null,\n records.length === 0\n ? h('div', { className: styles.failEmpty }, t('notificationsEmpty'))\n : h('div', { className: styles.noticeList },\n records.map((r) => {\n const isUpdate = r.kind === 'update'\n // 展示用仓库:历史记录存的可能是裸 npm 包名,反查成 owner/repo 才显示/提 Issue;\n // 查不到为空 → 仓库链接与提 Issue 按钮都不渲染\n const shownRepo = resolveRepo ? (resolveRepo(r.repo) ?? '') : r.repo\n return h('div', {\n key: r.id,\n // 更新提醒:整行可点击直达更新确认弹窗;install/uninstall 记录维持原交互\n className: r.ok\n ? `${styles.noticeRow} ${styles.noticeRowOk}${isUpdate ? ` ${styles.noticeRowUpdate}` : ''}`\n : styles.noticeRow,\n ...(isUpdate ? { onClick: () => onUpdate(r.repo), title: t('updateNoticeGo') } : {}),\n },\n h('div', { className: styles.noticeRowMain },\n h('div', {\n className: r.ok ? styles.noticeBadgeOk : styles.noticeBadgeFail,\n }, h(BadgeGlyph, { ok: r.ok })),\n h('div', { className: styles.noticeMain },\n h('div', { className: styles.noticeHead },\n h('span', {\n className: r.ok ? styles.noticeTextOk : styles.noticeTextFail,\n }, r.ok\n ? (isUpdate\n ? t('updateNoticeTitle')\n : (r.action === 'update' ? t('updateDone') : (r.kind === 'install' ? t('installDone') : t('uninstallDone'))))\n : (r.action === 'update'\n ? t('errorTitleUpdate')\n : (r.kind === 'install' ? t('errorTitleInstall') : t('errorTitleUninstall')))),\n // 更新提醒:新版本号紧随标题展示;repo 为纯文本(整行点击即去更新,不跳官网外链)\n isUpdate && r.version\n ? h('span', { className: styles.noticeVersion, title: r.version }, `v${r.version}`)\n : null,\n r.repo\n ? (isUpdate\n ? h('span', { className: styles.failRepo, title: r.repo }, r.repo)\n : shownRepo\n ? h('a', {\n className: styles.failRepo,\n // 跳转到官网详情页(含插件收录信息),不在通知弹窗直接跳 GitHub\n href: pluginSiteUrl(shownRepo),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: shownRepo,\n }, shownRepo)\n // 反查不到仓库身份(如命令行安装的裸 npm 包名):回退显示记录里的原始值,\n // 保证通知永不只剩一句「安装/更新成功」没有名字 —— 只是不给官网外链(查不到不敢乱跳)\n : h('span', { className: styles.failRepo, title: r.repo }, r.repo))\n : null,\n !r.ok && h('button', {\n className: styles.failCopy,\n onClick: () => onCopy(r.message),\n }, t('failCopy')),\n // 成功通知:时间戳在行右侧,与图标/文字垂直居中,卡片保持单行内容\n r.ok\n ? h('span', {\n className: styles.noticeTime,\n title: new Date(r.at).toLocaleString(),\n }, fmtTime(r.at))\n : null,\n // 更新提醒:行尾「去更新」按钮直达更新确认弹窗(整行也可点击)\n isUpdate\n ? h('button', {\n className: styles.noticeUpdateGo,\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onUpdate(r.repo) },\n }, t('updateNoticeGo'))\n : null,\n // 更新提醒:「忽略本次更新」按钮 —— 先弹确认,确认后本次版本不再提醒\n isUpdate\n ? h('button', {\n className: styles.noticeIgnore,\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onIgnoreUpdate(r.repo, r.version) },\n }, t('ignoreUpdateRun'))\n : null,\n // 每条通知右侧的删除按钮:先弹确认框,确认后移除这一条\n h('button', {\n className: styles.noticeRemove,\n 'aria-label': t('removeNotification'),\n title: t('removeNotification'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); setConfirmRemoveId(r.id) },\n }, h(CloseIcon)),\n ),\n // 每条失败记录是一个独立卡片:头部(状态/仓库/时间/复制完整日志)→ 修复或提 Issue 动作。\n // 卡片不展示错误日志预览,完整日志靠「复制完整日志」按钮带走,避免每条卡片被日志撑高\n !r.ok && (() => {\n const kind = classifyFailure(r.message)\n if (kind === 'npmTooOld') {\n // npm 内部崩溃(edgesOut)+ 本机 npm 版本过低:npm 自身已知缺陷,不是插件问题 ——\n // 直接给升级指引,不引导提 Issue\n const v = npmTooLowVersion(r.message)\n return h('div', { className: styles.failPrepareHint },\n t(v ? 'failNpmTooLowV' : 'failNpmTooLow', v ? { v } : undefined))\n }\n if (kind === 'dshMissing') {\n // 找不到 dsh 命令(Win「不是内部或外部命令」/ POSIX「command not found」/ spawn ENOENT):\n // 本机 DeepSeek Harness 未正确安装或 dsh 不在 PATH,不是插件问题 —— 直接给环境修复指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failDshMissingHint'))\n }\n if (kind === 'gitMissing') {\n // 找不到 git 命令(Win「'git' is not recognized」/ POSIX「git: command not found」/ spawn ENOENT):\n // 本机 Git 未安装或不在 PATH,不是插件问题 —— 直接给环境修复指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failGitMissingHint'))\n }\n if (kind === 'pnpmMissing') {\n // 找到了 dsh 但缺 pnpm(dsh 用它管理 profile 插件;dsh 报 pnpm not found on PATH):\n // 本机缺 pnpm,不是插件问题 —— 给安装指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failPnpmMissingHint'))\n }\n if (kind === 'npmMissing') {\n // 全局 npm 安装通道 spawn 的 npm 找不到:本机 npm 未安装或不在 PATH ——\n // 给安装指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failNpmMissingHint'))\n }\n if (kind === 'pnpmWorkspace') {\n // pnpm 拒绝把依赖装到 workspace 根目录(ERR_PNPM_ADDING_TO_ROOT):宿主在 profile\n // 目录调 pnpm add 未声明在根操作,任何插件都会失败 ——\n // 给 .npmrc 豁免指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failPnpmWorkspaceHint'))\n }\n if (kind === 'pnpmStore') {\n // pnpm 存在但 store 大版本不匹配(ERR_PNPM_UNEXPECTED_STORE):profile 目录的依赖是\n // 另一大版本 pnpm 装的,当前 pnpm 不认,任何插件装进该 profile 都会失败 ——\n // 给清理重建指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failPnpmStoreHint'))\n }\n if (kind === 'pnpmPolicy') {\n // pnpm 11 供应链安全策略拦截(minimumReleaseAge 拒收发布太新的包 / untrusted origin):\n // 本机 pnpm 策略不放行,装任何「刚发布/新来源」插件都撞墙 —— 给豁免指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t(pnpmPolicyHintOf(r.message), pnpmPolicyHintParams(r.message)))\n }\n if (kind === 'pnpmUnusedPatch') {\n // profile 里留着指向旧版本 dsh-plugin 的补丁声明(ERR_PNPM_UNUSED_PATCH):pnpm\n // 发现补丁没被用上就中止安装,任何插件都装不进来 —— 不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failPnpmUnusedPatchHint'))\n }\n if (kind === 'pnpmMissingDep') {\n // profile 里留着指向 registry 上不存在(404)的包的依赖:pnpm 连得上 registry,\n // 是被明确告知包不存在 —— 该 profile 的任何安装都会先卡在这条依赖上,与本次要装的\n // 插件无关 → 点名缺失的包 + 删除条目指引,不引导提 Issue\n const pkg = missingRegistryPackageOf(r.message)\n return h('div', null, [\n pkg ? h('div', { className: styles.failNetworkTarget }, t('failPnpmMissingDepTarget', { pkg })) : null,\n h('div', { className: styles.failPrepareHint }, t('failPnpmMissingDepHint')),\n ])\n }\n if (kind === 'fileLocked') {\n // profile 里的文件被其他进程占用(Windows os error 32):通常是宿主或杀毒软件\n // 持有句柄 —— 给出完全退出宿主的指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failFileLockedHint'))\n }\n if (kind === 'accessDenied') {\n // profile 里的文件被系统拒绝写入(Windows os error 5「拒绝访问」/ EPERM / EACCES):\n // 占用、只读属性、目录 ACL 或杀软拦截 —— 给退出宿主 + 检查权限的指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failAccessDeniedHint'))\n }\n if (kind === 'fsUnavailable') {\n // 本机磁盘写不进去(ENOSPC / EROFS / EMFILE 及 Windows os error 112、19):\n // 空间不足、盘只读、句柄耗尽,任何插件都装不进来 —— 按子场景给指引,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failFsUnavailableHint'))\n }\n if (kind === 'originRejected') {\n // 请求来源没通过本地 hub 服务的校验(服务端 403 untrusted origin):请求根本没进\n // 安装流程,与插件无关 —— 引导从本机地址重新打开市场,不引导提 Issue\n return h('div', { className: styles.failPrepareHint }, t('failOriginRejectedHint', { profile: env?.profile ?? '<profile>' }))\n }\n if (kind === 'network') {\n // 安装前预检 / 安装日志里的连接失败([network] / git fetch 超时 / DNS / TLS):\n // 是本机网络不通或代理有问题,不是插件问题 —— 提示检查网络 + 直达「系统诊断」,\n // 不引导提 Issue\n return h('div', null, [\n // 「无法访问 …」醒目行:精准告诉用户具体哪个地址连不上(消息里取不到地址就跳过这行)\n (() => { const target = unreachableTargetOf(r.message); return target ? h('div', { className: styles.failNetworkTarget }, t('failNetworkTarget', { url: target })) : null })(),\n // registry 被指向内网/自定义源(tarball 从非官方源下载失败):直接给出换源指引,\n // 否则用户外网是通的会困惑「为什么连不上」\n (() => { const host = registryHostOf(r.message); return host ? h('div', { className: styles.failPrepareHint }, t('failNetworkRegistryHint', { host })) : null })(),\n h('div', { className: styles.failPrepareHint }, t('failNetworkHint')),\n onRunDiagnostics ? h('button', {\n className: styles.failDiagBtn,\n onClick: onRunDiagnostics,\n }, t('failNetworkRunDiag')) : null,\n ])\n }\n if (kind === 'pluginPrepare' || kind === 'pnpmIgnoredBuild') {\n // [packaging](预检/装后校验拦截:git 分发缺产物)与\n // prepare 构建脚本实际执行失败 / 原生依赖构建被 pnpm 拦截:都是插件打包分发问题 —— 先说明原因,按钮在下方提交\n return h('div', null, [\n h('div', { className: styles.failPrepareHint }, kind === 'pnpmIgnoredBuild'\n ? t('failIgnoredBuild')\n : /\\[packaging\\]/i.test(r.message) ? t('failPackagingHint') : t('failPrepareHint')),\n r.repo && shownRepo ? h('a', {\n className: styles.failBigIssue,\n href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('failIssueHint'),\n }, t('failIssueBig')) : null,\n ])\n }\n return r.repo && shownRepo ? h('a', {\n className: styles.failBigIssue,\n href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('failIssueHint'),\n }, t('failIssueBig')) : null\n })(),\n ),\n ),\n // 失败通知:时间戳保留独立底部行(右下角);成功通知已并入头部行右侧\n !r.ok\n ? h('div', { className: styles.noticeFoot },\n h('span', {\n className: styles.noticeTime,\n title: new Date(r.at).toLocaleString(),\n }, fmtTime(r.at)),\n )\n : null,\n )\n }),\n ),\n h('div', { className: styles.modalActions },\n records.length > 0 ? h('button', {\n className: styles.failClear,\n onClick: () => setConfirmClear(true),\n }, t('notificationsClear')) : null,\n h('button', { className: styles.restartNow, onClick: onClose }, t('errorClose')),\n ),\n ),\n ),\n // 清空全部通知确认弹窗:独立弹出框(垃圾桶图标,危险操作),确认后才真正清空\n confirmClear && h(ConfirmDialog, {\n type: 'trash',\n title: t('notificationsClearConfirmTitle'),\n desc: t('notificationsClearConfirmDesc'),\n confirmLabel: t('notificationsClear'),\n t,\n onConfirm: () => { setConfirmClear(false); onClear() },\n onCancel: () => setConfirmClear(false),\n }),\n // 删除单条通知确认弹窗:独立弹出框(垃圾桶图标),确认后才移除\n confirmRemoveId !== null && h(ConfirmDialog, {\n type: 'trash',\n title: t('removeNotificationConfirmTitle'),\n desc: t('removeNotificationConfirmDesc'),\n confirmLabel: t('removeNotification'),\n t,\n onConfirm: () => { onRemove(confirmRemoveId); setConfirmRemoveId(null) },\n onCancel: () => setConfirmRemoveId(null),\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Section header: brand title row (H1 + open-site button) + tagline, followed\n * by the purple ad banner that promotes the catalog stats.\n */\nimport { createElement as h, Fragment } from 'react'\nimport styles from '../../styles/Header.module.css'\nimport type { Translate } from '../../types.ts'\nimport { GITHUB_URL, PLUGIN_VERSION } from '../../logic/constants.ts'\nimport { siteUrl } from '../../logic/urls.ts'\nimport { GitHubIcon, LogoIcon } from '../ui/icons.tsx'\n\nexport function CatalogHeader({ t, langPath, statsTotal, statsVerified, onToggleLang, hubUpdate, onVersionClick, onAboutClick }: {\n t: Translate\n langPath: string\n statsTotal: number\n statsVerified: number\n onToggleLang: () => void\n /** Hub 自身是否有可用更新:有则版本号后紧跟红色「可更新」徽标(整体一个可点入口) */\n hubUpdate: boolean\n /** 点击版本号(含红色徽标,同一入口):无论有无更新都打开更新记录弹窗 */\n onVersionClick: () => void\n /** 点击「关注我们」:打开平台介绍 + 用户反馈群二维码弹窗 */\n onAboutClick: () => void\n}) {\n return h(Fragment, null,\n h('div', { className: styles.header },\n // 第一行:logo + 标题(官网链接)与 GitHub 源码图标同行,GitHub 顶到标题行末尾\n h('div', { className: styles.headerTitleRow },\n h('a', {\n className: styles.brandTitle,\n href: siteUrl(langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('openHint'),\n 'aria-label': t('openHint'),\n },\n h(LogoIcon),\n h('h1', { className: styles.title }, t('title')),\n ),\n // 版本号:紧跟标题「DSH Plugin Hub」之后,常驻可点入口(<a> 内不能嵌套按钮,故从官网链接里移出放在旁边)。\n // 点击打开更新记录弹窗 —— 有更新看新版本内容,无更新看当前版本内容。\n // 有更新时版本号后直接跟一个红色「可更新」徽标(同一按钮内,不分开成两个元素),静态显示不闪烁。\n h('button', {\n className: styles.versionBtn,\n type: 'button',\n onClick: onVersionClick,\n title: t(hubUpdate ? 'hubUpdateHint' : 'versionHint'),\n 'aria-label': t(hubUpdate ? 'hubUpdateHint' : 'versionHint'),\n },\n `v${PLUGIN_VERSION}`,\n hubUpdate && h('span', { className: styles.hubUpdateBadge }, t('update')),\n ),\n // 右侧控件组:语言切换 + GitHub 源码图标(独立链接,brandTitle 是官网 <a> 不能嵌套),\n // 一起 space-between 顶到标题行最右\n h('div', { className: styles.headerRight },\n // 语言切换:按钮文字始终显示「要切到的语言」,点击即切,无需图标\n h('button', {\n className: styles.langBtn,\n type: 'button',\n onClick: onToggleLang,\n title: t('toggleLangHint'),\n 'aria-label': t('toggleLangHint'),\n }, langPath === 'zh/' ? 'EN' : '中文'),\n // 「关注我们」:点击打开平台介绍 + 用户反馈群二维码弹窗\n h('button', {\n className: styles.aboutBtn,\n type: 'button',\n onClick: onAboutClick,\n title: t('aboutDesc'),\n 'aria-label': t('aboutTitle'),\n }, t('followUs')),\n // GitHub 源码图标:独立链接(brandTitle 是官网 <a> 不能嵌套),放在控件组最后\n h('a', {\n className: styles.githubLink,\n href: GITHUB_URL,\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('githubHint'),\n 'aria-label': t('githubHint'),\n }, h(GitHubIcon)),\n ),\n ),\n // 第二行:副标题仍是官网链接,点击跳 dsh-plugin.org\n h('a', {\n className: styles.taglineLink,\n href: siteUrl(langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: t('openHint'),\n },\n h('div', { className: styles.tagline }, t('tagline', { total: statsTotal, verified: statsVerified })),\n ),\n ),\n h('a', {\n className: styles.adBanner,\n href: siteUrl(langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n },\n h('span', { className: styles.adBadge }, t('adBadge')),\n h('span', { className: styles.adText }, t('ad', { total: statsTotal, verified: statsVerified })),\n h('span', { className: styles.adArrow }, '\\u2197')),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Category tabs: an \"all\" chip followed by one chip per catalog category.\n * The \"all\" chip carries the total plugin count; the per-category chips\n * carry no counts so their widths stay uniform.\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/Header.module.css'\nimport type { LocaleId } from '../../types.ts'\nimport { CATEGORY_ORDER, CATEGORY_SHORT_LABELS, categoryLabel } from '../../logic/constants.ts'\n\nexport function CategoryTabs({ category, setCategory, allLabel, totalCount, langKey }: {\n category: string\n setCategory: (value: string) => void\n allLabel: string\n totalCount: number\n langKey: LocaleId\n}) {\n return h('div', { className: styles.tabs },\n // 第一个按钮固定为「全部」:展示全部分类,直接显示插件总数;\n // 其余分类按钮不带数量,保持排版整齐\n h('button', {\n key: 'all',\n className: category === 'all' ? styles.tabActive : styles.tab,\n onClick: () => setCategory('all'),\n },\n allLabel,\n h('span', { className: styles.tabCount }, totalCount)),\n CATEGORY_ORDER.map((id) => h('button', {\n key: id,\n className: category === id ? styles.tabActive : styles.tab,\n onClick: () => setCategory(id),\n },\n categoryLabel(CATEGORY_SHORT_LABELS, id, langKey))),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Toolbar above the market list:\n * row 1 — full-width search input;\n * row 2 — result count on the left, sort segmented control on the right\n * (mirrors the Installed view: clicking the same sort toggles\n * ascending/descending, a new sort uses its default order; the active\n * button shows an up/down arrow for the current direction).\n */\nimport { createElement as h, Fragment } from 'react'\nimport type { FormEvent, ReactNode } from 'react'\nimport styles from '../../styles/Header.module.css'\nimport type { Translate } from '../../types.ts'\nimport { SORTS } from '../../logic/constants.ts'\nimport type { SortKey } from '../../logic/constants.ts'\nimport { SortArrowIcon } from '../ui/icons.tsx'\n\n/** 单选按钮组中的一个按钮(segmented control,与已安装视图排序按钮同款) */\nfunction SegBtn({ active, onClick, label, icon }: {\n active: boolean\n onClick: () => void\n label: string\n icon?: ReactNode\n}) {\n return h('button', {\n type: 'button',\n className: active ? `${styles.segBtn} ${styles.segBtnActive}` : styles.segBtn,\n 'aria-pressed': active,\n onClick,\n }, label, icon)\n}\n\nexport function CatalogControls({ query, setQuery, sort, sortDir, toggleSort, t, resultText }: {\n query: string\n setQuery: (value: string) => void\n sort: SortKey\n /** 当前排序方向:决定激活排序按钮上的箭头朝上(正序)/朝下(倒序) */\n sortDir: 'asc' | 'desc'\n toggleSort: (value: SortKey) => void\n t: Translate\n resultText: string | null\n}) {\n return h(Fragment, null,\n // 第一行:搜索框占满整行(搜插件名称、描述、标签)\n h('div', { className: styles.searchRow },\n h('input', {\n className: styles.search,\n type: 'search',\n placeholder: t('search'),\n value: query,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) =>\n setQuery((e.target as HTMLInputElement).value),\n }),\n ),\n // 第二行:左侧筛选结果数「结果 N 条插件」(数字等宽预留 5 位不跳动),\n // 右侧排序按钮组(与已安装视图同款 segmented control,激活按钮带正/倒序箭头)\n h('div', { className: styles.controls },\n resultText ? h('span', { className: styles.resultSeg },\n ...resultText.split(/(\\d+)/).map((part, i) =>\n /^\\d+$/.test(part)\n ? h('span', { key: i, className: styles.resultCount }, part)\n : part)) : null,\n h('div', { className: styles.sortGroup },\n h('span', { className: styles.segLabel }, t('sortByLabel')),\n h('div', { className: styles.segGroup, role: 'radiogroup', 'aria-label': t('sortAria') },\n SORTS.map((key) => SegBtn({\n active: sort === key,\n onClick: () => toggleSort(key),\n label: t(key),\n icon: sort === key ? h(SortArrowIcon, { up: sortDir === 'asc' }) : null,\n })),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Incremental list: renders only the first batch of a (potentially huge)\n * result set and appends the next batch whenever the end sentinel scrolls\n * into view, so the plugin market never mounts thousands of cards at once.\n * The items reference is the list identity — category / search / sort\n * changes produce a new array, which resets the window to the first batch.\n */\nimport { useEffect, useRef, useState } from 'react'\n\n/** 首批渲染条数 & 每次滚到底追加的增量(单卡约 80px 高,100 条已远超一屏) */\nconst PAGE_SIZE = 100\n/** 哨兵进入视口底部前 800px 就提前加载下一批,滚到底时无感知衔接 */\nconst PRELOAD_MARGIN = '800px 0px'\n\nexport function useIncrementalList<T>(items: T[]) {\n const [limit, setLimit] = useState(PAGE_SIZE)\n const sentinelRef = useRef<HTMLDivElement | null>(null)\n\n // 筛选/分类/排序变化 → items 引用变化 → 窗口重置回首批\n useEffect(() => {\n setLimit(PAGE_SIZE)\n }, [items])\n\n // 哨兵进入视口(含预加载区)→ 追加下一批;已全部渲染则不再观察\n useEffect(() => {\n const el = sentinelRef.current\n if (!el || limit >= items.length) return\n const io = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) setLimit((cur) => Math.min(cur + PAGE_SIZE, items.length))\n }\n }, { rootMargin: PRELOAD_MARGIN })\n io.observe(el)\n return () => io.disconnect()\n }, [items.length, limit])\n\n return {\n shown: items.slice(0, limit),\n hasMore: limit < items.length,\n sentinelRef,\n }\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * One plugin card in the catalog list: name/category/verified badge,\n * description + topics, star/fork/date stats, and the detail/install/\n * uninstall actions.\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/List.module.css'\nimport type { HubPlugin, LocaleId, Translate } from '../../types.ts'\nimport { CATEGORY_LABELS, categoryLabel } from '../../logic/constants.ts'\nimport { pluginDetailUrl } from '../../logic/urls.ts'\nimport { fmtStars, relTime } from '../../logic/format.ts'\n\nexport function PluginCard({ plugin: p, copied, installedName, installedVersion, hasUpdate, t, langKey, langPath, onInstall, onUninstall }: {\n plugin: HubPlugin\n copied: string | null\n installedName: (p: HubPlugin) => string | null\n /** 已安装版本号(安装时从目录信号记录;无 release 的仓库为空,无版本号可展示) */\n installedVersion: (p: HubPlugin) => string | null\n /** 已安装且目录有更新(有版本比版本、无版本比仓库更新时间) */\n hasUpdate: (p: HubPlugin) => boolean\n t: Translate\n langKey: LocaleId\n langPath: string\n /** 第二个参数标记「更新」(已安装目标的覆盖安装):按钮/弹窗据此走更新语义 */\n onInstall: (p: HubPlugin, opts?: { update?: boolean }) => void\n onUninstall: (p: HubPlugin) => void\n}) {\n const repo = p.source?.repo ?? ''\n const isCopied = copied === repo\n const pkg = installedName(p)\n const isInstalled = pkg !== null\n const update = hasUpdate(p)\n // 版本号展示:已安装 → 当前已装版本(最能反映用户状态);未安装 → 目录最新版本\n const versionShown = isInstalled ? installedVersion(p) : p.version\n\n return h('div', { className: styles.card },\n h('div', { className: styles.cardMain },\n h('div', { className: styles.cardHead },\n h('div', { className: styles.cardTitle, title: p.description ?? '' }, p.displayName ?? p.slug),\n // 版本号紧跟插件名称:有版本才显示(无 release 的仓库不展示版本号)\n versionShown ? h('span', { className: styles.versionBadge, title: t('version') }, versionShown) : null,\n // 已安装且有更新:醒目提示(有 release 比版本号、无 release 比仓库最近更新时间)\n update ? h('span', { className: styles.updateBadge, title: t('updateAvailableHint') }, t('updateAvailable')) : null,\n p.category ? h('span', { className: styles.categoryBadge }, categoryLabel(CATEGORY_LABELS, p.category, langKey)) : null,\n p.compatibility?.status === 'verified'\n ? h('span', { className: styles.verified }, t('verified'))\n : null,\n ),\n // 描述始终显示:站点英文数据缺翻译时 description 回退成中文也照常展示 ——\n // 描述是了解插件的第一入口,语言不一致也不该省略。\n p.description ? h('p', { className: styles.desc }, p.description) : null,\n (p.topics?.length ?? 0) > 0\n ? h('div', { className: styles.topics },\n p.topics!.slice(0, 3).map((topic) => h('span', { key: topic, className: styles.topic }, topic)),\n )\n : null,\n ),\n h('div', { className: styles.cardSide },\n h('div', { className: styles.stats },\n h('span', { className: styles.star }, '\\u2605 ', fmtStars(p.stats?.stargazers_count)),\n h('span', { className: styles.fork }, t('fork'), ' ', fmtStars(p.stats?.forks_count)),\n h('span', { className: styles.date }, relTime(p.dates?.repoUpdatedAt, t)),\n ),\n repo\n ? h('div', { className: styles.actions },\n // 查看详情:未安装/已安装都始终显示,跳转官网详情页\n h('a', {\n className: styles.detailBtn,\n // 两级路径:/plugins/{ownerSlug}/{slug};缺 ownerSlug 时从 repo 推导\n href: pluginDetailUrl(p, langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n title: p.slug,\n }, t('detail')),\n isInstalled\n // 已安装且有更新:按钮变「可更新」,点击直接覆盖安装(安装完成自动记录新版本)\n ? (update\n ? h('button', {\n className: styles.installBtnUpdate,\n title: t('updateAvailableHint'),\n onClick: () => onInstall(p, { update: true }),\n }, t('update'))\n : h('button', {\n className: styles.installBtnInstalled,\n disabled: true,\n title: t('installed'),\n }, t('installed')))\n // 未安装:按钮恒为「安装」,点击先弹信任确认;AI 识别为「可能需要命令行辅助」\n // 的插件(webInstallable=false)不拦截,允许尝试一键安装,弹窗内会给出提示与\n // 复制命令通道,安装失败时引导去 dsh 终端手动执行\n : h('button', {\n className: isCopied ? styles.installBtnCopied : styles.installBtn,\n // 文字恒定避免按钮宽度变化导致卡片跳动;点击先弹信任确认,\n // 弹窗内可选择复制命令或直接安装\n onClick: () => onInstall(p),\n }, t('install')),\n isInstalled\n // 已安装:卸载按钮(危险色),保留明确状态语义\n ? h('button', {\n className: styles.uninstallBtn,\n onClick: () => onUninstall(p),\n }, t('uninstall'))\n : null,\n )\n : null,\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Catalog list: the scrollable container with the loading / failed / empty\n * states, the plugin cards, and the count footer. Resets scroll position when\n * the category or install-status filter changes so the replaced content is\n * not mistaken for a no-op update.\n */\nimport { createElement as h, useEffect, useRef } from 'react'\nimport styles from '../../styles/List.module.css'\nimport type { HubPlugin, LocaleId, Translate } from '../../types.ts'\nimport { siteUrl } from '../../logic/urls.ts'\nimport { useIncrementalList } from '../../hooks/useIncrementalList.ts'\nimport { PluginCard } from './PluginCard.tsx'\n\nexport function CatalogList({ plugins, failed, visible, total, t, langPath, reload, category, copied, installedName, installedVersion, hasUpdate, langKey, onInstall, onUninstall, hasProxy, onOpenDiagnostics }: {\n plugins: HubPlugin[] | null\n failed: boolean\n visible: HubPlugin[]\n total: number\n t: Translate\n langPath: string\n reload: () => void\n category: string\n copied: string | null\n installedName: (p: HubPlugin) => string | null\n installedVersion: (p: HubPlugin) => string | null\n hasUpdate: (p: HubPlugin) => boolean\n langKey: LocaleId\n onInstall: (p: HubPlugin, opts?: { update?: boolean }) => void\n onUninstall: (p: HubPlugin) => void\n /** 设置里是否配置了 HTTP 代理:目录拉不出来时据此精准提示(网络不通 vs 代理不可达) */\n hasProxy: boolean\n /** 「去系统诊断检测网络」直达:跳到设置 → 系统诊断自动跑连通性检测 */\n onOpenDiagnostics: () => void\n}) {\n /** 列表滚动容器:分类/搜索切换后列表内容替换但 scrollTop 保留,会让用户误以为列表没更新,需重置回顶部 */\n const listRef = useRef<HTMLDivElement | null>(null)\n /** 增量渲染:全量目录太大(4400+),只渲染首批,滚动接近底部时自动追加下一批 */\n const { shown, hasMore, sentinelRef } = useIncrementalList(visible)\n\n useEffect(() => {\n listRef.current?.scrollTo({ top: 0 })\n }, [category])\n\n return h('div', { className: styles.body },\n h('div', { ref: listRef, className: styles.list },\n plugins === null && !failed && h('div', { className: styles.state }, t('loading')),\n failed && h('div', { className: styles.state },\n h('div', { className: styles.stateTitle }, t('failed')),\n // 精准提示:配了代理 → 提示代理可能不可达;没配 → 直接提示网络不通\n h('div', { className: styles.stateDesc }, t(hasProxy ? 'failedDescProxy' : 'failedDescNoProxy')),\n h('div', { className: styles.stateActions },\n h('button', { className: styles.retryBtn, onClick: () => reload() }, t('retry')),\n h('button', { className: styles.diagBtn, onClick: onOpenDiagnostics }, t('failNetworkRunDiag')),\n ),\n ),\n plugins !== null && !failed && visible.length === 0 && h('div', { className: styles.state },\n h('div', { className: styles.stateTitle }, t('noResult')),\n h('div', { className: styles.stateDesc }, t('noResultDesc')),\n ),\n plugins !== null && !failed && shown.map((p) => h(PluginCard, {\n // 唯一 key:数据重构后同一 slug 可能对应多个作者仓库,仅用 slug 会撞 key,\n // 导致切换分类时 React 复用旧 DOM、列表不刷新。\n key: p.ownerSlug ? `${p.ownerSlug}/${p.slug}` : p.slug,\n plugin: p,\n copied,\n installedName,\n installedVersion,\n hasUpdate,\n t,\n langKey,\n langPath,\n onInstall,\n onUninstall,\n })),\n // 滚动加载哨兵:透明 1px 元素,进入视口即触发下一批渲染(加载是纯追加,无需按钮)\n hasMore && h('div', { ref: sentinelRef, className: styles.moreSentinel, 'aria-hidden': 'true' }),\n ),\n plugins !== null && !failed && h('div', { className: styles.footer },\n h('a', {\n className: styles.footLink,\n href: siteUrl(langPath),\n target: '_blank',\n rel: 'noopener noreferrer',\n }, t('browseAll', { n: total })),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Market view: the browse experience for the catalog — category tabs,\n * search/sort/install-state controls and the plugin list. Owns nothing;\n * it wires catalog state (query/sort/filter/category) to the small\n * presentational components so PluginHubSection stays free of view internals.\n */\nimport { createElement as h, Fragment } from 'react'\nimport type { HubPlugin, LocaleId } from '../../types.ts'\nimport type { useCatalog } from '../../hooks/useCatalog.ts'\nimport { CategoryTabs } from '../layout/CategoryTabs.tsx'\nimport { CatalogControls } from '../layout/CatalogControls.tsx'\nimport { CatalogList } from '../catalog/CatalogList.tsx'\n\ntype CatalogState = ReturnType<typeof useCatalog>\n\nexport function MarketView({ catalog, t, langPath, langKey, copied, resultText, onInstall, onUninstall, hasProxy, onOpenDiagnostics }: {\n catalog: CatalogState\n t: (key: string, params?: Record<string, string | number>) => string\n langPath: string\n langKey: LocaleId\n copied: string | null\n resultText: string | null\n onInstall: (p: HubPlugin, opts?: { update?: boolean }) => void\n onUninstall: (p: HubPlugin) => void\n hasProxy: boolean\n onOpenDiagnostics: () => void\n}) {\n return h(Fragment, null,\n // 分类行保持原位原样:全部 + 各分类 chips\n h(CategoryTabs, {\n category: catalog.category,\n setCategory: catalog.setCategory,\n allLabel: t('all'),\n totalCount: catalog.total,\n langKey,\n }),\n h(CatalogControls, {\n query: catalog.query,\n setQuery: catalog.setQuery,\n sort: catalog.sort,\n sortDir: catalog.sortDir,\n toggleSort: catalog.toggleSort,\n t,\n resultText,\n }),\n h(CatalogList, {\n plugins: catalog.plugins,\n failed: catalog.failed,\n visible: catalog.visible,\n total: catalog.total,\n t,\n langPath,\n reload: catalog.reload,\n category: catalog.category,\n copied,\n installedName: catalog.installedName,\n installedVersion: catalog.installedVersion,\n hasUpdate: catalog.hasUpdate,\n langKey,\n onInstall,\n onUninstall,\n hasProxy,\n onOpenDiagnostics,\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Primary navigation: a compact segmented control switching between the\n * four top-level sections — Market (browse), Installed (manage), Custom\n * (manual command installs) and Settings (network sources & preferences).\n * Kept visually distinct from the category chips so the hierarchy reads:\n * section → category → plugin.\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/SectionTabs.module.css'\nimport { BellIcon, InstalledIcon, MarketIcon, SettingsIcon, TerminalIcon } from '../ui/icons.tsx'\n\nexport type SectionView = 'market' | 'installed' | 'custom' | 'settings'\n\nconst ORDER: Array<{ id: SectionView; labelKey: string; hintKey: string; Icon: () => ReturnType<typeof h> }> = [\n { id: 'market', labelKey: 'viewMarket', hintKey: 'viewMarketHint', Icon: MarketIcon },\n { id: 'installed', labelKey: 'viewInstalled', hintKey: 'viewInstalledHint', Icon: InstalledIcon },\n { id: 'custom', labelKey: 'viewCustom', hintKey: 'viewCustomHint', Icon: TerminalIcon },\n { id: 'settings', labelKey: 'viewSettings', hintKey: 'viewSettingsHint', Icon: SettingsIcon },\n]\n\nexport function SectionTabs({ view, setView, installedCount, t, noticeCount, onOpenNotifications }: {\n view: SectionView\n setView: (value: SectionView) => void\n installedCount: number\n t: (key: string) => string\n /** 通知中心红圈计数(记录 + 进行中任务 + 待重启);0 时不显示徽标 */\n noticeCount: number\n /** 点击打开通知中心 */\n onOpenNotifications: () => void\n}) {\n return h('div', { className: styles.root, role: 'tablist' },\n ORDER.map(({ id, labelKey, hintKey, Icon }) => h('button', {\n key: id,\n role: 'tab',\n 'aria-selected': view === id,\n title: t(hintKey),\n className: view === id ? styles.tabActive : styles.tab,\n onClick: () => setView(id),\n },\n h('span', { className: styles.tabIcon }, h(Icon)),\n t(labelKey),\n id === 'installed' && installedCount > 0\n ? h('span', { className: view === id ? styles.tabCountActive : styles.tabCount }, installedCount)\n : null)),\n // 通知入口:设置在最后一个 tab 后边,靠右对齐 —— 铃铛 + 红底白字计数(内联跟在铃铛后,不悬浮)\n h('button', {\n type: 'button',\n className: styles.noticeBtn,\n onClick: onOpenNotifications,\n title: t('notificationsHint'),\n 'aria-label': t('notificationsHint'),\n },\n h('span', { className: styles.noticeIcon }, h(BellIcon)),\n noticeCount > 0 ? h('span', { className: styles.noticeCount }, noticeCount > 99 ? '99+' : String(noticeCount)) : null),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Installed view: manages the plugins installed into the current profile.\n * Follows the mainstream extension-manager pattern (VSCode Installed tab) —\n * a searchable, sortable list of installed entries that mixes catalog\n * plugins (full metadata) and custom command installs (outside the catalog,\n * only runtime info, tagged with a custom badge). The toolbar carries a\n * search box plus two segmented radio-button groups: source filter\n * (all / catalog / custom) and sort (name / recently installed / stars / forks).\n * Each row carries restart (when pending), update and uninstall actions\n * and opens a detail modal with the full install metadata.\n *\n * Pure presentational: owns only local search/sort state; the InstalledItem\n * model arrives from the catalog hook and actions bubble up via callbacks.\n */\nimport { createElement as h, useMemo, useState } from 'react'\nimport type { FormEvent, MouseEvent, ReactNode } from 'react'\nimport styles from '../../styles/InstalledView.module.css'\nimport type { LocaleId, Translate } from '../../types.ts'\nimport type { InstalledItem } from '../../logic/installed.ts'\nimport { CATEGORY_LABELS, categoryLabel } from '../../logic/constants.ts'\nimport { SortArrowIcon } from '../ui/icons.tsx'\n\nconst INSTALLED_SORTS = ['sortName', 'sortInstalledAt', 'sortStars', 'sortForks'] as const\ntype InstalledSortKey = (typeof INSTALLED_SORTS)[number]\n\n/** 各排序的默认方向:名称按字母正序,最近安装 / Star / Fork 按数值倒序 */\nconst SORT_DEFAULT_DIR: Record<InstalledSortKey, 'asc' | 'desc'> = {\n sortName: 'asc', sortInstalledAt: 'desc', sortStars: 'desc', sortForks: 'desc',\n}\n\n/** 已安装列表的来源筛选:全部 / 目录收录 / 自定义安装 */\ntype SourceFilter = 'all' | 'catalog' | 'custom'\n\n/** 单选按钮组中的一个按钮(segmented control,与排序/来源筛选共用);\n 可带尾随图标(排序按钮激活时显示当前方向箭头) */\nfunction SegBtn({ active, onClick, label, icon }: {\n active: boolean\n onClick: () => void\n label: string\n icon?: ReactNode\n}) {\n return h('button', {\n type: 'button',\n className: active ? `${styles.segBtn} ${styles.segBtnActive}` : styles.segBtn,\n 'aria-pressed': active,\n onClick,\n }, label, icon)\n}\n\nfunction InstalledRow({ item, t, langKey, canReveal, revealLabel, onOpenDetail, onReveal, onUpdate, onUninstall, onRestart }: {\n item: InstalledItem\n t: Translate\n langKey: LocaleId\n /** 系统文件管理器可定位安装目录的平台(macOS / Linux):行内显示打开目录按钮 */\n canReveal: boolean\n /** 打开目录按钮文案(macOS = 在 Finder 中显示,Linux = 在文件夹中显示) */\n revealLabel: string\n onOpenDetail: (item: InstalledItem) => void\n /** 在系统文件管理器里定位安装目录(macOS Finder / Linux 文件管理器) */\n onReveal: (item: InstalledItem) => void\n onUpdate: (item: InstalledItem) => void\n onUninstall: (item: InstalledItem) => void\n /** 重启宿主:仅待重启(装完未挂载)条目展示,重启后该插件才生效 */\n onRestart: () => void\n}) {\n const name = item.plugin?.displayName ?? item.name\n const repo = item.repo\n const category = item.plugin?.category\n const desc = item.plugin?.description\n // 命令行安装进来的插件没有目录元数据(plugin === null):列表里打「自定义安装」标签区分\n const isCustom = item.plugin === null\n return h('li', {\n className: styles.row,\n onClick: () => onOpenDetail(item),\n role: 'button',\n tabIndex: 0,\n title: t('detail'),\n onKeyDown: (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onOpenDetail(item)\n }\n },\n },\n // 第一行:状态点 + 名称/版本/更新徽标 + 行尾来源标签列 + 右侧固定操作按钮组\n h('div', { className: styles.rowTitleLine },\n // 运行状态点:绿 = 已加载进 loader;橙 = 待重启(装完未挂载的 dsh 插件);\n // 灰 = 非 dsh 插件(如官方示例项目,宿主不加载,无需重启)\n h('span', {\n className: item.loaded ? styles.statusDot\n : item.dshCapable ? `${styles.statusDot} ${styles.statusPending}`\n : `${styles.statusDot} ${styles.statusInactive}`,\n title: item.loaded ? t('statusRunning')\n : item.dshCapable ? t('statusPending')\n : t('exampleHint'),\n 'aria-label': item.loaded ? t('statusRunning')\n : item.dshCapable ? t('statusPending')\n : t('exampleHint'),\n }),\n // 主信息:名称 + 已装版本 + 有更新徽标(flex 撑满,超长省略)\n h('div', { className: styles.rowMain },\n h('span', { className: styles.rowTitle }, name),\n item.installedVersion\n ? h('span', { className: styles.versionBadge, title: t('installedVersionLabel') }, item.installedVersion)\n : null,\n item.hasUpdate\n ? h('span', { className: styles.updateBadge, title: t('updateAvailableHint') }, t('updateAvailable'))\n : null,\n ),\n // 来源标签列(行尾、操作按钮前,右对齐固定):目录插件 →「插件市场」(品牌色),\n // 命令行安装 →「手动安装」(琥珀色);两词 4 字等宽,所有条目标签同列对齐\n h('span', {\n className: isCustom\n ? `${styles.rowSourceTag} ${styles.rowSourceTagManual}`\n : `${styles.rowSourceTag} ${styles.rowSourceTagHub}`,\n title: isCustom ? t('manualInstallHint') : t('hubInstallHint'),\n }, isCustom ? t('manualInstall') : t('hubInstall')),\n // 行操作:重启(dsh 插件待重启时)/ 详情 / 更新(有更新时)/ 卸载 —— 按钮点击不触发行打开详情\n h('div', { className: styles.rowActions },\n // 装完未挂载的 dsh 插件:给「重启」入口,点了宿主重启后插件即生效;非 dsh 插件不提示(重启无用)\n !item.loaded && item.dshCapable\n ? h('button', {\n className: styles.rowRestart,\n type: 'button',\n title: t('restartPendingHint'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onRestart() },\n }, t('restart'))\n : null,\n // 支持文件管理器定位的平台(macOS / Linux):行内该位改为打开安装目录按钮;\n // 行点击本身即打开详情弹窗,故不支持的平台(如 Windows)不显示此按钮\n canReveal\n ? h('button', {\n className: styles.rowDetail,\n type: 'button',\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onReveal(item) },\n }, revealLabel)\n : null,\n item.hasUpdate && item.plugin\n ? h('button', {\n className: styles.rowUpdate,\n type: 'button',\n title: t('updateAvailableHint'),\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onUpdate(item) },\n }, t('update'))\n : null,\n h('button', {\n className: styles.rowUninstall,\n type: 'button',\n onClick: (e: MouseEvent<HTMLButtonElement>) => { e.stopPropagation(); onUninstall(item) },\n }, t('uninstall')),\n ),\n ),\n // 示例项目徽标单独一行(非 dsh 插件):标签较长也能完整显示,不挤压名称行\n !item.dshCapable\n ? h('div', { className: styles.exampleRow },\n h('span', { className: styles.exampleBadge, title: t('exampleHint') }, t('exampleLabel')),\n )\n : null,\n // 第二行:仓库 · 分类(与名称左对齐缩进,独立成行不再挤压名称)\n repo || category\n ? h('div', { className: styles.rowMeta },\n item.repo ? h('span', { className: styles.rowRepo }, item.repo) : null,\n category ? h('span', { className: styles.rowCategory },\n categoryLabel(CATEGORY_LABELS, category, langKey)) : null,\n )\n : null,\n // 第三行(仅目录插件):简介单独一行展示,超长以省略号收尾\n desc ? h('div', { className: styles.rowDesc, title: desc }, desc) : null,\n )\n}\n\n/** 行列表:单个已安装列表(自定义安装与目录插件混排,靠徽标区分)。 */\nfunction RowList({ items, t, langKey, canReveal, revealLabel, onOpenDetail, onReveal, onUpdate, onUninstall, onRestart }: {\n items: InstalledItem[]\n t: Translate\n langKey: LocaleId\n canReveal: boolean\n revealLabel: string\n onOpenDetail: (item: InstalledItem) => void\n onReveal: (item: InstalledItem) => void\n onUpdate: (item: InstalledItem) => void\n onUninstall: (item: InstalledItem) => void\n onRestart: () => void\n}) {\n return h('ul', { className: styles.list },\n items.map((item) => h(InstalledRow, {\n key: item.name,\n item,\n t,\n langKey,\n canReveal,\n revealLabel,\n onOpenDetail,\n onReveal,\n onUpdate,\n onUninstall,\n onRestart,\n })),\n )\n}\n\nexport function InstalledView({ items, t, langKey, platform, onOpenDetail, onReveal, onUpdate, onUninstall, onRestart }: {\n items: InstalledItem[]\n t: Translate\n langKey: LocaleId\n /** 宿主系统平台(node process.platform):支持文件管理器定位(macOS / Linux)时行内显示打开目录按钮 */\n platform: string\n onOpenDetail: (item: InstalledItem) => void\n onReveal: (item: InstalledItem) => void\n /** 更新:仅目录插件且有更新时触发(自定义安装无目录信号可比) */\n onUpdate: (item: InstalledItem) => void\n onUninstall: (item: InstalledItem) => void\n /** 重启宿主:待重启条目行内按钮触发(装完未挂载的插件重启后生效) */\n onRestart: () => void\n}) {\n const [query, setQuery] = useState('')\n /** 默认按「最近安装」排序(最新在前);点其他排序按钮用该排序的默认方向(Star/Fork 最多在前、名称正序) */\n const [sort, setSort] = useState<InstalledSortKey>('sortInstalledAt')\n /** 当前排序方向:点同一个排序按钮切换 正/倒序;点新排序用该排序的默认方向 */\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')\n /** 已安装列表的来源筛选:全部 / 目录收录 / 自定义安装(单选按钮组) */\n const [sourceFilter, setSourceFilter] = useState<SourceFilter>('all')\n\n /** 点击排序按钮:同一按钮切换正/倒序,新按钮用默认方向 */\n function pickSort(key: InstalledSortKey) {\n if (key === sort) setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))\n else { setSort(key); setSortDir(SORT_DEFAULT_DIR[key]) }\n }\n\n // 搜索 + 排序后的展示列表:搜索命中名称/包名/仓库/描述;排序支持名称/最近安装/Star/Fork\n const list = useMemo(() => {\n const q = query.trim().toLowerCase()\n const filtered = items.filter((item) => {\n if (!q) return true\n return (item.plugin?.displayName ?? item.name).toLowerCase().includes(q)\n || item.name.toLowerCase().includes(q)\n || (item.repo ?? '').toLowerCase().includes(q)\n || (item.plugin?.description ?? '').toLowerCase().includes(q)\n })\n const dir = sortDir === 'asc' ? 1 : -1\n return [...filtered].sort((a, b) => {\n if (sort === 'sortName') return (a.plugin?.displayName ?? a.name).localeCompare(b.plugin?.displayName ?? b.name) * dir\n // Star / Fork:目录插件按数量比较(正/倒序随 dir);自定义安装(无目录数据,stats 缺失)永远排最后\n if (sort === 'sortStars' || sort === 'sortForks') {\n const metric = sort === 'sortStars' ? 'stargazers_count' : 'forks_count'\n const sa = a.plugin?.stats?.[metric]\n const sb = b.plugin?.stats?.[metric]\n if (sa == null && sb == null) return 0\n if (sa == null) return 1\n if (sb == null) return -1\n return (sa - sb) * dir\n }\n // 最近安装:按安装时间比较;无安装时间记录的永远排最后\n const av = a.installedAt ?? ''\n const bv = b.installedAt ?? ''\n if (av === bv) return 0\n if (av === '') return 1\n if (bv === '') return -1\n return av.localeCompare(bv) * dir\n })\n }, [items, query, sort, sortDir])\n\n const catalogItems = list.filter((item) => item.plugin !== null)\n const customItems = list.filter((item) => item.plugin === null)\n // 已安装列表:搜索 + 排序后,再按来源筛选(全部 / 目录收录 / 自定义安装)\n const filtered = sourceFilter === 'all' ? list\n : sourceFilter === 'catalog' ? catalogItems : customItems\n\n // 行列表公共参数:macOS 文案特指 Finder,Windows / Linux 用通用「在文件夹中显示」\n const rowListProps = {\n t, langKey,\n canReveal: platform === 'darwin' || platform === 'win32' || platform === 'linux',\n revealLabel: platform === 'darwin' ? t('revealFolder') : t('openFolder'),\n onOpenDetail, onReveal, onUpdate, onUninstall, onRestart,\n }\n\n // 工具栏:第一行搜索框撑满,第二行来源筛选按钮组 + 排序按钮组(单选按钮组形态)\n const listToolbar = h('div', { className: styles.toolbar },\n h('div', { className: styles.searchWrap },\n h('input', {\n className: styles.searchInput,\n type: 'search',\n placeholder: t('installedSearch'),\n value: query,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) =>\n setQuery((e.target as HTMLInputElement).value),\n }),\n ),\n h('div', { className: styles.segRow },\n h('span', { className: styles.segLabel }, t('filterByLabel')),\n h('div', { className: styles.segGroup, role: 'radiogroup', 'aria-label': t('filterByLabel') },\n SegBtn({ active: sourceFilter === 'all', onClick: () => setSourceFilter('all'), label: t('all') }),\n SegBtn({ active: sourceFilter === 'catalog', onClick: () => setSourceFilter('catalog'), label: t('installedFilterCatalog') }),\n SegBtn({ active: sourceFilter === 'custom', onClick: () => setSourceFilter('custom'), label: t('customLabel') }),\n ),\n h('span', { className: styles.segLabel }, t('sortByLabel')),\n h('div', { className: styles.segGroup, role: 'radiogroup', 'aria-label': t('sortAria') },\n INSTALLED_SORTS.map((key) => SegBtn({\n active: sort === key,\n onClick: () => pickSort(key),\n label: t(key),\n icon: sort === key ? h(SortArrowIcon, { up: sortDir === 'asc' }) : null,\n })),\n ),\n ),\n )\n\n return h('div', { className: styles.root },\n listToolbar,\n // 筛选后的列表;一个都没装 → 引导空态,搜索/筛选无结果 → 无结果空态\n filtered.length === 0\n ? items.length === 0\n ? h('div', { className: styles.empty },\n h('div', { className: styles.emptyTitle }, t('installedEmpty')),\n h('div', { className: styles.emptyDesc }, t('installedEmptyDesc')),\n )\n : h('div', { className: styles.empty },\n h('div', { className: styles.emptyTitle }, t('noResult')),\n h('div', { className: styles.emptyDesc }, t('noResultDesc')),\n )\n : h(RowList, { items: filtered, ...rowListProps }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Custom install view: a standalone top-level section for manually\n * installing npm packages or GitHub sources outside the catalog. Three\n * installer cards, one per channel — npm package (bare name or a full\n * npm/pnpm install command, including the official global `npm install -g`),\n * GitHub source and the official `dsh plugin ... add <target>` command —\n * each with a placeholder example above the input and its own format check.\n * The cards stay separate so a user never has to guess which format goes\n * where. Finished installs surface in the Installed view, marked as custom.\n *\n * Pure presentational: owns only the three local input/error states; the\n * actual install (custom source, gated by the security toggles) bubbles up\n * via onInstallCustom.\n */\nimport { createElement as h, useState } from 'react'\nimport type { FormEvent, MouseEvent } from 'react'\nimport styles from '../../styles/CustomInstallView.module.css'\nimport modal from '../../styles/Modal.module.css'\nimport type { InstallChannel, Translate } from '../../types.ts'\nimport { CloseIcon, HelpIcon } from '../ui/icons.tsx'\n\n/* —— 自定义安装输入预检 ——\n * 提交前校验「输入是否符合该通道格式」,识别不了的输入不发请求,就地提示推荐格式。\n * 三个通道严格分开:npm 框认裸包名或完整 npm/pnpm 安装命令(含全局 `npm install -g`),\n * git 框只认 GitHub 地址,命令框只认官方 `dsh plugin --profile <name> <add|update> <target>`\n * (--profile 必填,无 -p 简写;update = 更新已安装目标到最新)。\n * 这里只做格式校验,真正归一化/安装由服务端完成。 */\n\n/** GitHub 地址(带前缀形态):github:、https://github.com/、git+https://github.com/、git@github.com: */\nconst GITHUB_URL_RE = /^(?:github:|https?:\\/\\/github\\.com\\/|git\\+https?:\\/\\/github\\.com\\/|git@github\\.com:)([A-Za-z0-9._-]+)\\/([A-Za-z0-9._-]+?)(?:\\.git)?$/\n/** 裸 owner/repo(npm 包名只有 @scope/pkg 才带斜杠,无 @ 前缀的 a/b 一定是 GitHub 仓库) */\nconst GITHUB_BARE_RE = /^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$/\n/** npm 包名(含 @scope/pkg) */\nconst NPM_PACKAGE_RE = /^(?:@[a-z0-9._-]+\\/)?[a-z0-9._-]+$/\n\n/** DSH 命令行前缀(官方唯一形式 `dsh plugin --profile <name> <add|update> <target>`)—— 提取其中的动作与目标。\n * 官方 CLI(apps/cli/src/args.ts,commander):--profile 为必填长选项(无 -p 简写,省略即报错),\n * 支持 `--profile=<name>` 等号形式;命令大小写不敏感。update = 已安装目标覆盖更新到最新;\n * remove 不走这里(卸载由「已安装」列表的卸载按钮执行,命令框不认卸载动词)。\n * 与 server 端 installTargetOf 口径一致。 */\nconst DSH_PLUGIN_CMD_RE = /^dsh\\s+plugin\\s+--profile(?:\\s+|=)\\S+\\s+(add|update)\\s+(.+)$/i\n\n/** npm 全局安装命令(官方 README 格式,如 `npm install -g @deepseek-ai/dsh @deepseek-harness-tui/dsh-tui`)——\n * 提取 -g 之后的包列表;任一包名非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 口径一致。 */\nconst NPM_GLOBAL_CMD_RE = /^npm\\s+(?:install|i)\\s+(?:-g|--global)\\s+(.+)$/i\n\n/** 常规 npm/pnpm 安装命令(装进当前 profile,如 `npm install lodash`、`pnpm add @scope/pkg`)——\n * 提取命令后的包列表;包列表在 splitPackages 里逐个校验。 */\nconst NPM_INSTALL_CMD_RE = /^(?:npm\\s+(?:install|i)|pnpm\\s+(?:add|i|install))\\s+(.+)$/i\n\n/** 解析 DSH 命令:返回 { action, target };非官方命令返回 null(交给格式错误提示)。 */\nfunction parseDshCommand(raw: string): { action: 'add' | 'update'; target: string } | null {\n const input = raw.trim()\n const match = DSH_PLUGIN_CMD_RE.exec(input)\n if (match === null) return null\n return { action: match[1].toLowerCase() as 'add' | 'update', target: match[2].trim() }\n}\n\n/** 空格分隔的包列表:逐个按 npm 包名语法校验 + 拒绝以 - 开头的 token(npm 会把 --xxx 当参数而非包名),\n * 任一非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 同口径。 */\nfunction splitPackages(raw: string): string[] | null {\n const packages = raw.trim().split(/\\s+/).filter((p) => p !== '')\n if (packages.length === 0 || packages.some((p) => !NPM_PACKAGE_RE.test(p) || p.startsWith('-'))) return null\n return packages\n}\n\n/** NPM 框输入解析结果:\n * - pkg:裸包名或常规安装命令(npm install / npm i / pnpm add / pnpm i),提取单个安装目标;\n * - global:官方全局安装命令(npm install -g <pkgs>),提取包列表走全局通道。 */\ntype NpmInputParse =\n | { kind: 'pkg'; target: string }\n | { kind: 'global'; pkgs: string[] }\n\nfunction parseNpmInput(raw: string): NpmInputParse | null {\n const input = raw.trim()\n // 裸包名(含 @scope/pkg)\n if (NPM_PACKAGE_RE.test(input)) return { kind: 'pkg', target: input }\n // 官方全局安装 npm install -g <pkgs>(装系统级 CLI 工具)\n const global = NPM_GLOBAL_CMD_RE.exec(input)\n if (global !== null) {\n const pkgs = splitPackages(global[1])\n if (pkgs !== null) return { kind: 'global', pkgs }\n return null\n }\n // 常规安装命令 npm install <pkgs> / pnpm add <pkgs> —— 装进当前 profile,一次一个包\n const install = NPM_INSTALL_CMD_RE.exec(input)\n if (install !== null) {\n const pkgs = splitPackages(install[1])\n if (pkgs !== null && pkgs.length === 1) return { kind: 'pkg', target: pkgs[0] }\n return null\n }\n return null\n}\n\nfunction isGitHubInput(raw: string): boolean {\n const input = raw.trim()\n return GITHUB_URL_RE.test(input) || GITHUB_BARE_RE.test(input)\n}\n\n/** 卡片标题旁的「帮助」弹窗:三块卡片各自的标题与格式清单语言包 key。 */\nconst HELP_CARDS = {\n npm: { titleKey: 'npmInstallLabel', contentKey: 'npmInstallHelp' },\n git: { titleKey: 'gitInstallLabel', contentKey: 'gitInstallHelp' },\n cmd: { titleKey: 'dshCmdLabel', contentKey: 'dshCmdHelp' },\n} as const\n\ntype HelpTarget = keyof typeof HELP_CARDS\n\nexport function CustomInstallView({ t, onInstallCustom, enableNpm, enableGit, enableDsh, onOpenSettings, profile }: {\n t: Translate\n /** 命令行安装:输入 npm 包名 / npm、pnpm 安装命令 / GitHub 地址 / dsh plugin 命令即装\n * (custom 源,受安全设置开关控制)。installChannel 必填 = 入口渠道(三张卡片之一):\n * 服务端日志/报错提示据此溯源「从哪个入口发起」;opts.globalNpm 表示官方 npm 全局安装\n * 命令(npm install -g),附带解析出的包列表(仍属 NPM 包入口)。 */\n onInstallCustom: (raw: string, opts: { installChannel: InstallChannel; globalNpm?: string[] }) => void\n /** 安全信任三通道开关:关掉后对应输入卡片禁用(不提交),并引导去设置打开 */\n enableNpm: boolean\n enableGit: boolean\n enableDsh: boolean\n /** 引导去「设置 → 安全信任」打开被关闭的通道开关 */\n onOpenSettings: () => void\n /** 当前 dsh profile 名(宿主 /env 快照):一键插入的更新命令用它拼 --profile */\n profile: string\n}) {\n /** 自定义安装:NPM 包输入与格式错误('' = 无错误) */\n const [npmQuery, setNpmQuery] = useState('')\n const [npmError, setNpmError] = useState('')\n /** 自定义安装:GitHub 源码输入与格式错误('' = 无错误) */\n const [gitQuery, setGitQuery] = useState('')\n const [gitError, setGitError] = useState('')\n /** 自定义安装:DSH 命令输入与格式错误('' = 无错误) */\n const [cmdQuery, setCmdQuery] = useState('')\n const [cmdError, setCmdError] = useState('')\n /** 卡片标题旁「帮助」弹窗:null = 未打开;'npm' | 'git' | 'cmd' = 打开对应卡片的格式清单 */\n const [helpFor, setHelpFor] = useState<HelpTarget | null>(null)\n\n /** 通道关闭提示行:开关关掉后替代示例与输入行,引导去设置打开 */\n const channelOffRow = h('div', { className: styles.channelOff },\n h('span', { className: styles.channelOffText }, t('channelDisabledHint')),\n h('button', {\n type: 'button',\n className: styles.channelOffBtn,\n onClick: onOpenSettings,\n }, t('goToSettings')),\n )\n\n // 三个通道分开校验 —— 识别不了的输入不发请求,就地提示推荐写法。\n // NPM 框认裸包名或完整 npm/pnpm 命令(含全局 npm install -g,走 globalNpm 通道);\n // 命令框只认官方 dsh plugin 命令,提交时剥成裸目标发给服务端。\n const submitNpm = () => {\n const raw = npmQuery.trim()\n if (!raw) return\n const parsed = parseNpmInput(raw)\n if (parsed === null) { setNpmError(t('npmInstallInvalid')); return }\n if (parsed.kind === 'global') {\n onInstallCustom(raw, { installChannel: 'npm', globalNpm: parsed.pkgs })\n } else {\n onInstallCustom(parsed.target, { installChannel: 'npm' })\n }\n setNpmQuery('')\n setNpmError('')\n }\n const submitGit = () => {\n const target = gitQuery.trim()\n if (!target) return\n if (!isGitHubInput(target)) { setGitError(t('gitInstallInvalid')); return }\n onInstallCustom(target, { installChannel: 'git' })\n setGitQuery('')\n setGitError('')\n }\n const submitCmd = () => {\n const raw = cmdQuery.trim()\n if (!raw) return\n const parsed = parseDshCommand(raw)\n if (parsed === null) { setCmdError(t('dshCmdInvalid', { profile })); return }\n // add / update 统一走安装流程:目标已安装时弹窗自动转「更新」覆盖重装(服务端 mode=update 放行),\n // 未安装时即为普通安装 —— 粘贴 `dsh plugin --profile web update dsh-plugin` 这类命令即可更新到最新\n onInstallCustom(parsed.target, { installChannel: 'dsh' })\n setCmdQuery('')\n setCmdError('')\n }\n /** 一键插入 DSH Plugin Hub 自身的更新命令:按当前 profile 拼官方命令填进输入框,用户确认后提交 */\n const insertHubUpdate = () => {\n setCmdQuery(`dsh plugin --profile ${profile} update dsh-plugin`)\n setCmdError('')\n }\n\n return h('div', { className: styles.root },\n // 页面说明:独立一级导航,交代「装完去哪看」\n h('p', { className: styles.desc }, t('customViewDesc')),\n // 三块卡片(一行一个):label + 文本框上方示例 + 输入行 + 错误区;\n // 安全信任开关关掉对应通道时,卡片禁用并显示「前往设置」提示行\n h('div', { className: styles.installCards },\n // NPM 包:输入包名或原生 npm/pnpm 安装命令即装(含官方全局 npm install -g)\n h('div', { className: enableNpm ? styles.installCard : `${styles.installCard} ${styles.installCardDisabled}` },\n h('div', { className: styles.installCardHead },\n h('span', { className: styles.installLabel }, t('npmInstallLabel')),\n // 标题旁帮助:点开该卡片的格式清单弹窗\n h('button', {\n type: 'button',\n className: styles.installHelpBtn,\n title: t('installHelp'),\n 'aria-label': t('installHelp'),\n onClick: () => setHelpFor('npm'),\n }, h(HelpIcon)),\n ),\n !enableNpm\n ? channelOffRow\n : [\n // 文本框上方的示例:把支持的原生命令模式写清楚(两行)\n h('div', { className: styles.installExample },\n t('npmInstallExample'), h('br'), t('npmInstallExample2')),\n h('div', { className: styles.installRow },\n h('input', {\n className: npmError ? `${styles.installInput} ${styles.installInputError}` : styles.installInput,\n type: 'text',\n placeholder: t('npmInstallPlaceholder'),\n value: npmQuery,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) => {\n setNpmQuery((e.target as HTMLInputElement).value)\n // 重新输入即清掉格式错误提示\n setNpmError('')\n },\n onKeyDown: (e: KeyboardEvent) => { if (e.key === 'Enter') submitNpm() },\n }),\n h('button', {\n className: styles.installBtn,\n type: 'button',\n disabled: npmQuery.trim() === '',\n onClick: submitNpm,\n }, t('installCliBtn')),\n ),\n // 格式错误:识别不了的包名就地说明,并给出推荐写法\n npmError ? h('div', { className: styles.installError }, npmError) : null,\n ],\n ),\n // GitHub 源码:输入仓库地址即装\n h('div', { className: enableGit ? styles.installCard : `${styles.installCard} ${styles.installCardDisabled}` },\n h('div', { className: styles.installCardHead },\n h('span', { className: styles.installLabel }, t('gitInstallLabel')),\n h('button', {\n type: 'button',\n className: styles.installHelpBtn,\n title: t('installHelp'),\n 'aria-label': t('installHelp'),\n onClick: () => setHelpFor('git'),\n }, h(HelpIcon)),\n ),\n !enableGit\n ? channelOffRow\n : [\n h('div', { className: styles.installExample }, t('gitInstallExample')),\n h('div', { className: styles.installRow },\n h('input', {\n className: gitError ? `${styles.installInput} ${styles.installInputError}` : styles.installInput,\n type: 'text',\n placeholder: t('gitInstallPlaceholder'),\n value: gitQuery,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) => {\n setGitQuery((e.target as HTMLInputElement).value)\n setGitError('')\n },\n onKeyDown: (e: KeyboardEvent) => { if (e.key === 'Enter') submitGit() },\n }),\n h('button', {\n className: styles.installBtn,\n type: 'button',\n disabled: gitQuery.trim() === '',\n onClick: submitGit,\n }, t('installCliBtn')),\n ),\n gitError ? h('div', { className: styles.installError }, gitError) : null,\n ],\n ),\n // 命令卡片:粘贴官方 dsh plugin 命令即装/即更新 —— 只认完整命令\n // (--profile 必填,可含 = 等号,动词 add/update,剥成裸目标走安装流程)\n h('div', { className: enableDsh ? styles.installCard : `${styles.installCard} ${styles.installCardDisabled}` },\n h('div', { className: styles.installCardHead },\n h('span', { className: styles.installLabel }, t('dshCmdLabel')),\n h('button', {\n type: 'button',\n className: styles.installHelpBtn,\n title: t('installHelp'),\n 'aria-label': t('installHelp'),\n onClick: () => setHelpFor('cmd'),\n }, h(HelpIcon)),\n // 一键插入 Hub 自身的更新命令:按当前 profile 拼 `dsh plugin --profile <p> update dsh-plugin`\n // 填入输入框(命令卡片被安全开关禁用时不显示,插入后也提交不了)\n enableDsh\n ? h('button', {\n type: 'button',\n className: styles.installInsertBtn,\n onClick: insertHubUpdate,\n }, t('dshCmdInsertHubUpdate'))\n : null,\n ),\n !enableDsh\n ? channelOffRow\n : [\n h('div', { className: styles.installExample }, t('dshCmdExample', { profile })),\n h('div', { className: styles.installRow },\n h('input', {\n className: cmdError ? `${styles.installInput} ${styles.installInputError}` : styles.installInput,\n type: 'text',\n placeholder: t('dshCmdPlaceholder'),\n value: cmdQuery,\n spellCheck: false,\n onInput: (e: FormEvent<HTMLInputElement>) => {\n setCmdQuery((e.target as HTMLInputElement).value)\n setCmdError('')\n },\n onKeyDown: (e: KeyboardEvent) => { if (e.key === 'Enter') submitCmd() },\n }),\n h('button', {\n className: styles.installBtn,\n type: 'button',\n disabled: cmdQuery.trim() === '',\n onClick: submitCmd,\n }, t('installCliBtn')),\n ),\n cmdError ? h('div', { className: styles.installError }, cmdError) : null,\n ],\n ),\n ),\n // 帮助弹窗:点卡片标题旁的问号打开 —— 宽窗(720px)把该通道支持的命令格式整行展示,防止折行\n helpFor !== null\n ? h('div', {\n className: modal.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) setHelpFor(null) },\n },\n h('div', { className: `${modal.errorModal} ${modal.helpModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: modal.modalHead },\n h('div', { className: modal.modalTitle }, `${t(HELP_CARDS[helpFor].titleKey)} · ${t('helpModalTitle')}`),\n h('button', {\n className: modal.modalClose,\n 'aria-label': t('errorClose'),\n onClick: () => setHelpFor(null),\n }, h(CloseIcon)),\n ),\n h('div', { className: modal.modalBody },\n // 格式清单:一行一条;`命令\\t说明` 的说明跟在命令后,纯说明行以 \\t 开头\n h('div', { className: styles.helpBody },\n t(HELP_CARDS[helpFor].contentKey, { profile }).split('\\n').map((line, i) => {\n const [cmd, note] = line.split('\\t')\n return h('div', { key: i, className: styles.helpLine },\n cmd !== '' ? h('span', { className: styles.helpCmd }, cmd) : null,\n note !== undefined ? h('span', { className: styles.helpNote }, note) : null,\n )\n }),\n ),\n ),\n ),\n )\n : null,\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Compact switch used by the settings rows. Native-button based so it is\n * keyboard focusable and announces state via aria-checked; styling driven\n * by the --hub-* tokens (on = brand fill, off = neutral track).\n */\nimport { createElement as h } from 'react'\nimport styles from '../../styles/Toggle.module.css'\n\nexport function Toggle({ checked, onChange, title, disabled }: {\n checked: boolean\n onChange: (next: boolean) => void\n title?: string\n disabled?: boolean\n}) {\n return h('button', {\n type: 'button',\n role: 'switch',\n 'aria-checked': checked,\n disabled,\n title,\n className: checked ? styles.toggleOn : styles.toggle,\n onClick: () => onChange(!checked),\n }, h('span', { className: styles.knob }))\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Button-style dropdown (native <select> replacement).\n *\n * The trigger is a compact toolbar button — hairline border + subtle grey\n * fill + current value + chevron — so it sits naturally next to the other\n * toolbar buttons and takes a single slot of horizontal space. Clicking\n * outside or pressing Esc closes the panel; options get a hover fill and\n * the active one a brand highlight, all driven by the --hub-* tokens.\n */\nimport { createElement as h, useEffect, useRef, useState } from 'react'\nimport type { JSX } from 'react'\nimport styles from '../../styles/Dropdown.module.css'\nimport { ChevronDownIcon } from './icons.tsx'\n\nexport interface DropdownOption<T extends string> {\n value: T\n label: string\n /** 可选计数徽标(如「已安装 12」) */\n count?: number\n}\n\ninterface DropdownProps<T extends string> {\n value: T\n options: DropdownOption<T>[]\n onChange: (value: T) => void\n title?: string\n /** 额外挂到根节点上的类名(如 margin 微调) */\n className?: string\n}\n\nexport function Dropdown<T extends string>({ value, options, onChange, title, className }: DropdownProps<T>): JSX.Element {\n const [open, setOpen] = useState(false)\n const rootRef = useRef<HTMLDivElement | null>(null)\n\n // 面板展开时:点面板外部或按 Esc 关闭。\n useEffect(() => {\n if (!open) return\n const onDoc = (e: MouseEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false)\n }\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false)\n }\n document.addEventListener('mousedown', onDoc)\n document.addEventListener('keydown', onKey)\n return () => {\n document.removeEventListener('mousedown', onDoc)\n document.removeEventListener('keydown', onKey)\n }\n }, [open])\n\n const current = options.find((o) => o.value === value)\n\n return h('div', {\n className: className ? `${styles.dropdown} ${className}` : styles.dropdown,\n ref: rootRef,\n },\n h('button', {\n className: styles.dropdownBtn,\n type: 'button',\n title,\n 'aria-haspopup': 'listbox',\n 'aria-expanded': open,\n onClick: () => setOpen((v) => !v),\n },\n h('span', { className: styles.dropdownLabel }, current?.label ?? value),\n h('span', { className: open ? styles.dropdownArrowOpen : styles.dropdownArrow }, h(ChevronDownIcon)),\n ),\n open && h('div', { className: styles.dropdownPanel, role: 'listbox' },\n options.map((o) => h('button', {\n key: o.value,\n type: 'button',\n role: 'option',\n 'aria-selected': o.value === value,\n className: o.value === value ? styles.dropdownItemActive : styles.dropdownItem,\n onClick: () => {\n onChange(o.value)\n setOpen(false)\n },\n },\n h('span', { className: styles.dropdownItemLabel }, o.label),\n typeof o.count === 'number'\n ? h('span', { className: o.value === value ? styles.dropdownCountActive : styles.dropdownCount }, o.count)\n : null,\n )),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * System diagnostics list: one row per connectivity channel (npm registry /\n * GitHub API / catalog site), each with a live status badge — 200 OK in\n * green, Unreachable in red, Checking… while probing. The list runs\n * automatically when the page opens; every row is a button that re-probes\n * just that channel, so a click always yields visible feedback\n * (row pulses → badge flips → latency refreshes).\n */\nimport { createElement as h, useCallback, useEffect, useRef, useState } from 'react'\nimport styles from '../../styles/DiagnosticsView.module.css'\nimport type { EnvInfo, Translate } from '../../types.ts'\nimport { PLUGIN_VERSION } from '../../logic/constants.ts'\n\ntype ProbeKey = 'npm' | 'github' | 'catalog' | 'proxy'\n\n/** 系统版本文本:提交 Issue 时粘贴到正文,方便作者复现。 */\nfunction formatEnv(env: EnvInfo): string {\n return [\n `DSH Plugin Hub ${PLUGIN_VERSION}`,\n `DSH ${env.dshVersion ?? 'unknown'}`,\n `Node ${env.nodeVersion}`,\n `${env.platform} ${env.arch} (${env.release})`,\n `Profile ${env.profile}`,\n env.dshHome ? `Home ${env.dshHome}` : '',\n ].filter(Boolean).join('\\n')\n}\n\ninterface RowState {\n key: ProbeKey\n /** 目标地址展示(registry 地址 / github.com / dsh-plugin.org) */\n display: string\n nameKey: string\n status: 'idle' | 'running' | 'ok' | 'fail'\n ms: number | null\n statusCode: number | null\n /** 失败细分原因:'tlsRevocation' = 证书吊销检查受阻(本机 TLS 环境问题,不是网络不通) */\n reason?: string | null\n}\n\nconst INITIAL_ROWS: RowState[] = [\n // npm 行 display 初始置空:设置里未配置镜像时显示「未配置(跟随本机)」,探测结果回来再用服务端 display 覆盖\n { key: 'npm', display: '', nameKey: 'diagNpm', status: 'idle', ms: null, statusCode: null },\n { key: 'github', display: 'github.com', nameKey: 'diagGithub', status: 'idle', ms: null, statusCode: null },\n { key: 'catalog', display: '', nameKey: 'diagCatalog', status: 'idle', ms: null, statusCode: null },\n]\n\nexport function DiagnosticsView({ t, env, proxy, onCopy }: {\n t: Translate\n env: EnvInfo | null\n /** 设置里配置的 HTTP 代理地址;留空(未配置)不显示代理行 */\n proxy: string\n onCopy: (text: string) => void\n}) {\n // 代理行仅在配置了 HTTP 代理时出现:用该代理探测 github.com,验证「代理能不能把请求带出去」。\n // 未配置(留空直连)没有可验证的代理,不渲染这一行,避免无意义的诊断项。\n const [rows, setRows] = useState<RowState[]>(() => {\n const base = INITIAL_ROWS.map((r) => ({ ...r }))\n if (proxy.trim() !== '') {\n base.push({ key: 'proxy', display: proxy.trim(), nameKey: 'diagProxy', status: 'idle', ms: null, statusCode: null })\n }\n return base\n })\n /** 当前探测请求:重测/卸载时 abort 旧请求,避免乱序结果覆盖 */\n const runningRef = useRef<AbortController | null>(null)\n\n const patchRows = (key: ProbeKey | undefined, patch: Partial<RowState>) => {\n setRows((prev) => prev.map((r) => (key === undefined || r.key === key ? { ...r, ...patch } : r)))\n }\n\n /** 探测:key 缺省 = 全量串行;传 key = 只重测该通道 */\n const run = useCallback((key?: ProbeKey) => {\n runningRef.current?.abort()\n const controller = new AbortController()\n runningRef.current = controller\n patchRows(key, { status: 'running', ms: null, statusCode: null, reason: null })\n\n void (async () => {\n try {\n const res = await fetch('/dsh-plugin-hub/diagnostics', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: key === undefined ? '{}' : JSON.stringify({ key }),\n cache: 'no-store',\n signal: controller.signal,\n })\n if (!res.ok || res.body === null) throw new Error(`http ${res.status}`)\n const reader = res.body.getReader()\n const decoder = new TextDecoder()\n let buf = ''\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buf += decoder.decode(value, { stream: true })\n let nl = buf.indexOf('\\n')\n while (nl !== -1) {\n const raw = buf.slice(0, nl).trim()\n buf = buf.slice(nl + 1)\n if (raw !== '') {\n const ev = JSON.parse(raw) as { type?: string; key?: string; ms?: number | null; status?: number | null; display?: string; reason?: string | null }\n if (ev.type === 'ok' || ev.type === 'fail') {\n patchRows(ev.key as ProbeKey, {\n status: ev.type === 'ok' ? 'ok' : 'fail',\n ms: typeof ev.ms === 'number' ? ev.ms : null,\n statusCode: typeof ev.status === 'number' ? ev.status : null,\n // 服务端带出实际使用的源地址(配置镜像 → 镜像地址;未配置 → 空串)\n display: typeof ev.display === 'string' ? ev.display : '',\n // 失败细分原因:证书吊销受阻时给对症提示,而非笼统「不可达」\n reason: typeof ev.reason === 'string' ? ev.reason : null,\n })\n }\n }\n nl = buf.indexOf('\\n')\n }\n }\n } catch {\n // 连接本地服务失败:该项标记失败(被新请求 abort 的旧请求直接忽略)\n if (controller.signal.aborted) return\n patchRows(key, { status: 'fail', ms: null, statusCode: null })\n }\n })()\n }, [])\n\n // 进入页面自动全量探测一轮;卸载时中断\n useEffect(() => {\n run()\n return () => runningRef.current?.abort()\n }, [run])\n\n const anyRunning = rows.some((r) => r.status === 'running')\n const allOk = !anyRunning && rows.every((r) => r.status === 'ok')\n const anyFail = !anyRunning && rows.some((r) => r.status === 'fail')\n\n return h('div', { className: styles.panel },\n // 最顶部:系统版本 —— 复制当前宿主版本与系统信息,提 Issue 时粘贴到正文便于复现\n h('div', { className: styles.envRow },\n h('div', { className: styles.envLabel },\n h('div', { className: styles.envTitle }, t('settingsEnvSnapshot')),\n h('div', { className: styles.envDesc }, t('settingsEnvSnapshotDesc')),\n ),\n h('button', {\n type: 'button',\n className: styles.envCopyBtn,\n disabled: env === null,\n onClick: () => { if (env) onCopy(formatEnv(env)) },\n }, t('settingsEnvCopy')),\n ),\n // 头部:右侧「立即诊断」按钮,点击全量重测所有通道\n h('div', { className: styles.head },\n h('span', { className: styles.headHint }, t('diagHeadHint', { n: rows.length })),\n h('button', {\n type: 'button',\n className: styles.runBtn,\n disabled: anyRunning,\n onClick: () => run(),\n }, t('diagRunAll')),\n ),\n rows.map((r) => {\n // 证书吊销检查受阻:badge 与悬浮提示都换成对症文案,避免用户朝「网络不通」方向排查\n const revokeBlocked = r.status === 'fail' && r.reason === 'tlsRevocation'\n const badge = r.status === 'running'\n ? h('span', { className: `${styles.badge} ${styles.badgeRunning}` }, t('diagChecking'))\n : r.status === 'ok'\n ? h('span', { className: `${styles.badge} ${styles.badgeOk}` },\n r.statusCode !== null ? `HTTP ${r.statusCode} ${t('diagOk')}` : t('diagOk'))\n : r.status === 'fail'\n ? h('span', { className: `${styles.badge} ${styles.badgeFail}` },\n revokeBlocked ? t('diagFailRevocation') : t('settingsDiagFail'))\n : h('span', { className: `${styles.badge} ${styles.badgeIdle}` }, t('diagIdle'))\n return h('button', {\n key: r.key,\n type: 'button',\n className: styles.row,\n disabled: r.status === 'running',\n onClick: () => run(r.key),\n title: revokeBlocked ? t('diagFailRevocationHint') : t('diagRecheck'),\n },\n h('span', { className: styles.name }, t(r.nameKey)),\n // npm 行未配置镜像:display 为空 → 显示「未配置(跟随本机)」,不误导成官方源;\n // 目录站点行不暴露域名/API 地址,固定显示「插件市场」这一友好称呼\n h('span', { className: styles.display },\n r.key === 'catalog' ? t('diagCatalogTarget') : (r.display !== '' ? r.display : t('diagNpmUnset'))),\n h('span', { className: styles.meta }, r.status === 'ok' && r.ms !== null ? `${r.ms} ms` : ''),\n badge,\n )\n }),\n // 底部总览:全部通过 / 存在异常 / 检测中,汇总整体状态\n h('div', {\n className: `${styles.summary} ${anyRunning ? styles.summaryRunning : allOk ? styles.summaryOk : styles.summaryFail}`,\n }, anyRunning ? t('diagSummaryRunning') : allOk ? t('diagSummaryOk') : t('diagSummaryFail')),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Built-in log viewer dialog: no external software needed — the app opens\n * its own window and loads the local system log (JSONL at\n * ~/.dsh/profiles/<profile>/hub.log) straight from the server, one page at\n * a time.\n *\n * Every line is categorized twice: a function area (install / uninstall /\n * update / diagnostics / settings / system) and a severity level (debug /\n * info / success / warn / error). Filtering on both axes lets you target,\n * say, only install errors — so the exact incompatible step of an install\n * (or uninstall) is easy to spot. Search narrows by event code or message.\n *\n * Server pagination: GET /dsh-plugin-hub/logs?offset=&limit=&category=\n * &level=&query= → { entries, total, hasMore, path }. The footer shows the\n * real file location and reveals it in the system file manager.\n */\nimport { createElement as h, useCallback, useEffect, useRef, useState } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport view from '../../styles/LogsView.module.css'\nimport type { Translate } from '../../types.ts'\nimport { openLogFile } from '../../data/host.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\nimport { ConfirmDialog } from './ConfirmDialog.tsx'\n\n/** 与服务端 /logs 返回的 LogEntry 对齐的客户端投影。 */\nexport interface LogEntryView {\n /** 毫秒时间戳 */\n at: number\n level: 'debug' | 'info' | 'success' | 'warn' | 'error'\n category: 'install' | 'uninstall' | 'update' | 'diagnostics' | 'settings' | 'system'\n /** 机器可读事件码,如 install.start */\n event: string\n message: string\n}\n\nexport type LogCategoryFilter = 'all' | LogEntryView['category']\nexport type LogLevelFilter = 'all' | LogEntryView['level']\n\nconst PAGE = 100\n\n/** 类别筛选标签:值 → 语言包 key(弹窗内 chip 与行内类别徽章共用)。 */\nconst CAT_LABEL: Record<LogEntryView['category'], string> = {\n install: 'logCatInstall',\n uninstall: 'logCatUninstall',\n update: 'logCatUpdate',\n diagnostics: 'logCatDiagnostics',\n settings: 'logCatSettings',\n system: 'logCatSystem',\n}\n\nconst CAT_FILTERS: Array<{ value: LogCategoryFilter; key: string }> = [\n { value: 'all', key: 'logCatAll' },\n { value: 'install', key: 'logCatInstall' },\n { value: 'uninstall', key: 'logCatUninstall' },\n { value: 'update', key: 'logCatUpdate' },\n { value: 'diagnostics', key: 'logCatDiagnostics' },\n { value: 'settings', key: 'logCatSettings' },\n { value: 'system', key: 'logCatSystem' },\n]\n\nconst LEVEL_FILTERS: Array<{ value: LogLevelFilter; key: string }> = [\n { value: 'all', key: 'logLvAll' },\n { value: 'error', key: 'logLvError' },\n { value: 'warn', key: 'logLvWarn' },\n { value: 'success', key: 'logLvSuccess' },\n { value: 'info', key: 'logLvInfo' },\n { value: 'debug', key: 'logLvDebug' },\n]\n\n/** 级别徽章文案:弹窗 chip 与行内级别徽章共用同一语言包 key。 */\nconst LEVEL_LABEL: Record<LogEntryView['level'], string> = {\n debug: 'logLvDebug',\n info: 'logLvInfo',\n success: 'logLvSuccess',\n warn: 'logLvWarn',\n error: 'logLvError',\n}\n\n/** 时间:YYYY-MM-DD HH:mm:ss(每条都精确到秒)。 */\nexport function fmtLogTime(at: number): string {\n const d = new Date(at)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`\n}\n\n/** 导出文件名时间戳:2026-08-24_21-35-00。 */\nfunction fmtFileStamp(at: number): string {\n const d = new Date(at)\n const pad = (n: number) => String(n).padStart(2, '0')\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}_${pad(d.getHours())}-${pad(d.getMinutes())}-${pad(d.getSeconds())}`\n}\n\n/** 单条日志行:时间 + 级别徽章 + 类别徽章 + 事件码 + 描述。查看器弹窗与设置页预览共用。 */\nexport function LogEntryRow({ e, t }: { e: LogEntryView; t: Translate }) {\n return h('div', { className: view.entry, title: e.message },\n h('span', { className: view.time }, fmtLogTime(e.at)),\n h('span', { className: `${view.badge} ${view[`badge${e.level}`]}` }, t(LEVEL_LABEL[e.level])),\n h('span', { className: `${view.catBadge} ${view[`cat${e.category}`]}` }, t(CAT_LABEL[e.category])),\n h('span', { className: view.event }, e.event),\n h('span', { className: view.message }, e.message),\n )\n}\n\nexport function LogsModal({ t, onClose }: {\n t: Translate\n onClose: () => void\n}) {\n const [category, setCategory] = useState<LogCategoryFilter>('all')\n const [level, setLevel] = useState<LogLevelFilter>('all')\n const [query, setQuery] = useState('')\n const [entries, setEntries] = useState<LogEntryView[]>([])\n const [total, setTotal] = useState(0)\n const [hasMore, setHasMore] = useState(false)\n const [path, setPath] = useState('')\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState(false)\n const [opening, setOpening] = useState(false)\n const [openFailed, setOpenFailed] = useState(false)\n const [showClearConfirm, setShowClearConfirm] = useState(false)\n const [clearing, setClearing] = useState(false)\n const [clearFailed, setClearFailed] = useState(false)\n const offsetRef = useRef(0)\n\n /** 拉一页:过滤参数取当前 state,偏移量由调用方给出。 */\n const fetchPage = useCallback(async (offset: number): Promise<{ entries: LogEntryView[]; total: number; hasMore: boolean; path: string } | null> => {\n try {\n const qs = new URLSearchParams({ offset: String(offset), limit: String(PAGE) })\n if (category !== 'all') qs.set('category', category)\n if (level !== 'all') qs.set('level', level)\n const q = query.trim()\n if (q !== '') qs.set('query', q)\n const res = await fetch(`/dsh-plugin-hub/logs?${qs.toString()}`, { cache: 'no-store' })\n if (!res.ok) return null\n return await res.json() as { entries: LogEntryView[]; total: number; hasMore: boolean; path: string }\n } catch {\n return null\n }\n }, [category, level, query])\n\n /** 从第一页重新加载(换筛选/搜索时)。 */\n const reload = useCallback(async () => {\n setLoading(true)\n const data = await fetchPage(0)\n if (data === null) {\n setError(true)\n setLoading(false)\n return\n }\n offsetRef.current = data.entries.length\n setEntries(data.entries)\n setTotal(data.total)\n setHasMore(data.hasMore)\n if (data.path !== '') setPath(data.path)\n setError(false)\n setLoading(false)\n }, [fetchPage])\n\n /** 追加下一页(「加载更多」)。 */\n const loadMore = useCallback(async () => {\n if (loading) return\n setLoading(true)\n const data = await fetchPage(offsetRef.current)\n if (data === null) {\n setError(true)\n setLoading(false)\n return\n }\n offsetRef.current += data.entries.length\n setEntries((prev) => [...prev, ...data.entries])\n setTotal(data.total)\n setHasMore(data.hasMore)\n setLoading(false)\n }, [fetchPage, loading])\n\n // 首次进入 + 类别/级别/搜索变化(搜索 280ms 防抖)都重查第一页\n const first = useRef(true)\n useEffect(() => {\n if (first.current) {\n first.current = false\n void reload()\n return\n }\n const id = window.setTimeout(() => { void reload() }, 280)\n return () => window.clearTimeout(id)\n }, [reload])\n\n /** 在系统文件管理器中定位日志文件(服务端 spawn open)。 */\n const openFile = async () => {\n if (opening) return\n setOpening(true)\n setOpenFailed(false)\n const ok = await openLogFile()\n setOpening(false)\n if (!ok) setOpenFailed(true)\n }\n\n /** 清空所有日志:确认弹窗(独立弹出框,垃圾桶图标)确认后执行。 */\n const doClear = async () => {\n setClearing(true)\n try {\n const res = await fetch('/dsh-plugin-hub/clear-log', { method: 'POST', cache: 'no-store' })\n if (!res.ok) {\n setClearFailed(true)\n return\n }\n await reload()\n } catch {\n setClearFailed(true)\n } finally {\n setClearing(false)\n setShowClearConfirm(false)\n }\n }\n\n /** 导出:拼纯文本 → Blob → 触发浏览器下载 .log 文件 */\n const exportFile = () => {\n const text = entries.map((e) => `[${fmtLogTime(e.at)}] [${e.level}] [${e.category}] [${e.event}] ${e.message}`).join('\\n')\n if (text === '') return\n const blob = new Blob([text], { type: 'text/plain;charset=utf-8' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = `dsh-plugin-hub-log-${fmtFileStamp(Date.now())}.log`\n document.body.appendChild(a)\n a.click()\n a.remove()\n URL.revokeObjectURL(url)\n }\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.errorModal} ${styles.logModal}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('logModalTitle')),\n h('div', { className: view.headActions },\n h('button', {\n type: 'button',\n className: view.clearBtn,\n disabled: clearing,\n title: t('logClearAllTip'),\n onClick: () => setShowClearConfirm(true),\n }, t('logClearAll')),\n ),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n // 类别筛选行:安装/卸载/更新… 功能域区分\n h('div', { className: view.filterBar },\n CAT_FILTERS.map((f) => h('button', {\n key: f.value,\n type: 'button',\n className: category === f.value ? `${view.filterChip} ${view.filterChipActive}` : view.filterChip,\n onClick: () => setCategory(f.value),\n }, t(f.key))),\n ),\n // 级别筛选行 + 搜索框:按级别区分报错与正常,便于针对性排查\n h('div', { className: view.filterBar },\n LEVEL_FILTERS.map((f) => h('button', {\n key: f.value,\n type: 'button',\n className: level === f.value ? `${view.filterChip} ${view.filterChipActive}` : view.filterChip,\n onClick: () => setLevel(f.value),\n }, t(f.key))),\n h('div', { className: view.search },\n h('input', {\n className: view.searchInput,\n type: 'search',\n value: query,\n placeholder: t('logSearchPlaceholder'),\n 'aria-label': t('logSearchPlaceholder'),\n onChange: (e) => setQuery((e.target as HTMLInputElement).value),\n }),\n ),\n ),\n h('div', { className: view.logList },\n error\n ? h('div', { className: view.empty }, t('logsLoadFail'))\n : loading && entries.length === 0\n ? h('div', { className: view.empty }, t('logsLoading'))\n : entries.length === 0\n ? h('div', { className: view.empty }, t('logEmptyFilter'))\n : entries.map((e, i) => h(LogEntryRow, { key: `${e.at}-${i}`, e, t })),\n // 分页:还有就「加载更多」,拉完了给个总数收尾\n entries.length > 0 && (hasMore\n ? h('button', {\n type: 'button',\n className: view.more,\n disabled: loading,\n onClick: () => void loadMore(),\n }, loading ? t('logsLoading') : t('logLoadMore'))\n : h('div', { className: view.moreEnd }, t('logNoMore', { n: total }))),\n ),\n ),\n // 底部:日志真实路径 + 打开文件 / 导出日志\n h('div', { className: view.foot },\n h('span', { className: view.footPath, title: path },\n `${t('logPathLabel')}: ${path === '' ? '…' : path}`),\n clearFailed\n ? h('span', { className: view.footFail }, t('logClearFailed'))\n : openFailed\n ? h('span', { className: view.footFail }, t('logOpenFileFail'))\n : h('span', { className: view.footCount }, t('logCount', { n: total })),\n h('div', { className: view.footActions },\n h('button', {\n type: 'button',\n className: view.btn,\n disabled: opening || path === '',\n title: t('logOpenFileTip'),\n onClick: () => void openFile(),\n }, t('logOpenFile')),\n h('button', {\n type: 'button',\n className: view.btn,\n disabled: entries.length === 0,\n onClick: exportFile,\n }, t('logsExport')),\n ),\n ),\n ),\n // 清空日志确认弹窗:独立弹出框(垃圾桶图标,危险操作),确认后才真正清空\n showClearConfirm && h(ConfirmDialog, {\n type: 'trash',\n title: t('logClearConfirmTitle'),\n desc: t('logClearConfirmDesc'),\n confirmLabel: t('logClearAll'),\n busy: clearing,\n busyLabel: t('logClearing'),\n t,\n onConfirm: () => void doClear(),\n onCancel: () => setShowClearConfirm(false),\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 日志存放位置弹窗:设置页不内联长表单(挡视线),点「修改」弹窗编辑。\n * 两种输入方式并存 —— 手输目录 / .log 文件路径,或点「选择目录」调系统\n * 原生文件夹对话框(服务端 spawn osascript / FolderBrowserDialog / zenity)。\n * 文本框预填当前生效位置,目录选择器也从该位置打开 —— 默认地址是动态的\n * (随用户主目录/平台变化,如 ~/.dsh/profiles/<profile>/hub.log),必须实时展示。\n * 留空或点「恢复默认」= 回到默认;保存前服务端预验证可写。\n */\nimport { createElement as h, useEffect, useState } from 'react'\nimport styles from '../../styles/Modal.module.css'\nimport view from '../../styles/LogsView.module.css'\nimport type { Translate } from '../../types.ts'\nimport { chooseLogDir } from '../../data/host.ts'\nimport { CloseIcon } from '../ui/icons.tsx'\n\nexport function LogsPathModal({ t, defaultPath, currentPath, onSaved, onClose }: {\n t: Translate\n /** 真正默认位置(服务端动态算出的 ~/.dsh/profiles/<profile>/hub.log),跨机器/平台不同 */\n defaultPath: string\n /** 当前生效的真实路径(可能已被自定义覆盖) */\n currentPath: string\n /** 保存成功回调(写入设置;父级据此刷新生效路径与日志列表) */\n onSaved: (value: string) => void\n onClose: () => void\n}) {\n // 打开即显示当前生效位置 —— 用户一眼看到日志现在存在哪,也方便在此基础上微调\n const [draft, setDraft] = useState(currentPath)\n const [saving, setSaving] = useState(false)\n const [fail, setFail] = useState(false)\n const [browsing, setBrowsing] = useState(false)\n const [browseFail, setBrowseFail] = useState(false)\n\n // Esc 关闭:与其它弹窗交互一致\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose() }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [onClose])\n\n /** 保存:空串 = 回默认;填回默认位置同样按「未自定义」处理(设置里保持干净)。\n * 服务端预建目录验证可写,失败给出反馈。 */\n const save = async () => {\n if (saving) return\n setSaving(true)\n setFail(false)\n try {\n const value = draft.trim()\n const normalized = value === '' || value === defaultPath ? '' : value\n const res = await fetch('/dsh-plugin-hub/settings', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ logPath: normalized }),\n cache: 'no-store',\n })\n if (!res.ok) {\n setFail(true)\n return\n }\n // 保存成功即关:主界面路径行随即刷新为新位置,本身就是反馈\n onSaved(normalized)\n onClose()\n } catch {\n setFail(true)\n } finally {\n setSaving(false)\n }\n }\n\n /** 选择目录:系统对话框从默认位置打开,选中路径回填输入框(仍可手改)。 */\n const browse = async () => {\n if (browsing) return\n setBrowsing(true)\n setBrowseFail(false)\n const picked = await chooseLogDir()\n setBrowsing(false)\n if (picked !== null) {\n setDraft(picked)\n setFail(false)\n } else {\n setBrowseFail(true)\n }\n }\n\n return h('div', {\n className: styles.overlay,\n onClick: (e: { target: unknown; currentTarget: unknown }) => {\n if (e.target === e.currentTarget) onClose()\n },\n },\n h('div', { className: `${styles.modal} ${styles.modalWide}`, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: styles.modalHead },\n h('div', { className: styles.modalTitle }, t('logPathSettingTitle')),\n h('button', {\n className: styles.modalClose,\n 'aria-label': t('errorClose'),\n onClick: onClose,\n }, h(CloseIcon)),\n ),\n h('div', { className: styles.modalBody },\n h('div', { className: view.pathDialog },\n h('div', { className: view.pathDialogDesc }, t('logPathSettingDesc')),\n // 手输路径 + 系统目录选择器两条路并行\n h('div', { className: view.pathDialogRow },\n h('input', {\n type: 'text',\n className: view.pathDraft,\n value: draft,\n placeholder: t('logPathPlaceholder'),\n spellCheck: false,\n onChange: (e: { currentTarget: HTMLInputElement }) => {\n setDraft(e.currentTarget.value)\n setFail(false)\n setBrowseFail(false)\n },\n }),\n h('button', {\n type: 'button',\n className: view.btn,\n disabled: browsing,\n title: t('logPathBrowse'),\n onClick: () => void browse(),\n }, browsing ? t('logPathSaving') : t('logPathBrowse')),\n ),\n // 提示 + 「恢复默认」:提示左、动作右,一行内不挤\n h('div', { className: view.pathDialogReset },\n h('span', { className: view.pathDialogHint }, t('logPathResetHint')),\n h('button', {\n type: 'button',\n className: view.linkBtn,\n onClick: () => {\n setDraft(defaultPath)\n setFail(false)\n setBrowseFail(false)\n },\n }, t('logPathReset')),\n ),\n browseFail && h('div', { className: view.footFail }, t('logPathBrowseFail')),\n fail && h('div', { className: view.footFail }, t('logPathSaveFail')),\n h('div', { className: view.pathDialogFoot },\n h('button', {\n type: 'button',\n className: view.btn,\n disabled: saving,\n onClick: onClose,\n }, t('confirmCancel')),\n h('button', {\n type: 'button',\n className: `${view.btn} ${view.btnPrimary}`,\n disabled: saving,\n onClick: () => void save(),\n }, saving ? t('logPathSaving') : t('logPathSave')),\n ),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * 系统日志入口视图:不在这里堆全文,而是给出「打开日志查看器」窗口入口 +\n * 日志文件真实路径(可一键在系统文件管理器中定位)+ 最近若干条预览。\n * 完整阅读/筛选/分页在 LogsModal 内置查看器弹窗里完成 —— 无需借助任何\n * 外部软件,点击即弹出自己的窗口加载本地 JSONL 日志。\n */\nimport { createElement as h, useCallback, useEffect, useRef, useState } from 'react'\nimport styles from '../../styles/LogsView.module.css'\nimport type { Translate } from '../../types.ts'\nimport { openLogFile } from '../../data/host.ts'\nimport { LogsModal, LogEntryRow, fmtLogTime, type LogEntryView } from '../modals/LogsModal.tsx'\nimport { LogsPathModal } from '../modals/LogsPathModal.tsx'\n\n/** 设置页预览条数:只放最近一小段,给用户快速感观,完整内容进查看器。 */\nconst PREVIEW = 12\n\nexport function LogsView({ t, logPath, onLogPathSaved }: {\n t: Translate\n /** 设置里已保存的日志位置覆盖(空串 = 默认位置) */\n logPath: string\n /** 保存自定义日志位置(写入设置,服务端同时预建目录验证可写) */\n onLogPathSaved: (value: string) => void\n}) {\n const [entries, setEntries] = useState<LogEntryView[]>([])\n const [path, setPath] = useState('')\n // 真正默认位置(~/.dsh/profiles/<profile>/hub.log,跨机器/平台动态):弹窗「恢复默认」用\n const [defaultPath, setDefaultPath] = useState('')\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState(false)\n const [open, setOpen] = useState(false)\n const [opening, setOpening] = useState(false)\n const [openFailed, setOpenFailed] = useState(false)\n // 日志存放位置弹窗:点「修改」打开,手输或选目录\n const [showPathModal, setShowPathModal] = useState(false)\n const mountedRef = useRef(true)\n\n const load = useCallback(async () => {\n setLoading(true)\n try {\n const res = await fetch('/dsh-plugin-hub/logs', { cache: 'no-store' })\n if (!res.ok) throw new Error(`http ${res.status}`)\n const data = await res.json() as { entries: LogEntryView[]; path: string; defaultPath?: string }\n if (mountedRef.current) {\n setEntries(data.entries)\n if (data.path !== '') setPath(data.path)\n if (data.defaultPath !== undefined) setDefaultPath(data.defaultPath)\n setError(false)\n }\n } catch {\n if (mountedRef.current) setError(true)\n } finally {\n if (mountedRef.current) setLoading(false)\n }\n }, [])\n\n useEffect(() => {\n mountedRef.current = true\n void load()\n return () => { mountedRef.current = false }\n }, [load])\n\n /** 导出:拼纯文本 → Blob → 触发浏览器下载 .log 文件 */\n const exportFile = () => {\n const text = entries.map((e) => `[${fmtLogTime(e.at)}] [${e.level}] [${e.category}] [${e.event}] ${e.message}`).join('\\n')\n if (text === '') return\n const blob = new Blob([text], { type: 'text/plain;charset=utf-8' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'dsh-plugin-hub-log.log'\n document.body.appendChild(a)\n a.click()\n a.remove()\n URL.revokeObjectURL(url)\n }\n\n /** 在系统文件管理器中定位日志文件。 */\n const openFile = async () => {\n if (opening) return\n setOpening(true)\n setOpenFailed(false)\n const ok = await openLogFile()\n setOpening(false)\n if (!ok) setOpenFailed(true)\n }\n\n const preview = entries.slice(0, PREVIEW)\n return h('div', { className: styles.panel },\n h('div', { className: styles.head },\n h('span', { className: styles.headHint }, t('logsHeadHint')),\n h('div', { className: styles.actions },\n h('button', {\n type: 'button',\n className: styles.btn,\n onClick: () => setOpen(true),\n }, t('logViewerOpen')),\n h('button', { type: 'button', className: styles.btn, disabled: entries.length === 0, onClick: exportFile }, t('logsExport')),\n h('button', { type: 'button', className: styles.btn, disabled: loading, onClick: () => void load() }, t('logsRefresh')),\n ),\n ),\n // 日志存放位置:一行展示真实路径 + 「修改」弹窗编辑(手输 / 选目录)+ 一键定位文件\n h('div', { className: styles.pathRow },\n h('span', { className: styles.pathLabel }, t('logPathSettingTitle')),\n h('span', { className: styles.pathText, title: path }, path === '' ? '…' : path),\n openFailed && h('span', { className: styles.footFail }, t('logOpenFileFail')),\n h('button', {\n type: 'button',\n className: styles.btn,\n onClick: () => setShowPathModal(true),\n }, t('logPathChange')),\n h('button', {\n type: 'button',\n className: styles.btn,\n disabled: opening || path === '',\n title: t('logOpenFileTip'),\n onClick: () => void openFile(),\n }, t('logOpenFile')),\n ),\n error\n ? h('div', { className: styles.empty }, t('logsLoadFail'))\n : loading && entries.length === 0\n ? h('div', { className: styles.empty }, t('logsLoading'))\n : entries.length === 0\n ? h('div', { className: styles.empty }, t('logsEmpty'))\n : h('div', { className: styles.list },\n preview.map((e, i) => h('button', {\n key: `${e.at}-${i}`,\n type: 'button',\n className: styles.previewRow,\n onClick: () => setOpen(true),\n title: t('logViewerOpen'),\n }, h(LogEntryRow, { e, t }))),\n ),\n open && h(LogsModal, { t, onClose: () => setOpen(false) }),\n showPathModal && h(LogsPathModal, {\n t,\n defaultPath,\n currentPath: path,\n onSaved: (v: string) => {\n onLogPathSaved(v)\n void load() // 刷新生效路径与最近日志(新位置若已写入则立即可见)\n },\n onClose: () => setShowPathModal(false),\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Settings view: desktop-settings navigation — a fixed left sidebar lists\n * the sections (icon + label, click to switch), the right pane shows the\n * active section's rows. New settings only add rows, new areas only add a\n * sidebar entry.\n *\n * Sections mirror what the local server actually enforces:\n * Updates & Sources — startup update check / npm mirror / HTTP proxy\n * (all wired into the install command path)\n * Security & Trust — restricted custom installs (server 403 gate)\n * Diagnostics — live connectivity probe + environment snapshot\n * Logs — system log viewer + storage location\n */\nimport { createElement as h, useEffect, useRef, useState } from 'react'\nimport type { ChangeEvent, MouseEvent, ReactNode } from 'react'\nimport styles from '../../styles/SettingsView.module.css'\nimport dropdownStyles from '../../styles/Dropdown.module.css'\nimport modalStyles from '../../styles/Modal.module.css'\nimport { Toggle } from '../ui/Toggle.tsx'\nimport { Dropdown } from '../ui/Dropdown.tsx'\nimport { DiagnosticsView } from './DiagnosticsView.tsx'\nimport { LogsView } from './LogsView.tsx'\nimport {\n CloseIcon, ConfirmIcon, DiagnosticsIcon, LogsIcon, ResetIcon, SecurityIcon, UpdatesIcon,\n} from '../ui/icons.tsx'\nimport type { EnvInfo, Translate } from '../../types.ts'\nimport type { HubSettings } from '../../hooks/useSettings.ts'\n\n/** 设置分组导航 key:顺序即展示顺序。导出供外部(如错误弹窗「去系统诊断」)跳转指定分组。 */\nexport type SettingsSection = 'updates' | 'security' | 'diagnostics' | 'logs' | 'reset'\n\n/** npm 镜像源预设:空串 = 未配置(跟随用户本机 npm 配置,本插件不注入任何 registry)。\n * 只提供常见国内顶级镜像下拉,不做自定义输入 —— 想用其它镜像直接在 ~/.npmrc 配置即可。 */\nconst MIRROR_PRESETS: Array<{ value: string; labelKey: string }> = [\n { value: '', labelKey: 'mirrorNone' },\n { value: 'https://registry.npmjs.org', labelKey: 'mirrorOfficial' },\n { value: 'https://registry.npmmirror.com', labelKey: 'mirrorNpmmirror' },\n { value: 'https://mirrors.cloud.tencent.com/npm/', labelKey: 'mirrorTencent' },\n { value: 'https://mirrors.tuna.tsinghua.edu.cn/npm/', labelKey: 'mirrorTsinghua' },\n]\n\n/** 左侧导航:顺序即展示顺序;labelKey 是分组标题,icon 是行内小图标。 */\nconst NAV: Array<{ key: SettingsSection; labelKey: string; icon: () => ReturnType<typeof h> }> = [\n { key: 'updates', labelKey: 'settingsUpdate', icon: UpdatesIcon },\n { key: 'security', labelKey: 'settingsSecurity', icon: SecurityIcon },\n { key: 'diagnostics', labelKey: 'settingsDiagnostics', icon: DiagnosticsIcon },\n { key: 'logs', labelKey: 'settingsLogs', icon: LogsIcon },\n { key: 'reset', labelKey: 'settingsReset', icon: ResetIcon },\n]\n\n/** 设置行:默认标签左控件右;stack=true 时控件独占一行(文本框整行显示),hairline 分隔。 */\nfunction SettingRow({ title, desc, children, stack = false }: {\n title: string\n desc?: string\n children: ReactNode\n stack?: boolean\n}) {\n return h('div', { className: stack ? styles.settingRowStack : styles.settingRow },\n h('div', { className: styles.settingLabel },\n h('div', { className: styles.settingTitle }, title),\n desc ? h('div', { className: styles.settingDesc }, desc) : null,\n ),\n h('div', { className: stack ? styles.settingControlStack : styles.settingControl }, children),\n )\n}\n\nexport function SettingsView({ t, settings, update, reset, env, onCopy, openSection, onConsumedOpenSection }: {\n t: Translate\n settings: HubSettings\n update: (patch: Partial<HubSettings>) => void\n reset: () => void\n env: EnvInfo | null\n onCopy: (text: string) => void\n /** 外部跳转信号(如错误弹窗「去系统诊断」):非空时切到对应分组,消费后通过 onConsumedOpenSection 清空 */\n openSection?: SettingsSection | null\n onConsumedOpenSection?: () => void\n}) {\n /** 当前激活的分组:左侧导航点击切换,右侧只渲染这一组 */\n const [section, setSection] = useState<SettingsSection>('updates')\n /** 恢复默认确认弹窗:点按钮先弹窗询问,确认后才真正 reset(不做两段式按钮) */\n const [resetConfirm, setResetConfirm] = useState(false)\n\n // 外部跳转(错误弹窗「去系统诊断」→ 设置 → 系统诊断):切到对应分组并清空信号,避免下次进入设置被强制带跳\n useEffect(() => {\n if (!openSection) return\n setSection(openSection)\n onConsumedOpenSection?.()\n }, [openSection, onConsumedOpenSection])\n\n // —— HTTP 代理连通性:输入停笔后防抖实时探测(服务端 /proxy-check 用该代理打 github.com)。\n // 结果只作提示、绝不阻断保存 —— 用户可能是先填地址后开代理,保存后再去开代理完全合法。\n const [proxyProbe, setProxyProbe] = useState<'idle' | 'checking' | 'ok' | 'fail'>('idle')\n // 失败细分原因(如 'tlsRevocation'):证书吊销受阻时提示「不是代理地址不通」,避免误导排查方向\n const [proxyProbeReason, setProxyProbeReason] = useState<string | null>(null)\n const proxyProbeTimer = useRef<number | null>(null)\n const proxyProbeSeq = useRef(0)\n // 卸载时清掉未触发的防抖计时器,避免卸载后 setState\n useEffect(() => () => {\n if (proxyProbeTimer.current !== null) window.clearTimeout(proxyProbeTimer.current)\n proxyProbeSeq.current += 1\n }, [])\n // 设置被外部重置(恢复默认/清空代理)时同步清掉探测状态,避免残留过期的「不通」提示\n useEffect(() => {\n if (settings.proxy === '') { setProxyProbe('idle'); setProxyProbeReason(null) }\n }, [settings.proxy])\n\n const probeProxyNow = (value: string) => {\n const v = value.trim()\n if (v === '') { setProxyProbe('idle'); setProxyProbeReason(null); return }\n const seq = ++proxyProbeSeq.current\n setProxyProbe('checking')\n setProxyProbeReason(null)\n void fetch('/dsh-plugin-hub/proxy-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ proxy: v }),\n cache: 'no-store',\n }).then((res) => res.json())\n .then((data: { ok?: boolean; reason?: string | null }) => {\n if (seq !== proxyProbeSeq.current) return\n setProxyProbe(data.ok ? 'ok' : 'fail')\n setProxyProbeReason(typeof data.reason === 'string' ? data.reason : null)\n })\n .catch(() => {\n if (seq !== proxyProbeSeq.current) return\n setProxyProbe('fail')\n setProxyProbeReason(null)\n })\n }\n\n const onProxyChange = (e: ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value\n // 保存照常:留空直连、填了就走该代理(先填后开代理也允许,仅提示不通)\n update({ proxy: value })\n if (proxyProbeTimer.current !== null) window.clearTimeout(proxyProbeTimer.current)\n // 停笔 700ms 再探测,避免每敲一个字符都发请求\n proxyProbeTimer.current = window.setTimeout(() => probeProxyNow(value), 700)\n }\n const onMirrorChange = (value: string) => update({ npmRegistry: value })\n\n /** 每个分组的页面副标题(导航标题之上再补一句说明,保持桌面设置质感) */\n const pageDesc: Record<SettingsSection, string> = {\n updates: t('settingsUpdateDesc'),\n security: t('settingsSecurityDesc'),\n diagnostics: t('settingsDiagnosticsDesc'),\n logs: t('settingsLogsDesc'),\n reset: t('settingsResetDesc'),\n }\n const activeNav = NAV.find((n) => n.key === section) ?? NAV[0]\n\n // —— 各分组的设置卡片(一页一个 card,内部一行一设置) ——\n\n const updatesCard = h('div', { className: styles.card },\n h(SettingRow, {\n title: t('settingsCheckOnStart'),\n desc: t('settingsCheckOnStartDesc'),\n children: h(Toggle, {\n checked: settings.checkUpdatesOnStart,\n onChange: (v) => update({ checkUpdatesOnStart: v }),\n title: t('settingsCheckOnStart'),\n }),\n }),\n // npm 镜像源:预设下拉(默认未配置跟随本机),选国内顶级镜像可加速安装;\n // 不做自定义输入,其它镜像写在 ~/.npmrc 即可被天然尊重。\n // 独占一行(同代理文本框):标签在上、下拉在下整行展开,长描述不会挤压控件\n h(SettingRow, {\n title: t('settingsMirror'),\n desc: t('settingsMirrorDesc'),\n stack: true,\n children: h(Dropdown, {\n value: settings.npmRegistry,\n options: MIRROR_PRESETS.map((m) => ({ value: m.value, label: t(m.labelKey) })),\n onChange: onMirrorChange,\n title: t('settingsMirror'),\n className: `${styles.controlDropdown} ${dropdownStyles.dropdownFill}`,\n }),\n }),\n // 代理地址:文本框独占一行,整行输入,便于粘贴长代理地址;停笔后实时探测连通性,\n // 不通仅提示(可保存)—— 用户可能先填地址后开代理\n h(SettingRow, {\n title: t('settingsProxy'),\n desc: t('settingsProxyDesc'),\n stack: true,\n children: h('div', { className: styles.proxyControl },\n h('input', {\n className: styles.textInput,\n type: 'text',\n value: settings.proxy,\n placeholder: 'http://127.0.0.1:7890',\n spellCheck: false,\n onChange: onProxyChange,\n }),\n proxyProbe === 'checking'\n ? h('div', { className: styles.proxyHint }, t('proxyCheckChecking'))\n : proxyProbe === 'ok'\n ? h('div', { className: `${styles.proxyHint} ${styles.proxyHintOk}` }, t('proxyCheckOk'))\n : proxyProbe === 'fail'\n ? h('div', { className: `${styles.proxyHint} ${styles.proxyHintFail}` },\n proxyProbeReason === 'tlsRevocation' ? t('proxyCheckRevocation') : t('proxyCheckFail'))\n : null,\n ),\n }),\n )\n\n const securityCard = h('div', { className: styles.card },\n // 安全与信任:命令行安装的三个通道开关(NPM 包 / GitHub 源码 / DSH 命令)——\n // 服务端按通道门禁 403 拦截(npm 目标吃 enableNpmInstall、git 目标吃 enableGitInstall),\n // DSH 命令框为纯客户端通道:关掉后命令输入卡片禁用并引导去设置打开;\n // 目录内收录的插件安装不受影响(默认全部开启)\n h(SettingRow, {\n title: t('settingsEnableNpm'),\n desc: t('settingsEnableNpmDesc'),\n children: h(Toggle, {\n checked: settings.enableNpmInstall,\n onChange: (v) => update({ enableNpmInstall: v }),\n title: t('settingsEnableNpm'),\n }),\n }),\n h(SettingRow, {\n title: t('settingsEnableGit'),\n desc: t('settingsEnableGitDesc'),\n children: h(Toggle, {\n checked: settings.enableGitInstall,\n onChange: (v) => update({ enableGitInstall: v }),\n title: t('settingsEnableGit'),\n }),\n }),\n h(SettingRow, {\n title: t('settingsEnableDsh'),\n desc: t('settingsEnableDshDesc'),\n children: h(Toggle, {\n checked: settings.enableDshInstall,\n onChange: (v) => update({ enableDshInstall: v }),\n title: t('settingsEnableDsh'),\n }),\n }),\n )\n\n const diagnosticsCard = h('div', { className: styles.card },\n // 系统版本(最顶部)+ 通道状态列表:进入页面自动探测一轮,整行可点击重测单项,实时反馈\n h(DiagnosticsView, { t, env, proxy: settings.proxy, onCopy }),\n )\n\n const logsCard = h('div', { className: styles.card },\n // 系统日志列表:操作记录(安装/卸载/设置/诊断),可刷新/复制/导出,点击弹窗查看;\n // 日志存放位置可设置(留空用默认),改动会写入设置并立即生效\n h(LogsView, {\n t,\n logPath: settings.logPath,\n onLogPathSaved: (v: string) => update({ logPath: v }),\n }),\n )\n\n const resetCard = h('div', { className: styles.card },\n h(SettingRow, {\n title: t('settingsReset'),\n desc: t('settingsResetDetail'),\n children: h('button', {\n type: 'button',\n className: styles.resetBtn,\n onClick: () => setResetConfirm(true),\n }, t('settingsResetRun')),\n }),\n )\n\n return h('div', { className: styles.root },\n // 左侧导航:固定宽度菜单栏,图标 + 名称,点击切换右侧内容\n h('nav', { className: styles.sidebar, 'aria-label': t('viewSettings') },\n NAV.map((item) => h('button', {\n key: item.key,\n type: 'button',\n className: section === item.key ? styles.navItemActive : styles.navItem,\n onClick: () => setSection(item.key),\n 'aria-current': section === item.key ? 'page' : undefined,\n title: t(item.labelKey),\n },\n h('span', { className: styles.navIcon }, h(item.icon)),\n h('span', { className: styles.navLabel }, t(item.labelKey)),\n )),\n ),\n // 右侧内容:只渲染当前分组,独立滚动\n h('div', { className: styles.content },\n h('div', { className: styles.pageHeader },\n h('div', { className: styles.pageTitle }, t(activeNav.labelKey)),\n h('div', { className: styles.pageDesc }, pageDesc[section]),\n ),\n section === 'updates' ? updatesCard\n : section === 'security' ? securityCard\n : section === 'diagnostics' ? diagnosticsCard\n : section === 'logs' ? logsCard\n : resetCard,\n ),\n // 恢复默认确认弹窗:点「恢复默认」先弹窗确认,确认后才真正 reset(替代两段式按钮)\n resetConfirm && h('div', {\n className: modalStyles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) setResetConfirm(false) },\n },\n h('div', { className: modalStyles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: modalStyles.modalHead },\n h('div', { className: modalStyles.modalTitle }, t('settingsReset')),\n h('button', {\n className: modalStyles.modalClose,\n type: 'button',\n 'aria-label': t('errorClose'),\n onClick: () => setResetConfirm(false),\n }, h(CloseIcon)),\n ),\n h('div', { className: modalStyles.modalBody },\n // 恢复默认 = 破坏性操作:红色警告三角图标,醒目提示风险\n h('div', { className: modalStyles.confirmIconWrap },\n h(ConfirmIcon, { type: 'warning' }),\n ),\n h('div', { className: modalStyles.failPrepareHint }, t('settingsResetConfirmDetail')),\n h('div', { className: modalStyles.modalActions },\n h('button', {\n className: modalStyles.restartLater,\n type: 'button',\n onClick: () => setResetConfirm(false),\n }, t('cancel')),\n h('button', {\n className: modalStyles.restartNowWarning,\n type: 'button',\n onClick: () => { setResetConfirm(false); reset() },\n }, t('settingsResetConfirm')),\n ),\n ),\n ),\n ),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * Plugin Hub section: wires the catalog data pipeline, the background task\n * queue and the feedback state together. Data/queue logic lives in hooks/,\n * rendering is delegated to the small presentational components in this\n * folder; it hosts the dialogs/toast and the section-level copy actions.\n */\nimport { createElement as h, useEffect, useRef, useState } from 'react'\nimport type { MouseEvent } from 'react'\nimport styles from '../styles/Header.module.css'\nimport modalStyles from '../styles/Modal.module.css'\nimport type { EnvInfo, HubPlugin, InstallChannel, SectionProps, ToastState } from '../types.ts'\nimport { installCommandOf, repoFromInstallTarget } from '../logic/install-command.ts'\nimport { PLUGIN_VERSION } from '../logic/constants.ts'\nimport { ensurePluginCss } from '../logic/ensure-plugin-css.ts'\nimport { getEnv, revealInstallFolder } from '../data/host.ts'\nimport { useCatalog } from '../hooks/useCatalog.ts'\nimport { useLanguage } from '../hooks/useLanguage.ts'\nimport { useSettings } from '../hooks/useSettings.ts'\nimport { useTaskQueue } from '../hooks/useTaskQueue.ts'\nimport { ErrorModal, InstallModal, RestartConfirmModal, UninstallModal, Toast } from './modals/modals.tsx'\nimport { AboutModal } from './modals/AboutModal.tsx'\nimport { HubUpdateModal } from './modals/HubUpdateModal.tsx'\nimport { InstalledDetailModal } from './modals/InstalledDetailModal.tsx'\nimport { NotificationsModal } from './modals/NotificationsModal.tsx'\nimport { addFailure, addSuccess, addUpdateNotice, clearNotifications, ignoreUpdate, loadIgnoredUpdates, loadNotifications, removeNotification, removeUpdateNotice } from '../logic/failures.ts'\nimport type { NotificationRecord } from '../logic/failures.ts'\nimport { CatalogHeader } from './layout/CatalogHeader.tsx'\nimport { MarketView } from './views/MarketView.tsx'\nimport { SectionTabs } from './layout/SectionTabs.tsx'\nimport type { SectionView } from './layout/SectionTabs.tsx'\nimport { InstalledView } from './views/InstalledView.tsx'\nimport { CustomInstallView } from './views/CustomInstallView.tsx'\nimport { SettingsView } from './views/SettingsView.tsx'\nimport type { SettingsSection } from './views/SettingsView.tsx'\nimport { CloseIcon, ConfirmIcon } from './ui/icons.tsx'\nimport type { InstalledItem } from '../logic/installed.ts'\nimport { issueRepoOf, pluginOfItem } from '../logic/installed.ts'\n\nexport function PluginHubSection({ t: _hostT, locale }: SectionProps) {\n const { lang, langKey, langPath, t, toggleLang } = useLanguage(locale)\n const catalog = useCatalog(lang)\n /** 设置状态:服务端 hub-settings.json 持久化,本地乐观更新即时生效 */\n const { settings: hubSettings, ready: settingsReady, update: updateSettings, reset: resetSettings } = useSettings()\n\n /** 一级导航:插件市场 / 已安装 / 自定义安装 / 设置 */\n const [view, setView] = useState<SectionView>('market')\n /** 外部跳转设置分组的一次性信号(错误弹窗「去系统诊断」→ 设置 → 系统诊断):\n * 传给 SettingsView 消费后即清空,避免下次进设置被强制带跳 */\n const [settingsSection, setSettingsSection] = useState<SettingsSection | null>(null)\n /** 网络不通提示的「去系统诊断」直达:关掉所有弹窗(错误/通知/安装确认进度等,\n * 否则 InstallModal 失败后仍停驻原地盖住设置页)→ 切到设置页 → 切到系统诊断分组(自动跑连通性检测) */\n const openDiagnostics = () => {\n setErrorMsg(null)\n setShowNotifications(false)\n setConfirmPlugin(null)\n setConfirmCustomTarget(null)\n setConfirmGlobalNpm(null)\n setUninstallPlugin(null)\n setUninstallItem(null)\n setDetailItem(null)\n setShowHubUpdate(false)\n setShowAbout(false)\n setIgnoreTarget(null)\n setShowRestartConfirm(false)\n setView('settings')\n setSettingsSection('diagnostics')\n }\n\n /** 全局反馈 Toast:{id} 用于重复触发时重新走入场动画,kind 决定文案与配色 */\n const [toast, setToast] = useState<ToastState | null>(null)\n /** 复制反馈:记录刚复制安装命令的仓库,按钮短暂切换为「已复制」样式 */\n const [copied, setCopied] = useState<string | null>(null)\n /** 信任确认弹窗:记录待安装的插件,确认后才执行复制 */\n const [confirmPlugin, setConfirmPlugin] = useState<HubPlugin | null>(null)\n /** 弹窗动作是否为「更新」:已安装插件点「更新」→ 走同一条 add 命令原位覆盖重装,文案区分安装/更新 */\n const [confirmIsUpdate, setConfirmIsUpdate] = useState(false)\n /** 命令行安装确认弹窗:记录待安装的裸目标(npm 包名 / GitHub 地址,DSH 命令已剥成裸目标)——\n * 与应用商店同一套确认/进度/结果弹窗,提供时 plugin 传 null 走 customTarget 模式 */\n const [confirmCustomTarget, setConfirmCustomTarget] = useState<string | null>(null)\n /** 自定义安装入口渠道(三张卡片之一):随确认弹窗记录,提交时上报服务端,\n * 报错/日志据此精准溯源「从哪个入口发起」(npm 全局安装固定为 'npm') */\n const [confirmCustomChannel, setConfirmCustomChannel] = useState<InstallChannel | null>(null)\n /** 全局 npm 安装确认弹窗(官方 `npm install -g <pkgs>`):记录原始命令 + 解析出的包列表,\n * 走与应用商店同一套确认/进度/结果弹窗(plugin 传 null,InstallModal 走 globalNpm 模式) */\n const [confirmGlobalNpm, setConfirmGlobalNpm] = useState<{ raw: string; pkgs: string[] } | null>(null)\n /** Hub 自我更新说明弹窗:点「可更新」徽标先展示版本 + Markdown 变更记录,确认后再进安装弹窗 */\n const [showHubUpdate, setShowHubUpdate] = useState(false)\n /** 「关注我们」弹窗:GitHub 图标后按钮点击打开,展示平台介绍 + 用户反馈群二维码(Worker /about 推送) */\n const [showAbout, setShowAbout] = useState(false)\n /** 卸载确认弹窗:记录待卸载的插件(目录内) */\n const [uninstallPlugin, setUninstallPlugin] = useState<HubPlugin | null>(null)\n /** 卸载确认弹窗:记录待卸载的已安装项(自定义安装无目录数据,按包名直卸) */\n const [uninstallItem, setUninstallItem] = useState<InstalledItem | null>(null)\n /** 已安装详情弹窗:记录当前查看的已安装项(行点击 / 详情按钮打开) */\n const [detailItem, setDetailItem] = useState<InstalledItem | null>(null)\n /** 待重启确认弹窗:已安装列表行内「重启」先弹「立即重启 / 稍后重启」确认(与通知中心一致),\n * 确认后才真正触发宿主重启,避免误触 */\n const [showRestartConfirm, setShowRestartConfirm] = useState(false)\n /** 安装/卸载完成后的结果视图:停留弹窗内,点「完成」关闭 */\n const [installDone, setInstallDone] = useState(false)\n const [uninstallDone, setUninstallDone] = useState(false)\n /** 结果视图是否给「立即重启」:服务端任务终态带出。仅刷新解决不了的兜底场景\n * (热挂载失败 / 非 dsh 插件 / 更新)为 true;其余(热挂载成功、卸载已即时停用)为 false,\n * 结果视图只给「完成」,关闭时自动刷新页面生效 */\n const [installNeedsRestart, setInstallNeedsRestart] = useState(false)\n const [uninstallNeedsRestart, setUninstallNeedsRestart] = useState(false)\n /** 结果视图是否显示「关闭后自动刷新」说明:插件已热挂进运行中 loader(安装)、或卸载后\n * 插件面板仍残留在当前页面(卸载)。关闭弹窗即整页刷新,不给手动刷新按钮。 */\n const [installNeedsReload, setInstallNeedsReload] = useState(false)\n const [uninstallNeedsReload, setUninstallNeedsReload] = useState(false)\n /** 结果视图「立即重启」:请求宿主重启后进入等待,服务回来后整页刷新 */\n const [restarting, setRestarting] = useState(false)\n /** 操作失败完整信息 + 所属插件仓库 + 失败类型(决定弹窗标题「安装失败/卸载失败」)+ 实际执行的安装命令 + 尝试过的安装方式(issue 预填用) */\n const [errorMsg, setErrorMsg] = useState<{ message: string; repo: string | null; kind: 'install' | 'uninstall'; command?: string; attempts?: string[] } | null>(null)\n /** 通知中心记录:localStorage 持久化,每次安装/卸载任务成败都留痕(启动时读回) */\n const [notifications, setNotifications] = useState<NotificationRecord[]>(() => loadNotifications())\n /** 通知中心弹窗:一级导航「设置」tab 后边的铃铛入口按钮打开 */\n const [showNotifications, setShowNotifications] = useState(false)\n /** 「忽略本次更新」确认弹窗:{ repo, version };null = 关闭 */\n const [ignoreTarget, setIgnoreTarget] = useState<{ repo: string; version?: string } | null>(null)\n /** 宿主机器环境快照:提交 bug 的 issue 正文附带;取不到为 null(链接少环境段,不阻塞) */\n const [env, setEnv] = useState<EnvInfo | null>(null)\n useEffect(() => {\n let alive = true\n void getEnv().then((info) => { if (alive) setEnv(info) })\n return () => { alive = false }\n }, [])\n\n // 样式自愈:宿主重启/热更可能移除 <style> 标签而模块缓存未失效(factory 不重跑、CSS 不回来)。\n // 挂载与每次切换视图时比对全局 CSS 清单,把缺失的样式补注入回去 —— 用户无需再手动点击恢复。\n useEffect(() => { ensurePluginCss() }, [view])\n\n /** 后台任务(弹窗已关)完成且只需刷新页面即生效时,等结果 Toast 读完再整页刷新:\n * 新插件(或卸载后残留)的客户端资源要重新加载页面才会生效,无需重启宿主。 */\n const scheduleAutoReload = () => {\n window.setTimeout(() => window.location.reload(), 1600)\n }\n\n const queue = useTaskQueue({\n t,\n // 界面语言带给服务端:网络预检等错误消息按用户语言提示(中文界面给中文,英文界面给英文)\n langKey,\n refreshInstalled: catalog.refreshInstalled,\n onInstallDone: (viaModal, repo, needsRestart, update, needsReload) => {\n const reload = needsReload === true\n setInstallNeedsRestart(needsRestart)\n setInstallNeedsReload(reload)\n if (viaModal) setInstallDone(true)\n // 弹窗外的后台安装:给结果 toast;需要页面重载时(热挂载的客户端 UI)读完后自动刷新\n else setToast({\n id: Date.now(),\n kind: reload ? 'installedReload' : needsRestart ? 'done' : 'installedLive',\n })\n if (!viaModal && reload) scheduleAutoReload()\n // 安装成功也写入通知记录:通知中心里成功与失败都能看到。\n // action 区分「安装成功」与「更新成功」(更新 = 覆盖重装,同一执行通道)\n setNotifications(addSuccess({ kind: 'install', action: update ? 'update' : 'install', repo: repo ?? '' }))\n },\n onUninstallDone: (viaModal, repo, needsRestart, needsReload) => {\n const reload = needsReload === true\n setUninstallNeedsRestart(needsRestart)\n setUninstallNeedsReload(reload)\n if (viaModal) setUninstallDone(true)\n else setToast({ id: Date.now(), kind: 'removed' })\n if (!viaModal && reload) scheduleAutoReload()\n setNotifications(addSuccess({ kind: 'uninstall', repo: repo ?? '' }))\n },\n onError: (message, repo, kind, command, attempts, update) => {\n // 提 Issue 目标先反查仓库身份:npm 包名能在已安装表/目录里反查到 owner/repo 才保留,\n // 反查不到置 null —— 错误弹窗据此不显示「一键提 Issue」按钮(防提到错误仓库)\n const issueRepo = issueRepoOf(repo ?? '', catalog.installedItems, catalog.plugins)\n setErrorMsg({ message, repo: issueRepo, kind, command, attempts })\n // 失败自动写入通知记录:任务在后台结束时没人盯着也能留痕。\n // 存原始 repo(可能只是裸包名)而非反查结果 —— 反查只服务于提 Issue,\n // 通知中心的展示反查由 NotificationsModal 做、查不到会回退显示原始值,\n // 若这里就丢掉原始值,通知里会连名字都看不到;action 区分「安装失败/更新失败」\n setNotifications(addFailure({ kind, action: update ? 'update' : 'install', repo: repo ?? '', message, command, attempts }))\n },\n installPlugin: confirmPlugin,\n installCustomTarget: confirmCustomTarget,\n installGlobalTarget: confirmGlobalNpm ? confirmGlobalNpm.pkgs.join(' ') : null,\n uninstallPlugin,\n uninstallName: uninstallItem ? uninstallItem.name : null,\n installedName: catalog.installedName,\n // 待重启项展示信息补齐:从目录按 owner/repo 解析插件简介/版本(找不到返回 null,行内只显示仓库名)\n resolvePending: (repo) => {\n const p = catalog.plugins?.find((x) => x.source?.repo === repo)\n return p ? { desc: p.description, version: p.version } : null\n },\n })\n\n /** 补齐更新提醒:把「当前有更新但通知中心还没有」的插件补写进通知(repo+version 去重)。\n * 返回本次实际新增的条数(0 = 无可更新或全部已提示过)。启动检查与打开通知中心共用,\n * 保证通知中心始终反映可更新状态:同一版本只一条、清空/删除后重开恢复、更新完成后消失。 */\n const syncUpdateNotices = (): number => {\n const updatable = catalog.installedItems.filter((i) => i.hasUpdate && i.plugin)\n if (updatable.length === 0) return 0\n const known = new Set(loadIgnoredUpdates())\n // 已忽略(repo+version 持久化)与通知中心已有的更新提醒都不再补写:\n // 忽略本次版本后不再提醒,直到下一个新版本(version 变化)才重新提示\n for (const r of loadNotifications()) {\n if (r.kind === 'update') known.add(`${r.repo}@${r.version ?? ''}`)\n }\n const fresh = updatable.filter((item) =>\n item.repo !== null && !known.has(`${item.repo}@${item.catalogVersion ?? ''}`))\n if (fresh.length === 0) return 0\n for (const item of fresh) {\n if (item.repo) addUpdateNotice({ kind: 'update', repo: item.repo, version: item.catalogVersion ?? undefined })\n }\n setNotifications(loadNotifications())\n return fresh.length\n }\n\n // 启动更新策略:目录数据与设置都就绪后触发一次 —— 开启「启动时检查更新」→ 发现可更新插件\n // 即写入通知中心(每条一条,点击可去更新),不弹窗打扰,由通知中心红点提示。\n // 绝不自动安装:是否更新完全由用户决定。\n // ref 守卫保证只跑一次,后续目录刷新/设置变化不会重复打扰。\n const startupCheckedRef = useRef(false)\n useEffect(() => {\n if (startupCheckedRef.current) return\n if (!settingsReady || catalog.plugins === null || catalog.failed) return\n startupCheckedRef.current = true\n if (!hubSettings.checkUpdatesOnStart) return\n syncUpdateNotices()\n }, [settingsReady, hubSettings, catalog.plugins, catalog.failed, catalog.installedItems, queue])\n\n // 信任/卸载/更新说明弹窗打开时按 Esc 关闭;任务进入后台队列后可随时关闭(任务继续)\n useEffect(() => {\n if (!confirmPlugin && !confirmCustomTarget && !confirmGlobalNpm && !uninstallPlugin && !uninstallItem && !detailItem && !showHubUpdate && !showAbout && !showNotifications && !ignoreTarget) return\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setConfirmPlugin(null)\n setConfirmCustomTarget(null)\n setConfirmCustomChannel(null)\n setConfirmGlobalNpm(null)\n setUninstallPlugin(null)\n setUninstallItem(null)\n setDetailItem(null)\n setUninstallDone(false)\n setShowHubUpdate(false)\n setShowAbout(false)\n setShowNotifications(false)\n setIgnoreTarget(null)\n }\n }\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [confirmPlugin, confirmCustomTarget, uninstallPlugin, uninstallItem, detailItem, showHubUpdate, showAbout, showNotifications, ignoreTarget])\n\n // Toast 统一自动消失\n useEffect(() => {\n if (!toast) return\n const timer = window.setTimeout(() => setToast(null), 2400)\n return () => window.clearTimeout(timer)\n }, [toast])\n\n /** 复制文本到剪贴板,返回是否成功(Clipboard API + 隐藏 textarea 兜底)。 */\n const doCopy = async (text: string): Promise<boolean> => {\n try {\n await navigator.clipboard.writeText(text)\n return true\n } catch {\n // Clipboard API unavailable (permissions/iframe) — fall back to the\n // legacy hidden-textarea trick, which works in any context.\n const ta = document.createElement('textarea')\n ta.value = text\n ta.style.position = 'fixed'\n ta.style.opacity = '0'\n document.body.appendChild(ta)\n ta.select()\n let ok = false\n try {\n ok = document.execCommand('copy')\n } catch {\n ok = false\n }\n document.body.removeChild(ta)\n return ok\n }\n }\n\n /** 命令行安装目标是否已安装(与服务端 already 判定同口径):GitHub 地址按仓库身份匹配\n * (归一化后比对已装项的 repo/spec),npm 包名按依赖 key 直查。命中 → 弹窗转「更新」语义\n * (mode=update 放行覆盖重装),避免重复点击撞 409 报错。 */\n const customTargetInstalled = (raw: string): boolean => {\n const target = raw.trim()\n if (!target) return false\n const repo = repoFromInstallTarget(target)\n const isRepo = /^[A-Za-z0-9._-]+\\/[A-Za-z0-9._-]+$/.test(repo)\n if (isRepo) {\n const needle = repo.toLowerCase()\n return catalog.installedItems.some((i) =>\n (i.repo !== null && i.repo.toLowerCase() === needle) ||\n repoFromInstallTarget(i.spec).toLowerCase() === needle)\n }\n // npm 包名(可带 @version):剥掉版本号后同时查已安装列表与原始依赖表。\n // Hub 自身(file:/link: 安装)被 installedItems 刻意排除(防误卸载),列表里查不到,\n // 但依赖表真实存在——补齐后「命令窗口重装 hub 自身」也能转「更新」语义,不再撞 already installed\n const pkg = repo.replace(/@[^@]*$/, '').toLowerCase()\n return catalog.installedItems.some((i) => i.name.toLowerCase() === pkg) ||\n Object.keys(catalog.installed).some((k) => k.toLowerCase() === pkg)\n }\n\n /** 弹窗动作一:复制安装命令到剪贴板,引导去终端粘贴执行(npm 通道显示包名命令)。 */\n const copyCommand = async (p: HubPlugin) => {\n const repo = p.source?.repo ?? ''\n const ok = await doCopy(installCommandOf(p))\n if (ok) {\n setCopied(repo)\n setToast({ id: Date.now(), kind: 'copied' })\n window.setTimeout(() => setCopied((cur) => (cur === repo ? null : cur)), 1600)\n }\n setConfirmPlugin(null)\n }\n\n /** 卸载弹窗动作:复制卸载命令,万一直接卸载失败可去终端手动执行。\n * 自定义安装(无目录数据)按已安装项包名直卸,同样给复制通道。 */\n const copyUninstallCommand = async () => {\n const name = uninstallItem ? uninstallItem.name : (uninstallPlugin ? catalog.installedName(uninstallPlugin) : null)\n if (!name) return\n const ok = await doCopy(`dsh plugin remove ${name}`)\n if (ok) setToast({ id: Date.now(), kind: 'copied' })\n }\n\n /** 详情弹窗动作:在系统文件管理器里定位安装目录;服务端失败给 toast 提示。 */\n const revealFolder = async (item: InstalledItem) => {\n const ok = await revealInstallFolder(item.name)\n if (!ok) setToast({ id: Date.now(), kind: 'revealFail' })\n }\n\n /** 「立即重启」:POST 同源 /restart,宿主进程自杀重启;随后轮询服务恢复后整页刷新。\n * 只在刷新解决不了的兜底场景(热挂载失败 / 非 dsh 插件 / 更新)出现。\n * 桌面端宿主归应用壳管(服务端回 `desktop: true` 且不重启):不轮询,改提示退出重开。 */\n const requestRestart = async () => {\n if (restarting) return\n setRestarting(true)\n let desktop = false\n try {\n // 响应可能在宿主进程被 kill 前返回,也可能直接断连 —— 两种都属正常\n const res = await fetch('/dsh-plugin-hub/restart', { method: 'POST' })\n const data = await res.json() as { desktop?: boolean }\n desktop = data.desktop === true\n } catch {\n /* 服务已终止,无需处理 */\n }\n if (desktop) {\n // 宿主不会重启,轮询等不到新服务:直接给出正确口径\n setRestarting(false)\n setToast({ id: Date.now(), kind: 'restartDesktop' })\n return\n }\n // 轮询同源端点,服务恢复后整页 reload(让新挂载的 bundle 完全初始化)\n let attempts = 0\n const poll = async () => {\n attempts += 1\n try {\n const res = await fetch('/dsh-plugin-hub/active', { method: 'GET', cache: 'no-store' })\n if (res.ok) {\n window.location.reload()\n return\n }\n } catch {\n /* 服务尚未恢复 */\n }\n if (attempts < 60) {\n window.setTimeout(poll, 1000)\n } else {\n setRestarting(false)\n setToast({ id: Date.now(), kind: 'fail' })\n }\n }\n window.setTimeout(poll, 1200)\n }\n\n const { total, installedName, installedVersion, hasUpdate } = catalog\n // 统计数字:官网 /api/stats.json 优先;拉取失败时用已加载列表兜底,避免展示 undefined。\n const statsTotal = catalog.stats?.total ?? total\n const statsVerified = catalog.stats?.verified ?? 0\n\n const count = catalog.visible.length\n\n // Hub 自身条目(目录数据里的 dshplugin/dsh-plugin-hub):头部「可更新」徽标的更新目标。\n // useCatalog 在过滤目录(自身不进插件列表)前单独保留该条目;目录可能尚未加载(此时为 null,徽标不渲染)。\n const hubEntry = catalog.hubPlugin\n\n return h('div', { className: styles.root },\n h(CatalogHeader, {\n t,\n langPath,\n statsTotal,\n statsVerified,\n onToggleLang: toggleLang,\n // Hub 自身版本信息入口:版本号常驻可点(无更新也看得到当前版本更新内容),\n // 有可用更新时版本号后紧跟红色「可更新」徽标(同一入口),点击都打开同一个更新说明弹窗。\n // 有更新弹窗显示新版本 + Markdown 变更记录,点「直接更新」进安装弹窗覆盖重装。\n hubUpdate: catalog.hubHasUpdate,\n // 点击版本号/徽标:先强制刷新拉取最新版本信息(发版后点击即见新版本),再打开弹窗\n onVersionClick: () => {\n void catalog.refreshHub().then(() => setShowHubUpdate(true))\n },\n onAboutClick: () => setShowAbout(true),\n }),\n // 一级导航行:tab 占满左侧,通知入口靠右(「设置」tab 后边,右对齐)\n h('div', { className: styles.tabsRow },\n // 「已安装」徽标 = 目录插件 + 自定义安装总数(installedItems 已排除 hub 自身)\n h(SectionTabs, {\n view,\n setView,\n installedCount: catalog.installedItems.length,\n t,\n // 通知中心入口:红圈徽标 = 记录数 + 进行中任务 + 待重启(有动静才醒目)\n noticeCount: notifications.length + queue.queue.length + queue.pendingRestarts.length,\n onOpenNotifications: () => {\n // 打开弹窗时补齐更新提醒(受「启动时检查更新」开关约束):同一版本只一条,\n // 清空/删除后重开仍恢复,直到插件更新完成才消失\n if (hubSettings.checkUpdatesOnStart) syncUpdateNotices()\n setShowNotifications(true)\n },\n }),\n ),\n view === 'market'\n ? h(MarketView, {\n catalog,\n t,\n langPath,\n langKey,\n copied,\n // 列表头部「筛选出 N 条」:分类/搜索/安装状态筛选后的结果数;全部视图且未筛选时显示总数\n resultText: catalog.plugins === null || catalog.failed\n ? null\n : catalog.category === 'all' && count === total\n ? t('pluginsTotal', { n: count })\n : t('filterResults', { n: count }),\n onInstall: (p, opts) => {\n setInstallDone(false)\n setConfirmIsUpdate(opts?.update ?? false)\n // 与卸载一致:重置弹窗关联任务,避免新弹窗误匹配到进行中的任务而禁用安装按钮\n queue.clearModalTask()\n setConfirmPlugin(p)\n },\n onUninstall: (p) => {\n setUninstallDone(false)\n queue.clearModalTask()\n setUninstallPlugin(p)\n },\n // 目录加载失败时的精准提示:设置里配了代理 → 提示代理不可达;没配 → 提示网络不通\n hasProxy: (hubSettings.proxy ?? '').trim() !== '',\n // 「去系统诊断检测网络」直达(复用网络失败弹窗的同一跳转:关弹窗 → 设置 → 系统诊断自动跑连通性检测)\n onOpenDiagnostics: openDiagnostics,\n })\n : view === 'installed'\n ? h(InstalledView, {\n items: catalog.installedItems,\n langKey,\n t,\n // 支持系统文件管理器定位的平台(macOS / Linux)上,行内「打开详情」替换为\n // 打开安装目录按钮(行点击本身即打开详情弹窗);Windows 不支持则按钮不显示\n platform: env?.platform ?? '',\n // 行点击 / 详情按钮:打开已安装详情弹窗(完整元数据 + 运行时信息)\n onOpenDetail: (item) => setDetailItem(item),\n onReveal: (item) => { void revealFolder(item) },\n // 更新:已安装视图的「更新」= 目录插件覆盖重装,与市场列表内更新同一流程\n onUpdate: (item) => {\n if (!item.plugin) return\n setDetailItem(null)\n setInstallDone(false)\n setConfirmIsUpdate(true)\n queue.clearModalTask()\n setConfirmPlugin(item.plugin)\n },\n // 卸载:目录插件与自定义安装统一按已安装项走卸载确认弹窗(自定义无目录数据,按包名直卸)\n onUninstall: (item) => {\n setDetailItem(null)\n setUninstallDone(false)\n queue.clearModalTask()\n setUninstallItem(item)\n },\n // 重启:待重启条目行内按钮 → 先弹「立即重启 / 稍后重启」确认(与通知中心一致),确认后才触发宿主重启\n onRestart: () => setShowRestartConfirm(true),\n })\n : view === 'custom'\n ? h(CustomInstallView, {\n t,\n // 命令行安装:与应用商店同一套确认/进度/结果弹窗 —— 输入 npm 包名 / GitHub 地址 /\n // dsh plugin 命令即装(custom 源,受安全设置三开关控制)。点安装先弹确认窗,\n // 确认后走队列安装(实时进度 + 成功结果视图);目标已安装 → 弹窗转「更新」覆盖重装,\n // 不会撞「already installed」报错。\n // 安全信任开关关掉对应通道 → 卡片禁用并提示去设置打开(onOpenSettings 跳到设置页)。\n enableNpm: hubSettings.enableNpmInstall,\n enableGit: hubSettings.enableGitInstall,\n enableDsh: hubSettings.enableDshInstall,\n onOpenSettings: () => setView('settings'),\n // 当前 profile:一键插入的 Hub 更新命令用它拼 --profile\n profile: env?.profile ?? 'web',\n onInstallCustom: (raw, opts) => {\n const target = raw.trim()\n if (!target) return\n setInstallDone(false)\n // 与目录安装一致:重置弹窗关联任务,避免新弹窗误匹配到进行中的任务\n queue.clearModalTask()\n // 官方全局 npm 安装(npm install -g <pkgs>):弹窗走 globalNpm 模式(系统级 CLI 工具,\n // 不进插件列表,不做「已安装→更新」判定 —— npm install -g 对已装包是原位覆盖更新,天然幂等)\n if (opts?.globalNpm && opts.globalNpm.length > 0) {\n setConfirmCustomTarget(null)\n setConfirmCustomChannel(null)\n setConfirmIsUpdate(false)\n setConfirmGlobalNpm({ raw, pkgs: opts.globalNpm })\n return\n }\n setConfirmGlobalNpm(null)\n // 记录入口渠道:报错/日志据此精准提示「从哪张卡片发起的安装」(NPM 包 / GitHub 源码 / DSH 命令)\n setConfirmCustomChannel(opts.installChannel)\n setConfirmIsUpdate(customTargetInstalled(target))\n setConfirmCustomTarget(target)\n },\n })\n : h(SettingsView, {\n t,\n settings: hubSettings,\n update: updateSettings,\n reset: resetSettings,\n env,\n onCopy: (text: string) => {\n doCopy(text)\n setToast({ id: Date.now(), kind: 'copied' })\n },\n // 网络不通提示「去系统诊断」→ 设置页并切到系统诊断分组(DiagnosticsView 挂载即自动跑探测)\n openSection: settingsSection,\n onConsumedOpenSection: () => setSettingsSection(null),\n }),\n // Hub 版本信息弹窗:版本号/徽标点击打开 —— 有更新显示新版本 + 变更记录 + 「直接更新」,\n // 无更新显示当前版本 + 记录 + 「已是最新」。Worker 拉取失败时兜底展示当前版本号。\n showHubUpdate && h(HubUpdateModal, {\n info: catalog.hubUpdateInfo ?? { version: PLUGIN_VERSION },\n lang,\n t,\n hasUpdate: catalog.hubHasUpdate,\n onClose: () => setShowHubUpdate(false),\n onProceed: () => {\n setShowHubUpdate(false)\n // 与列表内更新同一流程:覆盖重装 dsh-plugin + 结果视图「立即重启」\n if (hubEntry) {\n setInstallDone(false)\n setConfirmIsUpdate(true)\n queue.clearModalTask()\n setConfirmPlugin(hubEntry)\n }\n },\n }),\n // 「关注我们」弹窗:GitHub 图标后按钮点击打开 —— 平台介绍 + 用户反馈群二维码,\n // 内容由 dsh-update Worker 的 /about 接口以 Markdown 形式推送,作者随时可改,非写死。\n // Worker 未推送(info 为 null)时弹窗仍能打开并展示兜底文案,不影响其他功能。\n showAbout && h(AboutModal, {\n info: catalog.hubAboutInfo ?? null,\n lang,\n t,\n onClose: () => setShowAbout(false),\n }),\n // 安装/卸载任务通知中心:本地持久化的成败清单,随时可回来查看/复制/清空;\n // 进行中的任务(实时进度)与待重启插件也一并展示,关掉任务弹窗后仍可盯着\n showNotifications && h(NotificationsModal, {\n records: notifications,\n tasks: queue.queue,\n pendingRestarts: queue.pendingRestarts,\n t,\n env,\n onClose: () => setShowNotifications(false),\n onCopy: (text) => {\n doCopy(text)\n setToast({ id: Date.now(), kind: 'errCopied' })\n },\n onClear: () => setNotifications(clearNotifications()),\n onRemove: (id: number) => setNotifications(removeNotification(id)),\n // 更新提醒通知:点击直接进该插件的更新确认弹窗(与已安装列表「更新」同一流程)\n onUpdate: (repo: string) => {\n const plugin = catalog.installedItems.find((i) => i.repo === repo)?.plugin\n if (!plugin) return\n setShowNotifications(false)\n setInstallDone(false)\n setConfirmIsUpdate(true)\n queue.clearModalTask()\n setConfirmPlugin(plugin)\n },\n // 更新提醒「忽略本次更新」:先弹确认弹窗,确认后该版本不再提醒(持久化),直到下一个新版本\n onIgnoreUpdate: (repo: string, version?: string) => setIgnoreTarget({ repo, version }),\n cancelTask: queue.cancelTask,\n restarting,\n onRestart: () => setShowRestartConfirm(true),\n // 网络不通记录的「去系统诊断」直达:关通知中心 → 设置 → 系统诊断\n onRunDiagnostics: openDiagnostics,\n // 失败记录仓库反查:历史记录可能存的是裸 npm 包名,反查成 owner/repo 才显示仓库链接\n // 与提 Issue 按钮;查不到则隐藏(防提到错误仓库)\n resolveRepo: (repo: string) => issueRepoOf(repo, catalog.installedItems, catalog.plugins),\n }),\n // 「忽略本次更新」确认弹窗:确认后该版本写入忽略集(持久化)并从通知中心移除,\n // 本次版本不再提醒,直到插件发布下一个新版本\n ignoreTarget && h('div', {\n className: modalStyles.overlay,\n onClick: (e: MouseEvent<HTMLDivElement>) => { if (e.target === e.currentTarget) setIgnoreTarget(null) },\n },\n h('div', { className: modalStyles.modal, role: 'dialog', 'aria-modal': 'true' },\n h('div', { className: modalStyles.modalHead },\n h('div', { className: modalStyles.modalTitle }, t('ignoreUpdateConfirmTitle')),\n h('button', {\n className: modalStyles.modalClose,\n type: 'button',\n 'aria-label': t('errorClose'),\n onClick: () => setIgnoreTarget(null),\n }, h(CloseIcon)),\n ),\n h('div', { className: modalStyles.modalBody },\n // 忽略更新确认:品牌蓝问号图标,普通确认\n h('div', { className: modalStyles.confirmIconWrap },\n h(ConfirmIcon, { type: 'question' }),\n ),\n h('div', { className: modalStyles.failPrepareHint }, t('ignoreUpdateConfirmDetail')),\n h('div', { className: modalStyles.modalActions },\n h('button', {\n className: modalStyles.restartLater,\n type: 'button',\n onClick: () => setIgnoreTarget(null),\n }, t('confirmCancel')),\n h('button', {\n className: modalStyles.restartNow,\n type: 'button',\n onClick: () => {\n ignoreUpdate(ignoreTarget.repo, ignoreTarget.version)\n setNotifications(removeUpdateNotice(ignoreTarget.repo, ignoreTarget.version))\n setIgnoreTarget(null)\n },\n }, t('ignoreUpdateConfirm')),\n ),\n ),\n ),\n ),\n // 安装确认弹窗:锁定/进度/结果视图逻辑收敛在 modals.tsx;更新与安装同入口,仅标记 update\n confirmPlugin && h(InstallModal, {\n plugin: confirmPlugin,\n done: installDone,\n task: queue.installModalTask,\n t,\n langPath,\n restarting,\n update: confirmIsUpdate,\n // 仅命令行插件(webInstallable=false):弹窗只展示命令供复制,不提供一键安装\n cliOnly: confirmPlugin.install?.webInstallable === false,\n submitting: queue.submitting,\n needsRestart: installNeedsRestart,\n needsReload: installNeedsReload,\n // 结果弹窗关闭即生效:安装热挂载的插件要页面重载才渲染客户端 UI → 自动刷新,无需用户点按钮\n onClose: () => {\n const reload = installDone && installNeedsReload\n setConfirmPlugin(null)\n if (reload) window.location.reload()\n },\n onCopy: () => copyCommand(confirmPlugin),\n onInstall: () => queue.installNow(confirmPlugin, confirmIsUpdate ? { update: true } : undefined),\n // 重启:结果视图「立即重启」也会中断进行中的任务 → 先弹重启确认弹窗\n onRestart: () => setShowRestartConfirm(true),\n }),\n // 命令行安装确认弹窗:与目录安装同一套确认/进度/结果流程(plugin 传 null 走 customTarget 模式)。\n // 已安装目标 → update 标记,确认后走覆盖重装(服务端 mode=update 放行),不再 409 报错。\n confirmCustomTarget && h(InstallModal, {\n plugin: null,\n customTarget: confirmCustomTarget,\n done: installDone,\n task: queue.installModalTask,\n t,\n langPath,\n restarting,\n update: confirmIsUpdate,\n cliOnly: false,\n submitting: queue.submitting,\n needsRestart: installNeedsRestart,\n needsReload: installNeedsReload,\n onClose: () => {\n const reload = installDone && installNeedsReload\n setInstallDone(false)\n setConfirmCustomTarget(null)\n setConfirmCustomChannel(null)\n if (reload) window.location.reload()\n },\n onCopy: () => {\n doCopy(`pnpm add ${confirmCustomTarget}`)\n setToast({ id: Date.now(), kind: 'copied' })\n },\n onInstall: () => void queue.installCustom(confirmCustomTarget, {\n update: confirmIsUpdate,\n // 入口渠道(NPM 包 / GitHub 源码 / DSH 命令卡片):上报服务端,报错/日志据此溯源\n channel: confirmCustomChannel ?? 'npm',\n }),\n onRestart: () => setShowRestartConfirm(true),\n }),\n // 全局 npm 安装确认弹窗(官方 `npm install -g <pkgs>`):与应用商店同一套确认/进度/结果流程。\n // 装的是系统级 CLI 工具(如 @deepseek-ai/dsh),不进任何 profile、无需宿主重启;\n // 服务端任务终态 needsRestart=false → 结果视图仅「完成」。\n confirmGlobalNpm && h(InstallModal, {\n plugin: null,\n globalNpm: confirmGlobalNpm.pkgs,\n done: installDone,\n task: queue.installModalTask,\n t,\n langPath,\n restarting,\n update: false,\n cliOnly: false,\n submitting: queue.submitting,\n needsRestart: installNeedsRestart,\n needsReload: installNeedsReload,\n onClose: () => {\n const reload = installDone && installNeedsReload\n setInstallDone(false)\n setConfirmGlobalNpm(null)\n setConfirmCustomChannel(null)\n if (reload) window.location.reload()\n },\n onCopy: () => {\n doCopy(`npm install -g ${confirmGlobalNpm.pkgs.join(' ')}`)\n setToast({ id: Date.now(), kind: 'copied' })\n },\n onInstall: () => void queue.installGlobalNpm(confirmGlobalNpm.pkgs, { channel: 'npm' }),\n onRestart: () => setShowRestartConfirm(true),\n }),\n // 卸载确认弹窗:确认/进度/结果视图逻辑收敛在 modals.tsx。\n // 已安装视图的自定义安装(目录外)没有完整目录数据,按已安装项伪插件适配后走同一弹窗\n (uninstallPlugin || uninstallItem) && h(UninstallModal, {\n plugin: uninstallPlugin ?? pluginOfItem(uninstallItem!),\n done: uninstallDone,\n task: queue.uninstallModalTask,\n t,\n langPath,\n restarting,\n submitting: queue.submitting,\n needsRestart: uninstallNeedsRestart,\n needsReload: uninstallNeedsReload,\n // 卸载后插件面板要页面重载才摘除(带 UI 的插件)→ 关闭结果弹窗即自动刷新\n onClose: () => {\n const reload = uninstallDone && uninstallNeedsReload\n setUninstallDone(false)\n setUninstallPlugin(null)\n setUninstallItem(null)\n if (reload) window.location.reload()\n },\n onCancel: () => {\n setUninstallPlugin(null)\n setUninstallItem(null)\n },\n onCopyCommand: copyUninstallCommand,\n onConfirm: () => {\n if (uninstallItem) void queue.uninstallItem(uninstallItem)\n else if (uninstallPlugin) void queue.uninstallNow(uninstallPlugin)\n },\n onRestart: () => setShowRestartConfirm(true),\n }),\n // 已安装详情弹窗:目录元数据 + 宿主运行时信息的完整展示,操作(更新/卸载/复制路径)由此发起\n detailItem && h(InstalledDetailModal, {\n item: detailItem,\n t,\n lang: langKey,\n langPath,\n onClose: () => setDetailItem(null),\n onUpdate: (item) => {\n if (!item.plugin) return\n setDetailItem(null)\n setInstallDone(false)\n setConfirmIsUpdate(true)\n queue.clearModalTask()\n setConfirmPlugin(item.plugin)\n },\n onUninstall: (item) => {\n setDetailItem(null)\n setUninstallDone(false)\n queue.clearModalTask()\n setUninstallItem(item)\n },\n onCopyPath: (path) => {\n doCopy(path)\n setToast({ id: Date.now(), kind: 'copied' })\n },\n onReveal: (item) => { void revealFolder(item) },\n }),\n toast && h(Toast, { toast, t }),\n // 操作失败:完整错误弹窗(重复安装、CLI 失败、请求错误等),可复制并去插件仓库反馈\n errorMsg && h(ErrorModal, {\n message: errorMsg.message,\n repo: errorMsg.repo,\n kind: errorMsg.kind,\n command: errorMsg.command,\n attempts: errorMsg.attempts,\n t,\n env,\n onCopy: (text: string) => {\n doCopy(text)\n setToast({ id: Date.now(), kind: 'errCopied' })\n },\n // 网络不通错误的「去系统诊断」直达:关错误弹窗 → 设置 → 系统诊断\n onRunDiagnostics: openDiagnostics,\n onClose: () => setErrorMsg(null),\n }),\n // 待重启确认弹窗:已安装列表行内「重启」按钮点击后弹出(兜底场景),单个「立即重启」,关闭即视为稍后\n showRestartConfirm && h(RestartConfirmModal, {\n t,\n restarting,\n onClose: () => setShowRestartConfirm(false),\n onRestartNow: () => {\n setShowRestartConfirm(false)\n void requestRestart()\n },\n }),\n )\n}\n","/**\n * DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.\n * Website: https://dsh-plugin.org\n * GitHub: https://github.com/dshplugin/dsh-plugin-hub\n *\n * dsh-plugin client entry: wires the Plugin Hub into the host settings via\n * the module-loader bundle (see tsdown.config.ts). All UI logic lives in\n * PluginHubSection; this file only performs the cordis apply wiring.\n */\nimport { createElement as h } from 'react'\nimport type { HubClientContext } from './types.ts'\nimport { en, zh } from './locales.ts'\nimport { PluginHubSection } from './components/PluginHubSection.tsx'\nimport './styles/tokens.module.css'\n\nconst NS = 'dsh-plugin'\n\nexport const name = NS\nexport const inject = ['slots', 'locale']\n\nexport function apply(ctx: HubClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), `${NS}: dictionaries`)\n const t = ctx.locale.bind(NS)\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: NS,\n order: 60,\n label: () => t('nav'),\n locale: NS,\n inject: () => ({ t, locale: ctx.locale }),\n }, () => h(PluginHubSection, { t, locale: ctx.locale })))\n}\n"],"mappings":"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"}