Documentation
¶
Overview ¶
Package acpx 统一调用 CLI Coding Agent(claude / zcode / codex / opencode / minimax / kimi / gemini / qwen / mimo / pi / dsh 共 11 家,另有 GenericAgent 通用出口)。
核心抽象:Agent 接口把各家 headless 模式收敛为统一契约——
Run(Prompt/WorkDir/Model/Session/AllowedTools/Sandbox) → Result(Text/SessionID/Usage) + OnEvent 流式回调(文本增量/工具调用事件透传)
设计对齐 eino:AsTool() 把任意 Agent 包成 tool.BaseTool,挂进 ReAct agent 工具表 (与 rag.KnowledgeService.AsTool 同范式),让 LLM 自主决定调用哪个编码 agent。
安全模型(继承 Argus adapter_cli 实战纪律):
- 进程组执行:Setpgid + 超时/取消 TERM 整组 → killGrace 宽限后 SIGKILL(cmd.Cancel/WaitDelay)
- 环境变量白名单:绝不继承 ARGUS_*/OPENAI_* 等凭证给子进程
- stdout 限容:异常 agent 刷屏防内存放大(单行另设 maxLineLen 上限防无换行洪泛)
- prompt 注入防线:位置参数传递的 prompt 经 promptArg 防护,"-"/"--" 开头的 内容不会被 CLI flag 解析器消费(否则 LLM 自填 prompt 可注入沙箱旁路开关)
Index ¶
- Constants
- func CapsNames(c Capability) (supported, unsupported []string)
- func UnsupportedFields(a Agent, req RunRequest) []string
- type Agent
- type Capability
- type ClaudeCode
- type Codex
- type Event
- type Gemini
- type GenericAgent
- type Kimi
- type Mcode
- type Mimo
- type OpenCode
- type Pi
- type Registry
- type RunEvent
- type RunRequest
- type RunResult
- type Usage
Constants ¶
const ( SandboxReadonly = "readonly" SandboxWorkspace = "workspace" SandboxFull = "full" )
sandbox 词表。
const ( EventText = "text" EventThinking = "thinking" EventToolCall = "tool_call" EventToolResult = "tool_result" EventError = "error" EventResult = "result" )
事件词表。
Variables ¶
This section is empty.
Functions ¶
func CapsNames ¶
func CapsNames(c Capability) (supported, unsupported []string)
CapsNames 能力五字段的支持/不支持双名单(小写字段名,声明序)。capsString 与直连调用方的能力展示面(如 huginn agents 清单的「支持:… | 不支持:…」)共用 此单源——字段表只此一份,增删 Capability 字段时名单自动跟上。
func UnsupportedFields ¶
func UnsupportedFields(a Agent, req RunRequest) []string
UnsupportedFields 返回 req 中非零但 agent 声明不支持的控制面字段名(Go 字段 名,字段声明序)。Registry.Run 的 fail-fast 与直连调用方的降级裁决共用此单源: 经 Registry 的调用方无须自行调用(不支持的请求直接报错);绕过 Registry 直连 Agent.Run 的嵌入方(如 huginn preFlight 范式——整跑失败代价高,选择降级而非 fail-fast)按返回名单自行裁决「剔除降级 / 保留透传+显式告警,绝不静默」。
Types ¶
type Agent ¶
type Agent interface {
// Name agent 标识(claude / codex / opencode / zcode / minimax)。
Name() string
// Run 执行一次任务(headless 模式)。
Run(ctx context.Context, req RunRequest) (*RunResult, error)
// Capabilities 声明对 RunRequest 控制面字段的支持度。能力声明是接口契约的
// 一部分(编译期强制,不给实现者"忘记声明"的余地):Registry.Run 对请求中
// 声明不支持的非零字段 fail-fast——静默丢弃已证伪(kimi 收到 Sandbox=readonly
// 实则全自主裸跑,安全语义静默降级不可接受)。
Capabilities() Capability
}
Agent CLI 编码 agent 统一接口。
type Capability ¶
type Capability struct {
Model bool // 响应 Model 覆盖
Session bool // 响应 SessionID 续聊
MaxTurns bool // 响应 MaxTurns 轮数上限
AllowedTools bool // 响应 AllowedTools 工具白名单
Sandbox bool // 响应 Sandbox 沙箱级别
}
Capability agent 对 RunRequest 控制面字段的支持声明(五字段独立判定)。
type ClaudeCode ¶
type ClaudeCode struct {
Bin string // 默认 "claude"
// contains filtered or unexported fields
}
ClaudeCode Claude Code 适配器(headless:`claude -p --output-format stream-json`)。
func (*ClaudeCode) Capabilities ¶
func (c *ClaudeCode) Capabilities() Capability
Capabilities 全量支持:--model / --resume / --max-turns / --allowedTools / --permission-mode。
func (*ClaudeCode) Run ¶
func (c *ClaudeCode) Run(ctx context.Context, req RunRequest) (*RunResult, error)
Run 执行 headless 任务(stream-json NDJSON 事件流解析)。
type Codex ¶
type Codex struct {
Bin string // 默认 "codex"
}
Codex OpenAI Codex CLI 适配器(`codex exec --json --output-last-message <file>`)。
func (*Codex) Capabilities ¶
func (c *Codex) Capabilities() Capability
Capabilities 支持 Model/Sandbox(-m / --sandbox);exec 无续聊、轮数与工具白名单无对应参数。
type Event ¶
type Event struct {
Type string // text | thinking | tool_call | tool_result | error | result
Text string
Tool string // tool_call/tool_result 的工具名
Raw json.RawMessage
}
Event 流式事件。 各适配器转发覆盖(v0.10.10 起错误事件全量转发——此前只转 text,纯错误跑的 transcript 为空、排障断链):mimo=error/text/result(step_finish);codex= error/text;claude=text/thinking/tool_call/result(is_error 以 error 型转发); pi=error(含 abort)/text/assistant 终态(result);kimi=text;gemini/ opencode 非流式(错误走 Run 返回值,无流式事件)。
type Gemini ¶
type Gemini struct {
Bin string // 默认 "gemini"
// contains filtered or unexported fields
}
Gemini Gemini CLI 适配器(google-gemini/gemini-cli;Qwen Code 为其 fork,参数同族)。
协议要点(非交互模式):
- `gemini -p "<prompt>" --output-format json` 输出单 JSON 对象: {"response":"...","stats":{"models":{"<model>":{"tokens":{"prompt":N,"candidates":N}}}}}
- `-m/--model`;`--approval-mode default|auto_edit|yolo`(沙箱映射)
func (*Gemini) Capabilities ¶
func (g *Gemini) Capabilities() Capability
Capabilities 支持 Model/Sandbox(-m / --approval-mode);非交互模式无续聊、轮数与工具白名单无对应参数。
type GenericAgent ¶
type GenericAgent struct {
AgentName string // agent 标识(Name() 返回值)
Argv []string // argv 模板
IsJSON bool
}
GenericAgent 通用 CLI agent:以显式 argv 模板驱动任意 agent。 模板占位符:{prompt}(原样单参传入,无 shell 注入面)、{model}、{session}。 flag+占位符是**条件单元**:{model}/{session} 缺值时整体移除——连带移除紧邻的 前一个以 "-" 开头的参数(如 ["run","--model","{model}"] 在无 Model 时展开为 ["run"],绝不产生吞掉后续位置参数的悬空 flag)。 IsJSON=true 时按 {"text","sessionID","tokens":{"input","output"}} 解析输出。
用途:CLI 参数协议未稳定或私有 agent 的快速接入;协议稳定后应收敛为 专用适配器(mcode 于 2026-10-04 收敛为 Mcode,Minimax 预设随之移除)。
func NewDsh ¶
func NewDsh() *GenericAgent
NewDsh dsh(DeepSeek Harness)预设:headless profile 单任务出口—— `dsh --profile headless "<task>"` 打印最终 assistant 消息后退出(2026-09-28 本机真实 CLI 核实:stdout 即最终答复、exit 0;无 JSON/会话/模型参数面)。
func NewGenericAgent ¶
func NewGenericAgent(name string, argv []string, isJSON bool) *GenericAgent
NewGenericAgent 创建通用适配器。
func (*GenericAgent) Capabilities ¶
func (g *GenericAgent) Capabilities() Capability
Capabilities 由 argv 模板推导:含 {model} 占位 → 支持 Model,含 {session} → 支持 Session;模板机制无法表达轮数/工具白名单/沙箱,一律不支持。
func (*GenericAgent) Name ¶
func (g *GenericAgent) Name() string
func (*GenericAgent) Run ¶
func (g *GenericAgent) Run(ctx context.Context, req RunRequest) (*RunResult, error)
Run 执行通用 CLI agent。
type Kimi ¶
type Kimi struct {
Bin string // 默认 "kimi"
}
Kimi Kimi Code CLI 适配器(MoonshotAI/kimi-code,参数经本机真实 CLI --help 核实)。
协议要点(非交互模式,headless):
- `kimi -p "<prompt>"` 非交互执行(本身即全自主;不可与 --auto 组合——真实 CLI 实测报错)
- `--output-format stream-json` 输出 JSONL 消息流:{"role":"assistant","content":"..."}
- `-m/--model NAME` 覆盖模型;`-S/--session ID` 续聊
注:文档站描述的旧版 kimi-cli 用 `--print`;新一代 kimi-code 已改为 `-p` 直跑。
func (*Kimi) Capabilities ¶
func (k *Kimi) Capabilities() Capability
Capabilities 支持 Model/Session(--model / --session);沙箱/轮数/工具白名单无对应参数 (非交互模式本身即全自主——传 Sandbox 会被拒绝而非裸跑)。
type Mcode ¶
type Mcode struct {
Bin string // 默认 "mcode"
// contains filtered or unexported fields
}
Mcode MiniMax Code CLI 适配器(`mcode exec <prompt> --output-format json`, 参数与信封经本机真实 CLI 核实)。注册名沿历史键 "minimax"(bin 名为 mcode)。
协议要点(0.6.2 实弹):
- exec 单 JSON 信封输出(stdout 单行): {"schemaVersion","type":"exec.result","sessionId":"mvs_...","status": "succeeded","output","model":{...},"usage":{"inputTokens","outputTokens", "cacheReadTokens","totalTokens"},"usageIncomplete"}
- ⚠ 运行期失败 exit code 仍为 0(假模型名实弹核实)——失败识别只能靠信封 status=failed + error{category,message},本适配器如实上抛并经 EventError 全量转发(不因 exit 0 或有部分文本而当成功——mimo 同纪律)
- `--model provider/model` 覆盖模型;不传用 CLI 缺省(实测 MiniMax-M3.1-Flash-Preview)
- `--session mvs_...` 续聊(实测跨轮记忆成立,sessionId 稳定不变)
- `--max-steps N` 轮数预算(对应 MaxTurns)
- ⚠ 无沙箱可映射:--permission smart 在 headless 下工作区外写也放行 (实测于 $HOME 建文件成功),无"工作区内放行/外禁止"的运行时硬边界—— Capabilities 不声明 Sandbox,工作区硬条款仅剩 prompt 纪律(mimo 同款)
- 非 JSON 输出(版本差异/日志混入)走全文兜底,不崩不误报
func (*Mcode) Capabilities ¶
func (m *Mcode) Capabilities() Capability
Capabilities 支持 Model/Session/MaxTurns(--model / --session / --max-steps); 沙箱与工具白名单无对应参数面(见类型注释 ⚠ 条目)。
type Mimo ¶
type Mimo struct {
Bin string // 默认 "mimo"
// DefaultModel 请求未指定 Model 时的缺省模型(xiaomi/ 全名)。空 = 尊重
// 本机 CLI 配置(其缺省模型可能已被服务端下线)。
DefaultModel string
// contains filtered or unexported fields
}
Mimo 小米 MiMo Code 适配器(`mimo run --format json`,参数经本机真实 CLI 核实)。
协议要点:
- `mimo run "<prompt>" --format json` 输出 JSONL 事件: {"type":"text","part":{"text":"..."}}" 增量文本 {"type":"step_finish","sessionID":"...","part":{"tokens":{"input","output"},"cost":N}} {"type":"error","error":{"data":{"message":"..."},"message":"..."}}(错误详情在 error.data.message——2026-09 实弹核实;error.message 顶层路径为兼容回退)
- `-m provider/model` 覆盖模型:**须 xiaomi/ 全名前缀**(短名被服务端拒绝; 本机 CLI 缺省模型可能被服务端下线——ultraspeed 前车之鉴,生产装配建议显式 配置 DefaultModel)
- `-s/--session ID` 续聊
- ⚠ 运行期错误 exit code 仍为 0——错误识别只能靠事件流,本适配器对 error 事件如实上抛(不因恰好有部分文本而掩盖),并经 EventError 全量转发
func (*Mimo) Capabilities ¶
func (m *Mimo) Capabilities() Capability
Capabilities 支持 Model/Session(-m / -s);沙箱/轮数/工具白名单无对应参数。
type OpenCode ¶
type OpenCode struct {
Bin string // 默认 "opencode"
}
OpenCode opencode 适配器(`opencode run --json`)。
func (*OpenCode) Capabilities ¶
func (c *OpenCode) Capabilities() Capability
Capabilities 支持 Model/Session(-m / --session);沙箱/轮数/工具白名单无对应参数。
type Pi ¶
type Pi struct {
Bin string // 默认 "pi"
// DefaultModel 请求未指定 Model 时的缺省(provider/id 形态)。空 = 尊重
// 本机 CLI 配置。
DefaultModel string
// contains filtered or unexported fields
}
Pi pi-coding-agent 适配器(`pi --mode json -p --no-session`,参数经本机真实 CLI 核实,2026-09-28 实弹采样)。
协议要点:
- `pi --mode json -p "<prompt>"` 输出 JSONL 事件流: {"type":"message_start","message":{"role":...,"provider":...,"model":...}} {"type":"message_update","assistantMessageEvent":{"type":"text_delta",...}} {"type":"message_end","message":{"role":"assistant","content":[{"type": "thinking",...},{"type":"text","text":"..."}],"usage":{"input","output", "totalTokens","cost":{...}},"stopReason":...}} {"type":"turn_end"| "agent_end" | "agent_settled" | "session" | ...} 文本取 assistant message_end 的 "text" 内容块(thinking 块不计入正文); usage 含 input/output/reasoning 与 cost(多轮 message_end 后者覆盖前者)。
- `-p/--print` 非交互执行;`--no-session` 不落会话(acpx 语义:每次 Run = 独立任务,不在 ~/.pi 留状态);扩展/技能/AGENTS.md 发现保持本机默认 (编码任务需要这些环境)。
- `--model provider/id[:thinking]` 覆盖模型(支持 provider/id 形态)。
- 中止形态(turn_abort 等)无 assistant message_end:有 exit!=0 时以退出错 误为准;exit=0 且事件流含 abort 类事件时如实报错(不静默空成功)。
func (*Pi) Capabilities ¶
func (p *Pi) Capabilities() Capability
Capabilities 支持 Model(--model)与 Session(--session-id 精确续聊, 缺省则 --no-session 一次性);沙箱/轮数/工具白名单无对应参数。
type Registry ¶
type Registry struct {
// OnRun 每次经本 Registry 发起的运行结束后的回调(nil 安全)。
// 观测入口:接结构化日志/Prometheus/trace 均可,本包不硬依赖任何观测后端。
OnRun func(RunEvent)
// contains filtered or unexported fields
}
Registry agent 注册表:名字 → Agent 实例。
func NewRegistry ¶
func NewRegistry() *Registry
NewRegistry 创建注册表并注册缺省 agent (claude/zcode/codex/opencode/minimax/kimi/gemini/qwen/mimo/pi/dsh,11 家)。
type RunEvent ¶
type RunEvent struct {
Agent string // agent 名
Duration time.Duration // 运行耗时
Err error // 非空 = 运行失败
TextLen int // 产出文本长度(不落内容,防泄露)
Usage Usage
SessionID string
}
RunEvent 一次 agent 运行的观测事件(Registry.OnRun 钩子载荷)。
type RunRequest ¶
type RunRequest struct {
Prompt string // 任务描述
WorkDir string // 工作目录(agent 在此目录下执行)
Model string // 模型覆盖(空 = agent 默认)
// SessionID 续接会话(Claude --resume / opencode --session;Codex 暂不支持续聊)。
SessionID string
// MaxTurns 最大 agent 轮数上限(防失控循环;0 = agent 默认)。
MaxTurns int
// AllowedTools 工具白名单(claude 族语义:"Bash(git:*)" "Read" "Edit";
// 空 = agent 默认)。
AllowedTools []string
// Sandbox 沙箱级别:readonly | workspace | full(Codex 原生支持;
// claude 族映射 permission-mode)。
Sandbox string
// Env 额外环境变量白名单,两种形态:纯名("HF_TOKEN")按名从当前进程
// 透传;"KEY=VALUE" 字面注入(同名父进程值不透传——显式注入优先,见
// procx.ChildEnv)。值会进入子进程环境,调用方自负泄漏面。
Env []string
// Timeout 单次运行超时(0 = 10 分钟缺省)。
Timeout time.Duration
// OnEvent 流式事件回调(nil = 只取最终结果)。
// 注意:回调在 stdout 读取 goroutine 中同步执行——不得阻塞(拖慢子进程
// 输出消费),不得 panic(会击穿整个进程)。
OnEvent func(Event)
}
RunRequest 统一运行请求。
type RunResult ¶
type RunResult struct {
Text string // 最终 assistant 文本
SessionID string // 会话 ID(供续聊)
Usage Usage
Duration time.Duration
ExitCode int
Raw []byte // 原始 stdout(调试用)
// Stderr 子进程 stderr 尾巴(≤400 字节,rune 对齐;空 = 无输出)。成功
// 解析路径也有值——CLI 的告警/弃用提示走 stderr,transcript 排障需要。
Stderr string
}
RunResult 统一运行结果。