acpx

package
v0.13.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: MIT Imports: 15 Imported by: 1

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

View Source
const (
	SandboxReadonly  = "readonly"
	SandboxWorkspace = "workspace"
	SandboxFull      = "full"
)

sandbox 词表。

View Source
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 NewClaudeCode

func NewClaudeCode() *ClaudeCode

NewClaudeCode 创建 Claude Code 适配器。

func NewZCode

func NewZCode() *ClaudeCode

NewZCode 创建 ZCode 适配器(CLI 参数协议与 Claude Code 同族)。

func (*ClaudeCode) Capabilities

func (c *ClaudeCode) Capabilities() Capability

Capabilities 全量支持:--model / --resume / --max-turns / --allowedTools / --permission-mode。

func (*ClaudeCode) Name

func (a *ClaudeCode) Name() string

Name Agent 接口的 Name 实现(适配器嵌入即得)。

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 NewCodex

func NewCodex() *Codex

NewCodex 创建 Codex 适配器。

func (*Codex) Capabilities

func (c *Codex) Capabilities() Capability

Capabilities 支持 Model/Sandbox(-m / --sandbox);exec 无续聊、轮数与工具白名单无对应参数。

func (*Codex) Name

func (c *Codex) Name() string

func (*Codex) Run

func (c *Codex) Run(ctx context.Context, req RunRequest) (*RunResult, error)

Run 执行 Codex exec 任务。 最终文本优先取 --output-last-message 文件(官方保证的最终消息),事件流兜底。

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 NewGemini

func NewGemini() *Gemini

NewGemini 创建 Gemini CLI 适配器。

func NewQwen

func NewQwen() *Gemini

NewQwen 创建 Qwen Code 适配器(gemini-cli fork,参数同族)。

func (*Gemini) Capabilities

func (g *Gemini) Capabilities() Capability

Capabilities 支持 Model/Sandbox(-m / --approval-mode);非交互模式无续聊、轮数与工具白名单无对应参数。

func (*Gemini) Name

func (a *Gemini) Name() string

Name Agent 接口的 Name 实现(适配器嵌入即得)。

func (*Gemini) Run

func (g *Gemini) Run(ctx context.Context, req RunRequest) (*RunResult, error)

Run 执行 Gemini CLI 非交互任务。

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 NewKimi

func NewKimi() *Kimi

NewKimi 创建 Kimi 适配器。

func (*Kimi) Capabilities

func (k *Kimi) Capabilities() Capability

Capabilities 支持 Model/Session(--model / --session);沙箱/轮数/工具白名单无对应参数 (非交互模式本身即全自主——传 Sandbox 会被拒绝而非裸跑)。

func (*Kimi) Name

func (k *Kimi) Name() string

func (*Kimi) Run

func (k *Kimi) Run(ctx context.Context, req RunRequest) (*RunResult, error)

Run 执行 Kimi print 模式任务。

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 NewMcode

func NewMcode() *Mcode

NewMcode 创建 MiniMax Code 适配器(注册名 minimax)。

func (*Mcode) Capabilities

func (m *Mcode) Capabilities() Capability

Capabilities 支持 Model/Session/MaxTurns(--model / --session / --max-steps); 沙箱与工具白名单无对应参数面(见类型注释 ⚠ 条目)。

func (*Mcode) Name

func (a *Mcode) Name() string

Name Agent 接口的 Name 实现(适配器嵌入即得)。

func (*Mcode) Run

func (m *Mcode) Run(ctx context.Context, req RunRequest) (*RunResult, error)

Run 执行 mcode exec 任务。

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 NewMimo

func NewMimo() *Mimo

NewMimo 创建 MiMo 适配器。

func (*Mimo) Capabilities

func (m *Mimo) Capabilities() Capability

Capabilities 支持 Model/Session(-m / -s);沙箱/轮数/工具白名单无对应参数。

func (*Mimo) Name

func (a *Mimo) Name() string

Name Agent 接口的 Name 实现(适配器嵌入即得)。

func (*Mimo) Run

func (m *Mimo) Run(ctx context.Context, req RunRequest) (*RunResult, error)

Run 执行 mimo run 任务。

type OpenCode

type OpenCode struct {
	Bin string // 默认 "opencode"
}

OpenCode opencode 适配器(`opencode run --json`)。

func NewOpenCode

func NewOpenCode() *OpenCode

NewOpenCode 创建 opencode 适配器。

func (*OpenCode) Capabilities

func (c *OpenCode) Capabilities() Capability

Capabilities 支持 Model/Session(-m / --session);沙箱/轮数/工具白名单无对应参数。

func (*OpenCode) Name

func (c *OpenCode) Name() string

func (*OpenCode) Run

func (c *OpenCode) Run(ctx context.Context, req RunRequest) (*RunResult, error)

Run 执行 opencode run 任务(--session 续聊、-m provider/model)。

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 NewPi

func NewPi() *Pi

NewPi 创建 Pi 适配器。

func (*Pi) Capabilities

func (p *Pi) Capabilities() Capability

Capabilities 支持 Model(--model)与 Session(--session-id 精确续聊, 缺省则 --no-session 一次性);沙箱/轮数/工具白名单无对应参数。

func (*Pi) Name

func (a *Pi) Name() string

Name Agent 接口的 Name 实现(适配器嵌入即得)。

func (*Pi) Run

func (p *Pi) Run(ctx context.Context, req RunRequest) (*RunResult, error)

Run 执行 pi(--mode json 事件流解析)。

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 家)。

func (*Registry) AsTool

func (r *Registry) AsTool() tool.BaseTool

AsTool 把注册表包成 eino 工具(run_coding_agent),供 ReAct agent 自主调用。 与 rag.KnowledgeService.AsTool 同范式。 InferTool 失败(模板/schema 问题,属配置期错误)返回 nil——调用方不得把返回值 不判空就挂进工具表。

func (*Registry) Get

func (r *Registry) Get(name string) (Agent, bool)

Get 按名查找。

func (*Registry) Names

func (r *Registry) Names() []string

Names 返回全部注册名(注册序)。

func (*Registry) Register

func (r *Registry) Register(a Agent)

Register 注册 agent(重名覆盖)。

func (*Registry) Run

func (r *Registry) Run(ctx context.Context, name string, req RunRequest) (*RunResult, error)

Run 按名执行。入口先做能力校验:请求中 agent 声明不支持的非零字段 → fail-fast 报错(请求了即须兑现,拒绝静默降级——直连 Agent.Run 的调用方 应自行经 Capabilities 判断)。执行结束后发 RunEvent。

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
	// Interrupted 执行被中断(超时/调用方取消/被信号杀死,tools#46):
	// Text 只是**部分输出**、任务未完成,且返回值同时带非 nil error——
	// kimi 形态(无协议终态事件)下部分文本不得代理终态。nil error 时恒为
	// false;「正常完成但退出码非零」(终态优先路径)不算中断。
	Interrupted bool
}

RunResult 统一运行结果。

type Usage

type Usage struct {
	InputTokens  int
	OutputTokens int
	CostUSD      float64
}

Usage token 用量与成本(agent 输出缺失时为 0)。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL