feat: sistema de personalidades enriquecido + agente template
Fase 1: Sistema de personalidades enriquecido - Ampliar PersonalityCfg con role, backstory, expertise, limitations - Añadir CommunicationCfg (formality, humor, personality, response_style, quirks, catchphrases) - Crear tipos puros en pkg/personality/traits.go - Implementar BuildPersonalityPrompt() para generar bloque de system prompt - Integrar personalidad en agents/runtime.go (FromConfig + concatenacion al system prompt) Fase 2: Agente plantilla - Añadir campo Template bool a AgentMeta - Filtrar agentes template en launcher (skip si template: true) - Crear agents/_template/ con config.yaml completo y documentado - Incluir TODAS las secciones (skills, shared_knowledge, schedules, security) - agent.go minimo + prompts/system.md plantilla - Actualizar dev-scripts/agent/new-agent.sh para copiar desde _template/ Fase 3: Ejemplos de personalidades - Crear agents/_template/PERSONALITIES.md con 4 perfiles: * DevOps pragmatico * Analista meticuloso * Asistente amigable * Guardian de seguridad 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package personality
|
||||
|
||||
import "github.com/enmanuel/agents/internal/config"
|
||||
|
||||
// FromConfig convierte PersonalityCfg (config) a Personality (tipo puro).
|
||||
// Esta funcion es pura: no tiene side effects.
|
||||
func FromConfig(cfg config.PersonalityCfg) Personality {
|
||||
return Personality{
|
||||
Tone: Tone(cfg.Tone),
|
||||
Verbosity: Verbosity(cfg.Verbosity),
|
||||
Language: cfg.Language,
|
||||
LanguagesSupported: cfg.LanguagesSupported,
|
||||
EmojiStyle: EmojiStyle(cfg.EmojiStyle),
|
||||
Prefix: cfg.Prefix,
|
||||
ErrorStyle: ErrorStyle(cfg.ErrorStyle),
|
||||
Templates: Templates{
|
||||
Greeting: cfg.Templates.Greeting,
|
||||
UnknownCommand: cfg.Templates.UnknownCommand,
|
||||
PermissionDenied: cfg.Templates.PermissionDenied,
|
||||
Error: cfg.Templates.Error,
|
||||
Success: cfg.Templates.Success,
|
||||
Busy: cfg.Templates.Busy,
|
||||
},
|
||||
Behavior: Behavior{
|
||||
Proactive: cfg.Behavior.Proactive,
|
||||
AskConfirmation: cfg.Behavior.AskConfirmation,
|
||||
ShowReasoning: cfg.Behavior.ShowReasoning,
|
||||
ThreadReplies: cfg.Behavior.ThreadReplies,
|
||||
TypingIndicator: cfg.Behavior.TypingIndicator,
|
||||
AcknowledgeReceipt: cfg.Behavior.AcknowledgeReceipt,
|
||||
},
|
||||
Role: cfg.Role,
|
||||
Backstory: cfg.Backstory,
|
||||
Expertise: cfg.Expertise,
|
||||
Limitations: cfg.Limitations,
|
||||
Communication: Communication{
|
||||
Formality: Formality(cfg.Communication.Formality),
|
||||
Humor: Humor(cfg.Communication.Humor),
|
||||
Personality: PersonalityType(cfg.Communication.Personality),
|
||||
ResponseStyle: ResponseStyle(cfg.Communication.ResponseStyle),
|
||||
Quirks: cfg.Communication.Quirks,
|
||||
AvoidTopics: cfg.Communication.AvoidTopics,
|
||||
Catchphrases: cfg.Communication.Catchphrases,
|
||||
},
|
||||
CustomDirectives: cfg.CustomDirectives,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package personality
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// BuildPersonalityPrompt genera un bloque de system prompt a partir de la personalidad.
|
||||
// Esta funcion es pura: recibe datos, devuelve string, sin side effects.
|
||||
func BuildPersonalityPrompt(p Personality) string {
|
||||
if isEmpty(p) {
|
||||
return ""
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteString("## Tu personalidad\n\n")
|
||||
|
||||
// Role y backstory
|
||||
if p.Role != "" || p.Backstory != "" {
|
||||
if p.Backstory != "" {
|
||||
sb.WriteString(p.Backstory)
|
||||
sb.WriteString("\n\n")
|
||||
}
|
||||
if p.Role != "" {
|
||||
sb.WriteString(fmt.Sprintf("**Rol**: %s.\n", p.Role))
|
||||
}
|
||||
}
|
||||
|
||||
// Expertise
|
||||
if len(p.Expertise) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("**Expertise**: %s.\n", strings.Join(p.Expertise, ", ")))
|
||||
}
|
||||
|
||||
// Limitations
|
||||
if len(p.Limitations) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("**Limitaciones**: %s.\n", strings.Join(p.Limitations, ", ")))
|
||||
}
|
||||
|
||||
// Communication style
|
||||
if !isEmptyCommunication(p.Communication) {
|
||||
sb.WriteString("\n**Como te comunicas**:\n")
|
||||
|
||||
if p.Communication.Formality != "" {
|
||||
sb.WriteString(fmt.Sprintf("- Formalidad: %s\n", p.Communication.Formality))
|
||||
}
|
||||
|
||||
if p.Tone != "" {
|
||||
sb.WriteString(fmt.Sprintf("- Tono: %s\n", p.Tone))
|
||||
}
|
||||
|
||||
if p.Communication.Humor != "" {
|
||||
sb.WriteString(fmt.Sprintf("- Humor: %s\n", p.Communication.Humor))
|
||||
}
|
||||
|
||||
if p.Communication.Personality != "" {
|
||||
sb.WriteString(fmt.Sprintf("- Personalidad: %s\n", p.Communication.Personality))
|
||||
}
|
||||
|
||||
if p.Communication.ResponseStyle != "" {
|
||||
sb.WriteString(fmt.Sprintf("- Estilo de respuesta: %s\n", p.Communication.ResponseStyle))
|
||||
}
|
||||
|
||||
if p.Verbosity != "" {
|
||||
sb.WriteString(fmt.Sprintf("- Verbosidad: %s\n", p.Verbosity))
|
||||
}
|
||||
|
||||
if len(p.Communication.Quirks) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("- Rasgos unicos: %s\n", strings.Join(p.Communication.Quirks, "; ")))
|
||||
}
|
||||
|
||||
if len(p.Communication.AvoidTopics) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("- Evitas hablar de: %s\n", strings.Join(p.Communication.AvoidTopics, ", ")))
|
||||
}
|
||||
|
||||
if len(p.Communication.Catchphrases) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("- Frases tipicas: %s\n", strings.Join(p.Communication.Catchphrases, "; ")))
|
||||
}
|
||||
}
|
||||
|
||||
// Custom directives
|
||||
if len(p.CustomDirectives) > 0 {
|
||||
sb.WriteString("\n**Directivas especiales**:\n")
|
||||
for _, directive := range p.CustomDirectives {
|
||||
sb.WriteString(fmt.Sprintf("- %s\n", directive))
|
||||
}
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// isEmpty verifica si la personalidad esta vacia o solo tiene valores por defecto.
|
||||
func isEmpty(p Personality) bool {
|
||||
return p.Role == "" &&
|
||||
p.Backstory == "" &&
|
||||
len(p.Expertise) == 0 &&
|
||||
len(p.Limitations) == 0 &&
|
||||
isEmptyCommunication(p.Communication) &&
|
||||
len(p.CustomDirectives) == 0
|
||||
}
|
||||
|
||||
// isEmptyCommunication verifica si la seccion de comunicacion esta vacia.
|
||||
func isEmptyCommunication(c Communication) bool {
|
||||
return c.Formality == "" &&
|
||||
c.Humor == "" &&
|
||||
c.Personality == "" &&
|
||||
c.ResponseStyle == "" &&
|
||||
len(c.Quirks) == 0 &&
|
||||
len(c.AvoidTopics) == 0 &&
|
||||
len(c.Catchphrases) == 0
|
||||
}
|
||||
@@ -37,6 +37,43 @@ const (
|
||||
ErrorDetailed ErrorStyle = "detailed"
|
||||
)
|
||||
|
||||
type Formality string
|
||||
|
||||
const (
|
||||
FormalityFormal Formality = "formal"
|
||||
FormalitySemiformal Formality = "semiformal"
|
||||
FormalityCasual Formality = "casual"
|
||||
FormalityColoquial Formality = "coloquial"
|
||||
)
|
||||
|
||||
type Humor string
|
||||
|
||||
const (
|
||||
HumorNone Humor = "none"
|
||||
HumorSubtle Humor = "subtle"
|
||||
HumorModerate Humor = "moderate"
|
||||
HumorFrequent Humor = "frequent"
|
||||
)
|
||||
|
||||
type PersonalityType string
|
||||
|
||||
const (
|
||||
PersonalityAnalytical PersonalityType = "analytical"
|
||||
PersonalityCreative PersonalityType = "creative"
|
||||
PersonalityPragmatic PersonalityType = "pragmatic"
|
||||
PersonalityEmpathetic PersonalityType = "empathetic"
|
||||
PersonalityAssertive PersonalityType = "assertive"
|
||||
)
|
||||
|
||||
type ResponseStyle string
|
||||
|
||||
const (
|
||||
ResponseStructured ResponseStyle = "structured"
|
||||
ResponseConversational ResponseStyle = "conversational"
|
||||
ResponseBulletPoints ResponseStyle = "bullet_points"
|
||||
ResponseNarrative ResponseStyle = "narrative"
|
||||
)
|
||||
|
||||
type Templates struct {
|
||||
Greeting string
|
||||
UnknownCommand string
|
||||
@@ -55,6 +92,16 @@ type Behavior struct {
|
||||
AcknowledgeReceipt bool
|
||||
}
|
||||
|
||||
type Communication struct {
|
||||
Formality Formality
|
||||
Humor Humor
|
||||
Personality PersonalityType
|
||||
ResponseStyle ResponseStyle
|
||||
Quirks []string
|
||||
AvoidTopics []string
|
||||
Catchphrases []string
|
||||
}
|
||||
|
||||
type Personality struct {
|
||||
Tone Tone
|
||||
Verbosity Verbosity
|
||||
@@ -65,6 +112,18 @@ type Personality struct {
|
||||
ErrorStyle ErrorStyle
|
||||
Templates Templates
|
||||
Behavior Behavior
|
||||
|
||||
// Identidad narrativa
|
||||
Role string
|
||||
Backstory string
|
||||
Expertise []string
|
||||
Limitations []string
|
||||
|
||||
// Estilo de comunicacion
|
||||
Communication Communication
|
||||
|
||||
// Directivas personalizadas
|
||||
CustomDirectives []string
|
||||
}
|
||||
|
||||
// DefaultPersonality returns a sensible baseline.
|
||||
|
||||
Reference in New Issue
Block a user