refactor: CI optimization, logging improvements, and codebase formatting (#456)

* fix(db): remove unique constraint on folder to support multi-channel agents

* ci: implement automated skill drift detection and self-healing PRs

* fix: align registration logic with Gavriel's feedback and fix build/test issues from Daniel Mi

* style: conform to prettier standards for CI validation

* test: fix branch naming inconsistency in CI (master vs main)

* fix(ci): robust module resolution by removing file extensions in scripts

* refactor(ci): simplify skill validation by removing redundant combination tests

* style: conform skills-engine to prettier, unify logging in index.ts and cleanup unused imports

* refactor: extract multi-channel DB changes to separate branch

Move channel column, folder suffix logic, and related migrations
to feat/multi-channel-db-v2 for independent review. This PR now
contains only CI/CD optimizations, Prettier formatting, and
logging improvements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Gabi Simons
2026-02-25 23:13:36 +02:00
committed by GitHub
parent bd2e236f73
commit 11c201088b
76 changed files with 2333 additions and 1308 deletions

View File

@@ -5,7 +5,12 @@ import path from 'path';
import { ASSISTANT_NAME, DATA_DIR, STORE_DIR } from './config.js';
import { isValidGroupFolder } from './group-folder.js';
import { logger } from './logger.js';
import { NewMessage, RegisteredGroup, ScheduledTask, TaskRunLog } from './types.js';
import {
NewMessage,
RegisteredGroup,
ScheduledTask,
TaskRunLog,
} from './types.js';
let db: Database.Database;
@@ -94,26 +99,30 @@ function createSchema(database: Database.Database): void {
`ALTER TABLE messages ADD COLUMN is_bot_message INTEGER DEFAULT 0`,
);
// Backfill: mark existing bot messages that used the content prefix pattern
database.prepare(
`UPDATE messages SET is_bot_message = 1 WHERE content LIKE ?`,
).run(`${ASSISTANT_NAME}:%`);
database
.prepare(`UPDATE messages SET is_bot_message = 1 WHERE content LIKE ?`)
.run(`${ASSISTANT_NAME}:%`);
} catch {
/* column already exists */
}
// Add channel and is_group columns if they don't exist (migration for existing DBs)
try {
database.exec(
`ALTER TABLE chats ADD COLUMN channel TEXT`,
);
database.exec(
`ALTER TABLE chats ADD COLUMN is_group INTEGER DEFAULT 0`,
);
database.exec(`ALTER TABLE chats ADD COLUMN channel TEXT`);
database.exec(`ALTER TABLE chats ADD COLUMN is_group INTEGER DEFAULT 0`);
// Backfill from JID patterns
database.exec(`UPDATE chats SET channel = 'whatsapp', is_group = 1 WHERE jid LIKE '%@g.us'`);
database.exec(`UPDATE chats SET channel = 'whatsapp', is_group = 0 WHERE jid LIKE '%@s.whatsapp.net'`);
database.exec(`UPDATE chats SET channel = 'discord', is_group = 1 WHERE jid LIKE 'dc:%'`);
database.exec(`UPDATE chats SET channel = 'telegram', is_group = 1 WHERE jid LIKE 'tg:%'`);
database.exec(
`UPDATE chats SET channel = 'whatsapp', is_group = 1 WHERE jid LIKE '%@g.us'`,
);
database.exec(
`UPDATE chats SET channel = 'whatsapp', is_group = 0 WHERE jid LIKE '%@s.whatsapp.net'`,
);
database.exec(
`UPDATE chats SET channel = 'discord', is_group = 1 WHERE jid LIKE 'dc:%'`,
);
database.exec(
`UPDATE chats SET channel = 'telegram', is_group = 1 WHERE jid LIKE 'tg:%'`,
);
} catch {
/* columns already exist */
}
@@ -540,14 +549,12 @@ export function getRegisteredGroup(
containerConfig: row.container_config
? JSON.parse(row.container_config)
: undefined,
requiresTrigger: row.requires_trigger === null ? undefined : row.requires_trigger === 1,
requiresTrigger:
row.requires_trigger === null ? undefined : row.requires_trigger === 1,
};
}
export function setRegisteredGroup(
jid: string,
group: RegisteredGroup,
): void {
export function setRegisteredGroup(jid: string, group: RegisteredGroup): void {
if (!isValidGroupFolder(group.folder)) {
throw new Error(`Invalid group folder "${group.folder}" for JID ${jid}`);
}
@@ -566,9 +573,7 @@ export function setRegisteredGroup(
}
export function getAllRegisteredGroups(): Record<string, RegisteredGroup> {
const rows = db
.prepare('SELECT * FROM registered_groups')
.all() as Array<{
const rows = db.prepare('SELECT * FROM registered_groups').all() as Array<{
jid: string;
name: string;
folder: string;
@@ -594,7 +599,8 @@ export function getAllRegisteredGroups(): Record<string, RegisteredGroup> {
containerConfig: row.container_config
? JSON.parse(row.container_config)
: undefined,
requiresTrigger: row.requires_trigger === null ? undefined : row.requires_trigger === 1,
requiresTrigger:
row.requires_trigger === null ? undefined : row.requires_trigger === 1,
};
}
return result;