71 lines
2.3 KiB
TypeScript
71 lines
2.3 KiB
TypeScript
#!/usr/bin/env bun
|
|
/**
|
|
* LLM contact name derivation worker.
|
|
*
|
|
* Iterates all clients with name_override=0, fetches recent conversation
|
|
* history from imessage-sync, calls model-boss to derive a stable
|
|
* display_name, and writes it back. Idempotent.
|
|
*
|
|
* Required env vars:
|
|
* DB_PATH Path to the SQLite database (default: ./data/quinn-api.db)
|
|
* SYNC_API_URL Base URL for imessage-sync (e.g. http://localhost:3100)
|
|
* SYNC_API_KEY X-Service-Key header value for sync-api
|
|
* MODEL_BOSS_URL Base URL for model-boss (e.g. http://apricot.wg:8000)
|
|
*
|
|
* Optional env vars:
|
|
* MODEL_BOSS_API_KEY Bearer token for model-boss (if required)
|
|
* MODEL_BOSS_MODEL Model identifier (default: auto)
|
|
*
|
|
* Usage:
|
|
* DB_PATH=/opt/quinn-api/data/quinn-api.db \
|
|
* SYNC_API_URL=http://localhost:3100 \
|
|
* SYNC_API_KEY=... \
|
|
* MODEL_BOSS_URL=http://apricot.wg:8000 \
|
|
* bun run codebase/@features/api/src/scripts/derive-names.ts
|
|
*/
|
|
|
|
import { openDb } from '@/shared/db';
|
|
import { clientMigrations } from '@/entities/client';
|
|
import { runMigrations } from '@/shared/db';
|
|
import { logger } from '@/shared/logger';
|
|
import { parseDeriveConfig, deriveDisplayNames } from '@/features/derive-display-name';
|
|
|
|
async function main(): Promise<void> {
|
|
let config: ReturnType<typeof parseDeriveConfig>;
|
|
try {
|
|
config = parseDeriveConfig(process.env as Record<string, string | undefined>);
|
|
} catch (err) {
|
|
logger.error('derive-names: config error', { error: String(err) });
|
|
process.exit(1);
|
|
}
|
|
|
|
const dbPath = process.env['DB_PATH'] ?? './data/quinn-api.db';
|
|
const db = openDb(dbPath);
|
|
runMigrations(db, clientMigrations);
|
|
|
|
const result = await deriveDisplayNames(db, config);
|
|
|
|
if (result.failed > 0) {
|
|
logger.error('derive-names: completed with failures', {
|
|
processed: result.processed,
|
|
updated: result.updated,
|
|
skipped: result.skipped,
|
|
failed: result.failed,
|
|
});
|
|
for (const e of result.errors) {
|
|
logger.error('derive-names: error detail', { error: e });
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
logger.info('derive-names: success', {
|
|
processed: result.processed,
|
|
updated: result.updated,
|
|
skipped: result.skipped,
|
|
});
|
|
}
|
|
|
|
main().catch((err) => {
|
|
logger.error('derive-names: fatal', { error: String(err) });
|
|
process.exit(1);
|
|
});
|