Files
dsh-superagent/docs/006-部署.md
T

22 KiB
Raw Blame History

006 部署

用这份指南安装、配置并运行 dsh-superagent。它覆盖账号、启动检查、升级与排障,建立在 001 领域模型 至 005 面板 之上。

运行的是什么

  • 一个专用的 DeepSeek Harness profile,本指南称 superagent。从 Web profile 模板创建。它加载 bundle,并在 127.0.0.1 上提供它的面板。把它与你日常干活的 profile 分开:插件会改动进程级的 PATH 与 git 设置,它的进程也需要独立重启与升级。
  • 一个 agent GitHub 账号。 agent 以这个账号发评论、推分支、开 pull request,通过一个只登录了该账号的 GitHub CLI。
  • 可选: 一个用于聊天请求的 Feishu bot。

插件配置持有状态目录与机器限额。其余一切用面板:Sources 管仓库与账号,Policy 管允许名单,Execution 管 worker 目录与命令。

权限与隔离

bundle 为 Executors 定义了 dsh-superagent-worker,为 main Session 定义了 dsh-superagent-router。它们会出现在 DeepSeek Harness 的预设列表里,但只应给 dsh-superagent 用。不要给个人 Sessions 选它们,也不要禁用它们的配置行。应用需要它们来创建和恢复自己的 Sessions。

在 Web UI 里打开一个空白的受管 Session 时,可能选中 profile 的默认预设。dsh-superagent 会在第一个回合之前恢复它的角色专属预设。

两个预设都以操作者的 OS 用户身份、用 danger-full-access 运行,并从被订阅的 Threads 读取消息。账号包装器默认挑 agent 的凭据;它们不隔离进程。worker 可以按路径执行程序、读取操作者的 home 目录。要隔离,就用一个只装 agent 凭据的专用 OS 账号。

前提

  • Node.js 22.19+ 或 24+、pnpm、git 2.32+、Python 3.8+ 与 tmux
  • GitHub CLI(gh)2.48 或更新。Source 的 CLI 字段必须指向 gh 或 lark-cli 包装器;host 依赖它们的子命令与输出格式。
  • github.com 上的一个仓库;不支持 GitHub Enterprise Server。要为每个 Ticket 建一个 checkout,保留一份本地 clone,让 prepare command 能在其中添加 worktrees。那个仓库若用 Git LFS,安装 git-lfs。
  • 为 DeepSeek Harness 配置好的 model provider。dsh-superagent 使用 profile 的默认模型,除非 Eval 或 Execution 设置点名了另一个(可以带 reasoning effort);被复用的 Session 会在下一次派发时被重新指到其角色配置的模型。
  • 用 Feishu 则需要:lark-cli(测试于 1.0.90),以及一个带 bot 的 Feishu 或 Lark 应用

账号

agent GitHub 账号

  1. 为 agent 建一个 GitHub 用户账号,授予它对仓库的写权限。GitHub App 不能当 agent,因为 dsh-superagent 读取该账号的 notifications。

  2. 给它一个只用自己凭据的 GitHub CLI:

    mkdir -p ~/.local/bin
    cat > ~/.local/bin/gh-agent <<'EOF'
    #!/bin/sh
    GH_CONFIG_DIR="$HOME/.config/gh-agent" exec gh "$@"
    EOF
    chmod +x ~/.local/bin/gh-agent
    gh-agent auth login
    gh-agent api user --jq .login
    

    以 agent 账号登录;最后一条命令会打印它的 login。dsh-superagent 用同样的方式读 login。

Feishu bot(可选)

  1. 创建一个带 bot 能力的自建应用。授予它接收消息事件、读取与发送 chat 消息、读取 chat 成员的权限,然后发布应用版本。

  2. 给 bot 一份它自己的 lark-cli 配置,限定 bot 身份,外加一个包装器:

    LARKSUITE_CLI_CONFIG_DIR="$HOME/.lark-cli-dsh-superagent" lark-cli config init --app-id <cli_…> --app-secret-stdin
    LARKSUITE_CLI_CONFIG_DIR="$HOME/.lark-cli-dsh-superagent" lark-cli config strict-mode bot --global
    cat > ~/.local/bin/lark-bot <<'EOF'
    #!/bin/sh
    export LARKSUITE_CLI_CONFIG_DIR="$HOME/.lark-cli-dsh-superagent"
    exec lark-cli "$@"
    EOF
    chmod +x ~/.local/bin/lark-bot
    

    第一条命令从标准输入读 app secret。用一个独立的配置目录:lark-cli 每个 app id 只允许一个 profile,而你的个人配置里可能已经有该应用的用户登录。

    host 会拒绝一个能扮演用户的 CLI。它从 bot 配置读取 app id、Feishu/Lark 品牌与 bot 的 open_id。

    两份配置共享 keychain 里 app secret 的那个条目。要只移除 bot 配置,删它的目录即可;不要运行 lark-cli config remove,那会影响共享的 secret。

安装

在还没有 superagent profile 的机器上,把这个块跑一遍:

npm install -g @deepseek-ai/dsh@0.2.1-rc.3
git clone <this repository> dsh-superagent && cd dsh-superagent
pnpm install && pnpm build
dsh superagent --from-default-profile web --dump-config > /dev/null
dsh plugin --profile superagent add "link:$PWD"

上面钉住的是公开版本;其他版本必须满足 package.json 里的 engines.dsh。

第四条命令从 DeepSeek Harness Web 模板创建 ~/.dsh/profiles/superagent。第五条安装本 bundle。用 DSH_HOME 可以改变默认的 ~/.dsh 目录位置。

profile 创建命令只在新安装时运行。若该 profile 已存在,那条命令会替换它并删掉它的 cordis.patch.yml,机器配置也一并没了。不要拿它做升级。

机器配置

把 examples/profile.cordis.patch.yml 复制为 ~/.dsh/profiles/superagent/cordis.patch.yml(替换那个文件),并替换每一个 <placeholder>。要用 Feishu 或本 fork 的 Gitea Source,就同时启用那里的 dsh-superagent-feishu / dsh-superagent-gitea 条目。webserver 条目设定面板的端口。

键 必填 含义
stateDir 是 绝对路径:数据库、锁、worker-bin 里的命令垫片、agent 的 git 配置,默认还包括 work 下的 Ticket 目录。升级前先备份
promptMaxChars、admissionContextMaxPages、admissionContextTimeoutMs 否 可保存的提示词配置的最大体积;一次研判在多长的时间窗内读多少个 Thread 分页

首次启动之后,机器限额到 Settings → Deployment 或 DeepSeek Harness Plugin Manager 里改。改动无需重启即生效。stateDir 不能在那里改。非法值或未知配置键会阻止启动;日志会指出是哪个键。

启动与停止

scripts/dsh-superagent start
scripts/dsh-superagent status

start 在 tmux 会话 dsh-superagent 里运行 dsh --profile superagent,其他 profile 则是 dsh-<profile>。它至多等一分钟,等 runtime 就绪或报告一个设置需求。首次运行会打印缺少的设置信息。它拒绝重复实例,包括在本脚本之外启动的实例。

stop 与 restart 请求优雅关闭,并至多给 Executors 五分钟。它们从不强杀进程,也不碰其他 tmux 会话。

status 打印进程号、健康状况与设置问题。要换 profile 或端口,用 --profile 与 --url,或设置 DSH_SUPERAGENT_PROFILE 与 DSH_SUPERAGENT_URL。

status、start 与 restart 以四种退出码之一结束:

退出码 含义
0 服务正常运行
1 它没在跑、跑了双份、不回应、或其 runtime 报错;重启可能修好
2 它在跑,但 runtime 之外的某个部件——如某个 Source 或某次 Policy 同步(sync:<source id>)——在报错;重启修不好
3 它在跑,但在等待设置;重启修不好

还在启动中的 Source 算正常运行。设置检查没能检查到的 Feishu bot 也算。

status 在 errors 下返回失败的部件及其细节,在 setup 下返回设置需求。start 与 restart 把这些问题逐行打印;服务始终起不来时它们以 1 退出。只有刻意的 stop 会暂停自动恢复。

每个 profile 把日志与控制文件存放在 .artifacts/ 下:

  • 启动日志:dsh-superagent-<profile>-<date>-<time>-<pid>.log,其中 pid 属于脚本。保留最新 20 个。
  • 控制文件:control/profiles/<profile>/,内含停止标记、锁与进程号。

打开日志里打印的 URL,然后在侧边栏选 Superagent。

每小时检查

每小时检查建在你平时使用的 DeepSeek Harness profile 里,不要建在 superagent 里。agent 服务宕机时它必须还能运行。在那个 profile 里让一个 agent 用下面这段提示词创建一个每小时计划,并把 checkout 路径填进去:

Check dsh-superagent: run `scripts/dsh-superagent --profile superagent status` in <checkout>. Exit 0: do nothing and say nothing. Exit 2: do not restart; tell me each part under `errors` with its detail, unless you already told me about the same ones. Exit 3: do not restart; tell me what `setup` says setup needs, unless you already told me. If it reports manually_stopped: true, leave it stopped. Otherwise (exit 1) run `scripts/dsh-superagent --profile superagent --respect-stop restart`, which exits the same way: 0 means it recovered, so say nothing; 2 and 3 are reported as above; if it exits 1 or fails otherwise, read the newest .artifacts/dsh-superagent-superagent-*.log and the Troubleshooting section of docs/006-部署.md, fix what you can, and tell me what was wrong and what you did.

--respect-stop 保留一次刻意的停止。只有 stop 写那个标记;start 清除它。restart 不写标记,所以这个检查能恢复一次因关闭超时而中断的重启。

设置

设置必须成功,轮询与工作才会开始。Overview 列出缺失的需求并链接到对应设置。一次设置改动会重新运行设置检查。若你在应用之外修好了什么——例如 CLI 认证——点 Check again。

  1. Sources。 设置 GitHub 仓库(owner/name)与 agent CLI,例如 /home/me/.local/bin/gh-agent。请求通常经 agent 账号的 notifications 到达。新 Issue 或提到该账号的评论会在下一次轮询到达;靠编辑已有 Issue 正文补一个 @ 是不会到的——请改发一条新评论。用 Feishu 时,设置 bot CLI、chats、每个 chat 的全量接收或仅 @ 模式、以及是否接收私聊。

  2. Policy。 两条示例规则可以编辑或删除。在 On each Source 下,添加可以请求工作的 GitHub 账号与 Feishu 用户;在名单里有了人之前,任何请求都不可能成为 Ticket。用 Feishu 时,可以选一个 chat 作为名单同步的来源,在启动时与点 Sync now 时同步。

  3. Execution。 目录根与一条 prepare command。要让每个 Ticket 得到一份仓库的 checkout:

    git -C /home/me/src/widgets fetch --no-tags "https://github.com/$DSH_SUPERAGENT_GITHUB_REPOSITORY.git" "${DSH_SUPERAGENT_GITHUB_PR_HEAD:-HEAD}:refs/dsh-superagent/$DSH_SUPERAGENT_TICKET" &&
    git -C /home/me/src/widgets worktree add -b "agent/$DSH_SUPERAGENT_NAME" "$DSH_SUPERAGENT_DIR" "refs/dsh-superagent/$DSH_SUPERAGENT_TICKET"
    

    把个人 CLI——例如登录了你自己账号的那些——列为被屏蔽的命令。

  4. Prompts。 设置团队分节:GitHub 披露句、review bots、commit 作者与 auto-merge 条件。

Management API

面板使用一个本地 HTTP API,agent 也可以调用它。设置.md 用它保存设置,服务脚本读取 GET state。

向 http://127.0.0.1:<port>/orchestrator/api/ 发送请求,带上 x-orchestrator-request: 1。host 必须是 127.0.0.1:<port> 或 localhost:<port>。缺少请求头、或 Origin 来自别的站点,都会得到 403。

API 保存拥有面板的全部权限。与通过 main Session 工具做的保存不同,它可以修改执行环境与设置里的账号字段。

agent 可以依赖这些路由与字段。src/app/api.ts 里的其他路由服务于面板,并随面板一起变化。

请求 应答
GET state 每个页面都会读的内容:setup,其中 problem 与 feishuProblem 各为 null、或一个带 place、code、values 与 detail 的设置问题,设置解析出账号后还有 accounts;health,每个部件一个条目(见下),带 state(starting、ready、paused 或 error)、detail 与 at;load,即 Executor Sessions 的 running、Tickets 的 queued 与 maxWorkers;paused;以及 masterId
GET settings blocks:policy、eval 与 executor,各含其 value 与其 revision;sources:各 Source 实例,各含 id、kind、installed、其 block 的 value({"enabled": …, "config": {…}})与 revision、其 kind 的表单,以及有设置问题时的 problem;policyVersion;以及 environment,即执行环境的 root 与 variables
GET sources 每个 Source 的状态:state(missing、off、error、setup、starting、paused 或 ready)、其各部件的 health、其设置 problem、最近一天的 stats、当天它 filtered 的 Triggers、当天它 dropped 的消息(最新丢弃在前,每条含其 channel、preview、属于某 Ticket 时的 ticket(id 与 title)、存储里有它时的 thread、以及 dropped.at 与 dropped.reason——channelGone 或 channelIgnored)
PUT settings/<block>,体为 {"value": …, "revision": n} 保存一个 block:saved、该 block 的新 revision、policy_changed 与 restarting。value 是完整的 block,如同 GET settings 返回的那样;缺失的键取默认值
POST executor/pause,体为 {"paused": true} 或 false 暂停或恢复处理:paused
POST setup/check 通过重启 dsh-superagent 重新运行设置:restarting: true。设置无可修复时会被拒绝
POST policy-sync/<source id> 立刻同步该 Source 的允许名单:policy,即已保存的该 Source 的部分
GET prompts、PUT prompts,体为 {"config", "baseRevision"} 读取提示词配置:current(含其 revision 与 config)、defaults、sections(团队分节按 Sessions 读取的顺序)、skillName(团队技能名的模式)、builtin(团队技能不能占用的名字),以及 skillPrefix(Sessions 在该前缀下加载技能名)。或保存它:返回新 revision
POST tickets/<id>/retry、POST tickets/<id>/stop 重试或停止一个 Ticket,与面板一致

健康条目按职责分组:

条目 报告
runtime 应用自身
models 正在等模型预算重试的 Sessions
evals 最近一小时内、没有更晚判断也没有被 dismiss 的 unavailable Evals
assessment、launch、delivery、relay、notice、reply 003 执行 所述的 stored work;delivery 统计排队中的工作,reply 覆盖 Channel 消息
worker Executor Session 的事件处理;在其首次失败之后出现
github、feishu、history Source 轮询、事件与历史恢复
sync:<source id> 允许名单同步

一次拒绝有一个状态码与 error,即它的英文文本:

  • 400:非法值(issues,每条含其 path)、失败的账号检查(setup)、固定的拒绝理由(code 与 values)、或不是 JSON / 过大的请求体。
  • 404:不存在的东西。
  • 409:过期的 revision。
  • 500:其他一切。

各 block:

  • source:github、source:feishu:{"enabled": true, "config": {…}}。GitHub 的 config 有 repository 与 cli,以及默认关闭的开关 observeIssues、observePulls、observeComments 与 observeCi——它们分别接收仓库中每个新 Issue、新 pull request、评论与默认分支的 CI;Feishu 的有 cli、chats(形如 [{"chatId": "oc_…", "name": "…", "listen": "mentions"}],或 "all")、directMessages,以及取 "none" 或 "mentions" 的 otherChats。
  • policy:{"rules": […], "sources": {"github": {"allowed": [{"id": "<login>"}], "bots": [{"id": "dependabot[bot]"}]}, "feishu": {"allowed": [{"id": "ou_…", "name": "…"}], "syncChat": "oc_…", "admission": {"oc_…": {"unlistedAddressed": "explicit"}}}}}。bots 列出消息可以成为 inferred 候选的 bots。admission 的行以 chat id 为键——Feishu 还有 other 或 direct——GitHub 按 issues、pulls、comments 或 ci;未设置的单元格取其默认(见 002 授权)。
  • eval:mode、timeoutSeconds 与 model。
  • executor:model、maxWorkers、directory、prepare 与 blockedCommands。处理暂停是它自己的一项设置 paused,由 POST executor/pause 设定。

修改仓库或 CLI 会先运行对应的设置检查。检查失败返回 400,细节在 setup 里。一次成功的账号变更、或设置未就绪期间的任何保存,返回 restarting: true。应用重启期间 API 暂时不可用。

api=http://127.0.0.1:3082/orchestrator/api
rev=$(curl -s -H 'x-orchestrator-request: 1' $api/settings | jq '.sources[] | select(.id == "github") | .revision')
curl -s -X PUT -H 'x-orchestrator-request: 1' -H 'content-type: application/json' $api/settings/source:github \
  -d "{\"value\": {\"enabled\": true, \"config\": {\"repository\": \"acme/widgets\", \"cli\": \"$HOME/.local/bin/gh-agent\"}}, \"revision\": $rev}"

设置检查

设置检查使用 DeepSeek Harness 的 subprocess service,与 worker shell 相同。它会移除名字里含 KEY、PASSWORD、SECRET 或 TOKEN 的环境变量。

设置检查会验证 GitHub 仓库与 agent 的推送权限、写入 worker 环境,并确认 git 对 github.com 只使用 agent 的凭据。Feishu 的设置检查失败只禁用 Feishu Source。

设置检查写出的进程环境:

  • 命令垫片在 <stateDir>/worker-bin,位于 PATH 最前:gh 运行 agent 的 CLI;lark-cli 运行 bot 的 CLI;被屏蔽的命令失败。一个垫片在运行它的目标之前,先从 PATH 里移除自己所在的目录。
  • git 配置在 <stateDir>/worker-gitconfig:替换操作者的全局与系统 git 配置。它选择 agent CLI 作为 github.com 的凭据 helper,把 GitHub 的 SSH 地址重写为 HTTPS,并定义 Git LFS 过滤器。个人 git 设置——例如 HTTP 代理——不生效。这里不设提交身份,git 从不弹凭据提示,GH_TOKEN 与 GITHUB_TOKEN 会被移除。

worker-bin 或 worker-gitconfig 里有一个并非 dsh-superagent 写入的文件,设置检查就会停住。一个处在 git 仓库之内的 Ticket 目录,若该仓库自己的配置添加了凭据,这个 Ticket 就失败。

试一把

用一个被允许的 GitHub 账号,开一个 Issue,或发一条包含 @<agent login> <request> 的评论。在一个轮询间隔内(默认一分钟),Overview 应该出现一个 Ticket。agent 会确认请求、在它自己的 Session 与目录里干活,并在原始对话里交付。用 Feishu 时,在配置好的 chat 里 @ bot。

升级

  1. 等到没有 Executor 正处于回合中间。
  2. 备份 <stateDir>/orchestrator.sqlite。
  3. 运行 git pull && pnpm install && pnpm build。
  4. 运行 scripts/dsh-superagent restart 并检查它的状态。

一次重启会结束运行中的 Assignments,并带着恢复备注启动接替者。团队文本与被覆盖的提示词部件会保留;没有覆盖的部件跟随新默认值。升级后检查标了 Default updated 的部件。

被更新版本迁移过的数据库无法被旧版本打开。因此回滚需要升级前的那份备份。升级 DeepSeek Harness 本身之后,重启运行中的实例,让面板加载相匹配的构件。

agent 预设

worker 与 router 预设会把 shell 命令在 5 秒后移入后台。一个 Session 没有它的预设就无法加载。只要它们的 Sessions 还在使用,就保留 cordis.patch.yml 里的 dsh-superagent-worker 与 dsh-superagent-router 行;否则恢复会因 agent-preset/not-found 失败。

排障

设置问题带着修复链接出现在 overview 上,用面板的语言;日志与 API 显示下面这些英文文本。

症状 原因与修复
The agent GitHub CLI is not set. 在 GitHub 卡片上设置 agent 的 CLI
The agent GitHub CLI was not found. 设置包装器的绝对路径,或一个在 PATH 上的命令名
The agent GitHub CLI cannot read its account 用 auth login 给包装器登录
@… cannot read … 或 @… cannot push to … 给 agent 账号授予该仓库的写权限
The GitHub Source names no repository. 在 GitHub 卡片上设置仓库,owner/name
Ticket 因 The prepare command failed: … 失败 输出会点名原因,例如 clone 路径不对;修好命令,然后重试这个 Ticket
git does not read the github.com credential configuration dsh-superagent writes 安装 git 2.32 或更新
Ticket 因 The git configuration of the repository in … sets … 失败 从 clone 的 .git/config 里移除点名的凭据或 http.*.extraheader 设置
… was not written by dsh-superagent 把点名的文件移出 <stateDir>/worker-bin 或 <stateDir>/worker-gitconfig,或另选一个 stateDir
The bot lark-cli allows user identities 把 Feishu Source 指向一个仅 bot 的配置,如上文 Feishu bot 所述
The bot lark-cli does not work. 或 The bot identity of app … is … 检查配置里的 app id 与 secret
The Feishu bot is not a member of the chat. 在该 chat 的设置里把 bot 拉进群;下一次尝试就会成功
status 退出码 2 某个部件在报错,重启修不好:errors 点名每个部件(如 Management API 一节所列)及其细节;每个部件恢复正常后清掉自己的条目
status 退出码 3 设置在等待:setup 说明缺什么,overview 链接到能修复它的设置
status 退出码 1 服务没在跑、跑了双份、不回应、或其 runtime 报错;输出与最新的日志会说明是哪一种
… timed out after 90 s、… was stopped by …、… exited with code … 或 … could not run: … 某个 CLI 失败而没说明原因;以操作者的用户手动运行被点名的程序,看它自己的报错
面板说 dsh-superagent 不回应 它正在重启,或因配置问题没起来;DeepSeek Harness 日志会点名原因
dsh-superagent configuration has keys it does not use(日志) 移除点名的键;消息会说每个值现在在哪里
日志说插件与运行中的 dsh 不兼容 安装一个落在 engines.dsh 范围内的 DeepSeek Harness 版本
DeepSeek Harness 升级后,面板显示 "Failed to load plugins" 重启运行中的实例
@ 之后什么都没发生 检查作者是否在该 Source 的允许名单上、Source 是否开着、处理是否被暂停。GitHub 上,靠编辑 Issue 正文补的 @ 不会被收到;请在评论里 @ agent