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
99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
package builtin
|
|
|
|
import (
|
|
"log/slog"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/memohai/memoh/internal/config"
|
|
dbsqlc "github.com/memohai/memoh/internal/db/sqlc"
|
|
adapters "github.com/memohai/memoh/internal/memory/adapters"
|
|
storefs "github.com/memohai/memoh/internal/memory/storefs"
|
|
)
|
|
|
|
// BuiltinMemoryMode represents the operating mode of the built-in memory provider.
|
|
type BuiltinMemoryMode string
|
|
|
|
const (
|
|
ModeOff BuiltinMemoryMode = "off"
|
|
ModeSparse BuiltinMemoryMode = "sparse"
|
|
ModeDense BuiltinMemoryMode = "dense"
|
|
)
|
|
|
|
// NewBuiltinRuntimeFromConfig returns the appropriate memoryRuntime based on the
|
|
// provider's persisted config (memory_mode field). Falls back to the file runtime for "off" or unknown.
|
|
func NewBuiltinRuntimeFromConfig(log *slog.Logger, providerConfig map[string]any, fileRuntime any, store *storefs.Service, queries *dbsqlc.Queries, cfg config.Config) (any, error) {
|
|
mode := BuiltinMemoryMode(strings.TrimSpace(adapters.StringFromConfig(providerConfig, "memory_mode")))
|
|
|
|
switch mode {
|
|
case ModeSparse:
|
|
host, port := parseQdrantHostPort(cfg.Qdrant.BaseURL)
|
|
if host == "" {
|
|
host = "localhost"
|
|
}
|
|
if port == 0 {
|
|
port = 6334
|
|
}
|
|
collection := adapters.StringFromConfig(providerConfig, "qdrant_collection")
|
|
if collection == "" {
|
|
collection = "memory_sparse"
|
|
}
|
|
rt, err := newSparseRuntime(
|
|
host,
|
|
port,
|
|
cfg.Qdrant.APIKey,
|
|
collection,
|
|
strings.TrimSpace(cfg.Sparse.BaseURL),
|
|
store,
|
|
)
|
|
if err != nil {
|
|
if log != nil {
|
|
log.Warn("sparse runtime init failed, falling back to file runtime", slog.Any("error", err))
|
|
}
|
|
return fileRuntime, nil
|
|
}
|
|
return rt, nil
|
|
|
|
case ModeDense:
|
|
rt, err := newDenseRuntime(providerConfig, queries, cfg, store)
|
|
if err != nil {
|
|
if log != nil {
|
|
log.Warn("dense runtime init failed, falling back to file runtime", slog.Any("error", err))
|
|
}
|
|
return fileRuntime, nil
|
|
}
|
|
return rt, nil
|
|
|
|
default:
|
|
return fileRuntime, nil
|
|
}
|
|
}
|
|
|
|
// parseQdrantHostPort extracts host and gRPC port from a Qdrant base URL.
|
|
// Qdrant base URLs are typically HTTP (port 6333), but the gRPC port is 6334.
|
|
func parseQdrantHostPort(baseURL string) (string, int) {
|
|
baseURL = strings.TrimSpace(baseURL)
|
|
if baseURL == "" {
|
|
return "", 0
|
|
}
|
|
baseURL = strings.TrimPrefix(baseURL, "http://")
|
|
baseURL = strings.TrimPrefix(baseURL, "https://")
|
|
parts := strings.SplitN(baseURL, ":", 2)
|
|
host := parts[0]
|
|
if len(parts) == 2 {
|
|
httpPort, err := strconv.Atoi(strings.TrimRight(parts[1], "/"))
|
|
if err == nil {
|
|
switch httpPort {
|
|
case 6333:
|
|
return host, 6334
|
|
case 6334:
|
|
return host, 6334
|
|
default:
|
|
// Common case: operator already configured the intended gRPC port.
|
|
return host, httpPort
|
|
}
|
|
}
|
|
}
|
|
return host, 6334
|
|
}
|