mirror of
https://github.com/mudler/LocalAGI.git
synced 2026-07-23 18:55:52 -04:00
dc21ee83bc
* feat: implement 'agent run' CLI command (#448) - Add 'local-agi agent run' command supporting agent name or config file - Support 'local-agi agent run <name>' to run agent from registry (pool.json) - Support 'local-agi agent run --config <file.json>' to run from JSON config - Extract web server into 'local-agi serve' subcommand - Implement agent name lookup from registry - Add JSON config file parsing and validation - Create standalone agent execution logic - Add proper error handling for invalid inputs - Reuse existing service factories (actions, connectors, filters, skills) - Environment variable fallback for config values - No web server - agent runs in foreground with clean SIGINT/SIGTERM handling References: https://github.com/mudler/LocalAGI/issues/448 * refactor(cmd): use pool to start agent instead of duplicating logic Replace ~220 lines of duplicated agent initialization code in startStandaloneAgent() with a call to pool.StartAgentStandalone(). The new pool method delegates to the existing startAgentWithConfig(), eliminating code duplication between the CLI and the pool. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add default help command to root * fix: default to serve command when no subcommand provided The e2e tests fail because when the container starts with no arguments, the root command shows help instead of starting the web server. Changed the root command to call serveCmd.RunE() directly when no subcommand is provided, ensuring the web server starts by default. This fixes the CI e2e test failure where the web server wasn't starting. * fix: add serve subcommand to Dockerfile ENTRYPOINT * refactor: remove unused GetRAGProvider function * refactor: centralize env var setup in cmd/env.go --------- Co-authored-by: localai-bot <localai-bot@noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
105 lines
3.3 KiB
Go
105 lines
3.3 KiB
Go
package cmd
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Env contains all environment variables used by LocalAGI
|
|
type Env struct {
|
|
// Model and API configuration
|
|
Model string
|
|
LLMAPIURL string
|
|
LLMAPIKey string
|
|
MultimodalModel string
|
|
TranscriptionModel string
|
|
TranscriptionLanguage string
|
|
TTSModel string
|
|
Timeout string
|
|
|
|
// Directories and paths
|
|
StateDir string
|
|
LocalRAGURL string
|
|
CustomActionsDir string
|
|
SSHBoxURL string
|
|
CollectionDBPath string
|
|
FileAssets string
|
|
|
|
// Conversation settings
|
|
EnableConversationsLogging bool
|
|
APIKeys []string
|
|
ConversationDuration string
|
|
|
|
// RAG/Vector settings
|
|
VectorEngine string
|
|
EmbeddingModel string
|
|
MaxChunkingSize int
|
|
ChunkOverlap int
|
|
DatabaseURL string
|
|
}
|
|
|
|
// LoadEnv reads all environment variables and returns an Env struct
|
|
func LoadEnv() Env {
|
|
env := Env{
|
|
Model: envOrDefault("LOCALAGI_MODEL", ""),
|
|
LLMAPIURL: envOrDefault("LOCALAGI_LLM_API_URL", ""),
|
|
LLMAPIKey: envOrDefault("LOCALAGI_LLM_API_KEY", ""),
|
|
MultimodalModel: envOrDefault("LOCALAGI_MULTIMODAL_MODEL", ""),
|
|
TranscriptionModel: envOrDefault("LOCALAGI_TRANSCRIPTION_MODEL", ""),
|
|
TranscriptionLanguage: envOrDefault("LOCALAGI_TRANSCRIPTION_LANGUAGE", ""),
|
|
TTSModel: envOrDefault("LOCALAGI_TTS_MODEL", ""),
|
|
Timeout: envOrDefault("LOCALAGI_TIMEOUT", "5m"),
|
|
StateDir: envOrDefault("LOCALAGI_STATE_DIR", ""),
|
|
LocalRAGURL: os.Getenv("LOCALAGI_LOCALRAG_URL"),
|
|
CustomActionsDir: os.Getenv("LOCALAGI_CUSTOM_ACTIONS_DIR"),
|
|
SSHBoxURL: os.Getenv("LOCALAGI_SSHBOX_URL"),
|
|
EnableConversationsLogging: os.Getenv("LOCALAGI_ENABLE_CONVERSATIONS_LOGGING") == "true",
|
|
ConversationDuration: os.Getenv("LOCALAGI_CONVERSATION_DURATION"),
|
|
CollectionDBPath: os.Getenv("COLLECTION_DB_PATH"),
|
|
FileAssets: os.Getenv("FILE_ASSETS"),
|
|
VectorEngine: os.Getenv("VECTOR_ENGINE"),
|
|
EmbeddingModel: os.Getenv("EMBEDDING_MODEL"),
|
|
DatabaseURL: os.Getenv("DATABASE_URL"),
|
|
}
|
|
|
|
// Parse APIKeys from comma-separated string
|
|
if apiKeysEnv := os.Getenv("LOCALAGI_API_KEYS"); apiKeysEnv != "" {
|
|
env.APIKeys = strings.Split(apiKeysEnv, ",")
|
|
}
|
|
|
|
// Parse numeric values
|
|
if maxChunkingSizeEnv := os.Getenv("MAX_CHUNKING_SIZE"); maxChunkingSizeEnv != "" {
|
|
if n, err := strconv.Atoi(maxChunkingSizeEnv); err == nil {
|
|
env.MaxChunkingSize = n
|
|
}
|
|
}
|
|
|
|
if chunkOverlapEnv := os.Getenv("CHUNK_OVERLAP"); chunkOverlapEnv != "" {
|
|
if n, err := strconv.Atoi(chunkOverlapEnv); err == nil {
|
|
env.ChunkOverlap = n
|
|
}
|
|
}
|
|
|
|
// Set defaults for empty values
|
|
if env.VectorEngine == "" {
|
|
env.VectorEngine = "chromem"
|
|
}
|
|
if env.EmbeddingModel == "" {
|
|
env.EmbeddingModel = "granite-embedding-107m-multilingual"
|
|
}
|
|
if env.MaxChunkingSize == 0 {
|
|
env.MaxChunkingSize = 400
|
|
}
|
|
|
|
return env
|
|
}
|
|
|
|
// envOrDefault returns the environment variable value if set, otherwise the fallback.
|
|
func envOrDefault(envKey, fallback string) string {
|
|
if v := os.Getenv(envKey); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|