fix: tolerate empty Cordn coordinator tool responses

This commit is contained in:
SkateSpots 2026-10-29 22:53:36 +07:00
parent 96503b672c
commit eaf345e2ec

View file

@ -101,6 +101,7 @@ export class CordnCoordinatorClient {
name: string,
args: Record<string, unknown>,
schema: { parse: (value: unknown) => S },
empty?: () => S,
): Promise<S> {
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<ListAvailableKeyPackagesOutput> {
return this.call(COORDINATOR_METHODS.listAvailableKeyPackages, {}, listAvailableKeyPackagesOutputSchema);
return this.call(
COORDINATOR_METHODS.listAvailableKeyPackages,
{},
listAvailableKeyPackagesOutputSchema,
() => ({ keyPackages: [] }),
);
}
async consumeKeyPackage(id: string): Promise<KeyPackage> {
@ -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<FetchPendingWelcomesOutput> {
return this.call(COORDINATOR_METHODS.fetchPendingWelcomes, { ...input }, fetchPendingWelcomesOutputSchema);
return this.call(
COORDINATOR_METHODS.fetchPendingWelcomes,
{ ...input },
fetchPendingWelcomesOutputSchema,
() => ({ welcomes: [] }),
);
}
/* ── join requests (ask to be added) ────────────────────────────────────── */