mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
627b673a5c
* refactor: restructure memory into multi-provider adapters, remove manifest.json dependency - Rename internal/memory/provider to internal/memory/adapters with per-provider subdirectories (builtin, mem0, openviking) - Replace manifest.json-based delete/update with scan-based index from daily files - Add mem0 and openviking provider adapters with HTTP client, chat hooks, MCP tools, and CRUD - Wire provider lifecycle into registry (auto-instantiate on create, evict on update/delete) - Split docker-compose into base stack + optional overlays (qdrant, browser, mem0, openviking) - Update admin UI to support dynamic provider config schema rendering * chore(lint): fix all golangci-lint issues for clean CI * refactor(docker): replace compose overlay files with profiles * feat(memory): add built-in memory multi modes * fix(ci): golangci lint * feat(memory): edit built-in memory sparse design
228 lines
5.5 KiB
Go
228 lines
5.5 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
)
|
|
|
|
const (
|
|
DefaultConfigPath = "config.toml"
|
|
DefaultHTTPAddr = ":8080"
|
|
DefaultNamespace = "default"
|
|
DefaultSocketPath = "/run/containerd/containerd.sock"
|
|
DefaultMCPImage = "memohai/mcp:latest"
|
|
DefaultDataRoot = "data"
|
|
DefaultDataMount = "/data"
|
|
DefaultCNIBinaryDir = "/opt/cni/bin"
|
|
DefaultCNIConfigDir = "/etc/cni/net.d"
|
|
DefaultJWTExpiresIn = "24h"
|
|
DefaultPGHost = "127.0.0.1"
|
|
DefaultPGPort = 5432
|
|
DefaultPGUser = "postgres"
|
|
DefaultPGDatabase = "memoh"
|
|
DefaultPGSSLMode = "disable"
|
|
DefaultQdrantURL = "http://127.0.0.1:6334"
|
|
DefaultQdrantCollection = "memory"
|
|
MCPGRPCPort = 9090
|
|
)
|
|
|
|
type Config struct {
|
|
Log LogConfig `toml:"log"`
|
|
Server ServerConfig `toml:"server"`
|
|
Admin AdminConfig `toml:"admin"`
|
|
Auth AuthConfig `toml:"auth"`
|
|
Containerd ContainerdConfig `toml:"containerd"`
|
|
MCP MCPConfig `toml:"mcp"`
|
|
Postgres PostgresConfig `toml:"postgres"`
|
|
Qdrant QdrantConfig `toml:"qdrant"`
|
|
Sparse SparseConfig `toml:"sparse"`
|
|
AgentGateway AgentGatewayConfig `toml:"agent_gateway"`
|
|
BrowserGateway BrowserGatewayConfig `toml:"browser_gateway"`
|
|
}
|
|
|
|
type LogConfig struct {
|
|
Level string `toml:"level"`
|
|
Format string `toml:"format"`
|
|
}
|
|
|
|
type ServerConfig struct {
|
|
Addr string `toml:"addr"`
|
|
}
|
|
|
|
type AdminConfig struct {
|
|
Username string `toml:"username"`
|
|
Password string `toml:"password" json:"-"`
|
|
Email string `toml:"email"`
|
|
}
|
|
|
|
type AuthConfig struct {
|
|
JWTSecret string `toml:"jwt_secret" json:"-"`
|
|
JWTExpiresIn string `toml:"jwt_expires_in"`
|
|
}
|
|
|
|
type ContainerdConfig struct {
|
|
SocketPath string `toml:"socket_path"`
|
|
Namespace string `toml:"namespace"`
|
|
Socktainer SocktainerConfig `toml:"socktainer"`
|
|
}
|
|
|
|
type SocktainerConfig struct {
|
|
SocketPath string `toml:"socket_path"`
|
|
BinaryPath string `toml:"binary_path"`
|
|
}
|
|
|
|
type MCPConfig struct {
|
|
Registry string `toml:"registry"`
|
|
Image string `toml:"image"`
|
|
Snapshotter string `toml:"snapshotter"`
|
|
DataRoot string `toml:"data_root"`
|
|
CNIBinaryDir string `toml:"cni_bin_dir"`
|
|
CNIConfigDir string `toml:"cni_conf_dir"`
|
|
}
|
|
|
|
// ImageRef returns the fully qualified image reference, prepending the
|
|
// registry mirror when configured and normalizing for containerd compatibility.
|
|
// Containerd requires a fully-qualified domain in image references — short
|
|
// Docker Hub names like "memohai/mcp:latest" are misinterpreted as hosts.
|
|
func (c MCPConfig) ImageRef() string {
|
|
img := c.Image
|
|
if img == "" {
|
|
img = DefaultMCPImage
|
|
}
|
|
if c.Registry != "" {
|
|
return c.Registry + "/" + img
|
|
}
|
|
return NormalizeImageRef(img)
|
|
}
|
|
|
|
// NormalizeImageRef ensures an image reference is fully qualified for containerd.
|
|
func NormalizeImageRef(ref string) string {
|
|
firstSlash := strings.Index(ref, "/")
|
|
if firstSlash == -1 {
|
|
return "docker.io/library/" + ref
|
|
}
|
|
firstSegment := ref[:firstSlash]
|
|
if strings.Contains(firstSegment, ".") || strings.Contains(firstSegment, ":") || firstSegment == "localhost" {
|
|
return ref
|
|
}
|
|
return "docker.io/" + ref
|
|
}
|
|
|
|
type PostgresConfig struct {
|
|
Host string `toml:"host"`
|
|
Port int `toml:"port"`
|
|
User string `toml:"user"`
|
|
Password string `toml:"password" json:"-"`
|
|
Database string `toml:"database"`
|
|
SSLMode string `toml:"sslmode"`
|
|
}
|
|
|
|
type QdrantConfig struct {
|
|
BaseURL string `toml:"base_url"`
|
|
APIKey string `toml:"api_key" json:"-"`
|
|
TimeoutSeconds int `toml:"timeout_seconds"`
|
|
}
|
|
|
|
type SparseConfig struct {
|
|
BaseURL string `toml:"base_url"`
|
|
}
|
|
|
|
type AgentGatewayConfig struct {
|
|
Host string `toml:"host"`
|
|
Port int `toml:"port"`
|
|
}
|
|
|
|
func (c AgentGatewayConfig) BaseURL() string {
|
|
host := c.Host
|
|
if host == "" {
|
|
host = "127.0.0.1"
|
|
}
|
|
port := c.Port
|
|
if port == 0 {
|
|
port = 8081
|
|
}
|
|
return "http://" + host + ":" + strconv.Itoa(port)
|
|
}
|
|
|
|
type BrowserGatewayConfig struct {
|
|
Host string `toml:"host"`
|
|
Port int `toml:"port"`
|
|
}
|
|
|
|
func (c BrowserGatewayConfig) BaseURL() string {
|
|
host := c.Host
|
|
if host == "" {
|
|
host = "127.0.0.1"
|
|
}
|
|
port := c.Port
|
|
if port == 0 {
|
|
port = 8083
|
|
}
|
|
return "http://" + host + ":" + strconv.Itoa(port)
|
|
}
|
|
|
|
func Load(path string) (Config, error) {
|
|
cfg := Config{
|
|
Log: LogConfig{
|
|
Level: "info",
|
|
Format: "text",
|
|
},
|
|
Server: ServerConfig{
|
|
Addr: DefaultHTTPAddr,
|
|
},
|
|
Admin: AdminConfig{
|
|
Username: "admin",
|
|
Password: "change-your-password-here",
|
|
Email: "you@example.com",
|
|
},
|
|
Auth: AuthConfig{
|
|
JWTExpiresIn: DefaultJWTExpiresIn,
|
|
},
|
|
Containerd: ContainerdConfig{
|
|
SocketPath: DefaultSocketPath,
|
|
Namespace: DefaultNamespace,
|
|
},
|
|
MCP: MCPConfig{
|
|
Image: DefaultMCPImage,
|
|
DataRoot: DefaultDataRoot,
|
|
CNIBinaryDir: DefaultCNIBinaryDir,
|
|
CNIConfigDir: DefaultCNIConfigDir,
|
|
},
|
|
Postgres: PostgresConfig{
|
|
Host: DefaultPGHost,
|
|
Port: DefaultPGPort,
|
|
User: DefaultPGUser,
|
|
Database: DefaultPGDatabase,
|
|
SSLMode: DefaultPGSSLMode,
|
|
},
|
|
AgentGateway: AgentGatewayConfig{
|
|
Host: "127.0.0.1",
|
|
Port: 8081,
|
|
},
|
|
BrowserGateway: BrowserGatewayConfig{
|
|
Host: "127.0.0.1",
|
|
Port: 8083,
|
|
},
|
|
}
|
|
|
|
if path == "" {
|
|
path = DefaultConfigPath
|
|
}
|
|
|
|
if _, err := os.Stat(path); err != nil {
|
|
if os.IsNotExist(err) {
|
|
return cfg, nil
|
|
}
|
|
return cfg, err
|
|
}
|
|
|
|
if _, err := toml.DecodeFile(path, &cfg); err != nil {
|
|
return cfg, err
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|