ALTER TABLE base_model_catalog ADD COLUMN IF NOT EXISTS invocation_name text; UPDATE base_model_catalog SET invocation_name = COALESCE( NULLIF(metadata->>'officialModelId', ''), NULLIF(provider_model_name, ''), canonical_model_key ) WHERE invocation_name IS NULL OR trim(invocation_name) = ''; UPDATE base_model_catalog SET display_name = COALESCE( NULLIF(metadata->>'officialDisplayName', ''), NULLIF(default_snapshot->>'displayName', ''), NULLIF(display_name, ''), invocation_name ) WHERE catalog_type = 'system'; ALTER TABLE base_model_catalog ALTER COLUMN invocation_name SET NOT NULL; CREATE INDEX IF NOT EXISTS idx_base_model_catalog_invocation_name ON base_model_catalog(invocation_name); CREATE TABLE IF NOT EXISTS model_compatibility_aliases ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), base_model_id uuid NOT NULL REFERENCES base_model_catalog(id) ON DELETE CASCADE, alias text NOT NULL, model_type text NOT NULL, active boolean NOT NULL DEFAULT true, expires_at timestamptz, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), CONSTRAINT model_compatibility_aliases_nonempty CHECK (trim(alias) <> ''), CONSTRAINT model_compatibility_aliases_unique UNIQUE (base_model_id, alias, model_type) ); CREATE INDEX IF NOT EXISTS idx_model_compatibility_aliases_lookup ON model_compatibility_aliases(alias, model_type) WHERE active = true; CREATE TABLE IF NOT EXISTS model_alias_usage_metrics ( alias text NOT NULL, canonical_model_key text NOT NULL, model_type text NOT NULL, hit_count bigint NOT NULL DEFAULT 0, first_used_at timestamptz NOT NULL DEFAULT now(), last_used_at timestamptz NOT NULL DEFAULT now(), PRIMARY KEY (alias, canonical_model_key, model_type) ); -- Preserve unambiguous historical card/call names for the 14-day compatibility -- window. Ambiguous names are deliberately not inferred: they must be resolved -- to one canonical identity by an administrator before they can be registered. WITH alias_candidates AS ( SELECT b.id AS base_model_id, old_name.alias, model_type.value AS model_type, b.invocation_name FROM base_model_catalog b CROSS JOIN LATERAL jsonb_array_elements_text(b.model_type) AS model_type(value) CROSS JOIN LATERAL ( SELECT b.display_name AS alias UNION SELECT b.canonical_model_key AS alias ) old_name WHERE trim(COALESCE(old_name.alias, '')) <> '' AND old_name.alias <> b.invocation_name ), unambiguous AS ( SELECT alias, model_type, min(base_model_id::text)::uuid AS base_model_id FROM alias_candidates GROUP BY alias, model_type HAVING count(DISTINCT invocation_name) = 1 ) INSERT INTO model_compatibility_aliases (base_model_id, alias, model_type, expires_at) SELECT base_model_id, alias, model_type, now() + interval '14 days' FROM unambiguous ON CONFLICT (base_model_id, alias, model_type) DO NOTHING; -- Keep the old platform model_name/model_alias values as explicit compatibility -- aliases before canonical invocation names are written to platform_models. WITH platform_alias_candidates AS ( SELECT b.id AS base_model_id, old_name.alias, model_type.value AS model_type, b.invocation_name FROM platform_models pm JOIN base_model_catalog b ON b.id = pm.base_model_id CROSS JOIN LATERAL jsonb_array_elements_text(pm.model_type) AS model_type(value) CROSS JOIN LATERAL ( SELECT pm.model_name AS alias UNION SELECT pm.model_alias AS alias ) old_name WHERE trim(COALESCE(old_name.alias, '')) <> '' AND old_name.alias <> b.invocation_name ), unambiguous AS ( SELECT alias, model_type, min(base_model_id::text)::uuid AS base_model_id FROM platform_alias_candidates GROUP BY alias, model_type HAVING count(DISTINCT invocation_name) = 1 ) INSERT INTO model_compatibility_aliases (base_model_id, alias, model_type, expires_at) SELECT base_model_id, alias, model_type, now() + interval '14 days' FROM unambiguous ON CONFLICT (base_model_id, alias, model_type) DO NOTHING; WITH ranked_targets AS ( SELECT pm.id, b.invocation_name, COALESCE(NULLIF(b.display_name, ''), b.invocation_name) AS display_name, row_number() OVER ( PARTITION BY pm.platform_id, b.invocation_name ORDER BY CASE WHEN pm.model_name = b.invocation_name THEN 0 ELSE 1 END, pm.created_at ASC, pm.id ASC ) AS identity_rank FROM platform_models pm JOIN base_model_catalog b ON b.id = pm.base_model_id ) UPDATE platform_models pm SET model_name = target.invocation_name, model_alias = target.invocation_name, display_name = target.display_name, updated_at = now() FROM ranked_targets target WHERE target.id = pm.id AND target.identity_rank = 1 AND NOT EXISTS ( SELECT 1 FROM platform_models conflict WHERE conflict.platform_id = pm.platform_id AND conflict.id <> pm.id AND conflict.model_name = target.invocation_name ); UPDATE base_model_catalog SET default_snapshot = default_snapshot || jsonb_build_object( 'invocationName', invocation_name, 'modelAlias', invocation_name, 'displayName', display_name ) WHERE catalog_type = 'system' AND COALESCE(default_snapshot, '{}'::jsonb) <> '{}'::jsonb; CREATE OR REPLACE FUNCTION fill_system_base_model_default_snapshot() RETURNS trigger AS $$ BEGIN IF NEW.catalog_type = 'system' AND NEW.default_snapshot IS NULL THEN NEW.default_snapshot = jsonb_build_object( 'providerKey', NEW.provider_key, 'canonicalModelKey', NEW.canonical_model_key, 'invocationName', NEW.invocation_name, 'providerModelName', NEW.provider_model_name, 'modelType', NEW.model_type, 'modelAlias', NEW.invocation_name, 'displayName', NEW.display_name, 'capabilities', NEW.capabilities, 'baseBillingConfig', NEW.base_billing_config, 'defaultRateLimitPolicy', NEW.default_rate_limit_policy, 'pricingRuleSetId', COALESCE(NEW.pricing_rule_set_id::text, ''), 'runtimePolicySetId', COALESCE(NEW.runtime_policy_set_id::text, ''), 'runtimePolicyOverride', NEW.runtime_policy_override, 'metadata', NEW.metadata, 'pricingVersion', NEW.pricing_version, 'status', NEW.status ); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql;