feat: ekip davranis protokolunu guclendir

This commit is contained in:
2026-03-18 01:05:18 +03:00
parent 2d78b821d0
commit 4d6abff5c4
3 changed files with 142 additions and 51 deletions

View File

@@ -5,46 +5,143 @@ import { buildBootstrapPrompt } from "./bootstrapPrompt.js";
import { LogService } from "./logService.js";
import { PtyService } from "./ptyService.js";
import { getClaudeEnv, getPublicRuntimeConfig } from "./config.js";
import { findMentionedMember } from "./teamConfig.js";
import { findMentionedMember, findMentionedMembers } from "./teamConfig.js";
function cleanChunk(value) {
return stripAnsi(value).replace(/\r/g, "");
}
function normalizeText(value) {
return String(value ?? "")
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.toLowerCase()
.trim();
}
function isLikelyFollowUp(prompt) {
const normalized = String(prompt ?? "").trim();
const normalized = normalizeText(prompt);
const wordCount = normalized.split(/\s+/).filter(Boolean).length;
return [
wordCount <= 8,
/^(evet|hayir|tamam|olur|olsun|sade|sekersiz|şekersiz|detaylandir|detaylandır|devam|peki|neden|nasil|nasıl)\b/i.test(normalized)
/^(evet|hayir|tamam|olur|olsun|sade|sekersiz|detaylandir|detaylandir|devam|peki|neden|nasil|biraz ac|kisalt|ornek ver)\b/i.test(normalized)
].some(Boolean);
}
function buildRoutedPrompt(prompt, lastDirectedMember = null) {
const explicitTarget = findMentionedMember(prompt);
const targetMember = explicitTarget ?? (lastDirectedMember && isLikelyFollowUp(prompt) ? lastDirectedMember : null);
function isBriefingRequest(prompt) {
const normalized = normalizeText(prompt);
return [
"brief",
"briefing",
"ozet",
"durum raporu",
"tamamlandi mi",
"teslim durumu",
"son durum",
"rapor ver",
"breef"
].some((token) => normalized.includes(token));
}
if (!targetMember) {
return {
targetMember: null,
routedPrompt: `Not: Bu genel mesajdir. Once Mazlum cevap versin ve konusan herkes ad etiketi kullansin. Irgatov teknik gorev almaz; sadece kahve ve lojistik destek verir. Kullanici mesaji: ${prompt}`
};
}
function isCoordinationRequest(prompt) {
const normalized = normalizeText(prompt);
return [
"kendi aranizda konusun",
"aranizda konusun",
"toplanin",
"koordine olun",
"birbirinizle konusun",
"tartisin",
"degerlendirin",
"ekipce karar verin",
"kendi aralarinizda",
"kendi aranizda"
].some((token) => normalized.includes(token));
}
function buildGeneralPrompt(prompt) {
return {
mode: "general",
targetMember: null,
routedPrompt: `Yonlendirme notu: Bu mesaj tum ekibe yoneliktir. Once Mazlum cevap versin. Gerekirse diger ekip uyeleri kendi ad etiketiyle kisa katkilar yapsin. Kullaniciya konusurken herkes Patron diye hitap etsin. Ekip ici diyalog sadece gerekiyorsa kisa olsun. Gereksiz roleplay yapma. Sonuc net ve uygulanabilir olsun. Kullanici mesaji: ${prompt}`
};
}
function buildBriefingPrompt(prompt) {
return {
mode: "briefing",
targetMember: null,
routedPrompt: `Yonlendirme notu: Bu mesaj proje ozeti veya teslim briefigi gerektiriyor. Son ozet yalnizca Mazlum tarafindan verilsin. Cevap Mazlum: ile baslasin. Kullaniciya mutlaka Patron diye hitap et. Ozet duzenli, yonetsel ve net olsun. Gerekirse yapilanlar, kalan riskler ve sonraki adimlar kisaca belirtilsin. Diger ekip uyeleri yalnizca zorunluysa kisa katkida bulunsun. Kullanici mesaji: ${prompt}`
};
}
function buildCoordinationPrompt(prompt) {
return {
mode: "coordination",
targetMember: null,
routedPrompt: `Yonlendirme notu: Bu mesaj kisa ekip ici koordinasyon gerektiriyor. Once Mazlum durumu acsin. Gerekirse ilgili ekip uyeleri kendi ad etiketiyle kisa konussun. Ekip ici hitap kurallarini uygula: Mazlum Bey, UI Hanim, erkek ekip uyeleri arasinda gerektiginde Frontend Kanka, Backend Kanka, iOS Kanka. Diyalog kisa olsun. Ardindan net sonuc veya karar acikca verilsin. Kullaniciya donecek cerceve saygili olsun ve Patron hitabi korunsun. Kullanici mesaji: ${prompt}`
};
}
function buildDirectPrompt(prompt, targetMember) {
if (targetMember.name === "Irgatov") {
return {
mode: "irgatov_direct",
targetMember,
routedPrompt: `Not: Bu mesaj Irgatov icindir. Irgatov sadece kahve, icecek, servis ve basit lojistik destek konularinda cevap versin. Teknik plan, kod, mimari veya dosya yapisi onermesin. Cevap \`Irgatov:\` ile baslasin. Kullanici mesaji: ${prompt}`
routedPrompt: `Yonlendirme notu: Bu mesaj Irgatov icindir. Yalnizca Irgatov cevap versin. Cevap Irgatov: ile baslasin. Kullaniciya Patron diye hitap et. Irgatov sadece kahve, icecek, servis ve basit ofis lojistigi konularinda cevap verir. Teknik plan, kod, mimari, dosya yapisi veya teknoloji secimi hakkinda gorus bildirmez. Kullanici mesaji: ${prompt}`
};
}
return {
mode: "direct",
targetMember,
routedPrompt: `Not: Bu mesaj ${targetMember.name} icindir. Yalnizca ${targetMember.name} cevap versin ve cevap \`${targetMember.name}:\` ile baslasin. Kullanici mesaji: ${prompt}`
routedPrompt: `Yonlendirme notu: Bu mesaj dogrudan ${targetMember.name} icindir. Yalnizca ${targetMember.name} cevap versin. Cevap mutlaka ${targetMember.name}: ile baslasin. Kullaniciya mutlaka Patron diye hitap et. Kullaniciya karsi saygili, net ve profesyonel dil kullan. Gereksiz ekip ici diyalog kurma. Gerekirse cok kisa ofis tonu kullanabilirsin ama teknik icerigi golgeleme. Kullanici mesaji: ${prompt}`
};
}
function buildFollowUpPrompt(prompt, lastDirectedMember = null) {
if (!lastDirectedMember) {
return buildGeneralPrompt(prompt);
}
if (lastDirectedMember.name === "Irgatov") {
return buildDirectPrompt(prompt, lastDirectedMember);
}
return {
mode: "follow_up",
targetMember: lastDirectedMember,
routedPrompt: `Yonlendirme notu: Bu mesaj onceki konusmanin devamidir. Mumkunse onceki hedef kisi cevap versin. Cevap mevcut baglami korusun. Kullaniciya mutlaka Patron diye hitap et. Yalnizca gerekliyse kisa cevap ver. Gereksiz yeni ekip diyalogu baslatma. Cevap ${lastDirectedMember.name}: ile baslasin. Kullanici mesaji: ${prompt}`
};
}
function buildRoutedPrompt(prompt, lastDirectedMember = null) {
const mentionedMembers = findMentionedMembers(prompt);
if (isBriefingRequest(prompt)) {
return buildBriefingPrompt(prompt);
}
if (isCoordinationRequest(prompt)) {
return buildCoordinationPrompt(prompt);
}
if (mentionedMembers.length === 1) {
return buildDirectPrompt(prompt, mentionedMembers[0]);
}
if (mentionedMembers.length > 1) {
return buildGeneralPrompt(prompt);
}
if (lastDirectedMember && isLikelyFollowUp(prompt)) {
return buildFollowUpPrompt(prompt, lastDirectedMember);
}
return buildGeneralPrompt(prompt);
}
export class SessionManager {
constructor({ io, config }) {
this.io = io;