Re_Backend/src/migrations/20250130-migrate-to-vertex-ai.ts

200 lines
4.5 KiB
TypeScript

import { QueryInterface, QueryTypes } from 'sequelize';
/**
* Migration to migrate from multi-provider AI to Vertex AI Gemini
*
* Removes:
* - AI_PROVIDER
* - CLAUDE_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY
* - CLAUDE_MODEL, OPENAI_MODEL, GEMINI_MODEL
* - VERTEX_AI_MODEL (moved to environment variable only)
* - VERTEX_AI_LOCATION (moved to environment variable only)
*
* Note: Both VERTEX_AI_MODEL and VERTEX_AI_LOCATION are now configured via
* environment variables only (not in admin settings).
*
* This migration is idempotent - it will only delete configs that exist.
*/
export async function up(queryInterface: QueryInterface): Promise<void> {
// Remove old AI provider configurations
await queryInterface.sequelize.query(`
DELETE FROM admin_configurations
WHERE config_key IN (
'AI_PROVIDER',
'CLAUDE_API_KEY',
'OPENAI_API_KEY',
'GEMINI_API_KEY',
'CLAUDE_MODEL',
'OPENAI_MODEL',
'GEMINI_MODEL',
'VERTEX_AI_MODEL',
'VERTEX_AI_LOCATION'
)
`, { type: QueryTypes.DELETE });
}
export async function down(queryInterface: QueryInterface): Promise<void> {
// This migration only removes configs, so down migration would restore them
// However, we don't restore them as they're now environment-only
console.log('[Migration] Down migration skipped - AI configs are now environment-only');
// Restore old configurations (for rollback)
await queryInterface.sequelize.query(`
INSERT INTO admin_configurations (
config_id, config_key, config_category, config_value, value_type,
display_name, description, default_value, is_editable, is_sensitive,
validation_rules, ui_component, options, sort_order, requires_restart,
last_modified_by, last_modified_at, created_at, updated_at
) VALUES
(
gen_random_uuid(),
'AI_PROVIDER',
'AI_CONFIGURATION',
'claude',
'STRING',
'AI Provider',
'Active AI provider for conclusion generation (claude, openai, or gemini)',
'claude',
true,
false,
'{"enum": ["claude", "openai", "gemini"], "required": true}'::jsonb,
'select',
'["claude", "openai", "gemini"]'::jsonb,
22,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
gen_random_uuid(),
'CLAUDE_API_KEY',
'AI_CONFIGURATION',
'',
'STRING',
'Claude API Key',
'API key for Claude (Anthropic) - Get from console.anthropic.com',
'',
true,
true,
'{"pattern": "^sk-ant-", "minLength": 40}'::jsonb,
'input',
NULL,
23,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
gen_random_uuid(),
'OPENAI_API_KEY',
'AI_CONFIGURATION',
'',
'STRING',
'OpenAI API Key',
'API key for OpenAI (GPT-4) - Get from platform.openai.com',
'',
true,
true,
'{"pattern": "^sk-", "minLength": 40}'::jsonb,
'input',
NULL,
24,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
gen_random_uuid(),
'GEMINI_API_KEY',
'AI_CONFIGURATION',
'',
'STRING',
'Gemini API Key',
'API key for Gemini (Google) - Get from ai.google.dev',
'',
true,
true,
'{"minLength": 20}'::jsonb,
'input',
NULL,
25,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
gen_random_uuid(),
'CLAUDE_MODEL',
'AI_CONFIGURATION',
'claude-sonnet-4-20250514',
'STRING',
'Claude Model',
'Claude (Anthropic) model to use for AI generation',
'claude-sonnet-4-20250514',
true,
false,
'{}'::jsonb,
'input',
NULL,
27,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
gen_random_uuid(),
'OPENAI_MODEL',
'AI_CONFIGURATION',
'gpt-4o',
'STRING',
'OpenAI Model',
'OpenAI model to use for AI generation',
'gpt-4o',
true,
false,
'{}'::jsonb,
'input',
NULL,
28,
false,
NULL,
NULL,
NOW(),
NOW()
),
(
gen_random_uuid(),
'GEMINI_MODEL',
'AI_CONFIGURATION',
'gemini-2.0-flash-lite',
'STRING',
'Gemini Model',
'Gemini (Google) model to use for AI generation',
'gemini-2.0-flash-lite',
true,
false,
'{}'::jsonb,
'input',
NULL,
29,
false,
NULL,
NULL,
NOW(),
NOW()
)
ON CONFLICT (config_key) DO NOTHING
`, { type: QueryTypes.INSERT });
}