diff --git a/skills/azure-architecture-autopilot/references/phase1-advisor.md b/skills/azure-architecture-autopilot/references/phase1-advisor.md index a8d12c160..d8c447ce6 100644 --- a/skills/azure-architecture-autopilot/references/phase1-advisor.md +++ b/skills/azure-architecture-autopilot/references/phase1-advisor.md @@ -432,20 +432,63 @@ Dynamically composed based on the user's confirmed service list. Below is the JS | `subscription` | | string | Subscription name (required when using hierarchy) | | `resourceGroup` | | string | Resource group name (required when using hierarchy) | -**Service Type List (by category):** - -| Category | Types | -|----------|-------| -| **AI** | `ai_foundry`, `ai_hub`, `openai`, `ai_search` / `search`, `document_intelligence` / `form_recognizer`, `aml` | -| **Data** | `storage` / `adls`, `cosmos_db`, `sql_database`, `sql_server`, `databricks`, `data_factory` / `adf`, `fabric`, `redis`, `stream_analytics`, `synapse` | -| **Security** | `keyvault` / `kv` | -| **Compute** | `app_service` / `appservice`, `function_app`, `vm`, `aks`, `acr` / `container_registry` | -| **Network** | `firewall`, `bastion`, `vpn_gateway` / `vpn`, `app_gateway`, `front_door`, `cdn`, `nsg`, `pe` | -| **IoT** | `iot_hub` | -| **Integration** | `event_hub` | -| **Monitoring** | `log_analytics`, `app_insights` / `appinsights`, `monitor` | -| **DevOps** | `devops` | -| **Other** | `jumpbox`, `user`, etc. (unrecognized types use fuzzy matching + default icon) | +**Service Type — Canonical Reference:** + +> ⚠️ **CRITICAL**: Always use the **canonical type** from the table below. Do NOT use Azure ARM resource names (e.g., `private_endpoints`, `storage_accounts`, `data_factories`). The generator normalizes common variants, but using canonical types ensures correct icon rendering, PE detection, and color coding. + +| Category | Canonical Type | Azure Resource | Icon | +|----------|---------------|----------------|------| +| **AI** | `ai_foundry` | Microsoft.CognitiveServices/accounts (kind: AIServices) | AI Foundry | +| | `openai` | Microsoft.CognitiveServices/accounts (kind: OpenAI) | Azure OpenAI | +| | `ai_hub` | Foundry Project | AI Studio | +| | `search` | Microsoft.Search/searchServices | Cognitive Search | +| | `document_intelligence` | Microsoft.CognitiveServices/accounts (kind: FormRecognizer) | Form Recognizer | +| | `aml` | Microsoft.MachineLearningServices/workspaces | Machine Learning | +| **Data** | `fabric` | Microsoft.Fabric/capacities | Microsoft Fabric | +| | `adf` | Microsoft.DataFactory/factories | Data Factory | +| | `storage` | Microsoft.Storage/storageAccounts | Storage Account | +| | `adls` | ADLS Gen2 (Storage with HNS) | Data Lake | +| | `cosmos_db` | Microsoft.DocumentDB/databaseAccounts | Cosmos DB | +| | `sql_database` | Microsoft.Sql/servers/databases | SQL Database | +| | `sql_server` | Microsoft.Sql/servers | SQL Server | +| | `databricks` | Microsoft.Databricks/workspaces | Databricks | +| | `synapse` | Microsoft.Synapse/workspaces | Synapse Analytics | +| | `redis` | Microsoft.Cache/redis | Redis Cache | +| | `stream_analytics` | Microsoft.StreamAnalytics/streamingjobs | Stream Analytics | +| | `postgresql` | Microsoft.DBforPostgreSQL/flexibleServers | PostgreSQL | +| | `mysql` | Microsoft.DBforMySQL/flexibleServers | MySQL | +| **Security** | `keyvault` | Microsoft.KeyVault/vaults | Key Vault | +| | `sentinel` | Microsoft.SecurityInsights | Sentinel | +| **Compute** | `appservice` | Microsoft.Web/sites | App Service | +| | `function_app` | Microsoft.Web/sites (kind: functionapp) | Function App | +| | `vm` | Microsoft.Compute/virtualMachines | Virtual Machine | +| | `aks` | Microsoft.ContainerService/managedClusters | AKS | +| | `acr` | Microsoft.ContainerRegistry/registries | Container Registry | +| | `container_apps` | Microsoft.App/containerApps | Container Apps | +| | `static_web_app` | Microsoft.Web/staticSites | Static Web App | +| | `spring_apps` | Microsoft.AppPlatform/Spring | Spring Apps | +| **Network** | `pe` | Microsoft.Network/privateEndpoints | Private Endpoint | +| | `vnet` | Microsoft.Network/virtualNetworks | VNet | +| | `nsg` | Microsoft.Network/networkSecurityGroups | NSG | +| | `firewall` | Microsoft.Network/azureFirewalls | Firewall | +| | `bastion` | Microsoft.Network/bastionHosts | Bastion | +| | `app_gateway` | Microsoft.Network/applicationGateways | App Gateway | +| | `front_door` | Microsoft.Cdn/profiles (Front Door) | Front Door | +| | `vpn` | Microsoft.Network/virtualNetworkGateways | VPN Gateway | +| | `load_balancer` | Microsoft.Network/loadBalancers | Load Balancer | +| | `nat_gateway` | Microsoft.Network/natGateways | NAT Gateway | +| | `cdn` | Microsoft.Cdn/profiles | CDN | +| **IoT** | `iot_hub` | Microsoft.Devices/IotHubs | IoT Hub | +| | `digital_twins` | Microsoft.DigitalTwins/digitalTwinsInstances | Digital Twins | +| **Integration** | `event_hub` | Microsoft.EventHub/namespaces | Event Hub | +| | `event_grid` | Microsoft.EventGrid/topics | Event Grid | +| | `apim` | Microsoft.ApiManagement/service | API Management | +| | `service_bus` | Microsoft.ServiceBus/namespaces | Service Bus | +| | `logic_apps` | Microsoft.Logic/workflows | Logic Apps | +| **Monitoring** | `log_analytics` | Microsoft.OperationalInsights/workspaces | Log Analytics | +| | `appinsights` | Microsoft.Insights/components | App Insights | +| | `monitor` | Azure Monitor | Monitor | +| **Other** | `jumpbox`, `user`, `devops` | — | Special | **When Using Private Endpoints — PE Node Addition Required:** diff --git a/skills/azure-architecture-autopilot/scripts/generator.py b/skills/azure-architecture-autopilot/scripts/generator.py index 8c8d7373e..29b70e714 100644 --- a/skills/azure-architecture-autopilot/scripts/generator.py +++ b/skills/azure-architecture-autopilot/scripts/generator.py @@ -22,7 +22,7 @@ "ai_foundry": { "icon_svg": '', "color": "#0078D4", "bg": "#E8F4FD", "category": "AI", - "azure_icon_key": "azure_openai" + "azure_icon_key": "ai_foundry" }, "ai_hub": { "icon_svg": '', @@ -57,7 +57,7 @@ "fabric": { "icon_svg": 'F', "color": "#E8740C", "bg": "#FEF3E8", "category": "Data", - "azure_icon_key": "managed_service_fabric" + "azure_icon_key": "microsoft_fabric" }, "synapse": { "icon_svg": '', @@ -407,8 +407,74 @@ } +_TYPE_ALIASES = { + # Azure ARM resource names → canonical diagram type + # Network + "private_endpoints": "pe", "private_endpoint": "pe", + "virtual_networks": "vnet", "virtual_network": "vnet", + "network_security_groups": "nsg", "network_security_group": "nsg", + "bastion_hosts": "bastion", "bastion_host": "bastion", + "application_gateways": "app_gateway", "application_gateway": "app_gateway", + "front_doors": "front_door", "front_door_and_cdn_profiles": "front_door", + "virtual_network_gateways": "vpn", "vpn_gateways": "vpn", + "load_balancers": "load_balancer", + "nat_gateways": "nat_gateway", + "expressroute_circuits": "expressroute", + "firewalls": "firewall", + "cdn_profiles": "cdn", + # Data + "data_factories": "adf", "data_factory": "adf", + "storage_accounts": "storage", "storage_account": "storage", + "data_lake": "adls", "adls_gen2": "adls", "data_lake_storage": "adls", + "fabric_capacities": "fabric", "fabric_capacity": "fabric", "microsoft_fabric": "fabric", + "synapse_workspaces": "synapse", "synapse_workspace": "synapse", "synapse_analytics": "synapse", + "cosmos": "cosmos_db", "cosmosdb": "cosmos_db", "documentdb": "cosmos_db", + "sql_databases": "sql_database", "sql_db": "sql_database", + "sql_servers": "sql_server", + "redis_caches": "redis", "redis_cache": "redis", "cache_redis": "redis", + "stream_analytics_jobs": "stream_analytics", + "databricks_workspaces": "databricks", + "data_explorer_clusters": "data_explorer", "azure_data_explorer": "data_explorer", + "postgresql_server": "postgresql", "postgresql_servers": "postgresql", + "mysql_server": "mysql", "mysql_servers": "mysql", + # AI + "cognitive_services": "ai_foundry", "ai_services": "ai_foundry", "foundry": "ai_foundry", + "azure_openai": "openai", + "cognitive_search": "search", "search_services": "search", "search_service": "search", + "machine_learning": "aml", "ml": "aml", "machine_learning_workspaces": "aml", + "form_recognizers": "document_intelligence", + "ai_studio": "ai_hub", "foundry_project": "ai_hub", + # Security + "key_vault": "keyvault", "key_vaults": "keyvault", + "sentinel": "sentinel", "azure_sentinel": "sentinel", + # Compute + "virtual_machines": "vm", "virtual_machine": "vm", + "app_services": "appservice", "web_apps": "appservice", "web_app": "appservice", + "function_apps": "function_app", "functions": "function_app", + "kubernetes_services": "aks", "managed_clusters": "aks", "kubernetes": "aks", + "container_registries": "acr", + "container_apps_environments": "container_apps", + "spring_apps": "spring_apps", "azure_spring_apps": "spring_apps", + "static_apps": "static_web_app", "static_web_apps": "static_web_app", + # Integration + "event_hubs": "event_hub", + "event_grid_topics": "event_grid", "event_grid_domains": "event_grid", + "api_management_services": "apim", + "service_bus_namespaces": "service_bus", + "logic_app": "logic_apps", + "notification_hubs": "notification_hub", + # Monitoring + "log_analytics_workspaces": "log_analytics", + "application_insights": "appinsights", "app_insight": "appinsights", + # IoT + "iot_hubs": "iot_hub", + # Management + "backup_vaults": "backup", "backup_vault": "backup", +} + def get_service_info(svc_type: str) -> dict: t = svc_type.lower().replace("-", "_").replace(" ", "_") + t = _TYPE_ALIASES.get(t, t) info = SERVICE_ICONS.get(t, SERVICE_ICONS["default"]).copy() # Add official Azure icon data URI if available azure_key = info.get("azure_icon_key", t) @@ -418,10 +484,14 @@ def get_service_info(svc_type: str) -> dict: def generate_html(services: list, connections: list, title: str, vnet_info: str = "", hierarchy: list = None) -> str: + def _norm(t): + t = t.lower().replace("-", "_").replace(" ", "_") + return _TYPE_ALIASES.get(t, t) + nodes_js = json.dumps([{ "id": svc["id"], "name": svc["name"], - "type": svc.get("type", "default"), + "type": _norm(svc.get("type", "default")), "sku": svc.get("sku", ""), "private": svc.get("private", False), "details": svc.get("details", []), @@ -445,7 +515,7 @@ def generate_html(services: list, connections: list, title: str, vnet_info: str "dash": CONNECTION_STYLES.get(conn.get("type", "default"), CONNECTION_STYLES["default"])["dash"], } for conn in connections], ensure_ascii=False) - pe_count = sum(1 for s in services if s.get("type", "default") == "pe") + pe_count = sum(1 for s in services if _norm(s.get("type", "default")) == "pe") svc_count = len(services) - pe_count generated_at = datetime.now().strftime("%Y-%m-%d %H:%M") vnet_info_js = json.dumps(vnet_info, ensure_ascii=False) diff --git a/skills/azure-architecture-autopilot/scripts/icons.py b/skills/azure-architecture-autopilot/scripts/icons.py index b4cc837f0..c1867930c 100644 --- a/skills/azure-architecture-autopilot/scripts/icons.py +++ b/skills/azure-architecture-autopilot/scripts/icons.py @@ -3173,6 +3173,16 @@ "category": "compute", "name": "Workspaces", }, + "microsoft_fabric": { + "b64": "PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0OCIgaGVpZ2h0PSI0OCIgZmlsbD0iY3VycmVudENvbG9yIj48cGF0aCBmaWxsPSJ1cmwoI2k3ZmExYzEtYSkiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0ibTUuNjQgMzEuNi0uNTg2IDIuMTQ0Yy0uMjE4LjY4NS0uNTI0IDEuNjkzLS42ODkgMi41OWE1LjYzIDUuNjMgMCAwIDAgNC42MzggNy41ODhjLjc5Mi4xMTQgMS42ODguMTA4IDIuNjkyLS4wNGw0LjYxMy0uNjM2YTIuOTIgMi45MiAwIDAgMCAyLjQyMS0yLjEyN2wzLjE3NS0xMS42NjJMNS42NCAzMS41OTlaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSJ1cmwoI2k3ZmExYzEtYikiIGQ9Ik0xMC4xNCAzMi4xNTJjLTQuODYzLjc1My01Ljg2MSA0LjQyMy01Ljg2MSA0LjQyM2w0LjY1Ni0xNy4xMSAyNC4zMzMtMy4yOTItMy4zMTggMTIuMDUyYTEuNzEgMS43MSAwIDAgMS0xLjM4OCAxLjI0NGwtLjEzNi4wMjItMTguNDIzIDIuNjg0eiIvPjxwYXRoIGZpbGw9InVybCgjaTdmYTFjMS1jKSIgZmlsbC1vcGFjaXR5PSIuOCIgZD0iTTEwLjE0IDMyLjE1MmMtNC44NjMuNzUzLTUuODYxIDQuNDIzLTUuODYxIDQuNDIzbDQuNjU2LTE3LjExIDI0LjMzMy0zLjI5Mi0zLjMxOCAxMi4wNTJhMS43MSAxLjcxIDAgMCAxLTEuMzg4IDEuMjQ0bC0uMTM2LjAyMi0xOC40MjMgMi42ODR6Ii8+PHBhdGggZmlsbD0idXJsKCNpN2ZhMWMxLWQpIiBkPSJtMTIuODk5IDIxLjIzNSAyNi45MzgtMy45OGExLjYgMS42IDAgMCAwIDEuMzIzLTEuMTdsMi43OC0xMC4wNmExLjU5NSAxLjU5NSAwIDAgMC0xLjc0LTIuMDEyTDE2LjQ5OCA3LjgxYTcuMTkgNy4xOSAwIDAgMC01Ljc3NyA1LjE5M0w3LjAxMyAyNi40MzhjLjc0NC0yLjcxNyAxLjIwMi00LjM1NSA1Ljg4Ni01LjIwMyIvPjxwYXRoIGZpbGw9InVybCgjaTdmYTFjMS1lKSIgZD0ibTEyLjg5OSAyMS4yMzUgMjYuOTM4LTMuOThhMS42IDEuNiAwIDAgMCAxLjMyMy0xLjE3bDIuNzgtMTAuMDZhMS41OTUgMS41OTUgMCAwIDAtMS43NC0yLjAxMkwxNi40OTggNy44MWE3LjE5IDcuMTkgMCAwIDAtNS43NzcgNS4xOTNMNy4wMTMgMjYuNDM4Yy43NDQtMi43MTcgMS4yMDItNC4zNTUgNS44ODYtNS4yMDMiLz48cGF0aCBmaWxsPSJ1cmwoI2k3ZmExYzEtZikiIGZpbGwtb3BhY2l0eT0iLjQiIGQ9Im0xMi44OTkgMjEuMjM1IDI2LjkzOC0zLjk4YTEuNiAxLjYgMCAwIDAgMS4zMjMtMS4xN2wyLjc4LTEwLjA2YTEuNTk1IDEuNTk1IDAgMCAwLTEuNzQtMi4wMTJMMTYuNDk4IDcuODFhNy4xOSA3LjE5IDAgMCAwLTUuNzc3IDUuMTkzTDcuMDEzIDI2LjQzOGMuNzQ0LTIuNzE3IDEuMjAyLTQuMzU1IDUuODg2LTUuMjAzIi8+PHBhdGggZmlsbD0idXJsKCNpN2ZhMWMxLWcpIiBkPSJNMTIuODk5IDIxLjIzNmMtMy45MDEuNzA2LTQuODcgMS45NjItNS41MTQgMy45MzJMNC4yNzkgMzYuNTc3cy45OTItMy42MzMgNS43OTYtNC40MWwxOC4zNTItMi42NzMuMTM2LS4wMjJhMS43MSAxLjcxIDAgMCAwIDEuMzg4LTEuMjQ0bDIuNzMtOS45MTV6Ii8+PHBhdGggZmlsbD0idXJsKCNpN2ZhMWMxLWgpIiBmaWxsLW9wYWNpdHk9Ii4yIiBkPSJNMTIuODk5IDIxLjIzNmMtMy45MDEuNzA2LTQuODcgMS45NjItNS41MTQgMy45MzJMNC4yNzkgMzYuNTc3cy45OTItMy42MzMgNS43OTYtNC40MWwxOC4zNTItMi42NzMuMTM2LS4wMjJhMS43MSAxLjcxIDAgMCAwIDEuMzg4LTEuMjQ0bDIuNzMtOS45MTV6Ii8+PHBhdGggZmlsbD0idXJsKCNpN2ZhMWMxLWkpIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xMC4wNzUgMzIuMTY3Yy00LjA2LjY1Ny01LjM5MiAzLjM0NS01LjcxIDQuMTY0YTUuNjMgNS42MyAwIDAgMCA0LjYzOCA3LjU5Yy43OTIuMTE0IDEuNjg4LjEwOCAyLjY5Mi0uMDM5bDQuNjEzLS42MzdhMi45MiAyLjkyIDAgMCAwIDIuNDIxLTIuMTI3bDIuODk0LTEwLjYzMy0xMS41NDcgMS42ODN6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9Imk3ZmExYzEtYSIgeDE9IjEyLjk1MyIgeDI9IjEyLjk1MyIgeTE9IjQ0LjAwMSIgeTI9IjI5LjQ1NyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iLjA1NiIgc3RvcC1jb2xvcj0iIzJBQUM5NCIvPjxzdG9wIG9mZnNldD0iLjE1NSIgc3RvcC1jb2xvcj0iIzIzOUM4NyIvPjxzdG9wIG9mZnNldD0iLjM3MiIgc3RvcC1jb2xvcj0iIzE3N0U3MSIvPjxzdG9wIG9mZnNldD0iLjU4OCIgc3RvcC1jb2xvcj0iIzBFNjk2MSIvPjxzdG9wIG9mZnNldD0iLjc5OSIgc3RvcC1jb2xvcj0iIzA5NUQ1NyIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzA4NTk1NCIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJpN2ZhMWMxLWIiIHgxPSIzMS4zMzEiIHgyPSIxNy4yODYiIHkxPSIzMy40NDgiIHkyPSIxOC4xNzMiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9Ii4wNDIiIHN0b3AtY29sb3I9IiNBQkU4OEUiLz48c3RvcCBvZmZzZXQ9Ii41NDkiIHN0b3AtY29sb3I9IiMyQUFBOTIiLz48c3RvcCBvZmZzZXQ9Ii45MDYiIHN0b3AtY29sb3I9IiMxMTc4NjUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iaTdmYTFjMS1jIiB4MT0iLTMuMTgyIiB4Mj0iMTAuMTgzIiB5MT0iMzIuNzA2IiB5Mj0iMjguMTQ4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iIzZBRDZGOSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzZBRDZGOSIgc3RvcC1vcGFjaXR5PSIwIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9Imk3ZmExYzEtZCIgeDE9IjcuMDEzIiB4Mj0iNDIuNTg5IiB5MT0iMTUuMjE5IiB5Mj0iMTUuMjE5IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuMDQzIiBzdG9wLWNvbG9yPSIjMjVGRkQ0Ii8+PHN0b3Agb2Zmc2V0PSIuODc0IiBzdG9wLWNvbG9yPSIjNTVEREI5Ii8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9Imk3ZmExYzEtZSIgeDE9IjcuMDEzIiB4Mj0iMzkuMDYiIHkxPSIxMC4yNDciIHkyPSIyNS4xMjgiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBzdG9wLWNvbG9yPSIjNkFENkY5Ii8+PHN0b3Agb2Zmc2V0PSIuMjMiIHN0b3AtY29sb3I9IiM2MEU5RDAiLz48c3RvcCBvZmZzZXQ9Ii42NTEiIHN0b3AtY29sb3I9IiM2REU5QkIiLz48c3RvcCBvZmZzZXQ9Ii45OTQiIHN0b3AtY29sb3I9IiNBQkU4OEUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iaTdmYTFjMS1mIiB4MT0iOS45NzgiIHgyPSIyNy40MDQiIHkxPSIxMy4wMzEiIHkyPSIxNi44ODUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9IjAiLz48c3RvcCBvZmZzZXQ9Ii40NTkiIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iMCIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJpN2ZhMWMxLWciIHgxPSIxNS43NTYiIHgyPSIxNi4xNjgiIHkxPSIyNy45NiIgeTI9IjE1Ljc0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuMjA1IiBzdG9wLWNvbG9yPSIjMDYzRDNCIiBzdG9wLW9wYWNpdHk9IjAiLz48c3RvcCBvZmZzZXQ9Ii41ODYiIHN0b3AtY29sb3I9IiMwNjNEM0IiIHN0b3Atb3BhY2l0eT0iLjIzNyIvPjxzdG9wIG9mZnNldD0iLjg3MiIgc3RvcC1jb2xvcj0iIzA2M0QzQiIgc3RvcC1vcGFjaXR5PSIuNzUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iaTdmYTFjMS1oIiB4MT0iMi44MSIgeDI9IjE3LjcwMSIgeTE9IjI2Ljc0NCIgeTI9IjI5LjU0NSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iMCIvPjxzdG9wIG9mZnNldD0iLjQ1OSIgc3RvcC1jb2xvcj0iI2ZmZiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ZmZiIgc3RvcC1vcGFjaXR5PSIwIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9Imk3ZmExYzEtaSIgeDE9IjEzLjU2NyIgeDI9IjEwLjY2MiIgeTE9IjM5Ljk3IiB5Mj0iMjUuNzY0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuMDY0IiBzdG9wLWNvbG9yPSIjMDYzRDNCIiBzdG9wLW9wYWNpdHk9IjAiLz48c3RvcCBvZmZzZXQ9Ii4xNyIgc3RvcC1jb2xvcj0iIzA2M0QzQiIgc3RvcC1vcGFjaXR5PSIuMTM1Ii8+PHN0b3Agb2Zmc2V0PSIuNTYyIiBzdG9wLWNvbG9yPSIjMDYzRDNCIiBzdG9wLW9wYWNpdHk9Ii41OTkiLz48c3RvcCBvZmZzZXQ9Ii44NSIgc3RvcC1jb2xvcj0iIzA2M0QzQiIgc3RvcC1vcGFjaXR5PSIuOSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzA2M0QzQiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjwvc3ZnPg==", + "name": "Microsoft-Fabric", + "category": "Analytics", + }, + "ai_foundry": { + "b64": "PHN2ZyBpZD0idXVpZC02YjgzODBjMy0wZWU1LTRjNDQtOTJhMi1mMTg1YzgyZGI2YmEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjE4IiBoZWlnaHQ9IjE4IiB2aWV3Qm94PSIwIDAgMTggMTgiPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0idXVpZC0wNTg3NmM3Mi04ZjI2LTQwZGEtOTk2ZS1hNDg4MTcyZWMwNzIiIHgxPSItNjAzLjU2MyIgeTE9Ii0yMTguMzc4IiB4Mj0iLTYwNi42IiB5Mj0iLTIwNi4yMiIgZ3JhZGllbnRUcmFuc2Zvcm09InRyYW5zbGF0ZSg2MTcuMTI2IC0yMDUuNzU4KSBzY2FsZSgxIC0xKSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzcxMjU3NSIgLz48c3RvcCBvZmZzZXQ9Ii4wOSIgc3RvcC1jb2xvcj0iIzlhMjg4NCIgLz48c3RvcCBvZmZzZXQ9Ii4xOCIgc3RvcC1jb2xvcj0iI2JmMmM5MiIgLz48c3RvcCBvZmZzZXQ9Ii4yNyIgc3RvcC1jb2xvcj0iI2RhMmU5YyIgLz48c3RvcCBvZmZzZXQ9Ii4zNCIgc3RvcC1jb2xvcj0iI2ViMzBhMiIgLz48c3RvcCBvZmZzZXQ9Ii40IiBzdG9wLWNvbG9yPSIjZjEzMWE1IiAvPjxzdG9wIG9mZnNldD0iLjUiIHN0b3AtY29sb3I9IiNlYzMwYTMiIC8+PHN0b3Agb2Zmc2V0PSIuNjEiIHN0b3AtY29sb3I9IiNkZjJmOWUiIC8+PHN0b3Agb2Zmc2V0PSIuNzIiIHN0b3AtY29sb3I9IiNjOTJkOTYiIC8+PHN0b3Agb2Zmc2V0PSIuODMiIHN0b3AtY29sb3I9IiNhYTJhOGEiIC8+PHN0b3Agb2Zmc2V0PSIuOTUiIHN0b3AtY29sb3I9IiM4MzI2N2MiIC8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNzEyNTc1IiAvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJ1dWlkLWM0YTJmNjI3LWQ3MzAtNDQ3ZS05MTUyLTYyMDA5YzY0YzM2MSIgeDE9Ii02MDIuNDEyIiB5MT0iLTIwNi4wMjUiIHgyPSItNjAyLjQxMiIgeTI9Ii0yMjMuMTc1IiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDYxNy4xMjYgLTIwNS43NTgpIHNjYWxlKDEgLTEpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZGE3ZWQwIiAvPjxzdG9wIG9mZnNldD0iLjA4IiBzdG9wLWNvbG9yPSIjYjE3YmQ1IiAvPjxzdG9wIG9mZnNldD0iLjE5IiBzdG9wLWNvbG9yPSIjODc3OGRiIiAvPjxzdG9wIG9mZnNldD0iLjMiIHN0b3AtY29sb3I9IiM2Mjc2ZTEiIC8+PHN0b3Agb2Zmc2V0PSIuNDEiIHN0b3AtY29sb3I9IiM0NTc0ZTUiIC8+PHN0b3Agb2Zmc2V0PSIuNTQiIHN0b3AtY29sb3I9IiMyZTcyZTgiIC8+PHN0b3Agb2Zmc2V0PSIuNjciIHN0b3AtY29sb3I9IiMxZDcxZWIiIC8+PHN0b3Agb2Zmc2V0PSIuODEiIHN0b3AtY29sb3I9IiMxNDcxZWMiIC8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMTE3MWVkIiAvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJ1dWlkLTVhNGNmMjE1LTQ5MzItNGYxMi04YWYxLTFiNjgzM2RmMjU5YyIgeDE9Ii02MDMuNDM4IiB5MT0iLTIwNi40MTQiIHgyPSItNjE0LjgwNyIgeTI9Ii0yMjQuNjQ0IiBncmFkaWVudFRyYW5zZm9ybT0idHJhbnNsYXRlKDYxNy4xMjYgLTIwNS43NTgpIHNjYWxlKDEgLTEpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZGE3ZWQwIiAvPjxzdG9wIG9mZnNldD0iLjA1IiBzdG9wLWNvbG9yPSIjYjc3YmQ0IiAvPjxzdG9wIG9mZnNldD0iLjExIiBzdG9wLWNvbG9yPSIjOTA3OWRhIiAvPjxzdG9wIG9mZnNldD0iLjE4IiBzdG9wLWNvbG9yPSIjNmU3N2RmIiAvPjxzdG9wIG9mZnNldD0iLjI1IiBzdG9wLWNvbG9yPSIjNTE3NWUzIiAvPjxzdG9wIG9mZnNldD0iLjMzIiBzdG9wLWNvbG9yPSIjMzk3M2U3IiAvPjxzdG9wIG9mZnNldD0iLjQyIiBzdG9wLWNvbG9yPSIjMjc3MmU5IiAvPjxzdG9wIG9mZnNldD0iLjU0IiBzdG9wLWNvbG9yPSIjMWE3MWViIiAvPjxzdG9wIG9mZnNldD0iLjY4IiBzdG9wLWNvbG9yPSIjMTM3MWVjIiAvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzExNzFlZCIgLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cGF0aCBkPSJtMTIuMDYxLjAxMmMuNTM0LDAsMS4wMDguNDAxLDEuMTc4Ljk4NHMxLjE2Niw0LjE5LDEuMTY2LDQuMTl2Ny4xNjZoLTMuNjA3bC4wNzMtMTIuMzUyaDEuMTl2LjAxMloiIGZpbGw9InVybCgjdXVpZC0wNTg3NmM3Mi04ZjI2LTQwZGEtOTk2ZS1hNDg4MTcyZWMwNzIpIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0cm9rZS13aWR0aD0iMCIgLz48cGF0aCBkPSJtMTcuMzU2LDUuNjExYzAtLjI1NS0uMjA2LS40NDktLjQ0OS0uNDQ5aC0yLjEyNmMtMS40OTQsMC0yLjcwOSwxLjIxNS0yLjcwOSwyLjcwOXY0LjQ5NGgyLjU3NWMxLjQ5NCwwLDIuNzA5LTEuMjE1LDIuNzA5LTIuNzA5di00LjA0NVoiIGZpbGw9InVybCgjdXVpZC1jNGEyZjYyNy1kNzMwLTQ0N2UtOTE1Mi02MjAwOWM2NGMzNjEpIiBzdHJva2Utd2lkdGg9IjAiIC8+PHBhdGggZD0ibTEyLjA2MS4wMTJjLS40MTMsMC0uNzQxLjMyOC0uNzQxLjc0MWwtLjA3MywxMy42NGMwLDEuOTkyLTEuNjE1LDMuNjA3LTMuNjA3LDMuNjA3SDEuMDkzYy0uMzE2LDAtLjUyMi0uMzA0LS40MjUtLjU5NUw1LjkxNSwyLjQyOUM2LjQyNS45ODQsNy43ODUuMDEyLDkuMzE2LjAxMmgyLjc1Ny0uMDEyWiIgZmlsbD0idXJsKCN1dWlkLTVhNGNmMjE1LTQ5MzItNGYxMi04YWYxLTFiNjgzM2RmMjU5YykiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3Ryb2tlLXdpZHRoPSIwIiAvPjwvc3ZnPg==", + "name": "AI-Foundry", + "category": "AI + machine learning", + }, }