From 63a01e6a5ab8274901981564e8993869ba0705bb Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 23 Mar 2026 20:00:05 +0800 Subject: [PATCH] split canvas agent mode toggle from agent workspace --- .../settings/admin-settings-client.tsx | 21 +++++- app/api/site-settings/route.ts | 67 +++++++++++++++++++ app/canvas/[id]/page.tsx | 18 ++--- 3 files changed, 97 insertions(+), 9 deletions(-) diff --git a/app/(admin)/settings/admin-settings-client.tsx b/app/(admin)/settings/admin-settings-client.tsx index 23244dc83..302797b96 100644 --- a/app/(admin)/settings/admin-settings-client.tsx +++ b/app/(admin)/settings/admin-settings-client.tsx @@ -248,6 +248,7 @@ type SiteSettings = { rankingEnabled: boolean; canvasEnabled: boolean; agentEnabled: boolean; + canvasAgentModeEnabled: boolean; agentCategoryTreeConfig: { productCategories: string[]; audienceTags: string[]; @@ -676,6 +677,7 @@ export function AdminSettingsClient() { rankingEnabled: true, canvasEnabled: true, agentEnabled: true, + canvasAgentModeEnabled: true, agentCategoryTreeConfig: { productCategories: [], audienceTags: [], @@ -761,6 +763,7 @@ export function AdminSettingsClient() { rankingEnabled: siteSettingsData.rankingEnabled ?? true, canvasEnabled: siteSettingsData.canvasEnabled ?? true, agentEnabled: (siteSettingsData as any).agentEnabled ?? true, + canvasAgentModeEnabled: (siteSettingsData as any).canvasAgentModeEnabled ?? true, agentCategoryTreeConfig: { productCategories: Array.isArray((siteSettingsData as any).agentCategoryTreeConfig?.productCategories) ? (siteSettingsData as any).agentCategoryTreeConfig.productCategories @@ -5594,7 +5597,7 @@ export function AdminSettingsClient() {
- 开启后,首页侧边栏显示“智能体”入口,用户可进入画布智能体模式;关闭后隐藏入口。 + 开启后,首页侧边栏显示“智能体”入口,用户可进入独立的智能体工作台;关闭后隐藏该入口。
+
+
+ +
+ 控制无限画布右侧对话框中的 Agent模式 入口,与上面的智能体工作台入口独立。 +
+
+ + setSiteSettings({ ...siteSettings, canvasAgentModeEnabled: checked }) + } + /> +
+ {siteSettings.agentEnabled && (
diff --git a/app/api/site-settings/route.ts b/app/api/site-settings/route.ts index bef743d35..b88e97b9f 100644 --- a/app/api/site-settings/route.ts +++ b/app/api/site-settings/route.ts @@ -82,6 +82,7 @@ const MEMBERSHIP_USER_OVERRIDES_KEY = "membership_user_plan_overrides"; const STORAGE_FAILOVER_CONFIG_KEY = "storage_failover_config"; const REALTIME_CANVAS_CONFIG_KEY = "realtime_canvas_config"; const AGENT_CATEGORY_TREE_CONFIG_KEY = "agent_category_tree_config"; +const CANVAS_AGENT_MODE_ENABLED_KEY = "canvas_agent_mode_enabled"; function normalizeHomeVariant(value: unknown): "classic" | "lovart" { return value === "lovart" ? "lovart" : "classic"; @@ -196,6 +197,10 @@ function normalizeStorageFailoverConfig(value: unknown): { }; } +function normalizeCanvasAgentModeEnabled(value: unknown): boolean { + return value !== false; +} + function normalizeAgentCategoryTreeConfig(value: unknown): AgentCategoryTreeConfig { const raw = value && typeof value === "object" && !Array.isArray(value) @@ -244,6 +249,7 @@ export async function GET() { pointsPackagesSetting, dulupayConfigSetting, realtimeCanvasConfigSetting, + canvasAgentModeEnabledSetting, storageFailoverConfigSetting, ossImageMigrationConfigSetting, agentPresetLibraryConfigSetting, @@ -340,6 +346,12 @@ export async function GET() { .where(eq(systemSettings.key, REALTIME_CANVAS_CONFIG_KEY)) .limit(1) .then(rows => rows[0]), + db + .select() + .from(systemSettings) + .where(eq(systemSettings.key, CANVAS_AGENT_MODE_ENABLED_KEY)) + .limit(1) + .then(rows => rows[0]), db .select() .from(systemSettings) @@ -429,6 +441,9 @@ export async function GET() { : normalizeDulupayForPublic(dulupayConfigSetting?.value); const realtimeCanvasServiceEnabled = (realtimeCanvasConfigSetting?.value as { enabled?: boolean } | undefined)?.enabled !== false; + const canvasAgentModeEnabled = normalizeCanvasAgentModeEnabled( + canvasAgentModeEnabledSetting?.value + ); const storageFailoverConfig = normalizeStorageFailoverConfig( storageFailoverConfigSetting?.value ); @@ -488,6 +503,7 @@ export async function GET() { rankingEnabled: true, canvasEnabled: true, agentEnabled: true, + canvasAgentModeEnabled: true, agentPresetLibraryConfig: defaultAgentPresetLibraryConfig, agentCategoryTreeConfig: normalizeAgentCategoryTreeConfig(undefined), agentSecondaryTypeConfig: defaultAgentSecondaryTypeConfig, @@ -552,6 +568,7 @@ export async function GET() { pointsPackages, dulupayConfig, realtimeCanvasServiceEnabled, + canvasAgentModeEnabled, storageFailoverConfig, ossImageMigrationConfig, }); @@ -594,6 +611,7 @@ const updateSchema = z.object({ rankingEnabled: z.boolean().optional(), canvasEnabled: z.boolean().optional(), agentEnabled: z.boolean().optional(), + canvasAgentModeEnabled: z.boolean().optional(), agentPresetLibraryConfig: z .object({ sections: z @@ -869,6 +887,7 @@ export async function PUT(request: NextRequest) { dulupayConfig, storageFailoverConfig, ossImageMigrationConfig, + canvasAgentModeEnabled, ...siteSettingsPayload } = data; @@ -1026,6 +1045,26 @@ export async function PUT(request: NextRequest) { }); } + if (canvasAgentModeEnabled !== undefined) { + const normalized = normalizeCanvasAgentModeEnabled(canvasAgentModeEnabled); + await db + .insert(systemSettings) + .values({ + key: CANVAS_AGENT_MODE_ENABLED_KEY, + value: normalized, + updatedAt: new Date(), + updatedBy: session.user.id, + }) + .onConflictDoUpdate({ + target: systemSettings.key, + set: { + value: normalized, + updatedAt: new Date(), + updatedBy: session.user.id, + }, + }); + } + if (agentPresetLibraryConfig !== undefined) { const normalized = normalizeAgentPresetLibraryConfig(agentPresetLibraryConfig); await db @@ -1416,6 +1455,10 @@ export async function PUT(request: NextRequest) { ossImageMigrationConfig !== undefined ? normalizeOssImageMigrationConfig(ossImageMigrationConfig) : defaultOssImageMigrationConfig, + canvasAgentModeEnabled: + canvasAgentModeEnabled !== undefined + ? normalizeCanvasAgentModeEnabled(canvasAgentModeEnabled) + : normalizeCanvasAgentModeEnabled(undefined), }); } else { // 创建新设置 @@ -1597,6 +1640,26 @@ export async function PUT(request: NextRequest) { }); } + if (canvasAgentModeEnabled !== undefined) { + const normalized = normalizeCanvasAgentModeEnabled(canvasAgentModeEnabled); + await db + .insert(systemSettings) + .values({ + key: CANVAS_AGENT_MODE_ENABLED_KEY, + value: normalized, + updatedAt: new Date(), + updatedBy: session.user.id, + }) + .onConflictDoUpdate({ + target: systemSettings.key, + set: { + value: normalized, + updatedAt: new Date(), + updatedBy: session.user.id, + }, + }); + } + if (agentPresetLibraryConfig !== undefined) { const normalized = normalizeAgentPresetLibraryConfig(agentPresetLibraryConfig); await db @@ -1965,6 +2028,10 @@ export async function PUT(request: NextRequest) { ossImageMigrationConfig !== undefined ? normalizeOssImageMigrationConfig(ossImageMigrationConfig) : defaultOssImageMigrationConfig, + canvasAgentModeEnabled: + canvasAgentModeEnabled !== undefined + ? normalizeCanvasAgentModeEnabled(canvasAgentModeEnabled) + : normalizeCanvasAgentModeEnabled(undefined), }); } } catch (error) { diff --git a/app/canvas/[id]/page.tsx b/app/canvas/[id]/page.tsx index 426562878..0e8fbc826 100644 --- a/app/canvas/[id]/page.tsx +++ b/app/canvas/[id]/page.tsx @@ -273,6 +273,7 @@ export default function CanvasEditorPage({ params }: PageProps) { siteLogo?: string | null; siteLogoDark?: string | null; agentEnabled?: boolean; + canvasAgentModeEnabled?: boolean; realtimeCanvasEnabled?: boolean; realtimeCanvasServiceEnabled?: boolean; agentWorkflowShowcaseConfig?: AgentWorkflowShowcaseConfig; @@ -306,9 +307,10 @@ export default function CanvasEditorPage({ params }: PageProps) { const previousBrandForModelRef = useRef(""); const autoSelectedBrandModelBrandRef = useRef(""); const requestedAgentMode = mode === "agent"; - const isAgentFeatureEnabled = siteSettingsData?.agentEnabled !== false; + const isAgentWorkspaceEnabled = siteSettingsData?.agentEnabled !== false; + const isCanvasAgentModeEnabled = siteSettingsData?.canvasAgentModeEnabled !== false; const isAgentMode = - isAgentFeatureEnabled && requestedAgentMode; + isAgentWorkspaceEnabled && requestedAgentMode; const resolvedBrandModelConfig = useMemo( () => normalizeAgentWorkflowBrandModelConfig(siteSettingsData?.agentWorkflowBrandModelConfig), [siteSettingsData?.agentWorkflowBrandModelConfig] @@ -653,7 +655,7 @@ export default function CanvasEditorPage({ params }: PageProps) { ); useEffect(() => { - if (!requestedAgentMode || !isAgentFeatureEnabled || agentProjectId) return; + if (!requestedAgentMode || !isAgentWorkspaceEnabled || agentProjectId) return; let cancelled = false; const createAgentProject = async () => { @@ -686,7 +688,7 @@ export default function CanvasEditorPage({ params }: PageProps) { return () => { cancelled = true; }; - }, [agentProjectId, isAgentFeatureEnabled, requestedAgentMode, updateCanvasSearchParams]); + }, [agentProjectId, isAgentWorkspaceEnabled, requestedAgentMode, updateCanvasSearchParams]); useEffect(() => { if (!requestedAgentMode || !agentProjectId) return; @@ -1480,7 +1482,7 @@ export default function CanvasEditorPage({ params }: PageProps) { ); const agentDisabledNotice = - requestedAgentMode && !isAgentFeatureEnabled ? ( + requestedAgentMode && !isAgentWorkspaceEnabled ? (
@@ -1552,7 +1554,7 @@ export default function CanvasEditorPage({ params }: PageProps) { setPanelMode('fileList')} selectedAgentPresetId={null} chatScope="canvas" - agentEnabled={isAgentFeatureEnabled} + agentEnabled={isCanvasAgentModeEnabled} />
) : ( @@ -1725,7 +1727,7 @@ export default function CanvasEditorPage({ params }: PageProps) { 平移 (H) - {isAgentFeatureEnabled ? ( + {isAgentWorkspaceEnabled ? (