DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

s-huizhuy-u /

s-huizhuy-u/dsh-github-sync

Verified

Publish a DeepSeek Harness workspace to GitHub: create the repo, initialize git, commit, and push — with the token held in the DSH credential store.

★ 1 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@64258f7a

dsh-github-sync

English | 简体中文

在对话里把 DeepSeek Harness 工作区发布到 GitHub。

让助手同步项目,它会创建仓库、在工作区初始化 git、提交整棵工作树并推送。仓库名默认取项目文件夹名,可见性默认私有,两者都可以在单次调用时或在设置里覆盖。

你:   把这个项目传到 GitHub

DSH:  已同步 12 个变更文件到 octocat/my-project(分支 main)。
       仓库:https://github.com/octocat/my-project

功能

能力 说明
创建仓库 GitHub 上不存在就创建,已存在则复用
初始化 git 沿用项目当前所在分支;新仓库用 main
提交 暂存整棵工作树并提交;没有变更时复用现有 HEAD,而不是报错
推送 历史分叉时先 fetch + rebase 再推送
自动配置 写入账号的提交身份,并把分支上游记录下来
只读预览 github_status 报告同步将要做什么,不改动任何东西

环境要求

  • DeepSeek Harness 0.1.5-rc.2 或更高
  • Node.js 20.12+(需要 AbortSignal.any)
  • PATH 中有 git

安装

把包复制进 DSH profile 并完成声明:

node scripts/install.mjs

脚本会先定位 DSH home(依次检查 DSH_HOME、各平台默认路径、~/.dsh),把插件复制到 <profile>/.local-plugins/ 和 <profile>/node_modules/,加入 dsh.profile.bundles,并把加载行追加到 cordis.patch.yml。脚本可重复执行,并会打印每一个写入路径。

dsh-github-sync installer
  source   /path/to/dsh-github-sync
  DSH home ~/.config/dsh-desktop/harness  (holds profiles/web/package.json)
  profile  ~/.config/dsh-desktop/harness/profiles/web

  wrote    .../profiles/web/.local-plugins/dsh-github-sync
  wrote    .../profiles/web/node_modules/dsh-github-sync
  updated  .../profiles/web/package.json
  updated  .../profiles/web/cordis.patch.yml

重启 DSH 以加载插件。

DSH 桌面版存在不止一个可能的 home —— 启动器会导出 DSH_HOME,而 CLI 版默认用 ~/.dsh。脚本只接受真正含有 profile 清单的目录,--home <dir> 可覆盖探测结果。

认证

需要一个 GitHub personal access token。

按优先级有三种提供方式:

  1. 环境变量 —— GITHUB_TOKEN,其次 GH_TOKEN。不在磁盘上留下任何东西,是 CI 和共享机器上的最佳选择。
  2. 让助手存 —— 说「存一下我的 GitHub token」,它会用 github_configure 存储。
  3. HTTP —— POST /api/github-sync.token,body 为 {"token": "..."}。
# 方式 1:启动 DSH 前导出
export GITHUB_TOKEN=ghp_...

权限要求:

token 类型 需要的权限
classic repo(只发公开仓库可用 public_repo)
fine-grained Contents: Read and write;若要让插件自己创建仓库,另需 Administration: Read and write(或账户级 Repository creation)

⚠️ 注意一个容易误判的坑:仓库 API 返回的 permissions.push=true 反映的是你账号在该仓库的角色,不是这个 token 被授予的权限。判断 token 能否写入,要看 403 响应里的 x-accepted-github-permissions 头。

存储的 token 保存在 DSH 凭据库里,不在 settings.yaml。这一点很重要:凭据库以文件权限 0600 写在写锁之后,而设置字段会把 PAT 以明文留在设置界面会读回的 YAML 文件里。

所有 token 形态在进入日志或对话记录之前都会被遮蔽 —— 包括 git 报错时习惯性回显 remote URL 这种行为。

工具

github_sync

发布当前工作区。

参数 类型 默认值 含义
repo string 项目文件夹名,经 slug 化 仓库名
owner string 配置的 owner,其次 token 所属用户 仓库所有者
description string — 仅在创建仓库时生效
visibility private | public | internal 配置值,其次 private 新仓库的可见性
auto_init boolean false 是否让 GitHub 创建首个提交
commit_message string Initial commit,其次 chore: sync workspace 提交信息
push boolean true 设为 false 则只在本地提交
force boolean false 历史冲突时覆盖远端分支

auto_init 默认是 false,这是刻意的。用初始提交创建的仓库,本身已含有一个工作区没有的提交,会让第一次推送就被 non-fast-forward 拒绝。

github_status

报告一次同步会如何执行 —— 仓库名、git 状态、远端、token 来源、git 版本 —— 不改动任何东西。用于预览。它也会带出待处理的 harness 升级提醒(见 保持更新)。

github_configure

向 GitHub API 校验一个 personal access token 并存储。若 classic token 报告的 scope 不含 repo 会被拒绝;它的调用展示中永不回显 token。仅在用户主动提供了 token 时调用;如果用户不愿粘贴,优先用 GITHUB_TOKEN。

设置

github-sync 命名空间保存非敏感默认值,可在 设置 → 插件 中编辑:

键 默认值 含义
owner 空 新仓库的所属账号;空表示 token 自己的用户
visibility private 新建仓库的可见性
autoInit false 是否让 GitHub 创建首个提交
commitMessage 空 工作区尚无仓库时使用的提交信息

配置界面或脚本也可以直接用:

GET  /api/github-sync.settings   → 默认值、token 状态、git 版本
POST /api/github-sync.token      → { "token": "..." } 或 { "clear": true }
POST /api/github-sync.verify     → 校验已存储或传入的 token

设计取舍

有三个决定值得了解,因为每一个都对应一种具体的失败。

token 永不落盘。 origin 始终保存为干净的 https://github.com/<owner>/<repo>.git,而带认证信息的 URL 只作为单次 git push 的参数传入。因此 token 不会进入 .git/config,不会被之后手动执行的 git push 继承,也无法从仓库里被翻出来。

git 永不弹出提示。 每次 git 调用都带 GIT_TERMINAL_PROMPT=0、GIT_ASKPASS= 和 GCM_INTERACTIVE=never。没有这些,一次认证失败会让 git 在一个托管 harness 里根本不存在的控制台上等待输入密码,调用会一直挂到超时,而不是把失败报出来。

远端分叉是协调,不是覆盖。 当远端分支已有提交时,插件先 fetch 再 rebase,之后才推送;force 始终需要显式开启。rebase 冲突时会用 git rebase --abort 回滚,工作树被留在原样。

另外两个较小的点:

  • origin 保存的是仓库身份,不是凭据 —— 因此之后手动 git push 会用用户自己的 git 凭据,这才是应有的行为。
  • git 操作不是并发安全的。 github_sync 声明 isConcurrencySafe: false,因为同一工作区里两次 git 会在索引锁上相撞。

保持更新

插件是针对某一个 harness API 面写的。应用更新后,插件引用的包版本、导出或服务可能已不存在 —— 而它的失败形态是整棵插件树完全无法加载。

scripts/watch-dsh-update.mjs 记录 harness 核心版本,一旦变化就往 DSH home 写一条提醒:

node scripts/watch-dsh-update.mjs
========================================
  DSH updated - plugins may need updating
========================================

  The DeepSeek Harness core moved from 0.1.5-rc.2 to 0.1.6. Installed
  plugins were built against the previous surface and may no longer load.

  Send this to the assistant in DSH:

  "DSH was updated from 0.1.5-rc.2 to 0.1.6. Check every installed plugin
   for compatibility and update the ones that need it."

github_status 会读取这条提醒并并入自己的报告,因此助手可以主动提出,不必等用户自己注意到控制台输出。

把它注册成登录任务即可自动运行。在 Windows 上,放进「启动」文件夹的快捷方式就够了:

$startup = [Environment]::GetFolderPath('Startup')
$target  = '<profile>/node_modules/dsh-github-sync/scripts/watch-dsh-update.mjs'
$shell   = New-Object -ComObject WScript.Shell
$lnk     = $shell.CreateShortcut("$startup\DSH GitHub Sync Update Watch.lnk")
$lnk.TargetPath       = (Get-Command node).Source
$lnk.Arguments        = "`"$target`" --quiet"
$lnk.WindowStyle      = 7   # 最小化
$lnk.Save()

加 --quiet 可在没有变化时不输出。

如果 DSH 完全打不开,问题通常出在插件树上:先用安全模式启动,让助手逐个重新启用插件;或者手动跑一次这个 watcher,把它给出的那段话发给助手。

验证

test/verify.mjs 离线运行 33 项检查:REST 层由 stub fetch 提供,git 层跑在磁盘上真实的 bare 仓库上。这个组合恰好覆盖了生产上真正会出问题的顺序 —— 创建、初始化、提交、推送 —— 同时又完全不依赖外网。

node test/verify.mjs
units
  ok   slugifyRepoName produces names GitHub accepts
  ok   redact masks every token shape it may echo
  ok   the settings schema resolves every default
git (local bare remote)
  ok   a bare repository serves as the offline remote
  ok   a fresh init lands on the requested branch with no commits
  ok   the clean remote URL is what gets persisted
  ok   a diverged remote forces a rebase before the next push
tools (stubbed GitHub API)
  ok   apply() registers one namespace and three tools
  ok   github_sync reports NOT_CONFIGURED without touching the network
  ok   github_sync creates the repository, commits, and reports the outcome
  ok   a second sync with no changes reuses HEAD instead of failing
  ok   a TLS trust failure is reported as its own condition
  ok   a rejected call surfaces the permission GitHub asked for

33 passed, 0 failed

要从已安装的副本运行,这样 @deepseek-ai/* 才能解析:

node node_modules/dsh-github-sync/test/verify.mjs

故障排查

现象 原因与处理
No GitHub token is configured 设置 GITHUB_TOKEN,或用 github_configure 存一个,然后重启 DSH
GitHub rejected the request (HTTP 401) token 过期或错误,重新签发
HTTP 403 且带权限提示 提示里会给出 GitHub 要求的准确权限 —— fine-grained token 通常是 administration=write 或 repository_creation=write
自己拥有的仓库却 HTTP 404 token 看不见它 —— fine-grained token 需要勾选该仓库,并授予 Contents 与 Administration 写权限
TLS_UNTRUSTED 有 TLS 中间人代理或 GitHub 加速器在接管 api.github.com。Windows 信任它的根证书,Node 不信任:把该根证书以 PEM 形式指给 NODE_EXTRA_CA_CERTS 后重启 DSH —— 见 GitHub 加速器环境
git push failed … non-fast-forward 重试,或传 force 覆盖远端分支
REBASE_CONFLICT 在工作区手动解决冲突,或带 force 重跑
The git executable was not found on PATH 安装 Git 并重启 DSH,让新的 PATH 生效
插件始终不出现 确认加载行在 <profile>/cordis.patch.yml、包在 <profile>/node_modules/ 下,然后重启 DSH

GitHub 加速器环境

TLS 中间人型加速器(Watt Toolkit / Steam++、FastGithub、dev-sidecar)通过本地代理转发 GitHub,并用它自己的根证书重新签名连接。Windows 信任这个根证书;Node 不信任,因为 Node 自带一份 CA 列表,不读系统证书库。于是每次插件调用都失败在 TLS_UNTRUSTED,尽管网络本身完全正常。

导出加速器根证书并指给 Node:

# 1. 把加速器根证书导出为 PEM
$cert = Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -match 'SteamTools' } | Select-Object -First 1
$b64  = [Convert]::ToBase64String($cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert))
$pem  = "-----BEGIN CERTIFICATE-----`n" +
        (($b64 -split '(.{1,64})' | Where-Object { $_ }) -join "`n") +
        "`n-----END CERTIFICATE-----`n"
$path = "$env:LOCALAPPDATA\dsh-github-sync\certs\accelerator-root.pem"
New-Item -ItemType Directory -Path (Split-Path $path) -Force | Out-Null
[IO.File]::WriteAllText($path, $pem)

# 2. 让 Node 信任它。NODE_EXTRA_CA_CERTS 是追加式的,内置 CA 不受影响。
setx NODE_EXTRA_CA_CERTS $path

之后重启 DSH,让宿主进程继承这个变量。

git 通常什么都不用配。 Windows 版 git 默认使用 schannel 后端,它走 Windows 证书库校验 —— 所以只要 Windows 信任加速器根证书,git 本来就能用,而 http.sslCAInfo 会被静默忽略:

git config --show-origin --get http.sslBackend
# schannel   -> 由 Windows 证书库负责,git 侧不需要任何 CA 配置

只有当 git 报告的是 OpenSSL 后端时(macOS、Linux 的默认情况,以及部分这样配置的 Windows 构建)才需要给它单独的 bundle —— 而且要指向合并后的 bundle,因为直接替换默认值会破坏所有未被中间人的正常域名:

cat "$(git config --get http.sslCABundle 2>/dev/null || echo /etc/ssl/certs/ca-certificates.crt)" \
    ~/.local/share/dsh-github-sync/certs/accelerator-root.pem > ~/.local/share/dsh-github-sync/certs/combined.crt
git config --global http.sslCAInfo ~/.local/share/dsh-github-sync/certs/combined.crt

许可证

MIT —— 见 LICENSE。

—/ 5

No ratings yet

Verified DSH bundle

Commit 64258f7aef42

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout