LiZheng1992123/dsh-llm-kiro
Project Overview项目介绍
This is an LLM adapter plugin for DeepSeek Harness, which routes DSH LLM requests to a locally installed, logged-in Kiro CLI. It reuses Kiro's login status without extra configuration, fetches models in real time, supports tool bridging and accurate context counting. Note that switching models or thinking effort requires rebuilding the Kiro session, and long sessions leave extra records in Kiro CLI.
这是DeepSeek Harness的LLM适配器插件,可将DSH的LLM请求路由到本地已安装登录的Kiro CLI,复用Kiro登录态无需额外配置,支持实时拉取模型列表、工具桥接和上下文真实计量。注意切换模型或思考档位需要重建Kiro会话,超长会话会在Kiro CLI留下额外会话记录。
请帮我了解并安装插件:【dsh-llm-kiro】【https://github.com/LiZheng1992123/dsh-llm-kiro】
Send this message to DSH in your current session. CLI install commands may not be accurate across systems — DSH will figure it out for you.把上面这条消息直接发给当前会话里的 DSH,让它帮你了解并安装。安装命令不一定准确,发给 DSH 更稳。
Or use CLI install (for developers)或使用命令行安装(适合开发者)
CLI Install命令行安装
dsh plugin --profile web add github:LiZheng1992123/dsh-llm-kiro
把 LiZheng1992123/dsh-llm-kiro 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
dsh-llm-kiro
将 DeepSeek Harness 的 LLM 接缝(ctx.llm)路由到本机 Kiro CLI 的适配器插件(@lizheng1992123/dsh-llm-kiro),基于 kiro-cli 自带的 acp 子命令(Agent Client Protocol,JSON-RPC 2.0 over stdio)。
它注册 kiro provider 路由,让 harness 的模型请求复用本机 kiro-cli 的登录态——无需任何凭据或设置项。模型目录从 kiro-cli 实时拉取。
特性
- 无配置接入:完全复用本机
kiro-cli登录态(IAM Identity Center / Builder ID),不需要 API key 或 settings 段。 - 零运行时依赖:不依赖任何 agent SDK——ACP 客户端是纯 Node
child_process+ 手写 JSON-RPC(约 200 行),没有 postinstall,安装无需批准构建脚本。 - 长驻会话:每个宿主 session id 对应一个 warm
kiro-cli acp子进程,对话延续、工具轮次都发生在会话内部;maxSessions上限内按插入序 LRU 淘汰。 - 工具桥接:宿主工具通过每会话一个 loopback HTTP MCP server(
dsh-host)暴露给内层模型;模型调用到达 MCP server 后 park,宿主在下一轮请求里回传结果,按 callId 配对(120s 内未回传则超时取消)。 - 原生工具隔离:kiro 以
--trust-tools=(零信任)启动,一切工具调用都经过 ACPsession/request_permission回调——只有@dsh-hostMCP 工具被放行,内层模型的原生工具(fs、bash 等)一律拒绝。 - 真实上下文占用:kiro 在流中通过
_kiro.dev/metadata上报contextUsagePercentage,插件按模型窗口折算成inputTokens上报——UI 上下文环与自动压缩阈值用的是 kiro 侧的真实占用(含其 preset 开销),而不是字符估算;估算仅作未上报时的兜底。 - 模型目录:
kiro-cli chat --list-models --format json实时拉取(含context_window_tokens),TTL 缓存 + 并发共享 + 超时保护,失败回退静态目录。 - 思考档位:每个模型广告
low / medium / high / xhigh / max五档(kiro-cli--effort),选择后在会话重建时生效。 - 旁路请求:标题生成、compaction 等 side-channel 请求走冷启动一次性 ACP 会话,不占用 warm 会话,且复用主会话模型。
- 代理自动接入:
cliPath为默认值时自动探测已安装的 kiro-proxy 进程级代理包装器(~/.local/bin/kiro-proxy),插件派生的 kiro-cli 进程随之走代理,无需在宿主全局环境 export 任何代理变量。 - 溢出可恢复:内层报错文本经 dsh-llm 的
isContextWindowExceededError/isQuotaExceededError分类为CONTEXT_WINDOW_EXCEEDED/QUOTA_EXCEEDED上报,harness 的溢出自动恢复(配合compaction-basic)可以接管。
适配原理
1. LLM 接缝适配(ctx.llm → kiro-cli)
| harness 接缝 | 本插件实现 |
|---|---|
providerInfo(provider) |
返回 kiro(Kiro CLI)的展示名 |
listModels(provider) |
实时拉取 kiro-cli 模型目录 |
resolveModel(provider, model) |
从 live catalog / 静态表解析模型元数据(上下文窗口、思考档位、输出上限) |
stream(options) |
把一次 GenerateOptions 转成 ACP session/prompt 并流式回传 StreamChunk |
stream() 的分流与 qoder 插件一致:warm 会话路径(有 sessionId 且无 purpose)复用内层 ACP 会话;side-channel 路径走 coldStream() 一次性调用。
2. 会话模型适配
- 一宿主会话对应一 warm kiro-cli ACP 会话:
KiroSessionManager以宿主sessionId为键维护子进程,超出maxSessions按插入序 LRU 淘汰。 - 增量 feed:kiro 服务端持有会话状态,宿主每轮只把新用户轮次与改写消息渲染成纯文本 prompt(
planContinuation与 qoder 插件同逻辑);工具结果不进入文本 feed(走 MCP)。 - 重建检测:宿主 surface 被改写(compaction 折叠历史等)导致消息数变少或结构变化时,
planContinuation返回rebuild: true,插件 dispose 旧会话并按新 surface 冷启动,dsh 侧压缩与 kiro 内部状态不会产生双份状态。 - 模型/档位切换:
--model/--effort是 kiro-cli acp 的启动期参数,切换时插件销毁旧子进程、以新参数冷启动并重喂宿主历史(文本级延续)。这是与 qoder 插件(运行期setModel)的一个差异。
3. 工具桥接适配(HTTP MCP)
- 每个内层会话启动前,插件在
127.0.0.1随机端口起一个极简 streamable-HTTP MCP server(dsh-host),经session/new的mcpServers传入; - 宿主
ToolSchema.parameters是 JSON Schema,原样透传为 MCPinputSchema(无需 zod 转换); - 模型的工具调用以 HTTP
tools/call到达(参数完整携带),插件据此向宿主发出tool-call块并 park 响应; - turn 结束时机(settle window):ACP 的
session/prompt是一次长 RPC,模型被工具阻塞时没有任何"暂停"事件。插件在最后一次 MCP 调用后静默 400ms(窗口内并发的并行调用会并入同一轮),随后以tool-calls结束宿主轮次; - 宿主下一轮请求
deliverToolResults()按 callId 解析 park 的 handler,kiro 继续该 prompt RPC——对 kiro 而言只是"MCP 工具执行了一次"; - 迟到的并行调用(落在两轮间隙)会被缓存到下一轮开头补发,避免 prompt RPC 卡死到 120s 超时。
4. 权限门控
kiro-cli 以 --trust-tools=(不信任任何工具)启动,所有工具调用都触发 session/request_permission:插件对 _meta.kiro.mcpServerName === 'dsh-host'(或标题含 @dsh-host/)的调用自动 allow,其余(内层模型的原生 fs/bash 等)自动 deny。内层模型只能经由宿主 MCP 工具行动。
5. 上下文占用计量
kiro 流中的 _kiro.dev/metadata 通知携带 contextUsagePercentage(以及 credit 计量 meteringUsage)。插件按 resolveModel 广告的同一窗口折算:
inputTokens = contextUsagePercentage / 100 × contextWindow
这比 qoder 插件的 chars/4 估算更准(包含 kiro preset 自身开销)。未上报时(如冷启动首帧之前)回退到 chars/4 估算,口径与 harness estimate.ts 一致。
6. 错误分类与压缩分工
与 qoder 插件一致:压缩由 dsh(compaction-basic)执行,插件只充当 LLM 后端;内层报错文本经共享分类器映射为 harness 可路由的错误码。dsh 压缩改写 surface 后,插件检测 rebuild 并重建内层会话,不存在"两边各压一遍"。
注意:kiro-cli 自身也有内部 compaction。它以增量 feed 运行,内部压缩不影响 dsh 侧状态,但意味着超长会话中 kiro 可能遗忘 dsh 尚未压缩的早期细节。建议沿用 dsh 侧较低的
thresholdRatio(如 0.6),让 dsh 压缩先于 kiro 内部压缩触发。
安装
前置条件:本机已安装并登录 kiro-cli(kiro-cli whoami 可运行)。插件完全复用 kiro-cli 登录态,不需要 API key 或 settings 段。
运行环境要求:kiro-cli ACP 的会话状态落库在
~/Library/Application Support/kiro-cli/data.sqlite3(macOS)。运行 dsh server 的环境必须对该目录可写,否则session/new会无声挂起(只读沙箱中已实证)。正常部署无此限制。
从发布包引入
pnpm pack # 生成 lizheng1992123-dsh-llm-kiro-<version>.tgz
dsh plugin --profile <profile> add lizheng1992123-dsh-llm-kiro-<version>.tgz
dsh --profile <profile> --dump-config | grep llm-kiro # 验证
无 postinstall、无构建脚本批准流程。重启服务后模型选择器出现 kiro。
手动挂载(可选)
- id: llm-kiro
name: '@lizheng1992123/dsh-llm-kiro'
配置
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
maxSessions |
number | 8 |
同时保持 warm 的内层 kiro-cli 会话上限(超出按插入序 LRU 淘汰) |
modelCacheTtlSeconds |
number | 300 |
CLI 模型目录的缓存保鲜秒数 |
cliPath |
string | kiro-cli |
kiro-cli 可执行文件名或绝对路径。默认值会自动探测 kiro-proxy 包装器(见下节);填真实 CLI 的绝对路径则强制直连 |
代理(kiro-proxy 自动探测)
插件通过 spawn / execFile 直接拉起 kiro-cli,不经过交互式 shell,因此 kiro-cli-proxy 项目注入 ~/.zshrc 的 shell 函数对插件不生效。为此插件在 cliPath 保持默认值 kiro-cli 时按以下顺序解析实际启动的可执行文件:
~/.local/bin/kiro-proxy(kiro-cli-proxy 的标准安装位置,存在且可执行则优先);PATH中的kiro-proxy;- 都没有则回退到裸
kiro-cli(直连)。
探测到包装器时,插件 spawn 的每个 kiro-cli 进程(warm ACP 会话、模型目录拉取、side-channel 冷调用)都会经 kiro-proxy 注入 HTTP_PROXY / HTTPS_PROXY / NO_PROXY,代理配置的唯一事实来源仍是 ~/.kiro/settings/cli-proxy.json——kiro-proxy --proxy-off / --proxy-set / --proxy-bypass-add 对插件同样生效。插件启动时会打一条日志说明命中的解析结果。
注意两点:
- 绕过方式:显式把
cliPath设为真实 CLI 的绝对路径(如~/.local/bin/kiro-cli)即跳过包装器、强制直连。 - 回环依赖 noProxy:宿主工具经
http://127.0.0.1:<port>的 loopback MCP server 桥接给内层模型,cli-proxy.json的http.noProxy必须保留127.0.0.1/localhost(默认即包含),否则工具桥会被代理掐断。 - warm 会话是长驻进程,代理变量只在 spawn 时注入;改完
cli-proxy.json后新会话生效,旧会话随 LRU 淘汰或重建后更新。
上下文管理与压缩
与 qoder 插件相同的建议:加载 dsh-compaction-basic 与 dsh-token-meter,并把 thresholdRatio 调低到 0.6,让压力压缩远早于溢出触发:
- id: compaction-basic
config:
auto: true
thresholdRatio: 0.6
retainRatio: 0.16
源码结构
| 文件 | 职责 |
|---|---|
src/index.ts |
插件入口:ctx.llm.registerAdapter(['kiro'], adapter) |
src/adapter.ts |
KiroAdapter:模型列表/解析/流式生成,warm 会话管理、续轮规划、side-channel 冷调用 |
src/session.ts |
KiroSession:ACP 子进程生命周期、turn 状态机、工具 park/resume、usage 上报(真实占用优先)、错误分类 |
src/acp.ts |
极简 ACP JSON-RPC 2.0 stdio 客户端(跳过 stdout 混入的 Rust 日志行;应答 session/request_permission) |
src/mcpserver.ts |
每会话 loopback streamable-HTTP MCP server(JSON Schema 原样透传) |
src/models.ts |
实时模型目录拉取(TTL 缓存、并发共享、超时、静态回退) |
src/clipath.ts |
CLI 可执行文件解析:kiro-proxy 包装器自动探测与直连回退 |
src/catalog.ts |
静态模型表(回退用) |
src/render.ts |
宿主消息 → 内层纯文本 feed |
smoke.mjs |
端到端冒烟测试(不依赖 harness,直接驱动 adapter) |
已知限制
- 模型/思考档位切换会重建内层会话(kiro-cli 的
--model/--effort是进程启动参数);对话以宿主历史重喂,文本级延续。 - kiro 会话在 CLI 侧持久化:每次会话重建都会在 kiro-cli 的会话存储里留下一条记录,可用
kiro-cli chat --list-sessions/--delete-session <id>清理。 - 图片消息:宿主图片块目前在 feed 中渲染为
[图片附件]占位符(kiro ACP 声明支持图像输入,透传留待后续版本)。 - turn 结束依赖 400ms 静默窗口(ACP 没有工具等待事件);极端慢的并行工具调用风扇可能拆成两轮,功能不受影响。
开发与构建
pnpm install
pnpm test # vitest 单元测试
pnpm run build # tsc 产出 lib/types/*.d.ts,tsdown 产出 lib/index.js
node smoke.mjs # 端到端冒烟测试(需要本机已登录 kiro-cli)
pnpm pack # 生成 lizheng1992123-dsh-llm-kiro-<version>.tgz
multica-ai/dsh-multica-runtime
flyhigao/dsh-sticky-notes
liangmianya/dsh-synapse
alaliqing/claude-paper
omdsh-dev/dsh-annotation
Anionex/dsh-turn-rewind
hanshenmesen/dsh-turn-delete