feat: expose canvas agent rollout controls
This commit is contained in:
parent
fae9d32ffb
commit
43e01e7613
@ -204,6 +204,7 @@ import {
|
||||
getDefaultCanvasToolbarItem,
|
||||
normalizeCanvasToolbarConfig,
|
||||
} from "@/lib/canvas-toolbar-config";
|
||||
import type { CanvasAgentFeatureSettings } from "@/lib/canvas/agent-feature-flags";
|
||||
import { fetchUploadWithRetry } from "@/lib/client/upload-with-retry";
|
||||
import {
|
||||
AI_WASH_CONFIG_KEY,
|
||||
@ -1147,6 +1148,7 @@ type SiteSettings = {
|
||||
canvasEnabled: boolean;
|
||||
agentEnabled: boolean;
|
||||
canvasAgentModeEnabled: boolean;
|
||||
canvasAgentFeatureSettings: CanvasAgentFeatureSettings;
|
||||
videoCanvasEnabled: boolean;
|
||||
videoCanvasSidebarEnabled: boolean;
|
||||
agentCategoryTreeConfig: {
|
||||
@ -1225,6 +1227,43 @@ type HomeAnimationConfig = {
|
||||
updatedAt: string | null;
|
||||
};
|
||||
|
||||
const defaultCanvasAgentFeatureSettings: CanvasAgentFeatureSettings = {
|
||||
operationProtocolEnabled: true,
|
||||
writebackMode: "operation_authoritative",
|
||||
slotEnabled: true,
|
||||
viewOperationEnabled: true,
|
||||
annotationEditEnabled: true,
|
||||
};
|
||||
|
||||
function normalizeCanvasAgentFeatureSettingsForClient(
|
||||
value: unknown
|
||||
): CanvasAgentFeatureSettings {
|
||||
const raw =
|
||||
value && typeof value === "object" && !Array.isArray(value)
|
||||
? (value as Partial<CanvasAgentFeatureSettings>)
|
||||
: {};
|
||||
const writebackMode =
|
||||
raw.writebackMode === "legacy_canvas_media" ||
|
||||
raw.writebackMode === "operation_shadow" ||
|
||||
raw.writebackMode === "operation_authoritative"
|
||||
? raw.writebackMode
|
||||
: defaultCanvasAgentFeatureSettings.writebackMode;
|
||||
|
||||
return {
|
||||
operationProtocolEnabled:
|
||||
raw.operationProtocolEnabled ??
|
||||
defaultCanvasAgentFeatureSettings.operationProtocolEnabled,
|
||||
writebackMode,
|
||||
slotEnabled: raw.slotEnabled ?? defaultCanvasAgentFeatureSettings.slotEnabled,
|
||||
viewOperationEnabled:
|
||||
raw.viewOperationEnabled ??
|
||||
defaultCanvasAgentFeatureSettings.viewOperationEnabled,
|
||||
annotationEditEnabled:
|
||||
raw.annotationEditEnabled ??
|
||||
defaultCanvasAgentFeatureSettings.annotationEditEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
const defaultLovartPromptTagVisibility: LovartPromptTagVisibility = {
|
||||
nanoBananaPro: true,
|
||||
design: true,
|
||||
@ -2102,6 +2141,7 @@ export function AdminSettingsClient() {
|
||||
canvasEnabled: true,
|
||||
agentEnabled: true,
|
||||
canvasAgentModeEnabled: true,
|
||||
canvasAgentFeatureSettings: defaultCanvasAgentFeatureSettings,
|
||||
videoCanvasEnabled: true,
|
||||
videoCanvasSidebarEnabled: true,
|
||||
agentCategoryTreeConfig: {
|
||||
@ -2223,6 +2263,9 @@ export function AdminSettingsClient() {
|
||||
agentEnabled: (siteSettingsData as any).agentEnabled ?? true,
|
||||
canvasAgentModeEnabled:
|
||||
(siteSettingsData as any).canvasAgentModeEnabled ?? true,
|
||||
canvasAgentFeatureSettings: normalizeCanvasAgentFeatureSettingsForClient(
|
||||
(siteSettingsData as any).canvasAgentFeatureSettings
|
||||
),
|
||||
videoCanvasEnabled:
|
||||
(siteSettingsData as any).videoCanvasEnabled ??
|
||||
(siteSettingsData as any).videoCanvasSidebarEnabled ??
|
||||
@ -12172,6 +12215,165 @@ export function AdminSettingsClient() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4 rounded-lg border p-4">
|
||||
<div className="space-y-1">
|
||||
<Label>Canvas Agent 操作协议灰度</Label>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
控制对话框 Agent 是否通过受控协议写回画布,以及
|
||||
slot、视角和标注编辑能力的开放范围。
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
<div className="flex items-center justify-between gap-4 rounded-lg border p-3">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="canvasAgentOperationProtocolEnabled">
|
||||
操作协议
|
||||
</Label>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
关闭后不执行 CanvasOperationPlan,也不输出 shadow
|
||||
操作。
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={
|
||||
siteSettings.canvasAgentFeatureSettings
|
||||
.operationProtocolEnabled
|
||||
}
|
||||
id="canvasAgentOperationProtocolEnabled"
|
||||
onCheckedChange={(checked) =>
|
||||
setSiteSettings({
|
||||
...siteSettings,
|
||||
canvasAgentFeatureSettings: {
|
||||
...siteSettings.canvasAgentFeatureSettings,
|
||||
operationProtocolEnabled: checked,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2 rounded-lg border p-3">
|
||||
<Label htmlFor="canvasAgentWritebackMode">
|
||||
写回模式
|
||||
</Label>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
setSiteSettings({
|
||||
...siteSettings,
|
||||
canvasAgentFeatureSettings: {
|
||||
...siteSettings.canvasAgentFeatureSettings,
|
||||
writebackMode:
|
||||
value as CanvasAgentFeatureSettings["writebackMode"],
|
||||
},
|
||||
})
|
||||
}
|
||||
value={
|
||||
siteSettings.canvasAgentFeatureSettings.writebackMode
|
||||
}
|
||||
>
|
||||
<SelectTrigger id="canvasAgentWritebackMode">
|
||||
<SelectValue placeholder="选择写回模式" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="legacy_canvas_media">
|
||||
旧 canvasMedia
|
||||
</SelectItem>
|
||||
<SelectItem value="operation_shadow">
|
||||
Shadow 记录
|
||||
</SelectItem>
|
||||
<SelectItem value="operation_authoritative">
|
||||
Operation 权威写回
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
Shadow 只记录操作计划;权威写回会直接调用 mutation
|
||||
API 更新画布。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between gap-4 rounded-lg border p-3">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="canvasAgentSlotEnabled">
|
||||
Agent Slot
|
||||
</Label>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
允许 Agent 创建或填充画布生成槽位。
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={
|
||||
siteSettings.canvasAgentFeatureSettings.slotEnabled
|
||||
}
|
||||
id="canvasAgentSlotEnabled"
|
||||
onCheckedChange={(checked) =>
|
||||
setSiteSettings({
|
||||
...siteSettings,
|
||||
canvasAgentFeatureSettings: {
|
||||
...siteSettings.canvasAgentFeatureSettings,
|
||||
slotEnabled: checked,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between gap-4 rounded-lg border p-3">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="canvasAgentViewOperationEnabled">
|
||||
视角控制
|
||||
</Label>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
允许 Agent 临时缩放、平移并聚焦当前编辑对象。
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={
|
||||
siteSettings.canvasAgentFeatureSettings
|
||||
.viewOperationEnabled
|
||||
}
|
||||
id="canvasAgentViewOperationEnabled"
|
||||
onCheckedChange={(checked) =>
|
||||
setSiteSettings({
|
||||
...siteSettings,
|
||||
canvasAgentFeatureSettings: {
|
||||
...siteSettings.canvasAgentFeatureSettings,
|
||||
viewOperationEnabled: checked,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between gap-4 rounded-lg border p-3 md:col-span-2">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="canvasAgentAnnotationEditEnabled">
|
||||
标注编辑
|
||||
</Label>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
允许 Agent 读取画布批注、备注和框选区域并生成编辑任务。
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={
|
||||
siteSettings.canvasAgentFeatureSettings
|
||||
.annotationEditEnabled
|
||||
}
|
||||
id="canvasAgentAnnotationEditEnabled"
|
||||
onCheckedChange={(checked) =>
|
||||
setSiteSettings({
|
||||
...siteSettings,
|
||||
canvasAgentFeatureSettings: {
|
||||
...siteSettings.canvasAgentFeatureSettings,
|
||||
annotationEditEnabled: checked,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4 rounded-lg border p-4">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<div className="space-y-0.5">
|
||||
|
||||
@ -97,6 +97,19 @@ import {
|
||||
defaultCanvasToolbarConfig,
|
||||
normalizeCanvasToolbarConfig,
|
||||
} from "@/lib/canvas-toolbar-config";
|
||||
import {
|
||||
CANVAS_AGENT_ANNOTATION_EDIT_ENABLED_KEY,
|
||||
CANVAS_AGENT_FEATURE_SETTING_KEYS,
|
||||
CANVAS_AGENT_OPERATION_PROTOCOL_ENABLED_KEY,
|
||||
CANVAS_AGENT_SLOT_ENABLED_KEY,
|
||||
CANVAS_AGENT_VIEW_OPERATION_ENABLED_KEY,
|
||||
CANVAS_AGENT_WRITEBACK_MODE_KEY,
|
||||
canvasAgentFeatureFlagsToSettings,
|
||||
canvasAgentFeatureSettingsToSystemSettings,
|
||||
getCanvasAgentFeatureFlags,
|
||||
type CanvasAgentFeatureSettings,
|
||||
type CanvasAgentFeatureSettingsLike,
|
||||
} from "@/lib/canvas/agent-feature-flags";
|
||||
import {
|
||||
LOVART_HOME_SIDEBAR_CONFIG_KEY,
|
||||
defaultLovartHomeSidebarConfig,
|
||||
@ -453,6 +466,34 @@ function normalizeCanvasAgentModeEnabled(value: unknown): boolean {
|
||||
return value !== false;
|
||||
}
|
||||
|
||||
function normalizeCanvasAgentFeatureSettings(
|
||||
settings?: CanvasAgentFeatureSettingsLike | null
|
||||
): CanvasAgentFeatureSettings {
|
||||
return canvasAgentFeatureFlagsToSettings(
|
||||
getCanvasAgentFeatureFlags(process.env, settings)
|
||||
);
|
||||
}
|
||||
|
||||
function buildCanvasAgentFeatureSettings(
|
||||
valueByKey: Map<string, unknown>
|
||||
): CanvasAgentFeatureSettings {
|
||||
return normalizeCanvasAgentFeatureSettings({
|
||||
[CANVAS_AGENT_OPERATION_PROTOCOL_ENABLED_KEY]: valueByKey.get(
|
||||
CANVAS_AGENT_OPERATION_PROTOCOL_ENABLED_KEY
|
||||
),
|
||||
[CANVAS_AGENT_WRITEBACK_MODE_KEY]: valueByKey.get(
|
||||
CANVAS_AGENT_WRITEBACK_MODE_KEY
|
||||
),
|
||||
[CANVAS_AGENT_SLOT_ENABLED_KEY]: valueByKey.get(CANVAS_AGENT_SLOT_ENABLED_KEY),
|
||||
[CANVAS_AGENT_VIEW_OPERATION_ENABLED_KEY]: valueByKey.get(
|
||||
CANVAS_AGENT_VIEW_OPERATION_ENABLED_KEY
|
||||
),
|
||||
[CANVAS_AGENT_ANNOTATION_EDIT_ENABLED_KEY]: valueByKey.get(
|
||||
CANVAS_AGENT_ANNOTATION_EDIT_ENABLED_KEY
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeVideoCanvasEnabled(
|
||||
value: unknown,
|
||||
fallbackValue: unknown = true
|
||||
@ -700,6 +741,7 @@ async function getScopedPublicSiteSettings(
|
||||
LAYER_SPLIT_CONFIG_KEY,
|
||||
ANGLE_EDIT_CONFIG_KEY,
|
||||
CANVAS_AGENT_MODE_ENABLED_KEY,
|
||||
...CANVAS_AGENT_FEATURE_SETTING_KEYS,
|
||||
VIDEO_CANVAS_ENABLED_KEY,
|
||||
VIDEO_CANVAS_SIDEBAR_ENABLED_KEY,
|
||||
ENHANCE_PRO_KREA_SETTING_KEY,
|
||||
@ -721,6 +763,7 @@ async function getScopedPublicSiteSettings(
|
||||
canvasAgentModeEnabled: normalizeCanvasAgentModeEnabled(
|
||||
valueByKey.get(CANVAS_AGENT_MODE_ENABLED_KEY)
|
||||
),
|
||||
canvasAgentFeatureSettings: buildCanvasAgentFeatureSettings(valueByKey),
|
||||
videoCanvasEnabled: normalizeVideoCanvasEnabled(
|
||||
valueByKey.get(VIDEO_CANVAS_ENABLED_KEY),
|
||||
valueByKey.get(VIDEO_CANVAS_SIDEBAR_ENABLED_KEY)
|
||||
@ -787,6 +830,7 @@ async function getScopedPublicSiteSettings(
|
||||
LAYER_SPLIT_CONFIG_KEY,
|
||||
ANGLE_EDIT_CONFIG_KEY,
|
||||
CANVAS_AGENT_MODE_ENABLED_KEY,
|
||||
...CANVAS_AGENT_FEATURE_SETTING_KEYS,
|
||||
VIDEO_CANVAS_ENABLED_KEY,
|
||||
VIDEO_CANVAS_SIDEBAR_ENABLED_KEY,
|
||||
ENHANCE_PRO_KREA_SETTING_KEY,
|
||||
@ -805,6 +849,7 @@ async function getScopedPublicSiteSettings(
|
||||
canvasAgentModeEnabled: normalizeCanvasAgentModeEnabled(
|
||||
valueByKey.get(CANVAS_AGENT_MODE_ENABLED_KEY)
|
||||
),
|
||||
canvasAgentFeatureSettings: buildCanvasAgentFeatureSettings(valueByKey),
|
||||
videoCanvasEnabled: normalizeVideoCanvasEnabled(
|
||||
valueByKey.get(VIDEO_CANVAS_ENABLED_KEY),
|
||||
valueByKey.get(VIDEO_CANVAS_SIDEBAR_ENABLED_KEY)
|
||||
@ -1054,6 +1099,7 @@ export async function GET(request: NextRequest) {
|
||||
lovartHomeSidebarConfigSetting,
|
||||
layerSplitConfigSetting,
|
||||
canvasAgentModeEnabledSetting,
|
||||
canvasAgentFeatureSettingsRows,
|
||||
videoCanvasEnabledSetting,
|
||||
videoCanvasSidebarEnabledSetting,
|
||||
storageFailoverConfigSetting,
|
||||
@ -1180,6 +1226,10 @@ export async function GET(request: NextRequest) {
|
||||
.where(eq(systemSettings.key, CANVAS_AGENT_MODE_ENABLED_KEY))
|
||||
.limit(1)
|
||||
.then(rows => rows[0]),
|
||||
db
|
||||
.select({ key: systemSettings.key, value: systemSettings.value })
|
||||
.from(systemSettings)
|
||||
.where(inArray(systemSettings.key, [...CANVAS_AGENT_FEATURE_SETTING_KEYS])),
|
||||
db
|
||||
.select()
|
||||
.from(systemSettings)
|
||||
@ -1314,6 +1364,12 @@ export async function GET(request: NextRequest) {
|
||||
const canvasAgentModeEnabled = normalizeCanvasAgentModeEnabled(
|
||||
canvasAgentModeEnabledSetting?.value
|
||||
);
|
||||
const canvasAgentFeatureValueByKey = new Map<string, unknown>(
|
||||
canvasAgentFeatureSettingsRows.map((row) => [row.key, row.value])
|
||||
);
|
||||
const canvasAgentFeatureSettings = buildCanvasAgentFeatureSettings(
|
||||
canvasAgentFeatureValueByKey
|
||||
);
|
||||
const videoCanvasSidebarEnabled = normalizeVideoCanvasSidebarEnabled(
|
||||
videoCanvasSidebarEnabledSetting?.value
|
||||
);
|
||||
@ -1397,6 +1453,7 @@ export async function GET(request: NextRequest) {
|
||||
canvasEnabled: true,
|
||||
agentEnabled: true,
|
||||
canvasAgentModeEnabled: true,
|
||||
canvasAgentFeatureSettings,
|
||||
videoCanvasEnabled: true,
|
||||
videoCanvasSidebarEnabled: true,
|
||||
agentPresetLibraryConfig: defaultAgentPresetLibraryConfig,
|
||||
@ -1482,6 +1539,7 @@ export async function GET(request: NextRequest) {
|
||||
lovartHomeSidebarConfig,
|
||||
layerSplitEnabled,
|
||||
canvasAgentModeEnabled,
|
||||
canvasAgentFeatureSettings,
|
||||
videoCanvasEnabled,
|
||||
videoCanvasSidebarEnabled,
|
||||
storageFailoverConfig,
|
||||
@ -1576,6 +1634,19 @@ const updateSchema = z.object({
|
||||
canvasEnabled: z.boolean().optional(),
|
||||
agentEnabled: z.boolean().optional(),
|
||||
canvasAgentModeEnabled: z.boolean().optional(),
|
||||
canvasAgentFeatureSettings: z
|
||||
.object({
|
||||
operationProtocolEnabled: z.boolean(),
|
||||
writebackMode: z.enum([
|
||||
"legacy_canvas_media",
|
||||
"operation_shadow",
|
||||
"operation_authoritative",
|
||||
]),
|
||||
slotEnabled: z.boolean(),
|
||||
viewOperationEnabled: z.boolean(),
|
||||
annotationEditEnabled: z.boolean(),
|
||||
})
|
||||
.optional(),
|
||||
videoCanvasEnabled: z.boolean().optional(),
|
||||
videoCanvasSidebarEnabled: z.boolean().optional(),
|
||||
agentPresetLibraryConfig: z
|
||||
@ -2064,6 +2135,7 @@ export async function PUT(request: NextRequest) {
|
||||
canvasToolbarConfig,
|
||||
lovartHomeSidebarConfig,
|
||||
canvasAgentModeEnabled,
|
||||
canvasAgentFeatureSettings,
|
||||
videoCanvasEnabled,
|
||||
videoCanvasSidebarEnabled,
|
||||
homeAnimationConfig,
|
||||
@ -2332,6 +2404,40 @@ export async function PUT(request: NextRequest) {
|
||||
});
|
||||
};
|
||||
|
||||
const persistCanvasAgentFeatureSettings = async () => {
|
||||
if (canvasAgentFeatureSettings === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const normalized = normalizeCanvasAgentFeatureSettings(
|
||||
canvasAgentFeatureSettingsToSystemSettings(canvasAgentFeatureSettings)
|
||||
);
|
||||
const settingEntries = Object.entries(
|
||||
canvasAgentFeatureSettingsToSystemSettings(normalized)
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
settingEntries.map(([key, value]) =>
|
||||
db
|
||||
.insert(systemSettings)
|
||||
.values({
|
||||
key,
|
||||
value,
|
||||
updatedAt: new Date(),
|
||||
updatedBy: session.user.id,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: systemSettings.key,
|
||||
set: {
|
||||
value,
|
||||
updatedAt: new Date(),
|
||||
updatedBy: session.user.id,
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
await createAgentWorkflowScopeSnapshot();
|
||||
|
||||
// 查找现有设置
|
||||
@ -2489,6 +2595,8 @@ export async function PUT(request: NextRequest) {
|
||||
});
|
||||
}
|
||||
|
||||
await persistCanvasAgentFeatureSettings();
|
||||
|
||||
if (videoCanvasEnabled !== undefined) {
|
||||
const normalized = normalizeVideoCanvasEnabled(videoCanvasEnabled);
|
||||
await db
|
||||
@ -3142,6 +3250,8 @@ export async function PUT(request: NextRequest) {
|
||||
});
|
||||
}
|
||||
|
||||
await persistCanvasAgentFeatureSettings();
|
||||
|
||||
if (videoCanvasSidebarEnabled !== undefined) {
|
||||
const normalized = normalizeVideoCanvasSidebarEnabled(videoCanvasSidebarEnabled);
|
||||
await db
|
||||
|
||||
@ -11,6 +11,8 @@ export type CanvasAgentFeatureFlags = {
|
||||
annotationEditEnabled: boolean;
|
||||
};
|
||||
|
||||
export type CanvasAgentFeatureSettings = CanvasAgentFeatureFlags;
|
||||
|
||||
export const CANVAS_AGENT_OPERATION_PROTOCOL_ENABLED_KEY =
|
||||
"canvas_agent_operation_protocol_enabled";
|
||||
export const CANVAS_AGENT_WRITEBACK_MODE_KEY = "canvas_agent_writeback_mode";
|
||||
@ -124,6 +126,32 @@ export function getCanvasAgentFeatureFlags(
|
||||
return mergeCanvasAgentFeatureFlagsWithSettings(envFlags, settings);
|
||||
}
|
||||
|
||||
export function canvasAgentFeatureFlagsToSettings(
|
||||
flags: CanvasAgentFeatureFlags
|
||||
): CanvasAgentFeatureSettings {
|
||||
return {
|
||||
operationProtocolEnabled: flags.operationProtocolEnabled,
|
||||
writebackMode: flags.writebackMode,
|
||||
slotEnabled: flags.slotEnabled,
|
||||
viewOperationEnabled: flags.viewOperationEnabled,
|
||||
annotationEditEnabled: flags.annotationEditEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
export function canvasAgentFeatureSettingsToSystemSettings(
|
||||
settings: CanvasAgentFeatureSettings
|
||||
): CanvasAgentFeatureSettingsLike {
|
||||
return {
|
||||
[CANVAS_AGENT_OPERATION_PROTOCOL_ENABLED_KEY]:
|
||||
settings.operationProtocolEnabled,
|
||||
[CANVAS_AGENT_WRITEBACK_MODE_KEY]: settings.writebackMode,
|
||||
[CANVAS_AGENT_SLOT_ENABLED_KEY]: settings.slotEnabled,
|
||||
[CANVAS_AGENT_VIEW_OPERATION_ENABLED_KEY]: settings.viewOperationEnabled,
|
||||
[CANVAS_AGENT_ANNOTATION_EDIT_ENABLED_KEY]:
|
||||
settings.annotationEditEnabled,
|
||||
};
|
||||
}
|
||||
|
||||
export function canApplyCanvasAgentMutations(flags: CanvasAgentFeatureFlags) {
|
||||
return (
|
||||
flags.operationProtocolEnabled &&
|
||||
|
||||
@ -134,6 +134,8 @@ import {
|
||||
CANVAS_AGENT_SLOT_ENABLED_KEY,
|
||||
CANVAS_AGENT_VIEW_OPERATION_ENABLED_KEY,
|
||||
CANVAS_AGENT_WRITEBACK_MODE_KEY,
|
||||
canvasAgentFeatureFlagsToSettings,
|
||||
canvasAgentFeatureSettingsToSystemSettings,
|
||||
canApplyCanvasAgentMutations,
|
||||
getCanvasAgentFeatureFlags,
|
||||
normalizeCanvasAgentBoolean,
|
||||
@ -1833,6 +1835,28 @@ test.describe("canvas chat pure helpers", () => {
|
||||
annotationEditEnabled: false,
|
||||
});
|
||||
expect(canApplyCanvasAgentMutations(settingsOverride)).toBe(true);
|
||||
expect(canvasAgentFeatureFlagsToSettings(settingsOverride)).toEqual({
|
||||
operationProtocolEnabled: true,
|
||||
writebackMode: "operation_authoritative",
|
||||
slotEnabled: true,
|
||||
viewOperationEnabled: false,
|
||||
annotationEditEnabled: false,
|
||||
});
|
||||
expect(
|
||||
canvasAgentFeatureSettingsToSystemSettings({
|
||||
operationProtocolEnabled: false,
|
||||
writebackMode: "operation_shadow",
|
||||
slotEnabled: true,
|
||||
viewOperationEnabled: true,
|
||||
annotationEditEnabled: false,
|
||||
})
|
||||
).toEqual({
|
||||
[CANVAS_AGENT_OPERATION_PROTOCOL_ENABLED_KEY]: false,
|
||||
[CANVAS_AGENT_WRITEBACK_MODE_KEY]: "operation_shadow",
|
||||
[CANVAS_AGENT_SLOT_ENABLED_KEY]: true,
|
||||
[CANVAS_AGENT_VIEW_OPERATION_ENABLED_KEY]: true,
|
||||
[CANVAS_AGENT_ANNOTATION_EDIT_ENABLED_KEY]: false,
|
||||
});
|
||||
|
||||
const invalidSettingsFallback = getCanvasAgentFeatureFlags(
|
||||
{ CANVAS_AGENT_WRITEBACK_MODE: "operation_shadow" },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user