Skip to content

Commit d9e0e20

Browse files
committed
feat: reduce probe timeouts and add refreshProviders to server API
1 parent 80e56c1 commit d9e0e20

5 files changed

Lines changed: 79 additions & 10 deletions

File tree

apps/server/src/provider/Layers/ClaudeProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ export function adjustModelsForSubscription(
391391

392392
// ── SDK capability probe ────────────────────────────────────────────
393393

394-
const CAPABILITIES_PROBE_TIMEOUT_MS = 8_000;
394+
const CAPABILITIES_PROBE_TIMEOUT_MS = 2_000;
395395
const CLAUDE_RATE_LIMIT_PROBE_TIMEOUT_MS = 1_000;
396396

397397
/**

apps/server/src/provider/Layers/CodexProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ export const hasCustomModelProvider = readCodexConfigModelProvider().pipe(
282282
Effect.orElseSucceed(() => false),
283283
);
284284

285-
const CAPABILITIES_PROBE_TIMEOUT_MS = 8_000;
285+
const CAPABILITIES_PROBE_TIMEOUT_MS = 2_000;
286286

287287
const probeCodexCapabilities = (input: {
288288
readonly binaryPath: string;

apps/server/src/provider/codexAppServer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface JsonRpcProbeResponse {
2323
};
2424
}
2525

26-
const RATE_LIMITS_PROBE_GRACE_MS = 1_500;
26+
const RATE_LIMITS_PROBE_GRACE_MS = 150;
2727

2828
function readErrorMessage(response: JsonRpcProbeResponse): string | undefined {
2929
return typeof response.error?.message === "string" ? response.error.message : undefined;

apps/web/src/rpc/serverState.test.ts

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ const baseServerConfig: ServerConfig = {
6262

6363
const serverApi = {
6464
getConfig: vi.fn<() => Promise<ServerConfig>>(),
65+
refreshProviders: vi.fn<
66+
() => Promise<{
67+
providers: ReadonlyArray<ServerProvider>;
68+
}>
69+
>(),
6570
subscribeConfig: vi.fn((listener: (event: ServerConfigStreamEvent) => void) =>
6671
registerListener(configListeners, listener),
6772
),
@@ -101,6 +106,7 @@ beforeEach(() => {
101106
vi.clearAllMocks();
102107
lifecycleListeners.clear();
103108
configListeners.clear();
109+
serverApi.refreshProviders.mockResolvedValue({ providers: defaultProviders });
104110
resetServerStateForTests();
105111
});
106112

@@ -123,6 +129,7 @@ describe("serverState", () => {
123129
expect(serverApi.subscribeConfig).toHaveBeenCalledOnce();
124130
expect(serverApi.subscribeLifecycle).toHaveBeenCalledOnce();
125131
expect(serverApi.getConfig).toHaveBeenCalledOnce();
132+
expect(serverApi.refreshProviders).toHaveBeenCalledOnce();
126133
expect(configListener).toHaveBeenCalledWith(
127134
{
128135
issues: [],
@@ -168,10 +175,15 @@ describe("serverState", () => {
168175
expect(getServerConfig()).toEqual(streamedConfig);
169176
});
170177

178+
await waitFor(() => {
179+
expect(serverApi.refreshProviders).toHaveBeenCalledOnce();
180+
});
181+
171182
deferred.resolve(baseServerConfig);
172183
await new Promise((resolve) => setTimeout(resolve, 0));
173184

174185
expect(getServerConfig()).toEqual(streamedConfig);
186+
expect(serverApi.refreshProviders).toHaveBeenCalledOnce();
175187
stop();
176188
});
177189

@@ -274,24 +286,22 @@ describe("serverState", () => {
274286
});
275287

276288
expect(providersListener).toHaveBeenLastCalledWith({ providers: nextProviders });
277-
expect(configListener).toHaveBeenNthCalledWith(
278-
2,
289+
expect(configListener.mock.calls).toContainEqual([
279290
{
280291
issues: [{ kind: "keybindings.malformed-config", message: "bad json" }],
281292
providers: defaultProviders,
282293
settings: DEFAULT_SERVER_SETTINGS,
283294
},
284295
"keybindingsUpdated",
285-
);
286-
expect(configListener).toHaveBeenNthCalledWith(
287-
3,
296+
]);
297+
expect(configListener.mock.calls).toContainEqual([
288298
{
289299
issues: [{ kind: "keybindings.malformed-config", message: "bad json" }],
290300
providers: nextProviders,
291301
settings: DEFAULT_SERVER_SETTINGS,
292302
},
293303
"providerStatuses",
294-
);
304+
]);
295305
expect(configListener).toHaveBeenLastCalledWith(
296306
{
297307
issues: [{ kind: "keybindings.malformed-config", message: "bad json" }],
@@ -308,4 +318,39 @@ describe("serverState", () => {
308318
unsubscribeConfig();
309319
stop();
310320
});
321+
322+
it("applies eager refreshProviders results without waiting for stream events", async () => {
323+
const refreshedProviders: ReadonlyArray<ServerProvider> = [
324+
{
325+
...defaultProviders[0]!,
326+
checkedAt: "2026-01-03T00:00:00.000Z",
327+
usage: {
328+
updatedAt: "2026-01-03T00:00:00.000Z",
329+
buckets: [
330+
{
331+
id: "weekly",
332+
label: "Weekly usage limit",
333+
usedPercent: 12,
334+
remainingPercent: 88,
335+
resetsAt: "2026-01-08T16:19:00.000Z",
336+
},
337+
],
338+
},
339+
},
340+
];
341+
serverApi.getConfig.mockResolvedValueOnce(baseServerConfig);
342+
serverApi.refreshProviders.mockResolvedValueOnce({ providers: refreshedProviders });
343+
344+
const stop = startServerStateSync(serverApi);
345+
346+
await waitFor(() => {
347+
expect(getServerConfig()).toEqual({
348+
...baseServerConfig,
349+
providers: refreshedProviders,
350+
});
351+
});
352+
353+
expect(serverApi.refreshProviders).toHaveBeenCalledOnce();
354+
stop();
355+
});
311356
});

apps/web/src/rpc/serverState.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export interface ServerConfigUpdatedNotification {
2424

2525
type ServerStateClient = Pick<
2626
WsRpcClient["server"],
27-
"getConfig" | "subscribeConfig" | "subscribeLifecycle"
27+
"getConfig" | "refreshProviders" | "subscribeConfig" | "subscribeLifecycle"
2828
>;
2929

3030
function makeStateAtom<A>(label: string, initialValue: A) {
@@ -161,6 +161,24 @@ export function onProvidersUpdated(
161161

162162
export function startServerStateSync(client: ServerStateClient): () => void {
163163
let disposed = false;
164+
let providerRefreshRequested = false;
165+
166+
const requestProviderRefresh = () => {
167+
if (disposed || providerRefreshRequested) {
168+
return;
169+
}
170+
providerRefreshRequested = true;
171+
void client
172+
.refreshProviders()
173+
.then((payload) => {
174+
if (disposed) {
175+
return;
176+
}
177+
applyProvidersUpdated(payload);
178+
})
179+
.catch(() => undefined);
180+
};
181+
164182
const cleanups = [
165183
client.subscribeLifecycle((event) => {
166184
if (event.type === "welcome") {
@@ -169,6 +187,9 @@ export function startServerStateSync(client: ServerStateClient): () => void {
169187
}),
170188
client.subscribeConfig((event) => {
171189
applyServerConfigEvent(event);
190+
if (event.type === "snapshot") {
191+
requestProviderRefresh();
192+
}
172193
}),
173194
];
174195

@@ -180,8 +201,11 @@ export function startServerStateSync(client: ServerStateClient): () => void {
180201
return;
181202
}
182203
setServerConfigSnapshot(config);
204+
requestProviderRefresh();
183205
})
184206
.catch(() => undefined);
207+
} else {
208+
requestProviderRefresh();
185209
}
186210

187211
return () => {

0 commit comments

Comments
 (0)