Fix WebUI startup blocking on slow gateway routes

This commit is contained in:
chengyongru
2026-06-13 21:59:36 +08:00
committed by Xubin Ren
parent 3a221d74cf
commit af0e3441d7
12 changed files with 280 additions and 17 deletions
+7 -2
View File
@@ -11,7 +11,12 @@ import { StreamErrorNotice } from "@/components/thread/StreamErrorNotice";
import { ThreadViewport, type ThreadViewportHandle } from "@/components/thread/ThreadViewport";
import { useNanobotStream, type SendImage, type SendOptions } from "@/hooks/useNanobotStream";
import { useSessionHistory } from "@/hooks/useSessions";
import { fetchCliApps, fetchMcpPresets, fetchSettings, listSlashCommands } from "@/lib/api";
import {
fetchInstalledCliApps,
fetchMcpPresets,
fetchSettings,
listSlashCommands,
} from "@/lib/api";
import {
CLI_APPS_CHANGED_EVENT,
installedCliAppsFromPayload,
@@ -265,7 +270,7 @@ export function ThreadShell({
const cliApps = useInstalledSettingItems({
token,
eventName: CLI_APPS_CHANGED_EVENT,
fetchPayload: fetchCliApps,
fetchPayload: fetchInstalledCliApps,
isPayload: isCliAppsPayload,
selectItems: installedCliAppsFromPayload,
});
+12
View File
@@ -294,6 +294,18 @@ export async function fetchCliApps(
);
}
export async function fetchInstalledCliApps(
token: string,
base: string = "",
): Promise<CliAppsPayload> {
return request<CliAppsPayload>(
`${base}/api/settings/cli-apps?installed_only=1`,
token,
undefined,
API_READ_TIMEOUT_MS,
);
}
export async function runCliAppAction(
token: string,
action: "install" | "update" | "uninstall" | "test",
+20
View File
@@ -5,6 +5,7 @@ import {
deleteSession,
fetchFilePreview,
fetchCliApps,
fetchInstalledCliApps,
fetchMcpPresets,
fetchProviderModels,
fetchSessionAutomations,
@@ -375,6 +376,25 @@ describe("webui API helpers", () => {
);
});
it("reads installed CLI Apps without fetching the full catalog", async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,
json: async () => ({
apps: [],
installed_count: 0,
catalog_updated_at: null,
}),
} as Response);
await expect(fetchInstalledCliApps("tok")).resolves.toMatchObject({ apps: [] });
expect(fetch).toHaveBeenCalledWith(
"/api/settings/cli-apps?installed_only=1",
expect.objectContaining({
headers: { Authorization: "Bearer tok" },
}),
);
});
it("reads MCP presets and serializes actions", async () => {
vi.mocked(fetch).mockResolvedValueOnce({
ok: true,