mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-05-25 16:00:35 +00:00
2992eccbf0
* feat: add request-scoped context policies Add named turn profiles under agents.defaults so callers can opt into per-request context and tool policies without changing default chat behavior. Profiles can disable history, system context, skill prompts, or tools, and can limit skills/tools with allow lists. Wire profile selection through Pico message payloads, agent turn execution, Web chat selection, and Web visual config. Reject invalid turn profiles before saving config through Web APIs and document the new request context policy behavior. * fix: address turn profile review blockers * feat: simplify request context policy config * fix: suppress tool prompt when turn tools are disabled * fix: enforce turn profile tool restrictions
132 lines
3.2 KiB
Go
132 lines
3.2 KiB
Go
package agent
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/sipeed/picoclaw/pkg/config"
|
|
"github.com/sipeed/picoclaw/pkg/providers"
|
|
)
|
|
|
|
func resolveTurnProfileOptions(cfg *config.Config, opts processOptions) (processOptions, error) {
|
|
if cfg == nil {
|
|
return opts, nil
|
|
}
|
|
profile, ok, err := cfg.Agents.Defaults.ResolveTurnProfile()
|
|
if err != nil {
|
|
return opts, err
|
|
}
|
|
if !ok {
|
|
return opts, nil
|
|
}
|
|
opts.TurnProfile = profile
|
|
if profile.HistoryMode == config.TurnProfileModeOff {
|
|
opts.NoHistory = true
|
|
opts.EnableSummary = false
|
|
}
|
|
return opts, nil
|
|
}
|
|
|
|
func turnProfileSystemPromptOff(profile config.EffectiveTurnProfile) bool {
|
|
return profile.Enabled && profile.SystemPromptMode == config.TurnProfileModeOff
|
|
}
|
|
|
|
func turnProfileSkillsOff(profile config.EffectiveTurnProfile) bool {
|
|
return profile.Enabled && profile.SkillsMode == config.TurnProfileModeOff
|
|
}
|
|
|
|
func turnProfileCustomSkills(profile config.EffectiveTurnProfile) bool {
|
|
return profile.Enabled && profile.SkillsMode == config.TurnProfileModeCustom
|
|
}
|
|
|
|
func turnProfileHasCallableTools(
|
|
profile config.EffectiveTurnProfile,
|
|
defs []providers.ToolDefinition,
|
|
) bool {
|
|
if !profile.Enabled {
|
|
return true
|
|
}
|
|
return len(filterToolsByTurnProfile(defs, profile)) > 0
|
|
}
|
|
|
|
func turnProfileToolAllowed(profile config.EffectiveTurnProfile, name string) bool {
|
|
if !profile.Enabled {
|
|
return true
|
|
}
|
|
switch profile.ToolsMode {
|
|
case config.TurnProfileModeOff:
|
|
return false
|
|
case config.TurnProfileModeCustom:
|
|
allowed := cleanAllowedSet(profile.AllowedTools)
|
|
if len(allowed) == 0 {
|
|
return false
|
|
}
|
|
_, ok := allowed[strings.ToLower(strings.TrimSpace(name))]
|
|
return ok
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
|
|
func toolUseSystemPromptRule() string {
|
|
return "**ALWAYS use tools** - When you need to perform an action (schedule reminders, send messages, execute commands, etc.), you MUST call the appropriate tool. Do NOT just say you'll do it or pretend to do it."
|
|
}
|
|
|
|
func filterNamesByTurnProfile(names []string, allowed []string) []string {
|
|
if len(names) == 0 {
|
|
return nil
|
|
}
|
|
allowedSet := cleanAllowedSet(allowed)
|
|
if len(allowedSet) == 0 {
|
|
return nil
|
|
}
|
|
out := make([]string, 0, len(names))
|
|
for _, name := range names {
|
|
if _, ok := allowedSet[strings.ToLower(strings.TrimSpace(name))]; ok {
|
|
out = append(out, name)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func filterToolsByTurnProfile(
|
|
defs []providers.ToolDefinition,
|
|
profile config.EffectiveTurnProfile,
|
|
) []providers.ToolDefinition {
|
|
if !profile.Enabled {
|
|
return defs
|
|
}
|
|
switch profile.ToolsMode {
|
|
case config.TurnProfileModeOff:
|
|
return nil
|
|
case config.TurnProfileModeCustom:
|
|
allowed := cleanAllowedSet(profile.AllowedTools)
|
|
if len(allowed) == 0 {
|
|
return nil
|
|
}
|
|
filtered := make([]providers.ToolDefinition, 0, len(defs))
|
|
for _, def := range defs {
|
|
if _, ok := allowed[strings.ToLower(strings.TrimSpace(def.Function.Name))]; ok {
|
|
filtered = append(filtered, def)
|
|
}
|
|
}
|
|
return filtered
|
|
default:
|
|
return defs
|
|
}
|
|
}
|
|
|
|
func cleanAllowedSet(values []string) map[string]struct{} {
|
|
if len(values) == 0 {
|
|
return nil
|
|
}
|
|
out := make(map[string]struct{}, len(values))
|
|
for _, value := range values {
|
|
value = strings.ToLower(strings.TrimSpace(value))
|
|
if value == "" {
|
|
continue
|
|
}
|
|
out[value] = struct{}{}
|
|
}
|
|
return out
|
|
}
|