# Conflicts:
#	frontend-web/src/components/workspace/workspace-nav-menu.tsx
#	offline-backend-20260512/backend/app/gateway/routers/multi_agent.py
This commit is contained in:
fengxiangdebaozi committed 2026-07-26 20:55:50 +08:00
commit 239b798c5d
42 files changed
+2416 -282

No files matched your search

@@ -31,3 +31,20 @@ test("forces light theme for landing and chats_iframe routes only", () => {
);
assert.equal(resolveForcedThemeForPath("/page/workspace/chats/new"), undefined);
});
test("honors the dark-blue theme query on chats_iframe routes", () => {
assert.equal(
resolveForcedThemeForPath(
"/page/workspace/chats_iframe/new",
"?from=iframe&theme=dark-blue",
),
"dark",
);
assert.equal(
resolveForcedThemeForPath(
"/page/workspace/chats_iframe/new",
"?from=iframe&theme=red",
),
"light",
);
});
@@ -1,3 +1,5 @@
import { resolveEmbedThemeMode } from "@/core/embed/embed-session";
export function isChatsIframeWorkspacePath(pathname: string): boolean {
return (
pathname === "/page/workspace/chats_iframe/new" ||
@@ -7,10 +9,17 @@ export function isChatsIframeWorkspacePath(pathname: string): boolean {
export function resolveForcedThemeForPath(
pathname: string,
): "light" | undefined {
if (pathname === "/landing" || isChatsIframeWorkspacePath(pathname)) {
search = "",
): "light" | "dark" | undefined {
if (pathname === "/landing") {
return "light";
}
if (isChatsIframeWorkspacePath(pathname)) {
const normalizedSearch = search.startsWith("?") ? search : `?${search}`;
const rawTheme = new URLSearchParams(normalizedSearch).get("theme")?.trim();
return rawTheme ? resolveEmbedThemeMode(rawTheme) : "light";
}
return undefined;
}
@@ -187,4 +187,4 @@ test("unmapped incoming url resets auto-selected agent back to default when ther
forceDefaultAssistant: true,
},
);
});
});
@@ -504,12 +504,16 @@ export interface ModelConcurrencySettings {
enabled: boolean;
default_limit: number;
model_limits: Record<string, number>;
user_default_limit: number;
user_model_limits: Record<string, number>;
}
export interface ModelConcurrencyUpdate {
enabled?: boolean;
default_limit?: number;
model_limits?: Record<string, number>;
user_default_limit?: number;
user_model_limits?: Record<string, number>;
}
export async function loadSkillCompressionSettings(): Promise<SkillCompressionSettings> {
+43 -13
View File
@@ -322,11 +322,24 @@ function isModelConcurrencyLimitError(message: string): boolean {
return (
/\b429\b/.test(message) ||
/并发已达到上限/.test(message) ||
/并发调用已达到上限/.test(message) ||
/使用人数较多/.test(message) ||
/too many requests/i.test(message)
);
}
function friendlySendLimitMessage(message: string): string | null {
if (isActiveRunConflictError(message)) {
return "当前对话还在生成回答,请等待本轮回复结束,或先点“停止”再发送新的问题。";
}
if (isModelConcurrencyLimitError(message)) {
return /当前账号对该模型/.test(message)
? "当前账号对该模型的并发调用已达到上限,请等待已有回答结束后再试。"
: "当前使用人数较多,请稍等一下再试。";
}
return null;
}
function buildCurrentUserLabel(): string {
const auth = getStoredAuth();
if (!auth) {
@@ -684,14 +697,11 @@ export function useThreadStream({
}
return;
}
// 上一轮还没结束又发了新问题(后端 409):给一句明确的中文提示,而不是
// 把原始的英文/HTTP 错误抛给用户。
if (isActiveRunConflictError(message)) {
toast.info("当前对话还在生成回答,请等待本轮回复结束,或先点「停止」再发送新的问题。");
return;
}
if (isModelConcurrencyLimitError(message)) {
toast.info("当前使用人数较多,请稍等一下再试。");
// 上一轮还没结束又发了新问题(409)或并发达到上限(429):
// 给一句明确的中文提示,而不是把原始 HTTP 错误抛给用户。
const friendly = friendlySendLimitMessage(message);
if (friendly) {
toast.info(friendly);
return;
}
toast.error(message);
@@ -1197,11 +1207,31 @@ export function useThreadStream({
},
);
void queryClient.invalidateQueries({ queryKey: ["threads", "search"] });
} catch (error) {
setOptimisticMessages([]);
setIsUploading(false);
throw error;
} finally {
} catch (error) {
const message =
error instanceof Error ? error.message : String(error);
const friendly = friendlySendLimitMessage(message);
if (friendly) {
setOptimisticMessages((messages) => {
const human = messages.find((item) => item.type === "human");
const kept = human ? [human] : [];
return [
...kept,
{
type: "ai",
id: `opt-ai-limit-${Date.now()}`,
content: friendly,
additional_kwargs: { element: "task" },
} as Message,
];
});
setIsUploading(false);
return;
}
setOptimisticMessages([]);
setIsUploading(false);
throw error;
} finally {
sendInFlightRef.current = false;
}
},