feat: complete v0.3.1 agent workflow

This commit is contained in:
loveuer
2026-09-15 03:39:22 -07:00
parent 47671f3098
commit 065b30a84c
33 changed files with 4921 additions and 170 deletions
+32 -11
View File
@@ -13,6 +13,7 @@ import (
"agentu/internal/agent"
"agentu/internal/session"
"agentu/internal/skills"
"agentu/internal/tools"
"agentu/internal/tui"
"agentu/pkg/config"
@@ -40,8 +41,20 @@ func Run() error {
return err
}
globalSkills, err := skills.LoadGlobal()
if err != nil {
return fmt.Errorf("load global skills: %w", err)
}
rollbackStore := tools.NewRollbackStore()
var approvalBroker *tui.ApprovalBroker
var authorizer agent.ToolAuthorizer
if !opts.yolo && !opts.plain {
approvalBroker = tui.NewApprovalBroker()
authorizer = approvalBroker
}
providerName, providerConfig, provider := defaultProvider(cfg, http.DefaultClient)
assistant := newAssistant(cfg, providerName, providerConfig, provider, opts.yolo, http.DefaultClient)
assistant := newAssistant(cfg, providerName, providerConfig, provider, opts, globalSkills, authorizer, rollbackStore, http.DefaultClient)
modelManager, err := newSessionManager(cfg, assistant, http.DefaultClient)
if err != nil {
return err
@@ -54,7 +67,7 @@ func Run() error {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
return runInterface(ctx, assistant, modelManager, providerConfig, cfg.Agent.WorkingDir, opts, themeMode)
return runInterface(ctx, assistant, modelManager, providerConfig, cfg.Agent.WorkingDir, opts, themeMode, approvalBroker, rollbackStore)
}
func parseCLIOptions() cliOptions {
@@ -102,7 +115,8 @@ func newProviderClient(providerConfig config.ProviderConfig, httpClient *http.Cl
return llm.NewOpenAICompatibleClient(providerConfig.BaseURL, providerConfig.APIKey, httpClient)
}
func newAssistant(cfg *config.Config, providerName string, providerConfig config.ProviderConfig, provider llm.Provider, yolo bool, httpClient *http.Client) *agent.Agent {
func newAssistant(cfg *config.Config, providerName string, providerConfig config.ProviderConfig, provider llm.Provider, opts cliOptions, globalSkills []skills.Skill, authorizer agent.ToolAuthorizer, rollbackStore *tools.RollbackStore, httpClient *http.Client) *agent.Agent {
writesEnabled := opts.yolo || !opts.plain
return agent.New(agent.Options{
Provider: provider,
ProviderName: providerName,
@@ -110,16 +124,21 @@ func newAssistant(cfg *config.Config, providerName string, providerConfig config
Thinking: providerConfig.Thinking,
ThinkingParam: providerConfig.ThinkingParam,
ThinkingEnabled: providerConfig.ThinkingConfigured,
SystemPrompt: systemPrompt(cfg, yolo),
ToolRegistry: newToolRegistry(cfg.Agent.WorkingDir, yolo, httpClient),
SystemPrompt: systemPrompt(cfg, writesEnabled, opts.yolo, globalSkills),
ToolRegistry: newToolRegistry(cfg.Agent.WorkingDir, writesEnabled, httpClient),
Authorizer: authorizer,
RollbackStore: rollbackStore,
ToolTimeout: cfg.Agent.ToolTimeout,
MaxContextTokens: maxContextTokens(cfg, providerConfig),
})
}
func systemPrompt(cfg *config.Config, yolo bool) string {
instructions := tools.AgentInstructions(cfg.Agent.WorkingDir, yolo)
return strings.TrimSpace(cfg.Agent.SystemPrompt + "\n\n" + instructions)
func systemPrompt(cfg *config.Config, writesEnabled bool, yolo bool, globalSkills []skills.Skill) string {
parts := []string{cfg.Agent.SystemPrompt, tools.AgentInstructionsForMode(cfg.Agent.WorkingDir, writesEnabled, yolo)}
if formatted := skills.FormatForSystemPrompt(globalSkills); formatted != "" {
parts = append(parts, formatted)
}
return strings.TrimSpace(strings.Join(parts, "\n\n"))
}
func maxContextTokens(cfg *config.Config, providerConfig config.ProviderConfig) int {
@@ -129,9 +148,9 @@ func maxContextTokens(cfg *config.Config, providerConfig config.ProviderConfig)
return providerConfig.ContextTokens
}
func newToolRegistry(workingDir string, yolo bool, httpClient *http.Client) *tools.Registry {
func newToolRegistry(workingDir string, writesEnabled bool, httpClient *http.Client) *tools.Registry {
var registry *tools.Registry
if yolo {
if writesEnabled {
registry = tools.Builtins(workingDir)
} else {
registry = tools.ReadOnlyBuiltins(workingDir)
@@ -154,7 +173,7 @@ func newSessionManager(cfg *config.Config, assistant *agent.Agent, httpClient *h
return session.NewManager(cfg, assistant, httpClient, store)
}
func runInterface(ctx context.Context, assistant *agent.Agent, modelManager *session.Manager, providerConfig config.ProviderConfig, workingDir string, opts cliOptions, themeMode tui.ThemeMode) error {
func runInterface(ctx context.Context, assistant *agent.Agent, modelManager *session.Manager, providerConfig config.ProviderConfig, workingDir string, opts cliOptions, themeMode tui.ThemeMode, approvalBroker *tui.ApprovalBroker, rollbackStore *tools.RollbackStore) error {
if opts.plain {
return repl(ctx, assistant, modelManager)
}
@@ -165,6 +184,8 @@ func runInterface(ctx context.Context, assistant *agent.Agent, modelManager *ses
ThemeMode: themeMode,
ModelManager: modelManager,
WorkingDir: workingDir,
Approval: approvalBroker,
Rollback: rollbackStore,
})
printExitSession(modelManager)
return err