diff --git a/agents/runtime.go b/agents/runtime.go index 62a9ae2..267602d 100644 --- a/agents/runtime.go +++ b/agents/runtime.go @@ -92,6 +92,9 @@ type Agent struct { // Knowledge store — non-nil when knowledge is enabled knowledgeStore *shellknowledge.FileStore + // Shared knowledge store — non-nil when shared_knowledge is enabled + sharedKnowledgeStore *shellknowledge.FileStore + // Sanitization options — nil when sanitization is disabled sanitizeOpts *sanitize.Options @@ -235,6 +238,29 @@ func New(cfg *config.AgentConfig, rules []decision.Rule, agentACL acl.ACL, logge } } + // Shared knowledge store + var sharedKStore *shellknowledge.FileStore + if cfg.Tools.SharedKnowledge.Enabled { + sharedDir := cfg.Tools.SharedKnowledge.Dir + if sharedDir == "" { + sharedDir = "knowledges" + } + sharedDBPath := cfg.Tools.SharedKnowledge.DBPath + if sharedDBPath == "" { + sharedDBPath = "knowledges/data/knowledge.db" + } + var skErr error + sharedKStore, skErr = shellknowledge.New(sharedDir, sharedDBPath, logger) + if skErr != nil { + logger.Error("shared_knowledge_store_init_failed", "err", skErr) + } else { + if syncErr := sharedKStore.Sync(context.Background()); syncErr != nil { + logger.Error("shared_knowledge_sync_failed", "err", syncErr) + } + logger.Info("shared knowledge enabled", "dir", sharedDir, "db", sharedDBPath) + } + } + if !agentACL.Empty() { logger.Info("acl enabled (centralized security policy)") } @@ -252,7 +278,7 @@ func New(cfg *config.AgentConfig, rules []decision.Rule, agentACL acl.ACL, logge } // Tool registry — register tools enabled in config - toolReg := buildToolRegistry(cfg, sshExec, matrixClient, memStore, kStore, mcpManager, roomCtx, logger) + toolReg := buildToolRegistry(cfg, sshExec, matrixClient, memStore, kStore, sharedKStore, mcpManager, roomCtx, logger) // Rate limiting for tools if cfg.Security.ToolRateLimit.Enabled { @@ -278,25 +304,26 @@ func New(cfg *config.AgentConfig, rules []decision.Rule, agentACL acl.ACL, logge } a := &Agent{ - cfg: cfg, - acl: agentACL, - rules: rules, - llm: llmFunc, - matrix: matrixClient, - runner: runner, - toolReg: toolReg, - logger: logger, - cryptoStore: cryptoStore, - mcpManager: mcpManager, - done: make(chan struct{}), - commands: make(map[string]CommandHandler), - cmdAliases: command.BuiltinNames(), - startTime: time.Now(), - windows: make(map[string]memory.Window), - memStore: memStore, - knowledgeStore: kStore, - windowSize: windowSize, - roomCtx: roomCtx, + cfg: cfg, + acl: agentACL, + rules: rules, + llm: llmFunc, + matrix: matrixClient, + runner: runner, + toolReg: toolReg, + logger: logger, + cryptoStore: cryptoStore, + mcpManager: mcpManager, + done: make(chan struct{}), + commands: make(map[string]CommandHandler), + cmdAliases: command.BuiltinNames(), + startTime: time.Now(), + windows: make(map[string]memory.Window), + memStore: memStore, + knowledgeStore: kStore, + sharedKnowledgeStore: sharedKStore, + windowSize: windowSize, + roomCtx: roomCtx, } // Configure sanitization if enabled @@ -417,6 +444,9 @@ func (a *Agent) Run(ctx context.Context) error { if a.knowledgeStore != nil { defer a.knowledgeStore.Close() } + if a.sharedKnowledgeStore != nil { + defer a.sharedKnowledgeStore.Close() + } if a.mcpManager != nil { defer a.mcpManager.Close() } @@ -999,6 +1029,7 @@ func buildToolRegistry( matrixClient *matrix.Client, memStore memory.Store, kStore *shellknowledge.FileStore, + sharedKStore *shellknowledge.FileStore, mcpManager *shellmcp.Manager, roomCtx *toolmemory.RoomContext, logger *slog.Logger, @@ -1051,6 +1082,15 @@ func buildToolRegistry( logger.Debug("registered knowledge tools") } + // Shared knowledge tools + if cfg.Tools.SharedKnowledge.Enabled && sharedKStore != nil { + sharedTools := toolknowledge.NewSharedKnowledgeTools(sharedKStore) + for _, tool := range sharedTools { + reg.Register(tool) + } + logger.Debug("registered shared knowledge tools", "count", len(sharedTools)) + } + // MCP tools — register tools from all connected MCP servers if mcpManager != nil { for serverName, mcpClient := range mcpManager.AllClients() {