未绑定执行器时的交互拒绝按真实结果留痕

- 未绑定宿主执行器的交互兜底不再一律记成审批拒绝
- 新增稳定键 agent.direct_codex.interaction.no_adapter,字段为 method / outcome / request_id
- outcome 区分 decline / empty-permissions / unsupported-method,权限申请与未知方法不再被误标为 decline
- 同步更新 shared-memory 决策记录里的日志键口径
This commit is contained in:
2026-10-01 15:38:05 +08:00
parent ea33e8c166
commit c34e45e0c4
2 changed files with 14 additions and 4 deletions
@@ -41,11 +41,21 @@ pub(super) fn validate_approval_version(version: &str) -> Result<(), String> {
}
}
/// 未绑定宿主执行器时的交互兜底:一律拒绝,并把**真实结果形状**留痕。
///
/// 这是「回合没接单 / 适配器已释放」的唯一表现,不留痕线上就只剩一个没有原因的拒绝。
/// 不同交互方法的拒绝形状并不相同(审批是 `decline`,权限申请是空授权,未知方法直接报错),
/// 所以日志按 `outcome` 分类,不能一律记成审批拒绝。
pub(super) fn denied_response(id: u64, method: &str) -> Value {
// 没绑定宿主执行器时一律拒绝。这是「回合没接单 / 适配器已释放」的唯一表现,
// 不留痕线上就只剩一个没有原因的 decline。
let outcome = match method {
"item/commandExecution/requestApproval"
| "item/fileChange/requestApproval"
| "mcpServer/elicitation/request" => "decline",
"item/permissions/requestApproval" => "empty-permissions",
_ => "unsupported-method",
};
app_log!(
"agent.direct_codex.approval.denied reason=no-bound-host-execution-adapter request_id={id} method={method}"
"agent.direct_codex.interaction.no_adapter method={method} outcome={outcome} request_id={id}"
);
denied(id, method)
}