Skip to main content

soma_provider_adapters/python/
catalog.rs

1use std::path::PathBuf;
2
3use soma_provider_core::{ProviderCatalog, ProviderError};
4
5use super::{
6    PythonInterpreter, PythonSupervisorConfig, PythonWorkerIdentity, PythonWorkerSupervisor,
7    sha256_hex,
8};
9
10/// Discover a Python catalog inside the same supervised containment boundary
11/// used for activation. This prevents brokered mode from importing provider
12/// code in the host process or an ambient one-shot subprocess.
13pub async fn describe_persistent_catalog(
14    path: PathBuf,
15    interpreter: PythonInterpreter,
16    config: PythonSupervisorConfig,
17) -> Result<ProviderCatalog, ProviderError> {
18    let source = std::fs::read(&path)
19        .map_err(|error| ProviderError::execution("", "", error).with_phase("catalog-discovery"))?;
20    let source_digest = sha256_hex(&source);
21    let supervisor = PythonWorkerSupervisor::new_with_capabilities(
22        PythonWorkerIdentity {
23            path: path.clone(),
24            generation_id: format!("discovery-{}", &source_digest[..16]),
25            worker_group: source_digest.clone(),
26            source_digest,
27            catalog_fingerprint: String::new(),
28        },
29        interpreter,
30        config,
31        &soma_provider_core::HostCapabilities::default(),
32    );
33    let described = supervisor.preflight().await.map_err(|error| {
34        ProviderError::new(
35            error.code(),
36            "",
37            None,
38            error.to_string(),
39            "Inspect the contained Python provider discovery worker.",
40        )
41        .with_provider_kind("python")
42        .with_source(path.display().to_string())
43        .with_phase("catalog-discovery")
44    });
45    supervisor.shutdown().await;
46    soma_provider_core::validate_provider_manifest_value(&described?).map_err(|error| {
47        ProviderError::validation("", "", "python_catalog_invalid", error.to_string())
48            .with_provider_kind("python")
49            .with_source(path.display().to_string())
50            .with_phase("catalog-discovery")
51    })
52}