codex_runtime/runtime/
approvals.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use crate::runtime::rpc_contract::methods;
5
6#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
7#[serde(rename_all = "camelCase")]
8pub struct ServerRequest {
9 pub approval_id: String,
10 pub method: String,
11 pub params: Value,
12}
13
14#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
15#[serde(rename_all = "camelCase")]
16pub struct PendingServerRequest {
17 pub approval_id: String,
18 pub deadline_unix_ms: i64,
19 pub method: String,
20 pub params: Value,
21}
22
23#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
24#[serde(rename_all = "camelCase")]
25pub enum TimeoutAction {
26 Decline,
27 Cancel,
28 Error,
29}
30
31#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
32#[serde(rename_all = "camelCase")]
33pub struct ServerRequestConfig {
34 pub default_timeout_ms: u64,
35 pub on_timeout: TimeoutAction,
36 pub auto_decline_unknown: bool,
37}
38
39#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
40#[serde(rename_all = "camelCase")]
41pub enum ServerRequestRoute {
42 Queue,
43 AutoDecline,
44}
45
46impl Default for ServerRequestConfig {
47 fn default() -> Self {
48 Self {
49 default_timeout_ms: 30_000,
50 on_timeout: TimeoutAction::Decline,
51 auto_decline_unknown: true,
52 }
53 }
54}
55
56pub fn is_known_server_request_method(method: &str) -> bool {
59 matches!(
60 method,
61 methods::ITEM_COMMAND_EXECUTION_REQUEST_APPROVAL
62 | methods::ITEM_FILE_CHANGE_REQUEST_APPROVAL
63 | methods::ITEM_TOOL_REQUEST_USER_INPUT
64 | methods::ITEM_TOOL_CALL
65 | methods::ACCOUNT_CHATGPT_AUTH_TOKENS_REFRESH
66 )
67}
68
69pub fn route_server_request(method: &str, auto_decline_unknown: bool) -> ServerRequestRoute {
72 if auto_decline_unknown && !is_known_server_request_method(method) {
73 ServerRequestRoute::AutoDecline
74 } else {
75 ServerRequestRoute::Queue
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn routes_known_method_to_queue() {
85 let route = route_server_request("item/fileChange/requestApproval", true);
86 assert_eq!(route, ServerRequestRoute::Queue);
87 }
88
89 #[test]
90 fn routes_known_dynamic_tool_call_method_to_queue() {
91 let route = route_server_request("item/tool/call", true);
92 assert_eq!(route, ServerRequestRoute::Queue);
93 }
94
95 #[test]
96 fn routes_known_auth_refresh_method_to_queue() {
97 let route = route_server_request("account/chatgptAuthTokens/refresh", true);
98 assert_eq!(route, ServerRequestRoute::Queue);
99 }
100
101 #[test]
102 fn routes_unknown_method_to_auto_decline_when_enabled() {
103 let route = route_server_request("item/unknown/requestApproval", true);
104 assert_eq!(route, ServerRequestRoute::AutoDecline);
105 }
106
107 #[test]
108 fn routes_unknown_method_to_queue_when_auto_decline_disabled() {
109 let route = route_server_request("item/unknown/requestApproval", false);
110 assert_eq!(route, ServerRequestRoute::Queue);
111 }
112}