@codexa/cli 9.0.30 → 9.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { getDb } from "../db/connection";
1
+ import { dbGet, dbAll, dbRun } from "../db/connection";
2
2
  import { initSchema } from "../db/schema";
3
3
  import { existsSync, readFileSync, writeFileSync } from "fs";
4
4
  import { join } from "path";
@@ -31,12 +31,11 @@ interface ProductFeature {
31
31
  // PRODUCT IMPORT - Importa PRD existente
32
32
  // ═══════════════════════════════════════════════════════════════
33
33
 
34
- export function productImport(options: { file?: string; content?: string }): void {
35
- initSchema();
36
- const db = getDb();
34
+ export async function productImport(options: { file?: string; content?: string }): Promise<void> {
35
+ await initSchema();
37
36
 
38
37
  // Verificar se ja existe
39
- const existing = db.query("SELECT * FROM product_context WHERE id = 'default'").get();
38
+ const existing = await dbGet("SELECT * FROM product_context WHERE id = 'default'", ["default"]);
40
39
  if (existing) {
41
40
  console.log("\nContexto de produto ja definido.");
42
41
  console.log("Use: product reset para refazer\n");
@@ -58,7 +57,7 @@ export function productImport(options: { file?: string; content?: string }): voi
58
57
 
59
58
  // Salvar como pendente para o agente processar
60
59
  const now = new Date().toISOString();
61
- db.run(
60
+ await dbRun(
62
61
  `INSERT INTO product_context (id, name, problem, source, discovered_at, updated_at)
63
62
  VALUES ('pending', 'Pendente - PRD Importado', ?, 'import', ?, ?)`,
64
63
  [prdContent, now, now]
@@ -86,7 +85,7 @@ Comando para ver o PRD:
86
85
  // PRODUCT SET - Define campos do produto
87
86
  // ═══════════════════════════════════════════════════════════════
88
87
 
89
- export function productSet(options: {
88
+ export async function productSet(options: {
90
89
  name?: string;
91
90
  problem?: string;
92
91
  solution?: string;
@@ -97,17 +96,16 @@ export function productSet(options: {
97
96
  constraints?: string;
98
97
  goal?: string;
99
98
  feature?: string;
100
- }): void {
101
- initSchema();
102
- const db = getDb();
99
+ }): Promise<void> {
100
+ await initSchema();
103
101
 
104
102
  // Buscar pendente ou criar novo
105
- let pending = db.query("SELECT * FROM product_context WHERE id = 'pending'").get() as any;
103
+ let pending = await dbGet<any>("SELECT * FROM product_context WHERE id = 'pending'", ["pending"]);
106
104
  const now = new Date().toISOString();
107
105
 
108
106
  if (!pending) {
109
107
  // Criar novo registro pendente
110
- db.run(
108
+ await dbRun(
111
109
  `INSERT INTO product_context (id, name, problem, source, discovered_at, updated_at)
112
110
  VALUES ('pending', 'Pendente', '', 'guide', ?, ?)`,
113
111
  [now, now]
@@ -157,7 +155,7 @@ export function productSet(options: {
157
155
  values.push(now);
158
156
  values.push("pending");
159
157
 
160
- db.run(
158
+ await dbRun(
161
159
  `UPDATE product_context SET ${updates.join(", ")} WHERE id = ?`,
162
160
  values
163
161
  );
@@ -170,14 +168,15 @@ export function productSet(options: {
170
168
  const goal = parts[1] || options.goal;
171
169
  const priority = parts[2] || "medium";
172
170
 
173
- db.run(
171
+ await dbRun(
174
172
  `INSERT INTO product_goals (product_id, category, goal, priority, created_at)
175
173
  VALUES ('pending', ?, ?, ?, ?)`,
176
174
  [category, goal, priority, now]
177
175
  );
178
176
 
179
- const count = db.query("SELECT COUNT(*) as c FROM product_goals WHERE product_id = 'pending'").get() as any;
180
- console.log(`\nObjetivo adicionado (${count.c} total)`);
177
+ const countRow = await dbGet<any>("SELECT COUNT(*) as c FROM product_goals WHERE product_id = 'pending'", ["pending"]);
178
+ const count = countRow?.c ?? 0;
179
+ console.log(`\nObjetivo adicionado (${count} total)`);
181
180
  console.log(` [${category}] ${goal} (${priority})`);
182
181
  }
183
182
 
@@ -188,27 +187,28 @@ export function productSet(options: {
188
187
  const description = parts[1] || "";
189
188
  const priority = parts[2] || "medium";
190
189
 
191
- db.run(
190
+ await dbRun(
192
191
  `INSERT INTO product_features (product_id, name, description, priority, created_at)
193
192
  VALUES ('pending', ?, ?, ?, ?)`,
194
193
  [name, description, priority, now]
195
194
  );
196
195
 
197
- const count = db.query("SELECT COUNT(*) as c FROM product_features WHERE product_id = 'pending'").get() as any;
198
- console.log(`\nFeature adicionada (${count.c} total)`);
196
+ const countRow = await dbGet<any>("SELECT COUNT(*) as c FROM product_features WHERE product_id = 'pending'", ["pending"]);
197
+ const count = countRow?.c ?? 0;
198
+ console.log(`\nFeature adicionada (${count} total)`);
199
199
  console.log(` ${name} (${priority})`);
200
200
  }
201
201
 
202
202
  // Mostrar estado atual
203
- const current = db.query("SELECT * FROM product_context WHERE id = 'pending'").get() as any;
203
+ const current = await dbGet<any>("SELECT * FROM product_context WHERE id = 'pending'", ["pending"]);
204
204
 
205
205
  console.log("\nContexto de produto atualizado:");
206
206
  console.log("─".repeat(40));
207
- if (current.name !== "Pendente") console.log(` Nome: ${current.name}`);
208
- if (current.problem) console.log(` Problema: ${current.problem.substring(0, 50)}...`);
209
- if (current.solution) console.log(` Solucao: ${current.solution.substring(0, 50)}...`);
210
- if (current.target_users) console.log(` Usuarios: ${current.target_users.substring(0, 50)}...`);
211
- if (current.value_proposition) console.log(` Proposta: ${current.value_proposition.substring(0, 50)}...`);
207
+ if (current && current.name !== "Pendente") console.log(` Nome: ${current.name}`);
208
+ if (current?.problem) console.log(` Problema: ${current.problem.substring(0, 50)}...`);
209
+ if (current?.solution) console.log(` Solucao: ${current.solution.substring(0, 50)}...`);
210
+ if (current?.target_users) console.log(` Usuarios: ${current.target_users.substring(0, 50)}...`);
211
+ if (current?.value_proposition) console.log(` Proposta: ${current.value_proposition.substring(0, 50)}...`);
212
212
  console.log("\nPara confirmar: product confirm\n");
213
213
  }
214
214
 
@@ -216,11 +216,10 @@ export function productSet(options: {
216
216
  // PRODUCT CONFIRM - Confirma e salva
217
217
  // ═══════════════════════════════════════════════════════════════
218
218
 
219
- export function productConfirm(): void {
220
- initSchema();
221
- const db = getDb();
219
+ export async function productConfirm(): Promise<void> {
220
+ await initSchema();
222
221
 
223
- const pending = db.query("SELECT * FROM product_context WHERE id = 'pending'").get() as any;
222
+ const pending = await dbGet<any>("SELECT * FROM product_context WHERE id = 'pending'", ["pending"]);
224
223
  if (!pending) {
225
224
  throw new CodexaError("Nenhum contexto de produto pendente.\nExecute: product import primeiro");
226
225
  }
@@ -236,37 +235,39 @@ export function productConfirm(): void {
236
235
  const now = new Date().toISOString();
237
236
 
238
237
  // Desabilitar foreign keys temporariamente para permitir a migração
239
- db.run("PRAGMA foreign_keys = OFF");
238
+ await dbRun("PRAGMA foreign_keys = OFF");
240
239
 
241
240
  // Deletar goals e features do 'default' ANTES de deletar product_context
242
- db.run("DELETE FROM product_goals WHERE product_id = 'default'");
243
- db.run("DELETE FROM product_features WHERE product_id = 'default'");
244
- db.run("DELETE FROM product_context WHERE id = 'default'");
241
+ await dbRun("DELETE FROM product_goals WHERE product_id = 'default'", ["default"]);
242
+ await dbRun("DELETE FROM product_features WHERE product_id = 'default'", ["default"]);
243
+ await dbRun("DELETE FROM product_context WHERE id = 'default'", ["default"]);
245
244
 
246
245
  // Mover pending para default (primeiro os filhos, depois o pai)
247
- db.run(`UPDATE product_goals SET product_id = 'default' WHERE product_id = 'pending'`);
248
- db.run(`UPDATE product_features SET product_id = 'default' WHERE product_id = 'pending'`);
249
- db.run(
246
+ await dbRun(`UPDATE product_goals SET product_id = 'default' WHERE product_id = 'pending'`, ["pending"]);
247
+ await dbRun(`UPDATE product_features SET product_id = 'default' WHERE product_id = 'pending'`, ["pending"]);
248
+ await dbRun(
250
249
  `UPDATE product_context SET id = 'default', updated_at = ? WHERE id = 'pending'`,
251
250
  [now]
252
251
  );
253
252
 
254
253
  // Reabilitar foreign keys
255
- db.run("PRAGMA foreign_keys = ON");
254
+ await dbRun("PRAGMA foreign_keys = ON");
256
255
 
257
256
  // Gerar arquivo product-context.md
258
- generateProductMarkdown();
257
+ await generateProductMarkdown();
259
258
 
260
- const goalsCount = db.query("SELECT COUNT(*) as c FROM product_goals WHERE product_id = 'default'").get() as any;
261
- const featuresCount = db.query("SELECT COUNT(*) as c FROM product_features WHERE product_id = 'default'").get() as any;
259
+ const goalsCountRow = await dbGet<any>("SELECT COUNT(*) as c FROM product_goals WHERE product_id = 'default'", ["default"]);
260
+ const featuresCountRow = await dbGet<any>("SELECT COUNT(*) as c FROM product_features WHERE product_id = 'default'", ["default"]);
261
+ const goalsCount = goalsCountRow?.c ?? 0;
262
+ const featuresCount = featuresCountRow?.c ?? 0;
262
263
 
263
264
  console.log("\n" + "═".repeat(60));
264
265
  console.log("PRODUTO CONFIGURADO");
265
266
  console.log("═".repeat(60));
266
267
  console.log(`
267
268
  Nome: ${pending.name}
268
- Objetivos: ${goalsCount.c}
269
- Features: ${featuresCount.c}
269
+ Objetivos: ${goalsCount}
270
+ Features: ${featuresCount}
270
271
 
271
272
  Arquivo gerado: .codexa/product-context.md
272
273
 
@@ -279,12 +280,11 @@ Proximo passo: /codexa:feature para iniciar uma feature
279
280
  // PRODUCT SHOW - Mostra contexto atual
280
281
  // ═══════════════════════════════════════════════════════════════
281
282
 
282
- export function productShow(options: { json?: boolean; pending?: boolean } = {}): void {
283
- initSchema();
284
- const db = getDb();
283
+ export async function productShow(options: { json?: boolean; pending?: boolean } = {}): Promise<void> {
284
+ await initSchema();
285
285
 
286
286
  const id = options.pending ? "pending" : "default";
287
- const product = db.query(`SELECT * FROM product_context WHERE id = ?`).get(id) as any;
287
+ const product = await dbGet<any>(`SELECT * FROM product_context WHERE id = ?`, [id]);
288
288
 
289
289
  if (!product) {
290
290
  if (options.pending) {
@@ -294,8 +294,8 @@ export function productShow(options: { json?: boolean; pending?: boolean } = {})
294
294
  }
295
295
  }
296
296
 
297
- const goals = db.query(`SELECT * FROM product_goals WHERE product_id = ? ORDER BY priority, category`).all(id) as any[];
298
- const features = db.query(`SELECT * FROM product_features WHERE product_id = ? ORDER BY priority`).all(id) as any[];
297
+ const goals = await dbAll<any>(`SELECT * FROM product_goals WHERE product_id = ? ORDER BY priority, category`, [id]);
298
+ const features = await dbAll<any>(`SELECT * FROM product_features WHERE product_id = ? ORDER BY priority`, [id]);
299
299
 
300
300
  if (options.json) {
301
301
  console.log(JSON.stringify({
@@ -409,13 +409,12 @@ export function productShow(options: { json?: boolean; pending?: boolean } = {})
409
409
  // PRODUCT RESET - Reseta contexto de produto
410
410
  // ═══════════════════════════════════════════════════════════════
411
411
 
412
- export function productReset(): void {
413
- initSchema();
414
- const db = getDb();
412
+ export async function productReset(): Promise<void> {
413
+ await initSchema();
415
414
 
416
- db.run("DELETE FROM product_features");
417
- db.run("DELETE FROM product_goals");
418
- db.run("DELETE FROM product_context");
415
+ await dbRun("DELETE FROM product_features");
416
+ await dbRun("DELETE FROM product_goals");
417
+ await dbRun("DELETE FROM product_context");
419
418
 
420
419
  console.log("\nContexto de produto resetado.");
421
420
  console.log("Execute: product import para refazer\n");
@@ -425,11 +424,10 @@ export function productReset(): void {
425
424
  // GENERATE MARKDOWN
426
425
  // ═══════════════════════════════════════════════════════════════
427
426
 
428
- function generateProductMarkdown(): void {
429
- const db = getDb();
430
- const product = db.query("SELECT * FROM product_context WHERE id = 'default'").get() as any;
431
- const goals = db.query("SELECT * FROM product_goals WHERE product_id = 'default' ORDER BY priority, category").all() as any[];
432
- const features = db.query("SELECT * FROM product_features WHERE product_id = 'default' ORDER BY priority").all() as any[];
427
+ async function generateProductMarkdown(): Promise<void> {
428
+ const product = await dbGet<any>("SELECT * FROM product_context WHERE id = 'default'", ["default"]);
429
+ const goals = await dbAll<any>("SELECT * FROM product_goals WHERE product_id = 'default' ORDER BY priority, category", ["default"]);
430
+ const features = await dbAll<any>("SELECT * FROM product_features WHERE product_id = 'default' ORDER BY priority", ["default"]);
433
431
 
434
432
  if (!product) return;
435
433
 
@@ -1,4 +1,4 @@
1
- import { getDb } from "../db/connection";
1
+ import { dbGet, dbAll, dbRun } from "../db/connection";
2
2
  import { initSchema } from "../db/schema";
3
3
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
4
4
  import { join } from "path";
@@ -258,14 +258,12 @@ async function detectLibsUniversal(): Promise<DetectedLib[]> {
258
258
  if (!result || result.technologies.length === 0) continue;
259
259
 
260
260
  for (const tech of result.technologies) {
261
- // Skip runtime/build categories — those are languages/tools, not libraries
262
261
  if (tech.category === "runtime" || tech.category === "build") continue;
263
262
 
264
263
  const registry = UNIVERSAL_DOCS_REGISTRY[tech.name];
265
264
  const canonical = registry?.canonical || tech.name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
266
265
  const docsUrl = registry?.docsUrl || "";
267
266
 
268
- // Deduplicate by canonical name
269
267
  if (seen.has(canonical)) continue;
270
268
  seen.add(canonical);
271
269
 
@@ -347,8 +345,7 @@ ${docsLine}
347
345
  // ============================================================
348
346
 
349
347
  export async function researchStart(options: { json?: boolean } = {}): Promise<void> {
350
- initSchema();
351
- const db = getDb();
348
+ await initSchema();
352
349
 
353
350
  const libs = await detectLibsUniversal();
354
351
 
@@ -370,29 +367,26 @@ export async function researchStart(options: { json?: boolean } = {}): Promise<v
370
367
  for (const lib of libs) {
371
368
  const filePath = join(libContextDir, `${lib.canonical}.md`);
372
369
 
373
- // Registrar no banco
374
- const existingRecord = db
375
- .query("SELECT * FROM lib_contexts WHERE lib_name = ?")
376
- .get(lib.canonical) as any;
370
+ const existingRecord = await dbGet<any>(
371
+ "SELECT * FROM lib_contexts WHERE lib_name = ?",
372
+ [lib.canonical]
373
+ );
377
374
 
378
375
  if (existingRecord) {
379
- // Atualizar versao se mudou
380
376
  if (existingRecord.version !== lib.version && lib.version) {
381
- db.run(
377
+ await dbRun(
382
378
  "UPDATE lib_contexts SET version = ?, updated_at = ? WHERE lib_name = ?",
383
379
  [lib.version, new Date().toISOString(), lib.canonical]
384
380
  );
385
381
  }
386
382
  existing.push(lib.canonical);
387
383
  } else {
388
- // Criar novo registro
389
- db.run(
384
+ await dbRun(
390
385
  `INSERT INTO lib_contexts (lib_name, version, context_file, source_url, researched_at)
391
386
  VALUES (?, ?, ?, ?, ?)`,
392
387
  [lib.canonical, lib.version || "latest", filePath, lib.docsUrl, new Date().toISOString()]
393
388
  );
394
389
 
395
- // Criar arquivo se nao existe
396
390
  if (!existsSync(filePath)) {
397
391
  writeFileSync(filePath, generateLibContextTemplate(lib));
398
392
  }
@@ -400,7 +394,6 @@ export async function researchStart(options: { json?: boolean } = {}): Promise<v
400
394
  created.push(lib.canonical);
401
395
  }
402
396
 
403
- // Registrar mapeamento de agente (com filtro de ecosystem)
404
397
  const agentTypes = Object.entries(UNIVERSAL_AGENT_LIB_CATEGORIES)
405
398
  .filter(([_, config]) => {
406
399
  const categoryMatch = config.categories.includes(lib.category);
@@ -410,12 +403,13 @@ export async function researchStart(options: { json?: boolean } = {}): Promise<v
410
403
  .map(([agent]) => agent);
411
404
 
412
405
  for (const agentType of agentTypes) {
413
- const existingMapping = db
414
- .query("SELECT * FROM agent_lib_mappings WHERE agent_type = ? AND lib_name = ?")
415
- .get(agentType, lib.canonical);
406
+ const existingMapping = await dbGet<any>(
407
+ "SELECT * FROM agent_lib_mappings WHERE agent_type = ? AND lib_name = ?",
408
+ [agentType, lib.canonical]
409
+ );
416
410
 
417
411
  if (!existingMapping) {
418
- db.run(
412
+ await dbRun(
419
413
  "INSERT INTO agent_lib_mappings (agent_type, lib_name, priority) VALUES (?, ?, ?)",
420
414
  [agentType, lib.canonical, 0]
421
415
  );
@@ -424,7 +418,6 @@ export async function researchStart(options: { json?: boolean } = {}): Promise<v
424
418
  }
425
419
 
426
420
  if (options.json) {
427
- // Coletar ecossistemas detectados
428
421
  const ecosystems = [...new Set(libs.map(l => l.ecosystem))];
429
422
  console.log(JSON.stringify({
430
423
  detected: libs.length,
@@ -442,7 +435,6 @@ export async function researchStart(options: { json?: boolean } = {}): Promise<v
442
435
  return;
443
436
  }
444
437
 
445
- // Coletar ecossistemas
446
438
  const ecosystems = [...new Set(libs.map(l => l.ecosystem))];
447
439
 
448
440
  console.log(`\n${"=".repeat(60)}`);
@@ -451,7 +443,6 @@ export async function researchStart(options: { json?: boolean } = {}): Promise<v
451
443
  console.log(`\nEcossistemas: ${ecosystems.join(", ")}`);
452
444
  console.log(`Encontradas ${libs.length} bibliotecas:\n`);
453
445
 
454
- // Agrupar por ecossistema > categoria
455
446
  const byEcosystem: Record<string, Record<string, DetectedLib[]>> = {};
456
447
  for (const lib of libs) {
457
448
  if (!byEcosystem[lib.ecosystem]) {
@@ -495,9 +486,8 @@ export async function researchStart(options: { json?: boolean } = {}): Promise<v
495
486
  // COMMAND: research show
496
487
  // ============================================================
497
488
 
498
- export function researchShow(options: { json?: boolean; lib?: string } = {}): void {
499
- initSchema();
500
- const db = getDb();
489
+ export async function researchShow(options: { json?: boolean; lib?: string } = {}): Promise<void> {
490
+ await initSchema();
501
491
 
502
492
  let query = "SELECT * FROM lib_contexts";
503
493
  let params: any[] = [];
@@ -509,7 +499,7 @@ export function researchShow(options: { json?: boolean; lib?: string } = {}): vo
509
499
 
510
500
  query += " ORDER BY lib_name";
511
501
 
512
- const libs = db.query(query).all(...params) as any[];
502
+ const libs = await dbAll<any>(query, params);
513
503
 
514
504
  if (libs.length === 0) {
515
505
  if (options.json) {
@@ -522,17 +512,18 @@ export function researchShow(options: { json?: boolean; lib?: string } = {}): vo
522
512
  }
523
513
 
524
514
  if (options.json) {
525
- // Adicionar mapeamentos de agentes
526
- const result = libs.map(lib => {
527
- const mappings = db
528
- .query("SELECT agent_type FROM agent_lib_mappings WHERE lib_name = ?")
529
- .all(lib.lib_name) as any[];
515
+ const result = [];
516
+ for (const lib of libs) {
517
+ const mappings = await dbAll<any>(
518
+ "SELECT agent_type FROM agent_lib_mappings WHERE lib_name = ?",
519
+ [lib.lib_name]
520
+ );
530
521
 
531
- return {
522
+ result.push({
532
523
  ...lib,
533
524
  agents: mappings.map(m => m.agent_type)
534
- };
535
- });
525
+ });
526
+ }
536
527
 
537
528
  console.log(JSON.stringify({ libs: result }, null, 2));
538
529
  return;
@@ -543,9 +534,10 @@ export function researchShow(options: { json?: boolean; lib?: string } = {}): vo
543
534
  console.log(`${"=".repeat(60)}\n`);
544
535
 
545
536
  for (const lib of libs) {
546
- const mappings = db
547
- .query("SELECT agent_type FROM agent_lib_mappings WHERE lib_name = ?")
548
- .all(lib.lib_name) as any[];
537
+ const mappings = await dbAll<any>(
538
+ "SELECT agent_type FROM agent_lib_mappings WHERE lib_name = ?",
539
+ [lib.lib_name]
540
+ );
549
541
 
550
542
  const fileExists = existsSync(lib.context_file);
551
543
  let status = "pendente";
@@ -576,13 +568,13 @@ export function researchShow(options: { json?: boolean; lib?: string } = {}): vo
576
568
  // COMMAND: research fill
577
569
  // ============================================================
578
570
 
579
- export function researchFill(libName: string, options: { json?: boolean } = {}): void {
580
- initSchema();
581
- const db = getDb();
571
+ export async function researchFill(libName: string, options: { json?: boolean } = {}): Promise<void> {
572
+ await initSchema();
582
573
 
583
- const lib = db
584
- .query("SELECT * FROM lib_contexts WHERE lib_name = ?")
585
- .get(libName) as any;
574
+ const lib = await dbGet<any>(
575
+ "SELECT * FROM lib_contexts WHERE lib_name = ?",
576
+ [libName]
577
+ );
586
578
 
587
579
  if (!lib) {
588
580
  if (options.json) {
@@ -596,7 +588,6 @@ export function researchFill(libName: string, options: { json?: boolean } = {}):
596
588
 
597
589
  const versionStr = lib.version && lib.version !== "latest" ? lib.version : "latest";
598
590
 
599
- // Retornar instrucoes para o agente preencher
600
591
  const instructions = {
601
592
  lib_name: lib.lib_name,
602
593
  version: lib.version,
@@ -638,33 +629,34 @@ FORMATO DO ARQUIVO:
638
629
  // COMMAND: research map-agent
639
630
  // ============================================================
640
631
 
641
- export function researchMapAgent(options: {
632
+ export async function researchMapAgent(options: {
642
633
  agent: string;
643
634
  add?: string;
644
635
  remove?: string;
645
636
  json?: boolean;
646
- }): void {
647
- initSchema();
648
- const db = getDb();
637
+ }): Promise<void> {
638
+ await initSchema();
649
639
 
650
640
  if (options.add) {
651
641
  const libs = options.add.split(",").map(s => s.trim());
652
642
  for (const lib of libs) {
653
- const existingLib = db
654
- .query("SELECT * FROM lib_contexts WHERE lib_name = ?")
655
- .get(lib);
643
+ const existingLib = await dbGet<any>(
644
+ "SELECT * FROM lib_contexts WHERE lib_name = ?",
645
+ [lib]
646
+ );
656
647
 
657
648
  if (!existingLib) {
658
649
  console.error(`\nBiblioteca '${lib}' nao encontrada. Execute research start primeiro.\n`);
659
650
  continue;
660
651
  }
661
652
 
662
- const existing = db
663
- .query("SELECT * FROM agent_lib_mappings WHERE agent_type = ? AND lib_name = ?")
664
- .get(options.agent, lib);
653
+ const existingMapping = await dbGet<any>(
654
+ "SELECT * FROM agent_lib_mappings WHERE agent_type = ? AND lib_name = ?",
655
+ [options.agent, lib]
656
+ );
665
657
 
666
- if (!existing) {
667
- db.run(
658
+ if (!existingMapping) {
659
+ await dbRun(
668
660
  "INSERT INTO agent_lib_mappings (agent_type, lib_name) VALUES (?, ?)",
669
661
  [options.agent, lib]
670
662
  );
@@ -676,7 +668,7 @@ export function researchMapAgent(options: {
676
668
  if (options.remove) {
677
669
  const libs = options.remove.split(",").map(s => s.trim());
678
670
  for (const lib of libs) {
679
- db.run(
671
+ await dbRun(
680
672
  "DELETE FROM agent_lib_mappings WHERE agent_type = ? AND lib_name = ?",
681
673
  [options.agent, lib]
682
674
  );
@@ -684,10 +676,10 @@ export function researchMapAgent(options: {
684
676
  }
685
677
  }
686
678
 
687
- // Mostrar mapeamentos atuais
688
- const mappings = db
689
- .query("SELECT lib_name FROM agent_lib_mappings WHERE agent_type = ? ORDER BY lib_name")
690
- .all(options.agent) as any[];
679
+ const mappings = await dbAll<any>(
680
+ "SELECT lib_name FROM agent_lib_mappings WHERE agent_type = ? ORDER BY lib_name",
681
+ [options.agent]
682
+ );
691
683
 
692
684
  if (options.json) {
693
685
  console.log(JSON.stringify({ agent: options.agent, libs: mappings.map(m => m.lib_name) }));
@@ -708,12 +700,11 @@ export function researchMapAgent(options: {
708
700
  // COMMAND: research reset
709
701
  // ============================================================
710
702
 
711
- export function researchReset(): void {
712
- initSchema();
713
- const db = getDb();
703
+ export async function researchReset(): Promise<void> {
704
+ await initSchema();
714
705
 
715
- db.run("DELETE FROM agent_lib_mappings");
716
- db.run("DELETE FROM lib_contexts");
706
+ await dbRun("DELETE FROM agent_lib_mappings");
707
+ await dbRun("DELETE FROM lib_contexts");
717
708
 
718
709
  console.log("\nResearch resetado. Todos os contextos de biblioteca foram removidos.");
719
710
  console.log("Execute: research start para redetectar.\n");
@@ -724,27 +715,23 @@ export function researchReset(): void {
724
715
  // Used by utils.ts to inject lib context into subagent prompts.
725
716
  // ============================================================
726
717
 
727
- export function getLibContextsForAgent(agentType: string): string[] {
728
- initSchema();
729
- const db = getDb();
718
+ export async function getLibContextsForAgent(agentType: string): Promise<string[]> {
719
+ await initSchema();
730
720
 
731
- // Buscar libs mapeadas para o agente
732
- const mappings = db
733
- .query(`
734
- SELECT lc.context_file
721
+ const mappings = await dbAll<any>(
722
+ `SELECT lc.context_file
735
723
  FROM agent_lib_mappings alm
736
724
  JOIN lib_contexts lc ON alm.lib_name = lc.lib_name
737
725
  WHERE alm.agent_type = ? OR alm.agent_type = ?
738
- ORDER BY alm.priority DESC
739
- `)
740
- .all(agentType, agentType.split("-")[0]) as any[];
726
+ ORDER BY alm.priority DESC`,
727
+ [agentType, agentType.split("-")[0]]
728
+ );
741
729
 
742
730
  const contexts: string[] = [];
743
731
 
744
732
  for (const mapping of mappings) {
745
733
  if (existsSync(mapping.context_file)) {
746
734
  const content = readFileSync(mapping.context_file, "utf-8");
747
- // So inclui se nao estiver pendente
748
735
  if (!content.includes("status: pending-research")) {
749
736
  contexts.push(content);
750
737
  }