Combines three repositories into a single workspace: - go-agent → pkg/orchestrator (Clotho), pkg/jobrunner, pkg/loop, cmd/ - go-agentic → pkg/lifecycle (allowance, sessions, plans, dispatch) - php-devops → repos.yaml, setup.sh, scripts/, .core/ Module path: forge.lthn.ai/core/agent All packages build, all tests pass. Co-Authored-By: Virgil <virgil@lethean.io>
71 lines
2.2 KiB
Go
71 lines
2.2 KiB
Go
package loop
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// BuildSystemPrompt constructs the system prompt that instructs the model how
|
|
// to use the available tools. When no tools are registered it returns a plain
|
|
// assistant preamble without tool-calling instructions.
|
|
func BuildSystemPrompt(tools []Tool) string {
|
|
if len(tools) == 0 {
|
|
return "You are a helpful assistant."
|
|
}
|
|
|
|
var b strings.Builder
|
|
b.WriteString("You are a helpful assistant with access to the following tools:\n\n")
|
|
|
|
for _, tool := range tools {
|
|
b.WriteString(fmt.Sprintf("### %s\n", tool.Name))
|
|
b.WriteString(fmt.Sprintf("%s\n", tool.Description))
|
|
if tool.Parameters != nil {
|
|
schema, _ := json.MarshalIndent(tool.Parameters, "", " ")
|
|
b.WriteString(fmt.Sprintf("Parameters: %s\n", schema))
|
|
}
|
|
b.WriteString("\n")
|
|
}
|
|
|
|
b.WriteString("To use a tool, output a fenced block:\n")
|
|
b.WriteString("```tool\n")
|
|
b.WriteString("{\"name\": \"tool_name\", \"args\": {\"key\": \"value\"}}\n")
|
|
b.WriteString("```\n\n")
|
|
b.WriteString("You may call multiple tools in one response. After tool results are provided, continue reasoning. When you have a final answer, respond normally without tool blocks.\n")
|
|
|
|
return b.String()
|
|
}
|
|
|
|
// BuildFullPrompt assembles the complete prompt string from the system prompt,
|
|
// conversation history, and current user message. Each message is tagged with
|
|
// its role so the model can distinguish turns. Tool results are annotated with
|
|
// the tool name for traceability.
|
|
func BuildFullPrompt(system string, history []Message, userMessage string) string {
|
|
var b strings.Builder
|
|
|
|
if system != "" {
|
|
b.WriteString(system)
|
|
b.WriteString("\n\n")
|
|
}
|
|
|
|
for _, msg := range history {
|
|
switch msg.Role {
|
|
case RoleUser:
|
|
b.WriteString(fmt.Sprintf("[user]\n%s\n\n", msg.Content))
|
|
case RoleAssistant:
|
|
b.WriteString(fmt.Sprintf("[assistant]\n%s\n\n", msg.Content))
|
|
case RoleToolResult:
|
|
toolName := "unknown"
|
|
if len(msg.ToolUses) > 0 {
|
|
toolName = msg.ToolUses[0].Name
|
|
}
|
|
b.WriteString(fmt.Sprintf("[tool_result: %s]\n%s\n\n", toolName, msg.Content))
|
|
}
|
|
}
|
|
|
|
if userMessage != "" {
|
|
b.WriteString(fmt.Sprintf("[user]\n%s\n\n", userMessage))
|
|
}
|
|
|
|
return b.String()
|
|
}
|