Skip to content

feat(adapters): 新增 Kiro CLI 适配器#431

Merged
deepcoldy merged 5 commits into
deepcoldy:masterfrom
luozejian:feat/kiro-cli-adapter
Jul 13, 2026
Merged

feat(adapters): 新增 Kiro CLI 适配器#431
deepcoldy merged 5 commits into
deepcoldy:masterfrom
luozejian:feat/kiro-cli-adapter

Conversation

@luozejian

Copy link
Copy Markdown
Contributor

概述

支持 Kiro CLI (kiro-cli) 作为 botmux CLI 后端。新增 cliId: "kiro-cli",展示名为 Kiro,默认执行 kiro-cli chat,并保留现有 cliPathOverride 机制用于覆盖实际启动路径。

关键设计决策

  • 显式使用 chat 子命令:根据 Kiro 官方文档,交互会话入口为 kiro-cli chat,裸 kiro-cli 虽会默认进入 chat,但适配器里显式写出子命令,避免依赖默认路由。
  • 首条消息走 positional input:Kiro 文档支持 kiro-cli chat "prompt",因此设置 passesInitialPromptViaArgs: true,让首条消息随启动参数传入,减少首轮 stdin race。
  • 精确 resume 走 --resume-id:仅当 botmux 已持有 Kiro 原生 cliSessionId 时传 --resume-id <ID>。没有明确 ID 时不使用 --resume,避免目录级“最近会话”在多 bot 并发下串会话。
  • 不传 --model:Kiro chat 命令没有 --model 参数,模型切换通过 /modelkiro-cli settings chat.defaultModel 完成;adapter 会忽略 botmux 的 model 字段,防止 unknown flag 导致启动失败。
  • 工具信任使用 --trust-tools=read,write,shell:不使用 --trust-all-tools,因为 Kiro terminal UI 会弹风险确认,可能卡住无人值守的 botmux 会话。disableCliBypass: true 时不注入 trust 参数。
  • 多行输入使用 Ctrl+J 软换行:Kiro 文档说明 Ctrl+J 在 tmux 等终端中可作为换行输入;adapter 在 tmux 写入多行消息时逐行发送并用 C-j 插入软换行,最后 Enter 提交。
  • sandbox 绑定 ~/.kiro:Kiro 的认证、settings、skills 和 SQLite 会话库都位于 ~/.kiro,文件沙盒下将该目录真实绑定,避免登录态丢失或 SQLite 在 overlayfs 下异常。
  • 接入 Kiro Skills 目录:配置 skillsDir: "~/.kiro/skills",让 botmux 的技能发现/安装机制能识别 Kiro 的 Agent Skills 标准目录。

测试

  • test/cli-adapters.test.ts

    • 覆盖 kiro-cli factory、lazy resolve、id、display 相关基础矩阵
    • 覆盖 kiro-cli chat 参数生成
    • 覆盖 --trust-tools=read,write,shelldisableCliBypass
    • 覆盖 initialPrompt positional input
    • 覆盖 --resume-id <cliSessionId> 精确恢复
    • 覆盖不传 --model
    • 覆盖 authPaths: ["~/.kiro"]skillsDir: "~/.kiro/skills"
  • test/write-input.test.ts

    • 覆盖 Kiro 多行输入:逐行 sendText,中间用 C-j 软换行,最后 Enter 提交
  • test/bot-config-editor.test.ts

    • 覆盖 setup 序号 22 -> kiro-cli
    • 覆盖字面量 kiro-cli 可解析
  • test/card-builder.test.ts

    • 覆盖 kiro-cli -> Kiro 展示名
  • test/dashboard-sessions-ui.test.ts

    • 覆盖 dashboard sessions CLI 过滤项包含 kiro-cli

文档与脚手架

  • README.md / README.en.md 增加 Kiro / kiro-cli 到支持列表
  • docs-site/docs/zh/adapters.md / docs-site/docs/en/adapters.md 增加 kiro-cli 适配器说明
  • src/setup/bot-config-editor.ts setup 菜单追加第 22 项,遵守“新增 CLI 只追加到尾部”的稳定序号约定
  • src/worker.ts / src/im/lark/card-builder.ts 增加 Kiro 展示名映射
  • src/core/session-discovery.ts 增加 kiro-cli 进程名识别

验证步骤

pnpm test -- test/cli-adapters.test.ts test/write-input.test.ts test/card-builder.test.ts test/bot-config-editor.test.ts test/dashboard-sessions-ui.test.ts
pnpm build

验证结果:

  • 单测:545 passed
  • 构建:通过
  • pnpm daemon:restart:当前机器未找到 botmux 配置文件,提示需先运行 botmux setup,因此未完成 live daemon 重启

影响范围

  • 新增独立 CLI adapter,不改变其它 CLI 的启动参数和输入协议。
  • 公共注册路径有变更:CliId、adapter registry、setup CLI 选项、worker/card 展示名、dashboard CLI 过滤项。
  • sandbox 行为仅新增 kiro-cli~/.kiro carve-out,不影响现有 CLI 的 authPaths

@luozejian
luozejian requested a review from deepcoldy as a code owner July 10, 2026 11:18
@deepcoldy

Copy link
Copy Markdown
Owner

辛苦接 Kiro CLI 适配,整体方向看起来是对的:kiro-cli chat--resume-id--trust-tools=read,write,shell 这些参数也都能和 Kiro 文档对上。注册、展示名、setup 选项和基础测试也基本补齐了。

我这边主要看到两个需要先补的点:

  1. Kiro 的原生 session id 现在没有被 botmux 保存下来

    adapter 里只有在已经有 resumeSessionId 的时候才会传 --resume-id,但新会话启动后并没有任何地方把 Kiro 自己生成的 session id 读出来并存到 cliSessionId

    这样会导致一个比较实际的问题:Kiro 会话跑起来以后,如果 daemon / worker 重启,botmux 会尝试 resume,但手里没有 Kiro 的原生 ID,于是启动参数里不会带 --resume-id,最后很可能就变成新会话,旧上下文丢了,而且用户不一定能立刻意识到。

    建议补一个 session id 捕获路径,比如启动后通过 Kiro 支持的 /session-id 拿到 ID,或者从 Kiro 的本地 session store 里稳定解析出来,再走现有的 cli_session_id 持久化链路。实在暂时不做精确 resume,也建议明确标成限制,避免看起来支持但实际恢复不到原会话。

  2. workflow resume 的能力表漏了 kiro-cli

    现在 src/workflows/attempt-resume.ts 和前端 src/dashboard/web/workflows.ts 里都有一份 resume 能力列表,但没有把 kiro-cli 加进去。

    结果是:即使后面拿到了 Kiro 的 cliSessionId,workflow attempt 结束后从 UI 恢复终端时,后端也会认为这个 CLI 不支持 precise resume,前端也会按不可恢复处理。

    这里建议把 kiro-cli 加到“需要原生 cliSessionId 才能恢复”的那组里,并补一个 workflow resume 测试,防止以后新增 adapter 时漏掉这条链路。

我验证了一下:

  • PR head 上相关单测通过:adapter / write-input / card / setup / dashboard sessions 等测试共 623 passed
  • pnpm build 通过
  • 用当前 origin/master 临时 merge 了一下,没有冲突;merge 结果上相关测试也通过,pnpm build 也通过

所以主要不是编译或基础注册问题,而是 Kiro 接入后“会话恢复”这条链路还差最后一段。

@luozejian

Copy link
Copy Markdown
Contributor Author

@deepcoldy 已处理 review 反馈,并同步最新 origin/master 解决冲突。新增两个提交:

  • 904d5b9b fix(adapters): 补齐 Kiro 会话恢复链路
  • 43eb2015 chore(merge): 同步 master 并解决 Kiro 冲突

Review 反馈修复

针对 Kiro 会话恢复链路补齐了两块:

  1. 捕获并持久化 Kiro 原生 session id

    Kiro adapter 首次向 PTY 写入用户消息前,会先发送 /session-id。worker 侧从后续 PTY 输出中解析 Kiro 原生 session id,并复用现有 cli_session_id 持久化链路。

    为避免误识别,只解析两类输出:

    • kiro-cli chat --resume-id <uuid>
    • 单独一行 UUID

    不会把 Session ID: <botmux-id> 这种 botmux 自己的提示块误当成 Kiro 原生 ID。

  2. 补齐 workflow resume 能力表

    已把 kiro-cli 加入后端 src/workflows/attempt-resume.ts 和前端 src/dashboard/web/workflows.ts 中“需要原生 cliSessionId 才能 resume”的 CLI 列表。

    这样 workflow attempt 如果缺少 Kiro 原生 cliSessionId,会明确报 missing_cli_session_id,不会静默新起会话;前端也会按“缺少 cliSessionId”处理,而不是误判为不支持 resume。

冲突解决

随后同步了最新 origin/master,解决了上游新增 Grok Build 与本 PR 新增 Kiro 同时修改 CLI 注册/展示/文档列表造成的冲突。

处理方式是保留双方改动:

  • 保留上游 grok 适配器注册
  • 保留本 PR kiro-cli 适配器注册
  • CliId 同时包含 grokkiro-cli
  • registry.ts 同时导出并创建 createGrokAdapter / createKiroCliAdapter
  • session-discovery 同时识别 grok / kiro-cli 进程名
  • worker 和 Lark 卡片展示名同时包含 Grok Build / Kiro
  • setup 菜单序号保持上游 grok = 22kiro-cli 顺延追加为 23
  • README 中英文支持列表合并为 Grok Build + Kiro 都在列表中

新增/更新测试

  • test/kiro-session.test.ts

    • 覆盖 Kiro 输出中的 --resume-id <uuid> 解析
    • 覆盖单独 UUID 行解析
    • 覆盖不会误识别 Session ID: <botmux-id>
  • test/write-input.test.ts

    • 覆盖 Kiro 首次写入前发送 /session-id
    • 覆盖同一个 PTY 只请求一次 /session-id
  • test/workflow-attempt-resume.test.ts

    • 覆盖 kiro-cli 缺少原生 cliSessionId 时拒绝 resume
  • test/dashboard-workflow-resume.test.ts

    • 覆盖 dashboard 将 kiro-cli 识别为可 resume 且需要原生 cliSessionId
  • 合并冲突后也跑了 Grok 相关测试,确认上游 Grok Build 接入未被 Kiro 改动破坏。

验证

pnpm test -- test/kiro-session.test.ts test/cli-adapters.test.ts test/write-input.test.ts test/workflow-attempt-resume.test.ts test/dashboard-workflow-resume.test.ts test/card-builder.test.ts test/bot-config-editor.test.ts test/dashboard-sessions-ui.test.ts test/grok-transcript.test.ts test/structured-bridge-clis.test.ts
pnpm build

结果:

  • 单测:611 passed
  • 构建:通过

@deepcoldy

Copy link
Copy Markdown
Owner

辛苦,最新这版我重新看了一轮。之前提的两条主线基本补上了:

  • kiro-cli 已经会通过 /session-id 取 Kiro 原生 session id,并走 worker 现有的 cli_session_id 持久化链路。
  • workflow resume 的前后端能力表也补了 kiro-cli,缺少原生 cliSessionId 时会明确报错。
  • 跟最新 master 的 Grok Build 冲突处理看起来也没把双方注册点覆盖掉。

我这边还看到一个需要补的小缺口:

P2 非 tmux / PtyBackend 下仍然不会请求 Kiro session id

位置:src/adapters/cli/kiro-cli.ts:36 附近。

现在 /session-id 只在这个分支里发送:

if (pty.sendText && pty.sendSpecialKeys) {
  // send /session-id
}

PtyBackend 只有 write(),没有 sendText / sendSpecialKeys(见 src/adapters/backend/pty-backend.ts:48)。所以如果用户配置了 backendType: "pty",或者机器上 tmux 不可用,Kiro adapter 会走 fallback 分支:

pty.write(content.replace(/\n/g, '\x0a'));
await delay(1000);
pty.write('\r');

这个分支没有先发 /session-id。worker 侧虽然已经 arm 了 Kiro session id capture,但没有 slash command 输出可解析,cliSessionId 还是不会被保存。之后 worker / daemon 重启时就拿不到 --resume-id,非 tmux Kiro 会话仍然会丢上下文。

建议把 fallback 分支也补成先写一次 /session-id\r,等一下,再写真实用户消息;同时加一个只有 write() 的 fake PtyHandle 测试,覆盖非 tmux 路径也只请求一次 /session-id

我这轮验证:

  • PR head:作者列出的测试通过,611 passed
  • PR head:pnpm build 通过
  • 当前 origin/master + PR 临时 merge:无冲突;同一组关键测试通过,623 passed
  • merge 结果:pnpm build 通过

@deepcoldy

Copy link
Copy Markdown
Owner

我让agent直接修了吧

@deepcoldy
deepcoldy merged commit 292b6fe into deepcoldy:master Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants