File size: 5,006 Bytes
52a9af3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | mod approvals;
pub(crate) mod call_trace;
pub(crate) mod code_mode;
pub(crate) mod context;
mod control_tool_analytics;
pub(crate) mod events;
mod executed_tool_calls;
pub(crate) mod handlers;
pub(crate) mod hook_names;
pub(crate) mod hosted_spec;
pub(crate) mod lifecycle;
pub(crate) mod network_approval;
pub(crate) mod orchestrator;
pub(crate) mod parallel;
pub(crate) mod registry;
pub(crate) mod router;
pub(crate) mod runtimes;
pub(crate) mod sandboxing;
pub(crate) mod spec_plan;
pub(crate) mod tool_dispatch_trace;
mod tool_namespaces_info;
use std::borrow::Cow;
use crate::session::turn_context::TurnContext;
pub(crate) use approvals::ApprovalContext;
use codex_features::Feature;
use codex_protocol::exec_output::ExecToolCallOutput;
use codex_protocol::openai_models::ModelInfo;
use codex_protocol::openai_models::ToolMode;
use codex_tools::ToolName;
use codex_utils_output_truncation::TruncationPolicy;
use codex_utils_output_truncation::formatted_truncate_text;
use codex_utils_output_truncation::truncate_text;
pub(crate) use executed_tool_calls::ExecutedToolCalls;
pub use router::ToolRouter;
/// Legacy boundaries such as hook payloads, telemetry tags, and Responses tool
/// names still require a single flattened string. Keep comparisons and sorting
/// on `ToolName` itself; use this only when crossing those boundaries.
pub(crate) fn flat_tool_name(tool_name: &ToolName) -> Cow<'_, str> {
if tool_name.is_default_namespace() {
return Cow::Borrowed(tool_name.name.as_str());
}
match tool_name.namespace.as_deref() {
Some(namespace) => {
let mut name = String::with_capacity(namespace.len() + tool_name.name.len());
name.push_str(namespace);
name.push_str(&tool_name.name);
Cow::Owned(name)
}
None => Cow::Borrowed(tool_name.name.as_str()),
}
}
pub(crate) fn tool_user_shell_type(
user_shell: &crate::shell::Shell,
) -> codex_tools::ToolUserShellType {
match user_shell.shell_type {
crate::shell::ShellType::Zsh => codex_tools::ToolUserShellType::Zsh,
crate::shell::ShellType::Bash => codex_tools::ToolUserShellType::Bash,
crate::shell::ShellType::PowerShell => codex_tools::ToolUserShellType::PowerShell,
crate::shell::ShellType::Sh => codex_tools::ToolUserShellType::Sh,
crate::shell::ShellType::Cmd => codex_tools::ToolUserShellType::Cmd,
}
}
pub(crate) fn requested_tool_mode(turn_context: &TurnContext, model_info: &ModelInfo) -> ToolMode {
model_info.tool_mode.unwrap_or_else(|| {
if turn_context.config.features.enabled(Feature::CodeModeOnly) {
ToolMode::CodeModeOnly
} else if turn_context.config.features.enabled(Feature::CodeMode) {
ToolMode::CodeMode
} else {
ToolMode::Direct
}
})
}
pub(crate) fn effective_tool_mode(turn_context: &TurnContext, model_info: &ModelInfo) -> ToolMode {
let requested_tool_mode = requested_tool_mode(turn_context, model_info);
if !turn_context.code_mode_available
&& requested_tool_mode == ToolMode::CodeMode
&& !turn_context.config.code_mode.disable_in_process_fallback
{
ToolMode::Direct
} else {
requested_tool_mode
}
}
/// Format the combined exec output for sending back to the model.
/// Includes exit code and duration metadata; truncates large bodies safely.
pub fn format_exec_output_for_model(
exec_output: &ExecToolCallOutput,
truncation_policy: TruncationPolicy,
) -> String {
// round to 1 decimal place
let duration_seconds = ((exec_output.duration.as_secs_f32()) * 10.0).round() / 10.0;
let content = build_content_with_timeout(exec_output);
let total_lines = content.lines().count();
let formatted_output = truncate_text(&content, truncation_policy);
let mut sections = Vec::new();
sections.push(format!("Exit code: {}", exec_output.exit_code));
sections.push(format!("Wall time: {duration_seconds} seconds"));
if total_lines != formatted_output.lines().count() {
sections.push(format!("Total output lines: {total_lines}"));
}
sections.push("Output:".to_string());
sections.push(formatted_output);
sections.join("\n")
}
pub fn format_exec_output_str(
exec_output: &ExecToolCallOutput,
truncation_policy: TruncationPolicy,
) -> String {
let content = build_content_with_timeout(exec_output);
// Truncate for model consumption before serialization.
formatted_truncate_text(&content, truncation_policy)
}
/// Extracts exec output content and prepends a timeout message if the command timed out.
fn build_content_with_timeout(exec_output: &ExecToolCallOutput) -> String {
if exec_output.timed_out {
format!(
"command timed out after {} milliseconds\n{}",
exec_output.duration.as_millis(),
exec_output.aggregated_output.text
)
} else {
exec_output.aggregated_output.text.clone()
}
}
|