- agentSkills schema gets source TEXT NOT NULL DEFAULT 'managed' column
- Migration guard in getSkillRegistryDb() handles existing DBs via ALTER TABLE
- uninstall() now accepts agentSkillsDir and removes files before soft-deleting
- syncHermesNativeSkills() reads ~/.hermes/skills/, creates stub rows with source='native'
- listAgentSkills() returns typed objects {skillId, source, installedAt} not string[]
- Interim uninstall route fix: reads agentSkillsDir from query param until Plan 02 wires agentId
92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
import { sqliteTable, text, integer, real, primaryKey } from "drizzle-orm/sqlite-core";
|
|
|
|
export const skills = sqliteTable("skills", {
|
|
id: text("id").primaryKey(),
|
|
sourceId: text("source_id").notNull(),
|
|
name: text("name").notNull(),
|
|
description: text("description"),
|
|
sourceUrl: text("source_url"),
|
|
activeVersionId: text("active_version_id"),
|
|
removedAt: integer("removed_at"), // unix ms, nullable — soft-delete
|
|
createdAt: integer("created_at").notNull(),
|
|
updatedAt: integer("updated_at").notNull(),
|
|
});
|
|
|
|
export const skillVersions = sqliteTable("skill_versions", {
|
|
id: text("id").primaryKey(),
|
|
skillId: text("skill_id").notNull(),
|
|
version: text("version").notNull(),
|
|
fetchedAt: integer("fetched_at").notNull(),
|
|
cacheDir: text("cache_dir"),
|
|
});
|
|
|
|
export const skillFiles = sqliteTable("skill_files", {
|
|
id: text("id").primaryKey(),
|
|
versionId: text("version_id").notNull(),
|
|
path: text("path").notNull(),
|
|
kind: text("kind").notNull(), // "skill" | "reference" | "script" | "asset"
|
|
sizeBytes: integer("size_bytes"),
|
|
});
|
|
|
|
export const communityRatings = sqliteTable("community_ratings", {
|
|
id: text("id").primaryKey(),
|
|
skillId: text("skill_id").notNull(),
|
|
fetchedAt: integer("fetched_at").notNull(),
|
|
averageRating: real("average_rating"),
|
|
ratingCount: integer("rating_count"),
|
|
source: text("source"),
|
|
});
|
|
|
|
export const skillGroups = sqliteTable("skill_groups", {
|
|
id: text("id").primaryKey(),
|
|
name: text("name").notNull(),
|
|
description: text("description"),
|
|
isBuiltin: integer("is_builtin").notNull().default(0),
|
|
createdAt: integer("created_at").notNull(),
|
|
updatedAt: integer("updated_at").notNull(),
|
|
});
|
|
|
|
export const skillGroupMembers = sqliteTable("skill_group_members", {
|
|
groupId: text("group_id").notNull(),
|
|
skillId: text("skill_id").notNull(),
|
|
addedAt: integer("added_at").notNull(),
|
|
}, (t) => ({
|
|
pk: primaryKey({ columns: [t.groupId, t.skillId] }),
|
|
}));
|
|
|
|
export const skillGroupInheritance = sqliteTable("skill_group_inheritance", {
|
|
childGroupId: text("child_group_id").notNull(),
|
|
parentGroupId: text("parent_group_id").notNull(),
|
|
}, (t) => ({
|
|
pk: primaryKey({ columns: [t.childGroupId, t.parentGroupId] }),
|
|
}));
|
|
|
|
export const agentSkillGroups = sqliteTable("agent_skill_groups", {
|
|
agentId: text("agent_id").notNull(),
|
|
groupId: text("group_id").notNull(),
|
|
assignedAt: integer("assigned_at").notNull(),
|
|
}, (t) => ({
|
|
pk: primaryKey({ columns: [t.agentId, t.groupId] }),
|
|
}));
|
|
|
|
export const agentSkills = sqliteTable("agent_skills", {
|
|
agentId: text("agent_id").notNull(),
|
|
skillId: text("skill_id").notNull(),
|
|
installedAt: integer("installed_at").notNull(),
|
|
source: text("source").notNull().default("managed"), // 'managed' | 'native'
|
|
taskCount: integer("task_count").notNull().default(0),
|
|
avgCostUsd: real("avg_cost_usd"),
|
|
lastUsedAt: integer("last_used_at"),
|
|
}, (t) => ({
|
|
pk: primaryKey({ columns: [t.agentId, t.skillId] }),
|
|
}));
|
|
|
|
export const personalRatings = sqliteTable("personal_ratings", {
|
|
id: text("id").primaryKey(),
|
|
skillId: text("skill_id").notNull(),
|
|
versionId: text("version_id"),
|
|
stars: integer("stars").notNull(), // 1-5
|
|
note: text("note"),
|
|
createdAt: integer("created_at").notNull(),
|
|
updatedAt: integer("updated_at").notNull(),
|
|
});
|