hive-runtime: log the acp permission decision at the point it is made
This commit is contained in:
parent
90c7600c8a
commit
c433bdef92
1 changed files with 28 additions and 2 deletions
|
|
@ -252,15 +252,17 @@ pub(super) fn permission_outcome(
|
|||
let tool_call = params.get("toolCall");
|
||||
let field = |k: &str| tool_call.and_then(|t| t.get(k)).and_then(Value::as_str);
|
||||
let kind = field("kind").unwrap_or("other");
|
||||
let title = field("title");
|
||||
let ask = PermissionAsk {
|
||||
kind,
|
||||
// MCP tool calls are kind `other`; a title alone must not lift another
|
||||
// kind (`execute`, `fetch`) into one.
|
||||
mcp_server: (kind == "other")
|
||||
.then(|| field("title").and_then(|title| mcp_server_of(title, servers)))
|
||||
.then(|| title.and_then(|title| mcp_server_of(title, servers)))
|
||||
.flatten(),
|
||||
};
|
||||
let wanted = if permit(&ask) {
|
||||
let permitted = permit(&ask);
|
||||
let wanted = if permitted {
|
||||
["allow_once", "allow_always"]
|
||||
} else {
|
||||
["reject_once", "reject_always"]
|
||||
|
|
@ -275,6 +277,30 @@ pub(super) fn permission_outcome(
|
|||
.find(|o| o.get("kind").and_then(Value::as_str) == Some(want))
|
||||
.and_then(|o| o.get("optionId"))
|
||||
});
|
||||
// Log what the agent was actually told, not just the policy's
|
||||
// pre-resolution answer: `permit` saying yes doesn't mean the agent
|
||||
// offered a matching `allow_*` option, and that silent-cancel case is
|
||||
// exactly the shape a reporter sees as "tool call refused, nothing
|
||||
// actionable in the logs" — the earlier version of this log line
|
||||
// reported `permitted` and would have called that case "allowed".
|
||||
// `title` is only logged for `kind == "other"` (it identifies the MCP
|
||||
// tool/server) — an `execute` title can carry a command line and must
|
||||
// not land in the journal at this level.
|
||||
let other_title = (kind == "other").then_some(title).flatten();
|
||||
match chosen {
|
||||
Some(option) if permitted => {
|
||||
tracing::debug!(kind, mcp_server = ?ask.mcp_server, option = %option, "ACP permission request allowed");
|
||||
}
|
||||
Some(option) => {
|
||||
tracing::info!(kind, mcp_server = ?ask.mcp_server, title = other_title, option = %option, "ACP permission request denied by policy");
|
||||
}
|
||||
None => {
|
||||
// An anomaly, not a policy decision: the agent offered no
|
||||
// option matching what the policy wanted, so the request is
|
||||
// cancelled regardless of `permitted`.
|
||||
tracing::warn!(kind, mcp_server = ?ask.mcp_server, title = other_title, permitted, "ACP permission request cancelled — agent offered no matching option");
|
||||
}
|
||||
}
|
||||
match chosen {
|
||||
Some(option) => json!({ "outcome": { "outcome": "selected", "optionId": option } }),
|
||||
None => json!({ "outcome": { "outcome": "cancelled" } }),
|
||||
|
|
|
|||
Loading…
Reference in a new issue