diff --git a/src/lib/cordn/native/coordinator.ts b/src/lib/cordn/native/coordinator.ts index 965330c..3b7e575 100644 --- a/src/lib/cordn/native/coordinator.ts +++ b/src/lib/cordn/native/coordinator.ts @@ -101,6 +101,7 @@ export class CordnCoordinatorClient { name: string, args: Record, schema: { parse: (value: unknown) => S }, + empty?: () => S, ): Promise { await this.connected; const result = await this.client.callTool( @@ -108,7 +109,20 @@ export class CordnCoordinatorClient { undefined, { onprogress: () => undefined, resetTimeoutOnProgress: true }, ); - return schema.parse(result.structuredContent); + + // ContextVM normally returns `structuredContent`, but some coordinator + // builds return the JSON in a text content block and omit the structured + // field. Accept both; only then fall back to a method-specific empty value. + let payload: unknown = result.structuredContent; + if (payload === undefined) { + const content = result.content as Array<{ type?: string; text?: string }> | undefined; + const text = content?.find((item) => item.type === 'text')?.text; + if (text) { + try { payload = JSON.parse(text); } catch { /* not JSON */ } + } + } + if (payload === undefined && empty) return empty(); + return schema.parse(payload); } /* ── key packages ───────────────────────────────────────────────────────── */ @@ -122,7 +136,12 @@ export class CordnCoordinatorClient { } async listAvailableKeyPackages(): Promise { - return this.call(COORDINATOR_METHODS.listAvailableKeyPackages, {}, listAvailableKeyPackagesOutputSchema); + return this.call( + COORDINATOR_METHODS.listAvailableKeyPackages, + {}, + listAvailableKeyPackagesOutputSchema, + () => ({ keyPackages: [] }), + ); } async consumeKeyPackage(id: string): Promise { @@ -156,6 +175,7 @@ export class CordnCoordinatorClient { COORDINATOR_METHODS.fetchManyGroupMessages, { groups }, fetchManyGroupMessagesOutputSchema, + () => ({ messages: [] }), ); return { messages: result.messages.map((m) => groupMessageSchema.parse(m)) as GroupMessage[] }; } @@ -167,7 +187,12 @@ export class CordnCoordinatorClient { } async fetchPendingWelcomes(input: FetchPendingWelcomesInput = {}): Promise { - return this.call(COORDINATOR_METHODS.fetchPendingWelcomes, { ...input }, fetchPendingWelcomesOutputSchema); + return this.call( + COORDINATOR_METHODS.fetchPendingWelcomes, + { ...input }, + fetchPendingWelcomesOutputSchema, + () => ({ welcomes: [] }), + ); } /* ── join requests (ask to be added) ────────────────────────────────────── */