yao/mcpclient/store.go
Max 654e7ee567 feat(load): initialize and reload LLM Provider and MCP Client Registries
- Added initialization for LLM Provider and MCP Client Registries during the Load process.
- Implemented reload functionality for both registries to ensure they are properly refreshed when needed.
- Enhanced error handling to capture and report issues during initialization and reloading of the registries.
2026-04-28 14:33:10 +08:00

179 lines
3.1 KiB
Go

package mcpclient
import (
"encoding/json"
"fmt"
"github.com/yaoapp/gou/store"
)
const (
keyPrefix = "mcpclient:c:"
indexKey = "mcpclient:index"
)
func storeKey(id string) string { return keyPrefix + id }
func clientToMap(c *Client) (map[string]interface{}, error) {
raw, err := json.Marshal(c)
if err != nil {
return nil, err
}
var m map[string]interface{}
if err := json.Unmarshal(raw, &m); err != nil {
return nil, err
}
return m, nil
}
func mapToClient(m map[string]interface{}) (*Client, error) {
raw, err := json.Marshal(m)
if err != nil {
return nil, err
}
var c Client
if err := json.Unmarshal(raw, &c); err != nil {
return nil, err
}
return &c, nil
}
func storeGet(s, c store.Store, id string) (*Client, error) {
sk := storeKey(id)
if c != nil {
if val, ok := c.Get(sk); ok {
if m, ok := val.(map[string]interface{}); ok {
return mapToClient(m)
}
}
}
val, ok := s.Get(sk)
if !ok {
return nil, fmt.Errorf("client %s not found", id)
}
m, ok := val.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("client %s: unexpected store type %T", id, val)
}
cl, err := mapToClient(m)
if err != nil {
return nil, err
}
if c != nil {
c.Set(sk, m, 0)
}
return cl, nil
}
func storeSet(s, c store.Store, cl *Client) error {
m, err := clientToMap(cl)
if err != nil {
return err
}
sk := storeKey(cl.ID)
if err := s.Set(sk, m, 0); err != nil {
return err
}
if c != nil {
c.Set(sk, m, 0)
}
return nil
}
func storeDel(s, c store.Store, id string) error {
sk := storeKey(id)
if err := s.Del(sk); err != nil {
return err
}
if c != nil {
c.Del(sk)
}
return nil
}
func indexGet(s, c store.Store) ([]string, error) {
var raw interface{}
var ok bool
if c != nil {
raw, ok = c.Get(indexKey)
}
if !ok {
raw, ok = s.Get(indexKey)
if !ok {
return nil, nil
}
if c != nil {
c.Set(indexKey, raw, 0)
}
}
switch v := raw.(type) {
case []interface{}:
keys := make([]string, 0, len(v))
for _, item := range v {
if str, ok := item.(string); ok {
keys = append(keys, str)
}
}
return keys, nil
case []string:
return v, nil
default:
return nil, fmt.Errorf("unexpected index type %T", raw)
}
}
func indexSet(s, c store.Store, ids []string) error {
iface := make([]interface{}, len(ids))
for i, k := range ids {
iface[i] = k
}
if err := s.Set(indexKey, iface, 0); err != nil {
return err
}
if c != nil {
c.Set(indexKey, iface, 0)
}
return nil
}
func indexAdd(s, c store.Store, id string) error {
ids, err := indexGet(s, c)
if err != nil {
return err
}
for _, k := range ids {
if k == id {
return nil
}
}
return indexSet(s, c, append(ids, id))
}
func indexRemove(s, c store.Store, id string) error {
ids, err := indexGet(s, c)
if err != nil {
return err
}
filtered := make([]string, 0, len(ids))
for _, k := range ids {
if k != id {
filtered = append(filtered, k)
}
}
return indexSet(s, c, filtered)
}
func storeCleanAll(s, c store.Store) {
_ = s.Del(keyPrefix + "*")
_ = s.Del(indexKey)
if c != nil {
_ = c.Del(keyPrefix + "*")
_ = c.Del(indexKey)
}
}