mirror of
https://github.com/mudler/LocalAGI.git
synced 2026-07-23 18:55:52 -04:00
feat: add --prompt flag for foreground agent mode (#454)
* feat: add --prompt flag for foreground agent mode - Add --prompt/-p flag to 'agent run' command - When --prompt is provided, runs agent in foreground mode - Creates agent, executes Ask() with the prompt, prints response, and exits - Supports both agent name and --config file input modes - Follows existing code patterns in the repository * fix: correct JobResult field access for error and response --------- Co-authored-by: localai-bot <localai-bot@noreply.github.com>
This commit is contained in:
+113
-1
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mudler/LocalAGI/core/state"
|
||||
"github.com/mudler/LocalAGI/core/types"
|
||||
"github.com/mudler/LocalAGI/services"
|
||||
"github.com/mudler/LocalAGI/services/skills"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
|
||||
var (
|
||||
configFile string
|
||||
prompt string
|
||||
)
|
||||
|
||||
var agentRunCmd = &cobra.Command{
|
||||
@@ -27,9 +29,10 @@ var agentRunCmd = &cobra.Command{
|
||||
Two modes are supported:
|
||||
1. Run an agent by name from the registry (pool.json):
|
||||
local-agi agent run my-agent
|
||||
|
||||
2. Run an agent from a JSON config file:
|
||||
local-agi agent run --config agent.json
|
||||
3. Run an agent in foreground mode with a prompt:
|
||||
local-agi agent run my-agent --prompt "Your question here"
|
||||
|
||||
The agent runs in the foreground until interrupted (Ctrl+C).`,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
@@ -38,6 +41,7 @@ The agent runs in the foreground until interrupted (Ctrl+C).`,
|
||||
|
||||
func init() {
|
||||
agentRunCmd.Flags().StringVarP(&configFile, "config", "c", "", "path to agent JSON config file")
|
||||
agentRunCmd.Flags().StringVarP(&prompt, "prompt", "p", "", "run in foreground mode with the given prompt and exit after response")
|
||||
}
|
||||
|
||||
func runAgent(cmd *cobra.Command, args []string) error {
|
||||
@@ -46,9 +50,117 @@ func runAgent(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// If --prompt is provided, run in foreground mode
|
||||
if prompt != "" {
|
||||
return runAgentForeground(agentName, agentConfig, prompt)
|
||||
}
|
||||
|
||||
return startStandaloneAgent(agentName, agentConfig)
|
||||
}
|
||||
|
||||
// runAgentForeground runs an agent in foreground mode with a single prompt,
|
||||
// prints the response, and exits.
|
||||
func runAgentForeground(agentName string, agentConfig *state.AgentConfig, promptText string) error {
|
||||
// Load all environment variables
|
||||
env := LoadEnv()
|
||||
|
||||
if env.Model == "" {
|
||||
env.Model = agentConfig.Model
|
||||
}
|
||||
if env.LLMAPIURL == "" {
|
||||
env.LLMAPIURL = agentConfig.APIURL
|
||||
}
|
||||
if env.LLMAPIKey == "" {
|
||||
env.LLMAPIKey = agentConfig.APIKey
|
||||
}
|
||||
|
||||
if env.Model == "" {
|
||||
return fmt.Errorf("model not set: provide 'model' in config or set LOCALAGI_MODEL")
|
||||
}
|
||||
if env.LLMAPIURL == "" {
|
||||
return fmt.Errorf("API URL not set: provide 'api_url' in config or set LOCALAGI_LLM_API_URL")
|
||||
}
|
||||
|
||||
if env.StateDir == "" {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get working directory: %w", err)
|
||||
}
|
||||
env.StateDir = filepath.Join(cwd, "pool")
|
||||
}
|
||||
os.MkdirAll(env.StateDir, 0755)
|
||||
|
||||
// Override config with resolved values
|
||||
agentConfig.Model = env.Model
|
||||
agentConfig.APIURL = env.LLMAPIURL
|
||||
agentConfig.APIKey = env.LLMAPIKey
|
||||
agentConfig.MultimodalModel = env.MultimodalModel
|
||||
agentConfig.TranscriptionModel = env.TranscriptionModel
|
||||
agentConfig.TranscriptionLanguage = env.TranscriptionLanguage
|
||||
agentConfig.TTSModel = env.TTSModel
|
||||
|
||||
// Initialize skills service
|
||||
skillsService, err := skills.NewService(env.StateDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize skills service: %w", err)
|
||||
}
|
||||
|
||||
// Build service factories
|
||||
actionsFactory := services.Actions(map[string]string{
|
||||
services.ActionConfigSSHBoxURL: env.SSHBoxURL,
|
||||
services.ConfigStateDir: env.StateDir,
|
||||
services.CustomActionsDir: env.CustomActionsDir,
|
||||
})
|
||||
dynamicPromptsFactory := services.DynamicPrompts(map[string]string{
|
||||
services.ConfigStateDir: env.StateDir,
|
||||
services.CustomActionsDir: env.CustomActionsDir,
|
||||
})
|
||||
|
||||
// Create the pool
|
||||
pool, err := state.NewAgentPool(
|
||||
env.Model, env.MultimodalModel, env.TranscriptionModel, env.TranscriptionLanguage, env.TTSModel,
|
||||
env.LLMAPIURL, env.LLMAPIKey, env.StateDir,
|
||||
actionsFactory, services.Connectors, dynamicPromptsFactory, services.Filters,
|
||||
env.Timeout, false, skillsService,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create agent pool: %w", err)
|
||||
}
|
||||
|
||||
if env.LocalRAGURL != "" {
|
||||
pool.SetRAGProvider(state.NewHTTPRAGProvider(env.LocalRAGURL, env.LLMAPIKey))
|
||||
}
|
||||
|
||||
// Start the agent
|
||||
if err := pool.StartAgentStandalone(agentName, agentConfig); err != nil {
|
||||
return fmt.Errorf("failed to start agent: %w", err)
|
||||
}
|
||||
|
||||
a := pool.GetAgent(agentName)
|
||||
if a == nil {
|
||||
return fmt.Errorf("agent %q was not found after starting", agentName)
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Running agent %q in foreground mode with prompt...\n", agentName)
|
||||
|
||||
// Execute Ask with the prompt using WithText option
|
||||
result := a.Ask(types.WithText(promptText))
|
||||
|
||||
// Print the result
|
||||
if result.Error != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s\n", result.Error.Error())
|
||||
pool.Stop(agentName)
|
||||
return fmt.Errorf("agent error: %s", result.Error.Error())
|
||||
}
|
||||
|
||||
// Print the response
|
||||
fmt.Println(result.Response)
|
||||
|
||||
// Clean up
|
||||
pool.Stop(agentName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// resolveAgentConfig determines the agent name and config from either
|
||||
// a registry lookup or a JSON config file.
|
||||
func resolveAgentConfig(args []string) (string, *state.AgentConfig, error) {
|
||||
|
||||
Reference in New Issue
Block a user