mirror of
https://github.com/openai/codex.git
synced 2026-09-13 11:47:17 +00:00
## Why Memory read telemetry currently reconstructs the executable shell command after a tool call finishes. That duplicates shell, login-policy, and cwd resolution owned by the tool handlers, and can diverge from the environment-specific command that unified exec actually ran. ## What changed - Expose the existing restricted shell-script parser directly for raw script text. - Parse `shell_command` and `exec_command` input into plain command argv before classifying memory reads. - Preserve all-or-nothing safe-command validation for multi-command scripts. - Remove cwd resolution, shell selection, and the unnecessary async boundary from memory read metric emission. ## Testing - `just test -p codex-shell-command` - `cargo check -p codex-core`
65 lines
2.1 KiB
Rust
65 lines
2.1 KiB
Rust
use codex_protocol::parse_command::ParsedCommand;
|
|
use codex_shell_command::bash::parse_shell_script_into_commands;
|
|
use codex_shell_command::is_safe_command::is_known_safe_command;
|
|
use codex_shell_command::parse_command::parse_shell_script;
|
|
|
|
pub use crate::metrics::MEMORIES_USAGE_METRIC;
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub enum MemoriesUsageKind {
|
|
MemoryMd,
|
|
MemorySummary,
|
|
RawMemories,
|
|
RolloutSummaries,
|
|
Skills,
|
|
}
|
|
|
|
impl MemoriesUsageKind {
|
|
pub fn as_tag(self) -> &'static str {
|
|
match self {
|
|
Self::MemoryMd => "memory_md",
|
|
Self::MemorySummary => "memory_summary",
|
|
Self::RawMemories => "raw_memories",
|
|
Self::RolloutSummaries => "rollout_summaries",
|
|
Self::Skills => "skills",
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn memories_usage_kinds_from_command(command: &str) -> Vec<MemoriesUsageKind> {
|
|
let Some(commands) = parse_shell_script_into_commands(command) else {
|
|
return Vec::new();
|
|
};
|
|
if !commands
|
|
.iter()
|
|
.all(|command| is_known_safe_command(command))
|
|
{
|
|
return Vec::new();
|
|
}
|
|
|
|
parse_shell_script(command)
|
|
.into_iter()
|
|
.filter_map(|command| match command {
|
|
ParsedCommand::Read { path, .. } => get_memory_kind(path.display().to_string()),
|
|
ParsedCommand::Search { path, .. } => path.and_then(get_memory_kind),
|
|
ParsedCommand::ListFiles { .. } | ParsedCommand::Unknown { .. } => None,
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn get_memory_kind(path: String) -> Option<MemoriesUsageKind> {
|
|
if path.contains("memories/MEMORY.md") {
|
|
Some(MemoriesUsageKind::MemoryMd)
|
|
} else if path.contains("memories/memory_summary.md") {
|
|
Some(MemoriesUsageKind::MemorySummary)
|
|
} else if path.contains("memories/raw_memories.md") {
|
|
Some(MemoriesUsageKind::RawMemories)
|
|
} else if path.contains("memories/rollout_summaries/") {
|
|
Some(MemoriesUsageKind::RolloutSummaries)
|
|
} else if path.contains("memories/skills/") {
|
|
Some(MemoriesUsageKind::Skills)
|
|
} else {
|
|
None
|
|
}
|
|
}
|