1612 lines
48 KiB
TypeScript
1612 lines
48 KiB
TypeScript
import { apiFetch } from "@/core/api";
|
||
import { getBackendBaseURL } from "@/core/config";
|
||
import { withKnowledgeRequestTimeout } from "@/core/llmwiki/request-timeout";
|
||
import { OptType, writeYLog } from "@/core/log/y-log";
|
||
|
||
export type WordHeadingNumberingStyle =
|
||
| "hybrid_decimal"
|
||
| "official_chinese"
|
||
| "decimal"
|
||
| "chapter_section"
|
||
| "none";
|
||
|
||
export interface PromptPrefixSettings {
|
||
image_generation_unavailable_hint_enabled: boolean;
|
||
python_dependency_delete_protection_enabled: boolean;
|
||
enabled: boolean;
|
||
switch_label: string;
|
||
prompt_prefix: string;
|
||
ordinary_qa_markdown_format_enabled: boolean;
|
||
word_heading_numbering_style: WordHeadingNumberingStyle;
|
||
}
|
||
|
||
export type KnowledgeBaseProductVersion = "v1" | "v2";
|
||
|
||
export type OrdinaryKnowledgeLanding = "wiki" | "weknora";
|
||
|
||
export interface StrategyProjectSettings {
|
||
taiwan_strait_demo_enabled: boolean;
|
||
}
|
||
|
||
export interface StrategyProjectSettingsUpdate {
|
||
taiwan_strait_demo_enabled?: boolean;
|
||
}
|
||
|
||
export interface GeneralQaPageDescription {
|
||
welcome_title: string;
|
||
welcome_description: string;
|
||
input_placeholder: string;
|
||
}
|
||
|
||
export interface GeneralQaPageDescriptions {
|
||
full: GeneralQaPageDescription;
|
||
compact: GeneralQaPageDescription;
|
||
}
|
||
|
||
export interface PageHeaderDescription {
|
||
title: string;
|
||
description: string;
|
||
}
|
||
|
||
export interface AIWritingGuideCard {
|
||
title: string;
|
||
description: string;
|
||
}
|
||
|
||
export interface AIWritingPageDescription extends PageHeaderDescription {
|
||
guide_cards: AIWritingGuideCard[];
|
||
}
|
||
|
||
export interface PageDescriptionsSettings {
|
||
general_qa: GeneralQaPageDescriptions;
|
||
knowledge_base: PageHeaderDescription;
|
||
ai_writing: AIWritingPageDescription;
|
||
strategy_projects: PageHeaderDescription;
|
||
deep_research: PageHeaderDescription;
|
||
gongwen: PageHeaderDescription;
|
||
light_app_management: PageHeaderDescription;
|
||
light_app_list: PageHeaderDescription;
|
||
agents: PageHeaderDescription;
|
||
business_chains: PageHeaderDescription;
|
||
skills: PageHeaderDescription;
|
||
knowledge_management: PageHeaderDescription;
|
||
}
|
||
|
||
export type PageDescriptionsUpdate = PageDescriptionsSettings;
|
||
|
||
export async function loadPageDescriptionsSettings(): Promise<PageDescriptionsSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/page-descriptions`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`无法读取页面描述配置(HTTP ${response.status})`);
|
||
}
|
||
return (await response.json()) as PageDescriptionsSettings;
|
||
}
|
||
|
||
export async function updatePageDescriptionsSettings(
|
||
body: PageDescriptionsUpdate,
|
||
): Promise<PageDescriptionsSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/page-descriptions`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "保存页面描述配置失败" }));
|
||
throw new Error(detail.detail ?? "保存页面描述配置失败");
|
||
}
|
||
const data = (await response.json()) as PageDescriptionsSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-页面描述配置编辑",
|
||
url: "/api/system-settings/page-descriptions",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadStrategyProjectSettings(): Promise<StrategyProjectSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/strategy-projects`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`无法读取策略项目设置(HTTP ${response.status})`);
|
||
}
|
||
return (await response.json()) as StrategyProjectSettings;
|
||
}
|
||
|
||
export async function updateStrategyProjectSettings(
|
||
body: StrategyProjectSettingsUpdate,
|
||
): Promise<StrategyProjectSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/strategy-projects`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "保存策略项目设置失败" }));
|
||
throw new Error(detail.detail ?? "保存策略项目设置失败");
|
||
}
|
||
return (await response.json()) as StrategyProjectSettings;
|
||
}
|
||
|
||
export async function loadOrdinaryKnowledgeLanding(signal?: AbortSignal): Promise<OrdinaryKnowledgeLanding> {
|
||
return withKnowledgeRequestTimeout(async (requestSignal) => {
|
||
const response = await apiFetch(`${getBackendBaseURL()}/api/system-settings/ordinary-knowledge-landing`, { signal: requestSignal });
|
||
if (!response.ok) throw new Error("无法读取普通知识库默认页面设置");
|
||
return ((await response.json()) as { mode: OrdinaryKnowledgeLanding }).mode;
|
||
}, { signal, timeoutMs: 10_000 });
|
||
}
|
||
|
||
export async function saveOrdinaryKnowledgeLanding(mode: OrdinaryKnowledgeLanding): Promise<OrdinaryKnowledgeLanding> {
|
||
const response = await apiFetch(`${getBackendBaseURL()}/api/system-settings/ordinary-knowledge-landing`, {
|
||
method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ mode }),
|
||
});
|
||
if (!response.ok) throw new Error("保存失败,仅管理员可配置普通知识库默认页面");
|
||
return ((await response.json()) as { mode: OrdinaryKnowledgeLanding }).mode;
|
||
}
|
||
|
||
export async function loadKnowledgeBaseProductVersion(signal?: AbortSignal): Promise<KnowledgeBaseProductVersion> {
|
||
return withKnowledgeRequestTimeout(async (requestSignal) => {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/knowledge-base-product-version`,
|
||
{ signal: requestSignal },
|
||
);
|
||
if (!response.ok) throw new Error(`无法读取助手知识库访问设置(HTTP ${response.status})`);
|
||
return ((await response.json()) as { version: KnowledgeBaseProductVersion }).version;
|
||
}, { signal });
|
||
}
|
||
|
||
export async function updateKnowledgeBaseProductVersion(
|
||
version: KnowledgeBaseProductVersion,
|
||
): Promise<KnowledgeBaseProductVersion> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/knowledge-base-product-version`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({ version }),
|
||
},
|
||
);
|
||
if (!response.ok) throw new Error(`Failed to update knowledge base product version: ${response.status}`);
|
||
return ((await response.json()) as { version: KnowledgeBaseProductVersion }).version;
|
||
}
|
||
|
||
/**
|
||
* Whether assistant knowledge bases are released to ordinary users.
|
||
*
|
||
* The persisted v1/v2 product switch remains the source of truth: v1 keeps
|
||
* assistant knowledge admin-only, while v2 exposes it in day-to-day surfaces.
|
||
*/
|
||
export async function loadAssistantKnowledgeVisibility(signal?: AbortSignal): Promise<boolean> {
|
||
return (await loadKnowledgeBaseProductVersion(signal)) === "v2";
|
||
}
|
||
|
||
export async function saveAssistantKnowledgeVisibility(
|
||
visible: boolean,
|
||
): Promise<boolean> {
|
||
return (await updateKnowledgeBaseProductVersion(visible ? "v2" : "v1")) === "v2";
|
||
}
|
||
|
||
export interface PluginDomainAgentMappingDto {
|
||
id: string;
|
||
domain: string;
|
||
agent_id: string;
|
||
enabled: boolean;
|
||
}
|
||
|
||
export interface PluginManagementSettings {
|
||
domainAgentMappings: Array<{
|
||
id: string;
|
||
domain: string;
|
||
agentId: string;
|
||
enabled: boolean;
|
||
}>;
|
||
}
|
||
|
||
export interface PluginManagementUpdate {
|
||
domainAgentMappings?: Array<{
|
||
id: string;
|
||
domain: string;
|
||
agentId: string;
|
||
enabled: boolean;
|
||
}>;
|
||
}
|
||
|
||
export interface PromptPrefixUpdate {
|
||
image_generation_unavailable_hint_enabled?: boolean;
|
||
python_dependency_delete_protection_enabled?: boolean;
|
||
enabled?: boolean;
|
||
switch_label?: string;
|
||
prompt_prefix?: string;
|
||
ordinary_qa_markdown_format_enabled?: boolean;
|
||
word_heading_numbering_style?: WordHeadingNumberingStyle;
|
||
}
|
||
|
||
function fromPluginManagementDto(data: {
|
||
domain_agent_mappings: PluginDomainAgentMappingDto[];
|
||
}): PluginManagementSettings {
|
||
return {
|
||
domainAgentMappings: (data.domain_agent_mappings ?? []).map((item) => ({
|
||
id: item.id,
|
||
domain: item.domain,
|
||
agentId: item.agent_id,
|
||
enabled: item.enabled,
|
||
})),
|
||
};
|
||
}
|
||
|
||
function toPluginManagementDto(body: PluginManagementUpdate) {
|
||
return {
|
||
domain_agent_mappings: (body.domainAgentMappings ?? []).map((item) => ({
|
||
id: item.id,
|
||
domain: item.domain,
|
||
agent_id: item.agentId,
|
||
enabled: item.enabled,
|
||
})),
|
||
};
|
||
}
|
||
|
||
export async function loadPluginManagementSettings(): Promise<PluginManagementSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/plugin-management`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load plugin management settings: ${response.status}`,
|
||
);
|
||
}
|
||
const data = (await response.json()) as {
|
||
domain_agent_mappings: PluginDomainAgentMappingDto[];
|
||
};
|
||
const mapped = fromPluginManagementDto(data);
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-插件管理查看",
|
||
url: "/api/system-settings/plugin-management",
|
||
returnParam: mapped,
|
||
});
|
||
return mapped;
|
||
}
|
||
|
||
export async function updatePluginManagementSettings(
|
||
body: PluginManagementUpdate,
|
||
): Promise<PluginManagementSettings> {
|
||
const payload = toPluginManagementDto(body);
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/plugin-management`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(payload),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update plugin management settings" }));
|
||
throw new Error(detail.detail ?? "Failed to update plugin management settings");
|
||
}
|
||
const data = (await response.json()) as {
|
||
domain_agent_mappings: PluginDomainAgentMappingDto[];
|
||
};
|
||
const mapped = fromPluginManagementDto(data);
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-插件管理编辑",
|
||
url: "/api/system-settings/plugin-management",
|
||
reqParam: payload,
|
||
returnParam: mapped,
|
||
});
|
||
return mapped;
|
||
}
|
||
|
||
export async function loadPromptPrefixSettings(): Promise<PromptPrefixSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/prompt-prefix`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load prompt prefix settings: ${response.status}`);
|
||
}
|
||
const data = (await response.json()) as PromptPrefixSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-提示词前缀查看",
|
||
url: "/api/system-settings/prompt-prefix",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updatePromptPrefixSettings(
|
||
body: PromptPrefixUpdate,
|
||
): Promise<PromptPrefixSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/prompt-prefix`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update prompt prefix" }));
|
||
throw new Error(detail.detail ?? "Failed to update prompt prefix");
|
||
}
|
||
const data = (await response.json()) as PromptPrefixSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-提示词前缀编辑",
|
||
url: "/api/system-settings/prompt-prefix",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export interface PrivateSquareStatus {
|
||
enabled: boolean;
|
||
password_set: boolean;
|
||
}
|
||
|
||
export interface PrivateSquareUpdate {
|
||
enabled?: boolean;
|
||
password?: string;
|
||
}
|
||
|
||
export interface CitationDisplaySettings {
|
||
retrieved_files_enabled: boolean;
|
||
reference_mode_enabled: boolean;
|
||
cleanup_words: string[];
|
||
}
|
||
|
||
export interface CitationDisplayUpdate {
|
||
retrieved_files_enabled?: boolean;
|
||
reference_mode_enabled?: boolean;
|
||
cleanup_words?: string[];
|
||
}
|
||
|
||
export type HtmlMapEngine = "echarts" | "leaflet";
|
||
|
||
export interface HtmlMapSettings {
|
||
engine: HtmlMapEngine;
|
||
}
|
||
|
||
export interface HtmlRuntimeSettings {
|
||
base_url: string;
|
||
map_tile_url: string;
|
||
}
|
||
|
||
export type AppIdentityHeaderTitleFontMode = "adaptive" | "fixed";
|
||
|
||
export interface AppIdentitySettings {
|
||
system_name: string;
|
||
header_title_font_mode: AppIdentityHeaderTitleFontMode;
|
||
header_title_font_size: number;
|
||
logo_url: string | null;
|
||
logo_version: string | null;
|
||
has_logo: boolean;
|
||
light_red_header_background_url: string | null;
|
||
light_red_header_background_version: string | null;
|
||
has_light_red_header_background: boolean;
|
||
light_red_nav_active_url: string | null;
|
||
light_red_nav_active_version: string | null;
|
||
has_light_red_nav_active: boolean;
|
||
}
|
||
|
||
export interface AppIdentityUpdate {
|
||
systemName: string;
|
||
headerTitleFontMode: AppIdentityHeaderTitleFontMode;
|
||
headerTitleFontSize: number;
|
||
logo?: File | null;
|
||
removeLogo?: boolean;
|
||
lightRedHeaderBackground?: File | null;
|
||
removeLightRedHeaderBackground?: boolean;
|
||
lightRedNavActive?: File | null;
|
||
removeLightRedNavActive?: boolean;
|
||
}
|
||
|
||
export interface LeaderboardSettings {
|
||
exclude_user_ids: string[];
|
||
include_scheduled: boolean;
|
||
include_admins: boolean;
|
||
include_failed: boolean;
|
||
cleanup_system_questions: boolean;
|
||
}
|
||
|
||
export interface LeaderboardSettingsUpdate {
|
||
exclude_user_ids?: string[];
|
||
include_scheduled?: boolean;
|
||
include_admins?: boolean;
|
||
include_failed?: boolean;
|
||
cleanup_system_questions?: boolean;
|
||
}
|
||
|
||
export async function loadPrivateSquareStatus(): Promise<PrivateSquareStatus> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/private-square`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load private square settings: ${response.status}`,
|
||
);
|
||
}
|
||
const data = (await response.json()) as PrivateSquareStatus;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-私密广场查看",
|
||
url: "/api/system-settings/private-square",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export interface PublishSquare {
|
||
id: string;
|
||
name: string;
|
||
description: string;
|
||
}
|
||
|
||
export interface PublishSquaresSettings {
|
||
squares: PublishSquare[];
|
||
default_square_id: string;
|
||
}
|
||
|
||
export interface PublishSquaresUpdate {
|
||
squares?: PublishSquare[];
|
||
default_square_id?: string;
|
||
}
|
||
|
||
/** Agent Gallery category selected for the wx route's common-agent panel. */
|
||
export interface WxCommonAgentsSettings {
|
||
/** `null` keeps the original common-agent recommendation logic. */
|
||
agent_type: string | null;
|
||
}
|
||
|
||
export async function loadWxCommonAgents(): Promise<WxCommonAgentsSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/wx-common-agents`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load wx common agents: ${response.status}`);
|
||
}
|
||
return (await response.json()) as WxCommonAgentsSettings;
|
||
}
|
||
|
||
export async function updateWxCommonAgents(
|
||
agentType: string | null,
|
||
): Promise<WxCommonAgentsSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/wx-common-agents`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({ agent_type: agentType }),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update wx common agents" }));
|
||
throw new Error(detail.detail ?? "Failed to update wx common agents");
|
||
}
|
||
return (await response.json()) as WxCommonAgentsSettings;
|
||
}
|
||
|
||
export async function loadPublishSquares(): Promise<PublishSquaresSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/publish-squares`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load publish squares: ${response.status}`);
|
||
}
|
||
const data = (await response.json()) as PublishSquaresSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-发布广场查看",
|
||
url: "/api/system-settings/publish-squares",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updatePublishSquares(
|
||
body: PublishSquaresUpdate,
|
||
): Promise<PublishSquaresSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/publish-squares`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update publish squares" }));
|
||
throw new Error(detail.detail ?? "Failed to update publish squares");
|
||
}
|
||
const data = (await response.json()) as PublishSquaresSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-发布广场编辑",
|
||
url: "/api/system-settings/publish-squares",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export const BUILTIN_THEME_IDS = [
|
||
"light",
|
||
"dark",
|
||
"lightblue",
|
||
"lightgreen",
|
||
"iceblue",
|
||
"lightyellow",
|
||
] as const;
|
||
|
||
export type BuiltinThemeId = (typeof BUILTIN_THEME_IDS)[number];
|
||
export type ThemeMode = BuiltinThemeId | `custom-theme-${string}`;
|
||
export type CustomThemeBaseMode = "light" | "dark";
|
||
|
||
export interface CustomThemeColorOverrides {
|
||
button_hover?: string | null;
|
||
navigation_gradient_start?: string | null;
|
||
navigation_gradient_end?: string | null;
|
||
selected_background?: string | null;
|
||
border?: string | null;
|
||
muted?: string | null;
|
||
muted_text?: string | null;
|
||
destructive?: string | null;
|
||
brand_title?: string | null;
|
||
primary_foreground?: string | null;
|
||
}
|
||
|
||
export interface CustomThemePreset {
|
||
id: `custom-theme-${string}`;
|
||
name: string;
|
||
primary: string;
|
||
text_color?: string | null;
|
||
mode: CustomThemeBaseMode;
|
||
overrides?: CustomThemeColorOverrides;
|
||
enabled: boolean;
|
||
sort_order: number;
|
||
}
|
||
export type ViewMode = "card" | "list";
|
||
export type LayoutMode = "full" | "compact";
|
||
export type CompactShortcutParamType = "login" | "theme" | "path";
|
||
|
||
export interface CompactShortcutRouteParam {
|
||
key: string;
|
||
paramType: CompactShortcutParamType;
|
||
source?: string | null;
|
||
customValue?: string | null;
|
||
themeValue?: string | null;
|
||
}
|
||
|
||
export interface CompactShortcutButton {
|
||
id: string;
|
||
label: string;
|
||
url: string;
|
||
route_params: CompactShortcutRouteParam[];
|
||
enabled: boolean;
|
||
sort_order: number;
|
||
}
|
||
|
||
export interface AppearanceSettings {
|
||
default_theme: ThemeMode;
|
||
default_skill_view: ViewMode;
|
||
default_agent_view: ViewMode;
|
||
default_layout_mode: LayoutMode;
|
||
default_composer_width_full?: number;
|
||
default_composer_width_compact?: number;
|
||
default_composer_height_full?: number;
|
||
default_composer_height_compact?: number;
|
||
default_agent_composer_width?: number;
|
||
default_agent_composer_height?: number;
|
||
compact_shortcut_buttons: CompactShortcutButton[];
|
||
custom_themes: CustomThemePreset[];
|
||
}
|
||
|
||
export interface AppearanceUpdate {
|
||
default_theme?: ThemeMode;
|
||
default_skill_view?: ViewMode;
|
||
default_agent_view?: ViewMode;
|
||
default_layout_mode?: LayoutMode;
|
||
default_composer_width_full?: number;
|
||
default_composer_width_compact?: number;
|
||
default_composer_height_full?: number;
|
||
default_composer_height_compact?: number;
|
||
default_agent_composer_width?: number;
|
||
default_agent_composer_height?: number;
|
||
compact_shortcut_buttons?: CompactShortcutButton[];
|
||
custom_themes?: CustomThemePreset[];
|
||
}
|
||
|
||
export async function loadAppearanceSettings(): Promise<AppearanceSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/appearance`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load appearance settings: ${response.status}`,
|
||
);
|
||
}
|
||
const data = (await response.json()) as AppearanceSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-外观查看",
|
||
url: "/api/system-settings/appearance",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateAppearanceSettings(
|
||
body: AppearanceUpdate,
|
||
): Promise<AppearanceSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/appearance`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update appearance" }));
|
||
throw new Error(detail.detail ?? "Failed to update appearance");
|
||
}
|
||
const data = (await response.json()) as AppearanceSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-外观编辑",
|
||
url: "/api/system-settings/appearance",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadCitationDisplaySettings(): Promise<CitationDisplaySettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/citation-display`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load citation display settings: ${response.status}`,
|
||
);
|
||
}
|
||
const data = (await response.json()) as CitationDisplaySettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-引用展示查看",
|
||
url: "/api/system-settings/citation-display",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadLeaderboardSettings(): Promise<LeaderboardSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/leaderboard`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load leaderboard settings: ${response.status}`);
|
||
}
|
||
const data = (await response.json()) as LeaderboardSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-排行榜查看",
|
||
url: "/api/system-settings/leaderboard",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateLeaderboardSettings(
|
||
body: LeaderboardSettingsUpdate,
|
||
): Promise<LeaderboardSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/leaderboard`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update leaderboard settings" }));
|
||
throw new Error(detail.detail ?? "Failed to update leaderboard settings");
|
||
}
|
||
const data = (await response.json()) as LeaderboardSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-排行榜编辑",
|
||
url: "/api/system-settings/leaderboard",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadHtmlMapSettings(): Promise<HtmlMapSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/html-map`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load HTML map settings: ${response.status}`);
|
||
}
|
||
const data = (await response.json()) as HtmlMapSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-HTML地图查看",
|
||
url: "/api/system-settings/html-map",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateHtmlMapSettings(
|
||
body: HtmlMapSettings,
|
||
): Promise<HtmlMapSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/html-map`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update HTML map settings" }));
|
||
throw new Error(detail.detail ?? "Failed to update HTML map settings");
|
||
}
|
||
const data = (await response.json()) as HtmlMapSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-HTML地图编辑",
|
||
url: "/api/system-settings/html-map",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadAppIdentitySettings(): Promise<AppIdentitySettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/app-identity`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load app identity: ${response.status}`);
|
||
}
|
||
const data = (await response.json()) as AppIdentitySettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-系统名称查看",
|
||
url: "/api/system-settings/app-identity",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateAppIdentitySettings(
|
||
update: AppIdentityUpdate,
|
||
): Promise<AppIdentitySettings> {
|
||
const body = new FormData();
|
||
body.set("system_name", update.systemName);
|
||
body.set("header_title_font_mode", update.headerTitleFontMode);
|
||
body.set("header_title_font_size", String(update.headerTitleFontSize));
|
||
if (update.logo) body.set("logo", update.logo);
|
||
if (update.removeLogo) body.set("remove_logo", "true");
|
||
if (update.lightRedHeaderBackground) {
|
||
body.set("light_red_header_background", update.lightRedHeaderBackground);
|
||
}
|
||
if (update.removeLightRedHeaderBackground) {
|
||
body.set("remove_light_red_header_background", "true");
|
||
}
|
||
if (update.lightRedNavActive) {
|
||
body.set("light_red_nav_active", update.lightRedNavActive);
|
||
}
|
||
if (update.removeLightRedNavActive) {
|
||
body.set("remove_light_red_nav_active", "true");
|
||
}
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/app-identity`,
|
||
{ method: "PUT", body },
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update app identity" }));
|
||
throw new Error(detail.detail ?? "Failed to update app identity");
|
||
}
|
||
const data = (await response.json()) as AppIdentitySettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-系统名称编辑",
|
||
url: "/api/system-settings/app-identity",
|
||
reqParam: {
|
||
system_name: update.systemName,
|
||
header_title_font_mode: update.headerTitleFontMode,
|
||
header_title_font_size: update.headerTitleFontSize,
|
||
logo_name: update.logo?.name,
|
||
remove_logo: Boolean(update.removeLogo),
|
||
light_red_header_background_name:
|
||
update.lightRedHeaderBackground?.name,
|
||
remove_light_red_header_background: Boolean(
|
||
update.removeLightRedHeaderBackground,
|
||
),
|
||
light_red_nav_active_name: update.lightRedNavActive?.name,
|
||
remove_light_red_nav_active: Boolean(update.removeLightRedNavActive),
|
||
},
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function deleteAppIdentitySettings(): Promise<AppIdentitySettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/app-identity`,
|
||
{ method: "DELETE" },
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to reset app identity" }));
|
||
throw new Error(detail.detail ?? "Failed to reset app identity");
|
||
}
|
||
const data = (await response.json()) as AppIdentitySettings;
|
||
writeYLog({
|
||
optType: OptType.delete,
|
||
optDetail: "CM助手-全量-系统设置-系统名称清除配置",
|
||
url: "/api/system-settings/app-identity",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export function resolveAppIdentityLogoUrl(
|
||
logoUrl: string | null | undefined,
|
||
): string | undefined {
|
||
return resolveAppIdentityAssetUrl(logoUrl);
|
||
}
|
||
|
||
export function resolveAppIdentityAssetUrl(
|
||
assetUrl: string | null | undefined,
|
||
): string | undefined {
|
||
if (!assetUrl) return undefined;
|
||
if (/^https?:\/\//i.test(assetUrl)) return assetUrl;
|
||
const base = getBackendBaseURL();
|
||
return `${base}${assetUrl.startsWith("/") ? "" : "/"}${assetUrl}`;
|
||
}
|
||
|
||
export async function loadHtmlRuntimeSettings(): Promise<HtmlRuntimeSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/html-runtime`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load HTML runtime settings: ${response.status}`);
|
||
}
|
||
const data = (await response.json()) as HtmlRuntimeSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-HTML运行地址查看",
|
||
url: "/api/system-settings/html-runtime",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateHtmlRuntimeSettings(
|
||
body: HtmlRuntimeSettings,
|
||
): Promise<HtmlRuntimeSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/html-runtime`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update HTML runtime settings" }));
|
||
const message =
|
||
typeof detail.detail === "string"
|
||
? detail.detail
|
||
: "Failed to update HTML runtime settings";
|
||
throw new Error(message);
|
||
}
|
||
const data = (await response.json()) as HtmlRuntimeSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-HTML运行地址编辑",
|
||
url: "/api/system-settings/html-runtime",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateCitationDisplaySettings(
|
||
body: CitationDisplayUpdate,
|
||
): Promise<CitationDisplaySettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/citation-display`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update citation display" }));
|
||
throw new Error(detail.detail ?? "Failed to update citation display");
|
||
}
|
||
const data = (await response.json()) as CitationDisplaySettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-引用展示编辑",
|
||
url: "/api/system-settings/citation-display",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export interface SkillCompressionSettings {
|
||
enabled: boolean;
|
||
search_top_n: number;
|
||
keep_index_in_prompt: boolean;
|
||
}
|
||
|
||
export interface SkillCompressionUpdate {
|
||
enabled?: boolean;
|
||
search_top_n?: number;
|
||
keep_index_in_prompt?: boolean;
|
||
}
|
||
|
||
export interface SkillVersioningSettings {
|
||
enabled: boolean;
|
||
}
|
||
|
||
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 interface MemoryRuntimeSettings {
|
||
enabled: boolean;
|
||
}
|
||
|
||
export interface ConversationContextSettings {
|
||
max_run_steps: number;
|
||
recent_turn_window_enabled: boolean;
|
||
recent_turns: number;
|
||
max_conversation_rounds: number;
|
||
use_question_as_title: boolean;
|
||
}
|
||
|
||
export interface ConversationContextUpdate {
|
||
max_run_steps?: number;
|
||
recent_turn_window_enabled?: boolean;
|
||
max_conversation_rounds?: number;
|
||
use_question_as_title?: boolean;
|
||
}
|
||
|
||
export interface RoundtableRoomLimitSettings {
|
||
enabled: boolean;
|
||
max_rooms: number;
|
||
max_hold_minutes: number;
|
||
lease_minutes: number;
|
||
max_cycles: number;
|
||
write_file_compatibility_enabled: boolean;
|
||
}
|
||
|
||
export interface RoundtableRoomLimitUpdate {
|
||
enabled?: boolean;
|
||
max_rooms?: number;
|
||
max_hold_minutes?: number;
|
||
lease_minutes?: number;
|
||
max_cycles?: number;
|
||
write_file_compatibility_enabled?: boolean;
|
||
}
|
||
|
||
export interface OrdinaryKnowledgeRetrievalSettings {
|
||
smart_reasoning_enabled: boolean;
|
||
advanced_management_enabled: boolean;
|
||
}
|
||
|
||
export interface OrdinaryKnowledgeRetrievalUpdate {
|
||
smart_reasoning_enabled?: boolean;
|
||
advanced_management_enabled?: boolean;
|
||
}
|
||
|
||
export async function loadMemoryRuntimeSettings(): Promise<MemoryRuntimeSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/memory`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load memory runtime setting: ${response.status}`);
|
||
}
|
||
return (await response.json()) as MemoryRuntimeSettings;
|
||
}
|
||
|
||
export async function updateMemoryRuntimeSettings(
|
||
body: MemoryRuntimeSettings,
|
||
): Promise<MemoryRuntimeSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/memory`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update memory runtime setting" }));
|
||
throw new Error(detail.detail ?? "Failed to update memory runtime setting");
|
||
}
|
||
const data = (await response.json()) as MemoryRuntimeSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-问答记忆开关",
|
||
url: "/api/system-settings/memory",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export interface WriteFileCompatibilitySettings {
|
||
enabled: boolean;
|
||
}
|
||
|
||
export async function loadWriteFileCompatibilitySettings(): Promise<WriteFileCompatibilitySettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/write-file-compatibility`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load write_file compatibility setting: ${response.status}`,
|
||
);
|
||
}
|
||
return (await response.json()) as WriteFileCompatibilitySettings;
|
||
}
|
||
|
||
export async function updateWriteFileCompatibilitySettings(
|
||
body: WriteFileCompatibilitySettings,
|
||
): Promise<WriteFileCompatibilitySettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/write-file-compatibility`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response.json().catch(() => ({
|
||
detail: "Failed to update write_file compatibility setting",
|
||
}));
|
||
throw new Error(
|
||
detail.detail ?? "Failed to update write_file compatibility setting",
|
||
);
|
||
}
|
||
const data = (await response.json()) as WriteFileCompatibilitySettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-文件流式兼容开关",
|
||
url: "/api/system-settings/write-file-compatibility",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export interface CallMetricsSettings {
|
||
enabled: boolean;
|
||
}
|
||
|
||
export async function loadCallMetricsSettings(): Promise<CallMetricsSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/call-metrics`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`无法读取调用统计开关(HTTP ${response.status})`);
|
||
}
|
||
const data = (await response.json()) as CallMetricsSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-调用统计查看",
|
||
url: "/api/system-settings/call-metrics",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateCallMetricsSettings(
|
||
body: CallMetricsSettings,
|
||
): Promise<CallMetricsSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/call-metrics`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response.json().catch(() => ({
|
||
detail: "保存调用统计开关失败",
|
||
}));
|
||
throw new Error(detail.detail ?? "保存调用统计开关失败");
|
||
}
|
||
const data = (await response.json()) as CallMetricsSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-调用统计开关",
|
||
url: "/api/system-settings/call-metrics",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadConversationContextSettings(): Promise<ConversationContextSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/conversation-context`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load conversation context setting: ${response.status}`,
|
||
);
|
||
}
|
||
return (await response.json()) as ConversationContextSettings;
|
||
}
|
||
|
||
export async function updateConversationContextSettings(
|
||
body: ConversationContextUpdate,
|
||
): Promise<ConversationContextSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/conversation-context`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update conversation context setting" }));
|
||
throw new Error(
|
||
detail.detail ?? "Failed to update conversation context setting",
|
||
);
|
||
}
|
||
const data = (await response.json()) as ConversationContextSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-上下文管理",
|
||
url: "/api/system-settings/conversation-context",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadRoundtableRoomLimitSettings(): Promise<RoundtableRoomLimitSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/roundtable-room-limit`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`无法读取会商运行设置(HTTP ${response.status})`);
|
||
}
|
||
return (await response.json()) as RoundtableRoomLimitSettings;
|
||
}
|
||
|
||
export async function updateRoundtableRoomLimitSettings(
|
||
body: RoundtableRoomLimitUpdate,
|
||
): Promise<RoundtableRoomLimitSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/roundtable-room-limit`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "保存会商运行设置失败" }));
|
||
const message =
|
||
typeof detail.detail === "string" ? detail.detail : "保存会商运行设置失败";
|
||
throw new Error(message);
|
||
}
|
||
const data = (await response.json()) as RoundtableRoomLimitSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-会商运行限制",
|
||
url: "/api/system-settings/roundtable-room-limit",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadOrdinaryKnowledgeRetrievalSettings(): Promise<OrdinaryKnowledgeRetrievalSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/ordinary-knowledge-retrieval`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load ordinary knowledge retrieval setting: ${response.status}`,
|
||
);
|
||
}
|
||
return (await response.json()) as OrdinaryKnowledgeRetrievalSettings;
|
||
}
|
||
|
||
export async function updateOrdinaryKnowledgeRetrievalSettings(
|
||
body: OrdinaryKnowledgeRetrievalUpdate,
|
||
): Promise<OrdinaryKnowledgeRetrievalSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/ordinary-knowledge-retrieval`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update knowledge retrieval setting" }));
|
||
throw new Error(
|
||
detail.detail ?? "Failed to update knowledge retrieval setting",
|
||
);
|
||
}
|
||
const data = (await response.json()) as OrdinaryKnowledgeRetrievalSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-普通知识库检索与管理设置",
|
||
url: "/api/system-settings/ordinary-knowledge-retrieval",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadSkillCompressionSettings(): Promise<SkillCompressionSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/skill-compression`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load skill compression settings: ${response.status}`,
|
||
);
|
||
}
|
||
const data = (await response.json()) as SkillCompressionSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-技能压缩查看",
|
||
url: "/api/system-settings/skill-compression",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadSkillVersioningSettings(): Promise<SkillVersioningSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/skill-versioning`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load skill versioning settings: ${response.status}`,
|
||
);
|
||
}
|
||
const data = (await response.json()) as SkillVersioningSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-技能迭代查看",
|
||
url: "/api/system-settings/skill-versioning",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function loadModelConcurrencySettings(): Promise<ModelConcurrencySettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/model-concurrency`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load model concurrency settings: ${response.status}`,
|
||
);
|
||
}
|
||
const data = (await response.json()) as ModelConcurrencySettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-模型并发限制查看",
|
||
url: "/api/system-settings/model-concurrency",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateModelConcurrencySettings(
|
||
body: ModelConcurrencyUpdate,
|
||
): Promise<ModelConcurrencySettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/model-concurrency`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update model concurrency settings" }));
|
||
throw new Error(detail.detail ?? "Failed to update model concurrency settings");
|
||
}
|
||
const data = (await response.json()) as ModelConcurrencySettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-模型并发限制编辑",
|
||
url: "/api/system-settings/model-concurrency",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateSkillCompressionSettings(
|
||
body: SkillCompressionUpdate,
|
||
): Promise<SkillCompressionSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/skill-compression`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update skill compression" }));
|
||
throw new Error(detail.detail ?? "Failed to update skill compression");
|
||
}
|
||
const data = (await response.json()) as SkillCompressionSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-技能压缩编辑",
|
||
url: "/api/system-settings/skill-compression",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateSkillVersioningSettings(
|
||
body: SkillVersioningSettings,
|
||
): Promise<SkillVersioningSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/skill-versioning`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update skill versioning" }));
|
||
throw new Error(detail.detail ?? "Failed to update skill versioning");
|
||
}
|
||
const data = (await response.json()) as SkillVersioningSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-技能迭代编辑",
|
||
url: "/api/system-settings/skill-versioning",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
/** 「按类型聚合」模块(zzJC / zzXD)选中的智能体标签配置(需求 0616 #3/#4)。 */
|
||
export interface AgentModuleConfig {
|
||
key: string;
|
||
tag_ids: string[];
|
||
}
|
||
|
||
export async function loadAgentModuleConfig(
|
||
key: string,
|
||
): Promise<AgentModuleConfig> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/agent-modules/${encodeURIComponent(key)}`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load agent module config: ${response.status}`);
|
||
}
|
||
const data = (await response.json()) as AgentModuleConfig;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-智能体模块查看",
|
||
url: `/api/system-settings/agent-modules/${key}`,
|
||
reqParam: { key },
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updateAgentModuleConfig(
|
||
key: string,
|
||
tagIds: string[],
|
||
): Promise<AgentModuleConfig> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/agent-modules/${encodeURIComponent(key)}`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify({ tag_ids: tagIds }),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update agent module config" }));
|
||
throw new Error(detail.detail ?? "Failed to update agent module config");
|
||
}
|
||
const data = (await response.json()) as AgentModuleConfig;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-智能体模块编辑",
|
||
url: `/api/system-settings/agent-modules/${key}`,
|
||
reqParam: { key, tag_ids: tagIds },
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export interface LogSystemSettings {
|
||
enabled: boolean;
|
||
url: string;
|
||
label: string;
|
||
}
|
||
|
||
export async function loadLogSystemSettings(): Promise<LogSystemSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/log-system`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(`Failed to load log system settings: ${response.status}`);
|
||
}
|
||
const data = (await response.json()) as LogSystemSettings;
|
||
writeYLog({
|
||
optType: OptType.view,
|
||
optDetail: "CM助手-全量-系统设置-日志系统查看",
|
||
url: "/api/system-settings/log-system",
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export async function updatePrivateSquareSettings(
|
||
body: PrivateSquareUpdate,
|
||
): Promise<PrivateSquareStatus> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/private-square`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response
|
||
.json()
|
||
.catch(() => ({ detail: "Failed to update private square" }));
|
||
throw new Error(detail.detail ?? "Failed to update private square");
|
||
}
|
||
const data = (await response.json()) as PrivateSquareStatus;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-私密广场编辑",
|
||
url: "/api/system-settings/private-square",
|
||
// omit `password` (secret) from the logged request params
|
||
reqParam: { enabled: body.enabled, password_set: body.password != null },
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|
||
|
||
export interface RetryKeepPartialSettings {
|
||
enabled: boolean;
|
||
}
|
||
|
||
export async function loadRetryKeepPartialSettings(): Promise<RetryKeepPartialSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/retry-keep-partial`,
|
||
);
|
||
if (!response.ok) {
|
||
throw new Error(
|
||
`Failed to load retry-keep-partial setting: ${response.status}`,
|
||
);
|
||
}
|
||
return (await response.json()) as RetryKeepPartialSettings;
|
||
}
|
||
|
||
export async function updateRetryKeepPartialSettings(
|
||
body: RetryKeepPartialSettings,
|
||
): Promise<RetryKeepPartialSettings> {
|
||
const response = await apiFetch(
|
||
`${getBackendBaseURL()}/api/system-settings/retry-keep-partial`,
|
||
{
|
||
method: "PUT",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
},
|
||
);
|
||
if (!response.ok) {
|
||
const detail = await response.json().catch(() => ({
|
||
detail: "Failed to update retry-keep-partial setting",
|
||
}));
|
||
throw new Error(
|
||
detail.detail ?? "Failed to update retry-keep-partial setting",
|
||
);
|
||
}
|
||
const data = (await response.json()) as RetryKeepPartialSettings;
|
||
writeYLog({
|
||
optType: OptType.edit,
|
||
optDetail: "CM助手-全量-系统设置-重试保留正文开关",
|
||
url: "/api/system-settings/retry-keep-partial",
|
||
reqParam: body,
|
||
returnParam: data,
|
||
});
|
||
return data;
|
||
}
|