DeepSeek Harness 插件

vclike/dsh-github-companion

Star 数 ★ 0 分类 Git 与代码评审 收录于 2026-09-18

33 个 github_* 工具,覆盖 REST 读取、Issue 写入、Git 数据写入、私有仓库创建与克隆;附带进程内权限门与成本纪律伴生 skill,无需 gh CLI。

安装

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:vclike/dsh-github-companion

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWEDERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yamlallowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

DeepSeek Harness 上完整的 GitHub 集成包:33 个原生 agent 工具 + 进程内权限门 + 按需加载的用法技能 + 独立安装的成本纪律 companion skill——一次装齐。完全不依赖 gh CLI

English | 中文

已在 DeepSeek Harness 0.1.2-rc.10.1.5-rc.1 上验证(见 peerDependencies 声明); 宿主破坏性版本发布后会在此更新兼容结论。

包内三个挂载点

挂载点 作用
github-companion ctx.tools 上注册 33 个 github_* 工具。读/发现恒开;写/克隆/建仓按开关启用。
github-companion-gate 宿主 tools/pre-execute 权限缝的工作示例。三种模式、三种动作、完全权限下 fail-open。
github-companion-usage 把仓库根的 SKILL.md(能力地图、结果约定、工作流配方、故障速查)作为一个按需 agent skill 加载。

加上用户手动安装到 ~/.dsh/skills/dsh-github-companion/discipline companion skill(含 references/{cost-discipline,release-flows,incident-playbook,repo-hardening}.md),负责插件强制不了的事:推送纪律、tag 时机、预算反应、CI 模板。

它能做什么?

用大白话跟 agent 说需求就行,工具由它自己挑:

你说… agent 会… 背后调用的工具
"总结一下我 star 的项目这周有什么更新" 遍历 star 列表,逐仓查最新版本和提交,汇总成周报 list_starred · latest_release · list_commits
"某某仓库最近有什么新东西?" 拉最新 release 说明、近期提交、热门 issue latest_release · list_commits · list_issues
"把这个本地文件夹上传成一个私有仓库" 建仓,然后一次性原子提交全部文件 create_repository · push_files
"改掉 README 里的错别字,发个 v1.2.1" 在 main 上改文件并打 tag 发版 push_files · create_release
"我的 fork 哪些落后上游了?" 逐个对比上游并报告,你点头后才同步 list_forks · sync_fork
"给上游提个 issue 反馈这个 bug" 写好标题正文,经你确认后提交 create_issue
"看看某仓库的某个源码文件怎么实现的" 直接读公开代码、搜代码,不用离开对话 get_file_contents · search_code

安全模型 —— 读工具恒开;一切写操作(issue/分支/文件/发版/建仓)都经过权限门,先弹审批再执行;新建仓库强制私有;令牌不会进入子进程或日志(本地克隆工具开启时除外)。 没有令牌也能匿名只读公开数据(60 次/小时)。

为什么不包装 gh CLI

所有工具都直连 GitHub REST + GraphQL(fetch / undici)。github_clone_repository 唯一开 subprocess 调的是 git,不是 gh。选择直连的具体权衡:

维度 直连 REST(这个插件) 包装 gh CLI
外部依赖 零,跨平台一致 必须 PATH 有 gh,版本要对齐
多文件原子提交 blob → tree → commit → ref 一次完成 gh 无等价物——最接近是一次 git push 推一个文件
Actions 成本防护 推送前 GET /actions/runs?status=in_progress 主动拦截 gh run list 能做但多一次 shell round-trip
限流处理 自家重试策略 + 读 backoff 头,可配置 依赖 gh 的 stderr 文本,脆弱
沙箱/Windows 纯 JS,确定性强 gh.exe 不一定在 headless / 沙箱里
可测性 fetchImpl mock subprocess 黑盒
排错 curl -H "Authorization: Bearer …" 同代码路径 要翻译 gh 输出格式
GraphQL 原生(github_graphql 走 REST 不到的字段) gh api graphql 能做但要 shell 转义

如果未来真有部署需要 gh(例如 GHES 防火墙只放 SSH 不放 REST),加一个 useGhCli 兜底开关即可,默认仍然走 REST。

快速上手

dsh plugin add dsh-github-companion        # 装完重启 DSH
  1. 打开 DSH 设置 → GitHub 区块
  2. 粘贴令牌(凭证一节有一键申请链接)→ 保存
  3. 随口问一句 "我最近 star 了什么?" ——答得上来就配置完成

包内三个 cordis 挂载点

入口 插件 name 用途
dsh-github-companion github-companion ctx.tools 注册 GitHub REST 工具
dsh-github-companion/gate github-companion-gate 针对 github_* 工具的 tools/pre-execute 权限门示例
dsh-github-companion/skill github-companion-usage 注册 dsh-github-companion 按需技能

工具清单(共 33 个,按开关注册)

只读/发现 — 恒开:github_get_megithub_get_repositorygithub_get_file_contentsgithub_list_commitsgithub_search_repositoriesgithub_search_codegithub_search_issuesgithub_list_issuesgithub_get_issuegithub_list_releasesgithub_latest_releasegithub_list_starredgithub_list_forksgithub_list_watchedgithub_list_notificationsgithub_get_file_tree(一次调用递归列出整棵目录树)、github_list_my_repositories(唯一包含你自己私有仓的清单工具)、github_list_languagesgithub_list_contributorsgithub_list_tagsgithub_get_commit_activity(近一年周度活跃度,含统计冷缓存处理)

Issue 写操作 — 可开关(enableIssueWrites,默认开):github_create_issuegithub_update_issuegithub_add_issue_comment

Git 数据写操作 — 可开关(enableGitDataTools,默认):github_list_pull_requestsgithub_get_pull_requestgithub_create_branchgithub_create_or_update_filegithub_push_filesgithub_create_pull_requestgithub_create_releasegithub_sync_fork

仓库自动创建 — 可开关(enableRepoCreation,默认):github_create_repository —— 一律创建私有仓库(工具不提供公开选项,公开请到网页手动操作);需令牌的 Administration (rw) 权限。

规范返回值为 JSON 安全对象,带顶层 ok 字段。GitHub 领域错误(404/401/403/422…)以 { ok: false, status, message } 返回而非抛出,模型可以编程化处理;只有网络故障才表现为工具错误。

凭证

配置只保存环境变量credentialRef,默认 GITHUB_TOKEN)。实际值通过 harness 凭证缝(ctx.credentials)每次请求前解析——在任意 provider 层设置该变量(本地 provider 读取 ~/.dsh/.env 的 env 层,或在 shell 里 export),随时轮换,下一次请求即生效,无需重启。未配置 token 时工具以匿名模式访问公开仓库(核心限速 60 次/小时);github_get_me 会如实报告该状态。

token 永不进入子进程环境或日志——唯一的、可开关的例外:github_clone_repository 会把 token 经环境变量注入的认证头交给单个本地 git 子进程(不进命令行参数、URL、.git/config 或日志),子进程随操作结束消亡,token 在 harness 之外零残留。

第一步 · 申请令牌(二选一)

方式 A · 一键经典令牌(新手推荐)

  1. 登录 GitHub 后打开这个链接,插件所需的全部权限已自动预选: https://github.com/settings/tokens/new?scopes=repo,workflow&description=dsh-github-companion
  2. 按需选择有效期(不选也行)
  3. 拉到页面底部,点 Generate token
  4. 复制生成的值(ghp_ 开头),粘贴进插件设置卡片并保存

权衡:经典 repo 权限是账户级(全部仓库可读写),不能限定个别仓库;在意这点就用方式 B。

方式 B · 细粒度令牌(可按仓库控制)

申请入口:https://github.com/settings/personal-access-tokens/new(GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens):

  1. 填名称、选有效期
  2. Repository access:All repositories——以后新建的仓库自动纳入覆盖,无需回来改令牌
  3. 按下表勾选权限
  4. 生成并复制(github_pat_ 开头)

第二步 · 权限勾选对照(方式 B)

权限 用途
Metadata R API 必需
Contents RW 读文件、提交、分支、上传项目
Issues RW Issue 的创建/更新/评论
Pull requests RW PR 相关工具
Workflows RW 上传含工作流文件的项目时需要
Administration RW 自动新建仓库开关需要

推荐基线:前五项。只有打开建仓开关才追加 Administration RW;之后修改权限不会改变令牌值。

第三步 · 把令牌交给插件

  • 设置界面(推荐):DSH 设置 → GitHub 区块 → 粘贴到 Token 输入框 → 保存。立即生效;界面永不回显已保存的值
  • 环境变量:定义 GITHUB_TOKEN(如写在 ~/.dsh/.env),设置界面留空。轮换后下一次请求即生效

验证:问 agent 任意关于你 GitHub 账号的问题——github_get_me 应返回 authenticated: true(匿名模式返回 false 且只能读公开数据)。

存储说明:经设置界面保存的 PAT 会以明文落在本机的 ~/.dsh/settings.yaml(与该文档其余部分一致)。role('secret') 保护的是网络传输与界面回显,不是磁盘文件。若在意明文落盘,请改用环境变量方式(credentialRef),设置界面留空即可。

设置界面

三个挂载点各自注册设置命名空间,会渲染在 DSH 设置界面中:

  • github-toolsenableIssueWritesenableGitDataToolsenableRepoCreationenableCloneToolsworkspaceRoot默认克隆目录——克隆落点优先级:当前会话的工作区 → 此目录 → 询问;目录不存在时自动创建。agent 通过 github_get_me 读取该路径与状态)、proxyUrl(访问 api.github.com 的可选 HTTP(S) 代理 ——Node 的 fetch 不读系统代理,需要时在此显式填写;改动实时生效)、Actions 成本防护开关 actionsGuardEnabled + actionsGuardTagCooldownMinutes (见下文 Actions 成本防护
  • github-gatemodeoff|writes|all)、actionask|deny)、excludeTools(设置卡片以胶囊形式增删,附常用只读工具建议)

组合层默认值来自 cordis.yml 插入行(base 层);修改实时生效。

设置页的「GitHub」区块由本包自带的浏览器半(client.js,经 dsh.client manifest 暴露为 /plugins/dsh-github-companion/client.js)贡献,读写走官方 settings.describe/mutate 接口。注意:后端 settings.register 本身不产生 UI——每个设置区块都是客户端插件通过 settings.section 座位贡献的。

不经设置 UI 的等效做法:往 ~/.dsh/settings.yaml 直接加用户层分节:

github-tools:
  enableGitDataTools: true
  actionsGuardEnabled: true            # 默认 true
  actionsGuardTagCooldownMinutes: 30   # 默认 30;0 = 关闭
github-gate:
  mode: all

安装

# 已发布包(bundle 通道,重启后生效)
dsh plugin add dsh-github-companion

# 从本仓库的本地检出安装
dsh plugin add <你的检出目录>/dsh-github-companion   # 或 github:owner/repo#<sha>

然后设置 token;不需要权限门时,可从 profile 的 cordis.patch.yml 删掉 gate 那一行。

一个 bundle 一步装——v0.9.0 起包内自带按需加载的 agent 技能 github-companion-usage(能力开关地图、结果约定、令牌权限速查、工作流配方与故障手册),取代原先独立的 dsh-github-guide bundle。从旧版迁移:删掉 profile bundle 清单里的 dsh-github-guide 行及其 node_modules 链接(技能现在由主包以 dsh-github-companion/skill 入口提供)——两个挂载并存会把同名技能注册两次。

Actions 成本防护

私有仓的 Actions 分钟由 push 触发的 workflow run 在 in_progress 状态消耗,按 job 计费且向上取整。2026-08-28 的事故展示了烧穿速度:一条配置错误的 $0 预算把 Actions 锁死,僵尸排队烧掉约 1500 分钟而没干任何活。v0.8.1 起插件在其能控制的唯一推送面上加了硬防护:

  • github_push_files:目标仓已有 in_progress 的 workflow run 时拒绝,返回 push_guard_in_progress(HTTP 409)并列出运行中的 run——往已计费的 job 上叠推送,只会浪费已经花掉的分钟数
  • github_create_release:同样的 in-progress 预检,外加同名 tag 冷却(release_tag_cooldown,HTTP 429,默认 30 分钟),防止调试发版流水线时疯狂重打同一个 tag。冷却窗口只在创建成功后计时
  • fail-open 设计:预检 API 自身报错(403/404/网络断)时放行——防护自身的故障绝不能阻塞工作。Billing 接口有意不查:细粒度 PAT 在那里是 403,任何基于额度查询的熔断都是假防护。真正的断路器是 GitHub 侧的 停用预算(作者自跑 $20/月 Actions 预算;推理过程见配套技能)

配置方式(设置界面 github-tools 命名空间,或 ~/.dsh/settings.yaml 用户层):

github-tools:
  actionsGuardEnabled: true            # 默认 true
  actionsGuardTagCooldownMinutes: 30   # 默认 30;0 = 关闭

actionsGuardRefuseOnInProgress(默认 true)仅组合层可调。本地 git push 完全不经过插件进程,无法被拦截——这层防护请安装下面的配套技能补齐。

配套实践技能(用户级,跨工作区)

仓库里 skill/dsh-github-companion/ 是一个用户级技能——复制到 ~/.dsh/skills/dsh-github-companion 后所有 DSH 工作区自动加载(不像会话记忆,它不随工作区切换丢失,也不随插件升级被覆盖):

~/.dsh/skills/dsh-github-companion/
├── SKILL.md                        # 路由器:按任务告诉你读哪个分册
└── references/
    ├── cost-discipline.md          # 任何 push/tag/Release 之前必读
    ├── release-flows.md            # 发版链路、tag 重点火、草稿
    ├── incident-playbook.md        # CI 红 / run 卡死 / 预算报错
    └── repo-hardening.md           # 新私有仓 CI 加固模板

它补充插件导出的 github-companion-usage 技能(工具地图与配方)管不到的部分:成本纪律(一轮一推、禁 push && push --tags、先绿后 tag)、发版链路publish-selfcreate-tag → 自动 Release)、故障手册(npm ci 无限 peer 循环、预算锁死、卡死 run 取消)与 CI 加固模板。SKILL.md 只是路由器——agent 按任务只读需要的分册,上下文最小化。

配置(cordis.yml 插入行)

- insert:
    - id: github-tools
      name: dsh-github-companion
      config:
        credentialRef: GITHUB_TOKEN
        apiBaseUrl: https://api.github.com
        requestTimeoutMs: 30000
        maxRetries: 1
        maxPerPage: 30
        maxFileBytes: 262144
        enableIssueWrites: true
        enableGitDataTools: false
        enableRepoCreation: false
        enableCloneTools: false
        actionsGuardEnabled: true
        actionsGuardRefuseOnInProgress: true
        actionsGuardTagCooldownMinutes: 30
        workspaceRoot: ''
        proxyUrl: ''
    - id: github-permission-gate
      name: dsh-github-companion/gate
      config:
        mode: writes
        action: ask
        excludeTools: [github_search_code, …]  # 11 项作者默认
    - id: dsh-github-usage
      name: dsh-github-companion/skill

id: 是 loader 跟踪的 bundle 标识,沿用历史命名(github-tools / github-permission-gate / dsh-github-usage),保证现有 ~/.dsh/settings.yaml 无需迁移。只有 name:(模块路径)跟随新包名走。

开发

npm install
npm run typecheck
npm test
npm run test:coverage
npm run build
node scripts/verify-load.mjs

贡献约定与 PR 流程见 CONTRIBUTING.md;安全披露走 SECURITY.md

测试

四层,由快到全(不涉及任何付费服务——这里排的只是耗时和搭建成本):

# L1 — 离线:类型 + 83 个单测(client/tools/gate,mock fetch)
npm run typecheck && npm test

# L2 — 包能被 profile 的 link 布局加载
dsh plugin --profile <scratch> add <你的检出目录>/dsh-github-companion
cd ~/.dsh/profiles/<scratch>
dsh --profile <scratch> --dump-config
node <你的检出目录>/dsh-github-companion/scripts/verify-load.mjs

# L3 — 真连 GitHub API 冒烟(只读;匿名即可)
node scripts/smoke-live.mjs

# L4 — 认证+写操作:用一个一次性仓库

# L5 — agent 级端到端:装进日常 profile 后直接问

启动安全与恢复(实测结论)

插件出问题时会发生什么,全部在真实 harness 启动上验证过:

场景 结果
配置行健康 正常启动
schema 非法配置 整个 profile 拒绝启动,错误精确指到行 id 和字段
配置合法但 apply() 抛错 同样拒绝启动,堆栈点名插件
工具 execute() 运行时抛错 被工具注册表包含为 isError 结果,harness 继续运行

坏安装的爆炸半径是"这个 profile 在修好/删掉该行之前起不来"——绝不会静默变成半坏 agent。恢复手段:

dsh plugin --profile <name> remove dsh-github-companion

测量用的两个故障注入 overlay 在 scripts/bad-config.patch.ymlscripts/apply-throw.patch.yml,可对任何 scratch profile 重放。

许可

MIT

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →

社区评论

评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。