mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 00:14:33 +00:00
feat(agent): inject TTS [[tts]] directive guidance when auto mode is "tagged"
- Add TTSAutoMode field to LoopConfig, Loop, SystemPromptConfig - Wire from config.Tts.Auto through resolver to system prompt - Inject "## Voice Response" section explaining [[tts]] usage - Update AGENTS.md: voice only when user explicitly requests
This commit is contained in:
1 parent
a050079ade
commit
085b89bf72
7 files changed
+43
-1
No files matched your search
@@ -235,6 +235,7 @@ func wireExtras(
|
||||
SkillTenantCfgs: stores.SkillTenantCfgs,
|
||||
SystemConfigs: stores.SystemConfigs,
|
||||
Workspace: workspace,
|
||||
TTSAutoMode: appCfg.Tts.Auto,
|
||||
AutoInjector: autoInjector,
|
||||
EvolutionMetricsStore: stores.EvolutionMetrics,
|
||||
DomainBus: domainBus,
|
||||
|
||||
@@ -231,6 +231,7 @@ func (l *Loop) buildMessages(ctx context.Context, history []providers.Message, s
|
||||
SandboxWorkspaceAccess: l.sandboxWorkspaceAccess,
|
||||
ShellDenyGroups: l.shellDenyGroups,
|
||||
SelfEvolve: l.selfEvolve,
|
||||
TTSAutoMode: l.ttsAutoMode,
|
||||
ProviderType: providerTypeOf(l.provider),
|
||||
CredentialCLIContext: l.buildCredentialCLIContext(ctx),
|
||||
IsBootstrap: hadBootstrap && l.agentType != store.AgentTypePredefined,
|
||||
|
||||
@@ -200,6 +200,9 @@ type Loop struct {
|
||||
// Self-evolve: predefined agents can update SOUL.md through chat
|
||||
selfEvolve bool
|
||||
|
||||
// TTS auto mode from config: "off", "always", "inbound", "tagged"
|
||||
ttsAutoMode string
|
||||
|
||||
// Skill learning loop: when skillEvolve=true, the loop injects nudges reminding
|
||||
// the agent to capture reusable patterns as skills via skill_manage.
|
||||
skillEvolve bool
|
||||
@@ -388,6 +391,10 @@ type LoopConfig struct {
|
||||
// Self-evolve: predefined agents can update SOUL.md (style/tone) through chat
|
||||
SelfEvolve bool
|
||||
|
||||
// TTS auto mode from config: "off", "always", "inbound", "tagged"
|
||||
// When "tagged", inject [[tts]] directive guidance into system prompt.
|
||||
TTSAutoMode string
|
||||
|
||||
// Skill evolution: agent learning loop config (from other_config JSONB)
|
||||
SkillEvolve bool
|
||||
SkillNudgeInterval int // 0 = disabled, 15 = default
|
||||
@@ -529,6 +536,7 @@ func NewLoop(cfg LoopConfig) *Loop {
|
||||
promptMode: cfg.PromptMode,
|
||||
pinnedSkills: cfg.PinnedSkills,
|
||||
selfEvolve: cfg.SelfEvolve,
|
||||
ttsAutoMode: cfg.TTSAutoMode,
|
||||
skillEvolve: cfg.SkillEvolve,
|
||||
skillNudgeInterval: cfg.SkillNudgeInterval,
|
||||
isTeamLead: cfg.IsTeamLead,
|
||||
|
||||
@@ -120,6 +120,9 @@ type ResolverDeps struct {
|
||||
// Global workspace root (GOCLAW_WORKSPACE)
|
||||
Workspace string
|
||||
|
||||
// TTS auto mode from config: "off", "always", "inbound", "tagged"
|
||||
TTSAutoMode string
|
||||
|
||||
// V3 auto-inject: episodic memory injection into system prompt (nil = disabled)
|
||||
AutoInjector memory.AutoInjector
|
||||
|
||||
@@ -511,6 +514,7 @@ func NewManagedResolver(deps ResolverDeps) ResolverFunc {
|
||||
PromptMode: PromptMode(ag.ParsePromptMode()),
|
||||
PinnedSkills: ag.ParsePinnedSkills(),
|
||||
SelfEvolve: ag.ParseSelfEvolve(),
|
||||
TTSAutoMode: deps.TTSAutoMode,
|
||||
SkillEvolve: ag.AgentType == store.AgentTypePredefined && ag.ParseSkillEvolve(),
|
||||
SkillNudgeInterval: ag.ParseSkillNudgeInterval(),
|
||||
WorkspaceSharing: ag.ParseWorkspaceSharing(),
|
||||
|
||||
@@ -135,6 +135,10 @@ type SystemPromptConfig struct {
|
||||
// Self-evolution: predefined agents can update SOUL.md (style/tone)
|
||||
SelfEvolve bool
|
||||
|
||||
// TTSAutoMode: "off", "always", "inbound", "tagged". When "tagged", inject
|
||||
// [[tts]] directive guidance so the agent knows how to trigger voice responses.
|
||||
TTSAutoMode string
|
||||
|
||||
// ShellDenyGroups holds effective deny group overrides for this agent.
|
||||
// nil = all defaults. Used to adapt system prompt instructions.
|
||||
ShellDenyGroups map[string]bool
|
||||
@@ -327,6 +331,11 @@ func BuildSystemPrompt(cfg SystemPromptConfig) string {
|
||||
lines = append(lines, cfg.CredentialCLIContext, "")
|
||||
}
|
||||
|
||||
// 2.6. ## Voice Response — inject when TTS auto mode is "tagged"
|
||||
if (isFull || isTask) && !cfg.IsBootstrap && cfg.TTSAutoMode == "tagged" {
|
||||
lines = append(lines, buildVoiceResponseSection()...)
|
||||
}
|
||||
|
||||
// 3. ## Safety — task/none get slim version (keeps prompt injection defense)
|
||||
if isTask || isNone {
|
||||
lines = append(lines, buildSafetySlimSection()...)
|
||||
|
||||
@@ -729,3 +729,22 @@ func buildTeamMembersSection(members []store.TeamMemberData, teamGuidance string
|
||||
lines = append(lines, "")
|
||||
return lines
|
||||
}
|
||||
|
||||
// buildVoiceResponseSection generates guidance for triggering auto TTS in "tagged" mode.
|
||||
// When TTS auto mode is "tagged", agent responses containing [[tts]] are converted to voice.
|
||||
func buildVoiceResponseSection() []string {
|
||||
return []string{
|
||||
"## Voice Response",
|
||||
"",
|
||||
"You can respond with voice/audio by wrapping text with `[[tts]]`:",
|
||||
"",
|
||||
"```",
|
||||
"[[tts]]This text will be spoken aloud.[[/tts]]",
|
||||
"```",
|
||||
"",
|
||||
"**ONLY use [[tts]] when the user explicitly asks for voice/audio response.**",
|
||||
"Examples: \"read this aloud\", \"respond with voice\", \"speak this\", \"tell me a story (voice)\".",
|
||||
"Do NOT add [[tts]] just because you think it would be nice — text is the default.",
|
||||
"",
|
||||
}
|
||||
}
|
||||
@@ -113,4 +113,4 @@ Tips:
|
||||
|
||||
## Voice
|
||||
|
||||
If you have TTS capability, use voice for stories and "storytime" moments — more engaging than walls of text.
|
||||
If you have TTS capability, only use voice when the user explicitly asks for it (e.g. "read aloud", "respond with voice", "tell me a story in voice").
|
||||
Reference in new issue
Block a user