- 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.
179 lines
3.1 KiB
Go
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)
|
|
}
|
|
}
|