Expose instruction sources (AGENTS.md) via app server (#17506)

Addresses #17498

Problem: The TUI derived /status instruction source paths from the local
client environment, which could show stale <none> output or incorrect
paths when connected to a remote app server.

Solution: Add an app-server v2 instructionSources snapshot to thread
start/resume/fork responses, default it to an empty list when older
servers omit it, and render TUI /status from that server-provided
session data.

Additional context: The app-server field is intentionally named
instructionSources rather than AGENTS.md-specific terminology because
the loaded instruction sources can include global instructions, project
AGENTS.md files, AGENTS.override.md, user-defined instruction files, and
future dynamic sources.
This commit is contained in:
Eric Traut authored and GitHub committed 2026-04-12 15:50:12 -07:00
1 parent 470510174b
commit 46ab9974dc
23 files changed
+302 -69

No files matched your search

@@ -275,6 +275,7 @@ pub(super) async fn make_chatwidget_manual(
feedback: codex_feedback::CodexFeedback::new(),
current_rollout_path: None,
current_cwd: None,
instruction_source_paths: Vec::new(),
session_network_proxy: None,
status_line_invalid_items_warned: Arc::new(AtomicBool::new(false)),
terminal_title_invalid_items_warned: Arc::new(AtomicBool::new(false)),
@@ -76,6 +76,29 @@ async fn status_command_renders_immediately_without_rate_limit_refresh() {
);
}
#[tokio::test]
async fn status_command_renders_instruction_sources_from_thread_session() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
chat.instruction_source_paths = vec![chat.config.cwd.join("AGENTS.md").to_path_buf()];
chat.dispatch_command(SlashCommand::Status);
let rendered = match rx.try_recv() {
Ok(AppEvent::InsertHistoryCell(cell)) => {
lines_to_single_string(&cell.display_lines(/*width*/ 80))
}
other => panic!("expected status output, got {other:?}"),
};
assert!(
rendered.contains("Agents.md"),
"expected /status to render app-server instruction sources, got: {rendered}"
);
assert!(
!rendered.contains("Agents.md <none>"),
"expected /status to avoid stale <none> when app-server provided instruction sources, got: {rendered}"
);
}
#[tokio::test]
async fn status_command_overlapping_refreshes_update_matching_cells_only() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;