惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
WordPress大学
WordPress大学
U
Unit 42
I
InfoQ
A
About on SuperTechFans
宝玉的分享
宝玉的分享
J
Java Code Geeks
博客园 - 司徒正美
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
G
Google Developers Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
aimingoo的专栏
aimingoo的专栏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
腾讯CDC
Recent Announcements
Recent Announcements

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
test(extensions): use real response mocks · openclaw/open...
vincentkoc · 2026-06-23 · via Recent Commits to openclaw:main

@@ -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+3449

afterAll(() => {

3550

vi.doUnmock("openclaw/plugin-sdk/ssrf-runtime");

3651

vi.resetModules();

@@ -72,33 +87,26 @@ describe("lmstudio-models", () => {

7287

loadedContextLength?: number;

7388

maxContextLength?: number;

7489

}) =>

75-

vi.fn(async (url: string | URL, init?: RequestInit) => {

90+

vi.fn(async (url: string | URL, _init?: RequestInit) => {

7691

const key = params?.key ?? "qwen3-8b-instruct";

7792

if (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

}

96108

if (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

}

103111

throw new Error(`Unexpected fetch URL: ${String(url)}`);

104112

});

@@ -296,9 +304,8 @@ describe("lmstudio-models", () => {

296304

});

297305298306

it("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({

302309

models: [

303310

{

304311

type: "llm",

@@ -330,7 +337,7 @@ describe("lmstudio-models", () => {

330337

},

331338

],

332339

}),

333-

}));

340+

);

334341335342

const models = await discoverLmstudioModels({

336343

baseUrl: "http://localhost:1234/v1",

@@ -386,13 +393,7 @@ describe("lmstudio-models", () => {

386393

});

387394388395

it("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());

396397397398

const result = await fetchLmstudioModels({

398399

baseUrl: "http://localhost:1234/v1",

@@ -405,11 +406,7 @@ describe("lmstudio-models", () => {

405406406407

it("reports wrong-shaped model list payloads with owned errors", async () => {

407408

for (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));

413410414411

const result = await fetchLmstudioModels({

415412

baseUrl: "http://localhost:1234/v1",

@@ -424,12 +421,9 @@ describe("lmstudio-models", () => {

424421

it("caps oversized direct fetch timeouts before discovering models", async () => {

425422

const timeoutController = new AbortController();

426423

const 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+

);

433427434428

const result = await fetchLmstudioModels({

435429

baseUrl: "http://localhost:1234/v1",

@@ -521,20 +515,17 @@ describe("lmstudio-models", () => {

521515

const variantKey = `${canonicalKey}@q4_k_m`;

522516

const fetchMock = vi.fn(async (url: string | URL) => {

523517

if (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

}

539530

if (String(url).endsWith("/api/v1/models/load")) {

540531

return new Response("load failed", { status: 503 });

@@ -575,20 +566,12 @@ describe("lmstudio-models", () => {

575566

it("reports malformed model load JSON with an owned error", async () => {

576567

const fetchMock = vi.fn(async (url: string | URL) => {

577568

if (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

}

585573

if (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

}

593576

throw new Error(`Unexpected fetch URL: ${String(url)}`);

594577

});

@@ -608,12 +591,9 @@ describe("lmstudio-models", () => {

608591

const textSpy = vi.spyOn(tracked.response, "text").mockRejectedValue(new Error("unbounded"));

609592

const fetchMock = vi.fn(async (url: string | URL) => {

610593

if (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

}

618598

if (String(url).endsWith("/api/v1/models/load")) {

619599

return tracked.response;