Skip to content

Commit ba2aff0

Browse files
committed
chore(providers): trim bundled v2 profiles
1 parent 7667f2f commit ba2aff0

15 files changed

Lines changed: 75 additions & 306 deletions

File tree

crates/openshell-cli/src/run.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3372,7 +3372,7 @@ fn inferred_provider_type(command: &[String]) -> Option<String> {
33723372
/// passed through directly; the server validates they exist at sandbox creation.
33733373
///
33743374
/// `inferred_types` are provider **types** inferred from the trailing command
3375-
/// (e.g. `claude` type `"claude"`). These are resolved to provider names via
3375+
/// (e.g. `claude` -> type `"claude-code"`). These are resolved to provider names via
33763376
/// a type→name lookup, and missing types may be auto-created interactively.
33773377
///
33783378
/// Returns a deduplicated list of provider **names** suitable for
@@ -6966,7 +6966,7 @@ mod tests {
69666966
#[test]
69676967
fn inferred_provider_type_returns_type_for_known_command() {
69686968
let result = inferred_provider_type(&["claude".to_string(), "--help".to_string()]);
6969-
assert_eq!(result, Some("claude".to_string()));
6969+
assert_eq!(result, Some("claude-code".to_string()));
69706970
}
69716971

69726972
#[test]
@@ -6995,7 +6995,7 @@ mod tests {
69956995
#[test]
69966996
fn inferred_provider_type_handles_full_path() {
69976997
let result = inferred_provider_type(&["/usr/local/bin/claude".to_string()]);
6998-
assert_eq!(result, Some("claude".to_string()));
6998+
assert_eq!(result, Some("claude-code".to_string()));
69996999
}
70007000

70017001
#[test]

crates/openshell-providers/src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl ProviderRegistry {
144144
pub fn normalize_provider_type(input: &str) -> Option<&'static str> {
145145
let normalized = input.trim().to_ascii_lowercase();
146146
match normalized.as_str() {
147-
"claude" => Some("claude"),
147+
"claude" | "claude-code" | "claude_code" => Some("claude-code"),
148148
"codex" => Some("codex"),
149149
"copilot" => Some("copilot"),
150150
"opencode" => Some("opencode"),
@@ -178,7 +178,8 @@ mod tests {
178178
assert_eq!(normalize_provider_type("gitlab"), Some("gitlab"));
179179
assert_eq!(normalize_provider_type("glab"), Some("gitlab"));
180180
assert_eq!(normalize_provider_type("gh"), Some("github"));
181-
assert_eq!(normalize_provider_type("CLAUDE"), Some("claude"));
181+
assert_eq!(normalize_provider_type("CLAUDE"), Some("claude-code"));
182+
assert_eq!(normalize_provider_type("claude-code"), Some("claude-code"));
182183
assert_eq!(normalize_provider_type("generic"), Some("generic"));
183184
assert_eq!(normalize_provider_type("openai"), Some("openai"));
184185
assert_eq!(normalize_provider_type("anthropic"), Some("anthropic"));
@@ -191,7 +192,7 @@ mod tests {
191192
fn detects_provider_from_command_token() {
192193
assert_eq!(
193194
detect_provider_from_command(&["claude".to_string()]),
194-
Some("claude")
195+
Some("claude-code")
195196
);
196197
assert_eq!(
197198
detect_provider_from_command(&["/usr/bin/glab".to_string()]),

crates/openshell-providers/src/profiles.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,9 @@ use std::collections::{HashMap, HashSet};
1717
use std::sync::OnceLock;
1818

1919
const BUILT_IN_PROFILE_YAMLS: &[&str] = &[
20-
include_str!("../../../providers/anthropic.yaml"),
21-
include_str!("../../../providers/claude.yaml"),
22-
include_str!("../../../providers/codex.yaml"),
23-
include_str!("../../../providers/copilot.yaml"),
24-
include_str!("../../../providers/google-drive.yaml"),
20+
include_str!("../../../providers/claude-code.yaml"),
2521
include_str!("../../../providers/github.yaml"),
26-
include_str!("../../../providers/gitlab.yaml"),
2722
include_str!("../../../providers/nvidia.yaml"),
28-
include_str!("../../../providers/openai.yaml"),
29-
include_str!("../../../providers/opencode.yaml"),
30-
include_str!("../../../providers/outlook.yaml"),
3123
];
3224

3325
#[derive(Debug, thiserror::Error)]
@@ -1075,10 +1067,10 @@ mod tests {
10751067

10761068
#[test]
10771069
fn credential_env_vars_are_deduplicated_in_profile_order() {
1078-
let profile = get_default_profile("copilot").expect("copilot profile");
1070+
let profile = get_default_profile("claude-code").expect("claude-code profile");
10791071
assert_eq!(
10801072
profile.credential_env_vars(),
1081-
vec!["COPILOT_GITHUB_TOKEN", "GH_TOKEN", "GITHUB_TOKEN"]
1073+
vec!["ANTHROPIC_API_KEY", "CLAUDE_API_KEY"]
10821074
);
10831075
}
10841076

crates/openshell-providers/src/providers/claude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
pub struct ClaudeProvider;
99

1010
pub const SPEC: ProviderDiscoverySpec = ProviderDiscoverySpec {
11-
id: "claude",
11+
id: "claude-code",
1212
credential_env_vars: &["ANTHROPIC_API_KEY", "CLAUDE_API_KEY"],
1313
};
1414

crates/openshell-server/src/grpc/provider.rs

Lines changed: 54 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ use openshell_core::proto::{
573573
};
574574
use openshell_providers::{
575575
CredentialRefreshProfile, ProfileValidationDiagnostic, ProviderTypeProfile, default_profiles,
576-
get_default_profile, normalize_profile_id, normalize_provider_type, validate_profile_set,
576+
get_default_profile, normalize_profile_id, validate_profile_set,
577577
};
578578
use std::sync::Arc;
579579
use tonic::{Request, Response};
@@ -928,18 +928,6 @@ async fn profile_conflict_diagnostics(
928928
});
929929
continue;
930930
}
931-
if let Some(provider_type) = normalize_provider_type(&id) {
932-
diagnostics.push(ProfileValidationDiagnostic {
933-
source: source.clone(),
934-
profile_id: id.clone(),
935-
field: "id".to_string(),
936-
message: format!(
937-
"provider profile id '{id}' is reserved for legacy provider type '{provider_type}'"
938-
),
939-
severity: "error".to_string(),
940-
});
941-
continue;
942-
}
943931
if store
944932
.get_message_by_name::<StoredProviderProfile>(&id)
945933
.await
@@ -1514,6 +1502,29 @@ mod tests {
15141502
}
15151503
}
15161504

1505+
async fn import_test_refresh_profile(state: &Arc<ServerState>, id: &str, credential_key: &str) {
1506+
let mut profile = custom_profile(id);
1507+
profile.category = ProviderProfileCategory::Messaging as i32;
1508+
profile.credentials = vec![refreshable_credential("access_token", credential_key)];
1509+
handle_import_provider_profiles(
1510+
state,
1511+
Request::new(ImportProviderProfilesRequest {
1512+
profiles: vec![ProviderProfileImportItem {
1513+
profile: Some(profile),
1514+
source: format!("{id}.yaml"),
1515+
}],
1516+
}),
1517+
)
1518+
.await
1519+
.unwrap();
1520+
}
1521+
1522+
const TEST_GRAPH_PROVIDER_TYPE: &str = "test-msgraph";
1523+
1524+
async fn import_test_graph_refresh_profile(state: &Arc<ServerState>) {
1525+
import_test_refresh_profile(state, TEST_GRAPH_PROVIDER_TYPE, "MS_GRAPH_ACCESS_TOKEN").await;
1526+
}
1527+
15171528
fn static_credential(name: &str, env_var: &str, required: bool) -> ProviderProfileCredential {
15181529
ProviderProfileCredential {
15191530
name: name.to_string(),
@@ -1560,6 +1571,13 @@ mod tests {
15601571
.unwrap()
15611572
.into_inner();
15621573

1574+
let ids = response
1575+
.profiles
1576+
.iter()
1577+
.map(|profile| profile.id.as_str())
1578+
.collect::<Vec<_>>();
1579+
assert_eq!(ids, vec!["claude-code", "github", "nvidia"]);
1580+
15631581
let github = response
15641582
.profiles
15651583
.iter()
@@ -1569,13 +1587,6 @@ mod tests {
15691587
github.category,
15701588
ProviderProfileCategory::SourceControl as i32
15711589
);
1572-
assert!(
1573-
response
1574-
.profiles
1575-
.iter()
1576-
.all(|profile| profile.id != "generic"),
1577-
"generic remains a legacy provider type without a v2 profile"
1578-
);
15791590
}
15801591

15811592
#[tokio::test]
@@ -1685,38 +1696,36 @@ mod tests {
16851696
}
16861697

16871698
#[tokio::test]
1688-
async fn import_provider_profile_rejects_legacy_provider_type_ids() {
1699+
async fn import_provider_profile_allows_legacy_provider_type_ids_without_built_in_profiles() {
16891700
let state = test_server_state().await;
16901701
let response = handle_import_provider_profiles(
16911702
&state,
16921703
Request::new(ImportProviderProfilesRequest {
16931704
profiles: vec![ProviderProfileImportItem {
1694-
profile: Some(custom_profile("generic")),
1695-
source: "generic.yaml".to_string(),
1705+
profile: Some(custom_profile("codex")),
1706+
source: "codex.yaml".to_string(),
16961707
}],
16971708
}),
16981709
)
16991710
.await
17001711
.unwrap()
17011712
.into_inner();
17021713

1703-
assert!(!response.imported);
1704-
assert!(
1705-
response
1706-
.diagnostics
1707-
.iter()
1708-
.any(|diagnostic| diagnostic.message.contains("reserved"))
1709-
);
1714+
assert!(response.imported);
1715+
assert!(response.diagnostics.is_empty());
17101716

1711-
let missing = handle_get_provider_profile(
1717+
let imported = handle_get_provider_profile(
17121718
&state,
17131719
Request::new(GetProviderProfileRequest {
1714-
id: "generic".to_string(),
1720+
id: "codex".to_string(),
17151721
}),
17161722
)
17171723
.await
1718-
.unwrap_err();
1719-
assert_eq!(missing.code(), Code::NotFound);
1724+
.unwrap()
1725+
.into_inner()
1726+
.profile
1727+
.expect("codex profile should be returned");
1728+
assert_eq!(imported.id, "codex");
17201729
}
17211730

17221731
#[tokio::test]
@@ -2022,6 +2031,7 @@ mod tests {
20222031
#[tokio::test]
20232032
async fn configure_provider_refresh_stores_scoped_status_and_provider_expiry() {
20242033
let state = test_server_state().await;
2034+
import_test_graph_refresh_profile(&state).await;
20252035
create_provider_record(
20262036
state.store.as_ref(),
20272037
Provider {
@@ -2031,7 +2041,7 @@ mod tests {
20312041
created_at_ms: 0,
20322042
labels: HashMap::new(),
20332043
}),
2034-
r#type: "outlook".to_string(),
2044+
r#type: TEST_GRAPH_PROVIDER_TYPE.to_string(),
20352045
credentials: std::iter::once((
20362046
"MS_GRAPH_ACCESS_TOKEN".to_string(),
20372047
"token".to_string(),
@@ -2133,6 +2143,7 @@ mod tests {
21332143
#[tokio::test]
21342144
async fn delete_provider_refresh_preserves_manually_updated_expiry() {
21352145
let state = test_server_state().await;
2146+
import_test_graph_refresh_profile(&state).await;
21362147
create_provider_record(
21372148
state.store.as_ref(),
21382149
Provider {
@@ -2142,7 +2153,7 @@ mod tests {
21422153
created_at_ms: 0,
21432154
labels: HashMap::new(),
21442155
}),
2145-
r#type: "outlook".to_string(),
2156+
r#type: TEST_GRAPH_PROVIDER_TYPE.to_string(),
21462157
credentials: std::iter::once((
21472158
"MS_GRAPH_ACCESS_TOKEN".to_string(),
21482159
"token".to_string(),
@@ -2225,6 +2236,7 @@ mod tests {
22252236
#[tokio::test]
22262237
async fn configure_provider_refresh_rejects_credential_key_collision_for_attached_sandbox() {
22272238
let state = test_server_state().await;
2239+
import_test_graph_refresh_profile(&state).await;
22282240
create_provider_record(
22292241
state.store.as_ref(),
22302242
Provider {
@@ -2234,7 +2246,7 @@ mod tests {
22342246
created_at_ms: 0,
22352247
labels: HashMap::new(),
22362248
}),
2237-
r#type: "outlook".to_string(),
2249+
r#type: TEST_GRAPH_PROVIDER_TYPE.to_string(),
22382250
credentials: std::iter::once((
22392251
"MS_GRAPH_ACCESS_TOKEN".to_string(),
22402252
"existing-token".to_string(),
@@ -2255,7 +2267,7 @@ mod tests {
22552267
created_at_ms: 0,
22562268
labels: HashMap::new(),
22572269
}),
2258-
r#type: "outlook".to_string(),
2270+
r#type: TEST_GRAPH_PROVIDER_TYPE.to_string(),
22592271
credentials: std::iter::once(("OTHER_TOKEN".to_string(), "other".to_string()))
22602272
.collect(),
22612273
config: HashMap::new(),
@@ -2312,6 +2324,7 @@ mod tests {
23122324
#[tokio::test]
23132325
async fn configure_provider_refresh_treats_existing_refresh_state_keys_as_reserved() {
23142326
let state = test_server_state().await;
2327+
import_test_graph_refresh_profile(&state).await;
23152328
for name in ["first-graph", "second-graph"] {
23162329
create_provider_record(
23172330
state.store.as_ref(),
@@ -2322,7 +2335,7 @@ mod tests {
23222335
created_at_ms: 0,
23232336
labels: HashMap::new(),
23242337
}),
2325-
r#type: "outlook".to_string(),
2338+
r#type: TEST_GRAPH_PROVIDER_TYPE.to_string(),
23262339
credentials: HashMap::new(),
23272340
config: HashMap::new(),
23282341
credential_expires_at_ms: HashMap::new(),
@@ -2395,6 +2408,7 @@ mod tests {
23952408
#[tokio::test]
23962409
async fn configure_provider_refresh_rejects_profile_endpoint_override_and_missing_material() {
23972410
let state = test_server_state().await;
2411+
import_test_graph_refresh_profile(&state).await;
23982412
create_provider_record(
23992413
state.store.as_ref(),
24002414
Provider {
@@ -2404,7 +2418,7 @@ mod tests {
24042418
created_at_ms: 0,
24052419
labels: HashMap::new(),
24062420
}),
2407-
r#type: "outlook".to_string(),
2421+
r#type: TEST_GRAPH_PROVIDER_TYPE.to_string(),
24082422
credentials: std::iter::once((
24092423
"MS_GRAPH_ACCESS_TOKEN".to_string(),
24102424
"token".to_string(),
@@ -2773,25 +2787,6 @@ mod tests {
27732787
.unwrap_err();
27742788
assert_eq!(create_missing_credentials.code(), Code::InvalidArgument);
27752789

2776-
let refresh_bootstrap_provider = create_provider_record(
2777-
store,
2778-
Provider {
2779-
metadata: Some(openshell_core::proto::datamodel::v1::ObjectMeta {
2780-
id: String::new(),
2781-
name: "outlook-no-token-yet".to_string(),
2782-
created_at_ms: 1_000_000,
2783-
labels: HashMap::new(),
2784-
}),
2785-
r#type: "outlook".to_string(),
2786-
credentials: HashMap::new(),
2787-
config: HashMap::new(),
2788-
credential_expires_at_ms: HashMap::new(),
2789-
},
2790-
)
2791-
.await
2792-
.unwrap();
2793-
assert!(refresh_bootstrap_provider.credentials.is_empty());
2794-
27952790
handle_import_provider_profiles(
27962791
&state,
27972792
Request::new(ImportProviderProfilesRequest {

0 commit comments

Comments
 (0)