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 ? (