@@ -55,6 +55,9 @@ def add(self, *, documents, ids, metadatas=None):
5555 def upsert (self , * , documents , ids , metadatas = None ):
5656 self ._collection .upsert (documents = documents , ids = ids , metadatas = metadatas )
5757
58+ def update (self , ** kwargs ):
59+ self ._collection .update (** kwargs )
60+
5861 def query (self , ** kwargs ):
5962 return self ._collection .query (** kwargs )
6063
@@ -71,6 +74,44 @@ def count(self):
7174class ChromaBackend :
7275 """Factory for MemPalace's default ChromaDB backend."""
7376
77+ def __init__ (self ):
78+ # Per-instance client cache: palace_path -> chromadb.PersistentClient
79+ self ._clients : dict = {}
80+
81+ # ------------------------------------------------------------------
82+ # Internal helpers
83+ # ------------------------------------------------------------------
84+
85+ def _client (self , palace_path : str ):
86+ """Return a cached PersistentClient for *palace_path*, creating one if needed."""
87+ if palace_path not in self ._clients :
88+ _fix_blob_seq_ids (palace_path )
89+ self ._clients [palace_path ] = chromadb .PersistentClient (path = palace_path )
90+ return self ._clients [palace_path ]
91+
92+ # ------------------------------------------------------------------
93+ # Public static helpers (for callers that manage their own caching)
94+ # ------------------------------------------------------------------
95+
96+ @staticmethod
97+ def make_client (palace_path : str ):
98+ """Create and return a fresh PersistentClient (fix BLOB seq_ids first).
99+
100+ Intended for long-lived callers (e.g. mcp_server) that keep their own
101+ inode/mtime-based client cache.
102+ """
103+ _fix_blob_seq_ids (palace_path )
104+ return chromadb .PersistentClient (path = palace_path )
105+
106+ @staticmethod
107+ def backend_version () -> str :
108+ """Return the installed chromadb package version string."""
109+ return chromadb .__version__
110+
111+ # ------------------------------------------------------------------
112+ # Collection lifecycle
113+ # ------------------------------------------------------------------
114+
74115 def get_collection (self , palace_path : str , collection_name : str , create : bool = False ):
75116 if not create and not os .path .isdir (palace_path ):
76117 raise FileNotFoundError (palace_path )
@@ -82,12 +123,30 @@ def get_collection(self, palace_path: str, collection_name: str, create: bool =
82123 except (OSError , NotImplementedError ):
83124 pass
84125
85- _fix_blob_seq_ids (palace_path )
86- client = chromadb .PersistentClient (path = palace_path )
126+ client = self ._client (palace_path )
87127 if create :
88128 collection = client .get_or_create_collection (
89129 collection_name , metadata = {"hnsw:space" : "cosine" }
90130 )
91131 else :
92132 collection = client .get_collection (collection_name )
93133 return ChromaCollection (collection )
134+
135+ def get_or_create_collection (
136+ self , palace_path : str , collection_name : str
137+ ) -> "ChromaCollection" :
138+ """Shorthand for get_collection(..., create=True)."""
139+ return self .get_collection (palace_path , collection_name , create = True )
140+
141+ def delete_collection (self , palace_path : str , collection_name : str ) -> None :
142+ """Delete *collection_name* from the palace at *palace_path*."""
143+ self ._client (palace_path ).delete_collection (collection_name )
144+
145+ def create_collection (
146+ self , palace_path : str , collection_name : str , hnsw_space : str = "cosine"
147+ ) -> "ChromaCollection" :
148+ """Create (not get-or-create) *collection_name* with cosine HNSW space."""
149+ collection = self ._client (palace_path ).create_collection (
150+ collection_name , metadata = {"hnsw:space" : hnsw_space }
151+ )
152+ return ChromaCollection (collection )
0 commit comments