app-server: drop legacy profile config surface (#24067)

## Why

Legacy `[profiles.<name>]` config tables and the legacy `profile`
selector are being retired in favor of profile files selected with
`--profile <name>`. After #23886 removed the CLI-side legacy profile
plumbing, the app-server config surface still exposed those fields and
still carried conversion code for the old protocol shape.

## What changed

- Remove `profile`, `profiles`, and `ProfileV2` from the app-server
config protocol/schema output so `config/read` no longer returns legacy
profile config.
- Drop the old v1 `UserSavedConfig` profile conversion path from
`config`.
- Reject new app-server config writes under `profiles.*` with the same
migration direction used for `profile`, while still allowing callers to
clear existing legacy profile tables.
- Refresh app-server config coverage and the experimental API README
example around the remaining `Config` nesting path.

## Verification

- Added config-manager coverage that `config/read` omits legacy profile
config, `profiles.*` writes are rejected, and existing legacy profile
tables can still be cleared.
- Updated the v2 config RPC test to cover the rejected `profiles.*`
batch-write path.
This commit is contained in:
jif-oai
2026-05-22 19:41:39 +02:00
committed by GitHub
parent c0b16cfc6b
commit 162a6e746b
17 changed files with 67 additions and 677 deletions
@@ -1505,32 +1505,6 @@ fn ask_for_approval_granular_is_marked_experimental() {
);
}
#[test]
fn profile_v2_granular_approval_policy_is_marked_experimental() {
let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&ProfileV2 {
model: None,
model_provider: None,
approval_policy: Some(AskForApproval::Granular {
sandbox_approval: true,
rules: false,
skill_approval: false,
request_permissions: true,
mcp_elicitations: false,
}),
approvals_reviewer: None,
service_tier: None,
model_reasoning_effort: None,
model_reasoning_summary: None,
model_verbosity: None,
web_search: None,
tools: None,
chatgpt_base_url: None,
additional: HashMap::new(),
});
assert_eq!(reason, Some("askForApproval.granular"));
}
#[test]
fn config_granular_approval_policy_is_marked_experimental() {
let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&Config {
@@ -1554,8 +1528,6 @@ fn config_granular_approval_policy_is_marked_experimental() {
forced_login_method: None,
web_search: None,
tools: None,
profile: None,
profiles: HashMap::new(),
instructions: None,
developer_instructions: None,
compact_prompt: None,
@@ -1589,116 +1561,6 @@ fn config_approvals_reviewer_is_marked_experimental() {
forced_login_method: None,
web_search: None,
tools: None,
profile: None,
profiles: HashMap::new(),
instructions: None,
developer_instructions: None,
compact_prompt: None,
model_reasoning_effort: None,
model_reasoning_summary: None,
model_verbosity: None,
service_tier: None,
analytics: None,
apps: None,
desktop: None,
additional: HashMap::new(),
});
assert_eq!(reason, Some("config/read.approvalsReviewer"));
}
#[test]
fn config_nested_profile_granular_approval_policy_is_marked_experimental() {
let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&Config {
model: None,
review_model: None,
model_context_window: None,
model_auto_compact_token_limit: None,
model_auto_compact_token_limit_scope: None,
model_provider: None,
approval_policy: None,
approvals_reviewer: None,
sandbox_mode: None,
sandbox_workspace_write: None,
forced_chatgpt_workspace_id: None,
forced_login_method: None,
web_search: None,
tools: None,
profile: None,
profiles: HashMap::from([(
"default".to_string(),
ProfileV2 {
model: None,
model_provider: None,
approval_policy: Some(AskForApproval::Granular {
sandbox_approval: true,
rules: false,
skill_approval: false,
request_permissions: false,
mcp_elicitations: true,
}),
approvals_reviewer: None,
service_tier: None,
model_reasoning_effort: None,
model_reasoning_summary: None,
model_verbosity: None,
web_search: None,
tools: None,
chatgpt_base_url: None,
additional: HashMap::new(),
},
)]),
instructions: None,
developer_instructions: None,
compact_prompt: None,
model_reasoning_effort: None,
model_reasoning_summary: None,
model_verbosity: None,
service_tier: None,
analytics: None,
apps: None,
desktop: None,
additional: HashMap::new(),
});
assert_eq!(reason, Some("askForApproval.granular"));
}
#[test]
fn config_nested_profile_approvals_reviewer_is_marked_experimental() {
let reason = crate::experimental_api::ExperimentalApi::experimental_reason(&Config {
model: None,
review_model: None,
model_context_window: None,
model_auto_compact_token_limit: None,
model_auto_compact_token_limit_scope: None,
model_provider: None,
approval_policy: None,
approvals_reviewer: None,
sandbox_mode: None,
sandbox_workspace_write: None,
forced_chatgpt_workspace_id: None,
forced_login_method: None,
web_search: None,
tools: None,
profile: None,
profiles: HashMap::from([(
"default".to_string(),
ProfileV2 {
model: None,
model_provider: None,
approval_policy: None,
approvals_reviewer: Some(ApprovalsReviewer::AutoReview),
service_tier: None,
model_reasoning_effort: None,
model_reasoning_summary: None,
model_verbosity: None,
web_search: None,
tools: None,
chatgpt_base_url: None,
additional: HashMap::new(),
},
)]),
instructions: None,
developer_instructions: None,
compact_prompt: None,