Skip to content

Commit bb401f9

Browse files
Han KimHan Kim
authored andcommitted
fix(ui): reduce sessions list refresh cost
1 parent 4714891 commit bb401f9

5 files changed

Lines changed: 58 additions & 9 deletions

File tree

src/agents/model-selection-cli.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,43 @@ import { resolveRuntimeCliBackends } from "../plugins/cli-backends.runtime.js";
33
import { resolvePluginSetupCliBackendRuntime } from "../plugins/setup-registry.runtime.js";
44
import { normalizeProviderId } from "./model-selection-normalize.js";
55

6+
const cliProviderResultCache = new Map<string, boolean>();
7+
8+
export const __testing = {
9+
resetCliProviderCache(): void {
10+
cliProviderResultCache.clear();
11+
},
12+
};
13+
14+
function buildCliProviderCacheKey(provider: string, cfg?: OpenClawConfig): string {
15+
const configuredBackendKeys = Object.keys(cfg?.agents?.defaults?.cliBackends ?? {})
16+
.map((key) => normalizeProviderId(key))
17+
.sort()
18+
.join(",");
19+
return `${provider}|${configuredBackendKeys}`;
20+
}
21+
622
export function isCliProvider(provider: string, cfg?: OpenClawConfig): boolean {
723
const normalized = normalizeProviderId(provider);
24+
const cacheKey = buildCliProviderCacheKey(normalized, cfg);
25+
const cached = cliProviderResultCache.get(cacheKey);
26+
if (cached !== undefined) {
27+
return cached;
28+
}
29+
830
const backends = cfg?.agents?.defaults?.cliBackends ?? {};
31+
let result = false;
932
if (Object.keys(backends).some((key) => normalizeProviderId(key) === normalized)) {
10-
return true;
11-
}
12-
const cliBackends = resolveRuntimeCliBackends();
13-
if (cliBackends.some((backend) => normalizeProviderId(backend.id) === normalized)) {
14-
return true;
33+
result = true;
34+
} else {
35+
const cliBackends = resolveRuntimeCliBackends();
36+
if (cliBackends.some((backend) => normalizeProviderId(backend.id) === normalized)) {
37+
result = true;
38+
} else if (resolvePluginSetupCliBackendRuntime({ backend: normalized, config: cfg })) {
39+
result = true;
40+
}
1541
}
16-
if (resolvePluginSetupCliBackendRuntime({ backend: normalized, config: cfg })) {
17-
return true;
18-
}
19-
return false;
42+
43+
cliProviderResultCache.set(cacheKey, result);
44+
return result;
2045
}

src/agents/model-selection.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { OpenClawConfig } from "../config/types.js";
33
import { resetLogger, setLoggerOverride } from "../logging/logger.js";
44
import { createWarnLogCapture } from "../logging/test-helpers/warn-log-capture.js";
55
import { __testing as setupRegistryRuntimeTesting } from "../plugins/setup-registry.runtime.js";
6+
import { __testing as modelSelectionCliTesting } from "./model-selection-cli.js";
67
import {
78
buildAllowedModelSet,
89
inferUniqueProviderFromConfiguredModels,
@@ -157,6 +158,7 @@ describe("model-selection", () => {
157158

158159
describe("isCliProvider", () => {
159160
beforeEach(() => {
161+
modelSelectionCliTesting.resetCliProviderCache();
160162
setupRegistryRuntimeTesting.resetRuntimeState();
161163
setupRegistryRuntimeTesting.setRuntimeModuleForTest({
162164
resolvePluginSetupCliBackend: ({ backend }) =>
@@ -170,6 +172,7 @@ describe("model-selection", () => {
170172
});
171173

172174
afterEach(() => {
175+
modelSelectionCliTesting.resetCliProviderCache();
173176
setupRegistryRuntimeTesting.resetRuntimeState();
174177
});
175178

@@ -180,6 +183,23 @@ describe("model-selection", () => {
180183
it("returns false for provider ids", () => {
181184
expect(isCliProvider("example-cli", {} as OpenClawConfig)).toBe(false);
182185
});
186+
187+
it("caches setup registry cli backend lookups", () => {
188+
const resolvePluginSetupCliBackend = vi.fn(({ backend }) =>
189+
backend === "claude-cli"
190+
? {
191+
pluginId: "anthropic",
192+
backend: { id: "claude-cli", config: { command: "claude" } },
193+
}
194+
: undefined,
195+
);
196+
setupRegistryRuntimeTesting.setRuntimeModuleForTest({ resolvePluginSetupCliBackend });
197+
198+
expect(isCliProvider("claude-cli", {} as OpenClawConfig)).toBe(true);
199+
expect(isCliProvider("claude-cli", {} as OpenClawConfig)).toBe(true);
200+
201+
expect(resolvePluginSetupCliBackend).toHaveBeenCalledTimes(1);
202+
});
183203
});
184204

185205
describe("modelKey", () => {

ui/src/ui/app-chat.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export type ChatSendOptions = {
7878
};
7979

8080
export const CHAT_SESSIONS_ACTIVE_MINUTES = 120;
81+
export const CHAT_SESSIONS_REFRESH_LIMIT = 5;
8182
export {
8283
handleChatDraftChange,
8384
handleChatInputHistoryKey,

ui/src/ui/app-gateway.sessions.node.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const applySessionsChangedEventMock = vi.fn();
77

88
vi.mock("./app-chat.ts", () => ({
99
CHAT_SESSIONS_ACTIVE_MINUTES: 10,
10+
CHAT_SESSIONS_REFRESH_LIMIT: 5,
1011
flushChatQueueForEvent: vi.fn(),
1112
refreshChatAvatar: vi.fn(),
1213
}));

ui/src/ui/app-gateway.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
import { ConnectErrorDetailCodes } from "../../../src/gateway/protocol/connect-error-details.js";
66
import {
77
CHAT_SESSIONS_ACTIVE_MINUTES,
8+
CHAT_SESSIONS_REFRESH_LIMIT,
89
clearPendingQueueItemsForRun,
910
flushChatQueueForEvent,
1011
refreshChatAvatar,
@@ -584,6 +585,7 @@ function handleTerminalChatEvent(
584585
if (state === "final") {
585586
void loadSessions(host as unknown as SessionsState, {
586587
activeMinutes: CHAT_SESSIONS_ACTIVE_MINUTES,
588+
limit: CHAT_SESSIONS_REFRESH_LIMIT,
587589
});
588590
}
589591
}

0 commit comments

Comments
 (0)