story-kit: merge 130_bug_permission_approval_returns_wrong_format_tools_fail_after_user_approves
This commit is contained in:
@@ -1610,9 +1610,13 @@ async fn tool_prompt_permission(args: &Value, ctx: &AppContext) -> Result<String
|
|||||||
.map_err(|_| "Permission response channel closed unexpectedly".to_string())?;
|
.map_err(|_| "Permission response channel closed unexpectedly".to_string())?;
|
||||||
|
|
||||||
if approved {
|
if approved {
|
||||||
Ok(format!("Permission granted for '{tool_name}'"))
|
Ok(json!({"behavior": "allow"}).to_string())
|
||||||
} else {
|
} else {
|
||||||
Err(format!("User denied permission for '{tool_name}'"))
|
Ok(json!({
|
||||||
|
"behavior": "deny",
|
||||||
|
"message": format!("User denied permission for '{tool_name}'")
|
||||||
|
})
|
||||||
|
.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3016,4 +3020,55 @@ mod tests {
|
|||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert!(result.unwrap_err().contains("story_id"));
|
assert!(result.unwrap_err().contains("story_id"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn tool_prompt_permission_approved_returns_allow_json() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = test_ctx(tmp.path());
|
||||||
|
|
||||||
|
// Spawn a task that immediately sends approval through the channel.
|
||||||
|
let perm_rx = ctx.perm_rx.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut rx = perm_rx.lock().await;
|
||||||
|
if let Some(forward) = rx.recv().await {
|
||||||
|
let _ = forward.response_tx.send(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = tool_prompt_permission(
|
||||||
|
&json!({"tool_name": "Bash", "input": {"command": "echo hello"}}),
|
||||||
|
&ctx,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("should succeed on approval");
|
||||||
|
|
||||||
|
let parsed: Value = serde_json::from_str(&result).expect("result should be valid JSON");
|
||||||
|
assert_eq!(parsed["behavior"], "allow", "approved must return behavior:allow");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn tool_prompt_permission_denied_returns_deny_json() {
|
||||||
|
let tmp = tempfile::tempdir().unwrap();
|
||||||
|
let ctx = test_ctx(tmp.path());
|
||||||
|
|
||||||
|
// Spawn a task that immediately sends denial through the channel.
|
||||||
|
let perm_rx = ctx.perm_rx.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut rx = perm_rx.lock().await;
|
||||||
|
if let Some(forward) = rx.recv().await {
|
||||||
|
let _ = forward.response_tx.send(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = tool_prompt_permission(
|
||||||
|
&json!({"tool_name": "Write", "input": {}}),
|
||||||
|
&ctx,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("denial must return Ok, not Err");
|
||||||
|
|
||||||
|
let parsed: Value = serde_json::from_str(&result).expect("result should be valid JSON");
|
||||||
|
assert_eq!(parsed["behavior"], "deny", "denied must return behavior:deny");
|
||||||
|
assert!(parsed["message"].is_string(), "deny must include a message");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user