fix gateway loopback validation chains
This commit is contained in:
@@ -376,7 +376,7 @@ CREATE TABLE IF NOT EXISTS platform_models (
|
||||
base_model_id uuid REFERENCES base_model_catalog(id) ON DELETE SET NULL,
|
||||
model_name text NOT NULL,
|
||||
model_alias text,
|
||||
model_type text NOT NULL,
|
||||
model_type jsonb NOT NULL DEFAULT '[]'::jsonb,
|
||||
display_name text NOT NULL DEFAULT '',
|
||||
capability_override jsonb NOT NULL DEFAULT '{}'::jsonb,
|
||||
capabilities jsonb NOT NULL DEFAULT '{}'::jsonb,
|
||||
@@ -391,14 +391,17 @@ CREATE TABLE IF NOT EXISTS platform_models (
|
||||
enabled boolean NOT NULL DEFAULT true,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
UNIQUE(platform_id, model_name, model_type)
|
||||
UNIQUE(platform_id, model_name)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_base
|
||||
ON platform_models(base_model_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_lookup
|
||||
ON platform_models(model_type, model_name, enabled);
|
||||
ON platform_models(model_name, enabled);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_model_type
|
||||
ON platform_models USING gin(model_type);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_alias
|
||||
ON platform_models(model_alias);
|
||||
|
||||
@@ -323,7 +323,7 @@ CREATE TABLE IF NOT EXISTS platform_models (
|
||||
base_model_id uuid REFERENCES base_model_catalog(id) ON DELETE SET NULL,
|
||||
model_name text NOT NULL,
|
||||
model_alias text,
|
||||
model_type text NOT NULL,
|
||||
model_type jsonb NOT NULL DEFAULT '[]'::jsonb,
|
||||
display_name text NOT NULL DEFAULT '',
|
||||
capability_override jsonb NOT NULL DEFAULT '{}'::jsonb,
|
||||
capabilities jsonb NOT NULL DEFAULT '{}'::jsonb,
|
||||
@@ -338,7 +338,7 @@ CREATE TABLE IF NOT EXISTS platform_models (
|
||||
enabled boolean NOT NULL DEFAULT true,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
UNIQUE(platform_id, model_name, model_type)
|
||||
UNIQUE(platform_id, model_name)
|
||||
);
|
||||
|
||||
ALTER TABLE IF EXISTS platform_models
|
||||
@@ -636,7 +636,10 @@ CREATE INDEX IF NOT EXISTS idx_gateway_recharge_orders_user
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_base
|
||||
ON platform_models(base_model_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_lookup
|
||||
ON platform_models(model_type, model_name, enabled);
|
||||
ON platform_models(model_name, enabled);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_model_type
|
||||
ON platform_models USING gin(model_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_alias
|
||||
ON platform_models(model_alias);
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_capabilities
|
||||
|
||||
@@ -199,7 +199,19 @@ INSERT INTO platform_models (
|
||||
platform_id, base_model_id, model_name, model_alias, model_type, display_name,
|
||||
capabilities, pricing_mode, billing_config, retry_policy, rate_limit_policy, enabled
|
||||
)
|
||||
SELECT p.id, b.id, b.provider_model_name, b.canonical_model_key, b.model_type, b.display_name,
|
||||
SELECT p.id, b.id, b.provider_model_name, b.canonical_model_key,
|
||||
CASE b.model_type
|
||||
WHEN 'chat' THEN '["text_generate"]'::jsonb
|
||||
WHEN 'text' THEN '["text_generate"]'::jsonb
|
||||
WHEN 'responses' THEN '["text_generate"]'::jsonb
|
||||
WHEN 'image' THEN '["image_generate","image_edit"]'::jsonb
|
||||
WHEN 'images.generations' THEN '["image_generate"]'::jsonb
|
||||
WHEN 'images.edits' THEN '["image_edit"]'::jsonb
|
||||
WHEN 'video' THEN '["video_generate"]'::jsonb
|
||||
WHEN 'videos.generations' THEN '["video_generate"]'::jsonb
|
||||
ELSE jsonb_build_array(b.model_type)
|
||||
END,
|
||||
b.display_name,
|
||||
b.capabilities, 'inherit_discount', b.base_billing_config,
|
||||
'{"enabled":true,"maxAttempts":2}'::jsonb,
|
||||
b.default_rate_limit_policy,
|
||||
@@ -207,7 +219,7 @@ SELECT p.id, b.id, b.provider_model_name, b.canonical_model_key, b.model_type, b
|
||||
FROM integration_platforms p
|
||||
JOIN base_model_catalog b ON b.provider_key = p.provider
|
||||
WHERE p.platform_key IN ('openai-simulation', 'gemini-simulation')
|
||||
ON CONFLICT (platform_id, model_name, model_type) DO UPDATE
|
||||
ON CONFLICT (platform_id, model_name) DO UPDATE
|
||||
SET base_model_id = EXCLUDED.base_model_id,
|
||||
model_alias = EXCLUDED.model_alias,
|
||||
display_name = EXCLUDED.display_name,
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
DO $$
|
||||
DECLARE
|
||||
column_type text;
|
||||
BEGIN
|
||||
SELECT data_type
|
||||
INTO column_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'platform_models'
|
||||
AND column_name = 'model_type';
|
||||
|
||||
IF column_type IS DISTINCT FROM 'jsonb' THEN
|
||||
DROP INDEX IF EXISTS idx_platform_models_lookup;
|
||||
ALTER TABLE platform_models
|
||||
DROP CONSTRAINT IF EXISTS platform_models_platform_id_model_name_model_type_key;
|
||||
|
||||
ALTER TABLE platform_models
|
||||
ADD COLUMN IF NOT EXISTS model_type_next jsonb NOT NULL DEFAULT '[]'::jsonb;
|
||||
|
||||
UPDATE platform_models
|
||||
SET model_type_next = CASE trim(model_type)
|
||||
WHEN 'chat' THEN '["text_generate"]'::jsonb
|
||||
WHEN 'text' THEN '["text_generate"]'::jsonb
|
||||
WHEN 'responses' THEN '["text_generate"]'::jsonb
|
||||
WHEN 'image' THEN '["image_generate","image_edit"]'::jsonb
|
||||
WHEN 'images.generations' THEN '["image_generate"]'::jsonb
|
||||
WHEN 'images.edits' THEN '["image_edit"]'::jsonb
|
||||
WHEN 'video' THEN '["video_generate"]'::jsonb
|
||||
WHEN 'videos.generations' THEN '["video_generate"]'::jsonb
|
||||
ELSE jsonb_build_array(trim(model_type))
|
||||
END;
|
||||
|
||||
WITH ranked AS (
|
||||
SELECT id,
|
||||
first_value(id) OVER (
|
||||
PARTITION BY platform_id, model_name
|
||||
ORDER BY created_at ASC, id ASC
|
||||
) AS keep_id,
|
||||
row_number() OVER (
|
||||
PARTITION BY platform_id, model_name
|
||||
ORDER BY created_at ASC, id ASC
|
||||
) AS row_number
|
||||
FROM platform_models
|
||||
),
|
||||
merged AS (
|
||||
SELECT ranked.keep_id,
|
||||
jsonb_agg(DISTINCT type_value ORDER BY type_value) AS model_type
|
||||
FROM ranked
|
||||
JOIN platform_models model_row ON model_row.id = ranked.id
|
||||
CROSS JOIN LATERAL jsonb_array_elements_text(model_row.model_type_next) AS type_item(type_value)
|
||||
GROUP BY ranked.keep_id
|
||||
)
|
||||
UPDATE platform_models target
|
||||
SET model_type_next = merged.model_type
|
||||
FROM merged
|
||||
WHERE target.id = merged.keep_id;
|
||||
|
||||
WITH ranked AS (
|
||||
SELECT id,
|
||||
first_value(id) OVER (
|
||||
PARTITION BY platform_id, model_name
|
||||
ORDER BY created_at ASC, id ASC
|
||||
) AS keep_id,
|
||||
row_number() OVER (
|
||||
PARTITION BY platform_id, model_name
|
||||
ORDER BY created_at ASC, id ASC
|
||||
) AS row_number
|
||||
FROM platform_models
|
||||
)
|
||||
UPDATE gateway_access_rules rules
|
||||
SET resource_id = ranked.keep_id
|
||||
FROM ranked
|
||||
WHERE ranked.row_number > 1
|
||||
AND rules.resource_type = 'platform_model'
|
||||
AND rules.resource_id = ranked.id;
|
||||
|
||||
WITH ranked AS (
|
||||
SELECT id,
|
||||
row_number() OVER (
|
||||
PARTITION BY platform_id, model_name
|
||||
ORDER BY created_at ASC, id ASC
|
||||
) AS row_number
|
||||
FROM platform_models
|
||||
)
|
||||
DELETE FROM platform_models model_row
|
||||
USING ranked
|
||||
WHERE model_row.id = ranked.id
|
||||
AND ranked.row_number > 1;
|
||||
|
||||
ALTER TABLE platform_models DROP COLUMN model_type;
|
||||
ALTER TABLE platform_models RENAME COLUMN model_type_next TO model_type;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
UPDATE platform_models
|
||||
SET model_type = CASE
|
||||
WHEN jsonb_typeof(model_type) = 'array' THEN model_type
|
||||
WHEN jsonb_typeof(model_type) = 'string' THEN jsonb_build_array(model_type #>> '{}')
|
||||
ELSE '[]'::jsonb
|
||||
END;
|
||||
|
||||
UPDATE platform_models
|
||||
SET model_type = COALESCE((
|
||||
SELECT jsonb_agg(DISTINCT normalized_type ORDER BY normalized_type)
|
||||
FROM jsonb_array_elements_text(platform_models.model_type) AS item(model_type_value)
|
||||
CROSS JOIN LATERAL (
|
||||
VALUES
|
||||
(CASE item.model_type_value
|
||||
WHEN 'chat' THEN 'text_generate'
|
||||
WHEN 'text' THEN 'text_generate'
|
||||
WHEN 'responses' THEN 'text_generate'
|
||||
WHEN 'images.generations' THEN 'image_generate'
|
||||
WHEN 'images.edits' THEN 'image_edit'
|
||||
WHEN 'video' THEN 'video_generate'
|
||||
WHEN 'videos.generations' THEN 'video_generate'
|
||||
ELSE item.model_type_value
|
||||
END)
|
||||
) AS normalized(normalized_type)
|
||||
WHERE trim(normalized_type) <> ''
|
||||
), '[]'::jsonb);
|
||||
|
||||
UPDATE platform_models
|
||||
SET model_type = '["image_generate","image_edit"]'::jsonb
|
||||
WHERE model_type = '["image"]'::jsonb;
|
||||
|
||||
ALTER TABLE platform_models
|
||||
ALTER COLUMN model_type SET NOT NULL,
|
||||
ALTER COLUMN model_type SET DEFAULT '[]'::jsonb;
|
||||
|
||||
DROP INDEX IF EXISTS idx_platform_models_lookup;
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_lookup
|
||||
ON platform_models(model_name, enabled);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_platform_models_model_type
|
||||
ON platform_models USING gin(model_type);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_platform_models_platform_model_name
|
||||
ON platform_models(platform_id, model_name);
|
||||
@@ -0,0 +1,11 @@
|
||||
UPDATE platform_models m
|
||||
SET rate_limit_policy = '{}'::jsonb,
|
||||
updated_at = now()
|
||||
FROM base_model_catalog b,
|
||||
model_runtime_policy_sets rp
|
||||
WHERE m.base_model_id = b.id
|
||||
AND m.runtime_policy_set_id = rp.id
|
||||
AND m.runtime_policy_set_id IS NOT NULL
|
||||
AND m.runtime_policy_set_id IS DISTINCT FROM b.runtime_policy_set_id
|
||||
AND m.rate_limit_policy = b.default_rate_limit_policy
|
||||
AND rp.rate_limit_policy <> '{}'::jsonb;
|
||||
@@ -0,0 +1,108 @@
|
||||
DO $$
|
||||
DECLARE
|
||||
column_type text;
|
||||
BEGIN
|
||||
SELECT data_type
|
||||
INTO column_type
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'base_model_catalog'
|
||||
AND column_name = 'model_type';
|
||||
|
||||
IF column_type IS DISTINCT FROM 'jsonb' THEN
|
||||
DROP INDEX IF EXISTS idx_base_model_catalog_type;
|
||||
|
||||
ALTER TABLE base_model_catalog
|
||||
ADD COLUMN IF NOT EXISTS model_type_next jsonb NOT NULL DEFAULT '[]'::jsonb;
|
||||
|
||||
WITH source_types AS (
|
||||
SELECT id,
|
||||
CASE
|
||||
WHEN jsonb_typeof(capabilities->'originalTypes') = 'array' THEN capabilities->'originalTypes'
|
||||
WHEN jsonb_typeof(metadata->'originalTypes') = 'array' THEN metadata->'originalTypes'
|
||||
ELSE jsonb_build_array(model_type)
|
||||
END AS model_types
|
||||
FROM base_model_catalog
|
||||
),
|
||||
normalized_types AS (
|
||||
SELECT source_types.id, normalized.model_type
|
||||
FROM source_types
|
||||
CROSS JOIN LATERAL jsonb_array_elements_text(source_types.model_types) AS raw_type(model_type)
|
||||
CROSS JOIN LATERAL (
|
||||
SELECT 'text_generate' AS model_type
|
||||
WHERE raw_type.model_type IN ('chat', 'text', 'responses')
|
||||
UNION ALL SELECT 'image_generate'
|
||||
WHERE raw_type.model_type = 'image'
|
||||
UNION ALL SELECT 'image_edit'
|
||||
WHERE raw_type.model_type = 'image'
|
||||
UNION ALL SELECT 'image_generate'
|
||||
WHERE raw_type.model_type = 'images.generations'
|
||||
UNION ALL SELECT 'image_edit'
|
||||
WHERE raw_type.model_type = 'images.edits'
|
||||
UNION ALL SELECT 'video_generate'
|
||||
WHERE raw_type.model_type IN ('video', 'videos.generations')
|
||||
UNION ALL SELECT raw_type.model_type
|
||||
WHERE trim(raw_type.model_type) <> ''
|
||||
AND raw_type.model_type NOT IN (
|
||||
'chat', 'text', 'responses', 'image', 'images.generations', 'images.edits', 'video', 'videos.generations'
|
||||
)
|
||||
) AS normalized
|
||||
)
|
||||
UPDATE base_model_catalog target
|
||||
SET model_type_next = COALESCE((
|
||||
SELECT jsonb_agg(DISTINCT normalized_types.model_type ORDER BY normalized_types.model_type)
|
||||
FROM normalized_types
|
||||
WHERE normalized_types.id = target.id
|
||||
), '[]'::jsonb);
|
||||
|
||||
ALTER TABLE base_model_catalog DROP COLUMN model_type;
|
||||
ALTER TABLE base_model_catalog RENAME COLUMN model_type_next TO model_type;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
UPDATE base_model_catalog
|
||||
SET model_type = CASE
|
||||
WHEN jsonb_typeof(model_type) = 'array' THEN model_type
|
||||
WHEN jsonb_typeof(model_type) = 'string' THEN jsonb_build_array(model_type #>> '{}')
|
||||
ELSE '[]'::jsonb
|
||||
END;
|
||||
|
||||
UPDATE base_model_catalog
|
||||
SET default_snapshot = default_snapshot || jsonb_build_object('modelType', model_type)
|
||||
WHERE catalog_type = 'system'
|
||||
AND COALESCE(default_snapshot, '{}'::jsonb) <> '{}'::jsonb;
|
||||
|
||||
ALTER TABLE base_model_catalog
|
||||
ALTER COLUMN model_type SET NOT NULL,
|
||||
ALTER COLUMN model_type SET DEFAULT '[]'::jsonb;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_base_model_catalog_type
|
||||
ON base_model_catalog(provider_key, status);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_base_model_catalog_model_type
|
||||
ON base_model_catalog USING gin(model_type);
|
||||
|
||||
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,
|
||||
'providerModelName', NEW.provider_model_name,
|
||||
'modelType', NEW.model_type,
|
||||
'modelAlias', 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;
|
||||
@@ -0,0 +1,9 @@
|
||||
UPDATE platform_models m
|
||||
SET model_type = b.model_type,
|
||||
updated_at = now()
|
||||
FROM base_model_catalog b
|
||||
WHERE m.base_model_id = b.id
|
||||
AND jsonb_typeof(b.model_type) = 'array'
|
||||
AND jsonb_array_length(b.model_type) > 0
|
||||
AND m.model_type <> b.model_type
|
||||
AND COALESCE(m.capabilities, '{}'::jsonb) = COALESCE(b.capabilities, '{}'::jsonb);
|
||||
@@ -0,0 +1,48 @@
|
||||
ALTER TABLE gateway_wallet_accounts
|
||||
ADD COLUMN IF NOT EXISTS total_recharged numeric NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS total_spent numeric NOT NULL DEFAULT 0;
|
||||
|
||||
ALTER TABLE gateway_wallet_transactions
|
||||
ADD COLUMN IF NOT EXISTS account_id uuid REFERENCES gateway_wallet_accounts(id) ON DELETE CASCADE,
|
||||
ADD COLUMN IF NOT EXISTS direction text,
|
||||
ADD COLUMN IF NOT EXISTS balance_before numeric,
|
||||
ADD COLUMN IF NOT EXISTS idempotency_key text;
|
||||
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = 'gateway_wallet_transactions'
|
||||
AND column_name = 'wallet_account_id'
|
||||
) THEN
|
||||
EXECUTE 'UPDATE gateway_wallet_transactions SET account_id = wallet_account_id WHERE account_id IS NULL';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
UPDATE gateway_wallet_transactions
|
||||
SET direction = CASE
|
||||
WHEN transaction_type IN ('recharge', 'refund', 'credit') THEN 'credit'
|
||||
ELSE 'debit'
|
||||
END
|
||||
WHERE direction IS NULL;
|
||||
|
||||
UPDATE gateway_wallet_transactions
|
||||
SET balance_before = COALESCE(balance_after, 0) + CASE
|
||||
WHEN direction = 'debit' THEN COALESCE(amount, 0)
|
||||
ELSE -COALESCE(amount, 0)
|
||||
END
|
||||
WHERE balance_before IS NULL;
|
||||
|
||||
ALTER TABLE gateway_wallet_transactions
|
||||
ALTER COLUMN direction SET DEFAULT 'debit',
|
||||
ALTER COLUMN direction SET NOT NULL,
|
||||
ALTER COLUMN balance_before SET DEFAULT 0,
|
||||
ALTER COLUMN balance_before SET NOT NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_gateway_wallet_transactions_account
|
||||
ON gateway_wallet_transactions(account_id, created_at DESC);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uniq_gateway_wallet_tx_idempotency
|
||||
ON gateway_wallet_transactions(account_id, idempotency_key)
|
||||
WHERE idempotency_key IS NOT NULL;
|
||||
Reference in New Issue
Block a user