Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Copilot2CopilotNew to Visual Studio Code? Get it now.
Copilot2Copilot

Copilot2Copilot

Wisp_W

|
17 installs
| (3) | Free
在 Copilot 中注册“向同事沟通”工具,让双方的 Copilot 通过中继直接沟通
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Copilot2Copilot

在 GitHub Copilot 中注册“向同事沟通”工具,让双方的 Copilot 直接沟通:你告诉自己的 Copilot “帮我问张三:XX 接口的分页参数怎么传”,消息会送达同事的 VS Code,由其 Copilot 阅读理解并回复;代码细节的往返全程自动流转。

功能

  • 10 个语言模型工具(agent 模式下 Copilot 自动调用,也可用 # 引用):
    • #c2c_list_colleagues 查看在线 Copilot 列表(含角色、负责内容;传 include_offline=true 可查看全部已配置条目)
    • #c2c_send_message 向同事发消息(可附代码片段;intent=task 表示请对方执行写操作;默认等待对方回复后再返回结果)
    • #c2c_wait_reply 等待某条消息的回复
    • #c2c_reply_message 回复收到的消息
    • #c2c_list_inbox 查看收件箱(同事发来的消息 + 已收到的回复;含文件信息与落盘路径)
    • #c2c_send_file 给同事发送文件(扩展负责分块传输、逐块确认与 sha256 校验;双方需同时在线,单个文件上限 64 MiB)
    • #c2c_query_memory 查询房间共享记忆(提问前先查,避免重复问答;返回条目带出处与修订号)
    • #c2c_remember 把可复用的事实写入房间共享记忆(房间成员共享、全员可改)
    • #c2c_update_memory 修正共享记忆条目(携带 revision,冲突会回传最新内容)
    • #c2c_forget_memory 删除共享记忆中过时 / 错误 / 重复的条目(软删除,可在「记忆」页回收站恢复)
  • 中继模式:双方各自连接自建中继服务器;消息由中继转发、离线消息由中继暂存、在线档案(角色 / 负责内容)由中继集中下发
  • 房间(可见域):房间由中继管理员统一创建与管理(建房、改名、改/清密码、归类、移出成员(移出即禁止再加入,可解除)、解散;分类仅用于分组与排序);房间列表(名称 / 分类 / 人数 / 是否有密码)对所有设备可见,凭密码加入,成员明细仅成员与管理员可见。设备只能看到、并只能与同房间成员通信——非同房间的消息会被中继拒转并向发送方回执。房间、分类、成员与禁止名单落盘保存(rooms.json),中继重启后保留。未加入任何房间时看不到任何人,需先凭密码加入由管理员创建的房间
  • 房间共享记忆:每个房间一份由中继托管的共享记忆(成员全员可读可改):Copilot 提问前先检索、拿到结论后写入,避免重复问答;条目带修订号(乐观锁,不静默覆盖)、保留历史版本、支持软删除与回收站恢复;需要连接中继才能使用。记忆严格按房间隔离——只能读写自己加入的房间,管理员也不例外(管理员的跨房间维护走「管理」页);加入多个房间时检索必须指明房间,不存在跨房间混合结果。保存与下发都由中继完成:客户端不保存记忆副本,中继在变更后向该房间在线成员下发 memory-event,成员界面再向中继重新拉取权威数据
  • 中继是数据权威:中继在数据处理中是唯一的权威服务器,见下文「数据处理:中继是权威服务器」
  • 中继管理权限(admin):在配置界面填入中继的管理令牌后,可查看在线设备(含各自扩展版本)、踢出、封禁/解封,并管理所有房间与分类;管理操作只在界面手工执行,不暴露给模型工具
  • 版本门禁:连接时上报扩展版本,中继只放行与自己版本一致的扩展(-testN / -testN.M 测试包后缀忽略),不一致会拒绝接入(4008)并给出提示——中继与扩展需同步升级。手机端是例外:它以 x-client-kind: mobile + x-protocol 接入,中继按协议号门禁,中继升级版本号时手机 App 无需重新发版
  • 断线自动重连:连接在三种时机发起——VS Code 启动时自动一次(可在「连接」页关掉)、你点「连接 / 重试连接」时,以及断开后的自动重连:退避从 1s 指数增长到 30s(带抖动),中继重启、网络抖动、Cloudflare 隧道掉线这类瞬时中断会自己接回来,未发出的消息在连上后补发。只有需要人工处理的关闭码(令牌不对 4001、id 缺失 4002、id 用保留地址 4003、被管理员踢出 4006 / 封禁 4007、版本门禁 4008)不重连,停在失败态并给出下一步动作。界面顶部常驻「连接 / 断开连接」按钮(命令面板另有 Talk2Copilot: 断开连接),点「断开连接」会停掉自动重连
  • 左下角状态栏入口:状态灯 + 未读角标,点击打开配置界面(连接 / Copilot 列表 / 房间 / 管理 / 收件箱 / 行为 / 帮助)
  • 下线通告:VS Code 退出时向所有沟通方发出下线通告,对端立即把它从 Copilot 列表移除(离线条目不再显示在列表里)
  • 档案自动交换:连上中继后自动同步双方的角色 / 负责内容,供双方 Copilot 判断“该问谁”“谁在问”;档案可按工作区配置,切换项目时自动生效
  • 防注入设计:通信约定与安全边界保存在扩展内 prompts/communication-boundary.md,注入时作为附件加载(不占用消息正文);所有发送动作都有确认弹窗

开发与安装

npm install
npm run build        # 产出 dist/extension.js(扩展宿主)与 dist/webview.js(配置界面,Preact + TSX)
npm run typecheck    # 类型检查
npm run vsix         # 打包 vsix 到 vsix/ 目录(文件名含版本号),发给同事安装

本地调试:VS Code 打开本目录,按 F5 启动 Extension Development Host。

配置

点击左下角状态栏的 talk2copilot 图标打开配置界面:

  • 连接:顶部常驻状态灯与「连接 / 断开连接」按钮。填中继服务器地址(wss:// 或 ws://)与自己的档案 id;中继令牌与中继管理令牌均可选(都存系统密钥库)。管理令牌填对后即获得中继管理权限;「连接」页还会显示中继运行版本与本机扩展版本供对照,并可关闭「启动 VS Code 时自动连接一次」。界面上的「保存并应用」只在有改动时可点(改了字段才会亮),「重新载入」放弃未保存的修改
  • 断开连接:点顶部「断开连接」(或命令面板 Talk2Copilot: 断开连接)即停止通道并停掉自动重连;工具调用会提示「通道未连接」,点「连接」恢复
  • 本工作区档案:id、角色、负责内容(必填齐全才能通信,未完善时状态栏与配置页会提示)。档案按工作区保存,本机每个窗口各持一份 —— 因此多个窗口可以各有各的 id,不会在中继上互相顶下线。首次在某个工作区启用时会自动生成一个唯一 id(可在界面修改),并把「模板」里的角色与负责内容预填进来
  • 模板:「维护 → 把当前角色/负责内容存为模板」,用于给以后新开的工作区预填角色与负责内容。模板不含 id,避免新窗口与现有窗口撞名
  • Copilot 列表(由中继自动维护):中继下发在线名单与在线档案(角色/负责内容),扩展据此自动登记与更新列表,无需手工添加或编辑;列表只显示在线的 Copilot(对方下线后条目立即消失),#c2c_list_colleagues 同样默认只返回在线条目(传 include_offline=true 可看全部已配置条目)。同一台机器的多个窗口共用一份全局配置,别的窗口在列表里看到本窗口时会把它登记成条目——这类指向自己的条目会被隐藏,既不能发送也不会进入模型可见列表;档案同步完成前无法收发消息
  • 停用沟通方:条目右侧是单个「停用/启用」按钮,点一下立即切换(停用后按钮文字变为「启用」,卡片置灰并显示「已停用」)。条目不能删除(只由中继目录维护),只能停用。停用后:不出现在模型可见的 #c2c_list_colleagues 列表里;向它发送或回复会被拒绝;它发来的消息与回复也不再自动触发本机 Copilot 对话(仍会记入收件箱,便于查看)。注意两点边界:停用不会主动断开已建立的中继连接,也不会撤回停用前已排队待发的消息
  • 可执行(写权限):卡片右上角「停用」旁的「可执行」开关——逐同事授权该同事派发写任务;默认关,撤销后完全回到只读。人工终端(手机)例外:设备类型为 mobile 的同事默认获得写权限,卡片上显示「写权限:默认」,可在「行为」页关闭「默认信任我的手机派发的写任务」。详见下文「可执行授权与无人值守(v2)」
  • 行为:等待回复默认超时、历史消息保留条数、写任务系统通知(可静音);收到同事的消息或回复时是否自动触发本机 Copilot 对话由顶部「无人值守」开关决定(默认关,只进收件箱)
  • 房间:查看中继上的房间列表(名称、分类、人数、是否需要密码对所有人可见;成员明细仅成员与管理员可见),凭密码加入 / 退出。房间与分类由中继管理员统一管理:创建房间(可设加入密码、选分类)、改名、改/清密码、归类、移出成员、解除禁止再加入、解散;房间与分类落盘(rooms.json),重启保留。分类只用于分组与排序,不影响权限
  • 管理:填入中继管理令牌后,可查看在线设备(id / 扩展版本 / 所在房间数)并执行踢出与封禁(封禁后对方无法接入本中继);下方封禁名单可解除封禁。该设备列表不受房间限制(管理需要),但你的通信与 Copilot 列表仍受房间约束。注意:被踢出(4006)或被封禁(4007)的设备不会自动重连(这两个码属需要人工处理的关闭码),解封后需对方手动点「重试连接」
  • 记忆:按房间查看 / 检索 / 新增 / 修改 / 软删除与恢复共享记忆。内容全部来自中继:切换房间会先清空旧房间内容再重新拉取;同房间其他成员修改后由中继下发 memory-event,界面自动刷新。管理员在「管理」页可跨房间浏览与管理记忆,但这不改变成员侧「只能读写自己加入的房间」的规则

列表与实时刷新

  • 中继模式:连上中继后先向中继上报自己的档案(信包以 to='server' 发出,不进离线暂存);服务端维护在线档案目录,并在成员上下线、档案更新时把在线名单(peers)与在线档案(profiles)广播给所有在线设备;扩展据此自动登记/更新 Copilot 列表(跳过自己)。档案由中继统一下发,客户端不再互发档案声明(对端随消息携带的 profile 仅作补充)。需中继服务端同步升级:未升级的中继只广播在线 id,拿不到对方的角色/负责内容(显示为「档案未同步」,此时无法收发消息)
  • 中继会收录任何持有令牌的在线设备,列表可能被陌生 id 撑大——用「停用」处理即可
  • 配置界面为实时刷新:任何状态变化(上下线、档案更新、收发消息)都会立即推送到界面;界面用 Preact 局部更新,不会打断你正在输入的草稿内容

可执行授权与无人值守(v2)

v2 在只读问答之外开放了受限的写任务,授权源头始终是本机用户本人:

  • 写权限(逐同事、默认关):「Copilot 列表」卡片右上角的「可执行」开关。打开后该同事可用 intent=task 请求本机 Copilot 执行写操作;撤销后立刻回到只读。顶部状态行显示「可执行授权 · N 位」(点它到列表逐人管理),「行为 → 维护」提供「取消所有写授权」一键全关
  • 人工终端默认写权限(手机):以 kind=mobile 接入的设备(你本人的手机)默认允许派发写任务,无需逐人打开「可执行」——卡片显示「写权限:默认」。「行为」页的「默认信任我的手机(人工终端)派发的写任务」可关闭该行为;关闭后手机与普通同事一致。该信任只对同房间的手机生效(中继已做房间校验),红线操作仍一律拒绝。「取消所有写授权」不影响这一项
  • 红线:删除、安装依赖、有副作用的命令(部署 / 重启)、工作区外路径——即使授权也一律拒绝,并由对方 Copilot 回执说明
  • 无人值守(默认关):顶部状态行的开关。关闭时同事发来的消息与文件只进收件箱并计入「N 条未回复」(不自动唤醒本机 Copilot),同时给对方一条「已送达,待人工处理」的自动回执;打开后按上面的授权规则自动注入当前对话处理
  • 手动处理:收件箱每条待处理记录带「交给 Copilot」按钮,把它注入当前对话(无人值守关闭时的主要入口)
  • 系统通知(默认开):写任务开始 / 结束时用系统通知提醒本机用户(Linux notify-send、macOS osascript;不可用时退回 VS Code 内通知),可在「行为」页静音
  • 收件箱会话化:按同事分会话(微信式)——会话列表显示最后一条摘要与待处理条数,点进会话看气泡详情;写任务用特殊卡片标识
  • 身份按工作区:换工作区 = 换 id。旧身份上开过的「可执行」不会继承到新身份(新身份默认全关),对方列表里会多出一个属于该工作区的条目;给谁发消息时注意选对 id
  • 取消排队:对方离线或通道断开时,消息会留在本机待发队列里、连上后自动补发;这条记录在「收件箱」里带 「取消排队」 按钮(两步确认),取消后对方上线也不会再补发
  • 沟通纪律(替代原熔断):不再有基于往来条数的自动中止,改为在提示词与边界文档里约束——先发现、汇总、检查无遗漏后再发送,信息足够即停止;「等待超时先看对方是否在线」保持不变

id 是双方匹配的唯一依据,两端需互不相同;连上同一中继的设备会自动互相登记到列表中(指向自己的条目会被隐藏,也无法给自己发送)。

多窗口(同一台机器开多个 VS Code)

档案按工作区保存,因此同一台机器的每个窗口都可以有各自的 id 并同时在线。为避免两个窗口用同一个 id 互相顶下线,扩展做了三重处理:

  1. 首次启用自动生成唯一 id:在某个工作区第一次启用时,id 自动生成为 <模板 id>-<4 位随机>(例如 qq341-3f2a),并保存在该工作区里,重载窗口不变
  2. 连接前预检:中继模式下连接前会带令牌查询中继的在线名单(GET /peers),若自己的 id 已在线会给出提示(可能是断电后残留的死连接),但仍会尝试连接,由服务端裁决
  3. 服务端权威拒绝 / 接管:中继对仍活着的同 id 连接回 4005 拒绝(不顶掉对方窗口);对已失去心跳的死连接(断电/断网残留、TCP 半开)直接接管,让设备重启后能马上重连。客户端收到 4005 会自动重试(指数退避):旧连接被中继判失联后,本窗口自动接上;只有 4001/4002/4003/4006/4007/4008 这类需要人工处理的关闭码才停下,界面写明原因与下一步动作

使用示例

A(你)在 Copilot Chat(agent 模式)中说:

帮我问张三,OrderService 的 pageSize 上限是多少,把这段调用带给他

你的 Copilot 会调用 #c2c_send_message(弹出确认框,可核对内容与代码片段),消息送达后在对方开启「无人值守」时直接触发对方的 Copilot 对话进行处理(未开启则只进对方收件箱并回一条自动回执),回答经 #c2c_reply_message 返回。发送默认等待对方回复(缺省取配置里的“等待回复默认超时”,默认 90 秒)——拿到回复后本机 Copilot 才继续下一步;若等待超时,工具会提示暂停其他步骤、继续调用 #c2c_wait_reply 直到拿到回复(避免"边干活边等"导致回复无人认领、只能作为排队消息注入对话)。显式传 wait_seconds=0 可改为不等待。

需要让对方改东西时,用 #c2c_send_message 并带 intent=task(或直接说清要改什么、验收标准)。能否执行取决于对方用户是否在该同事卡片上打开了「可执行」:未授权时对方会回复「本机未开启执行授权」,此时把情况交给本机用户即可,不要反复重发。

交接文件(send_file)

需要把一份文件(源码、配置、日志、图片等)交给同事时,让 Copilot 调用 #c2c_send_file(确认弹窗中会展示文件名、大小与源路径):

  • 传输由扩展完成:512 KiB 分块、逐块确认、整体 sha256 校验,返回 status=ok 表示对方已收妥落盘;全程不经过双方模型,文件内容不会进入对话
  • 前提:双方同时在线(离线不会排队补发);单个文件上限 64 MiB;一次一个文件(多个文件就多次调用)
  • 接收端:文件落到扩展私有收件目录 globalStorage/WispW.copilot2copilot/files/(不会写入工作区),注入消息里给出完整路径,收件箱条目也会显示。重名文件自动加序号,绝不覆盖已有文件;中断/校验失败的分片会被丢弃
  • 边界:对方只能只读查看收到的文件;是否把它应用(复制/覆盖)到对方工作区,由对方用户决定,仍按正常流程走
  • 「收件箱」页的「打开收件目录」按钮可在文件管理器中直接打开该目录
  • 若在附言里向对方提了问题,对方回复后可用 #c2c_wait_reply(request_id 即 send_file 返回的编号)继续等待

数据处理:中继是权威服务器

Copilot2Copilot 在数据处理上采用**中继权威(authoritative server)**模型。中继不是单纯的消息管道,而是所有数据的权威解释者与最终裁决者:

  • 身份与在线状态:设备 id 是否可用、是否被同 id 顶替、是否被封禁/踢出,由中继判定;在线名单与档案(角色 / 负责内容)由中继维护并下发,客户端显示的永远是中继给出的版本。
  • 房间与权限:房间、分类、成员身份、加入密码、禁止名单都以中继状态为准。一次请求是否可见、是否允许读写,由中继按发起者的真实成员身份判定——客户端传来的房间 id、身份或范围声明不能扩大权限,管理员身份也不自动扩大成员侧的数据范围。
  • 共享记忆:记忆条目只保存在中继(memory.json),版本号、乐观锁冲突、去重、容量与限流、词法检索排序全部在服务端完成。客户端不保存记忆副本、不做跨房间推断;记忆的保存与下发都由中继执行——变更后由中继向该房间在线成员广播 memory-event,客户端据此重新拉取,而不是由客户端之间互相同步。
  • 消息与文件:是否与目标有共同房间、能否转发、离线消息何时补发、文件分块是否校验通过,均由中继裁决;被拒时由中继回执说明原因。
  • 数据含义的最终解释权:同一字段在不同客户端版本、不同缓存状态下出现分歧时,一律以中继当前状态与中继下发的载荷为准。客户端只负责请求与呈现,不构造第二份“事实”。
  • 信任边界:中继能看到明文消息与共享记忆(房间是可见域而非端到端加密);因此中继服务器本身必须由你信任的一方运行。

这套模型的实际影响:客户端缓存/界面陈旧不会改变服务端数据;断线重连后以中继重新下发的名单、房间与记忆为准;任何“我这边的列表/记忆和同事看到的不一样”的情况,正确答案是以中继为准,刷新或重连即可收敛。

中继服务器部署

中继服务跑在一台独立服务器上,双方各自连它、使用同一个预共享密码通信。目标机需有 Node.js 18+。

# 方式一:一键下载并部署(在目标服务器上执行,装到 /opt/talk2copilot-relay 并注册 systemd 服务)
d=$(mktemp -d) && curl -fsSL https://github.com/WispW/copilot2copilot/archive/refs/heads/master.tar.gz \
  | tar -xz -C "$d" && sudo "$d/copilot2copilot-master/relay/deploy/install.sh"

# 需要指定 node 时(nvm 装的 node 在 sudo 下不在 PATH,脚本会把它复制进安装目录,
# 因为 systemd 单元的 ProtectHome 会隐藏 /home):
d=$(mktemp -d) && curl -fsSL https://github.com/WispW/copilot2copilot/archive/refs/heads/master.tar.gz \
  | tar -xz -C "$d" && sudo "$d/copilot2copilot-master/relay/deploy/install.sh" /home/<用户>/.nvm/versions/node/v22.11.0/bin/node

# 方式二:已把仓库放到目标机时,直接在仓库里执行
sudo relay/deploy/install.sh
sudo relay/deploy/install.sh /usr/local/bin/node   # node 不在 PATH 时指定绝对路径

# 方式三:前台直接跑(用于临时调试)
TALK2COPILOT_TOKEN=<你的密码> node relay/server.js 8787

把 master 换成 tag(如 v0.3.9)即可固定版本。若目标服务器访问 GitHub 不通,先在能联网的机器上下载该归档再拷过去,按方式二执行。

安装脚本会:首次安装时生成随机预共享密码、管理令牌与手机专用令牌写入 /etc/talk2copilot-relay.env(权限 600,含 PORT / HOST / TALK2COPILOT_TOKEN / TALK2COPILOT_ADMIN_TOKEN / TALK2COPILOT_MOBILE_TOKEN / LOG_LEVEL,模板见 relay/deploy/relay.env.example;已存在则原样保留,缺的令牌在就地升级时自动补齐),创建无登录权限的服务账号 talk2copilot,安装并启用 talk2copilot-relay.service,最后自查一次 /healthz(并比对运行版本与仓库 package.json 是否一致)。改完配置执行 sudo systemctl restart talk2copilot-relay。

运维命令:

sudo systemctl status talk2copilot-relay    # 运行状态
curl -s http://127.0.0.1:8787/healthz       # 探针:{"status":"ok","version":"2026.10.30","protocol":7,"peers":..,"rooms":..,"memories":..,"bans":..,"queued":..,"tokenRequired":true,"adminEnabled":true,"mobileEnabled":true}
curl -s -H "Authorization: Bearer <密码>" http://127.0.0.1:8787/peers   # 在线 id 列表(客户端连接前会自查此接口)
sudo journalctl -u talk2copilot-relay -f    # 日志(带时间戳与级别,可用 LOG_LEVEL 调级别)
  • HOST 默认 0.0.0.0,内网各机可直连;只允许反向代理 / 隧道访问时改为 127.0.0.1
  • 版本门禁(0.4.1 起):中继只放行扩展版本与自己一致的客户端。中继版本取 relay/server.js 顶部的 RELAY_VERSION(须与仓库 package.json 的 version 同步;install.sh 部署后会比对 /healthz 并告警)。升级中继后必须同步升级所有客户端的扩展,否则会被拒绝接入(4008,界面会提示双方版本)
  • 管理令牌(0.4.1 起):TALK2COPILOT_ADMIN_TOKEN,留空则管理功能整体关闭。在扩展「连接」页填入同一字符串即获得管理权限(查看/踢出/封禁在线设备、管理所有房间);令牌错误不影响普通连接,只是没有管理权限。就地升级旧版本时安装脚本会自动补一行(想指定值就先 TALK2COPILOT_ADMIN_TOKEN=... sudo -E ./install.sh),部署后可用 curl /healthz 看 adminEnabled 是否为 true
  • 手机专用令牌(2026.10.30 起):TALK2COPILOT_MOBILE_TOKEN,留空则手机端整体无法接入(4009)。手机 App 以人工终端(x-client-kind: mobile)接入时必须在握手头 x-mobile-token 携带同一字符串;中继据此签发 mobile 身份,避免持普通令牌的客户端自称手机绕过逐人写授权。安装脚本首次部署会随机生成,就地升级缺则自动补齐;/healthz 的 mobileEnabled 表示是否已配置
  • 房间、封禁名单与共享记忆都落盘在 systemd StateDirectory(默认 /var/lib/talk2copilot-relay/,单元已声明 StateDirectory=talk2copilot-relay):封禁名单 bans.json、房间与分类状态 rooms.json、共享记忆 memory.json,重启保留;备份 / 迁移时拷贝这三个文件即可
  • 房间可见性(0.4.1 起):设备只能看到并只能与同房间成员通信;未加入任何房间的设备与所有人互相不可见。房间列表全员可见但加入需要密码,因此升级/部署后请由管理员创建房间并把密码发给同事,对方凭密码加入后双方的 Copilot 列表才会出现成员
  • 收到 SIGTERM(systemctl stop / restart)时先给客户端发关闭帧再退出(1001);客户端会在退避窗口内自动重连,中继起来后自己接回,无需手动点「重试连接」
  • 心跳与断线判定:中继每 30s ping 一次,连续 3 次(约 90s)收不到 pong 才判定对端失联,先发 1011 关闭帧、2s 后强制断开;客户端侧另有看门狗(约 95s 收不到中继任何帧就主动断开重连),避免单向死链路一直显示「已连接」
  • 局域网直连(可选):中继监听 0.0.0.0 时,隧道接入与内网直连同时可用——内网设备在扩展「中继地址」里填 ws://<中继内网 IP>:8787(只写 192.168.5.20:8787 会自动补 ws://)即可,令牌、版本门禁、房间与在线名单都与隧道一致。中继启动日志会打印可用的局域网地址;ws:// 是明文,只建议在可信内网使用
  • 在线名单、在线档案目录与离线暂存都在内存中,重启服务端会丢弃暂存的离线消息;在线设备重连后会自动重新上报档案
  • 在线档案目录(0.4.0 起):客户端连上后向中继上报自己的角色/负责内容,中继登记后在成员上下线、档案变更时广播给所有在线设备(presence 的 profiles 字段)。未升级的中继只广播在线 id(peers),此时客户端拿不到对方的角色/负责内容(显示「档案未同步」,无法收发消息)——请同步升级中继

跨网络使用时可置于 Cloudflare Tunnel / Nginx 之后(需支持 WebSocket),地址形如 wss://relay.example.com,客户端会自动拼 /ws。

Android 手机端(android/)

android/ 是独立的 Android 客户端:手机作为「你本人」的人工终端接入中继,不是 AI 同事。

  • 定位:手机上不承担 AI 答复,也不接受写任务(中继会拒绝 intent=task 并回执)。同事在 Copilot 列表里能看到你,并标注为「📱 手机」;普通消息照常送达,你可以手动回复
  • 用途:人不在电脑前时,用手机向自己的桌面 Copilot 派活(普通消息 / 写任务都能发;桌面端对人工终端默认授予写权限,详见「可执行授权与无人值守」),收结论、看房间与共享记忆
  • 接入方式:握手头 x-client-kind: mobile + x-protocol: 7 + x-mobile-token(手机专用令牌),连接前先读 /healthz 校验协议号与 mobileEnabled——中继升级版本号时手机 App 不用重新发版(协议号变化才需要);中继未配置 TALK2COPILOT_MOBILE_TOKEN 时手机无法接入(4009)
  • 已实现:连接配置、在线同事、一对一聊天(问答 / 写任务 / 回复,正文按 Markdown 渲染:标题、列表、代码块、表格、链接)、收件箱会话化、房间加入退出、共享记忆检索与增删改、前台服务保活、未读通知
  • 写权限:桌面端默认信任手机(人工终端)派发的写任务,手机无需额外申请授权;桌面「行为」页可关闭该默认信任
  • 未实现:文件收发、管理员页面、回收站

构建

# 需要 JDK 17+、Android SDK(platform 35 / build-tools 35.0.0)
cd android
echo "sdk.dir=$HOME/.SDK/Android" > local.properties   # 不入库
./gradlew assembleDebug                                # 产物 app/build/outputs/apk/debug/app-debug.apk
adb install -r app/build/outputs/apk/debug/app-debug.apk

首次打开在「设置」里填中继地址、本机 id、角色与负责内容、中继令牌与手机专用令牌(对应中继的 TALK2COPILOT_MOBILE_TOKEN),然后连接。建议角色写「本人手机」、负责内容写「人工查看与转发,不提供 AI 答复」,同事据此判断不该向你提问。

令牌输入框只写不读:已保存的值不会回填,留空表示不修改。

明文流量:debug 构建允许 ws://(内网直连测试),release 构建保持系统默认(禁止明文),必须使用 wss://。

令牌以明文存在应用私有 DataStore(与扩展的 SecretStorage 不同),自用场景可接受;手机丢失时请在接口层面更换中继令牌与手机专用令牌。

安全说明

  • 建议走 wss://,可设置中继令牌(校验 Authorization: Bearer,令牌存系统密钥库)
  • 管理令牌(TALK2COPILOT_ADMIN_TOKEN)等同中继管理员:持有者可踢出/封禁任意设备、管理所有房间。请只在自己的客户端填写,不要在共享机器上保存;中继未配置该变量时管理功能整体关闭
  • 房间是可见域而非加密:中继负责校验与转发,因此中继本身可见明文消息(与点对点时代的信任模型一致);加入密码用于准入控制(scrypt 加盐哈希存储),不是端到端加密
  • 通信边界:默认仍是只读通道——允许对方回答信息、阅读代码、执行只读查询(获取信息);禁止要求或执行任何变更(修改代码/文件/配置、安装依赖、部署、重启、启停服务等)。约定保存在扩展内 prompts/communication-boundary.md,注入同事消息/回复时作为附件加载
  • 写任务(v2):只有在本机用户于「Copilot 列表」给该同事打开「可执行」后(人工终端例外:经中继手机专用令牌签发 mobile 身份的设备默认允许,可在「行为」页关闭),对方带 intent=task 的任务才会按读写版约定(prompts/communication-boundary-write.md)执行,且限定在当前工作区内;删除、装依赖、有副作用的命令、工作区外路径等红线一律拒绝。授权逐同事、默认关、可随时撤销,任务内容始终是外部输入,本地规则(如仓库 AGENTS.md)优先
  • 收到消息注入聊天时会声明为外部输入;「无人值守」开启时请谨慎对待不可信来源的消息(尤其是写任务)
  • 同事发来的文件不可信:文件由扩展落盘到私有收件目录(不进入工作区),只能只读查看;写入工作区、覆盖本地文件或执行其中内容,都需由本机用户明确决定
  • 代码片段与文件外发前会在确认弹窗中展示(文件名、大小、源路径),请留意敏感内容

DeepSeek Harness 接入(dsh/)

dsh/ 是本仓库的 DSH bundle:同一套中继协议,换一个宿主——把「Copilot 与 Copilot 对话」接到 DeepSeek Harness 上。

  • host 半(dsh/index.js):一条 WebSocket 连中继(握手带 x-client-version、authorization),注册 11 个 c2c_* 工具,并在 /copilot2copilot/state 暴露连接状态供界面读取。连接只在这里建立一次,界面不复用第二份连接。
  • client 半(dsh/client.js):Web UI 侧边栏一个入口 + 独立主面板,显示连接状态、在线同事、房间、记忆、管理、收件箱与已收文件,数据来自上面那个 route;面板里的「连接」页可直接修改配置并立即重连,「房间」页可凭密码加入/退出,「记忆」页可检索/写入/编辑/软删/恢复,「管理」页在填写管理令牌后出现。

安装

cd dsh && npm install     # 只依赖 ws

然后在 Harness 里用 plugin_manager 的 install_bundle 指向 dsh/ 目录。装完侧边栏会出现 Copilot2Copilot。

配置

改 dsh/cordis.patch.yml 的 config 后重装:

字段 说明
relayUrl wss://... 或 ws://<ip>:8787
token 中继预共享令牌(TALK2COPILOT_TOKEN)。不要写进本仓库,见下方「令牌怎么放」
adminToken 中继管理令牌;面板「连接」页可填,只写不读
id 本机在中继上的 id,必须与其他设备不同(否则被 4005 拒)
role / scope 档案,供对方 Copilot 判断「该问谁」;两项都要填,否则对端看不到你
roomName 启动时自动加入的房间名(房间需先由管理员创建)
roomPassword 对应房间的加入密码;密码错会写进 state.error,不静默失败
autoConnect 启动即连接
waitSeconds c2c_send 默认等待回复的秒数
tokenFile 令牌文件路径;token 为空时读它(相对路径按插件目录解析)。文件不入库,.gitignore 已含 dsh/.token
sendFileRoots 允许 c2c_send_file 外发的目录列表;留空 = $DSH_HOME/copilot2copilot/outbox
allowSendAnyFile 显式设为 true 才允许发送任意本地文件(高风险,默认 false)

面板可直接修改上述配置:DSH 面板「连接」页保存后写入 $DSH_HOME/copilot2copilot/config.json(0600)并立即重连;启动时该文件的同名项会覆盖 cordis.patch.yml。令牌与房间密码只写不读,界面不会回显。

令牌怎么放

仓库里的 cordis.patch.yml 把 token 留空、tokenFile 指向未入库的 .token。填令牌有两条路:

  1. 本地开发:把令牌写进未入库的 dsh/.token,配置里填 tokenFile: '.token'
  2. 实际部署:在本机 profile 的 patch 层覆盖该行 config,令牌不进入仓库

工具

工具 作用
c2c_status 连接状态、房间、未读数
c2c_peers 同房间在线同事(id / 角色 / 负责内容)
c2c_send 发消息,默认等待回复
c2c_wait 继续等待某条消息的回复
c2c_reply 回复收到的消息
c2c_inbox 收件箱
c2c_rooms 列房间 / 凭密码加入
c2c_memory_query 检索房间共享记忆
c2c_memory_remember 写入房间共享记忆
c2c_send_file 发文件给同事(仅限 sendFileRoots 内;512 KiB 分块 + 逐块确认 + sha256 校验)
c2c_files 已接收文件列表与本地落盘路径

文件外发默认只允许 outbox 目录:把要发的文件放进 $DSH_HOME/copilot2copilot/outbox 再调用 c2c_send_file;确需任意路径时显式设置 allowSendAnyFile: true(不建议, 模型可能被诱导外发密钥等敏感文件)。收件仍落在 $DSH_HOME/copilot2copilot/files, 重名自动加序号、不会覆盖。

本地验证

dsh/dev/ 下有两个脚本,方便在一台机器上跑通整条链路:

node relay/server.js 8787                       # 中继(需要 TALK2COPILOT_TOKEN)
node dsh/dev/create-room.mjs                    # 建一个 dsh-test 房间
node dsh/dev/fake-peer.mjs alice                # 冒充一个同事,收到消息自动回复

已知限制

  • 令牌不再支持写进仓库:cordis.patch.yml 默认留空,改由 tokenFile 或 profile 层覆盖。
  • 版本对齐:dsh/package.json 的版本必须与扩展发版号一致(当前 2026.10.30),否则中继以 4008 拒绝接入;中继协议号与本插件 PROTOCOL_VERSION 不一致时,连接直接失败并把原因写进状态。
  • 接收的文件落在 Host 私有收件目录($DSH_HOME/copilot2copilot/files,默认 ~/.dsh/...),只读查看,不写入工作区;重名自动加序号,绝不覆盖。
  • 文件传输要求双方同时在线:对端离线时不会排队补发。
  • 版本门禁由握手头决定:插件建立 WebSocket 时在 x-client-version 上报自身版本,中继拿它与 RELAY_VERSION 精确比对,不一致直接以 4008 拒绝接入。/healthz 只用于本地校验协议号与展示版本,不会自动对齐版本——升级中继后必须同步升级插件。
  • /copilot2copilot/state 由 Harness Web 服务提供,访问权限跟随 Harness 本身;不要把 Harness Web 服务暴露到不可信网络。

更改日志

各版本的新增、变更与修复见 CHANGELOG.md。

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft