Files
codex/codex-rs/tui/src/ide_context.rs
T
Benjamin Carlsson 78d4c7c7fa Extract shared TUI user prompt helpers from IDE context (#55597)
Move context prefixing and request extraction into `user_prompt`, and update
IDE context injection, thread routing, thread titles, transcript export, and
user message rendering to use the shared helpers. Preserve the request
delimiter, text element byte offsets, and input ordering.

Move the existing last-delimiter extraction test alongside the shared helpers.

GitOrigin-RevId: 3ee350506a536a6dba9575e8311188bc92fed584
2026-10-20 15:15:24 +00:00

117 lines
3.2 KiB
Rust

//! IDE context data model and public helpers for TUI `/ide` support.
mod ipc;
mod prompt;
#[cfg(windows)]
mod windows_pipe;
pub(crate) use ipc::fetch_ide_context;
pub(crate) use prompt::apply_ide_context_to_user_input;
pub(crate) use prompt::has_prompt_context;
use serde::Deserialize;
#[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub(crate) struct IdeContext {
active_file: Option<ActiveFile>,
#[serde(default)]
open_tabs: Vec<FileDescriptor>,
}
#[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
struct ActiveFile {
#[serde(flatten)]
descriptor: FileDescriptor,
selection: Range,
#[serde(default)]
active_selection_content: String,
#[serde(default)]
selections: Vec<Range>,
}
#[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
struct FileDescriptor {
label: String,
path: String,
}
#[derive(Debug, Clone, Deserialize, PartialEq)]
struct Range {
start: Position,
end: Position,
}
#[derive(Debug, Clone, Deserialize, PartialEq)]
struct Position {
line: u32,
character: u32,
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
use serde_json::json;
#[test]
fn deserializes_existing_ide_context_shape() {
let value = json!({
"activeFile": {
"label": "lib.rs",
"path": "src/lib.rs",
"fsPath": "/repo/src/lib.rs",
"selection": {
"start": { "line": 1, "character": 2 },
"end": { "line": 3, "character": 4 }
},
"activeSelectionContent": "selected",
"selections": []
},
"openTabs": [
{
"label": "main.rs",
"path": "src/main.rs",
"fsPath": "/repo/src/main.rs",
"startLine": 2,
"endLine": 10
}
],
"processEnv": {
"path": "/usr/bin"
}
});
let context: IdeContext = serde_json::from_value(value).expect("deserialize ide context");
assert_eq!(
context,
IdeContext {
active_file: Some(ActiveFile {
descriptor: FileDescriptor {
label: "lib.rs".to_string(),
path: "src/lib.rs".to_string(),
},
selection: Range {
start: Position {
line: 1,
character: 2,
},
end: Position {
line: 3,
character: 4,
},
},
active_selection_content: "selected".to_string(),
selections: Vec::new(),
}),
open_tabs: vec![FileDescriptor {
label: "main.rs".to_string(),
path: "src/main.rs".to_string(),
}],
}
);
}
}