@cccarv82/freya 1.0.49 → 1.0.51
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/cli/web.js +53 -15
- package/package.json +1 -1
package/cli/web.js
CHANGED
|
@@ -611,6 +611,7 @@ function run(cmd, args, cwd) {
|
|
|
611
611
|
function isAllowedChatSearchPath(relPath) {
|
|
612
612
|
if (!relPath) return false;
|
|
613
613
|
if (relPath.startsWith('..')) return false;
|
|
614
|
+
if (relPath.startsWith('data/chat/')) return false;
|
|
614
615
|
return relPath.startsWith('data/') || relPath.startsWith('logs/') || relPath.startsWith('docs/');
|
|
615
616
|
}
|
|
616
617
|
|
|
@@ -625,13 +626,16 @@ async function copilotSearch(workspaceDir, query, opts = {}) {
|
|
|
625
626
|
'Você é um buscador local de arquivos.',
|
|
626
627
|
'Objetivo: encontrar registros relevantes para a consulta do usuário.',
|
|
627
628
|
'Escopo: procure SOMENTE nos diretórios data/, logs/ e docs/ do workspace.',
|
|
629
|
+
'Exclua data/chat/ (conversa), a menos que o usuário peça explicitamente por chat.',
|
|
628
630
|
'Use ferramentas para ler/consultar arquivos, mas não modifique nada.',
|
|
629
631
|
`Consulta do usuário: "${q}"`,
|
|
630
632
|
'',
|
|
631
633
|
'Responda APENAS com JSON válido (sem code fences) no formato:',
|
|
632
|
-
'{"
|
|
634
|
+
'{"answer":"<resposta humana, clara e direta>","evidence":[{"file":"<caminho relativo>","date":"YYYY-MM-DD ou vazio","detail":"<frase curta e única com a evidência>"}],"matches":[{"file":"<caminho relativo>","date":"YYYY-MM-DD ou vazio","snippet":"<trecho curto>"}]}',
|
|
633
635
|
`Limite de matches: ${limit}.`,
|
|
634
|
-
'
|
|
636
|
+
'A resposta deve soar humana, bem escrita, sem repetições, e mencionar a quantidade de registros encontrados.',
|
|
637
|
+
'Priorize responder exatamente à pergunta (ex.: data e ID da última CHG).',
|
|
638
|
+
'Na seção evidence, escreva evidências curtas e não repetidas (máx 5).',
|
|
635
639
|
'A lista deve estar ordenada por relevância.'
|
|
636
640
|
].join('\n');
|
|
637
641
|
|
|
@@ -678,32 +682,60 @@ async function copilotSearch(workspaceDir, query, opts = {}) {
|
|
|
678
682
|
.filter((m) => m.file && isAllowedChatSearchPath(m.file))
|
|
679
683
|
.slice(0, limit);
|
|
680
684
|
|
|
681
|
-
const
|
|
682
|
-
|
|
685
|
+
const evidenceRaw = Array.isArray(parsed.evidence) ? parsed.evidence : [];
|
|
686
|
+
const evidence = evidenceRaw
|
|
687
|
+
.map((m) => {
|
|
688
|
+
const fileRaw = String(m && m.file ? m.file : '').trim();
|
|
689
|
+
const dateRaw = String(m && m.date ? m.date : '').trim();
|
|
690
|
+
const detailRaw = String(m && m.detail ? m.detail : '').trim();
|
|
691
|
+
let rel = fileRaw;
|
|
692
|
+
if (fileRaw.startsWith(workspaceDir)) {
|
|
693
|
+
rel = path.relative(workspaceDir, fileRaw).replace(/\\/g, '/');
|
|
694
|
+
}
|
|
695
|
+
return { file: rel.replace(/\\/g, '/'), date: dateRaw, detail: detailRaw };
|
|
696
|
+
})
|
|
697
|
+
.filter((m) => m.file && m.detail && isAllowedChatSearchPath(m.file))
|
|
698
|
+
.slice(0, 5);
|
|
699
|
+
|
|
700
|
+
const answer = String(parsed.answer || '').trim();
|
|
701
|
+
return { ok: true, answer, matches, evidence };
|
|
683
702
|
}
|
|
684
703
|
|
|
685
|
-
function buildChatAnswer(query, matches, summary) {
|
|
704
|
+
function buildChatAnswer(query, matches, summary, evidence, answer) {
|
|
686
705
|
const count = matches.length;
|
|
687
706
|
let summaryText = String(summary || '').trim();
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
707
|
+
let answerText = String(answer || '').trim();
|
|
708
|
+
if (!answerText) {
|
|
709
|
+
if (!summaryText) {
|
|
710
|
+
if (count === 0) {
|
|
711
|
+
summaryText = `Não encontrei registros relacionados a "${query}".`;
|
|
712
|
+
} else {
|
|
713
|
+
summaryText = `Encontrei ${count} registro(s) relacionados a "${query}".`;
|
|
714
|
+
}
|
|
693
715
|
}
|
|
716
|
+
answerText = summaryText;
|
|
694
717
|
}
|
|
695
718
|
|
|
696
719
|
const lines = [];
|
|
697
720
|
lines.push(`Encontrei ${count} registro(s).`);
|
|
698
|
-
lines.push(`Resumo
|
|
721
|
+
lines.push(`Resumo: ${answerText}`);
|
|
722
|
+
|
|
723
|
+
const evidences = Array.isArray(evidence) && evidence.length
|
|
724
|
+
? evidence
|
|
725
|
+
: matches.slice(0, 5).map((m) => ({ file: m.file, date: m.date, detail: m.snippet }));
|
|
726
|
+
|
|
727
|
+
if (!evidences.length) return lines.join('\n');
|
|
699
728
|
|
|
700
|
-
|
|
729
|
+
lines.push('');
|
|
730
|
+
lines.push('Principais evidências:');
|
|
731
|
+
for (const m of evidences.slice(0, 5)) {
|
|
701
732
|
const parts = [];
|
|
702
733
|
if (m.date) parts.push(`**${m.date}**`);
|
|
703
734
|
if (m.file) parts.push('`' + m.file + '`');
|
|
704
735
|
const prefix = parts.length ? parts.join(' — ') + ':' : '';
|
|
705
|
-
const
|
|
706
|
-
|
|
736
|
+
const detail = (m.detail || m.snippet || '').toString().trim();
|
|
737
|
+
if (!detail) continue;
|
|
738
|
+
lines.push(`- ${prefix} ${detail}`);
|
|
707
739
|
}
|
|
708
740
|
|
|
709
741
|
return lines.join('\n');
|
|
@@ -1727,7 +1759,13 @@ async function cmdWeb({ port, dir, open, dev }) {
|
|
|
1727
1759
|
const copilotResult = await copilotSearch(workspaceDir, query, { limit: 8 });
|
|
1728
1760
|
if (copilotResult.ok) {
|
|
1729
1761
|
const matches = copilotResult.matches || [];
|
|
1730
|
-
const answer = buildChatAnswer(
|
|
1762
|
+
const answer = buildChatAnswer(
|
|
1763
|
+
query,
|
|
1764
|
+
matches,
|
|
1765
|
+
copilotResult.summary,
|
|
1766
|
+
copilotResult.evidence,
|
|
1767
|
+
copilotResult.answer
|
|
1768
|
+
);
|
|
1731
1769
|
return safeJson(res, 200, { ok: true, sessionId, answer, matches });
|
|
1732
1770
|
}
|
|
1733
1771
|
|