Add room skill settings inventory
This commit is contained in:
@@ -1,5 +1,25 @@
|
||||
import { Database } from 'bun:sqlite';
|
||||
|
||||
const ROOM_SKILL_OVERRIDES_SCHEMA = `
|
||||
CREATE TABLE IF NOT EXISTS room_skill_overrides (
|
||||
chat_jid TEXT NOT NULL,
|
||||
agent_type TEXT NOT NULL,
|
||||
skill_scope TEXT NOT NULL,
|
||||
skill_name TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (chat_jid, agent_type, skill_scope, skill_name),
|
||||
FOREIGN KEY (chat_jid) REFERENCES room_settings(chat_jid) ON DELETE CASCADE,
|
||||
CHECK (agent_type IN ('claude-code', 'codex')),
|
||||
CHECK (enabled IN (0, 1)),
|
||||
CHECK (length(skill_scope) > 0),
|
||||
CHECK (length(skill_name) > 0)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_room_skill_overrides_room
|
||||
ON room_skill_overrides(chat_jid, agent_type);
|
||||
`;
|
||||
|
||||
export function applyBaseSchema(database: Database): void {
|
||||
database.exec(`
|
||||
CREATE TABLE IF NOT EXISTS chats (
|
||||
@@ -410,8 +430,7 @@ export function applyBaseSchema(database: Database): void {
|
||||
last_used_at TEXT,
|
||||
archived_at TEXT
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_memories_scope
|
||||
ON memories(scope_kind, scope_key);
|
||||
CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope_kind, scope_key);
|
||||
CREATE INDEX IF NOT EXISTS idx_memories_active
|
||||
ON memories(scope_kind, scope_key, archived_at, created_at);
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
||||
@@ -435,4 +454,5 @@ export function applyBaseSchema(database: Database): void {
|
||||
VALUES (new.id, new.content, new.keywords_json);
|
||||
END;
|
||||
`);
|
||||
database.exec(ROOM_SKILL_OVERRIDES_SCHEMA);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ function getExpectedSchemaMigrations(): Array<{
|
||||
{ version: 13, name: 'message_source_kind' },
|
||||
{ version: 14, name: 'work_item_attachments' },
|
||||
{ version: 15, name: 'turn_progress_text' },
|
||||
{ version: 16, name: 'room_skill_overrides' },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
29
src/db/migrations/016_room-skill-overrides.ts
Normal file
29
src/db/migrations/016_room-skill-overrides.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { Database } from 'bun:sqlite';
|
||||
|
||||
import type { SchemaMigrationDefinition } from './types.js';
|
||||
|
||||
export const ROOM_SKILL_OVERRIDES_MIGRATION: SchemaMigrationDefinition = {
|
||||
version: 16,
|
||||
name: 'room_skill_overrides',
|
||||
apply(database: Database) {
|
||||
database.exec(`
|
||||
CREATE TABLE IF NOT EXISTS room_skill_overrides (
|
||||
chat_jid TEXT NOT NULL,
|
||||
agent_type TEXT NOT NULL,
|
||||
skill_scope TEXT NOT NULL,
|
||||
skill_name TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (chat_jid, agent_type, skill_scope, skill_name),
|
||||
FOREIGN KEY (chat_jid) REFERENCES room_settings(chat_jid) ON DELETE CASCADE,
|
||||
CHECK (agent_type IN ('claude-code', 'codex')),
|
||||
CHECK (enabled IN (0, 1)),
|
||||
CHECK (length(skill_scope) > 0),
|
||||
CHECK (length(skill_name) > 0)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_room_skill_overrides_room
|
||||
ON room_skill_overrides(chat_jid, agent_type);
|
||||
`);
|
||||
},
|
||||
};
|
||||
@@ -15,6 +15,7 @@ import { PAIRED_VERDICT_AND_STEP_TELEMETRY_MIGRATION } from './012_paired-verdic
|
||||
import { MESSAGE_SOURCE_KIND_MIGRATION } from './013_message-source-kind.js';
|
||||
import { WORK_ITEM_ATTACHMENTS_MIGRATION } from './014_work-item-attachments.js';
|
||||
import { TURN_PROGRESS_TEXT_MIGRATION } from './015_turn-progress-text.js';
|
||||
import { ROOM_SKILL_OVERRIDES_MIGRATION } from './016_room-skill-overrides.js';
|
||||
import type {
|
||||
SchemaMigrationArgs,
|
||||
SchemaMigrationDefinition,
|
||||
@@ -38,6 +39,7 @@ const ORDERED_SCHEMA_MIGRATIONS: readonly SchemaMigrationDefinition[] = [
|
||||
MESSAGE_SOURCE_KIND_MIGRATION,
|
||||
WORK_ITEM_ATTACHMENTS_MIGRATION,
|
||||
TURN_PROGRESS_TEXT_MIGRATION,
|
||||
ROOM_SKILL_OVERRIDES_MIGRATION,
|
||||
];
|
||||
|
||||
function ensureSchemaMigrationsTable(database: Database): void {
|
||||
|
||||
@@ -28,6 +28,16 @@ interface StoredRoomModeRow {
|
||||
source: RoomModeSource;
|
||||
}
|
||||
|
||||
export interface StoredRoomSkillOverride {
|
||||
chatJid: string;
|
||||
agentType: AgentType;
|
||||
skillScope: string;
|
||||
skillName: string;
|
||||
enabled: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface AssignRoomInput {
|
||||
name: string;
|
||||
roomMode?: RoomMode;
|
||||
@@ -307,6 +317,62 @@ export function getStoredRoomRoleAgentPlanFromDatabase(
|
||||
return stored ? resolveStoredRoomRoleAgentPlan(database, stored) : undefined;
|
||||
}
|
||||
|
||||
export function getStoredRoomSkillOverridesFromDatabase(
|
||||
database: Database,
|
||||
chatJid?: string,
|
||||
): StoredRoomSkillOverride[] {
|
||||
const params: string[] = [];
|
||||
const where = chatJid ? 'WHERE chat_jid = ?' : '';
|
||||
if (chatJid) params.push(chatJid);
|
||||
|
||||
let rows: Array<{
|
||||
chat_jid: string;
|
||||
agent_type: string;
|
||||
skill_scope: string;
|
||||
skill_name: string;
|
||||
enabled: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}>;
|
||||
try {
|
||||
rows = database
|
||||
.prepare(
|
||||
`SELECT chat_jid, agent_type, skill_scope, skill_name, enabled,
|
||||
created_at, updated_at
|
||||
FROM room_skill_overrides
|
||||
${where}
|
||||
ORDER BY chat_jid, agent_type, skill_scope, skill_name`,
|
||||
)
|
||||
.all(...params) as Array<{
|
||||
chat_jid: string;
|
||||
agent_type: string;
|
||||
skill_scope: string;
|
||||
skill_name: string;
|
||||
enabled: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}>;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
return rows
|
||||
.map((row) => {
|
||||
const agentType = normalizeStoredAgentType(row.agent_type);
|
||||
if (!agentType) return null;
|
||||
return {
|
||||
chatJid: row.chat_jid,
|
||||
agentType,
|
||||
skillScope: row.skill_scope,
|
||||
skillName: row.skill_name,
|
||||
enabled: row.enabled === 1,
|
||||
createdAt: row.created_at,
|
||||
updatedAt: row.updated_at,
|
||||
};
|
||||
})
|
||||
.filter((row): row is StoredRoomSkillOverride => Boolean(row));
|
||||
}
|
||||
|
||||
function getStoredRoomModeRowFromDatabase(
|
||||
database: Database,
|
||||
chatJid: string,
|
||||
|
||||
@@ -36,9 +36,11 @@ import {
|
||||
getRegisteredGroupFromDatabase,
|
||||
getStoredRoomRoleAgentPlanFromDatabase,
|
||||
getStoredRoomSettingsFromDatabase,
|
||||
getStoredRoomSkillOverridesFromDatabase,
|
||||
setExplicitRoomModeInDatabase,
|
||||
setRegisteredGroupForTestsInDatabase,
|
||||
setStoredRoomOwnerAgentTypeForTestsInDatabase,
|
||||
type StoredRoomSkillOverride,
|
||||
updateRegisteredGroupNameInDatabase,
|
||||
} from './rooms.js';
|
||||
import { type StoredRoomSettings } from './room-registration.js';
|
||||
@@ -363,6 +365,14 @@ export function getStoredRoomRoleAgentPlan(
|
||||
return getStoredRoomRoleAgentPlanFromDatabase(db, chatJid);
|
||||
}
|
||||
|
||||
export function getStoredRoomSkillOverrides(
|
||||
chatJid?: string,
|
||||
): StoredRoomSkillOverride[] {
|
||||
const db = getDatabaseIfInitialized();
|
||||
if (!db) return [];
|
||||
return getStoredRoomSkillOverridesFromDatabase(db, chatJid);
|
||||
}
|
||||
|
||||
export function getExplicitRoomMode(chatJid: string): RoomMode | undefined {
|
||||
return getExplicitRoomModeFromDatabase(requireDatabase(), chatJid);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user