dsh-agent-plugins-market 0.4.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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -0
  3. package/README.zh.md +171 -0
  4. package/client/client.js +954 -0
  5. package/client/client.js.map +1 -0
  6. package/cordis.patch.yml +4 -0
  7. package/lib/commands-mounts.js +169 -0
  8. package/lib/context.js +80 -0
  9. package/lib/discovery/manifests.js +214 -0
  10. package/lib/discovery/surfaces.js +232 -0
  11. package/lib/discovery.js +234 -0
  12. package/lib/git.js +52 -0
  13. package/lib/hooks-mounts.js +95 -0
  14. package/lib/index.js +73 -0
  15. package/lib/manager.js +490 -0
  16. package/lib/mcp-config.js +100 -0
  17. package/lib/mcp-mounts.js +88 -0
  18. package/lib/paths.js +85 -0
  19. package/lib/routes.js +208 -0
  20. package/lib/skills-parse.js +114 -0
  21. package/lib/skills-provider.js +170 -0
  22. package/lib/state.js +64 -0
  23. package/lib/types/commands-mounts.d.ts +29 -0
  24. package/lib/types/context.d.ts +13 -0
  25. package/lib/types/discovery/manifests.d.ts +55 -0
  26. package/lib/types/discovery/surfaces.d.ts +15 -0
  27. package/lib/types/discovery.d.ts +16 -0
  28. package/lib/types/git.d.ts +8 -0
  29. package/lib/types/hooks-mounts.d.ts +19 -0
  30. package/lib/types/index.d.ts +27 -0
  31. package/lib/types/manager.d.ts +87 -0
  32. package/lib/types/mcp-config.d.ts +28 -0
  33. package/lib/types/mcp-mounts.d.ts +31 -0
  34. package/lib/types/paths.d.ts +29 -0
  35. package/lib/types/routes.d.ts +11 -0
  36. package/lib/types/skills-parse.d.ts +22 -0
  37. package/lib/types/skills-provider.d.ts +16 -0
  38. package/lib/types/state.d.ts +6 -0
  39. package/lib/types/types.d.ts +165 -0
  40. package/lib/types/validate.d.ts +34 -0
  41. package/lib/types.js +10 -0
  42. package/lib/validate.js +199 -0
  43. package/package.json +114 -0
  44. package/schemas/1.0.0/mcp.schema.json +120 -0
  45. package/schemas/1.0.0/plugin.schema.json +65 -0
  46. package/schemas/README.md +14 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","names":["Component","h","useState","h","Modal","css","Button","MarkdownText","useState","useCallback","useMemo","h","css","Button","Input","Toast","Modal","Tooltip","primitives","h"],"sources":["../src/client/locales.ts","../src/client/api.ts","../src/client/ErrorBoundary.tsx","../src/client/market.module.css","../src/client/SuiteDetail.tsx","../src/client/MarketSection.tsx","../src/client/index.ts"],"sourcesContent":["/** zh/en dictionaries for the Agent Plugins Market section. */\n\nexport type Dictionary = Record<string, string>\n\nexport const zh: Dictionary = {\n nav: 'Agent Plugins 市场',\n subtitle: '发现与安装 Agent Plugins(agent-plugins.org 便携包)',\n searchPh: '搜索 Agent Plugins…',\n tabAll: '全部',\n tabInstalled: '已安装',\n tabUninstalled: '未安装',\n market: '仓库源',\n addSource: '添加源',\n sourceIdPh: '源 id(小写字母数字)',\n sourceUrlPh: 'git 仓库地址',\n sourceUrlLocalPh: '本地仓库路径(绝对路径或 ~/…)',\n sourceModeGit: '远程 git',\n sourceModeLocal: '本地目录',\n branchPh: '分支(可选)',\n sourceLocal: '本地',\n editSource: '编辑当前源',\n editSourceTitle: '编辑仓库源',\n addSourceTitle: '新增仓库源',\n save: '保存',\n confirmDelete: '确认删除',\n refreshAll: '刷新全部',\n detailTitle: 'Agent Plugins 详情',\n overviewSection: '概览',\n skillsSection: '技能',\n mcpSection: 'MCP 服务',\n commandsSection: '命令',\n agentsSection: '子代理',\n hooksLabel: 'Hooks',\n sourceLabel: '来源',\n dimensionLabel: '维度',\n layoutLabel: '布局',\n statusLabel: '状态',\n authorLabel: '作者',\n keywordsLabel: '关键词',\n disabledLabel: '已停用',\n notInstalledLabel: '未安装',\n noSkills: '(无技能)',\n noMcp: '(无 MCP 服务)',\n loading: '加载中…',\n lspSection: 'LSP 服务',\n editorHint: '仓库源提供 Agent Plugins。本地目录直接读取(实时反映工作树);git 源克隆到 ~/.dsh/agent-plugins/.sources/<id>。',\n idHint: '小写字母/数字/连字符,全局唯一',\n urlGitHint: 'git 仓库地址,例如 https://github.com/org/repo.git',\n urlLocalHint: '绝对路径或 ~/…,直接读取本地目录(不克隆、移除源时不会删除)',\n branchHint: '可选;不填则跟踪默认分支',\n idFixed: 'id 不可修改(源标识全局唯一)',\n idAutoLabel: '源 ID(自动生成)',\n idAutoHint: '自动从插件清单名或仓库名解析,无需填写',\n detailHint: '点击技能或 MCP 服务行可展开查看详情',\n add: '添加',\n remove: '移除',\n refresh: '刷新',\n install: '安装',\n installing: '安装中…',\n installedBadge: '已安装',\n uninstall: '卸载',\n uninstallConfirmTitle: '卸载 Agent Plugins',\n uninstallConfirmDesc: '将从已安装列表移除该 Agent Plugins,其技能与 MCP 工具随即停止注入。仓库源克隆保留。',\n removeSourceConfirmTitle: '移除仓库源',\n removeSourceConfirmDesc: '将删除该源的本地克隆与全部安装记录。',\n enable: '启用',\n disable: '禁用',\n cancel: '取消',\n confirm: '确认',\n empty: '没有匹配的 Agent Plugins',\n installedEmpty: '还没有安装 Agent Plugins',\n loadFail: 'Agent Plugins 目录加载失败,请稍后重试',\n actionFail: '操作失败',\n version: '版本',\n dimensionUser: '用户级',\n dimensionProject: '项目级',\n layoutV1: '便携 v1',\n layoutCC: 'Claude Code',\n layoutCodex: 'Codex',\n layoutSkills: '技能集合',\n layoutUniversal: '通用',\n layoutCursor: 'Cursor',\n layoutKimi: 'Kimi',\n layoutRemote: '远程引用',\n remoteRef: '远程',\n surfaceSkills: '技能',\n surfaceMcp: 'MCP',\n surfaceHooks: 'Hooks',\n surfaceCommands: '命令',\n surfaceAgents: '子代理',\n surfaceLsp: 'LSP',\n sourceNotCloned: '未克隆',\n sourceCloned: '已克隆',\n errors: '校验问题',\n grid: '网格',\n list: '列表',\n openSettings: '在设置中打开',\n rootLabel: 'Agent Plugins 目录',\n dataLabel: 'Agent Plugins 数据目录',\n countAll: '共 {n} 个 Agent Plugins',\n countInstalled: '已装 {n}',\n countEnabled: '启用 {n}',\n}\n\nexport const en: Dictionary = {\n nav: 'Agent Plugins Market',\n subtitle: 'Discover and install Agent Plugins suites (agent-plugins.org portable packages)',\n searchPh: 'Search suites…',\n tabAll: 'All',\n tabInstalled: 'Installed',\n tabUninstalled: 'Uninstalled',\n market: 'Sources',\n addSource: 'Add source',\n sourceIdPh: 'source id (lowercase alnum)',\n sourceUrlPh: 'git repository URL',\n sourceUrlLocalPh: 'local repository path (absolute or ~/…)',\n sourceModeGit: 'remote git',\n sourceModeLocal: 'local dir',\n branchPh: 'branch (optional)',\n sourceLocal: 'local',\n editSource: 'Edit source',\n editSourceTitle: 'Edit source',\n addSourceTitle: 'Add source',\n save: 'Save',\n confirmDelete: 'Delete',\n refreshAll: 'Refresh all',\n detailTitle: 'Suite details',\n overviewSection: 'Overview',\n skillsSection: 'Skills',\n mcpSection: 'MCP servers',\n commandsSection: 'Commands',\n agentsSection: 'Subagents',\n hooksLabel: 'Hooks',\n sourceLabel: 'Source',\n dimensionLabel: 'Dimension',\n layoutLabel: 'Layout',\n statusLabel: 'Status',\n authorLabel: 'Author',\n keywordsLabel: 'Keywords',\n disabledLabel: 'disabled',\n notInstalledLabel: 'not installed',\n noSkills: '(no skills)',\n noMcp: '(no MCP servers)',\n loading: 'Loading…',\n lspSection: 'LSP servers',\n editorHint: 'A source provides suites (Agent Plugins). Local directories are read in place (live working tree); git sources clone into ~/.dsh/agent-plugins/.sources/<id>.',\n idHint: 'lowercase letters / digits / hyphens, globally unique',\n urlGitHint: 'git repository URL, e.g. https://github.com/org/repo.git',\n urlLocalHint: 'absolute path or ~/…, read in place (never cloned, never deleted on removal)',\n branchHint: 'optional; defaults to the repository default branch',\n idFixed: 'id is fixed (the source identifier is globally unique)',\n idAutoLabel: 'Source ID (auto)',\n idAutoHint: 'Derived from the suite or repo name — no need to type it',\n detailHint: 'Click a skill or MCP server row to expand its details',\n add: 'Add',\n remove: 'Remove',\n refresh: 'Refresh',\n install: 'Install',\n installing: 'Installing…',\n installedBadge: 'Installed',\n uninstall: 'Uninstall',\n uninstallConfirmTitle: 'Uninstall suite',\n uninstallConfirmDesc: 'Removes the suite from the installed list; its skills and MCP tools stop injecting. The source clone stays.',\n removeSourceConfirmTitle: 'Remove source',\n removeSourceConfirmDesc: 'Deletes the local clone and all install records of this source.',\n enable: 'Enable',\n disable: 'Disable',\n cancel: 'Cancel',\n confirm: 'Confirm',\n empty: 'No matching suites',\n installedEmpty: 'No suites installed yet',\n loadFail: 'Failed to load the suite catalog, try again later',\n actionFail: 'Action failed',\n version: 'Version',\n dimensionUser: 'user',\n dimensionProject: 'project',\n layoutV1: 'portable v1',\n layoutCC: 'Claude Code',\n layoutCodex: 'Codex',\n layoutSkills: 'skill dir',\n layoutUniversal: 'universal',\n layoutCursor: 'Cursor',\n layoutKimi: 'Kimi',\n layoutRemote: 'remote reference',\n remoteRef: 'remote',\n surfaceSkills: 'skills',\n surfaceMcp: 'MCP',\n surfaceHooks: 'hooks',\n surfaceCommands: 'commands',\n surfaceAgents: 'subagents',\n surfaceLsp: 'LSP',\n sourceNotCloned: 'not cloned',\n sourceCloned: 'cloned',\n errors: 'validation issues',\n grid: 'grid',\n list: 'list',\n openSettings: 'Open in settings',\n rootLabel: 'Suite root',\n dataLabel: 'Suite data root',\n countAll: '{n} suites',\n countInstalled: '{n} installed',\n countEnabled: '{n} enabled',\n}\n","/** Typed fetch helpers over the host's `/api/agent-plugins/*` routes. */\n\nexport interface SourceOverview {\n id: string\n url: string\n branch?: string\n /** Local-directory source (read directly, never cloned or deleted). */\n local?: boolean\n cloned: boolean\n lockCommit?: string\n error?: string\n suiteIds: string[]\n}\n\nexport interface SuiteSurfaceCounts {\n skills: number\n mcp: number\n hooks: number\n commands: number\n agents: number\n lsp: number\n}\n\nexport interface SuiteCardData {\n sourceId: string\n suiteId: string\n name: string\n version?: string\n description?: string\n keywords: string[]\n surfaces: SuiteSurfaceCounts\n enabled: boolean\n installed: boolean\n dimension: string\n layout: string\n remoteUrl?: string\n errors: string[]\n}\n\nexport interface OverviewData {\n sources: SourceOverview[]\n suites: SuiteCardData[]\n totals: { all: number; installed: number; enabled: number }\n roots: { user: string; data: string }\n}\n\nexport async function fetchOverview(): Promise<OverviewData> {\n const response = await fetch('/api/agent-plugins/overview', { credentials: 'same-origin' })\n if (!response.ok) throw new Error(`overview failed: ${response.status}`)\n return response.json() as Promise<OverviewData>\n}\n\n/** One skill's metadata inside a suite detail. */\nexport interface SuiteSkillMeta {\n name: string\n description: string\n whenToUse?: string\n path: string\n}\n\n/** One CC command with its full template for preview. */\nexport interface CommandPreview {\n name: string\n description?: string\n content: string\n}\n\n/** One CC agent definition with its full text for preview. */\nexport interface AgentPreview {\n name: string\n description?: string\n content: string\n}\n\n/** One LSP definition file (JSON) for preview. */\nexport interface LspPreview {\n name: string\n content: string\n}\n\n/** One flattened CC hook entry for preview. */\nexport interface HookPreview {\n event: string\n matcher?: string\n command: string\n}\n\n/** One validated mcp.json server entry. */\nexport interface McpServerDetail {\n key: string\n type: string\n command?: string\n url?: string\n args?: string[]\n env?: Record<string, string>\n cwd?: string\n headers?: Record<string, string>\n}\n\n/** Full suite detail served by the market's detail modal. */\nexport interface SuiteDetail {\n sourceId: string\n suiteId: string\n name: string\n version: string | null\n description: string | null\n author: string | null\n keywords: string[]\n layout: string\n dimension: string\n root: string\n remoteUrl: string | null\n installed: boolean\n enabled: boolean\n skills: SuiteSkillMeta[]\n mcpServers: McpServerDetail[]\n hooks: { count: number; entries: HookPreview[] }\n commands: CommandPreview[]\n agents: AgentPreview[]\n lsp: LspPreview[]\n errors: string[]\n}\n\n/** One skill's full file text. */\nexport interface SkillContent {\n name: string\n description: string\n content: string\n path: string\n}\n\nexport async function fetchSuiteDetail(sourceId: string, suiteId: string): Promise<SuiteDetail> {\n const response = await fetch(`/api/agent-plugins/suite?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}`, { credentials: 'same-origin' })\n if (!response.ok) throw new Error(`suite detail failed: ${response.status}`)\n return response.json() as Promise<SuiteDetail>\n}\n\nexport async function fetchSkillContent(sourceId: string, suiteId: string, skill: string): Promise<SkillContent> {\n const response = await fetch(`/api/agent-plugins/skill?sourceId=${encodeURIComponent(sourceId)}&suiteId=${encodeURIComponent(suiteId)}&skill=${encodeURIComponent(skill)}`, { credentials: 'same-origin' })\n if (!response.ok) throw new Error(`skill content failed: ${response.status}`)\n return response.json() as Promise<SkillContent>\n}\n\nexport async function postAction(path: string, body: Record<string, unknown>): Promise<Record<string, unknown>> {\n const response = await fetch(`/api/agent-plugins/${path}`, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n const payload = await response.json() as { ok: boolean; error?: string }\n if (!response.ok || payload.ok !== true) {\n throw new Error(payload.error ?? `request failed: ${response.status}`)\n }\n return payload\n}\n","/**\n * Error boundary for untrusted preview content.\n *\n * Skill/command/agent bodies and hook/LSP JSON are third-party content; a\n * renderer throw must degrade to a plain-text fallback instead of unmounting\n * the whole settings section (React has no built-in boundary).\n */\nimport { createElement as h, Component, type ReactNode } from 'react'\n\ninterface Props {\n children: ReactNode\n fallback?: (error: Error) => ReactNode\n}\n\ninterface State {\n error: Error | undefined\n}\n\nexport class ErrorBoundary extends Component<Props, State> {\n override state: State = { error: undefined }\n\n static getDerivedStateFromError(error: Error): State {\n return { error }\n }\n\n override componentDidCatch(error: Error, info: unknown): void {\n console.warn('[dsh-agent-plugins-market] preview render failed:', error, info)\n }\n\n override render(): ReactNode {\n if (this.state.error !== undefined) {\n return this.props.fallback === undefined\n ? h('pre', { className: 'dsh-agent-plugins-fallback' }, `预览渲染失败:${this.state.error.message}`)\n : this.props.fallback(this.state.error)\n }\n return this.props.children\n }\n}\n","/**\n * Agent Plugins Market section styles. Colors ride the dsh --dsw-alias-* tokens with\n * light-mode fallbacks so the page follows the active theme; the section\n * lives inside the settings dialog, so it scrolls within the dialog and\n * never takes over the app frame.\n */\n\n.market {\n height: 100%;\n min-height: 0;\n display: flex;\n flex-direction: column;\n min-width: 0;\n gap: 14px;\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.header {\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.titleRow {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n line-height: 24px;\n}\n\n.sub {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n margin: 0;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.spacer {\n flex: 1;\n}\n\n.tabGap {\n width: 16px;\n flex-shrink: 0;\n}\n\n.searchGroup {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.searchWrap {\n display: flex;\n align-items: center;\n}\n\n.searchInput {\n display: flex;\n align-items: center;\n}\n\n.searchInput input {\n width: 240px;\n font-size: 12px;\n line-height: 20px;\n}\n\n.tabRow {\n display: flex;\n gap: 2px;\n border-bottom: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n align-items: flex-end;\n justify-content: flex-end;\n}\n\n.tab,\n.tabOn {\n border: none;\n background: none;\n font: inherit;\n font-size: 13px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n padding: 7px 12px;\n cursor: pointer;\n border-bottom: 2px solid transparent;\n white-space: nowrap;\n}\n\n.tabOn {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n border-bottom-color: var(--dsw-alias-brand-primary, #4f6ef7);\n font-weight: 600;\n}\n\n/* View-switch control (列表/网格): same metrics as .tab so it aligns on the row. */\n.viewSwitch {\n border: none;\n background: none;\n font: inherit;\n font-size: 13px;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n padding: 7px 12px;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.viewSwitch:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.body {\n display: flex;\n gap: 20px;\n min-height: 0;\n flex: 1;\n align-items: flex-start;\n}\n\n/* --- source tabs (top, primary) -------------------------------------------------- */\n\n.sourceTabsRow {\n display: block;\n padding: 0;\n}\n\n.sourceTabsScroll {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));\n gap: 6px;\n}\n\n.srcTabEdit {\n border: none;\n background: none;\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n padding: 2px 2px;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.srcTabEdit:hover {\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.srcTabOn .srcTabEdit {\n color: rgba(255, 255, 255, 0.85);\n}\n\n.srcTabOn .srcTabEdit:hover {\n color: #fff;\n}\n\n.srcTab,\n.srcTabOn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 24px;\n border: 1px solid var(--dsw-alias-border-l3, #d9dde3);\n border-radius: 999px;\n overflow: hidden;\n background: var(--dsw-alias-bg-layer-1, #fff);\n}\n\n.srcTabMain {\n border: none;\n background: none;\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary, #1f2328);\n padding: 2px 2px 2px 10px;\n cursor: pointer;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n flex: 1;\n}\n\n.srcTabMain:hover {\n color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n\n.srcTabOn {\n background: var(--dsw-alias-brand-primary, #4f6ef7);\n border-color: var(--dsw-alias-brand-primary, #4f6ef7);\n}\n\n.srcTabOn .srcTabMain {\n color: #fff;\n font-weight: 600;\n}\n\n.srcTabDel {\n border: none;\n background: none;\n font: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary, #9ca3af);\n padding: 2px 8px 2px 2px;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.srcTabDel:hover {\n color: var(--dsw-alias-state-error-primary, #dc2626);\n}\n\n.srcTabOn .srcTabDel {\n color: rgba(255, 255, 255, 0.85);\n}\n\n.srcTabOn .srcTabDel:hover {\n color: #fff;\n}\n\n/* --- card grid ----------------------------------------------------------------- */\n\n.grid {\n flex: 1;\n min-height: 0;\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 12px;\n min-width: 0;\n align-content: start;\n overflow-y: auto;\n scrollbar-gutter: stable;\n padding-right: 4px;\n}\n\n.list {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n overflow-y: auto;\n scrollbar-gutter: stable;\n padding-right: 4px;\n}\n\n.list .card {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px 14px;\n}\n\n.list .cardTop {\n flex: 0 0 auto;\n}\n\n.list .cardDesc {\n flex: 1;\n min-width: 200px;\n min-height: 0;\n -webkit-line-clamp: 1;\n}\n\n.list .cardActions {\n flex: 0 0 auto;\n}\n\n.list .meta {\n flex-basis: 100%;\n}\n\n.empty {\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n padding: 48px 0;\n text-align: center;\n font-size: 13px;\n grid-column: 1 / -1;\n}\n\n.card {\n background: var(--dsw-alias-bg-layer-1, #fff);\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 12px;\n padding: 12px 14px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n}\n\n.cardTop {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.cardTitle {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n}\n\n.cardName {\n font-size: 13px;\n font-weight: 600;\n line-height: 22px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.version {\n font-size: 12px;\n line-height: 20px;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n font-variant-numeric: tabular-nums;\n flex-shrink: 0;\n}\n\n.cardActions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.switchOn,\n.switchOff {\n position: relative;\n width: 38px;\n height: 22px;\n border: none;\n border-radius: 999px;\n cursor: pointer;\n padding: 0;\n flex-shrink: 0;\n transition: background-color 0.15s ease;\n}\n\n.switchOn {\n background: var(--dsw-alias-state-success-primary, #22c55e);\n}\n\n.switchOff {\n background: var(--dsw-alias-state-neutral, #d1d5db);\n}\n\n.switchOn:disabled,\n.switchOff:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.switchThumb {\n position: absolute;\n top: 3px;\n left: 3px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: #fff;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);\n transition: left 0.15s ease;\n pointer-events: none;\n}\n\n.switchOn .switchThumb {\n left: 19px;\n}\n\n.desc {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n min-height: 36px;\n margin: 0;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.meta {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n align-items: center;\n}\n\n.src {\n font-size: 12px;\n color: var(--dsw-alias-label-secondary, #9ca3af);\n text-decoration: none;\n}\n\n.tag {\n border: 1px solid var(--dsw-alias-border-l3, #d9dde3);\n color: var(--dsw-alias-label-secondary, #6b7280);\n border-radius: 4px;\n flex-shrink: 0;\n padding: 1px 6px;\n font-size: 12px;\n line-height: 18px;\n}\n\n.okState {\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-success-primary, #16a34a);\n white-space: nowrap;\n}\n\n.warnLine {\n color: var(--dsw-alias-state-warn-primary, #b45309);\n font-weight: 600;\n font-size: 12px;\n line-height: 18px;\n margin: 0;\n cursor: help;\n}\n\n.modalFooter {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n width: 100%;\n}\n\n.modalFooterLeft {\n margin-right: auto;\n display: flex;\n gap: 8px;\n}\n\n/* --- source editor modal --------------------------------------------------------- */\n\n.editorDialog {\n width: min(500px, 92vw);\n}\n\n.editorForm {\n display: flex;\n flex-direction: column;\n gap: 14px;\n min-width: 0;\n}\n\n.modeRow {\n display: flex;\n gap: 6px;\n padding: 3px;\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-2, #f3f4f6);\n align-self: flex-start;\n}\n\n.seg,\n.segOn {\n border: none;\n background: none;\n font: inherit;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n padding: 5px 14px;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.segOn {\n background: var(--dsw-alias-bg-layer-1, #fff);\n color: var(--dsw-alias-label-primary, #1f2328);\n font-weight: 600;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);\n}\n\n.fieldGroup {\n display: flex;\n flex-direction: column;\n gap: 5px;\n}\n\n.fieldLabel {\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-label-secondary, #6b7280);\n}\n\n.fieldHint {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n}\n\n.staticId {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 7px 10px;\n border: 1px dashed var(--dsw-alias-border-l3, #d9dde3);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-2, #f3f4f6);\n}\n\n.staticIdValue {\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n/* --- suite detail modal ---------------------------------------------------------- */\n\n.detailDialog {\n width: min(800px, 94vw);\n}\n\n.detailBody {\n display: flex;\n flex-direction: column;\n gap: 14px;\n max-height: 78vh;\n overflow-y: auto;\n}\n\n.detailSections {\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.detailSection {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.detailHead {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-label-secondary, #6b7280);\n border-bottom: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n padding-bottom: 4px;\n}\n\n.detailGrid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: 6px 14px;\n}\n\n.detailCell {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.detailKey {\n font-size: 12px;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n}\n\n.detailValue {\n font-size: 13px;\n color: var(--dsw-alias-label-primary, #1f2328);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.detailDesc {\n margin: 4px 0 0;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-secondary, #6b7280);\n}\n\n.mono {\n font-family: ui-monospace, Menlo, Consolas, monospace;\n font-size: 12px;\n line-height: 18px;\n word-break: break-all;\n white-space: pre-wrap;\n margin: 0;\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.detailItem {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.detailItemRow,\n.detailItemOpen {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n border: none;\n background: none;\n font: inherit;\n text-align: left;\n padding: 7px 10px;\n cursor: pointer;\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n\n.detailItemRow:hover {\n background: var(--dsw-alias-bg-hover, rgba(0, 0, 0, 0.05));\n}\n\n.detailItemOpen {\n background: var(--dsw-alias-bg-selected, rgba(79, 110, 247, 0.08));\n}\n\n.detailItemName {\n font-size: 13px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.detailItemDesc {\n flex: 1;\n min-width: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.detailChevron {\n flex-shrink: 0;\n color: var(--dsw-alias-label-tertiary, #8b93a1);\n}\n\n.skillContent {\n border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);\n padding: 10px 12px;\n max-height: 320px;\n overflow-y: auto;\n font-size: 13px;\n line-height: 20px;\n color: var(--dsw-alias-label-primary, #1f2328);\n}\n","/**\n * Suite detail modal: click one suite card to browse its internals.\n *\n * Sections: manifest overview, the skill list (each skill expands to its\n * SKILL.md body through the safe MarkdownText renderer), the validated\n * mcp.json servers (each expands to its full config), command/subagent file\n * lists, hook/LSP counts, and validation diagnostics.\n */\nimport { createElement as h, useEffect, useState, type ReactNode } from 'react'\nimport { Button, Modal, MarkdownText } from '@deepseek-ai/dsh-client-ui-primitives'\nimport { fetchSkillContent, fetchSuiteDetail, type McpServerDetail, type SuiteDetail } from './api.js'\nimport { ErrorBoundary } from './ErrorBoundary.js'\nimport type { Translate } from './index.js'\nimport css from './market.module.css'\n\nexport interface SuiteDetailModalProps {\n t: Translate\n sourceId: string\n suiteId: string\n onClose: () => void\n}\n\nexport function SuiteDetailModal({ t, sourceId, suiteId, onClose }: SuiteDetailModalProps): ReactNode {\n const [detail, setDetail] = useState<SuiteDetail | undefined>(undefined)\n const [error, setError] = useState<string | undefined>(undefined)\n const [openSkill, setOpenSkill] = useState<string | undefined>(undefined)\n const [skillText, setSkillText] = useState<string | undefined>(undefined)\n const [skillLoading, setSkillLoading] = useState(false)\n const [openMcp, setOpenMcp] = useState<string | undefined>(undefined)\n const [openPreview, setOpenPreview] = useState<string | undefined>(undefined)\n\n useEffect(() => {\n let cancelled = false\n setDetail(undefined)\n setError(undefined)\n fetchSuiteDetail(sourceId, suiteId)\n .then(value => { if (!cancelled) setDetail(value) })\n .catch(reason => { if (!cancelled) setError(reason instanceof Error ? reason.message : String(reason)) })\n return () => { cancelled = true }\n }, [sourceId, suiteId])\n\n const toggleSkill = async (name: string): Promise<void> => {\n if (openSkill === name) {\n setOpenSkill(undefined)\n return\n }\n setOpenSkill(name)\n setSkillLoading(true)\n setSkillText(undefined)\n try {\n const content = await fetchSkillContent(sourceId, suiteId, name)\n setSkillText(content.content)\n } catch (reason) {\n setSkillText(`⚠ ${reason instanceof Error ? reason.message : String(reason)}`)\n } finally {\n setSkillLoading(false)\n }\n }\n\n const toggleMcp = (key: string): void => {\n setOpenMcp(openMcp === key ? undefined : key)\n }\n\n const layoutLabel = detail === undefined\n ? ''\n : detail.layout === 'agent-plugin-v1' ? t('layoutV1') : detail.layout === 'claude-code' ? t('layoutCC') : detail.layout === 'codex' ? t('layoutCodex') : detail.layout === 'remote' ? t('layoutRemote') : t('layoutSkills')\n\n return h(Modal, {\n open: true,\n onClose,\n title: detail === undefined ? t('detailTitle') : `${detail.name}${detail.version === null ? '' : ` v${detail.version}`}`,\n description: detail === undefined ? undefined : t('detailHint'),\n closeLabel: t('cancel'),\n className: css.detailDialog,\n contentClassName: css.detailBody,\n footer: h('div', { className: css.modalFooter },\n h(Button, { variant: 'ghost', onClick: onClose }, t('cancel')),\n ),\n children: h(ErrorBoundary, {\n fallback: boundaryError => h('div', { className: css.warnLine }, `${t('actionFail')}: ${boundaryError.message}`),\n children: error !== undefined\n ? h('div', { className: css.warnLine }, error)\n : detail === undefined\n ? h('div', { className: css.empty }, t('loading'))\n : h('div', { className: css.detailSections },\n h('section', { className: css.detailSection },\n h('h4', { className: css.detailHead }, t('overviewSection')),\n h('div', { className: css.detailGrid },\n h('div', { className: css.detailCell }, h('span', { className: css.detailKey }, t('sourceLabel')), h('span', { className: css.detailValue }, detail.sourceId)),\n h('div', { className: css.detailCell }, h('span', { className: css.detailKey }, t('dimensionLabel')), h('span', { className: css.detailValue }, detail.dimension === 'user' ? t('dimensionUser') : t('dimensionProject'))),\n h('div', { className: css.detailCell }, h('span', { className: css.detailKey }, t('layoutLabel')), h('span', { className: css.detailValue }, layoutLabel)),\n h('div', { className: css.detailCell }, h('span', { className: css.detailKey }, t('statusLabel')), h('span', { className: detail.enabled ? css.okState : css.detailValue }, detail.installed ? (detail.enabled ? t('installedBadge') : t('disabledLabel')) : t('notInstalledLabel'))),\n detail.author === null ? null : h('div', { className: css.detailCell }, h('span', { className: css.detailKey }, t('authorLabel')), h('span', { className: css.detailValue }, detail.author)),\n detail.keywords.length === 0 ? null : h('div', { className: css.detailCell }, h('span', { className: css.detailKey }, t('keywordsLabel')), h('span', { className: css.detailValue }, detail.keywords.join(', '))),\n ),\n detail.description === null ? null : h('p', { className: css.detailDesc }, detail.description),\n h('div', { className: css.detailCell }, h('span', { className: css.detailKey }, t('rootLabel')), h('span', { className: css.mono }, detail.root)),\n ),\n h('section', { className: css.detailSection },\n h('h4', { className: css.detailHead }, `${t('skillsSection')} (${detail.skills.length})`),\n detail.skills.length === 0\n ? h('div', { className: css.sidebarEmpty }, '—')\n : detail.skills.map(skill => h('div', { key: skill.name, className: css.detailItem },\n h('button', {\n type: 'button',\n className: openSkill === skill.name ? css.detailItemOpen : css.detailItemRow,\n onClick: () => { void toggleSkill(skill.name) },\n },\n h('span', { className: css.detailItemName }, skill.name),\n h('span', { className: css.detailItemDesc }, skill.description),\n h('span', { className: css.detailChevron }, openSkill === skill.name ? '▾' : '▸'),\n ),\n openSkill !== skill.name ? null : h('div', { className: css.skillContent },\n skillLoading ? t('loading') : h(MarkdownText, { text: skillText ?? '' }),\n ),\n )),\n ),\n h('section', { className: css.detailSection },\n h('h4', { className: css.detailHead }, `${t('mcpSection')} (${detail.mcpServers.length})`),\n detail.mcpServers.length === 0\n ? h('div', { className: css.sidebarEmpty }, '—')\n : detail.mcpServers.map(server => h('div', { key: server.key, className: css.detailItem },\n h('button', {\n type: 'button',\n className: openMcp === server.key ? css.detailItemOpen : css.detailItemRow,\n onClick: () => toggleMcp(server.key),\n },\n h('span', { className: css.detailItemName }, server.key),\n h('span', { className: css.detailItemDesc }, mcpSummary(server)),\n h('span', { className: css.detailChevron }, openMcp === server.key ? '▾' : '▸'),\n ),\n openMcp !== server.key ? null : h('pre', { className: css.mono }, JSON.stringify(server, null, 2)),\n )),\n ),\n h('section', { className: css.detailSection },\n h('h4', { className: css.detailHead }, `${t('commandsSection')} (${detail.commands.length})`),\n detail.commands.length === 0 ? h('div', { className: css.sidebarEmpty }, '—')\n : detail.commands.map(command => h(PreviewRow, {\n key: `c:${command.name}`,\n t,\n name: `/${command.name}`,\n description: command.description,\n open: openPreview === `c:${command.name}`,\n onToggle: () => setOpenPreview(openPreview === `c:${command.name}` ? undefined : `c:${command.name}`),\n children: h(MarkdownText, { text: command.content }),\n })),\n ),\n h('section', { className: css.detailSection },\n h('h4', { className: css.detailHead }, `${t('agentsSection')} (${detail.agents.length})`),\n detail.agents.length === 0 ? h('div', { className: css.sidebarEmpty }, '—')\n : detail.agents.map(agent => h(PreviewRow, {\n key: `a:${agent.name}`,\n t,\n name: agent.name,\n description: agent.description,\n open: openPreview === `a:${agent.name}`,\n onToggle: () => setOpenPreview(openPreview === `a:${agent.name}` ? undefined : `a:${agent.name}`),\n children: h(MarkdownText, { text: agent.content }),\n })),\n ),\n h('section', { className: css.detailSection },\n h('h4', { className: css.detailHead }, `${t('hooksLabel')} (${detail.hooks.count})`),\n detail.hooks.count === 0 ? h('div', { className: css.sidebarEmpty }, '—')\n : detail.hooks.entries.map((hook, index) => h(PreviewRow, {\n key: `h:${index}`,\n t,\n name: hook.event,\n description: hook.command,\n open: openPreview === `h:${index}`,\n onToggle: () => setOpenPreview(openPreview === `h:${index}` ? undefined : `h:${index}`),\n children: h('pre', { className: css.mono }, JSON.stringify(hook, null, 2)),\n })),\n ),\n h('section', { className: css.detailSection },\n h('h4', { className: css.detailHead }, `${t('lspSection')} (${detail.lsp.length})`),\n detail.lsp.length === 0 ? h('div', { className: css.sidebarEmpty }, '—')\n : detail.lsp.map(entry => h(PreviewRow, {\n key: `l:${entry.name}`,\n t,\n name: entry.name,\n open: openPreview === `l:${entry.name}`,\n onToggle: () => setOpenPreview(openPreview === `l:${entry.name}` ? undefined : `l:${entry.name}`),\n children: h('pre', { className: css.mono }, entry.content),\n })),\n ),\n detail.errors.length === 0 ? null : h('section', { className: css.detailSection },\n h('h4', { className: css.detailHead }, `${t('errors')} (${detail.errors.length})`),\n detail.errors.map((entry, index) => h('div', { key: index, className: css.warnLine }, entry)),\n ),\n ),\n }),\n })\n}\n\nfunction mcpSummary(server: McpServerDetail): string {\n if (server.type === 'stdio') return server.command ?? server.type\n return server.url ?? server.type\n}\n\nfunction PreviewRow(props: {\n t: Translate\n name: string\n description?: string\n open: boolean\n onToggle: () => void\n children: ReactNode\n}): ReactNode {\n const { t: _t, name, description, open, onToggle, children } = props\n return h('div', { className: css.detailItem },\n h('button', {\n type: 'button',\n className: open ? css.detailItemOpen : css.detailItemRow,\n onClick: onToggle,\n },\n h('span', { className: css.detailItemName }, name),\n description === undefined ? null : h('span', { className: css.detailItemDesc }, description),\n h('span', { className: css.detailChevron }, open ? '▾' : '▸'),\n ),\n open ? h('div', { className: css.skillContent }, children) : null,\n )\n}\n","/**\n * The Agent Plugins Market settings section.\n *\n * Layout: repository sources run along the TOP as chips (全部 first), with\n * edit-current / add / refresh-all controls on the right; below sit search,\n * status tabs, and the card grid. Colors ride the dsh --dsw-alias-* tokens\n * with light-mode fallbacks so the page follows the active theme.\n */\nimport { createElement as h, useCallback, useEffect, useMemo, useState, type ReactElement, type ReactNode } from 'react'\nimport {\n Button,\n Input,\n Modal,\n Toast,\n Tooltip,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { fetchOverview, postAction, type OverviewData, type SourceOverview, type SuiteCardData } from './api.js'\nimport type { Translate } from './index.js'\nimport { ErrorBoundary } from './ErrorBoundary.js'\nimport { SuiteDetailModal } from './SuiteDetail.js'\nimport css from './market.module.css'\n\nexport interface MarketSectionProps {\n t: Translate\n}\n\ntype Tab = 'all' | 'installed' | 'uninstalled'\ntype Category = 'all' | string\ntype ViewMode = 'grid' | 'list'\n\ninterface ToastState {\n key: number\n message: string\n}\n\ninterface ConfirmState {\n kind: 'uninstall' | 'removeSource'\n sourceId: string\n suiteId?: string\n}\n\ntype EditorState =\n | { mode: 'edit'; source: SourceOverview }\n | { mode: 'add' }\n | undefined\n\nconst EMPTY_OVERVIEW: OverviewData = { sources: [], suites: [], totals: { all: 0, installed: 0, enabled: 0 }, roots: { user: '', data: '' } }\n\nexport function MarketSection({ t }: MarketSectionProps): ReactNode {\n const [overview, setOverview] = useState<OverviewData>(EMPTY_OVERVIEW)\n const [loading, setLoading] = useState(true)\n const [search, setSearch] = useState('')\n const [tab, setTab] = useState<Tab>('all')\n const [category, setCategory] = useState<Category>('all')\n const [view, setView] = useState<ViewMode>('grid')\n const [busy, setBusy] = useState<string | undefined>(undefined)\n const [toast, setToast] = useState<ToastState | undefined>(undefined)\n const [confirm, setConfirm] = useState<ConfirmState | undefined>(undefined)\n const [editor, setEditor] = useState<EditorState>(undefined)\n const [detail, setDetail] = useState<{ sourceId: string; suiteId: string } | undefined>(undefined)\n\n const refresh = useCallback(async () => {\n try {\n setOverview(await fetchOverview())\n } catch {\n setToast({ key: Date.now(), message: t('loadFail') })\n } finally {\n setLoading(false)\n }\n }, [t])\n\n useEffect(() => {\n void refresh()\n }, [refresh])\n\n const action = useCallback(async (key: string, path: string, body: Record<string, unknown>): Promise<boolean> => {\n setBusy(key)\n try {\n await postAction(path, body)\n await refresh()\n return true\n } catch (error) {\n setToast({ key: Date.now(), message: `${t('actionFail')}: ${error instanceof Error ? error.message : String(error)}` })\n return false\n } finally {\n setBusy(undefined)\n }\n }, [refresh, t])\n\n // Scope totals follow the selected source pill; without a selection they\n // mirror the overview-wide totals (全部 / 已安装 / 未安装 stay consistent\n // with the visible set).\n const scopeTotals = useMemo(() => {\n if (category === 'all') return overview.totals\n const scoped = overview.suites.filter(suite => suite.sourceId === category)\n return {\n all: scoped.length,\n installed: scoped.filter(suite => suite.installed).length,\n enabled: scoped.filter(suite => suite.enabled).length,\n }\n }, [overview, category])\n\n const filtered = useMemo(() => {\n const needle = search.trim().toLowerCase()\n return overview.suites.filter((suite) => {\n if (category !== 'all' && suite.sourceId !== category) return false\n if (tab === 'installed' && !suite.installed) return false\n if (tab === 'uninstalled' && suite.installed) return false\n if (needle === '') return true\n const haystack = `${suite.name} ${suite.description ?? ''} ${suite.keywords.join(' ')}`.toLowerCase()\n return haystack.includes(needle)\n })\n }, [overview, search, tab, category])\n\n const openUninstall = useCallback((suite: SuiteCardData) => {\n setConfirm({ kind: 'uninstall', sourceId: suite.sourceId, suiteId: suite.suiteId })\n }, [])\n\n const confirmAction = useCallback(async () => {\n if (confirm === undefined) return\n if (confirm.kind === 'uninstall' && confirm.suiteId !== undefined) {\n await action(`u:${confirm.suiteId}`, 'uninstall', { sourceId: confirm.sourceId, suiteId: confirm.suiteId })\n } else if (confirm.kind === 'removeSource') {\n await action(`s:${confirm.sourceId}`, 'sources/remove', { id: confirm.sourceId })\n if (category === confirm.sourceId) setCategory('all')\n }\n setConfirm(undefined)\n }, [confirm, action, category])\n\n const selectedSource = category === 'all' ? undefined : overview.sources.find(source => source.id === category)\n\n return h(ErrorBoundary, {\n fallback: error => h('div', { className: css.empty }, `${t('actionFail')}: ${error.message}`),\n children: h('div', { className: css.market },\n h('header', { className: css.header },\n h('div', { className: css.titleRow },\n h('h2', { className: css.title }, t('nav')),\n h('p', { className: css.sub }, t('subtitle')),\n h('div', { className: css.spacer }),\n h('div', { className: css.searchGroup },\n h(Button, { variant: 'ghost', size: 'sm', title: t('addSource'), onClick: () => setEditor({ mode: 'add' }) }, '+'),\n h(Button, { variant: 'ghost', size: 'sm', title: t('refreshAll'), onClick: () => { void action('s:refresh:all', 'sources/refresh', {}) } }, '↻'),\n h('div', { className: css.searchWrap },\n h(Input, { className: css.searchInput, placeholder: t('searchPh'), value: search, onChange: event => setSearch((event.target as HTMLInputElement).value) })),\n ),\n ),\n h('div', { className: css.sourceTabsRow },\n h('div', { className: css.sourceTabsScroll },\n h(SourceTab, {\n key: '__all__',\n t,\n active: category === 'all',\n label: `${t('tabAll')} ${overview.totals.all}`,\n onSelect: () => setCategory('all'),\n }),\n ...[...overview.sources].sort((a, b) => a.id.localeCompare(b.id)).map(source => h(SourceTab, {\n key: source.id,\n t,\n active: category === source.id,\n label: `${source.id}${source.local === true ? ` · ${t('sourceLocal')}` : ''} ${source.suiteIds.length}${source.cloned === false ? ' ⚠' : ''}`,\n onSelect: () => setCategory(source.id),\n onDelete: () => setConfirm({ kind: 'removeSource', sourceId: source.id }),\n onEdit: selectedSource?.id === source.id ? () => setEditor({ mode: 'edit', source: source }) : undefined,\n })),\n ),\n ),\n h('div', { className: css.tabRow },\n h(TabButton, { t, active: tab === 'all', label: `${t('tabAll')} ${scopeTotals.all}`, onClick: () => setTab('all') }),\n h(TabButton, { t, active: tab === 'installed', label: `${t('tabInstalled')} ${scopeTotals.installed}`, onClick: () => setTab('installed') }),\n h(TabButton, { t, active: tab === 'uninstalled', label: `${t('tabUninstalled')} ${scopeTotals.all - scopeTotals.installed}`, onClick: () => setTab('uninstalled') }),\n h('div', { className: css.tabGap }),\n h('button', {\n type: 'button',\n className: css.viewSwitch,\n onClick: () => setView(view === 'grid' ? 'list' : 'grid'),\n }, view === 'grid' ? t('list') : t('grid')),\n ),\n ),\n h('main', { className: view === 'grid' ? css.grid : css.list },\n loading\n ? h('div', { className: css.empty }, '…')\n : filtered.length === 0\n ? h('div', { className: css.empty }, tab === 'installed' ? t('installedEmpty') : t('empty'))\n : filtered.map(suite => h(SuiteCard, {\n key: `${suite.sourceId}/${suite.suiteId}`,\n t, suite,\n busy: busy !== undefined,\n onOpen: () => setDetail({ sourceId: suite.sourceId, suiteId: suite.suiteId }),\n onInstall: () => { void action(`i:${suite.suiteId}`, 'install', { sourceId: suite.sourceId, suiteId: suite.suiteId }) },\n onToggle: () => { void action(`e:${suite.suiteId}`, 'set-enabled', { sourceId: suite.sourceId, suiteId: suite.suiteId, enabled: !suite.enabled }) },\n onRefresh: () => { void action(`r:${suite.suiteId}`, 'sources/refresh', { id: suite.sourceId }) },\n onUninstall: () => openUninstall(suite),\n })),\n ),\n toast === undefined ? null : h(Toast, { key: toast.key, text: toast.message, onDone: () => setToast(undefined) }),\n confirm === undefined ? null : h(Modal, {\n open: true,\n onClose: () => setConfirm(undefined),\n title: confirm.kind === 'uninstall' ? t('uninstallConfirmTitle') : `${t('removeSourceConfirmTitle')}「${confirm.sourceId}」`,\n closeLabel: t('cancel'),\n description: confirm.kind === 'uninstall' ? t('uninstallConfirmDesc') : t('removeSourceConfirmDesc'),\n footer: h('div', { className: css.modalFooter },\n h(Button, { variant: 'ghost', onClick: () => setConfirm(undefined) }, t('cancel')),\n h(Button, { variant: 'primary', onClick: () => { void confirmAction() } }, t('confirmDelete')),\n ),\n }),\n detail === undefined ? null : h(SuiteDetailModal, {\n t,\n sourceId: detail.sourceId,\n suiteId: detail.suiteId,\n onClose: () => setDetail(undefined),\n }),\n\n editor === undefined ? null : h(SourceEditorModal, {\n t,\n editor,\n busy: busy !== undefined,\n onClose: () => setEditor(undefined),\n onSave: async (url, branch, local) => {\n const key = editor.mode === 'edit' ? `s:edit:${editor.source.id}` : `s:add:${url}`\n const body = { url, ...branch === '' ? {} : { branch }, local }\n if (editor.mode === 'add') {\n setBusy(key)\n try {\n const payload = await postAction('sources/add', body)\n const derived = (payload['source'] as { id?: string } | undefined)?.id\n await refresh()\n setEditor(undefined)\n if (derived !== undefined) setCategory(derived)\n return true\n } catch (error) {\n setToast({ key: Date.now(), message: `${t('actionFail')}: ${error instanceof Error ? error.message : String(error)}` })\n return false\n } finally {\n setBusy(undefined)\n }\n }\n const ok = await action(key, 'sources/update', { id: editor.source.id, ...body })\n if (ok) setEditor(undefined)\n return ok\n },\n onRemove: async (id) => {\n setConfirm({ kind: 'removeSource', sourceId: id })\n setEditor(undefined)\n },\n }),\n )\n })\n}\n\nfunction TabButton({ t: _t, active, label, onClick }: { t: Translate; active: boolean; label: string; onClick: () => void }): ReactNode {\n return h('button', { type: 'button', className: active ? css.tabOn : css.tab, onClick }, label)\n}\n\n/** A source tab with a trailing delete control (deletion confirms at the section level). */\nfunction SourceTab(props: {\n t: Translate\n active?: boolean\n label: string\n onSelect: () => void\n onDelete?: () => void\n onEdit?: () => void\n}): ReactNode {\n const { t, active = false, label, onSelect, onDelete, onEdit } = props\n return h('div', { className: active ? css.srcTabOn : css.srcTab },\n h('button', { type: 'button', className: css.srcTabMain, onClick: onSelect }, label),\n onEdit === undefined ? null : h('button', {\n type: 'button',\n className: css.srcTabEdit,\n title: t('editSource'),\n onClick: (event: { stopPropagation(): void }) => { event.stopPropagation(); onEdit() },\n }, '✎'),\n onDelete === undefined ? null : h('button', {\n type: 'button',\n className: css.srcTabDel,\n title: t('remove'),\n onClick: (event: { stopPropagation(): void }) => { event.stopPropagation(); onDelete() },\n }, '×'),\n )\n}\n\nfunction SourceEditorModal(props: {\n t: Translate\n editor: Exclude<EditorState, undefined>\n busy: boolean\n onClose: () => void\n onSave: (url: string, branch: string, local: boolean) => Promise<boolean>\n onRemove: (id: string) => void\n}): ReactNode {\n const { t, editor } = props\n const [local, setLocal] = useState(editor.mode === 'edit' && editor.source.local === true)\n const [url, setUrl] = useState(editor.mode === 'edit' ? editor.source.url : '')\n const [branch, setBranch] = useState(editor.mode === 'edit' ? (editor.source.branch ?? '') : '')\n const id = editor.mode === 'edit' ? editor.source.id : ''\n const title = editor.mode === 'edit' ? t('editSourceTitle') : t('addSourceTitle')\n return h(Modal, {\n open: true,\n onClose: props.onClose,\n title,\n description: t('editorHint'),\n closeLabel: t('cancel'),\n className: css.editorDialog,\n footer: h('div', { className: css.modalFooter },\n h('div', { className: css.modalFooterLeft },\n editor.mode === 'edit'\n ? h(Button, { variant: 'ghost', onClick: () => props.onRemove(id) }, `🗑 ${t('remove')}`)\n : null,\n ),\n h(Button, { variant: 'ghost', onClick: props.onClose }, t('cancel')),\n h(Button, {\n variant: 'primary',\n disabled: props.busy,\n onClick: () => { void props.onSave(url.trim(), branch.trim(), local) },\n }, t('save')),\n ),\n children: h('div', { className: css.editorForm },\n h('div', { className: css.modeRow },\n h('button', {\n type: 'button',\n className: local ? css.seg : css.segOn,\n onClick: () => setLocal(false),\n }, t('sourceModeGit')),\n h('button', {\n type: 'button',\n className: local ? css.segOn : css.seg,\n onClick: () => setLocal(true),\n }, t('sourceModeLocal')),\n ),\n editor.mode === 'edit'\n ? h('div', { className: css.fieldGroup },\n h('label', { className: css.fieldLabel }, t('sourceIdPh')),\n h('div', { className: css.staticId },\n h('span', { className: css.staticIdValue }, id),\n h('span', { className: css.fieldHint }, t('idFixed')),\n ),\n )\n : null,\n h('div', { className: css.fieldGroup },\n h('label', { className: css.fieldLabel }, local ? t('sourceUrlLocalPh') : t('sourceUrlPh')),\n h(Input, { placeholder: local ? t('sourceUrlLocalPh') : t('sourceUrlPh'), value: url, onChange: event => setUrl((event.target as HTMLInputElement).value) }),\n h('span', { className: css.fieldHint }, local ? t('urlLocalHint') : t('urlGitHint')),\n ),\n local ? null : h('div', { className: css.fieldGroup },\n h('label', { className: css.fieldLabel }, t('branchPh')),\n h(Input, { placeholder: t('branchPh'), value: branch, onChange: event => setBranch((event.target as HTMLInputElement).value) }),\n h('span', { className: css.fieldHint }, t('branchHint')),\n ),\n ),\n })\n}\n\n/** A green/gray switch control for suite enable state. */\nfunction ToggleSwitch(props: {\n on: boolean\n disabled?: boolean\n title?: string\n onChange: () => void\n}): ReactNode {\n return h('button', {\n type: 'button',\n role: 'switch',\n 'aria-checked': props.on,\n title: props.title,\n disabled: props.disabled,\n className: props.on ? css.switchOn : css.switchOff,\n onClick: (event: { stopPropagation(): void }) => { event.stopPropagation(); props.onChange() },\n }, h('span', { className: css.switchThumb }))\n}\n\nfunction SuiteCard(props: {\n t: Translate\n suite: SuiteCardData\n busy: boolean\n onOpen: () => void\n onInstall: () => void\n onToggle: () => void\n onRefresh: () => void\n onUninstall: () => void\n}): ReactNode {\n const { t, suite, busy } = props\n const tags: Array<[string, number]> = ([\n [t('surfaceSkills'), suite.surfaces.skills],\n [t('surfaceMcp'), suite.surfaces.mcp],\n [t('surfaceHooks'), suite.surfaces.hooks],\n [t('surfaceCommands'), suite.surfaces.commands],\n [t('surfaceAgents'), suite.surfaces.agents],\n [t('surfaceLsp'), suite.surfaces.lsp],\n ] as Array<[string, number]>).filter(([, count]) => count > 0)\n const layoutLabel = suite.layout === 'agent-plugin-v1' ? t('layoutV1') : suite.layout === 'claude-code' ? t('layoutCC') : suite.layout === 'codex' ? t('layoutCodex') : suite.layout === 'universal' ? t('layoutUniversal') : suite.layout === 'cursor' ? t('layoutCursor') : suite.layout === 'kimi' ? t('layoutKimi') : suite.layout === 'remote' ? t('layoutRemote') : t('layoutSkills')\n const isRemote = suite.remoteUrl !== undefined\n const stop = (callback: () => void) => (event: { stopPropagation(): void }) => { event.stopPropagation(); callback() }\n return h('article', { className: css.card, onClick: props.onOpen },\n h('div', { className: css.cardTop },\n h('div', { className: css.cardTitle },\n h('span', { className: css.cardName }, suite.name),\n suite.version === undefined ? null : h('span', { className: css.version }, `v${suite.version}`),\n ),\n h('div', { className: css.cardActions },\n suite.installed\n ? h(ToggleSwitch, {\n on: suite.enabled,\n disabled: busy,\n title: suite.enabled ? t('disable') : t('enable'),\n onChange: props.onToggle,\n })\n : h(Button, {\n variant: 'primary', size: 'sm', disabled: busy || isRemote,\n title: isRemote ? suite.remoteUrl : undefined,\n onClick: stop(props.onInstall),\n }, isRemote ? t('remoteRef') : t('install')),\n suite.installed ? h(Button, { variant: 'ghost', size: 'sm', title: t('refresh'), disabled: busy, onClick: stop(props.onRefresh) }, '↻') : null,\n suite.installed ? h(Button, { variant: 'ghost', size: 'sm', title: t('uninstall'), disabled: busy, onClick: stop(props.onUninstall) }, '🗑') : null,\n ),\n ),\n h('p', { className: css.desc }, suite.description ?? ''),\n h('div', { className: css.meta },\n h('span', { className: css.src }, `${suite.sourceId} · ${isRemote ? t('remoteRef') : (suite.dimension === 'user' ? t('dimensionUser') : t('dimensionProject'))}`),\n h('span', { className: css.tag }, layoutLabel),\n suite.installed ? h('span', { className: suite.enabled ? css.okState : css.tag }, suite.enabled ? `✓ ${t('installedBadge')}` : t('installedBadge')) : null,\n ...tags.map(([label, count]) => h('span', { key: label, className: css.tag }, `${label} ${count}`)),\n suite.errors.length === 0 ? null : h(Tooltip, {\n label: suite.errors.slice(0, 8).join(';'),\n children: h('span', { className: css.warnLine }, `⚠ ${t('errors')} ${suite.errors.length}`) as unknown as ReactElement,\n }),\n ),\n )\n}\n","/**\n * dsh-agent-plugins-market client: registers the Agent Plugins Market section inside the Web\n * GUI's settings dialog (the same settings.section seat dshmarket uses).\n * Mirrors the market's integration contract: the bundle's only externals are\n * react and the injected `dsh.client.inject` module table, so it cannot reach\n * packages the host does not serve.\n */\nimport { createElement as h } from 'react'\nimport * as primitives from '@deepseek-ai/dsh-client-ui-primitives'\nimport { en, zh } from './locales.js'\nimport { MarketSection } from './MarketSection.js'\n\nconst NS = 'dsh-agent-plugins-market'\n\nexport type Translate = (key: string) => string\n\n/** The subset of the locale service this plugin touches. */\ninterface LocaleService {\n register(namespace: string, dicts: { zh: Record<string, string>; en: Record<string, string> }): unknown\n bind(namespace: string): Translate\n}\n\n/** The subset of the slots service this plugin touches. */\ninterface SlotsService {\n inject(slot: string, register: () => unknown): void\n register(meta: Record<string, unknown>, component: () => unknown): unknown\n}\n\n/** The client cordis context this plugin relies on (structural subset). */\ninterface SuiteClientContext {\n effect(callback: () => unknown, label?: string): void\n locale: LocaleService\n slots: SlotsService\n}\n\nexport const name = 'dsh-agent-plugins-market'\nexport const inject = ['slots', 'locale']\n\n/** Primitives this section renders with; absent exports degrade the whole section. */\nexport const REQUIRED_PRIMITIVES = ['Button', 'Input', 'Modal', 'Toast', 'Tooltip'] as const\n\n/** Detect host primitives that predate the exports this UI relies on. */\nexport function missingPrimitives(module: Record<string, unknown>, required: readonly string[] = REQUIRED_PRIMITIVES): string[] {\n return required.filter(name => module[name] === undefined)\n}\n\nexport function apply(ctx: SuiteClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-agent-plugins: dictionaries')\n const t = ctx.locale.bind(NS)\n\n const gaps = missingPrimitives(primitives as unknown as Record<string, unknown>)\n if (gaps.length > 0) {\n console.warn(`[dsh-agent-plugins-market] host ui-primitives missing ${gaps.join(', ')} — Agent Plugins Market section disabled (dsh web >= 0.1.0-rc.6 required)`)\n return\n }\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'agent-plugin',\n order: 45,\n label: () => t('nav'),\n locale: NS,\n inject: () => ({ t }),\n }, () => h(MarketSection, {\n t,\n })))\n}\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ # dsh bundle patch: inserts this plugin into a profile's layer stack.
2
+ - insert:
3
+ - id: dsh-agent-plugins-market
4
+ name: 'dsh-agent-plugins-market'
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Claude Code command compatibility: `commands/*.md` of enabled suites
3
+ * register as dsh slash commands.
4
+ *
5
+ * A CC command is a prompt template the model executes (its body carries
6
+ * `$ARGUMENTS` and execution rules), so the handler maps it onto the
7
+ * harness's follow-up mechanism: the template with `$ARGUMENTS` substituted
8
+ * becomes one durable user-role follow-up message on the receiving agent.
9
+ * Registrations reconcile on every enable/disable/install/uninstall; a
10
+ * broken command file or an unavailable `ctx.commands` is contained per
11
+ * command and reported as a diagnostic.
12
+ */
13
+ import { readFile, readdir } from 'node:fs/promises';
14
+ import { join } from 'node:path';
15
+ import { parse as parseYaml } from 'yaml';
16
+ import { parseSkillFrontmatter, stripFrontmatter } from './skills-parse.js';
17
+ const COMMAND_NAME = /^[a-z][a-z0-9_-]*$/;
18
+ export class CommandMountRegistry {
19
+ ctx;
20
+ live = new Map();
21
+ constructor(ctx) {
22
+ this.ctx = ctx;
23
+ }
24
+ /** Register/unregister suite commands and agent-commands to match the enabled suites exactly. */
25
+ async reconcile(enabledSuites) {
26
+ const diagnostics = [];
27
+ const wanted = new Map();
28
+ for (const suite of enabledSuites) {
29
+ for (const spec of [...await readCommands(suite.root), ...await readAgents(suite.root)]) {
30
+ const key = `${suite.id}/${spec.name}`;
31
+ wanted.set(key, { ...spec, suiteId: suite.id, suiteName: suite.manifest.name });
32
+ }
33
+ }
34
+ for (const [key, disposer] of [...this.live]) {
35
+ if (!wanted.has(key)) {
36
+ disposer();
37
+ this.live.delete(key);
38
+ }
39
+ }
40
+ const host = this.ctx;
41
+ if (typeof host.commands?.register !== 'function') {
42
+ if (wanted.size > 0)
43
+ diagnostics.push({ suiteId: '', command: '', reason: 'ctx.commands is not available in this profile' });
44
+ return diagnostics;
45
+ }
46
+ for (const [key, spec] of wanted) {
47
+ if (this.live.has(key))
48
+ continue;
49
+ try {
50
+ const disposer = host.commands.register({
51
+ name: spec.name,
52
+ description: `[${spec.suiteName}] ${spec.description}`,
53
+ ...spec.hint === undefined ? {} : { input: { hint: spec.hint } },
54
+ handler: (invocation) => {
55
+ const agent = invocation.agent;
56
+ const text = [
57
+ `[Agent Plugins 命令 /${spec.name}(来自 ${spec.suiteId})]`,
58
+ '',
59
+ spec.body.replaceAll('$ARGUMENTS', invocation.rawInput.trim()),
60
+ ].join('\n');
61
+ agent.followup({ content: [{ type: 'text', text }], source: { kind: 'plugin', plugin: 'dsh-agent-plugins-market' } });
62
+ return { kind: 'success', text: `/${spec.name} 已转交模型执行(${spec.suiteId})` };
63
+ },
64
+ });
65
+ this.live.set(key, disposer);
66
+ }
67
+ catch (error) {
68
+ diagnostics.push({ suiteId: spec.suiteId, command: spec.name, reason: error instanceof Error ? error.message : String(error) });
69
+ }
70
+ }
71
+ return diagnostics;
72
+ }
73
+ /** Dispose every registered command; used at plugin teardown. */
74
+ disposeAll() {
75
+ for (const disposer of [...this.live.values()])
76
+ disposer();
77
+ this.live.clear();
78
+ }
79
+ }
80
+ /** Parse `commands/*.md` of one suite root (Claude Code format). */
81
+ export async function readCommands(root) {
82
+ let entries;
83
+ try {
84
+ entries = await readdir(join(root, 'commands'));
85
+ }
86
+ catch {
87
+ return [];
88
+ }
89
+ const specs = [];
90
+ for (const entry of entries) {
91
+ if (!entry.endsWith('.md'))
92
+ continue;
93
+ const name = entry.slice(0, -3);
94
+ if (!COMMAND_NAME.test(name))
95
+ continue;
96
+ let text;
97
+ try {
98
+ text = await readFile(join(root, 'commands', entry), 'utf8');
99
+ }
100
+ catch {
101
+ continue;
102
+ }
103
+ const meta = commandMeta(text);
104
+ const description = meta?.description ?? firstLine(text);
105
+ if (description === undefined)
106
+ continue;
107
+ specs.push({ name, description, hint: meta?.hint, body: stripFrontmatter(text) });
108
+ }
109
+ return specs;
110
+ }
111
+ /** Parse `agents/*.md` of one suite root into `agent-<name>` commands so
112
+ * subagents are selectable from the slash-command menu, grouped by the
113
+ * `agent-` prefix (the harness command UI has no group headers). */
114
+ export async function readAgents(root) {
115
+ let entries;
116
+ try {
117
+ entries = await readdir(join(root, 'agents'));
118
+ }
119
+ catch {
120
+ return [];
121
+ }
122
+ const specs = [];
123
+ for (const entry of entries) {
124
+ if (!entry.endsWith('.md'))
125
+ continue;
126
+ const name = `agent-${entry.slice(0, -3)}`;
127
+ if (!COMMAND_NAME.test(name))
128
+ continue;
129
+ let text;
130
+ try {
131
+ text = await readFile(join(root, 'agents', entry), 'utf8');
132
+ }
133
+ catch {
134
+ continue;
135
+ }
136
+ const parsed = parseSkillFrontmatter(text, name);
137
+ const description = typeof parsed === 'string' ? parsed : parsed.description;
138
+ if (description === undefined)
139
+ continue;
140
+ specs.push({ name, description, hint: '子代理', body: stripFrontmatter(text) });
141
+ }
142
+ return specs;
143
+ }
144
+ function commandMeta(text) {
145
+ const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(text);
146
+ if (match === null)
147
+ return undefined;
148
+ try {
149
+ const raw = parseYaml(match[1]);
150
+ if (typeof raw !== 'object' || raw === null)
151
+ return undefined;
152
+ const record = raw;
153
+ const meta = {};
154
+ const description = record['description'];
155
+ if (typeof description === 'string' && description.trim() !== '')
156
+ meta.description = description.trim();
157
+ const hint = record['argument-hint'];
158
+ if (typeof hint === 'string' && hint.trim() !== '')
159
+ meta.hint = hint.trim();
160
+ return meta;
161
+ }
162
+ catch {
163
+ return undefined;
164
+ }
165
+ }
166
+ function firstLine(text) {
167
+ const line = text.split('\n').map(line => line.trim()).find(line => line !== '');
168
+ return line;
169
+ }
package/lib/context.js ADDED
@@ -0,0 +1,80 @@
1
+ import { deriveServerName } from './mcp-config.js';
2
+ /** Mount the agent_plugins query tool. */
3
+ export function mountSuiteContext(ctx, manager) {
4
+ const disposers = [];
5
+ ctx.inject(['tools'], (toolsCtx) => {
6
+ const tools = toolsCtx;
7
+ if (typeof tools.tools?.register !== 'function')
8
+ return;
9
+ const parameters = {
10
+ type: 'object',
11
+ properties: {
12
+ action: { type: 'string', enum: ['list', 'info'], description: 'list: 列出全部 Agent Plugins;info: 查看单个 Agent Plugins 详情' },
13
+ suiteId: { type: 'string', description: 'info 动作时必填:Agent Plugins id' },
14
+ sourceId: { type: 'string', description: 'info 动作时可选:Agent Plugins 所属仓库源 id' },
15
+ },
16
+ required: ['action'],
17
+ additionalProperties: false,
18
+ };
19
+ const outputSchema = {
20
+ type: 'object',
21
+ properties: {
22
+ suites: { type: 'array', items: { type: 'object' } },
23
+ skills: { type: 'array', items: { type: 'object' } },
24
+ mcpServers: { type: 'array', items: { type: 'object' } },
25
+ note: { type: 'string' },
26
+ },
27
+ };
28
+ const dispose = tools.tools.register({
29
+ name: 'agent_plugins',
30
+ description: '查询当前会话启用的 Agent Plugins:列出插件清单、技能与 MCP 工具前缀;技能正文通过 skill 工具加载。',
31
+ parameters,
32
+ renderIntent: 'generic',
33
+ output: {
34
+ schema: outputSchema,
35
+ render: (_args, value) => {
36
+ const text = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
37
+ return [{ type: 'text', text }];
38
+ },
39
+ },
40
+ execute: async (args) => {
41
+ const record = args;
42
+ const action = record['action'];
43
+ if (action === 'list')
44
+ return listPayload(await manager.enabledUserSuites());
45
+ if (action === 'info')
46
+ return infoPayload(await manager.enabledUserSuites(), record);
47
+ return { suites: [], skills: [], mcpServers: [], note: `unknown action ${JSON.stringify(action)}` };
48
+ },
49
+ });
50
+ disposers.push(dispose);
51
+ });
52
+ return () => {
53
+ for (const dispose of disposers)
54
+ dispose();
55
+ };
56
+ }
57
+ function listPayload(suites) {
58
+ return {
59
+ suites: suites.map(suite => ({
60
+ id: suite.id,
61
+ sourceId: suite.sourceId,
62
+ name: suite.manifest.name,
63
+ version: suite.manifest.version ?? null,
64
+ description: suite.manifest.description ?? null,
65
+ layout: suite.manifest.layout,
66
+ })),
67
+ skills: suites.flatMap(suite => suite.skills.map(skill => ({ suiteId: suite.id, name: skill.name, description: `[${suite.manifest.name}] ${skill.description}` }))),
68
+ mcpServers: suites.flatMap(suite => suite.mcp === undefined
69
+ ? []
70
+ : Object.keys(suite.mcp.servers).map(key => ({ suiteId: suite.id, server: key, tools: `mcp__${deriveServerName(suite.id, key)}__*` }))),
71
+ note: '技能正文通过 skill 工具按 name 加载;MCP 工具名形如 mcp__<plugin>__<server>__<tool>。',
72
+ };
73
+ }
74
+ function infoPayload(suites, record) {
75
+ const suiteId = record['suiteId'];
76
+ const suite = suites.find(entry => entry.id === suiteId);
77
+ if (suite === undefined)
78
+ return { suites: [], skills: [], mcpServers: [], note: `未找到 Agent Plugins "${String(suiteId)}"(仅列出用户级已启用 Agent Plugins)` };
79
+ return listPayload([suite]);
80
+ }