


























@@ -31,6 +31,21 @@ vi.mock("openclaw/plugin-sdk/ssrf-runtime", async (importOriginal) => {
3131};
3232});
333334+function jsonResponse(payload: unknown, init?: ResponseInit): Response {
35+return new Response(JSON.stringify(payload), {
36+status: 200,
37+headers: { "content-type": "application/json" },
38+ ...init,
39+});
40+}
41+42+function malformedJsonResponse(): Response {
43+return new Response("{ nope", {
44+status: 200,
45+headers: { "content-type": "application/json" },
46+});
47+}
48+3449afterAll(() => {
3550vi.doUnmock("openclaw/plugin-sdk/ssrf-runtime");
3651vi.resetModules();
@@ -72,33 +87,26 @@ describe("lmstudio-models", () => {
7287loadedContextLength?: number;
7388maxContextLength?: number;
7489}) =>
75-vi.fn(async (url: string | URL, init?: RequestInit) => {
90+vi.fn(async (url: string | URL, _init?: RequestInit) => {
7691const key = params?.key ?? "qwen3-8b-instruct";
7792if (String(url).endsWith("/api/v1/models")) {
78-return {
79-ok: true,
80-json: async () => ({
81-models: [
82-{
83-type: "llm",
84- key,
85-max_context_length: params?.maxContextLength,
86-variants: params?.variants,
87-selected_variant: params?.selectedVariant,
88-loaded_instances: params?.loadedContextLength
89- ? [{ id: "inst-1", config: { context_length: params.loadedContextLength } }]
90- : [],
91-},
92-],
93-}),
94-};
93+return jsonResponse({
94+models: [
95+{
96+type: "llm",
97+ key,
98+max_context_length: params?.maxContextLength,
99+variants: params?.variants,
100+selected_variant: params?.selectedVariant,
101+loaded_instances: params?.loadedContextLength
102+ ? [{ id: "inst-1", config: { context_length: params.loadedContextLength } }]
103+ : [],
104+},
105+],
106+});
95107}
96108if (String(url).endsWith("/api/v1/models/load")) {
97-return {
98-ok: true,
99-json: async () => ({ status: "loaded" }),
100-requestInit: init,
101-};
109+return jsonResponse({ status: "loaded" });
102110}
103111throw new Error(`Unexpected fetch URL: ${String(url)}`);
104112});
@@ -296,9 +304,8 @@ describe("lmstudio-models", () => {
296304});
297305298306it("discovers llm models and maps metadata", async () => {
299-const fetchMock = vi.fn(async (_url: string | URL, _init?: RequestInit) => ({
300-ok: true,
301-json: async () => ({
307+const fetchMock = vi.fn(async (_url: string | URL, _init?: RequestInit) =>
308+jsonResponse({
302309models: [
303310{
304311type: "llm",
@@ -330,7 +337,7 @@ describe("lmstudio-models", () => {
330337},
331338],
332339}),
333-}));
340+);
334341335342const models = await discoverLmstudioModels({
336343baseUrl: "http://localhost:1234/v1",
@@ -386,13 +393,7 @@ describe("lmstudio-models", () => {
386393});
387394388395it("reports malformed model list JSON with an owned error", async () => {
389-const fetchMock = vi.fn(async () => ({
390-ok: true,
391-status: 200,
392-json: async () => {
393-throw new SyntaxError("bad json");
394-},
395-}));
396+const fetchMock = vi.fn(async () => malformedJsonResponse());
396397397398const result = await fetchLmstudioModels({
398399baseUrl: "http://localhost:1234/v1",
@@ -405,11 +406,7 @@ describe("lmstudio-models", () => {
405406406407it("reports wrong-shaped model list payloads with owned errors", async () => {
407408for (const payload of [[], { models: {} }, { models: [null] }]) {
408-const fetchMock = vi.fn(async () => ({
409-ok: true,
410-status: 200,
411-json: async () => payload,
412-}));
409+const fetchMock = vi.fn(async () => jsonResponse(payload));
413410414411const result = await fetchLmstudioModels({
415412baseUrl: "http://localhost:1234/v1",
@@ -424,12 +421,9 @@ describe("lmstudio-models", () => {
424421it("caps oversized direct fetch timeouts before discovering models", async () => {
425422const timeoutController = new AbortController();
426423const timeoutSpy = vi.spyOn(AbortSignal, "timeout").mockReturnValue(timeoutController.signal);
427-const fetchMock = vi.fn(async (_url: string | URL, init?: RequestInit) => ({
428-ok: true,
429-status: 200,
430-requestInit: init,
431-json: async () => ({ models: [] }),
432-}));
424+const fetchMock = vi.fn(async (_url: string | URL, _init?: RequestInit) =>
425+jsonResponse({ models: [] }),
426+);
433427434428const result = await fetchLmstudioModels({
435429baseUrl: "http://localhost:1234/v1",
@@ -521,20 +515,17 @@ describe("lmstudio-models", () => {
521515const variantKey = `${canonicalKey}@q4_k_m`;
522516const fetchMock = vi.fn(async (url: string | URL) => {
523517if (String(url).endsWith("/api/v1/models")) {
524-return {
525-ok: true,
526-json: async () => ({
527-models: [
528-{
529-type: "llm",
530-key: canonicalKey,
531-variants: [variantKey],
532-selected_variant: variantKey,
533-loaded_instances: [],
534-},
535-],
536-}),
537-};
518+return jsonResponse({
519+models: [
520+{
521+type: "llm",
522+key: canonicalKey,
523+variants: [variantKey],
524+selected_variant: variantKey,
525+loaded_instances: [],
526+},
527+],
528+});
538529}
539530if (String(url).endsWith("/api/v1/models/load")) {
540531return new Response("load failed", { status: 503 });
@@ -575,20 +566,12 @@ describe("lmstudio-models", () => {
575566it("reports malformed model load JSON with an owned error", async () => {
576567const fetchMock = vi.fn(async (url: string | URL) => {
577568if (String(url).endsWith("/api/v1/models")) {
578-return {
579-ok: true,
580-json: async () => ({
581-models: [{ type: "llm", key: "qwen3-8b-instruct", loaded_instances: [] }],
582-}),
583-};
569+return jsonResponse({
570+models: [{ type: "llm", key: "qwen3-8b-instruct", loaded_instances: [] }],
571+});
584572}
585573if (String(url).endsWith("/api/v1/models/load")) {
586-return {
587-ok: true,
588-json: async () => {
589-throw new SyntaxError("bad json");
590-},
591-};
574+return malformedJsonResponse();
592575}
593576throw new Error(`Unexpected fetch URL: ${String(url)}`);
594577});
@@ -608,12 +591,9 @@ describe("lmstudio-models", () => {
608591const textSpy = vi.spyOn(tracked.response, "text").mockRejectedValue(new Error("unbounded"));
609592const fetchMock = vi.fn(async (url: string | URL) => {
610593if (String(url).endsWith("/api/v1/models")) {
611-return {
612-ok: true,
613-json: async () => ({
614-models: [{ type: "llm", key: "qwen3-8b-instruct", loaded_instances: [] }],
615-}),
616-};
594+return jsonResponse({
595+models: [{ type: "llm", key: "qwen3-8b-instruct", loaded_instances: [] }],
596+});
617597}
618598if (String(url).endsWith("/api/v1/models/load")) {
619599return tracked.response;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。