@@ -53,12 +53,12 @@ export async function getMemorySearchManager(params: {
5353 return { manager : cached } ;
5454 }
5555 if ( statusOnly ) {
56- // Reuse an existing full manager for status requests to avoid duplicate
57- // QMD managers and extra sqlite handles for the same agent/config.
5856 const fullCached = QMD_MANAGER_CACHE . get ( `${ baseCacheKey } :full` ) ;
5957 if ( fullCached ) {
60- QMD_MANAGER_CACHE . set ( cacheKey , fullCached ) ;
61- return { manager : fullCached } ;
58+ // Status callers often close the manager they receive. Wrap the live
59+ // full manager with a no-op close so health/status probes do not tear
60+ // down the active QMD manager for the process.
61+ return { manager : new BorrowedMemoryManager ( fullCached ) } ;
6262 }
6363 }
6464 try {
@@ -71,8 +71,11 @@ export async function getMemorySearchManager(params: {
7171 } ) ;
7272 if ( primary ) {
7373 if ( statusOnly ) {
74- QMD_MANAGER_CACHE . set ( cacheKey , primary ) ;
75- return { manager : primary } ;
74+ const wrapper = new CachedStatusMemoryManager ( primary , ( ) => {
75+ QMD_MANAGER_CACHE . delete ( cacheKey ) ;
76+ } ) ;
77+ QMD_MANAGER_CACHE . set ( cacheKey , wrapper ) ;
78+ return { manager : wrapper } ;
7679 }
7780 const wrapper = new FallbackMemoryManager (
7881 {
@@ -105,6 +108,97 @@ export async function getMemorySearchManager(params: {
105108 }
106109}
107110
111+ class BorrowedMemoryManager implements MemorySearchManager {
112+ constructor ( private readonly inner : MemorySearchManager ) { }
113+
114+ async search (
115+ query : string ,
116+ opts ?: { maxResults ?: number ; minScore ?: number ; sessionKey ?: string } ,
117+ ) {
118+ return await this . inner . search ( query , opts ) ;
119+ }
120+
121+ async readFile ( params : { relPath : string ; from ?: number ; lines ?: number } ) {
122+ return await this . inner . readFile ( params ) ;
123+ }
124+
125+ status ( ) {
126+ return this . inner . status ( ) ;
127+ }
128+
129+ async sync ( params ?: {
130+ reason ?: string ;
131+ force ?: boolean ;
132+ sessionFiles ?: string [ ] ;
133+ progress ?: ( update : MemorySyncProgressUpdate ) => void ;
134+ } ) {
135+ await this . inner . sync ?.( params ) ;
136+ }
137+
138+ async probeEmbeddingAvailability ( ) : Promise < MemoryEmbeddingProbeResult > {
139+ return await this . inner . probeEmbeddingAvailability ( ) ;
140+ }
141+
142+ async probeVectorAvailability ( ) {
143+ return await this . inner . probeVectorAvailability ( ) ;
144+ }
145+
146+ async close ( ) { }
147+ }
148+
149+ class CachedStatusMemoryManager implements MemorySearchManager {
150+ private closed = false ;
151+
152+ constructor (
153+ private readonly inner : MemorySearchManager ,
154+ private readonly onClose : ( ) => void ,
155+ ) { }
156+
157+ async search (
158+ query : string ,
159+ opts ?: { maxResults ?: number ; minScore ?: number ; sessionKey ?: string } ,
160+ ) {
161+ return await this . inner . search ( query , opts ) ;
162+ }
163+
164+ async readFile ( params : { relPath : string ; from ?: number ; lines ?: number } ) {
165+ return await this . inner . readFile ( params ) ;
166+ }
167+
168+ status ( ) {
169+ return this . inner . status ( ) ;
170+ }
171+
172+ async sync ( params ?: {
173+ reason ?: string ;
174+ force ?: boolean ;
175+ sessionFiles ?: string [ ] ;
176+ progress ?: ( update : MemorySyncProgressUpdate ) => void ;
177+ } ) {
178+ await this . inner . sync ?.( params ) ;
179+ }
180+
181+ async probeEmbeddingAvailability ( ) : Promise < MemoryEmbeddingProbeResult > {
182+ return await this . inner . probeEmbeddingAvailability ( ) ;
183+ }
184+
185+ async probeVectorAvailability ( ) {
186+ return await this . inner . probeVectorAvailability ( ) ;
187+ }
188+
189+ async close ( ) {
190+ if ( this . closed ) {
191+ return ;
192+ }
193+ this . closed = true ;
194+ try {
195+ await this . inner . close ?.( ) ;
196+ } finally {
197+ this . onClose ( ) ;
198+ }
199+ }
200+ }
201+
108202export async function closeAllMemorySearchManagers ( ) : Promise < void > {
109203 const managers = Array . from ( QMD_MANAGER_CACHE . values ( ) ) ;
110204 QMD_MANAGER_CACHE . clear ( ) ;
0 commit comments