Skip to main content

codex_runtime/runtime/api/
mod.rs

1use crate::runtime::core::Runtime;
2use crate::runtime::errors::RpcError;
3use crate::runtime::rpc_contract::methods;
4use crate::runtime::turn_output::parse_thread_id;
5
6mod attachment_validation;
7mod command_exec_api;
8mod flow;
9mod models;
10mod prompt_run;
11mod thread_api;
12pub(crate) mod tool_use_hooks;
13mod turn_error;
14mod wire;
15
16use std::path::PathBuf;
17
18#[cfg(test)]
19use attachment_validation::validate_prompt_attachments;
20#[cfg(test)]
21use wire::build_prompt_inputs;
22#[cfg(test)]
23use wire::{input_item_to_wire, turn_start_params_to_wire};
24use wire::{thread_start_params_to_wire, validate_thread_start_security};
25
26fn resolve_attachment_path(cwd: &str, path: &str) -> PathBuf {
27    let path = PathBuf::from(path);
28    if path.is_absolute() {
29        path
30    } else {
31        PathBuf::from(cwd).join(path)
32    }
33}
34
35mod types;
36
37pub use models::{
38    PromptRunError, PromptRunParams, PromptRunResult, PromptTurnFailure, PromptTurnTerminalState,
39};
40pub(crate) use types::{
41    normalize_sandbox_mode_alias, sandbox_mode_to_wire_value, sandbox_policy_to_wire_value,
42    summarize_sandbox_policy, summarize_sandbox_policy_wire_value,
43};
44pub use types::{
45    ApprovalPolicy, ByteRange, CommandExecOutputDeltaNotification, CommandExecOutputStream,
46    CommandExecParams, CommandExecResizeParams, CommandExecResizeResponse, CommandExecResponse,
47    CommandExecTerminalSize, CommandExecTerminateParams, CommandExecTerminateResponse,
48    CommandExecWriteParams, CommandExecWriteResponse, ExternalNetworkAccess, InputItem,
49    Personality, PromptAttachment, ReasoningEffort, SandboxPolicy, SandboxPreset, ServiceTier,
50    SkillDependencies, SkillErrorInfo, SkillInterface, SkillMetadata, SkillScope,
51    SkillToolDependency, SkillsListEntry, SkillsListExtraRootsForCwd, SkillsListParams,
52    SkillsListResponse, TextElement, ThreadAgentMessageItemView, ThreadCommandExecutionItemView,
53    ThreadHandle, ThreadId, ThreadItemPayloadView, ThreadItemType, ThreadItemView,
54    ThreadListParams, ThreadListResponse, ThreadListSortKey, ThreadLoadedListParams,
55    ThreadLoadedListResponse, ThreadReadParams, ThreadReadResponse, ThreadRollbackParams,
56    ThreadRollbackResponse, ThreadStartParams, ThreadTurnErrorView, ThreadTurnStatus,
57    ThreadTurnView, ThreadView, TurnHandle, TurnId, TurnStartParams, DEFAULT_REASONING_EFFORT,
58};
59
60impl Runtime {
61    pub(crate) async fn thread_start_raw(
62        &self,
63        mut p: ThreadStartParams,
64    ) -> Result<ThreadHandle, RpcError> {
65        p = escalate_approval_if_tool_hooks(self, p);
66        validate_thread_start_security(&p)?;
67        let response = self
68            .call_validated(methods::THREAD_START, thread_start_params_to_wire(&p))
69            .await?;
70        let thread_id = parse_thread_id(&response).ok_or_else(|| {
71            RpcError::InvalidRequest(format!(
72                "thread/start missing thread id in result: {response}"
73            ))
74        })?;
75        Ok(ThreadHandle {
76            thread_id,
77            runtime: self.clone(),
78        })
79    }
80}
81
82/// If the runtime has pre-tool-use hooks, escalate approval policy from Never → Untrusted
83/// so that codex sends approval requests that the hook loop can intercept.
84/// Pure transform; no I/O. Allocation: none. Complexity: O(1).
85fn escalate_approval_if_tool_hooks(
86    runtime: &Runtime,
87    mut p: ThreadStartParams,
88) -> ThreadStartParams {
89    if runtime.has_pre_tool_use_hooks()
90        && matches!(p.approval_policy, None | Some(ApprovalPolicy::Never))
91    {
92        p.approval_policy = Some(ApprovalPolicy::Untrusted);
93    }
94    p
95}
96
97#[cfg(test)]
98mod tests;