feat: AssistantSearchResponse (#1804)

Co-authored-by: David Duong <david@duong.cz>
This commit is contained in:
William FH
2025-12-02 10:24:07 -08:00
committed by GitHub
parent fa6c009f5f
commit b78a73835f
5 changed files with 132 additions and 15 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@langchain/langgraph-sdk": patch
---
feat(sdk): add `includePagination` property when searching from assistants
+53 -15
View File
@@ -4,6 +4,7 @@ import {
AssistantSortBy,
AssistantSelectField,
AssistantVersion,
AssistantsSearchResponse,
CancelAction,
Checkpoint,
Config,
@@ -616,8 +617,20 @@ export class AssistantsClient extends BaseClient {
/**
* List assistants.
* @param query Query options.
* @returns List of assistants.
* @returns List of assistants or, when includePagination is true, a mapping with the assistants and next cursor.
*/
async search(query: {
graphId?: string;
name?: string;
metadata?: Metadata;
limit?: number;
offset?: number;
sortBy?: AssistantSortBy;
sortOrder?: SortOrder;
select?: AssistantSelectField[];
includePagination: true;
}): Promise<AssistantsSearchResponse>;
async search(query?: {
graphId?: string;
name?: string;
@@ -627,20 +640,45 @@ export class AssistantsClient extends BaseClient {
sortBy?: AssistantSortBy;
sortOrder?: SortOrder;
select?: AssistantSelectField[];
}): Promise<Assistant[]> {
return this.fetch<Assistant[]>("/assistants/search", {
method: "POST",
json: {
graph_id: query?.graphId ?? undefined,
name: query?.name ?? undefined,
metadata: query?.metadata ?? undefined,
limit: query?.limit ?? 10,
offset: query?.offset ?? 0,
sort_by: query?.sortBy ?? undefined,
sort_order: query?.sortOrder ?? undefined,
select: query?.select ?? undefined,
},
});
includePagination?: false;
}): Promise<Assistant[]>;
async search(query?: {
graphId?: string;
name?: string;
metadata?: Metadata;
limit?: number;
offset?: number;
sortBy?: AssistantSortBy;
sortOrder?: SortOrder;
select?: AssistantSelectField[];
includePagination?: boolean;
}): Promise<Assistant[] | AssistantsSearchResponse> {
const json = {
graph_id: query?.graphId ?? undefined,
name: query?.name ?? undefined,
metadata: query?.metadata ?? undefined,
limit: query?.limit ?? 10,
offset: query?.offset ?? 0,
sort_by: query?.sortBy ?? undefined,
sort_order: query?.sortOrder ?? undefined,
select: query?.select ?? undefined,
};
const [assistants, response] = await this.fetch<Assistant[]>(
"/assistants/search",
{
method: "POST",
json,
withResponse: true,
}
);
if (query?.includePagination) {
const next = response.headers.get("X-Pagination-Next");
return { assistants, next };
}
return assistants;
}
/**
+1
View File
@@ -6,6 +6,7 @@ export type {
AssistantBase,
AssistantGraph,
AssistantVersion,
AssistantsSearchResponse,
Checkpoint,
Config,
Cron,
+7
View File
@@ -134,6 +134,13 @@ export interface Assistant extends AssistantBase {
updated_at: string;
}
export interface AssistantsSearchResponse {
/** The assistants returned for the current search page. */
assistants: Assistant[];
/** Pagination cursor from the X-Pagination-Next response header. */
next: string | null;
}
export interface AssistantGraph {
nodes: Array<{
id: string | number;
+66
View File
@@ -0,0 +1,66 @@
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { Client } from "../client.js";
import { overrideFetchImplementation } from "../singletons/fetch.js";
function assistantPayload() {
return {
assistant_id: "asst_123",
graph_id: "graph_123",
config: { configurable: { foo: "bar" } },
context: { foo: "bar" },
created_at: "2024-01-01T00:00:00Z",
metadata: { env: "test" },
version: 1,
name: "My Assistant",
description: "Example",
updated_at: "2024-01-02T00:00:00Z",
};
}
describe("assistants.search", () => {
let fetchMock: ReturnType<typeof vi.fn>;
beforeEach(() => {
fetchMock = vi.fn();
overrideFetchImplementation(fetchMock);
(globalThis as any).fetch = fetchMock;
});
afterEach(() => {
vi.restoreAllMocks();
});
it("returns list by default", async () => {
const assistant = assistantPayload();
fetchMock.mockResolvedValueOnce({
ok: true,
status: 200,
json: () => Promise.resolve([assistant]),
text: () => Promise.resolve(""),
headers: new Headers({}),
});
const client = new Client({ apiKey: "test-api-key" });
const result = await client.assistants.search({ limit: 3 });
expect(result).toEqual([assistant]);
});
it("can include pagination metadata", async () => {
const assistant = assistantPayload();
fetchMock.mockResolvedValueOnce({
ok: true,
status: 200,
json: () => Promise.resolve([assistant]),
text: () => Promise.resolve(""),
headers: new Headers({ "X-Pagination-Next": "42" }),
});
const client = new Client({ apiKey: "test-api-key" });
const result = await client.assistants.search({ includePagination: true });
expect(result).toEqual({ assistants: [assistant], next: "42" });
});
});