281799fad2
14 tools read-only para inspecção da BD Paperclip directamente via MCP,
eliminando psql nos skills /clip-*. 2 tools write (rotation, cancel issue).
- src/db.ts: pool PG singleton + COMPANY_ID + helper query() parametrizado
- src/tools/diagnostics.ts: 16 tools, 100% queries com $1,$2 (zero injection)
- src/tools/index.ts: registo ...diagnosticsTools
- package.json: pg ^8.13.1 + @types/pg ^8.11.10
- CHANGELOG.md: changelog completo
Fix: diag_agents_without_membership cast a.id::text + filtros
principal_type='agent' AND status='active'.
Validado:
- 14/14 read tools testadas contra BD real (CEO=19 runs, 65 agentes,
Reality Checker sem heartbeat/membership, 2 routines next_run_at NULL)
- npm audit: 0 vulnerabilidades
- grep '\${' em SQL: zero matches
Refs: Desk #2041
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
34 lines
884 B
TypeScript
34 lines
884 B
TypeScript
import pg from 'pg';
|
|
import { logger } from './utils/logger.js';
|
|
|
|
const { Pool } = pg;
|
|
|
|
let pool: pg.Pool | null = null;
|
|
|
|
export function getPool(): pg.Pool {
|
|
if (pool) return pool;
|
|
const connectionString = process.env.PAPERCLIP_DB_URL;
|
|
if (!connectionString) {
|
|
throw new Error('PAPERCLIP_DB_URL não definido — diagnostics tools requerem acesso BD');
|
|
}
|
|
pool = new Pool({
|
|
connectionString,
|
|
max: 5,
|
|
idleTimeoutMillis: 30000,
|
|
connectionTimeoutMillis: 5000,
|
|
});
|
|
pool.on('error', (err) => logger.error('pg pool error:', err));
|
|
return pool;
|
|
}
|
|
|
|
export async function query<T = Record<string, unknown>>(
|
|
text: string,
|
|
params: unknown[] = []
|
|
): Promise<T[]> {
|
|
const result = await getPool().query(text, params);
|
|
return result.rows as T[];
|
|
}
|
|
|
|
export const COMPANY_ID =
|
|
process.env.PAPERCLIP_COMPANY_ID ?? 'ebe10308-efd7-453f-86ab-13e6fe84004f';
|