- Add personalRatings table to skill-registry-schema.ts - Add taskCount, avgCostUsd, lastUsedAt columns to agentSkills in schema - Add CREATE_PERSONAL_RATINGS_TABLE DDL constant in skill-registry-db.ts - Add ALTER TABLE statements for new agent_skills usage columns (idempotent) - Create skill-registry-ratings.ts with skillRatingService factory - rate() appends personal rating, validates stars 1-5 - getRatings() returns ratings ordered by createdAt DESC - recordUsageForAgent() atomically updates task_count, avg_cost_usd, last_used_at - All 8 tests pass
91 lines
3.1 KiB
TypeScript
91 lines
3.1 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(),
|
|
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(),
|
|
});
|