10 KiB
CHANGES — 本 fork 的改动
给接手这个 fork 的人。上游是 deepseek-ai/dsh-superagent-prototype(DeepSeek 团队的研究原型),
基线 = 6337fc8(pristine);其上是本 fork 的 11 个提交(4379973 → cf40686)。
总述
本 fork 在上游研究原型之上做了三件事:
- 新增 Gitea Source:面向自建 Gitea 实例的纯拉取轮询——不用 webhook、不需要外网回调, 部署机器无需公网入口。设计决策见 GITEA-DESIGN.md。
- Windows 全面移植:上游原型只在 Linux/macOS 上跑通,本 fork 修复了四个卡死部署的
Windows 缺陷(都在
4379973内,见下文)。 - 部署 / 运维层若干改进:面板头部一键切换部署默认模型、Source 活性与轮询停滞上报、 结束工单执行目录的磁盘回收、复用会话的角色模型重新指认等。
提交清单
按时间序;每条的"改了哪里"都对照 git show --stat 核实过。
4379973 Sources: add Gitea; fix Windows shims for shell tool, repo paths and stateDir
最大的一笔,Gitea Source 全家桶 + 四个 Windows 缺陷修复合在同一个提交里。
Gitea Source:新增 src/sources/gitea.ts(Source kind、轮询 round、GiteaConfigSchema、
插件入口)、src/sources/gitea-api.ts(最小 REST 客户端:凭据只从 env[tokenEnv] 读、zod
校验、分页、可注入 fetch)、src/sources/gitea-trigger.ts、src/sources/gitea-channel.ts;
src/kv.ts 加 gitea 命名空间(since / retry / 每线程与每流游标);src/deployment.ts 加
GiteaSetupSchema、giteaOnly()、resolveGiteaDeployment();src/app/setup.ts 加
source:gitea 分支与 resolve() 的 gitea-only 路径;src/setup.ts 加 gitea 的 setup problem
码;src/infra/environment.ts 加 Gitea 的 gh 封禁 shim 与 git 凭据 store;bundle 接线
(cordis.patch.yml 插件行默认 disabled、package.json 导出 ./gitea-watch、
tsdown.config.ts 入口);src/client/locales.ts 文案;docs/007 模块与测试表;
GITEA-DESIGN.md;tests/gitea.spec.ts。
四个 Windows 缺陷:
- stateDir:
src/deployment.ts的absolute()校验正则/^\//拒绝D:\...盘符路径 → 扩为接受盘符与 UNC。 - worker shim / git 凭据:Gitea 的 git 凭据不走 POSIX shell 型 credential helper,改用
git 内置的
store --file=...(src/infra/environment.ts,代码注释:Windows git 行为一致), 写入 gitconfig 的路径反斜杠统一换成正斜杠。 - 仓库路径:Gitea 的 API 不认
%2F编码的 owner/repo,resolveGiteaDeployment直接以 字面repos/${repository}请求(src/deployment.ts)。 - shell 工具:
src/app/sessions.ts给 master 会话的tools.restrict白名单硬编码'bash',Windows 上注册的 shell 工具是pwsh,症状 = 既有会话 resume 必挂 unknown global tool → 新增SHELL_TOOL = process.platform === 'win32' ? 'pwsh' : 'bash'并让白名单与 WORK_TOOLS 都用它。
e8b91ab Infra: write gitea git-credentials line with the deployment's own scheme
动机:凭据行写死 https://,与 http 实例的 credential.<url>.helper 查找不匹配,git 取不到
凭据。改了哪里:src/infra/environment.ts 的 writeGiteaCredentials() 改按部署 URL 自身的
scheme/host 写这一行。
589b5a6 Sources: accept login:password Basic credential for Gitea (API + git store)
动机:当时所用实例的 token 校验链损坏,需要以账号密码 Basic 顶替。改了哪里:
src/sources/gitea-api.ts 新增 giteaAuthorization()——凭据含 : 走 HTTP Basic,否则按
token <x>;src/infra/environment.ts 的 writeGiteaCredentials() 同一规则(Basic 时 store
只存冒号后的密码段)。API 与 git 两路一致。历史注记:上游 Gitea 1.26 收紧 Basic 后本部署
已改回细粒度 token,此提交保留为兜底能力(见"部署实战要点")。
a662188 Panel: switch the deployment default model from the header
动机:面板只能显示 DSH 默认模型不能改,换 Executor / Assessor 模型要手工编辑 profile。
改了哪里:新增 src/app/default-model.ts 的 switchDefaultModel()——走
sessionController.selectModel(与 DSH 模型选择器同一路径,写 profile 的
agent-default-model),按 catalog 校验、值未变报 unchanged、后台保存靠轮询确认;
src/app/http.ts 加 PUT default-model 路由;src/client/default-model.tsx 头部控件;
tests/default-model.spec.ts。只影响新会话(既有会话见 dee76b1 / acacbb2)。
b348d69 Overview: report liveness and a Source whose poll loop stopped
动机:轮询循环死了的服务照常响应每个请求,面板看不出来。改了哪里:
src/app/views/overview.ts 新增 liveness(startedAt / uptimeMs / lastPollAt / pollAgeMs /
polling),Source 连续 3 个自己的轮询周期没有新动静(且不低于 180 s)报 stalled problem;
src/app/http.ts、src/app/runtime.ts 传入进程 startedAt;src/client/overview.tsx 展示。
3bee231 Execution: reclaim the directories of Ended Tickets after a retention
动机:每张工单留下 clone 与产物,长期吃磁盘。改了哪里:新增 src/app/reclaim.ts——
Reclaimer 每小时扫一次执行根,删超过保留期的 ended 工单目录;src/policy.ts 加
executor.reclaimAfterDays(默认 14,0 = 关闭,0–365);面板 overview / execution 显示回收
摘要。防误删四道闸:过了保留期、路径必须在执行根内、目录 basename 必须等于
execution.name、该目录不在任何 open 工单的目录集中。
d527ad8 Sessions: account a restored Session to its Workspace
动机:数据迁移后面板看不到 worker 会话——ensure() 只在新建会话时登记 Workspace,从盘上
恢复的会话永远不在 Workspace 记录里。改了哪里:src/app/sessions.ts 改为对每次 ensure 都
幂等 workspaceRegistry.create(cwd),未记账的既有会话补 attachSession(失败只 warn,不拦
启动)。
dee76b1 + acacbb2 Roles: re-point reused Sessions when a role model drifts
动机(dee76b1):角色模型只给新建会话播种,旧会话被唤醒后永远用旧路由——症状是改了
executor.model 之后老工单仍用 DeepSeek,新开任务才生效。改了哪里:src/app/role-models.ts
新增 alignRoleModel(),dispatch 时比对既有会话的持久 selection / header 与配置的角色模型,
漂移则 append model/selection 事件;src/app/sessions.ts 对非新建会话调用它。
关键修正(acacbb2):只 append 事件不刷内存缓存,真机复跑下一半秒的装配仍用旧模型——
prompt 装配读的是 Session Controller 的内存 selection。改为优先调用 sessionController
实例内部的 agents.selectForNextRequest()(append + 刷 Agent 缓存,且不动全局默认),该
内部面不存在时回退公开 selectModel()(会顺带保存默认,换正确性)。
tests/role-models.spec.ts 钉住快路径与回退路径两条。
17be661 Default model: let the picker choose a reasoning effort
动机:头部快捷菜单只有 provider/model,catalog 声明的思考强度只能去 Eval / Execution 表单
里手打。改了哪里:src/client/default-model.tsx 为目录里带 efforts 的行展开二级菜单(模型
默认 + 各档位);src/app/default-model.ts 校验 effort 属于目录、只改强度也算真切换、转发
带 brand 的 id;docs/006、docs/007 同步。
cf40686 Sources: carry the Gitea kanban convention in the Source's own instructions
动机:看板约定是部署侧约定,不该写进用户仓库的 AGENTS.md。改了哪里:src/sources/gitea.ts
注册环境变量 DSH_SUPERAGENT_GITEA_KANBAN,约定文本写进它自己的 description,经既有的环境
说明机制注入 worker 提示词。约定内容:Issue 挂在项目看板上,列名与标签同名,现共 9 列 =
文档性维护、已完成、进行中、下一顺位、排队、等外部资源、暂缓、观察、开放问题(首列原名
Uncategorized,已改名);该 Gitea 版本没有 Projects API,改标签或移卡后跑外部同步脚本
card-sync.mjs,只碰这个看板、不直接操作数据库。
测试基线
上游原型在 Windows 本机跑 pnpm test 有约 38 个固有失败(tmux、lark-cli、POSIX shims、
deployment 相关、docs 测试的 path.sep 枚举、NTFS 语义等)。本 fork 的门禁口径 = 零回归:
失败集合必须始终 ⊆ 基线,即 pnpm typecheck 全绿且失败集合不新增条目。新增测试文件:
tests/gitea.spec.ts(21 例)、tests/role-models.spec.ts(14 例)、
tests/default-model.spec.ts(14 例)、tests/reclaim.spec.ts(5 例)。
Gitea 部署实战要点(运维备忘)
- 1.25 / 1.26 / 1.27 均无 Projects REST API,Projects API 首发于 1.28。判断以在跑的二进制
为准——main 分支的 swagger 是预览文档,≠ 已发布能力。看板同步只能靠外部脚本(见
cf40686)。 - 1.26 起密码 Basic 在 API 写路由被拒(报
token is required),只读路由仍可用;必须用 细粒度 token。scope 按最小需要给,本部署用的例子:write:issue+write:notification+read:user+write:repository。 - 一个凭据两用:同一个 token 既做 API 认证头(
token <x>)也做 git 的 HTTPS 密码——本 fork 的gitea-api.ts与environment.ts凭据 store 是同一规则,轮换时一处换新两处都要动。 - 实例若 token 校验链坏掉,可临时回退
login:passwordBasic(589b5a6);升级 1.26 后写 路径必须回到 token。 - Windows git 兼容性:MSYS bash 自带的 ucrt64 构建 git 2.56 与该 Gitea 实例的 http/2 协议交互挂起(clone 卡死);Git for Windows 2.39 正常。worker 用的是系统 PATH 里的 git, 不受 MSYS 那份影响,但手工在 MSYS 环境里跑长 clone 时注意。
已知限制
- 无 webhook,纯轮询(默认 60 s,可配 60–3600 s);响应速度换部署侧零入站端口。
- bot 不自动 merge PR,人工合并是设计(Gitea 侧 auto-merge 在 MVP 裁剪线之外,见 GITEA-DESIGN.md)。
- Gitea API 无
is_bot字段,非 agent、不在名单里的 actor 一律按 human 处理;自动化账号要 手工维护进 Policy 的bots名单。 - 结束的工单可被 human 唤醒,所以执行目录回收留有保留期(默认 14 天,见
3bee231)。