Files
codex/codex-rs/connectors/src/plugin_config_tests.rs
jif 4e0f863df3 Add a connector declaration snapshot (#29851)
## Why

Connector declarations currently enter Codex through broad plugin
capability summaries, then MCP setup, turn tooling, and `app/list` each
reconstruct the same information. That makes executor-selected
connectors difficult to add without coupling connector behavior to the
host plugin loader.

This PR introduces a small connector-owned value that later stack layers
can populate before thread startup.

## What changed

- Move the pure app-declaration parser into `codex-connectors`,
preserving declaration order and category cleanup while leaving
host-side validation and deduplication unchanged.
- Add an immutable `ConnectorSnapshot` with ordered connector IDs and
plugin display-name provenance.
- Adapt the existing local-plugin capability summaries into that
snapshot at current consumer boundaries.
- Use the snapshot for MCP tool provenance, turn connector inventory,
and `app/list`.
- Keep the crate API narrow: no test-only snapshot accessors are
exposed.

The externally visible behavior is unchanged. Connector tools still come
from the orchestrator-owned `/ps/mcp` server, and local plugin
enablement remains owned by the existing plugin loader.

## Stack scope

This is the foundation only. It does not read selected executor packages
or change thread startup. #29852 adds the executor-backed declaration
reader, and #29856 composes selected declarations into a thread
snapshot.
2026-06-24 23:24:01 +01:00

54 lines
1.5 KiB
Rust

use codex_plugin::AppConnectorId;
use codex_plugin::AppDeclaration;
use pretty_assertions::assert_eq;
use super::parse_plugin_app_config;
#[test]
fn parses_plugin_app_config_in_order_without_validating_connector_ids() {
let parsed = parse_plugin_app_config(
r#"{
"apps": {
"calendar": {
"id": "connector_calendar",
"category": " productivity "
},
"drive": {
"id": "connector_calendar",
"category": " "
},
"blank": {
"id": " "
}
}
}"#,
)
.expect("plugin app config should parse");
assert_eq!(
parsed,
vec![
AppDeclaration {
name: "calendar".to_string(),
connector_id: AppConnectorId("connector_calendar".to_string()),
category: Some("productivity".to_string()),
},
AppDeclaration {
name: "drive".to_string(),
connector_id: AppConnectorId("connector_calendar".to_string()),
category: None,
},
AppDeclaration {
name: "blank".to_string(),
connector_id: AppConnectorId(" ".to_string()),
category: None,
},
]
);
}
#[test]
fn rejects_invalid_plugin_app_config() {
assert!(parse_plugin_app_config("not json").is_err());
}