# dsh-connection-card-host [English](README.md) | **中文** > **把「连接」做成 DSH 里的一等对象:会话是节点,连接是容器,卡片是连接级插件 —— 一个「连接级插件宿主」。** [![](https://img.shields.io/badge/powered_by-dsh-4D6BFE?style=flat-square&logo=deepseek&logoColor=white)](https://github.com/deepseek-ai/deepseek-harness) [![Awesome DSH Plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com) [![GitHub stars](https://img.shields.io/github/stars/Noob-stupid/dsh-connection-card-host?style=flat-square&logo=github)](https://github.com/Noob-stupid/dsh-connection-card-host/stargazers) [![License](https://img.shields.io/github/license/Noob-stupid/dsh-connection-card-host?style=flat-square)](LICENSE) [![Last commit](https://img.shields.io/github/last-commit/Noob-stupid/dsh-connection-card-host?style=flat-square)](https://github.com/Noob-stupid/dsh-connection-card-host/commits/main) [![CI](https://img.shields.io/github/actions/workflow/status/Noob-stupid/dsh-connection-card-host/ci.yml?label=ci&style=flat-square)](https://github.com/Noob-stupid/dsh-connection-card-host/actions/workflows/ci.yml) [![publish-npm CI](https://img.shields.io/github/actions/workflow/status/Noob-stupid/dsh-connection-card-host/publish-npm.yml?label=publish-npm&style=flat-square)](https://github.com/Noob-stupid/dsh-connection-card-host/actions/workflows/publish-npm.yml) [![topic: dsh-plugin](https://img.shields.io/badge/topic-dsh_plugin-4D6BFE?style=flat-square)](https://github.com/topics/dsh-plugin) [![npm version](https://img.shields.io/npm/v/@noob-stupid/dsh-connection-card-host?style=flat-square)](https://www.npmjs.com/package/@noob-stupid/dsh-connection-card-host) [![npm downloads](https://img.shields.io/npm/dm/@noob-stupid/dsh-connection-card-host?style=flat-square)](https://www.npmjs.com/package/@noob-stupid/dsh-connection-card-host) [![GitHub Release](https://img.shields.io/github/v/release/Noob-stupid/dsh-connection-card-host?style=flat-square)](https://github.com/Noob-stupid/dsh-connection-card-host/releases) [![dsh.so risk](https://www.dsh.so/badge/dsh-connection-card-host.svg)](https://www.dsh.so/artifact/dsh-connection-card-host/) **为什么是这个插件**:别的插件把能力写死在插件里;这个插件让能力变成「连接上可安装的卡片」—— **装、卸、隔离都是连接粒度**的。 在一个 DSH 里同时开着好几个会话(一个查资料、一个写代码、一个跑实验)是常态。 缺的不是"会话之间能互相看见"这个功能,而是 **DSH 的会话之间可编程的关系层**: 没有一个可以挂东西的"关系对象",权限边界、共享前提、可装载的能力就都无处安放。

连接是平台对象:会话 A 与会话 B 之间是一条连接,连接上有事件总线、权限边界、公约盒与卡片宿主;卡片挂在连接上,受连接权限约束,连接经适配层调用 DSH

在这个关系层之上,连接的两端**互相看得见、说得上话、共用得上工具 —— 而互不打扰**。
**实际操作**(录屏) 从输入框左侧锚点拖出连线 **交互结构**([架构图](docs/capabilities.md)) 拖拽建连的结构:锚点 → 会话行 → 竖轨

左:真实操作 · 右:同一动作的交互结构示意,标出了「开关语义」

--- ## 目录 - [它能做什么](#它能做什么) - [三十秒上手](#三十秒上手) - [三个层次:感知 / 约定 / 传话](#三个层次感知--约定--传话) - [连接上的卡片](#连接上的卡片) - [卡片能做什么 / 不能做什么](#卡片能做什么--不能做什么) - [架构与成本](#架构与成本) - [安装](#安装) - [怎么用](#怎么用) - [配置项](#配置项) - [卡片开发](#卡片开发) - [卸载](#卸载) - [FAQ](#faq) - [文档](#文档) - [维护](#维护) --- ## 它能做什么 | | | |:---|:---| | **互相看得见** | 查得到对方**正在改哪个文件、计划进行到第几步、最近用了什么工具** —— 自动采集,对方不需要专门告诉你 | | **说得上话** | 给对端发消息,**紧急度自己判断**:只告知(不打断)/排队/插话/**抢占式中断**(第四档,**默认关闭**) | | **共用得上工具** | 连接上可以挂**卡片**:卡片能给会话提供工具,甚至带几十 MB 的真依赖 | | **共用前提** | 「公约盒」存放双方说好的事:接口、单位、命名、分工边界 | | **互不打扰** | 感知是**拉取式**的 —— 对方不查就零成本;不相关的连接**不会吵到你** | 同一个关系层的两个例子:A 问 B 现在在干什么;或者 B 交给 A 一个只存在于这条连接上的工具。 --- ## 三十秒上手 1. **建连接**:按住输入框左侧的圆点(或会话行上的「…」),拖到左侧会话列表里的某一行。
**起手式与开关语义** - 输入框左侧的**圆点** → 拖到某一行 - 会话行上的「**…**」→ 拖到另一行 - 落点即开关:**未连的行 = 连接**;**已连的行 = 断开**(悬停时会提示) - 也可以从侧栏「连接」面板里选两个会话 **从会话行拖 → 连上之后**(录屏) 从会话行拖出连线,松手后出现竖轨与权限彩点
2. **完事**。两端各自收到一条静默通知(说清了连上了谁、能做什么),**不打断任何人**。 3. 想看得更细:点侧栏「连接」,或者让会话自己调 `connection_peer_work`。 连接建立后,会话行右侧会出现**竖轨**,两端各一个**彩色圆点** —— 那是该方向的权限:

连接面板:每个连接的权限可以两个方向分别设置,卡片、感知、约定都在同一条连接下

连接会持久化:下次 DSH 启动时自动恢复。 --- ## 三个层次:感知 / 约定 / 传话 这三层是**分开的**,因为它们的代价差别很大: | 层 | 机制 | 进对方上下文吗 | 迫使对方行动吗 | 成本 | |:---|:---|:---|:---|:---| | **A 工作状态** | 拉取(对端主动查) | 只在它查的时候 | ❌ 不会 | **0** | | **B 公约盒** | 拉取(对端主动查) | 只在它查的时候 | ❌ 不会 | **0** | | **C 传话** | 推送(进对方收件箱) | **无条件** | ✅ **必然** | 每条都花 | **关键事实**:在 DSH 里投递一条消息 = **迫使对方跑一轮**(agent loop 没有"看到但不理"这个状态)。 所以「说话」和「感知」必须分开做 —— 想要对方**知道**,用 A/B;想要对方**做事**,才用 C。 ### A. 工作状态(自动,0 成本) 自动从运行事件里采集,**不要求模型额外产出任何东西**: ``` 【session-1a2b3c4d】 状态:正在执行命令(2 秒前) 最近动过的文件:/src/example.js 进度:第 12 轮 / 第 4 步 ``` ### B. 公约盒(显式,0 成本) 双方说好的标准:接口签名、单位、坐标系、命名、**谁的活归谁**。 面板上可增删;会话用 `connection_conventions` / `connection_declare` 读写。 ### C. 传话(四档紧急度,**由发起方判断**) | 档位 | 底层 | 对方会怎样 | |:---|:---|:---| | `quiet` | `inject` | 放进上下文**但不唤醒** —— 它下次干活时看到,**不被打断** | | `normal` | `followup` | **排队** —— 处理完手头的事就看到 | | `urgent` | `steer` | **插话** —— 插进它**正在跑的那一轮**,当场读到 | | `preempt` | `steer` + 可选 `cancel` | **抢占** —— **打断**它正在跑的这一轮(第四档,**默认关闭**;不满足条件时自动退化为 `urgent`,消息照样送到) | `urgent` 而对端空闲时**自动降级为排队**(下一轮立刻开始,效果等同即时),不会失败。 **`preempt` 的四个条件** —— 必须全部满足,否则退化为 `urgent` 投递,**永不失败**: | 条件 | 取值 | |:---|:---| | 连接权限 | 需要**写权限**(只读连接不能停别人的活) | | 频率上限 | **每个连接 5 分钟最多 1 次** | | 对端正执行工具 | **绝不打断** —— 跑一半的工具被 cancel 会留下悬空调用 | | 对端空闲或状态未知 | 不打断,只投递 | > `preempt` 是破坏性的:被打断的那一轮,已经做的工作白费。 > 取消一轮时必须带 `keepInbox` —— 它默认**清空收件箱**,会把用户自己排队的输入和别的会话发来的消息一起丢掉。 --- ## 连接上的卡片 **卡片 = 挂在连接上、且能分端可见的插件。** | | DSH 插件 | 卡片 | |:---|:---|:---| | 装在哪 | 整个 DSH(profile) | **一条连接** | | 谁能调 | 所有会话 | **只这条连接上的会话** | | 可见性 | 全局 | **可分端**:两端 / 仅 A / 仅 B | | 生命周期 | 随 DSH 起停 | 随连接上的装载卸载 |

会话用一个常驻桥接工具,按需发现并调用卡片提供的工具,且受可见范围约束

### 卡片能给会话提供工具 卡片里 `api.registerTool(name, fn)` 注册的工具,连接上的会话可以用 **一个**常驻桥接工具按需发现并调用: ``` connection_card_tool ← 唯一常驻的(1 个 schema) ├─ 不传 tool → 列出本连接上「对你在的这一端可见」的卡片与工具 └─ 传 tool → 调用它 ``` **为什么是一个桥接、而不是每个工具各占一个 schema**:后者会让**每个会话**都为 每个卡片工具付常驻成本,而卡片是随连接动态装载的。桥接只占 1 个, 而且天然能在桥接层强制可见范围。 ### 卡片里可以塞真依赖 卡片可以自带依赖(几十 MB 也可以),装在 `$DSH_HOME/connection-cards/cards/`, **不碰 DSH profile**。 ### 面板内安装与更新

卡片选择器:内置卡片一键加;也可以给包名、仓库 tgz 地址或本地目录来安装

卡片有**三种来源** —— 与连接面板里**卡片选择器**的三种来源一致: | 来源 | 给什么 | 实现 | |:---|:---|:---| | **包名**(注册表) | `monitor-card` / `@scope/monitor-card` | 从 registry 拉 **tarball**(一次 HTTPS GET) | | **仓库 tgz 地址** | `https://example.com/card.tgz` | 下载后解压 | | **本地目录** | `D:\my-cards\monitor-card` | 直接拷贝 | - **装**:包名 / 仓库 tgz 地址 / 本地目录 → 装进我们自己的目录,**不跑 pnpm、不改 profile**; 装完**立刻可用**,**不需要重启 DSH** - **更新**:已安装的卡片带「检查更新」入口,三态分列 ``` 「检查更新」→「↑ 更新到 x.y.z」/「已是最新」/「无法检查」 ``` **"无法检查"绝不显示成"已是最新"** —— 那是谎报。 - **卸**:已安装的卡片带卸载入口,点击前**说清会移除什么**(包括它在各条连接上的卡片实例)并确认一次。 内置卡随插件分发,**不给卸载**。卸载结果**如实回报**:清了什么、什么还被占用没清掉。 ### 声明:第三方 / 社区卡片可以直接下载安装,装完即用 **可以在内部直接下载安装外部 DSH 会话相关的插件卡片,并立即使用。** 这不是"官方卡片市场",也不是一个需要审核上架的中心 —— 它是**开放的分发**: 任何按[卡片协议](docs/card-protocol.md)写出来的包,都能从上面三种来源装进你自己的 DSH。 **装完即可用** —— 卡片装到一条连接上之后: - 连接上的会话**立刻**能用它提供的工具(经 `connection_card_tool` 桥接调用)—— **不需要重启 DSH,不需要改 DSH 配置**:不跑 pnpm、不写 `dsh.profile.bundles` - 卡片装在自己的目录 `$DSH_HOME/connection-cards/cards//`,与 DSH profile 完全隔离 > 第三方 / 社区卡片与 DSH 官方项目**没有隶属关系**;本插件不提供审核、背书, > 也不存在"官方目录"这种东西。 --- ## 卡片能做什么 / 不能做什么 卡片就是普通 DSH 插件,所以**不是每个插件都适合当卡片**。一个候选能不能挂到连接上、 挂上去之后有多少能用,由下面这张规格表决定。候选列表会**提前**标出 **适配 / 能力 / 局部 / 全局 / 未判定**,但**只标注、不阻断** —— 是否挂载始终由你决定, 判定本身是启发式的。 ### 挂载:三扇门 | 门 | 要求 | 不过会怎样 | |:---|:---|:---| | **① 作用域** | 注册到**连接级**位置(`conversation.*` / `message.*` / `input.*`)或**纯能力**(无客户端半边) | 注册到 **App 级**位置(侧栏 / 布局 / 设置页 / 主题 / 标题栏 / 工作区)⇒ **不建议当卡片**:全局 UI 塞进连接级面板既装不下、也会和 App 布局打架 | | **② 模块** | 宿主**入口的 import 闭包**内依赖必须全部可解析 | 拒绝挂载,并**分类**说清:**致命**(缺宿主能力,改设计才行)/ **可选**(缺第三方依赖,补上就能过) | | **③ 能力** | `inject` ⊆ `{tools, effect, llm, prompt}` | 拒绝挂载 —— 它要的是本插件没有的宿主服务。**拒绝是正确行为**,答案不是放宽能力面 | ② 的扫描面:只看**入口真正会加载到的文件** —— `tests/` `bin/` `client/build.mjs` `*.d.ts` 里的 import **不算运行时依赖**。 **不跑 pnpm、不执行构建**:宿主不装依赖、也不构建任何包。所以**作者没提交构建产物** (只有源码)的包挂不上 —— 拒绝原因会写明这一点。 ### 客户端 UI 能到哪一层 ``` 能挂 ≠ 能取源码 ≠ 能注册槽位 ≠ 能渲染 ``` | 情况 | 结果 | |:---|:---| | 只用 `slots` / `effect` | **能渲染** ✓ | | 依赖客户端 hook(`useScene` / `useEnabled` / `locale` / `configForms` …) | **挂得上、槽位也注册了,但渲染失败** —— **显示原因、不白屏** ✓ | | 客户端制品上限 | **32 MB**(自包含 bundle 到几 MB 是正常的:内联字体/素材) | | 组件的调用方式 | `createElement(component, {})` ⇒ **不给 props**:需要槽位 props 的组件会报错,被错误边界接住 | ### 支持 / 不支持 | | 支持 | 不支持 | |:---|:---|:---| | **宿主工具** | `api.registerTool(name, fn)` → 会话经 `connection_card_tool` 调用 | 把工具注册进 DSH 全局 Loader | | **面板** | 可选的面板 HTML(宿主侧渲染后取回) | 面板里执行任意浏览器侧代码 | | **客户端 UI** | 只用 `slots` / `effect` 的组件 | 需要客户端 hook、或需要槽位 props 的组件 | | **连接级事件** | `on(event, handler)` / `emit(event, data)` | 跨连接的事件 | | **消息** | `send(kind, text)` / `read()`(以某一端身份) | 会话内容的自动镜像(见[配置项](#配置项)) | | **依赖** | 卡片自带的任意依赖 | 在你机器上跑 pnpm 或构建步骤 | | **分发** | registry / 仓库 tgz / 本地目录 | 审核上架的中心或市场 | | **隔离** | 分端可见、版本门控、`import` / `apply` 崩溃隔离 | 卡片抛异常拖垮宿主 | ### 明确写出的边界 | 边界 | 含义 | |:---|:---| | **分端可见** | 可见范围分端:两端 / 仅 A 端 / 仅 B 端。**A 端可见 ≠ B 端可见**;不可见的一端硬调会被拒绝,并说明原因 | | **版本门控** | DSH 版本不匹配会被**明确拒绝并说明原因**,而不是装上再崩。卡片另有一条 CardAPI 版本护栏(要更高版本的卡片会被拒绝装载并说明原因) | | **崩溃隔离** | 卡片 import / apply 抛异常不会拖垮宿主 | | **不重写 DSH** | 不碰 DSH 的通信、权限、插件系统;卡片**不注册到 DSH 全局 Loader** | --- ## 架构与成本 三层,边界很硬 —— 每层只跟下一层说话: ``` ┌─────────────────────────────────────────────────────────────┐ │ 卡片层(连接级插件) │ │ 只依赖 CardAPI,绝不 import @deepseek-ai/* │ │ → DSH 升级不影响卡片;我们改 CardAPI 才影响(有版本护栏) │ ├─────────────────────────────────────────────────────────────┤ │ 连接层(本插件) │ │ 连接 / 权限 / 感知 / 公约盒 / 卡片宿主 / 消息投递 │ │ → DSH 升级时,只需要改这一层 │ ├─────────────────────────────────────────────────────────────┤ │ DSH 适配层(DSHAdapter + 白名单 + 审计) │ │ 所有 DSH 交互的唯一出口 │ └─────────────────────────────────────────────────────────────┘ ``` ### 权限是**分方向**的 一根线两端各一个圆点,颜色是**那个方向**的权限 —— 两个方向互不影响, 可以做成「甲能发、乙只能看」:

连线颜色表示该方向的权限:灰=只读,蓝=可建议,橙=可写入;两端可不对称

| 该方向的权限 | 允许什么 | |:---|:---| | **只读** | 感知与公约盒(两层都是拉取式,与权限无关) | | **可建议** | 不修改对端工作的传话 | | **可写入** | 能改变对端行为的传话,包括 `preempt` | 降低权限立即生效;提高权限需要被授权的一方确认。拒绝会说明原因。 ### 成本 | 项 | 成本 | 说明 | |:---|:---|:---| | **感知(A + B 两层)** | **0 上下文** | 拉取式;对端不查就不产生任何成本 | | **卡片工具** | **1 个常驻 schema** | 而不是每个卡片工具各占一个 | | **不相关的连接** | **0 打扰** | 搭线不唤醒;不相关的会话照常干活 | | **常驻工具 schema** | 5 个 `connection_*`,对没有连接的会话隐藏 | 工具面按会话 scope 过滤:一条连接都没有的会话不背这份 schema | 有至少一条连接的会话,会带上这 5 个 `connection_*` 工具的 schema。 --- ## 安装 **npm(推荐,可锁版本)**: ```sh dsh plugin --profile web add @noob-stupid/dsh-connection-card-host ``` **固定版本:用 Releases 的 tgz 附件**: ```sh dsh plugin --profile web add https://github.com/Noob-stupid/dsh-connection-card-host/releases/download//noob-stupid-dsh-connection-card-host-.tgz # 同一份 tgz 先下载到本地再装,效果相同 dsh plugin --profile web add ./noob-stupid-dsh-connection-card-host-.tgz ``` **GitHub 直装**(装**默认分支最新提交**,不是固定版本): ```sh dsh plugin --profile web add github:Noob-stupid/dsh-connection-card-host # 同上,GitHub 简写(可省 github:)—— 带斜杠就走 GitHub 仓库 dsh plugin --profile web add Noob-stupid/dsh-connection-card-host ``` **前置条件** - `pnpm` 在 `PATH` 上 —— `dsh plugin` 会调它。 - **兼容性**:`peerDependencies` 声明 `@deepseek-ai/dsh >=0.2.0-rc.1 <0.3.0` (另有 `@deepseek-ai/cordis` 与两个 `@deepseek-ai/dsh-client-*`)—— DSH 会在安装时**按版本门控**,不匹配会明确拒绝并说明原因(而不是装上再崩)。 - 这四个 peer 都标了 `peerDependenciesMeta.optional`:这样按包名安装**只增加 1 个包**, **不会**把 `@deepseek-ai/*` 依赖树拖进你的 profile。本包**运行时一个 `@deepseek-ai/*` 都不 import**(浏览器端那两个由 DSH 的 `__ModuleLoader__` 注入),标 optional **不改门控** —— DSH 的 `evaluatePluginCompatibility` 只读 `peerDependencies`。 细节见 [`docs/compatibility.md`](docs/compatibility.md)。 - `lib/` 已随仓库提交并在 npm 包里带上:装完即可用,不需要构建步骤, 本包也没有需要授权的构建脚本。 --- ## 怎么用 **建连接** —— [三十秒上手](#三十秒上手)写了两个拖拽起手式和侧栏面板。落点即开关; 连接会在重启后恢复。 **设权限** —— 在连接面板里按方向分别设置。降低立即生效;提高需要对方确认。 **让会话干活** —— 连接建立后,会话拿到 `connection_*` 这一组工具: | 工具 | 用途 | |:---|:---| | `connection_peer_work` | 读对端工作状态(A 层) | | `connection_conventions` | 读公约盒(B 层) | | `connection_declare` | 写公约盒(B 层) | | `connection_send` | 发消息,带紧急度(C 层) | | `connection_card_tool` | 列出并调用本连接上卡片提供的工具 | 感知类工具(`connection_peer_work`、`connection_conventions`)是只读的,改不了对端。 --- ### agent 的 skill 随插件一起装好 装上插件就够了:它通过 DSH 的 skill-provider 通道注册一个 **`connection-card` skill**, 所以那个实例里**任何 agent** 都能在会话目录里看到这套连接工具怎么用 —— 不用往 `~/.dsh/skills/` 拷文件,也不用多做一步。 - 文本的唯一出处:[`skills/connection-card.md`](skills/connection-card.md)。 - 插件加载期间它就在;**卸载插件它就消失**(注册绑定在插件生命周期上)。 - 内容覆盖:五个宿主工具各自什么时候用、四档紧急度怎么挑 (`quiet` 只告知 / `normal` 排队 / `urgent` 插话 / `preempt` 抢占)。 - 想当**普通本地 skill** 用也行:同一个文件就是一份合法的扁平 skill, 拷成 `~/.dsh/skills/connection-card.md` 即可。 ## 配置项 本插件**没有配置文件**,也不接收任何设置 schema。可配置的东西都在界面上配, 其余的都在同一个目录里: | 位置 | 存什么 | |:---|:---| | 连接面板(侧栏) | 连接、分方向权限、公约盒、卡片挂载 | | 卡片选择器(连接面板内) | 卡片的安装与更新 | | `$DSH_HOME/connection-cards/` | 全部持久状态:`connections.json`、已安装的卡片、防篡改的 `audit.log` | 有两个行为**刻意默认关闭**,需要一次明确动作才打开: | 行为 | 默认 | 怎么打开 | |:---|:---|:---| | `preempt`(抢占式中断) | **关** | 需要该连接上的**写权限**(见 [C 层](#三个层次感知--约定--传话)) | | 第三方卡片适配 | **关** | 创建 `$DSH_HOME/connection-cards/adapter.enabled`;删掉该文件即关闭 | **会话内容的自动镜像永久关闭** —— 除非会话主动调 `connection_send`,否则不在会话之间转发 任何东西。感知(A/B 两层)是拉取式的替代方案。 --- ## 卡片开发 一张卡片就是一个带 `dshCard` 清单的 npm 包: ```json { "name": "my-card", "version": "1.0.0", "main": "index.js", "dshCard": { "id": "my-card", "name": "我的卡片", "entry": "index.js", "api": 1 } } ``` ```js // index.js —— ⚠️ 绝不 import 任何 @deepseek-ai/*,所有交互走 api export function apply(api) { api.log(`已装载(scope=${api.scope})`) // 给连接上的会话提供工具 api.registerTool('greet', async (args) => { return `你好,${args?.name ?? '世界'}` }) } // 面板 HTML(可选) export function renderPanel(api) { return `
可见范围:${api.scope}
` } ``` | `api` 成员 | 说明 | |:---|:---| | `registerTool(name, fn)` | 注册工具 → 会话经 `connection_card_tool` 调用 | | `send(kind, text)` / `read()` | 以某一端身份收发连接消息 | | `on(event, handler)` / `emit(event, data)` | 连接级事件 | | `scope` | 本实例作用在哪一端(`both` / `a` / `b`) | | `log(...)` | 写宿主日志 | **`dshCard.api`** 是卡片声明自己需要的 **CardAPI 版本**(缺省 1): - **加东西不升版本** —— 老卡片照常跑 - **删或改语义才升版本** —— 宿主会拒绝装载要更高版本的卡片,并说明原因 > 这是**我们自己的兼容性护栏**:卡片不依赖 DSH 内部包,所以 DSH 升级不影响卡片; > 但**我们改 `CardAPI` 会影响卡片**,而 DSH 的版本门控管不到这一层。 细节见 [`docs/card-protocol.md`](docs/card-protocol.md)。 --- ## 卸载 **移除插件** ```sh dsh plugin --profile web remove @noob-stupid/dsh-connection-card-host ``` **移除它的状态** —— 插件的所有状态都在一个目录里,所以删掉它也就删掉了连接、已安装的卡片和审计日志: ```sh rm -rf "$DSH_HOME/connection-cards" ``` 如果你打算重装并保留连接,就别删这个目录。 --- ## FAQ **没有连接能用卡片吗?** 不能。卡片挂在连接上,只有这条连接上的会话能调它提供的工具。 **挂卡片会动我的 DSH profile 吗?** 不会。卡片装在 `$DSH_HOME/connection-cards/cards//` 下;不跑 pnpm、不写 `dsh.profile.bundles`、不重启。 **为什么某个常用插件挂不上?** 大概率是[卡片能做什么 / 不能做什么](#卡片能做什么--不能做什么)里的 ② 或 ③ 门没过。 拒绝信息会写明是哪扇门、为什么。最常见的原因是包只提交了源码、没提交构建产物 —— 宿主不构建任何东西。 **卡片挂上了但界面上什么都没有。** 看客户端 UI 那张表:需要客户端 hook 的卡片槽位注册成功但渲染失败。 面板会显示失败原因,不会白屏。 **连接会额外花我的上下文吗?** 感知(A/B 两层)是拉取式的,会话不问就不花。一条连接都没有的会话不背任何 `connection_*` 工具 schema;有连接的会话带这 5 个;卡片工具合计只占 1 个桥接 schema。 **对端会话离线时还能用吗?** 消息照样送到,但对端界面上显示为普通消息而不是连接卡片,内容开头会标明这一点。 东西不会丢。 **第三方卡片有人审核吗?** 没有。没有市场、没有审核、没有背书 —— 只从你信得过的来源装。 --- ## 文档 | 文档 | 内容 | |:---|:---| | [`docs/capabilities.md`](docs/capabilities.md) | **能力报告**:逐项结果、上下文成本总账、已知限制 | | [`docs/card-protocol.md`](docs/card-protocol.md) | 卡片协议:清单、CardAPI、安装校验、分发来源 | | [`docs/compatibility.md`](docs/compatibility.md) | 兼容性:DSH 版本门控机制、两条防线 | | [`docs/adapter-api.md`](docs/adapter-api.md) | DSH 适配层:稳定接口与白名单 | --- ## 维护 **本仓库是稳定门面**,只在发版时按晋级流程同步。开发发生在预览线仓库 [`dsh-connection-card-host-preview`](https://github.com/Noob-stupid/dsh-connection-card-host-preview)。
改这个插件时 - `lib/` 随仓库提交,CI 会断言**源码与构建产物对齐**(`scripts/ci/check-src-lib-parity.mjs`), 所以改了 `src/` 必须同时更新重新构建出来的 `lib/`。 - 宿主侧改动要**重启 DSH 或重载插件**才生效;客户端侧改动还需要刷新页面。 - CI 有四道硬门槛:语法检查、单元/契约测试 + 产物对齐、插件 patch 清单、 被跟踪文件的本机路径扫描。 - `npm test` 不需要任何依赖、不需要网络。
---

MIT · 与 DSH 官方无隶属关系