




















@@ -21,11 +21,13 @@ vi.mock("openclaw/plugin-sdk/provider-auth", () => ({
2121}));
22222323let listCodexAppServerModels: typeof import("./models.js").listCodexAppServerModels;
24+let listAllCodexAppServerModels: typeof import("./models.js").listAllCodexAppServerModels;
2425let resetSharedCodexAppServerClientForTests: typeof import("./shared-client.js").resetSharedCodexAppServerClientForTests;
25262627describe("listCodexAppServerModels", () => {
2728beforeAll(async () => {
2829({ listCodexAppServerModels } = await import("./models.js"));
30+({ listAllCodexAppServerModels } = await import("./models.js"));
2931({ resetSharedCodexAppServerClientForTests } = await import("./shared-client.js"));
3032});
3133@@ -97,4 +99,132 @@ describe("listCodexAppServerModels", () => {
9799harness.client.close();
98100startSpy.mockRestore();
99101});
102+103+it("lists all app-server model pages through one client", async () => {
104+const harness = createClientHarness();
105+const startSpy = vi.spyOn(CodexAppServerClient, "start").mockReturnValue(harness.client);
106+107+const listPromise = listAllCodexAppServerModels({ limit: 1, timeoutMs: 1000 });
108+await vi.waitFor(() => expect(harness.writes.length).toBeGreaterThanOrEqual(1));
109+const initialize = JSON.parse(harness.writes[0] ?? "{}") as { id?: number };
110+harness.send({
111+id: initialize.id,
112+result: { userAgent: "openclaw/0.118.0 (macOS; test)" },
113+});
114+await vi.waitFor(() => expect(harness.writes.length).toBeGreaterThanOrEqual(3));
115+const firstList = JSON.parse(harness.writes[2] ?? "{}") as {
116+id?: number;
117+params?: { cursor?: string | null };
118+};
119+expect(firstList.params?.cursor).toBeNull();
120+121+harness.send({
122+id: firstList.id,
123+result: {
124+data: [
125+{
126+id: "gpt-5.4",
127+model: "gpt-5.4",
128+upgrade: null,
129+upgradeInfo: null,
130+availabilityNux: null,
131+displayName: "gpt-5.4",
132+description: "GPT-5.4",
133+hidden: false,
134+inputModalities: ["text"],
135+supportedReasoningEfforts: [],
136+defaultReasoningEffort: "medium",
137+supportsPersonality: false,
138+additionalSpeedTiers: [],
139+isDefault: false,
140+},
141+],
142+nextCursor: "page-2",
143+},
144+});
145+await vi.waitFor(() => expect(harness.writes.length).toBeGreaterThanOrEqual(4));
146+const secondList = JSON.parse(harness.writes[3] ?? "{}") as {
147+id?: number;
148+params?: { cursor?: string | null };
149+};
150+expect(secondList.params?.cursor).toBe("page-2");
151+152+harness.send({
153+id: secondList.id,
154+result: {
155+data: [
156+{
157+id: "gpt-5.2",
158+model: "gpt-5.2",
159+upgrade: null,
160+upgradeInfo: null,
161+availabilityNux: null,
162+displayName: "gpt-5.2",
163+description: "GPT-5.2",
164+hidden: false,
165+inputModalities: ["text", "image"],
166+supportedReasoningEfforts: [],
167+defaultReasoningEffort: "medium",
168+supportsPersonality: false,
169+additionalSpeedTiers: [],
170+isDefault: false,
171+},
172+],
173+nextCursor: null,
174+},
175+});
176+177+await expect(listPromise).resolves.toMatchObject({
178+models: [{ id: "gpt-5.4" }, { id: "gpt-5.2" }],
179+});
180+harness.client.close();
181+startSpy.mockRestore();
182+});
183+184+it("marks all-model listing truncated after the page cap", async () => {
185+const harness = createClientHarness();
186+const startSpy = vi.spyOn(CodexAppServerClient, "start").mockReturnValue(harness.client);
187+188+const listPromise = listAllCodexAppServerModels({ limit: 1, timeoutMs: 1000, maxPages: 1 });
189+await vi.waitFor(() => expect(harness.writes.length).toBeGreaterThanOrEqual(1));
190+const initialize = JSON.parse(harness.writes[0] ?? "{}") as { id?: number };
191+harness.send({
192+id: initialize.id,
193+result: { userAgent: "openclaw/0.118.0 (macOS; test)" },
194+});
195+await vi.waitFor(() => expect(harness.writes.length).toBeGreaterThanOrEqual(3));
196+const firstList = JSON.parse(harness.writes[2] ?? "{}") as { id?: number };
197+harness.send({
198+id: firstList.id,
199+result: {
200+data: [
201+{
202+id: "gpt-5.4",
203+model: "gpt-5.4",
204+upgrade: null,
205+upgradeInfo: null,
206+availabilityNux: null,
207+displayName: "gpt-5.4",
208+description: "GPT-5.4",
209+hidden: false,
210+inputModalities: ["text"],
211+supportedReasoningEfforts: [],
212+defaultReasoningEffort: "medium",
213+supportsPersonality: false,
214+additionalSpeedTiers: [],
215+isDefault: false,
216+},
217+],
218+nextCursor: "page-2",
219+},
220+});
221+222+await expect(listPromise).resolves.toMatchObject({
223+models: [{ id: "gpt-5.4" }],
224+nextCursor: "page-2",
225+truncated: true,
226+});
227+harness.client.close();
228+startSpy.mockRestore();
229+});
100230});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。