Merge branch 'v2/main' into v2/fix/2224-union-required-undeclared
This commit is contained in:
commit
665e8aa84a
3 changed files with 482 additions and 44 deletions
|
|
@ -116,9 +116,12 @@ export class FakeInspectorClient
|
|||
listResourceTemplates = vi.fn(
|
||||
async () => this.resourceTemplatePages.shift() ?? { resourceTemplates: [] },
|
||||
);
|
||||
listRequestorTasks = vi.fn(
|
||||
async () => this.taskPages.shift() ?? { tasks: [] },
|
||||
);
|
||||
// Typed by its signature rather than inferred, so `mock.calls` carries the
|
||||
// cursor a test asserts on — the empty-string pagination case (#2220) turns
|
||||
// on *which* cursor each call received, not just how many there were.
|
||||
listRequestorTasks = vi.fn<
|
||||
(cursor?: string) => Promise<ListResult<"tasks", Task>>
|
||||
>(async () => this.taskPages.shift() ?? { tasks: [] });
|
||||
listSkills = vi.fn(async () => this.skillPages.shift() ?? { skills: [] });
|
||||
// `skills/get` echoes a minimal entry; tests that care override the mock.
|
||||
getSkill = vi.fn(async (uri: string) => ({
|
||||
|
|
|
|||
|
|
@ -3045,7 +3045,13 @@ export class InspectorClient extends InspectorClientEventTarget {
|
|||
throw new Error("Client is not connected");
|
||||
}
|
||||
const result = await this.client.request(
|
||||
{ method: "tasks/list", params: cursor ? { cursor } : {} },
|
||||
{
|
||||
method: "tasks/list",
|
||||
// `!== undefined`, not truthiness: a cursor is opaque and `""` is a
|
||||
// legal value a server may hand back. Dropping it asks for page one
|
||||
// again, so a caller walking pages would loop on the first page.
|
||||
params: cursor !== undefined ? { cursor } : {},
|
||||
},
|
||||
ListTasksResultSchema,
|
||||
this.getRequestOptions(),
|
||||
);
|
||||
|
|
@ -5242,7 +5248,10 @@ export class InspectorClient extends InspectorClientEventTarget {
|
|||
const effectiveMeta = this.mergeMeta(metadata);
|
||||
const params: ListResourcesRequest["params"] = {
|
||||
...(effectiveMeta ? { _meta: effectiveMeta } : {}),
|
||||
...(cursor ? { cursor } : {}),
|
||||
// `!== undefined`, not truthiness: a cursor is opaque and `""` is a
|
||||
// legal value a server may hand back. Dropping it asks for page one
|
||||
// again, so a caller walking pages would loop on the first page.
|
||||
...(cursor !== undefined ? { cursor } : {}),
|
||||
};
|
||||
const response = await this.invokeMcpClient(() =>
|
||||
this.client!.request(
|
||||
|
|
@ -5416,7 +5425,10 @@ export class InspectorClient extends InspectorClientEventTarget {
|
|||
const effectiveMeta = this.mergeMeta(metadata);
|
||||
const params: ListResourceTemplatesRequest["params"] = {
|
||||
...(effectiveMeta ? { _meta: effectiveMeta } : {}),
|
||||
...(cursor ? { cursor } : {}),
|
||||
// `!== undefined`, not truthiness: a cursor is opaque and `""` is a
|
||||
// legal value a server may hand back. Dropping it asks for page one
|
||||
// again, so a caller walking pages would loop on the first page.
|
||||
...(cursor !== undefined ? { cursor } : {}),
|
||||
};
|
||||
const response = await this.invokeMcpClient(
|
||||
() =>
|
||||
|
|
@ -5480,7 +5492,10 @@ export class InspectorClient extends InspectorClientEventTarget {
|
|||
const effectiveMeta = this.mergeMeta(metadata);
|
||||
const params: ListPromptsRequest["params"] = {
|
||||
...(effectiveMeta ? { _meta: effectiveMeta } : {}),
|
||||
...(cursor ? { cursor } : {}),
|
||||
// `!== undefined`, not truthiness: a cursor is opaque and `""` is a
|
||||
// legal value a server may hand back. Dropping it asks for page one
|
||||
// again, so a caller walking pages would loop on the first page.
|
||||
...(cursor !== undefined ? { cursor } : {}),
|
||||
};
|
||||
const response = await this.invokeMcpClient(() =>
|
||||
this.client!.request(
|
||||
|
|
|
|||
|
|
@ -181,7 +181,13 @@ export class ManagedRequestorTasksState extends TypedEventTarget<ManagedRequesto
|
|||
? { ...t, status: "cancelled" as const }
|
||||
: t,
|
||||
);
|
||||
this.tasks = cursor ? [...this.tasks, ...page] : page;
|
||||
// `=== undefined`, not truthiness, on both the append test and the loop
|
||||
// condition: a cursor is opaque and `""` is a legal value (#2220). Under
|
||||
// a truthiness check an empty `nextCursor` ended the walk after page one
|
||||
// AND made the next page replace the list rather than extend it — the
|
||||
// user-visible task list silently stopping at four rows against a
|
||||
// conforming server.
|
||||
this.tasks = cursor === undefined ? page : [...this.tasks, ...page];
|
||||
cursor = result.nextCursor;
|
||||
pageCount++;
|
||||
if (pageCount >= MAX_PAGES) {
|
||||
|
|
@ -189,7 +195,7 @@ export class ManagedRequestorTasksState extends TypedEventTarget<ManagedRequesto
|
|||
`Maximum pagination limit (${MAX_PAGES} pages) reached while listing requestor tasks`,
|
||||
);
|
||||
}
|
||||
} while (cursor);
|
||||
} while (cursor !== undefined);
|
||||
this.dispatchTypedEvent("tasksChange", this.tasks);
|
||||
return this.getTasks();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue