@codexa/cli 9.0.31 → 9.0.33
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.
- package/commands/architect.ts +52 -87
- package/commands/check.ts +22 -23
- package/commands/clear.ts +42 -48
- package/commands/decide.ts +46 -44
- package/commands/discover.ts +81 -94
- package/commands/integration.test.ts +262 -313
- package/commands/knowledge.test.ts +56 -61
- package/commands/knowledge.ts +126 -131
- package/commands/patterns.ts +28 -43
- package/commands/plan.ts +50 -48
- package/commands/product.ts +57 -59
- package/commands/research.ts +64 -77
- package/commands/review.ts +100 -86
- package/commands/simplify.ts +24 -35
- package/commands/spec-resolver.test.ts +52 -48
- package/commands/spec-resolver.ts +21 -23
- package/commands/standards.ts +20 -27
- package/commands/sync.ts +2 -8
- package/commands/task.ts +106 -97
- package/commands/team.test.ts +22 -83
- package/commands/team.ts +62 -50
- package/commands/utils.ts +83 -81
- package/context/assembly.ts +0 -1
- package/context/generator.ts +66 -79
- package/context/sections.ts +8 -14
- package/db/connection.ts +209 -19
- package/db/schema.test.ts +288 -299
- package/db/schema.ts +298 -394
- package/db/test-helpers.ts +18 -29
- package/gates/standards-validator.test.ts +83 -86
- package/gates/standards-validator.ts +9 -41
- package/gates/validator.test.ts +13 -22
- package/gates/validator.ts +69 -107
- package/package.json +2 -1
- package/protocol/process-return.ts +41 -57
- package/simplify/prompt-builder.test.ts +44 -42
- package/simplify/prompt-builder.ts +12 -14
- package/workflow.ts +159 -174
package/commands/product.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
180
|
-
|
|
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
|
-
|
|
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
|
|
198
|
-
|
|
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 =
|
|
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
|
|
209
|
-
if (current
|
|
210
|
-
if (current
|
|
211
|
-
if (current
|
|
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 =
|
|
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
|
-
|
|
238
|
+
await dbRun("PRAGMA foreign_keys = OFF");
|
|
240
239
|
|
|
241
240
|
// Deletar goals e features do 'default' ANTES de deletar product_context
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
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
|
|
261
|
-
const
|
|
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
|
|
269
|
-
Features: ${featuresCount
|
|
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 =
|
|
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 =
|
|
298
|
-
const features =
|
|
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
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
|
430
|
-
const
|
|
431
|
-
const
|
|
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
|
|
package/commands/research.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
.
|
|
376
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
414
|
-
|
|
415
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
526
|
-
const
|
|
527
|
-
const mappings =
|
|
528
|
-
|
|
529
|
-
|
|
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
|
-
|
|
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 =
|
|
547
|
-
|
|
548
|
-
|
|
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 =
|
|
584
|
-
|
|
585
|
-
|
|
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 =
|
|
654
|
-
|
|
655
|
-
|
|
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
|
|
663
|
-
|
|
664
|
-
|
|
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 (!
|
|
667
|
-
|
|
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
|
-
|
|
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
|
-
|
|
688
|
-
|
|
689
|
-
.
|
|
690
|
-
|
|
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
|
-
|
|
716
|
-
|
|
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
|
-
|
|
732
|
-
|
|
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
|
-
|
|
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
|
}
|