115 lines
4.2 KiB
JavaScript
115 lines
4.2 KiB
JavaScript
/**
|
|
* DB schema migration for the skill system.
|
|
* Called once during server bootstrap.
|
|
*/
|
|
|
|
export async function ensureSkillSchema(pool) {
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS adm_skills (
|
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
slug VARCHAR(64) NOT NULL,
|
|
name VARCHAR(128) NOT NULL,
|
|
type ENUM('builtin','user_published','mcp_tool','webhook')
|
|
NOT NULL DEFAULT 'builtin',
|
|
status ENUM('active','disabled','pending_review','deprecated')
|
|
NOT NULL DEFAULT 'active',
|
|
enabled TINYINT(1) NOT NULL DEFAULT 1,
|
|
rollout_pct TINYINT UNSIGNED NOT NULL DEFAULT 100,
|
|
publisher_id INT UNSIGNED NULL,
|
|
runtime JSON NULL,
|
|
input_schema JSON NULL,
|
|
pricing JSON NULL,
|
|
meta JSON NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_slug (slug)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS adm_skill_flags (
|
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
skill_id INT UNSIGNED NOT NULL,
|
|
scope_type ENUM('global','user','plan','caller_type') NOT NULL,
|
|
scope_id VARCHAR(128) NULL,
|
|
enabled TINYINT(1) NOT NULL DEFAULT 1,
|
|
note VARCHAR(512) NOT NULL DEFAULT '',
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uq_flag (skill_id, scope_type, scope_id),
|
|
KEY idx_skill (skill_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
|
`);
|
|
|
|
await pool.query(`
|
|
CREATE TABLE IF NOT EXISTS adm_skill_invocations (
|
|
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
skill_id INT UNSIGNED NOT NULL,
|
|
caller_id VARCHAR(64) NULL,
|
|
caller_type VARCHAR(32) NOT NULL DEFAULT 'unknown',
|
|
input_snapshot JSON NULL,
|
|
status ENUM('pending','running','success','failed','blocked_by_flag')
|
|
NOT NULL DEFAULT 'pending',
|
|
credits_charged INT NOT NULL DEFAULT 0,
|
|
latency_ms INT NULL,
|
|
error_message TEXT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (id),
|
|
KEY idx_skill (skill_id),
|
|
KEY idx_caller (caller_id),
|
|
KEY idx_created (created_at)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
|
`);
|
|
|
|
// Seed built-in skills if not yet present
|
|
await seedBuiltinSkills(pool);
|
|
}
|
|
|
|
async function seedBuiltinSkills(pool) {
|
|
const [existing] = await pool.query(
|
|
"SELECT slug FROM adm_skills WHERE slug = 'awesome-design-md' LIMIT 1",
|
|
);
|
|
if (existing.length) return; // already seeded
|
|
|
|
await pool.query(
|
|
`INSERT INTO adm_skills
|
|
(slug, name, type, status, enabled, rollout_pct, runtime, input_schema, pricing, meta)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
[
|
|
'awesome-design-md',
|
|
'Design Style Generator',
|
|
'builtin',
|
|
'active',
|
|
1,
|
|
100,
|
|
JSON.stringify({
|
|
executor: 'goosed',
|
|
config: {},
|
|
}),
|
|
JSON.stringify({
|
|
type: 'object',
|
|
required: ['design', 'task'],
|
|
properties: {
|
|
design: {
|
|
type: 'string',
|
|
description: 'Brand design style (notion, airbnb, apple, stripe, ...)',
|
|
},
|
|
task: {
|
|
type: 'string',
|
|
description: 'UI generation task description',
|
|
},
|
|
},
|
|
}),
|
|
JSON.stringify({ model: 'free', price_credits: 0 }),
|
|
JSON.stringify({
|
|
description: 'Generate UI components following a curated brand design system (powered by awesome-design-md)',
|
|
tags: ['design', 'ui', 'codegen'],
|
|
source: 'awesome-design-md',
|
|
fallback_skills: [],
|
|
}),
|
|
],
|
|
);
|
|
}
|