export type CanvasAgentWritebackMode = | "legacy_canvas_media" | "operation_shadow" | "operation_authoritative"; export type CanvasAgentFeatureFlags = { operationProtocolEnabled: boolean; writebackMode: CanvasAgentWritebackMode; slotEnabled: boolean; viewOperationEnabled: boolean; annotationEditEnabled: boolean; }; type EnvLike = Record; const WRITEBACK_MODES = new Set([ "legacy_canvas_media", "operation_shadow", "operation_authoritative", ]); export function normalizeCanvasAgentBoolean( value: unknown, fallback: boolean ) { if (typeof value !== "string") return fallback; const normalized = value.trim().toLowerCase(); if (!normalized) return fallback; if (["1", "true", "yes", "on", "enabled"].includes(normalized)) return true; if (["0", "false", "no", "off", "disabled"].includes(normalized)) return false; return fallback; } export function normalizeCanvasAgentWritebackMode( value: unknown, fallback: CanvasAgentWritebackMode = "operation_authoritative" ): CanvasAgentWritebackMode { const normalized = typeof value === "string" ? value.trim() : ""; return WRITEBACK_MODES.has(normalized as CanvasAgentWritebackMode) ? (normalized as CanvasAgentWritebackMode) : fallback; } export function getCanvasAgentFeatureFlags( env: EnvLike = process.env ): CanvasAgentFeatureFlags { return { operationProtocolEnabled: normalizeCanvasAgentBoolean( env.CANVAS_AGENT_OPERATION_PROTOCOL_ENABLED, true ), writebackMode: normalizeCanvasAgentWritebackMode( env.CANVAS_AGENT_WRITEBACK_MODE, "operation_authoritative" ), slotEnabled: normalizeCanvasAgentBoolean( env.CANVAS_AGENT_SLOT_ENABLED, true ), viewOperationEnabled: normalizeCanvasAgentBoolean( env.CANVAS_AGENT_VIEW_OPERATION_ENABLED, true ), annotationEditEnabled: normalizeCanvasAgentBoolean( env.CANVAS_AGENT_ANNOTATION_EDIT_ENABLED, true ), }; } export function canApplyCanvasAgentMutations(flags: CanvasAgentFeatureFlags) { return ( flags.operationProtocolEnabled && flags.writebackMode === "operation_authoritative" ); } export function shouldStreamCanvasAgentShadowOperations( flags: CanvasAgentFeatureFlags ) { return flags.operationProtocolEnabled && flags.writebackMode === "operation_shadow"; }