feat(secretaria): injeta funcionamento da clínica (horários/feriados) no prompt
brain.ts busca GET /status da agenda-bridge (aberto hoje?, próximo dia aberto, grade da semana, feriados) e injeta no system prompt via formatClinicStatus, junto da data já existente. Regra: a Secretária só oferece horário/agenda quando a clínica está ABERTA — em dia fechado/feriado, informa o horário e oferece o próximo dia disponível. (Par do satélite: scoreodonto #2.) Testado em dev: ao pedirem "hoje" num domingo, ofereceu "amanhã" nos horários configurados. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,7 @@ class ProtocolEngine {
|
||||
if (!agent)
|
||||
throw new Error('Agente não encontrado');
|
||||
// Monta system prompt a partir dos nós ativos + contexto externo
|
||||
const systemPrompt = await this.buildSystemPrompt(agent, conversation, opts, userMessage);
|
||||
let systemPrompt = await this.buildSystemPrompt(agent, conversation, opts, userMessage);
|
||||
// Carrega apenas as últimas N mensagens (não o histórico completo)
|
||||
const contextWindow = agent.context_window ?? 8;
|
||||
const recentMessages = await this.db('sec_messages')
|
||||
@@ -114,6 +114,19 @@ class ProtocolEngine {
|
||||
clinicaId: opts?.clinicaId ?? secCfg?.clinica_id,
|
||||
},
|
||||
};
|
||||
// Funcionamento da clínica (aberto hoje?, feriados) — injeta no prompt para a
|
||||
// Secretária saber quando dizer que está fechado, sem depender de tool call.
|
||||
const statusClinicaId = opts?.clinicaId ?? secCfg?.clinica_id;
|
||||
if (agendaUrl && statusClinicaId) {
|
||||
try {
|
||||
const u = new URL(`${agendaUrl.replace(/\/$/, '')}/status`);
|
||||
u.searchParams.set('clinica_id', statusClinicaId);
|
||||
const r = await fetch(u, { headers: { 'x-nw-agenda-secret': agendaSecret ?? '' }, signal: AbortSignal.timeout(6000) });
|
||||
if (r.ok)
|
||||
systemPrompt += ProtocolEngine.formatClinicStatus(await r.json());
|
||||
}
|
||||
catch { /* best-effort: sem status, a Secretária segue com a data já injetada */ }
|
||||
}
|
||||
let response;
|
||||
let usageInfo = null;
|
||||
let providerUsed = null;
|
||||
@@ -173,6 +186,32 @@ class ProtocolEngine {
|
||||
const p = (n, d = 2) => String(n).padStart(d, '0');
|
||||
return `${p(now.getDate())}${p(now.getMonth() + 1)}${String(now.getFullYear()).slice(-2)}${p(now.getHours())}${p(now.getMinutes())}${p(now.getSeconds())}`;
|
||||
}
|
||||
// Formata o /status da agenda (funcionamento da clínica) para o system prompt.
|
||||
// A Secretária usa isso para NÃO oferecer horários/agendar em dia/hora fechado.
|
||||
static formatClinicStatus(st) {
|
||||
if (!st?.hoje)
|
||||
return '';
|
||||
const dm = (s) => { const m = String(s).match(/^(\d{4})-(\d{2})-(\d{2})/); return m ? `${m[3]}/${m[2]}` : s; };
|
||||
const janelas = (arr) => (arr || []).map((h) => `${h.inicio}–${h.fim}`).join(', ');
|
||||
const L = ['=== FUNCIONAMENTO DA CLÍNICA ==='];
|
||||
const h = st.hoje;
|
||||
L.push(h.aberto
|
||||
? `Hoje é ${h.dia_nome} (${dm(h.data)}): ABERTO — ${janelas(h.horarios)}.`
|
||||
: `Hoje é ${h.dia_nome} (${dm(h.data)}): FECHADO${h.motivo ? ` (${h.motivo})` : ''}.`);
|
||||
if (st.proximo_aberto && (!h.aberto || st.proximo_aberto.data !== h.data)) {
|
||||
const p = st.proximo_aberto;
|
||||
L.push(`Próximo dia aberto: ${p.dia_nome} (${dm(p.data)}), ${janelas(p.horarios)}.`);
|
||||
}
|
||||
if (Array.isArray(st.semana) && st.semana.length) {
|
||||
const grade = st.semana.map((d) => `${d.dia_nome.slice(0, 3)} ${d.aberto ? janelas(d.horarios) : 'fechado'}`).join('; ');
|
||||
L.push(`Grade da semana: ${grade}.`);
|
||||
}
|
||||
if (Array.isArray(st.feriados_proximos) && st.feriados_proximos.length) {
|
||||
L.push(`Próximos feriados/fechamentos: ${st.feriados_proximos.map((f) => `${dm(f.data)} ${f.nome}`).join('; ')}.`);
|
||||
}
|
||||
L.push('IMPORTANTE: só ofereça horários e confirme agendamento quando a clínica estiver ABERTA. Se pedirem em dia/horário fechado ou feriado, informe o horário de funcionamento e ofereça o próximo dia disponível.');
|
||||
return `\n\n${L.join('\n')}\n`;
|
||||
}
|
||||
// ── System Prompt Builder ─────────────────────────────────────────────────
|
||||
async buildSystemPrompt(agent, conversation, opts, userMessage) {
|
||||
const nodes = await this.db('sec_brain_nodes')
|
||||
|
||||
Reference in New Issue
Block a user