@@ -41,7 +41,10 @@ function resource(value: string): { id: string; kind?: string } | undefined {
4141 }
4242}
4343
44- async function metadata ( client : ManagedSearchMcpClient , id : string ) : Promise < NativeDocument > {
44+ async function metadata (
45+ client : ManagedSearchMcpClient ,
46+ id : string
47+ ) : Promise < NativeDocument | undefined > {
4548 if ( ! UUID . test ( id ) ) invalid ( 'Invalid Lucid document identity.' )
4649 const row = object ( await client . call ( 'lucid_get_document_metadata' , { document_id : id } ) )
4750 const url = resource ( string ( row . viewUrl ) )
@@ -58,7 +61,7 @@ async function metadata(client: ManagedSearchMcpClient, id: string): Promise<Nat
5861 typeof row . lastModified !== 'string' ||
5962 ! Number . isFinite ( Date . parse ( row . lastModified ) )
6063 )
61- invalid ( 'Lucid document metadata is incomplete, changed, or no longer readable.' )
64+ return undefined
6265 return {
6366 id,
6467 kind : url . kind ,
@@ -99,6 +102,7 @@ export async function searchLucidMcp(
99102 'Lucid document search requires a document UUID or Lucid URL and a literal text query.'
100103 )
101104 const document = await metadata ( client , scope . id )
105+ if ( ! document ) invalid ( 'Lucid document metadata is incomplete or no longer readable.' )
102106 if (
103107 ( scope . kind && document . kind !== scope . kind ) ||
104108 ! products . some ( ( product ) => product === document . kind )
@@ -176,13 +180,16 @@ export async function searchLucidMcp(
176180 const limit = Math . max ( 1 , Math . min ( MAX_CANDIDATES , input . limit ) )
177181 const documents = await mapWithConcurrency ( candidates . slice ( 0 , limit ) , 3 , async ( candidate ) => {
178182 const document = await metadata ( client , candidate . id )
179- if ( document . kind !== candidate . kind ) invalid ( 'Lucid document product changed during search.' )
183+ if ( ! document || document . kind !== candidate . kind ) {
184+ dropped = true
185+ return undefined
186+ }
180187 return document
181188 } )
182189 const capped = candidates . length > limit || result . results . length >= 200
183190 const localDates = hasDateBounds ( input . filters ) || Boolean ( dateSortDirection ( input . filters ) )
184191 return {
185- documents,
192+ documents : documents . filter ( ( document ) => document !== undefined ) ,
186193 hasMore : capped ,
187194 partial : dropped || capped || localDates ,
188195 message :
@@ -191,7 +198,7 @@ export async function searchLucidMcp(
191198 ? ' Dates use current modification timestamps; sorting and the end-date filter cover only the retrieved candidates, not the entire account.'
192199 : '' ) +
193200 ( capped ? ' The candidate limit was reached; narrow the title query.' : '' ) +
194- ( dropped ? ' Unsupported search results were excluded.' : '' ) ,
201+ ( dropped ? ' Unsupported or no-longer-readable search results were excluded.' : '' ) ,
195202 }
196203}
197204
@@ -225,6 +232,7 @@ export async function readLucidMcp(
225232 reference : Pick < NativeDocument , 'id' | 'kind' | 'revision' >
226233) : Promise < NativeDocument > {
227234 const before = await metadata ( client , reference . id )
235+ if ( ! before ) invalid ( 'Lucid document metadata is incomplete or no longer readable.' )
228236 if (
229237 ( reference . kind && reference . kind !== before . kind ) ||
230238 ( reference . revision && reference . revision !== before . revision )
@@ -304,6 +312,7 @@ export async function readLucidMcp(
304312 }
305313 const after = await metadata ( client , before . id )
306314 if (
315+ ! after ||
307316 after . revision !== before . revision ||
308317 after . kind !== before . kind ||
309318 after . modifiedAt !== before . modifiedAt ||
0 commit comments