mirror of
https://github.com/mudler/LocalAI.git
synced 2026-04-01 05:36:49 -04:00
* feat: add distributed mode (experimental) Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix data races, mutexes, transactions Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactorings Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fixups Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix events and tool stream in agent chat Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * use ginkgo Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * fix(cron): compute correctly time boundaries avoiding re-triggering Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * enhancements, refactorings Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * do not flood of healthy checks Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * do not list obvious backends as text backends Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * tests fixups Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * refactoring and consolidation Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * Drop redundant healthcheck Signed-off-by: Ettore Di Giacinto <mudler@localai.io> * enhancements, refactorings Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
218 lines
7.9 KiB
Go
218 lines
7.9 KiB
Go
package agents
|
|
|
|
import "encoding/json"
|
|
|
|
// KB mode constants for AgentConfig.KBMode.
|
|
const (
|
|
KBModeAutoSearch = "auto_search" // default: auto-search KB on each user message
|
|
KBModeTools = "tools" // expose search_memory / add_memory as agent tools
|
|
KBModeBoth = "both" // auto-search + tools
|
|
)
|
|
|
|
// Skills mode constants for AgentConfig.SkillsMode.
|
|
const (
|
|
SkillsModePrompt = "prompt" // default: inject skill descriptions into system prompt
|
|
SkillsModeTools = "tools" // expose skills as callable tools
|
|
SkillsModeBoth = "both" // both prompt + tools
|
|
)
|
|
|
|
// Conversation storage mode constants for AgentConfig.ConversationStorageMode.
|
|
const (
|
|
ConvStorageUserOnly = "user_only" // default: store only user messages
|
|
ConvStorageUserAndAssistant = "user_and_assistant" // store user and assistant messages separately
|
|
ConvStorageWholeConversation = "whole_conversation" // store entire conversation as single block
|
|
)
|
|
|
|
// AgentConfig defines the configuration for an agent.
|
|
// JSON field names match LocalAGI's state.AgentConfig for import/export compatibility.
|
|
type AgentConfig struct {
|
|
// Integrations
|
|
Connector []ConnectorConfig `json:"connectors"`
|
|
Actions []ActionsConfig `json:"actions"`
|
|
DynamicPrompts []DynamicPromptsConfig `json:"dynamic_prompts"`
|
|
MCPServers []MCPServer `json:"mcp_servers"`
|
|
MCPSTDIOServers MCPSTDIOServers `json:"mcp_stdio_servers"`
|
|
MCPPrepareScript string `json:"mcp_prepare_script"`
|
|
Filters []FiltersConfig `json:"filters"`
|
|
|
|
// Basic info
|
|
Description string `json:"description"`
|
|
Name string `json:"name"`
|
|
|
|
// Models
|
|
Model string `json:"model"`
|
|
MultimodalModel string `json:"multimodal_model"`
|
|
TranscriptionModel string `json:"transcription_model"`
|
|
TranscriptionLanguage string `json:"transcription_language"`
|
|
TTSModel string `json:"tts_model"`
|
|
|
|
// API
|
|
APIURL string `json:"api_url"`
|
|
APIKey string `json:"api_key"`
|
|
LocalRAGURL string `json:"local_rag_url"`
|
|
LocalRAGAPIKey string `json:"local_rag_api_key"`
|
|
|
|
// Timing
|
|
LastMessageDuration string `json:"last_message_duration"`
|
|
PeriodicRuns string `json:"periodic_runs"`
|
|
SchedulerPollInterval string `json:"scheduler_poll_interval"`
|
|
|
|
// Behavior
|
|
StandaloneJob bool `json:"standalone_job"`
|
|
InitiateConversations bool `json:"initiate_conversations"`
|
|
CanPlan bool `json:"enable_planning"`
|
|
PlanReviewerModel string `json:"plan_reviewer_model"`
|
|
DisableSinkState bool `json:"disable_sink_state"` // legacy, kept for JSON compat — sink state is always disabled
|
|
PermanentGoal string `json:"permanent_goal"`
|
|
SystemPrompt string `json:"system_prompt"`
|
|
SkillsPrompt string `json:"skills_prompt"`
|
|
InnerMonologueTemplate string `json:"inner_monologue_template"`
|
|
SchedulerTaskTemplate string `json:"scheduler_task_template"`
|
|
|
|
// Knowledge base
|
|
EnableKnowledgeBase bool `json:"enable_kb"`
|
|
KBMode string `json:"kb_mode,omitempty"` // "auto_search" (default), "tools", "both"
|
|
KnowledgeBaseResults int `json:"kb_results"`
|
|
EnableKBCompaction bool `json:"enable_kb_compaction"`
|
|
KBCompactionInterval string `json:"kb_compaction_interval"`
|
|
KBCompactionSummarize bool `json:"kb_compaction_summarize"`
|
|
KBAutoSearch bool `json:"kb_auto_search"` // legacy, kept for JSON compat
|
|
KBAsTools bool `json:"kb_as_tools"` // legacy, kept for JSON compat
|
|
|
|
// Reasoning & tools
|
|
EnableReasoning bool `json:"enable_reasoning"` // legacy, kept for JSON compat
|
|
EnableForceReasoningTool bool `json:"enable_reasoning_tool"` // legacy, kept for JSON compat
|
|
EnableReasoningForInstruct bool `json:"enable_reasoning_for_instruct"` // enables ForceReasoning + ForceReasoningTool
|
|
EnableGuidedTools bool `json:"enable_guided_tools"`
|
|
CanStopItself bool `json:"can_stop_itself"`
|
|
|
|
// Skills
|
|
EnableSkills bool `json:"enable_skills"`
|
|
SkillsMode string `json:"skills_mode,omitempty"` // "prompt" (default), "tools", or "both"
|
|
SelectedSkills []string `json:"selected_skills,omitempty"` // Per-agent skill selection
|
|
|
|
// Memory
|
|
LongTermMemory bool `json:"long_term_memory"`
|
|
SummaryLongTermMemory bool `json:"summary_long_term_memory"`
|
|
ConversationStorageMode string `json:"conversation_storage_mode"`
|
|
|
|
// Execution
|
|
ParallelJobs int `json:"parallel_jobs"`
|
|
CancelPreviousOnNewMessage *bool `json:"cancel_previous_on_new_message"`
|
|
StripThinkingTags bool `json:"strip_thinking_tags"`
|
|
EnableEvaluation bool `json:"enable_evaluation"`
|
|
MaxEvaluationLoops int `json:"max_evaluation_loops"`
|
|
MaxAttempts int `json:"max_attempts"`
|
|
MaxIterations int `json:"max_iterations"` // max tool loop iterations
|
|
LoopDetection int `json:"loop_detection"`
|
|
EnableAutoCompaction bool `json:"enable_auto_compaction"`
|
|
AutoCompactionThreshold int `json:"auto_compaction_threshold"`
|
|
}
|
|
|
|
// ConnectorConfig defines a connector integration (Slack, Discord, etc.).
|
|
type ConnectorConfig struct {
|
|
Type string `json:"type"`
|
|
Config string `json:"config"`
|
|
}
|
|
|
|
// ActionsConfig defines an action (tool) available to the agent.
|
|
type ActionsConfig struct {
|
|
Type string `json:"type"`
|
|
Config string `json:"config"`
|
|
}
|
|
|
|
// DynamicPromptsConfig defines a dynamic prompt template.
|
|
type DynamicPromptsConfig struct {
|
|
Type string `json:"type"`
|
|
Config string `json:"config"`
|
|
}
|
|
|
|
// FiltersConfig defines a job filter/trigger.
|
|
type FiltersConfig struct {
|
|
Type string `json:"type"`
|
|
Config string `json:"config"`
|
|
}
|
|
|
|
// MCPServer defines an HTTP-based MCP server endpoint.
|
|
type MCPServer struct {
|
|
URL string `json:"url"`
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
// MCPSTDIOServers is a list of stdio MCP servers that can be unmarshaled from
|
|
// either a JSON array of MCPSTDIOServer objects or a JSON string in Claude Desktop
|
|
// format ({"mcpServers": {"name": {"command": "...", "args": [...]}}}).
|
|
type MCPSTDIOServers []MCPSTDIOServer
|
|
|
|
// UnmarshalJSON handles both array and string (Claude Desktop JSON) formats.
|
|
func (m *MCPSTDIOServers) UnmarshalJSON(data []byte) error {
|
|
// Try array format first
|
|
var arr []MCPSTDIOServer
|
|
if err := json.Unmarshal(data, &arr); err == nil {
|
|
*m = arr
|
|
return nil
|
|
}
|
|
|
|
// Try string format (Claude Desktop JSON blob)
|
|
var raw string
|
|
if err := json.Unmarshal(data, &raw); err == nil {
|
|
parsed, err := parseClaudeDesktopMCP(raw)
|
|
if err != nil {
|
|
return nil // silently ignore unparseable strings
|
|
}
|
|
*m = parsed
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// parseClaudeDesktopMCP parses the {"mcpServers": {...}} format into MCPSTDIOServer list.
|
|
func parseClaudeDesktopMCP(raw string) ([]MCPSTDIOServer, error) {
|
|
var wrapper struct {
|
|
MCPServers map[string]struct {
|
|
Command string `json:"command"`
|
|
Cmd string `json:"cmd"`
|
|
Args []string `json:"args"`
|
|
Env map[string]string `json:"env"`
|
|
} `json:"mcpServers"`
|
|
}
|
|
if err := json.Unmarshal([]byte(raw), &wrapper); err != nil {
|
|
return nil, err
|
|
}
|
|
var result []MCPSTDIOServer
|
|
for name, srv := range wrapper.MCPServers {
|
|
cmd := srv.Command
|
|
if cmd == "" {
|
|
cmd = srv.Cmd
|
|
}
|
|
var envList []string
|
|
for k, v := range srv.Env {
|
|
envList = append(envList, k+"="+v)
|
|
}
|
|
result = append(result, MCPSTDIOServer{
|
|
Name: name,
|
|
Cmd: cmd,
|
|
Args: srv.Args,
|
|
Env: envList,
|
|
})
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// MCPSTDIOServer defines a local command-based MCP server.
|
|
type MCPSTDIOServer struct {
|
|
Name string `json:"name,omitempty"`
|
|
Args []string `json:"args"`
|
|
Env []string `json:"env"`
|
|
Cmd string `json:"cmd"`
|
|
}
|
|
|
|
// AgentKey returns the namespaced key for an agent: "{userID}:{name}" or just "{name}" if no userID.
|
|
func AgentKey(userID, name string) string {
|
|
if userID == "" {
|
|
return name
|
|
}
|
|
return userID + ":" + name
|
|
}
|