package exec import ( "context" "time" ) type Request struct { WorkDir string `json:"work_dir"` Prompt string `json:"prompt"` Instructions string `json:"instructions"` Targets []string `json:"targets"` Timeout time.Duration `json:"timeout"` // ToolProfile is workspace (default, document tools) or reasoning (no tools). ToolProfile string `json:"tool_profile,omitempty"` // OnEvent 可选过程事件回调(nil = 调用方不需要过程,后端行为与现状完全一致)。 // 实现方必须保证:回调在 Execute 返回前完成(同步调用或等待收尾),无泄漏 goroutine; // 回调内不得阻塞(消费方自行节流/异步入队)。 OnEvent func(ev ProcessEvent) `json:"-"` // ---- v0.2 能力字段(全部可选;零值 = 既有行为,向后兼容) ---- // Model 覆盖本请求使用的模型(后端构造时的默认模型仍兜底)。 Model string `json:"model,omitempty"` // ToolAllowlist 收窄可见工具集;出现后端未注册的工具名时 fail-closed。 ToolAllowlist []string `json:"tool_allowlist,omitempty"` // Skills 声明本次执行需要加载的技能(内核在系统提示中列出并由 load_skill 按需展开)。 Skills []string `json:"skills,omitempty"` // Budget 单次步骤执行的共享预算;步骤重试应传入剩余额度,不得各自另起一份。 Budget *Budget `json:"budget,omitempty"` // SessionScope / ExecutionID 只用于日志与过程事件贯穿,不参与控制流。 SessionScope string `json:"session_scope,omitempty"` ExecutionID string `json:"execution_id,omitempty"` // Env 是组合根批准后注入执行类工具(run_command 等)的白名单环境变量。 // 后端不得把自身持有的密钥并入其中。 Env map[string]string `json:"env,omitempty"` } // Budget 是一次步骤执行的共享预算(agent-execution 标准:重试层各有职责, // 共享总预算与截止时间,避免传输、步骤与主循环次数相乘)。 // 全部字段可选;零值字段不设限。 type Budget struct { MaxPromptTokens int `json:"max_prompt_tokens,omitempty"` MaxCompletionTokens int `json:"max_completion_tokens,omitempty"` MaxToolCalls int `json:"max_tool_calls,omitempty"` // Deadline 绝对截止时刻;与 Request.Timeout 先到者生效。 Deadline time.Time `json:"deadline,omitempty"` } // ProcessEvent 对 agentx 事件与远程 runner NDJSON 过程帧的统一投影, // 供小队过程流式展示消费(见 .doc/system-design/2026-09-28-agent-process-streaming-and-subagent-view-design.md)。 type ProcessEvent struct { Type string // text_delta | reasoning_delta | tool_call_delta | tool_execution_start | tool_execution_end | message_end | ... Text string // delta 文本(Type 为 *_delta 时) Tool string // 工具名(tool_* 时) Detail string // 工具参数/结果摘要(tool_execution_* 时) // CallID 是提供方 tool-call id;在 tool_call_delta / tool_execution_start / // tool_execution_end 时填写。零值 = 旧行为(消费方仍可按 Tool 名启发式配对)。 CallID string `json:"call_id,omitempty"` // Status 在 tool_execution_end 时填写:ok | error | denied | canceled。 // 空串 = legacy/unknown,不得臆造。 Status string `json:"status,omitempty"` // ErrorReason 在 Status 为 error/denied/canceled 时携带真实失败文本。 ErrorReason string `json:"error_reason,omitempty"` // PromptTokens / CompletionTokens 在 Type=usage 时填写。 PromptTokens int CompletionTokens int // 以下在 Type=usage 或 message_end 时填写(N3 WP6:上一请求与缓存命中拆分)。 LastPromptTokens int LastCompletionTokens int CacheReadTokens int CacheWriteTokens int } const ( ToolProfileWorkspace = "workspace" ToolProfileReasoning = "reasoning" ) type Result struct { Success bool `json:"success"` Patches map[string][]byte `json:"patches"` Logs string `json:"logs"` ErrorReason string `json:"error_reason"` // Retryable marks a provider-transient failure that may receive a // fresh step invocation. Permanent missing deliverables stay false. // Canceled and Unknown are never retryable; do not set Retryable with them. Retryable bool `json:"retryable,omitempty"` // PromptTokens and CompletionTokens are set by pi-native when the provider reports usage. PromptTokens int `json:"prompt_tokens,omitempty"` CompletionTokens int `json:"completion_tokens,omitempty"` // ---- terminal fidelity (optional; zero-value = legacy behavior) ---- // Canceled marks an aborted/canceled run. Distinct from Retryable: // a canceled action must not be auto-retried (Retryable must stay false). Canceled bool `json:"canceled,omitempty"` // Unknown marks that execution reached the provider/tool stage and the // terminal outcome could not be determined (side effects may exist). // Unknown is not a retryable failure. Unknown bool `json:"unknown,omitempty"` // SideEffects qualifies external side-effect risk for retry/fallback. // Empty means SideEffectPossible — the safe legacy reading. Set // SideEffectNone only when no tool dispatch (or equivalent) is provable. SideEffects SideEffects `json:"side_effects,omitempty"` } // EffectiveSideEffects returns the side-effect qualifier for retry decisions. // An empty SideEffects value means SideEffectPossible (backward compatible). func (r *Result) EffectiveSideEffects() SideEffects { if r == nil || r.SideEffects == "" { return SideEffectPossible } return r.SideEffects } type Backend interface { Name() string Execute(ctx context.Context, req Request) (*Result, error) }