diff --git a/crates/catalogd/src/service.rs b/crates/catalogd/src/service.rs index b472173..863228e 100644 --- a/crates/catalogd/src/service.rs +++ b/crates/catalogd/src/service.rs @@ -31,6 +31,10 @@ pub fn router(registry: Registry) -> Router { // Phase 17: model profiles .route("/profiles", post(create_profile).get(list_profiles)) .route("/profiles/{id}", get(get_profile).delete(delete_profile)) + // Phase 41: profile-type routes + .route("/profiles/retrieval", get(list_retrieval_profiles)) + .route("/profiles/memory", get(list_memory_profiles)) + .route("/profiles/observer", get(list_observer_profiles)) .with_state(registry) } @@ -398,6 +402,9 @@ struct CreateProfileRequest { /// indexes to. Defaults to Parquet+HNSW. #[serde(default)] vector_backend: shared::types::VectorBackend, + /// Phase 41: Profile type for routing + activation behavior. + #[serde(default)] + profile_type: shared::types::ProfileType, } fn default_embed_model_req() -> String { "nomic-embed-text".to_string() } @@ -417,6 +424,7 @@ async fn create_profile( created_by: req.created_by, bucket: req.bucket, vector_backend: req.vector_backend, + profile_type: req.profile_type, }; match registry.put_profile(profile).await { Ok(p) => Ok((StatusCode::CREATED, Json(p))), @@ -428,6 +436,24 @@ async fn list_profiles(State(registry): State) -> impl IntoResponse { Json(registry.list_profiles().await) } +async fn list_retrieval_profiles(State(registry): State) -> impl IntoResponse { + let all = registry.list_profiles().await; + let retrieval: Vec<_> = all.into_iter().filter(|p| p.profile_type == shared::types::ProfileType::Retrieval).collect(); + Json(retrieval) +} + +async fn list_memory_profiles(State(registry): State) -> impl IntoResponse { + let all = registry.list_profiles().await; + let memory: Vec<_> = all.into_iter().filter(|p| p.profile_type == shared::types::ProfileType::Memory).collect(); + Json(memory) +} + +async fn list_observer_profiles(State(registry): State) -> impl IntoResponse { + let all = registry.list_profiles().await; + let observer: Vec<_> = all.into_iter().filter(|p| p.profile_type == shared::types::ProfileType::Observer).collect(); + Json(observer) +} + async fn get_profile( State(registry): State, Path(id): Path, diff --git a/crates/shared/src/types.rs b/crates/shared/src/types.rs index ba46012..c22749a 100644 --- a/crates/shared/src/types.rs +++ b/crates/shared/src/types.rs @@ -269,6 +269,20 @@ pub struct ModelProfile { /// / 5M+ vector workloads. #[serde(default)] pub vector_backend: VectorBackend, + /// Phase 41: Profile type for routing + activation behavior. + /// Default Execution for backward compatibility. + #[serde(default)] + pub profile_type: ProfileType, +} + +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Default)] +#[serde(rename_all = "snake_case")] +pub enum ProfileType { + #[default] + Execution, + Retrieval, + Memory, + Observer, } fn default_embed_model() -> String { "nomic-embed-text".to_string() }