diff --git a/cmd/olliesrv/internal/agent/agent_config.go b/cmd/olliesrv/internal/agent/agent_config.go index c598d6f..501b69e 100644 --- a/cmd/olliesrv/internal/agent/agent_config.go +++ b/cmd/olliesrv/internal/agent/agent_config.go @@ -24,6 +24,7 @@ func (p *Prompt) UnmarshalJSON(data []byte) error { type AgentConfig struct { Prompt Prompt `json:"prompt,omitempty"` + UserPrompts Prompt `json:"userPrompts,omitempty"` Backend string `json:"backend,omitempty"` Model string `json:"model,omitempty"` Tools *bool `json:"tools,omitempty"` diff --git a/cmd/olliesrv/internal/agent/runtime.go b/cmd/olliesrv/internal/agent/runtime.go index a9c2f3d..b527c86 100644 --- a/cmd/olliesrv/internal/agent/runtime.go +++ b/cmd/olliesrv/internal/agent/runtime.go @@ -129,16 +129,17 @@ func RenderTools(infos []toolsrv.ToolInfo) string { // agent. The agent struct stores a pointer to the active Runtime; switching // agents replaces it atomically. type Runtime struct { - Backend backend.Backend - ToolServer *toolsrv.Conn - Preamble *Preamble - Tools []backend.Tool - ToolMeta map[string]toolsrv.ToolInfo - Exec toolExecutor - GenParams backend.GenerationParams - MaxSteps int + Backend backend.Backend + ToolServer *toolsrv.Conn + Preamble *Preamble + Tools []backend.Tool + ToolMeta map[string]toolsrv.ToolInfo + Exec toolExecutor + GenParams backend.GenerationParams + MaxSteps int CompactionModel string - Messages []string + UserPrompt string // resolved user prompts, prepended to each turn's input + Messages []string } // PreambleString returns the fully rendered system prompt. @@ -167,6 +168,7 @@ func BuildRuntime(cfg *AgentConfig, srv *toolsrv.Conn, cwd string, env []string, } var agentPrompt string + var userPrompt string var genParams backend.GenerationParams var maxSteps int if cfg != nil { @@ -175,6 +177,11 @@ func BuildRuntime(cfg *AgentConfig, srv *toolsrv.Conn, cwd string, env []string, } else { agentPrompt = resolved } + if resolved, err := resolvePrompt(cfg.UserPrompts, cwd, env); err != nil { + fmt.Fprintf(os.Stderr, "resolve user prompts: %v\n", err) + } else { + userPrompt = resolved + } genParams = cfg.GenerationParams maxSteps = cfg.MaxSteps } @@ -221,6 +228,7 @@ func BuildRuntime(cfg *AgentConfig, srv *toolsrv.Conn, cwd string, env []string, GenParams: genParams, MaxSteps: maxSteps, CompactionModel: compactionModel, + UserPrompt: userPrompt, Messages: messages, } } diff --git a/cmd/olliesrv/internal/agent/turn.go b/cmd/olliesrv/internal/agent/turn.go index 58b3bb5..68ff578 100644 --- a/cmd/olliesrv/internal/agent/turn.go +++ b/cmd/olliesrv/internal/agent/turn.go @@ -84,6 +84,11 @@ func (ag *Agent) Submit(ctx context.Context, input string) { // executeTurn runs a single agent turn and returns the next prompt to execute, // or "" if there is nothing more to do. func (ag *Agent) executeTurn(ctx context.Context, input string) string { + // Prepend resolved user prompts (active global rules) to the user input. + if ag.runtime.UserPrompt != "" { + input = ag.runtime.UserPrompt + "\n\n" + input + } + ag.emit(Event{Role: "user", Content: input}) // Snapshot messages before this turn modifies them. Restored on context