Files
memind_adm/server/skills/schema.mjs
T

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: [],
}),
],
);
}