Eric-GoodBoy-Tech/dsh-agsh-context

dsh-agsh-context

AgentShell 嵌入 DSH 的桥插件:唯一 shell 工具(持续终端)+ pre-step 落点 + llm/stream 短路接管(git 分发)

待分类

dsh-agsh-context

AgentShell 嵌入 DSH 的桥插件(Path B:请求接管)。git 分发,官方 dsh plugin 安装,预设挂载用裸包名。

它做什么

在 agsh 预设下,DSH 负责调度与 API 调用,AgentShell 持续终端是凭证/节点/history 的唯一权威:

  1. 唯一模型工具 shell — 指向持续终端(tmux PTY + agent.zsh headless);执行走注入协议,工具结果由终端 precmd 尾调写入节点 history,插件轮询 history 取结果(History 即同步通道)。
  2. agent/pre-step — 用户消息按落点规则写入目标节点 history:有凭证沿用;drop 后自然回到上一节点 claim 继续(claim 被其他会话锁挡下则回退会话专属节点);仅首句落会话专属节点。
  3. llm/stream 短路接管 — 循环主请求替换为 agsh context build --cred <id> 上下文 + 一次全新 one-shot 调用;回合模型:回合结束无需 drop,凭证跨轮保留,执行 drop 则本节点段立即结束。

非 agsh 会话零侵入(全部钩子带预设/目录门禁)。

实时流式与重试

第 3 步的内层 ctx.llm.stream(innerOptions) 实时放行:每个 chunk 收到即交给 DSH,思维链 / 正文 / 工具调用都以模型生成速度到达 UI。判定与重试分三层:

  • 漂移就地改写 — shell tool-call 的参数名漂移(如把 cmd 写成 command、cmd 为空串)时,就地改写 block-end 的 arguments 为规格键。不重发、不中断;前端与节点 history 拿到的都是规范参数。
  • 内容级重试(step 级) — 参数不可用(非法 JSON / 无有效值 / 装配失败)且非 max-tokens 截断时,本次尝试以 error 收尾(失败码 AGSH_TOOLCALL);插件在 agent/request-error 上认领该码,写入 llm/retry + llm/retry-started 后请求 DSH 重跑本 step。DSH 开一次新的 attempt,前端据此擦掉失败尝试已流出的内容再重新渲染。失败尝试不写节点 history。
  • 流以 error 收尾 — 原样放行,交给 DSH 原生 dsh-llm-retry(按 provider 的 retryPolicy,默认 5 次)。

预算:环境变量 AGSH_API_RETRY_MAX(含首次,默认 2 ⇒ 每个用户回合最多自动重发 1 次;非法值回落 2),按会话记账、新用户消息清零。预算耗尽后不再合成 error:坏参数原样走到工具边界(工具报错 → 模型下一步自纠),回合不会因为「重试用完」而失败。

为何不流内重发:流内「丢弃整次尝试再重发」必须先把整次调用的全部 chunk 攥在手里才能决策——代价是思维链被压到流末尾一次性倾泻(实测每块间隔 0.03ms、整段 28ms 内到齐;同 provider/模型下标准预设是 78ms/块、铺开 10 秒)。改走 step 级重试后,实时显示与重试不再互相牺牲。

为何幂等:失败尝试一律不写节点 history,命令执行发生在流成功结束之后 ⇒ 重发时命令未执行、history 未写。

与标准库的关系:分类规格镜像 agsh-stdlib/api-retry-core.ts(仅指针,无跨仓 import);该 core 供标准模式的 api-retry.ts 适配器使用(包装 agsh.api.stream),与本插件目标不同、各自独立。

借用 DSH 事件的边界:llm/retry / llm/retry-started 的字段逐条对齐 @deepseek-ai/dsh-llm-retry 的持久化 invariant(turn/step 必须在开启中的 step、provider 必须等于该 step 的路由、retry 序号按 provider + policyKey 递增、failure.message/code 非空)。记录被宿主拒收时降级为放行错误,不死循环。

依赖

  • 运行时依赖:@deepseek-ai/cordis ^4.0.1、@deepseek-ai/dsh-llm ^0.1.0-rc.6。第 2 步 bun install 把它们装进 checkout 的 node_modules;dsh plugin add <目录> 是 link: 语义(profile 里的 dsh-agsh-context 是指向 checkout 的符号链接),ESM 加载器按链接真实路径解析,所以裸名 import 时依赖从 checkout 的 node_modules 命中
  • DSH 启动时会用 healProfilesModuleFallback 把 harness 依赖平铺 symlink 到 $DSH_HOME/profiles/node_modules,是 --preserve-symlinks 路径下的第二解析锚点
  • AgentShell 运行件(agent.zsh + src/cli.ts)通过 AGSH_ROOT 定位(或工作目录下的 agent-shell/src/cli.ts)——从未装过先按 INSTALL.md 第 0-2 节从零安装(写 ~/.zshrc 与重启 DSH 两步需用户确认);AgentShell 框架独立发布,不随本包分发
  • 机器前置:bun、jq、tmux

安装(git 分发)

机器上还没有 AgentShell 运行件或 bun/jq/tmux?先按 INSTALL.md 第 0-2 节准备(关键步骤需用户确认),再从下表「取代码」开始。

步骤命令落地
取代码git clone https://github.com/Eric-GoodBoy-Tech/dsh-agsh-context /path/to/dsh-agsh-context(稳定路径,装后保留)源码 + preset/ + dist/
装依赖并构建cd /path/to/dsh-agsh-context && bun install && bun run builddist/index.js(node 目标)
官方安装进 profiledsh plugin --profile web add /path/to/dsh-agsh-contextprofile 目录内裸名 dsh-agsh-context 可解析
注册预设mkdir -p ~/.dsh/.agent-presets/agsh && cp preset/preset.yml preset/agent.cordis.yml ~/.dsh/.agent-presets/agsh/挂载行已是裸包名
验证在 profile 目录:node --input-type=module -e "import('dsh-agsh-context').then(m=>console.log(m.name,typeof m.isAgentShellSession,typeof m.inject,typeof m.apply))"agsh-context function object function
回退预设挂载行改回绝对路径,dsh plugin --profile web remove dsh-agsh-context恢复开发态挂载

不想手动装?把 INSTALL.md 里的「给安装/排障 Agent 的提示词模板」整段复制给你的 DSH Agent,让它替你完成上表全部步骤。

链接安装注意:dsh plugin add <目录> 安装为符号链接(link:),profile 的 node_modules/dsh-agsh-context 指向 checkout 目录本身——安装后不要移动或删除 checkout,否则插件立即失效(恢复目录或重新 bun install 后重跑 dsh plugin --profile <name> add <目录> 即可修复)。

在预设中挂载

开发态(本地源码路径):

- id: agsh-context
  name: '/path/to/dsh-agsh-context/src/index.ts'

发布后(裸包名,dsh plugin add 安装):

- id: agsh-context
  name: 'dsh-agsh-context'

开发

bun install          # 装依赖
bun run build        # node 目标构建 dist/index.js(external @deepseek-ai/*)

发布入口 main/exports 指向 dist/index.js。git 分发,无 npm 发布步骤。