Files
kolaytercih/src/lib/ai/sohbet-gecmisi.ts
bilalgursen 3f1e770013 fix(danisman): H3 (3) — bedelsiz onay yolu yalnız gerçek onayda açılsın [KARAR]
Onay mesajı artık baştan sona evet/hayır sözlerinden oluşmalı; "evet. <gerçek
soru>" normal (kredili) soru sayılır, 0 kredide 402 döner. "Profil onayı
kredi harcamaz" kararı (26 Eyl) gerçek onay için aynen duruyor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-05 01:06:01 +03:00

69 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Danışman sohbet geçmişinin saf kuralları (api/soru/route.ts kullanır).
*
* Saf modül: DB'ye ve oturuma dokunmaz, Next dışından da çalışır.
*/
export type SohbetMesaji = { role: "user" | "assistant"; content: string };
/**
* Modele giden mesaj penceresi: kayıtlı geçmiş + yeni soru. Kayıt her zaman
* soru-cevap çifti değildir — hata/iade sonrası kullanıcı mesajı cevapsız
* kalır, pencere de sayıyla kesildiği için danışman mesajıyla başlayabilir.
* Burada düzeltilir: baştaki danışman mesajları atılır, art arda aynı rolden
* gelenler tek mesajda birleşir (yinelenen metin bir kez yazılır). Sonuç
* hep user ile başlar, roller sırayla değişir ve yeni soruyla biter.
*/
export function modelPenceresi(gecmis: SohbetMesaji[], yeniSoru: string): SohbetMesaji[] {
const gruplar: { role: SohbetMesaji["role"]; parcalar: string[] }[] = [];
for (const m of [...gecmis, { role: "user" as const, content: yeniSoru }]) {
const son = gruplar.at(-1);
if (!son && m.role === "assistant") continue;
if (son?.role === m.role) {
if (!son.parcalar.includes(m.content)) son.parcalar.push(m.content);
} else {
gruplar.push({ role: m.role, parcalar: [m.content] });
}
}
return gruplar.map((g) => ({ role: g.role, content: g.parcalar.join("\n\n") }));
}
/** Danışmanın onay sorusunda geçen sabit ibare; istemci de bunu görmez, yalnız sunucu arar. */
const ONAY_SORUSU = "profiline kaydedeyim mi";
const ONAY_SOZLERI = [
"evet",
"olur",
"tamam",
"kaydet",
"kaydedebilirsin",
"kaydedelim",
"hayır",
"hayir",
"yok",
"kaydetme",
"gerek yok",
"istemiyorum",
"şimdilik hayır",
];
/** Onay sözünün ardından gelebilecek dolgu; bunların dışındaki her kelime mesajı soru yapar. */
const ONAY_DOLGU = [...ONAY_SOZLERI, "bunu", "lütfen", "lutfen", "teşekkürler", "tesekkurler", "teşekkür ederim", "sağ ol"];
const ONAY_KALIBI = new RegExp(`^(?:${ONAY_SOZLERI.join("|")})(?: (?:${ONAY_DOLGU.join("|")}))*$`);
/**
* Onay mesajı mı: son danışman mesajı "kaydedeyim mi?" diye sormuş VE adayın
* mesajı BAŞTAN SONA evet/hayır sözlerinden oluşuyor. Bu mesaj kredi harcamaz
* (Bilal, 26 Eyl 2026). Yalnız başına bakmak yetmiyordu: "evet. Ege hukuk
* taban sırası kaç?" kredisiz tam cevap alıyordu. Kalıba uymayan mesaj
* normal (kredili) soru sayılır.
*/
export function onayMesajiMi(mesaj: string, sonAsistan: string | undefined): boolean {
if (!sonAsistan || !sonAsistan.toLocaleLowerCase("tr-TR").includes(ONAY_SORUSU)) return false;
const m = mesaj
.toLocaleLowerCase("tr-TR")
.replace(/[.,!?;:…'"()]+/g, " ")
.replace(/\s+/g, " ")
.trim();
return ONAY_KALIBI.test(m);
}