mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-09 21:49:37 +00:00
fix(frontend): authenticate remaining gateway reads (#4827)
* fix(frontend): authenticate remaining gateway reads * fix(frontend): authenticate artifact reads * fix(frontend): include status in model errors
This commit is contained in:
parent
5b523bc979
commit
b341120a4a
@ -1,5 +1,7 @@
|
||||
import type { BaseStream } from "@langchain/langgraph-sdk/react";
|
||||
|
||||
import { fetch } from "@/core/api/fetcher";
|
||||
|
||||
import type { AgentThreadState } from "../threads";
|
||||
|
||||
import { buildWriteFileDraftContent } from "./preview";
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
import { throwGatewayApiError } from "@/core/api/errors";
|
||||
import { fetch } from "@/core/api/fetcher";
|
||||
|
||||
import { getBackendBaseURL } from "../config";
|
||||
import { isStaticWebsiteOnly } from "../static-mode";
|
||||
|
||||
@ -14,6 +17,12 @@ export async function loadModels(): Promise<ModelsResponse> {
|
||||
}
|
||||
|
||||
const res = await fetch(`${getBackendBaseURL()}/api/models`);
|
||||
if (!res.ok) {
|
||||
await throwGatewayApiError(
|
||||
res,
|
||||
`Failed to load models: ${res.status} ${res.statusText}`.trim(),
|
||||
);
|
||||
}
|
||||
const data = (await res.json()) as Partial<ModelsResponse>;
|
||||
return {
|
||||
models: data.models ?? [],
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { fetch } from "@/core/api/fetcher";
|
||||
import { getBackendBaseURL } from "@/core/config";
|
||||
|
||||
import type { WorkspaceChangesResponse } from "./types";
|
||||
|
||||
@ -51,6 +51,7 @@ describe("loadArtifactContent", () => {
|
||||
expect(new Headers(init?.headers).get("Range")).toBe(
|
||||
`bytes=0-${ARTIFACT_PREVIEW_MAX_BYTES - 1}`,
|
||||
);
|
||||
expect(init?.credentials).toBe("include");
|
||||
return new Response(bytes, {
|
||||
status: 206,
|
||||
headers: {
|
||||
|
||||
71
frontend/tests/unit/core/models/api.test.ts
Normal file
71
frontend/tests/unit/core/models/api.test.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { afterEach, expect, test, rs } from "@rstest/core";
|
||||
|
||||
afterEach(() => {
|
||||
rs.unstubAllGlobals();
|
||||
});
|
||||
|
||||
test("loadModels includes credentials for authenticated gateway requests", async () => {
|
||||
let requestedInit: RequestInit | undefined;
|
||||
const fetchMock = rs.fn(
|
||||
async (_input: RequestInfo | URL, init?: RequestInit) => {
|
||||
requestedInit = init;
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
models: [
|
||||
{
|
||||
id: "model-1",
|
||||
name: "model-1",
|
||||
model: "model-1",
|
||||
display_name: "Model 1",
|
||||
},
|
||||
],
|
||||
token_usage: { enabled: true },
|
||||
}),
|
||||
{ status: 200 },
|
||||
);
|
||||
},
|
||||
);
|
||||
rs.stubGlobal("fetch", fetchMock);
|
||||
|
||||
const { loadModels } = await import("@/core/models/api");
|
||||
|
||||
await expect(loadModels()).resolves.toMatchObject({
|
||||
models: [{ id: "model-1" }],
|
||||
token_usage: { enabled: true },
|
||||
});
|
||||
expect(requestedInit?.credentials).toBe("include");
|
||||
});
|
||||
|
||||
test("loadModels rejects unsuccessful gateway responses", async () => {
|
||||
rs.stubGlobal(
|
||||
"fetch",
|
||||
rs.fn(
|
||||
async () =>
|
||||
new Response(JSON.stringify({ detail: "Model registry unavailable" }), {
|
||||
status: 503,
|
||||
statusText: "Service Unavailable",
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const { loadModels } = await import("@/core/models/api");
|
||||
|
||||
await expect(loadModels()).rejects.toThrow("Model registry unavailable");
|
||||
});
|
||||
|
||||
test("loadModels includes the status code when statusText is empty", async () => {
|
||||
rs.stubGlobal(
|
||||
"fetch",
|
||||
rs.fn(
|
||||
async () =>
|
||||
new Response("upstream unavailable", {
|
||||
status: 503,
|
||||
statusText: "",
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
const { loadModels } = await import("@/core/models/api");
|
||||
|
||||
await expect(loadModels()).rejects.toThrow("Failed to load models: 503");
|
||||
});
|
||||
@ -47,4 +47,8 @@ test("fetchWorkspaceChanges can request file metadata without diffs", async () =
|
||||
const url = new URL(requestedUrl, "http://localhost");
|
||||
expect(url.searchParams.get("include_files")).toBe("true");
|
||||
expect(url.searchParams.get("include_diff")).toBe("false");
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.objectContaining({ credentials: "include" }),
|
||||
);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user