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:
@@ -57,7 +57,7 @@ export 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: number = agent.context_window ?? 8
|
||||
@@ -138,6 +138,18 @@ export class ProtocolEngine {
|
||||
},
|
||||
}
|
||||
|
||||
// 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: string
|
||||
let usageInfo: any = null
|
||||
let providerUsed: string | null = null
|
||||
@@ -203,6 +215,32 @@ export class ProtocolEngine {
|
||||
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: any): string {
|
||||
if (!st?.hoje) return ''
|
||||
const dm = (s: string) => { const m = String(s).match(/^(\d{4})-(\d{2})-(\d{2})/); return m ? `${m[3]}/${m[2]}` : s }
|
||||
const janelas = (arr: any[]) => (arr || []).map((h) => `${h.inicio}–${h.fim}`).join(', ')
|
||||
const L: string[] = ['=== 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: any) => `${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: any) => `${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 ─────────────────────────────────────────────────
|
||||
|
||||
private async buildSystemPrompt(
|
||||
|
||||
Reference in New Issue
Block a user