easyai-ai-gateway/apps/api/migrations/0054_coding_agent_text_models.sql

590 lines
20 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Add the latest coding-agent text models from server-main and official docs.
-- Alias values that become EasyAI-facing model names must avoid spaces.
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 (
'moonshot-openai',
'moonshot-openai',
'openai',
'KimiOpenAI兼容',
'https://static.51easyai.com/kimi-logo-124.png',
'server-main.integration-platform',
'{}'::jsonb,
'{}'::jsonb,
jsonb_build_object(
'seed', 'server-main-provider-defaults',
'syncSource', 'server-main.integration-platform',
'sourceCode', 'moonshot-openai',
'sourceSpecType', 'openai'
),
'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,
source = EXCLUDED.source,
metadata = model_catalog_providers.metadata || EXCLUDED.metadata,
status = EXCLUDED.status,
updated_at = now();
UPDATE model_catalog_providers
SET default_base_url = 'https://api.moonshot.cn/v1',
default_auth_type = 'APIKey',
metadata = metadata || jsonb_build_object(
'defaultConnectionSource', 'server-main.integration-platform',
'defaultBaseUrlSynced', 'https://api.moonshot.cn/v1',
'defaultAuthTypeSynced', 'APIKey'
),
updated_at = now()
WHERE provider_key = 'moonshot-openai';
UPDATE base_model_catalog b
SET canonical_model_key = 'easyai:Doubao-Seed-2.0-Code-Preview',
updated_at = now()
WHERE b.canonical_model_key = 'easyai:Doubao Seed 2.0 Code Preview'
AND NOT EXISTS (
SELECT 1
FROM base_model_catalog existing
WHERE existing.canonical_model_key = 'easyai:Doubao-Seed-2.0-Code-Preview'
);
WITH doubao_alias(old_alias, new_alias, volces_model_name) AS (
VALUES (
'Doubao Seed 2.0 Code Preview',
'Doubao-Seed-2.0-Code-Preview',
'doubao-seed-2-0-code-preview-260215'
)
),
targets AS (
SELECT b.id,
b.provider_key,
b.canonical_model_key,
b.provider_model_name,
d.old_alias,
d.new_alias,
d.volces_model_name
FROM base_model_catalog b
CROSS JOIN doubao_alias d
WHERE (
b.provider_key = 'easyai'
AND b.provider_model_name IN (d.old_alias, d.new_alias)
)
OR (
b.provider_key = 'volces-openai'
AND b.provider_model_name = d.volces_model_name
)
)
UPDATE base_model_catalog b
SET provider_model_name = CASE
WHEN targets.provider_key = 'easyai' THEN targets.new_alias
ELSE b.provider_model_name
END,
display_name = targets.new_alias,
metadata = jsonb_set(
jsonb_set(
COALESCE(b.metadata, '{}'::jsonb),
'{alias}',
to_jsonb(targets.new_alias),
true
),
'{rawModel}',
COALESCE(b.metadata -> 'rawModel', '{}'::jsonb)
|| jsonb_build_object('alias', targets.new_alias)
|| CASE
WHEN targets.provider_key = 'easyai'
THEN jsonb_build_object('name', targets.new_alias)
ELSE '{}'::jsonb
END,
true
),
default_snapshot = CASE
WHEN b.default_snapshot IS NULL THEN NULL
ELSE jsonb_set(
COALESCE(b.default_snapshot, '{}'::jsonb) || jsonb_build_object(
'canonicalModelKey',
CASE
WHEN targets.provider_key = 'easyai'
THEN 'easyai:' || targets.new_alias
ELSE b.canonical_model_key
END,
'providerModelName',
CASE
WHEN targets.provider_key = 'easyai' THEN targets.new_alias
ELSE b.provider_model_name
END,
'modelAlias',
targets.new_alias,
'displayName',
targets.new_alias
),
'{metadata}',
jsonb_set(
jsonb_set(
COALESCE(b.default_snapshot -> 'metadata', '{}'::jsonb),
'{alias}',
to_jsonb(targets.new_alias),
true
),
'{rawModel}',
COALESCE(b.default_snapshot -> 'metadata' -> 'rawModel', '{}'::jsonb)
|| jsonb_build_object('alias', targets.new_alias)
|| CASE
WHEN targets.provider_key = 'easyai'
THEN jsonb_build_object('name', targets.new_alias)
ELSE '{}'::jsonb
END,
true
),
true
)
END,
updated_at = now()
FROM targets
WHERE b.id = targets.id;
WITH doubao_alias(old_alias, new_alias, volces_model_name) AS (
VALUES (
'Doubao Seed 2.0 Code Preview',
'Doubao-Seed-2.0-Code-Preview',
'doubao-seed-2-0-code-preview-260215'
)
)
UPDATE platform_models pm
SET model_name = doubao_alias.new_alias,
updated_at = now()
FROM integration_platforms p, doubao_alias
WHERE pm.platform_id = p.id
AND p.provider = 'easyai'
AND pm.model_name = doubao_alias.old_alias
AND NOT EXISTS (
SELECT 1
FROM platform_models existing
WHERE existing.platform_id = pm.platform_id
AND existing.model_name = doubao_alias.new_alias
);
WITH doubao_alias(old_alias, new_alias, volces_model_name) AS (
VALUES (
'Doubao Seed 2.0 Code Preview',
'Doubao-Seed-2.0-Code-Preview',
'doubao-seed-2-0-code-preview-260215'
)
)
UPDATE platform_models pm
SET provider_model_name = CASE
WHEN p.provider = 'easyai' THEN doubao_alias.new_alias
ELSE pm.provider_model_name
END,
model_alias = doubao_alias.new_alias,
display_name = doubao_alias.new_alias,
updated_at = now()
FROM integration_platforms p, doubao_alias
WHERE pm.platform_id = p.id
AND (
(
p.provider = 'easyai'
AND pm.model_name IN (doubao_alias.old_alias, doubao_alias.new_alias)
)
OR (
p.provider = 'volces-openai'
AND (
pm.model_name = doubao_alias.volces_model_name
OR pm.provider_model_name = doubao_alias.volces_model_name
)
)
);
WITH model_defs AS (
SELECT *
FROM (
VALUES
(
'easyai',
'easyai',
'EasyAI',
'easyai',
'easyai:GLM-5.2',
'GLM-5.2',
'GLM-5.2',
'GLM-5.2',
'GLM-5.2',
'旗舰 Coding 模型,文本输入/输出1M 上下文,最大输出 128K支持思考模式、工具调用与结构化输出。',
'https://static.51easyai.com/chatglm-color.webp',
jsonb_build_array('text_generate', 'tools_call'),
'{
"text_generate": {"max_context_tokens": 1000000, "max_output_tokens": 131072, "supportTool": true, "supportThinking": true, "supportThinkingModeSwitch": true, "supportStructuredOutput": true},
"tools_call": {"max_context_tokens": 1000000, "max_output_tokens": 131072, "supportTool": true, "supportThinking": true, "supportThinkingModeSwitch": true, "supportStructuredOutput": true},
"originalTypes": ["text_generate", "tools_call"]
}'::jsonb,
'easyai:GLM-4.7'
),
(
'zhipu-openai',
'zhipu-openai',
'智谱AI',
'openai',
'zhipu-openai:glm-5.2',
'glm-5.2',
'glm-5.2',
'GLM-5.2',
'GLM-5.2',
'旗舰 Coding 模型,文本输入/输出1M 上下文,最大输出 128K支持思考模式、工具调用与结构化输出。',
'https://static.51easyai.com/chatglm-color.webp',
jsonb_build_array('text_generate', 'tools_call'),
'{
"text_generate": {"max_context_tokens": 1000000, "max_output_tokens": 131072, "supportTool": true, "supportThinking": true, "supportThinkingModeSwitch": true, "supportStructuredOutput": true},
"tools_call": {"max_context_tokens": 1000000, "max_output_tokens": 131072, "supportTool": true, "supportThinking": true, "supportThinkingModeSwitch": true, "supportStructuredOutput": true},
"originalTypes": ["text_generate", "tools_call"]
}'::jsonb,
'zhipu-openai:glm-4.7'
),
(
'easyai',
'easyai',
'EasyAI',
'easyai',
'easyai:Kimi-K2.7-Code',
'Kimi-K2.7-Code',
'Kimi-K2.7-Code',
'Kimi-K2.7-Code',
'Kimi-K2.7-Code',
'Kimi 最强 Coding 模型,支持文本、图片与视频输入,思考模式、对话与 Agent 任务256K 上下文,默认最大输出 32K。',
'https://static.51easyai.com/kimi-logo-124.png',
jsonb_build_array('text_generate', 'image_analysis', 'video_understanding', 'tools_call'),
'{
"text_generate": {"max_context_tokens": 262144, "max_output_tokens": 32768, "supportTool": true, "supportThinking": true},
"image_analysis": {"max_context_tokens": 262144, "max_output_tokens": 32768, "supportThinking": true},
"video_understanding": {"max_context_tokens": 262144, "max_output_tokens": 32768, "supportThinking": true},
"tools_call": {"max_context_tokens": 262144, "max_output_tokens": 32768, "supportTool": true, "supportThinking": true},
"originalTypes": ["text_generate", "image_analysis", "video_understanding", "tools_call"]
}'::jsonb,
'easyai:DeepSeek-V4-Pro'
),
(
'moonshot-openai',
'moonshot-openai',
'KimiOpenAI兼容',
'openai',
'moonshot-openai:kimi-k2.7-code',
'kimi-k2.7-code',
'kimi-k2.7-code',
'Kimi-K2.7-Code',
'Kimi-K2.7-Code',
'Kimi 最强 Coding 模型,支持文本、图片与视频输入,思考模式、对话与 Agent 任务256K 上下文,默认最大输出 32K。',
'https://static.51easyai.com/kimi-logo-124.png',
jsonb_build_array('text_generate', 'image_analysis', 'video_understanding', 'tools_call'),
'{
"text_generate": {"max_context_tokens": 262144, "max_output_tokens": 32768, "supportTool": true, "supportThinking": true},
"image_analysis": {"max_context_tokens": 262144, "max_output_tokens": 32768, "supportThinking": true},
"video_understanding": {"max_context_tokens": 262144, "max_output_tokens": 32768, "supportThinking": true},
"tools_call": {"max_context_tokens": 262144, "max_output_tokens": 32768, "supportTool": true, "supportThinking": true},
"originalTypes": ["text_generate", "image_analysis", "video_understanding", "tools_call"]
}'::jsonb,
'deepseek-openai:deepseek-v4-pro'
),
(
'easyai',
'easyai',
'EasyAI',
'easyai',
'easyai:MiniMax-M3',
'MiniMax-M3',
'MiniMax-M3',
'MiniMax-M3',
'MiniMax-M3',
'原生多模态、1M 上下文的 Frontier Coding 模型,适用于 Agent 推理、工具调用、代码和长上下文任务。',
'https://static.51easyai.com/minimax-color.png',
jsonb_build_array('text_generate', 'image_analysis', 'video_understanding', 'tools_call'),
'{
"text_generate": {"max_context_tokens": 1000000, "supportTool": true, "supportThinking": true, "supportThinkingModeSwitch": true},
"image_analysis": {"max_context_tokens": 1000000, "supportThinking": true, "supportThinkingModeSwitch": true},
"video_understanding": {"max_context_tokens": 1000000, "supportThinking": true, "supportThinkingModeSwitch": true},
"tools_call": {"max_context_tokens": 1000000, "supportTool": true, "supportThinking": true, "supportThinkingModeSwitch": true},
"originalTypes": ["text_generate", "image_analysis", "video_understanding", "tools_call"]
}'::jsonb,
'easyai:MiniMax M2.7'
),
(
'minimax-openai',
'minimax-openai',
'MiniMaxOpenAI兼容',
'openai',
'minimax-openai:MiniMax-M3',
'MiniMax-M3',
'MiniMax-M3',
'MiniMax-M3',
'MiniMax-M3',
'原生多模态、1M 上下文的 Frontier Coding 模型,适用于 Agent 推理、工具调用、代码和长上下文任务。',
'https://static.51easyai.com/minimax-color.png',
jsonb_build_array('text_generate', 'image_analysis', 'video_understanding', 'tools_call'),
'{
"text_generate": {"max_context_tokens": 1000000, "supportTool": true, "supportThinking": true, "supportThinkingModeSwitch": true},
"image_analysis": {"max_context_tokens": 1000000, "supportThinking": true, "supportThinkingModeSwitch": true},
"video_understanding": {"max_context_tokens": 1000000, "supportThinking": true, "supportThinkingModeSwitch": true},
"tools_call": {"max_context_tokens": 1000000, "supportTool": true, "supportThinking": true, "supportThinkingModeSwitch": true},
"originalTypes": ["text_generate", "image_analysis", "video_understanding", "tools_call"]
}'::jsonb,
'minimax-openai:MiniMax-M2.7'
)
) AS defs(
provider_key,
source_provider_code,
source_provider_name,
source_spec_type,
canonical_model_key,
provider_model_name,
raw_model_name,
display_name,
model_alias,
description,
icon_path,
model_type,
capabilities,
template_key
)
),
source_rows AS (
SELECT
providers.id AS provider_id,
model_defs.provider_key,
model_defs.source_provider_code,
model_defs.source_provider_name,
model_defs.source_spec_type,
model_defs.canonical_model_key,
model_defs.provider_model_name,
model_defs.raw_model_name,
model_defs.display_name,
model_defs.model_alias,
model_defs.description,
model_defs.icon_path,
model_defs.model_type,
model_defs.capabilities,
COALESCE(
template.base_billing_config,
'{"text":{"basePrice":0.01,"baseWeight":1},"image":{"basePrice":10,"baseWeight":1},"video":{"basePrice":100,"baseWeight":1},"currency":"resource"}'::jsonb
) AS base_billing_config,
COALESCE(
template.default_rate_limit_policy,
jsonb_build_object('platformLimits', jsonb_build_object('max_concurrent_requests', 5))
) AS default_rate_limit_policy,
COALESCE(
template.pricing_rule_set_id,
(SELECT id FROM model_pricing_rule_sets WHERE rule_set_key = 'default-multimodal-v1' LIMIT 1)
) AS pricing_rule_set_id,
COALESCE(
template.runtime_policy_set_id,
(SELECT id FROM model_runtime_policy_sets WHERE policy_key = 'default-runtime-v1' LIMIT 1)
) AS runtime_policy_set_id,
COALESCE(template.runtime_policy_override, '{}'::jsonb) AS runtime_policy_override,
COALESCE(template.pricing_version, 1) AS pricing_version
FROM model_defs
LEFT JOIN model_catalog_providers providers
ON providers.provider_key = model_defs.provider_key
OR providers.provider_code = model_defs.provider_key
LEFT JOIN base_model_catalog template
ON template.canonical_model_key = model_defs.template_key
),
payload AS (
SELECT
source_rows.*,
jsonb_build_object(
'source', 'server-main.integration-platform',
'sourceProviderCode', source_provider_code,
'sourceProviderName', source_provider_name,
'sourceSpecType', source_spec_type,
'originalTypes', model_type,
'alias', model_alias,
'description', description,
'iconPath', icon_path,
'billingType', 'external-api',
'billingMode', '',
'referenceModel', '',
'modelWeight', NULL,
'selectable', true,
'rawModel', jsonb_build_object(
'name', raw_model_name,
'types', model_type,
'alias', model_alias,
'description', description,
'icon_path', icon_path,
'capabilities', capabilities - 'originalTypes'
)
) AS metadata
FROM source_rows
),
snapshot AS (
SELECT
payload.*,
jsonb_build_object(
'providerKey', provider_key,
'canonicalModelKey', canonical_model_key,
'providerModelName', provider_model_name,
'modelType', model_type,
'modelAlias', model_alias,
'displayName', display_name,
'capabilities', capabilities,
'baseBillingConfig', base_billing_config,
'defaultRateLimitPolicy', default_rate_limit_policy,
'pricingRuleSetId', COALESCE(pricing_rule_set_id::text, ''),
'runtimePolicySetId', COALESCE(runtime_policy_set_id::text, ''),
'runtimePolicyOverride', runtime_policy_override,
'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,
pricing_rule_set_id,
runtime_policy_set_id,
runtime_policy_override,
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,
pricing_rule_set_id,
runtime_policy_set_id,
runtime_policy_override,
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 = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.provider_model_name
ELSE base_model_catalog.provider_model_name
END,
model_type = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.model_type
ELSE base_model_catalog.model_type
END,
display_name = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.display_name
ELSE base_model_catalog.display_name
END,
capabilities = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.capabilities
ELSE base_model_catalog.capabilities
END,
base_billing_config = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.base_billing_config
ELSE base_model_catalog.base_billing_config
END,
default_rate_limit_policy = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.default_rate_limit_policy
ELSE base_model_catalog.default_rate_limit_policy
END,
pricing_rule_set_id = COALESCE(base_model_catalog.pricing_rule_set_id, EXCLUDED.pricing_rule_set_id),
runtime_policy_set_id = COALESCE(base_model_catalog.runtime_policy_set_id, EXCLUDED.runtime_policy_set_id),
runtime_policy_override = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.runtime_policy_override
ELSE base_model_catalog.runtime_policy_override
END,
metadata = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.metadata
ELSE base_model_catalog.metadata
END,
catalog_type = 'system',
default_snapshot = EXCLUDED.default_snapshot,
pricing_version = CASE
WHEN base_model_catalog.customized_at IS NULL THEN EXCLUDED.pricing_version
ELSE base_model_catalog.pricing_version
END,
status = CASE
WHEN base_model_catalog.customized_at IS NULL THEN 'active'
ELSE base_model_catalog.status
END,
updated_at = now();
INSERT INTO platform_models (
platform_id,
base_model_id,
model_name,
provider_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.provider_model_name,
b.display_name,
b.model_type,
b.display_name,
b.capabilities,
'inherit_discount',
b.base_billing_config,
'{"enabled":true,"maxAttempts":1}'::jsonb,
b.default_rate_limit_policy,
true
FROM integration_platforms p
JOIN base_model_catalog b ON b.provider_key = p.provider
WHERE b.canonical_model_key IN (
'easyai:GLM-5.2',
'zhipu-openai:glm-5.2',
'easyai:Kimi-K2.7-Code',
'moonshot-openai:kimi-k2.7-code',
'easyai:MiniMax-M3',
'minimax-openai:MiniMax-M3'
)
AND p.deleted_at IS NULL
ON CONFLICT (platform_id, model_name) DO UPDATE
SET base_model_id = EXCLUDED.base_model_id,
provider_model_name = EXCLUDED.provider_model_name,
model_alias = EXCLUDED.model_alias,
display_name = EXCLUDED.display_name,
model_type = EXCLUDED.model_type,
capabilities = EXCLUDED.capabilities,
pricing_mode = EXCLUDED.pricing_mode,
billing_config = EXCLUDED.billing_config,
retry_policy = EXCLUDED.retry_policy,
rate_limit_policy = EXCLUDED.rate_limit_policy,
enabled = EXCLUDED.enabled,
updated_at = now();