diff --git a/ai-hub/app/api/routes/admin.py b/ai-hub/app/api/routes/admin.py index b556f57..1697015 100644 --- a/ai-hub/app/api/routes/admin.py +++ b/ai-hub/app/api/routes/admin.py @@ -119,6 +119,8 @@ # Derived TLS enabled from endpoint protocol endpoint = update.external_endpoint.lower() settings.GRPC_TLS_ENABLED = endpoint.startswith("https://") or ":443" in endpoint + if update.grpc_endpoint is not None: + settings.GRPC_TARGET_ORIGIN = update.grpc_endpoint settings.save_to_yaml() return {"message": "Swarm configuration updated successfully"} @@ -140,7 +142,8 @@ "allow_oidc_login": settings.ALLOW_OIDC_LOGIN }, "swarm": { - "external_endpoint": settings.GRPC_EXTERNAL_ENDPOINT + "external_endpoint": settings.GRPC_EXTERNAL_ENDPOINT, + "grpc_endpoint": getattr(settings, "GRPC_TARGET_ORIGIN", None) } } diff --git a/ai-hub/app/api/routes/nodes.py b/ai-hub/app/api/routes/nodes.py index 1f85d57..41cb38e 100644 --- a/ai-hub/app/api/routes/nodes.py +++ b/ai-hub/app/api/routes/nodes.py @@ -1126,19 +1126,11 @@ def _generate_node_config_yaml(node: models.AgentNode, skill_overrides: dict = None, db: Session = None) -> str: """Helper to generate the agent_config.yaml content.""" + from app.config import settings - # Defaults - hub_url = os.getenv("HUB_PUBLIC_URL", "http://127.0.0.1:8000") - hub_grpc = os.getenv("HUB_GRPC_ENDPOINT", "127.0.0.1:50051") - - # Overlay with dynamically configured Swarm Admin settings if available - if db: - swarm_setting = db.query(models.SystemSettings).filter_by(key="swarm").first() - if swarm_setting and isinstance(swarm_setting.value, dict): - if swarm_setting.value.get("external_endpoint"): - hub_url = swarm_setting.value.get("external_endpoint") - if swarm_setting.value.get("grpc_endpoint"): - hub_grpc = swarm_setting.value.get("grpc_endpoint") + # Use dynamically configured Swarm Admin settings or fallbacks + hub_url = settings.GRPC_EXTERNAL_ENDPOINT or os.getenv("HUB_PUBLIC_URL", "http://127.0.0.1:8000") + hub_grpc = settings.GRPC_TARGET_ORIGIN or os.getenv("HUB_GRPC_ENDPOINT", "127.0.0.1:50051") secret_key = os.getenv("SECRET_KEY", "dev-secret-key-1337") diff --git a/ai-hub/app/api/schemas.py b/ai-hub/app/api/schemas.py index 3f2b501..63c0ec6 100644 --- a/ai-hub/app/api/schemas.py +++ b/ai-hub/app/api/schemas.py @@ -103,6 +103,7 @@ class SwarmConfigUpdate(BaseModel): external_endpoint: Optional[str] = None + grpc_endpoint: Optional[str] = None class AppConfigUpdate(BaseModel): allow_password_login: Optional[bool] = None diff --git a/ai-hub/app/config.py b/ai-hub/app/config.py index 7f4668b..b17f0d0 100644 --- a/ai-hub/app/config.py +++ b/ai-hub/app/config.py @@ -54,6 +54,7 @@ class SwarmSettings(BaseModel): external_endpoint: Optional[str] = None + grpc_endpoint: Optional[str] = None class AppConfig(BaseModel): """Top-level Pydantic model for application configuration.""" @@ -134,6 +135,11 @@ self.GRPC_EXTERNAL_ENDPOINT: Optional[str] = os.getenv("GRPC_EXTERNAL_ENDPOINT") or \ get_from_yaml(["swarm", "external_endpoint"]) or \ config_from_pydantic.swarm.external_endpoint + + self.GRPC_TARGET_ORIGIN: Optional[str] = os.getenv("GRPC_TARGET_ORIGIN") or \ + os.getenv("HUB_GRPC_ENDPOINT") or \ + get_from_yaml(["swarm", "grpc_endpoint"]) or \ + config_from_pydantic.swarm.grpc_endpoint # Infer TLS from endpoint protocol = self.GRPC_EXTERNAL_ENDPOINT.split("://")[0] if self.GRPC_EXTERNAL_ENDPOINT and "://" in self.GRPC_EXTERNAL_ENDPOINT else "http" diff --git a/frontend/src/features/settings/components/cards/NetworkIdentityCard.js b/frontend/src/features/settings/components/cards/NetworkIdentityCard.js index db373a9..40bbdf9 100644 --- a/frontend/src/features/settings/components/cards/NetworkIdentityCard.js +++ b/frontend/src/features/settings/components/cards/NetworkIdentityCard.js @@ -45,7 +45,7 @@ }; const isOidcValid = !adminConfig.oidc?.server_url || lastTestedConfig.oidc === JSON.stringify(adminConfig.oidc); - const isSwarmValid = !adminConfig.swarm?.external_endpoint || lastTestedConfig.swarm === JSON.stringify(adminConfig.swarm); + const isSwarmValid = (!adminConfig.swarm?.external_endpoint || !adminConfig.swarm?.grpc_endpoint) || lastTestedConfig.swarm === JSON.stringify(adminConfig.swarm); if (userProfile?.role !== 'admin') return null; @@ -238,10 +238,10 @@ )} -
Auto-detected provisioning discovery endpoint.
+Used by agents to download OTA updates and push REST logs.
setAdminConfig({...adminConfig, swarm: {...adminConfig.swarm, external_endpoint: e.target.value}})} className={inputClass} - placeholder="https://ai.jerxie.com" + placeholder="https://ai.company.com" autoComplete="off" />The precise Domain:Port agents use for high-throughput streaming over HTTP/2.
+The precise Domain:Port agents use for continuous data streaming.
setAdminConfig({...adminConfig, swarm: {...adminConfig.swarm, grpc_endpoint: e.target.value}})} className={inputClass} - placeholder="ai.jerxie.com:443" + placeholder="ai.company.com:443" autoComplete="off" />