easyai-ai-gateway/apps/api/migrations/0059_responses_protocols_and_chains.sql

274 lines
12 KiB
SQL

CREATE TABLE IF NOT EXISTS gateway_response_chains (
public_response_id text PRIMARY KEY,
parent_response_id text REFERENCES gateway_response_chains(public_response_id) ON DELETE RESTRICT,
gateway_task_id uuid NOT NULL REFERENCES gateway_tasks(id) ON DELETE CASCADE,
gateway_user_id uuid REFERENCES gateway_users(id) ON DELETE SET NULL,
user_id text NOT NULL,
user_source text NOT NULL DEFAULT 'gateway',
gateway_tenant_id uuid REFERENCES gateway_tenants(id) ON DELETE SET NULL,
tenant_id text,
tenant_key text,
api_key_id text,
platform_id uuid NOT NULL REFERENCES integration_platforms(id) ON DELETE RESTRICT,
platform_model_id uuid NOT NULL REFERENCES platform_models(id) ON DELETE RESTRICT,
client_id text NOT NULL,
upstream_protocol text NOT NULL,
upstream_endpoint text NOT NULL,
upstream_response_id text,
request_snapshot jsonb NOT NULL DEFAULT '{}'::jsonb,
response_snapshot jsonb NOT NULL DEFAULT '{}'::jsonb,
internal_snapshot jsonb NOT NULL DEFAULT '{}'::jsonb,
created_at timestamptz NOT NULL DEFAULT now(),
expires_at timestamptz NOT NULL,
CONSTRAINT gateway_response_chains_public_id_check
CHECK (public_response_id ~ '^resp_[A-Za-z0-9_-]+$'),
CONSTRAINT gateway_response_chains_protocol_check
CHECK (upstream_protocol IN ('openai_chat_completions', 'openai_responses'))
);
ALTER TABLE gateway_response_chains
DROP CONSTRAINT IF EXISTS gateway_response_chains_public_id_check;
ALTER TABLE gateway_response_chains
ADD CONSTRAINT gateway_response_chains_public_id_check
CHECK (public_response_id ~ '^resp_[A-Za-z0-9_-]+$');
CREATE INDEX IF NOT EXISTS idx_gateway_response_chains_owner
ON gateway_response_chains(gateway_user_id, user_id, gateway_tenant_id, tenant_id, tenant_key);
CREATE INDEX IF NOT EXISTS idx_gateway_response_chains_expiry
ON gateway_response_chains(expires_at);
CREATE INDEX IF NOT EXISTS idx_gateway_response_chains_platform_model
ON gateway_response_chains(platform_model_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_gateway_response_chains_upstream_response
ON gateway_response_chains(upstream_response_id)
WHERE upstream_response_id IS NOT NULL;
-- Keep capability data provider-specific. A missing supportedApiProtocols field
-- intentionally remains legacy-compatible and means Chat Completions only.
UPDATE base_model_catalog
SET capabilities = jsonb_set(
capabilities,
'{text_generate,supportedApiProtocols}',
'["openai_chat_completions","openai_responses"]'::jsonb,
true
),
default_snapshot = CASE
WHEN COALESCE(default_snapshot, '{}'::jsonb) = '{}'::jsonb THEN default_snapshot
ELSE jsonb_set(
default_snapshot,
'{capabilities,text_generate,supportedApiProtocols}',
'["openai_chat_completions","openai_responses"]'::jsonb,
true
)
END,
updated_at = now()
WHERE provider_key = 'volces-openai'
AND provider_model_name = 'doubao-seed-2-0-pro-260215';
WITH provider AS (
SELECT id FROM model_catalog_providers
WHERE provider_key = 'aliyun-bailian-openai' OR provider_code = 'aliyun-bailian-openai'
LIMIT 1
), template AS (
SELECT * FROM base_model_catalog
WHERE provider_key = 'aliyun-bailian-openai'
AND provider_model_name IN ('qwen3.7-max', 'qwen3.7-plus')
ORDER BY CASE WHEN provider_model_name = 'qwen3.7-plus' THEN 0 ELSE 1 END
LIMIT 1
), payload AS (
SELECT
provider.id AS provider_id,
'aliyun-bailian-openai'::text AS provider_key,
'aliyun-bailian-openai:qwen3.7-plus'::text AS canonical_model_key,
'qwen3.7-plus'::text AS provider_model_name,
'["text_generate","tools_call"]'::jsonb AS model_type,
'Qwen3.7-Plus'::text AS display_name,
jsonb_set(
COALESCE(template.capabilities, '{"originalTypes":["text_generate","tools_call"],"text_generate":{"supportTool":true},"tools_call":{"supportTool":true}}'::jsonb),
'{text_generate,supportedApiProtocols}',
'["openai_chat_completions","openai_responses"]'::jsonb,
true
) AS capabilities,
COALESCE(template.base_billing_config, '{}'::jsonb) AS base_billing_config,
COALESCE(template.default_rate_limit_policy, '{}'::jsonb) AS default_rate_limit_policy,
COALESCE(template.metadata, '{}'::jsonb) || jsonb_build_object(
'alias', 'Qwen3.7-Plus',
'selectable', true,
'sourceProviderCode', 'aliyun-bailian-openai'
) AS metadata,
COALESCE(template.pricing_version, 1) AS pricing_version
FROM provider
LEFT JOIN template ON true
), snapshot AS (
SELECT payload.*,
jsonb_build_object(
'providerKey', provider_key,
'canonicalModelKey', canonical_model_key,
'providerModelName', provider_model_name,
'modelType', model_type,
'modelAlias', display_name,
'capabilities', capabilities,
'baseBillingConfig', base_billing_config,
'defaultRateLimitPolicy', default_rate_limit_policy,
'metadata', metadata,
'pricingVersion', pricing_version,
'status', 'active'
) AS default_snapshot
FROM payload
)
INSERT INTO base_model_catalog (
provider_id, provider_key, canonical_model_key, provider_model_name, model_type,
display_name, capabilities, base_billing_config, default_rate_limit_policy,
metadata, catalog_type, default_snapshot, pricing_version, status
)
SELECT provider_id, provider_key, canonical_model_key, provider_model_name, model_type,
display_name, capabilities, base_billing_config, default_rate_limit_policy,
metadata, 'system', default_snapshot, pricing_version, 'active'
FROM snapshot
ON CONFLICT (canonical_model_key) DO UPDATE
SET provider_id = EXCLUDED.provider_id,
provider_key = EXCLUDED.provider_key,
provider_model_name = EXCLUDED.provider_model_name,
model_type = EXCLUDED.model_type,
display_name = EXCLUDED.display_name,
capabilities = jsonb_set(
base_model_catalog.capabilities,
'{text_generate,supportedApiProtocols}',
'["openai_chat_completions","openai_responses"]'::jsonb,
true
),
default_snapshot = EXCLUDED.default_snapshot,
status = 'active',
updated_at = now();
INSERT INTO model_catalog_providers (
provider_key, provider_code, provider_type, display_name, icon_path, source,
capability_schema, default_rate_limit_policy, metadata, status
) VALUES (
'deepseek-openai', 'deepseek-openai', 'openai', 'DeepSeek',
'https://static.51easyai.com/deepseek-color%20%281%29.webp',
'gateway.responses-protocol-migration', '{}'::jsonb, '{}'::jsonb,
'{"seed":"responses-protocols","sourceSpecType":"openai"}'::jsonb, 'active'
)
ON CONFLICT (provider_key) DO UPDATE
SET provider_code = EXCLUDED.provider_code,
provider_type = EXCLUDED.provider_type,
display_name = EXCLUDED.display_name,
icon_path = EXCLUDED.icon_path,
metadata = model_catalog_providers.metadata || EXCLUDED.metadata,
status = 'active',
updated_at = now();
WITH provider AS (
SELECT id FROM model_catalog_providers
WHERE provider_key = 'deepseek-openai' OR provider_code = 'deepseek-openai'
LIMIT 1
), template AS (
SELECT * FROM base_model_catalog
WHERE provider_model_name = 'deepseek-v4-pro'
ORDER BY CASE WHEN provider_key = 'deepseek-openai' THEN 0 ELSE 1 END
LIMIT 1
), payload AS (
SELECT
provider.id AS provider_id,
'deepseek-openai'::text AS provider_key,
'deepseek-openai:deepseek-v4-pro'::text AS canonical_model_key,
'deepseek-v4-pro'::text AS provider_model_name,
'["text_generate","tools_call"]'::jsonb AS model_type,
'DeepSeek-V4-Pro'::text AS display_name,
jsonb_set(
COALESCE(template.capabilities, '{"originalTypes":["text_generate","tools_call"],"text_generate":{"supportTool":true},"tools_call":{"supportTool":true}}'::jsonb),
'{text_generate,supportedApiProtocols}',
'["openai_chat_completions","anthropic_messages"]'::jsonb,
true
) AS capabilities,
COALESCE(template.base_billing_config, '{}'::jsonb) AS base_billing_config,
COALESCE(template.default_rate_limit_policy, '{}'::jsonb) AS default_rate_limit_policy,
COALESCE(template.metadata, '{}'::jsonb) || jsonb_build_object(
'alias', 'DeepSeek-V4-Pro',
'selectable', true,
'sourceProviderCode', 'deepseek-openai',
'sourceProviderName', 'DeepSeek 官网'
) AS metadata,
COALESCE(template.pricing_version, 1) AS pricing_version
FROM provider
LEFT JOIN template ON true
), snapshot AS (
SELECT payload.*,
jsonb_build_object(
'providerKey', provider_key,
'canonicalModelKey', canonical_model_key,
'providerModelName', provider_model_name,
'modelType', model_type,
'modelAlias', display_name,
'capabilities', capabilities,
'baseBillingConfig', base_billing_config,
'defaultRateLimitPolicy', default_rate_limit_policy,
'metadata', metadata,
'pricingVersion', pricing_version,
'status', 'active'
) AS default_snapshot
FROM payload
)
INSERT INTO base_model_catalog (
provider_id, provider_key, canonical_model_key, provider_model_name, model_type,
display_name, capabilities, base_billing_config, default_rate_limit_policy,
metadata, catalog_type, default_snapshot, pricing_version, status
)
SELECT provider_id, provider_key, canonical_model_key, provider_model_name, model_type,
display_name, capabilities, base_billing_config, default_rate_limit_policy,
metadata, 'system', default_snapshot, pricing_version, 'active'
FROM snapshot
ON CONFLICT (canonical_model_key) DO UPDATE
SET provider_id = EXCLUDED.provider_id,
provider_key = EXCLUDED.provider_key,
provider_model_name = EXCLUDED.provider_model_name,
model_type = EXCLUDED.model_type,
display_name = EXCLUDED.display_name,
capabilities = jsonb_set(
base_model_catalog.capabilities,
'{text_generate,supportedApiProtocols}',
'["openai_chat_completions","anthropic_messages"]'::jsonb,
true
),
default_snapshot = EXCLUDED.default_snapshot,
status = 'active',
updated_at = now();
UPDATE platform_models model
SET base_model_id = base.id,
model_name = base.provider_model_name,
provider_model_name = CASE
WHEN platform.provider = 'volces-openai' THEN 'doubao-seed-2-0-pro-260215'
WHEN platform.provider = 'aliyun-bailian-openai' THEN 'qwen3.7-plus'
WHEN platform.provider = 'deepseek-openai' THEN 'deepseek-v4-pro'
ELSE model.provider_model_name
END,
model_alias = CASE
WHEN platform.provider = 'volces-openai' THEN 'Doubao Seed 2.0 Pro'
WHEN platform.provider = 'aliyun-bailian-openai' THEN 'Qwen3.7-Plus'
WHEN platform.provider = 'deepseek-openai' THEN 'DeepSeek-V4-Pro'
END,
display_name = CASE
WHEN platform.provider = 'volces-openai' THEN 'Doubao Seed 2.0 Pro'
WHEN platform.provider = 'aliyun-bailian-openai' THEN 'Qwen3.7-Plus'
WHEN platform.provider = 'deepseek-openai' THEN 'DeepSeek-V4-Pro'
END,
model_type = '["text_generate","tools_call"]'::jsonb,
enabled = true,
updated_at = now()
FROM integration_platforms platform, base_model_catalog base
WHERE model.platform_id = platform.id
AND (
(platform.provider = 'volces-openai'
AND base.canonical_model_key = 'volces-openai:doubao-seed-2-0-pro-260215'
AND (model.model_name = 'doubao-seed-2-0-pro-260215' OR model.provider_model_name = 'doubao-seed-2-0-pro-260215' OR model.model_alias = 'Doubao Seed 2.0 Pro'))
OR
(platform.provider = 'aliyun-bailian-openai'
AND base.canonical_model_key = 'aliyun-bailian-openai:qwen3.7-plus'
AND (model.model_name = 'qwen3.7-plus' OR model.provider_model_name = 'qwen3.7-plus' OR model.display_name = 'Qwen3.7-Plus'))
OR
(platform.provider = 'deepseek-openai'
AND base.canonical_model_key = 'deepseek-openai:deepseek-v4-pro'
AND (model.model_name = 'deepseek-v4-pro' OR model.provider_model_name = 'deepseek-v4-pro' OR model.display_name = 'DeepSeek-V4-Pro'))
);