import { PANEL_DESIGN_TOKEN_ALLOWLIST } from './plugins/plugin-panel-shell' /** * The document wrapped around an agent-written chat visual before it enters its sandboxed frame. * Same placement rule as the plugin panel shell: the CSP meta parses before any visual markup, so * nothing later in the document can loosen it, and the visual's own /
merge into ours. * * Network: scripts, styles, fonts and images may load from a pinned set of public CDNs; nothing may * fetch, open sockets, frame, or submit. A page can still encode data in a request to an allowed * CDN — an accepted, disclosed risk, not a guarantee that no data leaves. * * Electron-free string builder: desktop, the web client and mobile build the same document. */ export const NATIVE_CHAT_VISUAL_CDN_ORIGINS = [ 'https://cdn.jsdelivr.net', 'https://unpkg.com', 'https://cdnjs.cloudflare.com', 'https://esm.sh', 'https://fonts.googleapis.com', 'https://fonts.gstatic.com' ] as const const ASSET_SOURCES = `'unsafe-inline' data: blob: ${NATIVE_CHAT_VISUAL_CDN_ORIGINS.join(' ')}` const MEDIA_SOURCES = `data: blob: ${NATIVE_CHAT_VISUAL_CDN_ORIGINS.join(' ')}` export const NATIVE_CHAT_VISUAL_CSP = [ "default-src 'none'", `script-src ${ASSET_SOURCES}`, `style-src ${ASSET_SOURCES}`, `font-src ${MEDIA_SOURCES}`, `img-src ${MEDIA_SOURCES}`, "connect-src 'none'", "frame-src 'none'", "child-src 'none'", "worker-src 'none'", "object-src 'none'", "media-src 'none'", "manifest-src 'none'", "form-action 'none'", "base-uri 'none'" ].join('; ') /** Frame names carry this prefix so the main process registers them before content runs. */ export const NATIVE_CHAT_VISUAL_FRAME_NAME_PREFIX = 'orca-chat-visual:' export const NATIVE_CHAT_VISUAL_SIZE_TYPE = 'orca-visual-size' export const NATIVE_CHAT_VISUAL_OPEN_LINK_TYPE = 'orca-visual-open-link' export const NATIVE_CHAT_VISUAL_THEME_TYPE = 'orca-visual-theme' export const NATIVE_CHAT_VISUAL_MIN_HEIGHT = 80 export const NATIVE_CHAT_VISUAL_MAX_HEIGHT = 2000 const MAX_LINK_LENGTH = 2048 /** Theme variables a visual may style against: the plugin panel set plus the chart series. */ export const NATIVE_CHAT_VISUAL_THEME_TOKENS = [ ...PANEL_DESIGN_TOKEN_ALLOWLIST, '--chart-1', '--chart-2', '--chart-3', '--chart-4', '--chart-5', '--font-sans', '--font-mono' ] as const export type NativeChatVisualTheme = { colorScheme: 'light' | 'dark' tokens: Readonly