Built-ins

Shell Built-In

内建 shell tools、sandbox 模式与审批流程

Shell Built-In

Shell 不再是 plugin。它是 @downcity/shell 提供的内建能力,通过 new Shell() 挂到 Agent 上。

import { Agent } from "@downcity/agent";
import { Shell } from "@downcity/shell";

const agent = new Agent({
  id: "repo-helper",
  path: "/path/to/project",
  shell: new Shell(),
});

Tools

传入 shell: new Shell() 后,模型会获得这些工具:

  • shell_exec
  • shell_session

shell_exec 用于一次性非交互命令;shell_session 用于 PTY 交互式会话,支持 startsendreadliststop action。

shell_exectimeout_ms 是命令总执行时长。显式传入较短值会按该值超时并终止进程;长任务应改用 shell_session,不要依赖 shell_exec 持续等待。

Sandbox 模式

Shell tools 默认进入 Safe Sandbox。

只有需要宿主级能力时才使用 sandbox: "unrestricted",例如 brew installnpm install -gpip install --usergh auth login,或初始化项目 sandbox 外的宿主服务。

shell_exec({
  cmd: "brew install ffmpeg",
  sandbox: "unrestricted",
  reason: "Homebrew 需要写入宿主级 package 目录。",
});

Unrestricted 执行每次都需要用户审批。缺少 reason 会在执行前被拒绝。

审批 API

前端或 SDK 客户端通过发起工具调用的 Session 审批:

const pending = await session.approvals();

await session.resolve_approval({
  approval_id: pending[0].approval_id,
  decision: "approved",
});

本地和远程 Session 暴露相同 API。实时 UI 在 session.subscribe() 收到 approval-required Tool Part 时,从 mutation.part.approval 读取请求,再通过 session.resolve_approval(...) 提交决定。

Session Approval Mode

Shell approval mode 只作用于当前 session:

  • ask:默认模式,每次 unrestricted 请求都进入审批队列。
  • always-allow:当前 session 内自动通过 shell approval,不再弹出新的 pending approval。
await session.set_approval_mode({
  mode: "always-allow",
});

const current = await session.approval_mode();

always-allow 不改变 sandbox 模式,只是把原本需要手动批准的 unrestricted 请求自动记录为 approved。已有 pending approval 不会被自动批准。

关键语义

  • Shell 归属于 @downcity/shell,不属于 @downcity/plugins
  • Agent 只挂载 Shell tools;工具审批和实时 Mutation 都归属具体 Session。
  • Safe Sandbox 命令可读写项目,并使用配置的 sandbox 目录。
  • Unrestricted 命令只有在逐次审批通过后才会离开 Safe Sandbox 执行。
  • always-allow 只影响当前 session 的新 approval 请求,不影响其它 session。
  • 对 unrestricted shell_session 会话执行的每一次 send 也需要审批。
  • agent.dispose() 会释放 Shell sessions,并把仍在等待的 approval 兑现为过期,调用不会永久挂起。

相关文档