@8wave/ai-elements 0.119.0-beta.33 → 0.119.0-beta.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{Agent-Gdgpd3LA.js → Agent-DU38SnNd.js} +411 -247
- package/dist/_chunks/Agent-DU38SnNd.js.map +1 -0
- package/dist/_chunks/{PkChatbotFilePreview-3i9jZIdS.js → PkChatbotFilePreview-Bdi4_IFu.js} +2 -2
- package/dist/_chunks/PkChatbotFilePreview-Bdi4_IFu.js.map +1 -0
- package/dist/_chunks/{PkStreamingMarkdown-B1t1tBvW.js → PkStreamingMarkdown-xnhBbPf5.js} +3 -3
- package/dist/_chunks/{PkStreamingMarkdown-B1t1tBvW.js.map → PkStreamingMarkdown-xnhBbPf5.js.map} +1 -1
- package/dist/_chunks/{PkToolEditSpreadsheet-Xzum_9NH.js → PkToolEditSpreadsheet-Ct9pdQJ1.js} +3 -3
- package/dist/_chunks/{PkToolEditSpreadsheet-Xzum_9NH.js.map → PkToolEditSpreadsheet-Ct9pdQJ1.js.map} +1 -1
- package/dist/_chunks/{PkToolRequestGeolocation-PxhQxMP1.js → PkToolRequestGeolocation-DzhrY8bg.js} +2 -2
- package/dist/_chunks/{PkToolRequestGeolocation-PxhQxMP1.js.map → PkToolRequestGeolocation-DzhrY8bg.js.map} +1 -1
- package/dist/_chunks/{PkToolRequestOAuthConnection-W3ilzpr7.js → PkToolRequestOAuthConnection-CzRKRGoG.js} +2 -2
- package/dist/_chunks/{PkToolRequestOAuthConnection-W3ilzpr7.js.map → PkToolRequestOAuthConnection-CzRKRGoG.js.map} +1 -1
- package/dist/_chunks/{PkToolShowArtifact-DGGEb2LF.js → PkToolShowArtifact-DPt1qDUk.js} +2 -2
- package/dist/_chunks/{PkToolShowArtifact-DGGEb2LF.js.map → PkToolShowArtifact-DPt1qDUk.js.map} +1 -1
- package/dist/_chunks/{PkToolShowContactForm-Dn6CEXF_.js → PkToolShowContactForm-OdC7bsXd.js} +2 -2
- package/dist/_chunks/{PkToolShowContactForm-Dn6CEXF_.js.map → PkToolShowContactForm-OdC7bsXd.js.map} +1 -1
- package/dist/_chunks/{PkToolShowForm-CbuToc8O.js → PkToolShowForm-uFmaQoI1.js} +3 -3
- package/dist/_chunks/{PkToolShowForm-CbuToc8O.js.map → PkToolShowForm-uFmaQoI1.js.map} +1 -1
- package/dist/_chunks/{PkToolShowImageGallery-Dh0v2Df8.js → PkToolShowImageGallery-KmMO4UuQ.js} +2 -2
- package/dist/_chunks/{PkToolShowImageGallery-Dh0v2Df8.js.map → PkToolShowImageGallery-KmMO4UuQ.js.map} +1 -1
- package/dist/_chunks/{PkToolShowProductList-bAis8u1t.js → PkToolShowProductList-cld-FOFb.js} +2 -2
- package/dist/_chunks/{PkToolShowProductList-bAis8u1t.js.map → PkToolShowProductList-cld-FOFb.js.map} +1 -1
- package/dist/_chunks/{PkToolShowSources-D532Worv.js → PkToolShowSources-BlpCKc4N.js} +3 -3
- package/dist/_chunks/{PkToolShowSources-D532Worv.js.map → PkToolShowSources-BlpCKc4N.js.map} +1 -1
- package/dist/_chunks/{PkToolShowSuggestedReply-BISQY1ce.js → PkToolShowSuggestedReply-xUBuqStM.js} +2 -2
- package/dist/_chunks/{PkToolShowSuggestedReply-BISQY1ce.js.map → PkToolShowSuggestedReply-xUBuqStM.js.map} +1 -1
- package/dist/_chunks/{PkToolShowVideo-DcMzLibC.js → PkToolShowVideo-KDNxItWl.js} +2 -2
- package/dist/_chunks/{PkToolShowVideo-DcMzLibC.js.map → PkToolShowVideo-KDNxItWl.js.map} +1 -1
- package/dist/_chunks/{PkToolShowWebPages-RuwkZDMH.js → PkToolShowWebPages-D35B7GzS.js} +2 -2
- package/dist/_chunks/{PkToolShowWebPages-RuwkZDMH.js.map → PkToolShowWebPages-D35B7GzS.js.map} +1 -1
- package/dist/_chunks/{chatImagePolicy-BL4O14e9.js → chatImagePolicy-B_6Xg-r7.js} +2 -2
- package/dist/_chunks/{chatImagePolicy-BL4O14e9.js.map → chatImagePolicy-B_6Xg-r7.js.map} +1 -1
- package/dist/_chunks/{markdown-BbaLt57-.js → markdown-BKLfFJPr.js} +96 -90
- package/dist/_chunks/markdown-BKLfFJPr.js.map +1 -0
- package/dist/ai-elements.es.js +1898 -1893
- package/dist/ai-elements.es.js.map +1 -1
- package/dist-vue/PkChatbot.js +1 -1
- package/dist-vue/PkChatbotAuth.js +1 -1
- package/dist-vue/PkChatbotEmptyState.js +1 -1
- package/dist-vue/PkChatbotFilePreview.js +1 -1
- package/dist-vue/PkChatbotInput.js +1 -1
- package/dist-vue/PkChatbotMessages.js +1 -1
- package/dist-vue/PkChatbotStepPayload.js +1 -1
- package/dist-vue/PkChatbotStepToolDetail.js +1 -1
- package/dist-vue/PkChatbotSteps.js +1 -1
- package/dist-vue/PkChatbotViewChat.js +1 -1
- package/dist-vue/PkChatbotViewConversations.js +1 -1
- package/dist-vue/PkChatbotViewFiles.js +1 -1
- package/dist-vue/PkChatbotViewProfile.js +1 -1
- package/dist-vue/_chunks/{Agent-DU1WWaHR.js → Agent-DDm9cCaN.js} +103 -102
- package/dist-vue/_chunks/Agent-DDm9cCaN.js.map +1 -0
- package/dist-vue/_chunks/{Document-Cto-Qws0.js → Document-CZemm1AR.js} +17 -13
- package/dist-vue/_chunks/Document-CZemm1AR.js.map +1 -0
- package/dist-vue/_chunks/Media-D-UGzdcW.js +301 -0
- package/dist-vue/_chunks/Media-D-UGzdcW.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbot-wODOAtOD.js → PkChatbot-DXwMfwN4.js} +8 -8
- package/dist-vue/_chunks/{PkChatbot-wODOAtOD.js.map → PkChatbot-DXwMfwN4.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotAuth-BVZzjbK9.js → PkChatbotAuth-CHoEXxmg.js} +8 -8
- package/dist-vue/_chunks/{PkChatbotAuth-BVZzjbK9.js.map → PkChatbotAuth-CHoEXxmg.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotEmptyState-Dx4mTkTX.js → PkChatbotEmptyState-Dve5Ci2Y.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotEmptyState-Dx4mTkTX.js.map → PkChatbotEmptyState-Dve5Ci2Y.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotFilePreview-Lxgu89Hg.js → PkChatbotFilePreview-D8XyjDPJ.js} +2 -2
- package/dist-vue/_chunks/PkChatbotFilePreview-D8XyjDPJ.js.map +1 -0
- package/dist-vue/_chunks/PkChatbotInput-DiCxEime.js +392 -0
- package/dist-vue/_chunks/PkChatbotInput-DiCxEime.js.map +1 -0
- package/dist-vue/_chunks/PkChatbotMessages-CTp0NkY2.js +881 -0
- package/dist-vue/_chunks/PkChatbotMessages-CTp0NkY2.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotStepPayload-f2mYAVpu.js → PkChatbotStepPayload-B1o2DbQz.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotStepPayload-f2mYAVpu.js.map → PkChatbotStepPayload-B1o2DbQz.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotStepToolDetail-BcYheOnU.js → PkChatbotStepToolDetail-DpYV0KLn.js} +3 -3
- package/dist-vue/_chunks/{PkChatbotStepToolDetail-BcYheOnU.js.map → PkChatbotStepToolDetail-DpYV0KLn.js.map} +1 -1
- package/dist-vue/_chunks/PkChatbotSteps-BPon4zjv.js +189 -0
- package/dist-vue/_chunks/PkChatbotSteps-BPon4zjv.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotViewChat-DZqXDwzk.js → PkChatbotViewChat-dJE2iHPN.js} +237 -236
- package/dist-vue/_chunks/PkChatbotViewChat-dJE2iHPN.js.map +1 -0
- package/dist-vue/_chunks/{PkChatbotViewConversations-CXcToApC.js → PkChatbotViewConversations-DcEcJgwV.js} +3 -3
- package/dist-vue/_chunks/{PkChatbotViewConversations-CXcToApC.js.map → PkChatbotViewConversations-DcEcJgwV.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotViewFiles-O8lhbXAX.js → PkChatbotViewFiles-DDEJqXct.js} +3 -3
- package/dist-vue/_chunks/{PkChatbotViewFiles-O8lhbXAX.js.map → PkChatbotViewFiles-DDEJqXct.js.map} +1 -1
- package/dist-vue/_chunks/{PkChatbotViewProfile-kryFJi0l.js → PkChatbotViewProfile-B79UynQ8.js} +2 -2
- package/dist-vue/_chunks/{PkChatbotViewProfile-kryFJi0l.js.map → PkChatbotViewProfile-B79UynQ8.js.map} +1 -1
- package/dist-vue/_chunks/{PkStreamingMarkdown-CywawRVj.js → PkStreamingMarkdown-CqT_orLj.js} +3 -3
- package/dist-vue/_chunks/{PkStreamingMarkdown-CywawRVj.js.map → PkStreamingMarkdown-CqT_orLj.js.map} +1 -1
- package/dist-vue/_chunks/{PkSvgViewer-DU8K_gAD.js → PkSvgViewer-CZASatr4.js} +2 -2
- package/dist-vue/_chunks/{PkSvgViewer-DU8K_gAD.js.map → PkSvgViewer-CZASatr4.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolEditSpreadsheet-BT4HueLs.js → PkToolEditSpreadsheet-Dcp3VFzY.js} +3 -3
- package/dist-vue/_chunks/{PkToolEditSpreadsheet-BT4HueLs.js.map → PkToolEditSpreadsheet-Dcp3VFzY.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolRequestGeolocation-JZYgc-2X.js → PkToolRequestGeolocation-DG4-qKRq.js} +2 -2
- package/dist-vue/_chunks/{PkToolRequestGeolocation-JZYgc-2X.js.map → PkToolRequestGeolocation-DG4-qKRq.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolRequestOAuthConnection-Ck2tRuls.js → PkToolRequestOAuthConnection-CZhNEM-o.js} +2 -2
- package/dist-vue/_chunks/{PkToolRequestOAuthConnection-Ck2tRuls.js.map → PkToolRequestOAuthConnection-CZhNEM-o.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowArtifact-BiFJoOTT.js → PkToolShowArtifact-Qfkz64NY.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowArtifact-BiFJoOTT.js.map → PkToolShowArtifact-Qfkz64NY.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowContactForm-B7DvA6O1.js → PkToolShowContactForm-CRLEkYSE.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowContactForm-B7DvA6O1.js.map → PkToolShowContactForm-CRLEkYSE.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowDiagram-DGMwlxqB.js → PkToolShowDiagram-j4FJ34Ta.js} +3 -3
- package/dist-vue/_chunks/{PkToolShowDiagram-DGMwlxqB.js.map → PkToolShowDiagram-j4FJ34Ta.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowForm-BZmAnMSD.js → PkToolShowForm-DdFBwLMf.js} +4 -4
- package/dist-vue/_chunks/{PkToolShowForm-BZmAnMSD.js.map → PkToolShowForm-DdFBwLMf.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowImageGallery-BsYTRg_W.js → PkToolShowImageGallery-CxlOwuTJ.js} +3 -3
- package/dist-vue/_chunks/{PkToolShowImageGallery-BsYTRg_W.js.map → PkToolShowImageGallery-CxlOwuTJ.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowProductList-D1_v79Xm.js → PkToolShowProductList-dfd3vmhl.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowProductList-D1_v79Xm.js.map → PkToolShowProductList-dfd3vmhl.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowSources-Czu2IiGq.js → PkToolShowSources-B8Euk3rp.js} +3 -3
- package/dist-vue/_chunks/{PkToolShowSources-Czu2IiGq.js.map → PkToolShowSources-B8Euk3rp.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowSuggestedReply-I6FBos-F.js → PkToolShowSuggestedReply-Cl3Pswi4.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowSuggestedReply-I6FBos-F.js.map → PkToolShowSuggestedReply-Cl3Pswi4.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowVideo-D3D2sTAP.js → PkToolShowVideo-C84UrvZ7.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowVideo-D3D2sTAP.js.map → PkToolShowVideo-C84UrvZ7.js.map} +1 -1
- package/dist-vue/_chunks/{PkToolShowWebPages-DTq0811l.js → PkToolShowWebPages-CzzuVQqL.js} +2 -2
- package/dist-vue/_chunks/{PkToolShowWebPages-DTq0811l.js.map → PkToolShowWebPages-CzzuVQqL.js.map} +1 -1
- package/dist-vue/_chunks/{createChatbotApiClient-BlJ952Kb.js → createChatbotApiClient-DrUsRvCw.js} +3 -3
- package/dist-vue/_chunks/createChatbotApiClient-DrUsRvCw.js.map +1 -0
- package/dist-vue/_chunks/{useChatbotStore-CueyhDPB.js → useChatbotStore-DHmjHPR5.js} +3 -3
- package/dist-vue/_chunks/{useChatbotStore-CueyhDPB.js.map → useChatbotStore-DHmjHPR5.js.map} +1 -1
- package/dist-vue/_chunks/{utils-DmRXPCqa.js → utils-7oPvmwwu.js} +2 -2
- package/dist-vue/_chunks/{utils-DmRXPCqa.js.map → utils-7oPvmwwu.js.map} +1 -1
- package/dist-vue/api.js +1 -1
- package/dist-vue/composables.js +5 -5
- package/dist-vue/composables.js.map +1 -1
- package/dist-vue/index.js +5190 -5185
- package/dist-vue/index.js.map +1 -1
- package/dist-vue/locales.js +2 -0
- package/dist-vue/packages/composable/src/chatbot/useChatbotStore.d.ts +6 -0
- package/dist-vue/packages/models/src/schema/Branding.d.ts +5 -0
- package/dist-vue/packages/models/src/schema/Chat.d.ts +8 -0
- package/dist-vue/packages/models/src/schema/Media.d.ts +34 -0
- package/dist-vue/packages/models/src/schema/ModelProvider.d.ts +12 -1
- package/dist-vue/packages/models/src/schema/constants.d.ts +26 -1
- package/package.json +1 -1
- package/dist/_chunks/Agent-Gdgpd3LA.js.map +0 -1
- package/dist/_chunks/PkChatbotFilePreview-3i9jZIdS.js.map +0 -1
- package/dist/_chunks/markdown-BbaLt57-.js.map +0 -1
- package/dist-vue/_chunks/Agent-DU1WWaHR.js.map +0 -1
- package/dist-vue/_chunks/Document-Cto-Qws0.js.map +0 -1
- package/dist-vue/_chunks/Media-C6RS-s98.js +0 -139
- package/dist-vue/_chunks/Media-C6RS-s98.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotFilePreview-Lxgu89Hg.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotInput-jj3qQl_f.js +0 -388
- package/dist-vue/_chunks/PkChatbotInput-jj3qQl_f.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotMessages-5wPl7-j-.js +0 -876
- package/dist-vue/_chunks/PkChatbotMessages-5wPl7-j-.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotSteps-DKyF0ykL.js +0 -191
- package/dist-vue/_chunks/PkChatbotSteps-DKyF0ykL.js.map +0 -1
- package/dist-vue/_chunks/PkChatbotViewChat-DZqXDwzk.js.map +0 -1
- package/dist-vue/_chunks/createChatbotApiClient-BlJ952Kb.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Agent-DU38SnNd.js","names":["z.codec","z.record","z.string","z.unknown","z.uuid","z.number","z.boolean","z.union","z.array","z.enum","z.object","z.string","z.enum","z.number","z.object","z.string","z.array","z.number","z.boolean","z.object","z.enum","z.string","z.number","z.literal","z.url","z.discriminatedUnion","z.record","z.array","z.custom","z.object","z.enum","z.number","z.boolean","z.unknown","z.string","z.array","z.literal","z.record","z.url","z.lazy","z.coerce.date","z.null","z.discriminatedUnion","z.uuid","url","unknown","object","_null","string","codec","lazy","number","custom","array","literal","_enum","boolean","date","discriminatedUnion","uuid","union","record","decodeOnly","input","output","value","MAX_SCHEMA_SIZE_BYTES","jsonSchemaField","val","makeSortEnum","makeSortEnums","i","zodQs","v","defaultNumber","defaultSize","a","b","sortEnums","sort","HEX_COLOR_REGEX","BrandingPaletteSchema","BrandingColorsSchema","BrandingMode","\"System\"","\"ForceLight\"","\"ForceDark\"","BrandingAssetSlot","\"LogoLight\"","\"LogoDark\"","\"Mark\"","\"EmailLogo\"","\"EmailBanner\"","BrandingAssetRefSchema","BrandingAssetsSchema","BrandingTextSchema","DeploymentBrandingSchema","PatchAssetsSchema","PatchTextSchema","BrandingPatchSchema","tolerant","schema","deepFreeze","child","DeviceContextSchema","MIME_TYPE_REGEX","AUDIO_EXTENSIONS","extension","OTHER_AUDIO_EXTENSIONS","bareMimeType","mimeType","isAudioFile","getExtensionFromFilename","name","CODE_FILE_FORMATS","format","codeExtensionsOf","mimeTypes","chatDropAccepts","allowedMimeTypes","code","loose","types","type","allowed","StoragePolicy","\"DEFAULT\"","\"COLD\"","\"HOT\"","\"ARCHIVE\"","AzureBlobStorageHandleSchema","S3StorageHandleSchema","StorageHandleSchema","MediaSourceSchema","ext","MediaSchema","MediaType","\"picture\"","\"video\"","\"audio\"","\"office\"","\"archive\"","\"binary\"","\"executable\"","PictureRawOptionsSchema","VideoRawOptionsSchema","AudioRawOptionsSchema","OfficeRawOptionsSchema","ArchiveRawOptionsSchema","BinaryRawOptionsSchema","ExecutableRawOptionsSchema","lastDot","filename","AgentStatus","\"Draft\"","\"Active\"","\"Inactive\"","AgentVisibility","\"Public\"","\"Private\"","\"Organization\"","AgentType","\"Chat\"","\"Reasoning\"","AgentSearchMode","\"Semantic\"","\"Balanced\"","\"Keyword\"","OPENAI_REASONING_EFFORTS","ANTHROPIC_THINKING_EFFORTS","GOOGLE_THINKING_LEVELS","OPENAI_REASONING_SUMMARIES","OpenAIReasoningSchema","AnthropicReasoningSchema","GoogleReasoningSchema","DeepSeekReasoningSchema","GENERIC_REASONING_PROVIDERS","GENERIC_REASONING_EFFORTS","GenericReasoningSchema","legacyLevel","accepted","AgentReasoningObjectSchema","migrateReasoningConfig","obj","isAlreadyMigrated","provider","effort","reasoningSummary","migrated","openaiEffort","summary","anthropicEffort","googleLevel","genericEffort","AgentReasoningSchema","AgentBuiltInTool","\"Geocode\"","\"GetWeather\"","\"ReadDocumentFile\"","\"RequestConfirm\"","\"RequestGeolocation\"","\"RetrieveRevisedAnswers\"","\"SearchInKnowledgeBase\"","\"SearchInUserFiles\"","\"UserMemory\"","\"Spreadsheet\"","\"QuerySpreadsheet\"","\"RunWorker\"","\"ScheduleWakeup\"","\"FetchTeamsChannelHistory\"","\"ShowArtifact\"","\"ShowCalendarEvent\"","\"ShowComparison\"","\"ShowContactForm\"","\"ShowDiagram\"","\"ShowEmail\"","\"ShowImageGallery\"","\"ShowLocation\"","\"ShowMessage\"","\"ShowForm\"","\"ShowProductList\"","\"ShowQrCode\"","\"ShowSources\"","\"ShowSuggestedReply\"","\"ShowVideo\"","\"ShowWeather\"","\"ShowWebPages\"","\"ShowMultipleChoice\"","MCP_TOOL_PREFIX","API_TOOL_PREFIX","SUBAGENT_TOOL_PREFIX","isPresentationTool","toolName","USER_ANSWERED_TOOLS","isUserAnsweredTool","VOICE_RENDERED_TOOLS","LEGACY_VOICE_RENDER_ACK_PREFIX","isVoiceRenderAck","AgentFormSettingsSchema","WebSearchProvider","\"Perplexity\"","\"Parallel\"","\"Native\"","PerplexitySearchConfigSchema","ParallelSearchConfigSchema","NativeWebSearchConfigSchema","AgentWebSearchSchema","AgentUserMemorySchema","AgentUserFilesSchema","AgentToolApprovalSchema","AgentToolsSchema","AgentRankingSchema","AgentModelSchema","LocalizedStringSchema","DEFAULT_WIDGET_URL","AgentLoaderStrategy","\"InlineModule\"","\"ScriptSrc\"","\"DynamicImport\"","AgentChannel","\"Frontoffice\"","\"App\"","\"Widget\"","ALL_AGENT_CHANNELS","IMAGE_HOST_PATTERN","normalizeImageHost","trimmed","AgentInterfaceSchema","host","hosts","CHAT_FILE_UPLOAD_DEFAULT_MIME_TYPES","SPREADSHEET_MIME_TYPE","AgentFileUploadSchema","AgentGatewayOptionsSchema","AgentOpenAiApiSchema","AgentToolWorkingSetMode","\"Off\"","\"Shadow\"","AgentToolWorkingSetSchema","AgentVoiceSchema","seconds","AgentVoiceCapabilitySchema","VoiceSessionSchema","VoiceOptionSchema","AgentSettingsSchema","AgentSecuritySchema","items","item","AgentPublicSchema","AgentBrandingInterfaceSchema","AgentBrandingSchema","AuthMethodsSchema","AgentAccessGrantedSchema","AgentAccessRequiresAuthSchema","AgentAccessExtrasSchema"],"sources":["../../../../packages/models/src/utils.ts","../../../../packages/models/src/schema/Branding.ts","../../../../packages/models/src/schema/DeviceContext.ts","../../../../packages/models/src/schema/Media.ts","../../../../packages/models/src/schema/Agent.ts"],"sourcesContent":["import * as z from 'zod'\n\n/**\n * Bidirectional wrapper for decode-time normalizations.\n *\n * Response serialization must never hit a unidirectional transform\n * (z.preprocess/.transform throw ZodEncodeError under zod encode), so\n * normalizing schemas are expressed as codecs: `decode` runs the\n * normalization (output validity is enforced by the output schema at\n * runtime), while `encode` is the identity for already-normalized data.\n */\nexport const decodeOnly = <Input extends z.ZodType, Output extends z.ZodType>(\n input: Input,\n output: Output,\n decode: (value: z.output<Input>) => z.input<Output>,\n) =>\n z.codec(input, output, {\n // Identity: already-normalized data is serialized unchanged. The\n // input schema re-validates at runtime, so the cast is type-only.\n encode: (value) => value as z.output<Input>,\n decode,\n })\n\nconst MAX_SCHEMA_SIZE_BYTES = 50 * 1024 // 50 KB\n\n/** Reusable Zod field for JSON Schema objects with a 50 KB size limit. */\nexport const jsonSchemaField = z\n .record(z.string(), z.unknown())\n .refine((val) => JSON.stringify(val).length <= MAX_SCHEMA_SIZE_BYTES, {\n message: `Schema must not exceed ${MAX_SCHEMA_SIZE_BYTES / 1024} KB`,\n })\n\n/**\n * Reusable UUID schema, built once.\n *\n * `z.uuid()` inside a loop or a hot function rebuilds the schema on every call,\n * which costs more than the check itself. Pair it with `.validate()` when only\n * the boolean is needed: `safeParse` builds a ZodError nobody reads.\n */\nexport const UuidSchema = z.uuid()\n\nexport type QueryStringFilter<T extends string = string> = `filter[${T}]`\nexport type Querystring = {\n 'page[number]'?: number | string\n 'page[size]'?: number | string\n sort?: string[] | string\n [filterKeys: QueryStringFilter]: unknown\n [otherKeys: string]: unknown\n}\n\nexport const makeSortEnum = <const T extends string>(input: T) => {\n return [`${input}`, `-${input}`] as [T, `-${T}`]\n}\n\nexport const makeSortEnums = <const T extends string>(input: readonly T[]) => {\n return input.flatMap((i) => makeSortEnum(i))\n}\n\nexport const zodQs = {\n pagination: (defaultNumber = 1, defaultSize = 10) => {\n return {\n 'page[number]': z\n .number()\n .or(z.string())\n .transform((v) => Number(v))\n .default(defaultNumber),\n 'page[size]': z\n .number()\n .or(z.string())\n .transform((v) => Number(v))\n .default(defaultSize),\n }\n },\n filter: <const T extends string>(input: T) => {\n return { [`filter[${input}]`]: z.string().optional() } as Record<\n `filter[${T}]`,\n z.ZodOptional<z.ZodString | z.ZodArray<z.ZodString>>\n >\n },\n include: <const T extends string>(input: T) => {\n return { [`include[${input}]`]: z.string().optional() } as Record<\n `include[${T}]`,\n z.ZodOptional<z.ZodArray<z.ZodString> | z.ZodString>\n >\n },\n range: <const T extends string>(input: T) => {\n return {\n [`from[${input}]`]: z.string().optional(),\n [`to[${input}]`]: z.string().optional(),\n } as Record<`from[${T}]` | `to[${T}]`, z.ZodOptional<z.ZodString>>\n },\n has: <const T extends string>(input: T) => {\n return { [`has[${input}]`]: z.boolean().optional() } as Record<\n `has[${T}]`,\n z.ZodOptional<z.ZodBoolean>\n >\n },\n fullText: () => {\n return { [`filter[fullText]`]: z.string().optional() }\n },\n ids: () => {\n return { ids: z.union([z.string(), z.array(z.string())]).optional() }\n },\n deleted: () => {\n return { 'filter[isDeleted]': z.boolean().default(false) }\n },\n filters: <const T extends string>(input: readonly T[]) => {\n return input\n .map((i) => zodQs.filter(i))\n .reduce((a, b) => ({ ...a, ...b }))\n },\n sort: <const S extends string>(sort: S[]) => {\n const sortEnums = makeSortEnums(sort) as [S, ...`-${S}`[]]\n return {\n // @ts-expect-error: zod does not support tuple types\n sort: z.enum(sortEnums).optional().default(sortEnums[0]),\n }\n },\n}\n\n/**\n * A tool name without the namespace a model invented for it (Gemini's\n * `default_api:toolName`). One definition, because several readers must\n * agree on it: the repair of a tool call, and the closure acceptance, which\n * reads the call before the repair has run (`createClosureAcceptance`).\n */\nexport const stripInventedNamespace = (toolName: string): string =>\n toolName.replace(/^[a-zA-Z_]+:/, '')\n\n/**\n * The registered name a tool name stands for, when the intent is\n * unambiguous: the name without an invented namespace, the name itself, or\n * the one registered name that ends with `-<name>` (a dropped `mcp-` prefix).\n * Shared by the repair of a tool call, by the working set, which must\n * recognize a call to a tool it hid (the repair only sees the tools of the\n * step), and by the message detail, which reads those calls as the working\n * set did (`summarizeToolSelection`).\n */\nexport const resolveToolName = (\n toolName: string,\n names: Iterable<string>,\n): string | undefined => {\n const known = new Set(names)\n const cleaned = stripInventedNamespace(toolName)\n if (cleaned !== toolName && known.has(cleaned)) {\n return cleaned\n }\n if (known.has(toolName)) {\n return toolName\n }\n const matches = [...known].filter((name) => name.endsWith(`-${cleaned}`))\n return matches.length === 1 ? matches[0] : undefined\n}\n","import * as z from 'zod'\nimport { PWA_MANIFEST_BASE, pwaManifestIcons } from './PwaManifest'\n\n/** A six-digit hex color: the only form a theme or agent color is stored in. */\nexport const HEX_COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/\n\n/** The three colors a theme sets: the ones `packages/style` itself overrides. */\nexport const BrandingPaletteSchema = z.object({\n brand: z.string().regex(HEX_COLOR_REGEX),\n accent: z.string().regex(HEX_COLOR_REGEX),\n info: z.string().regex(HEX_COLOR_REGEX),\n})\nexport type BrandingPalette = z.infer<typeof BrandingPaletteSchema>\n\n/**\n * Light and dark come together: the dark brand of the design system is an\n * independent color, not a derivation of the light one, so a theme that sets\n * only the light palette would sit next to the default dark one.\n */\nexport const BrandingColorsSchema = z.object({\n light: BrandingPaletteSchema,\n dark: BrandingPaletteSchema,\n})\nexport type BrandingColors = z.infer<typeof BrandingColorsSchema>\n\n/**\n * Whether two palettes, or two pairs of them, are the same colors, whatever\n * the case of the hex.\n */\nexport const sameBrandingColors = <T extends BrandingColors | BrandingPalette>(\n a: T,\n b: T,\n) => JSON.stringify(a).toLowerCase() === JSON.stringify(b).toLowerCase()\n\n/** Whether the user picks light or dark, or the deployment fixes one. */\nexport enum BrandingMode {\n System = 'system',\n ForceLight = 'force-light',\n ForceDark = 'force-dark',\n}\n\n/** The image slots of a theme. */\nexport enum BrandingAssetSlot {\n LogoLight = 'logoLight',\n LogoDark = 'logoDark',\n Mark = 'mark',\n EmailLogo = 'emailLogo',\n EmailBanner = 'emailBanner',\n}\n\n/** Largest image a theme slot accepts, before any processing. */\nexport const BRANDING_ASSET_MAX_BYTES = 512 * 1024\n\n/** Largest side of a raster image: a 1200 px email banner has to fit. */\nexport const BRANDING_RASTER_MAX_SIDE = 2048\n\n/**\n * Width an email image is stored at, twice the width it is shown at for high\n * density screens. Gmail and Outlook show neither SVG nor WebP, so the two\n * email slots store a PNG, or a JPEG when the image is opaque.\n */\nexport const BRANDING_EMAIL_WIDTH: Partial<Record<BrandingAssetSlot, number>> =\n {\n [BrandingAssetSlot.EmailLogo]: 400,\n [BrandingAssetSlot.EmailBanner]: 1200,\n }\n\n/** The formats an image is uploaded in. */\nexport const BRANDING_ASSET_MIME_TYPES = [\n 'image/svg+xml',\n 'image/png',\n 'image/webp',\n] as const\nexport type BrandingAssetMimeType = (typeof BRANDING_ASSET_MIME_TYPES)[number]\n\n/** The formats an image is stored in: an opaque email image becomes a JPEG. */\nexport const BRANDING_STORED_MIME_TYPES = [\n ...BRANDING_ASSET_MIME_TYPES,\n 'image/jpeg',\n] as const\nexport type BrandingStoredMimeType = (typeof BRANDING_STORED_MIME_TYPES)[number]\n\n/** An uploaded image, addressed by the sha256 of the bytes that are served. */\nexport const BrandingAssetRefSchema = z.object({\n checksum: z.string().regex(/^[0-9a-f]{64}$/),\n mimeType: z.enum(BRANDING_STORED_MIME_TYPES),\n width: z.number().int().positive().nullable(),\n height: z.number().int().positive().nullable(),\n})\nexport type BrandingAssetRef = z.infer<typeof BrandingAssetRefSchema>\n\n/** Null in a slot means the image the bundle ships. */\nexport const BrandingAssetsSchema = z.object({\n [BrandingAssetSlot.LogoLight]: BrandingAssetRefSchema.nullable(),\n [BrandingAssetSlot.LogoDark]: BrandingAssetRefSchema.nullable(),\n [BrandingAssetSlot.Mark]: BrandingAssetRefSchema.nullable(),\n [BrandingAssetSlot.EmailLogo]: BrandingAssetRefSchema.nullable(),\n [BrandingAssetSlot.EmailBanner]: BrandingAssetRefSchema.nullable(),\n})\nexport type BrandingAssets = z.infer<typeof BrandingAssetsSchema>\n\nexport const BrandingTextSchema = z.object({\n /** Window title, emails, Teams app, MCP client name. */\n productName: z.string().trim().min(1).max(60),\n /** Strong line of the logo, PWA short name. */\n shortName: z.string().trim().min(1).max(24),\n description: z.string().trim().max(200).nullable(),\n /** Small line above the short name in the logo. */\n productTagline: z.string().trim().max(40).nullable(),\n /** Email footer and image alt texts; no footer when null. */\n companyName: z.string().trim().max(80).nullable(),\n})\nexport type BrandingText = z.infer<typeof BrandingTextSchema>\n\n/** A complete theme: what every level resolves to. */\nexport const BrandingSchema = z.object({\n colors: BrandingColorsSchema,\n mode: z.enum(BrandingMode),\n assets: BrandingAssetsSchema,\n text: BrandingTextSchema,\n})\nexport type Branding = z.infer<typeof BrandingSchema>\n\n/** A complete theme with the hash of its content, served to the clients. */\nexport const ResolvedBrandingSchema = BrandingSchema.extend({\n version: z.string(),\n})\nexport type ResolvedBranding = z.infer<typeof ResolvedBrandingSchema>\n\n/**\n * What the embeddable widget gets of the deployment theme: the stylesheet it\n * puts in its shadow root, which the page's own stylesheet cannot reach.\n */\nexport const DeploymentBrandingSchema = z.object({\n css: z.string(),\n})\nexport type DeploymentBranding = z.infer<typeof DeploymentBrandingSchema>\n\nconst PatchAssetsSchema = BrandingAssetsSchema.partial()\nconst PatchTextSchema = BrandingTextSchema.partial().extend({\n productName: BrandingTextSchema.shape.productName.nullish(),\n shortName: BrandingTextSchema.shape.shortName.nullish(),\n})\n\n/**\n * What a level stores, and what a write accepts: every section and every\n * value optional, and a missing or null one inherits from the level below. An\n * empty string clears an optional text.\n */\nexport const BrandingPatchSchema = z.object({\n colors: BrandingColorsSchema.nullish(),\n mode: z.enum(BrandingMode).nullish(),\n assets: PatchAssetsSchema.nullish(),\n text: PatchTextSchema.nullish(),\n})\nexport type BrandingPatch = z.infer<typeof BrandingPatchSchema>\n\n/**\n * The deployment patch as the system page reads and saves it. The revision\n * names the stored document the page started from: a save sends it back, and\n * is refused when another one landed in between, rather than undoing it.\n */\nexport const SystemBrandingSchema = z.object({\n patch: BrandingPatchSchema,\n revision: z.string().min(1).max(64),\n})\nexport type SystemBranding = z.infer<typeof SystemBrandingSchema>\n\n/** A value that reads as missing when it does not validate. */\nconst tolerant = <T extends z.ZodType>(schema: T) =>\n schema.optional().catch(undefined)\n\n/**\n * The read side of {@link BrandingPatchSchema}: a stored value that no longer\n * validates (a format a later release dropped, a hand edit) loses only itself,\n * so one bad logo does not turn a white-label back into the default theme. The\n * colors are one value: a single invalid color drops both palettes, since half\n * a theme mixed with the default colors is worse than the default.\n */\nconst BrandingPatchReadSchema = z.object({\n colors: tolerant(BrandingColorsSchema.nullable()),\n mode: tolerant(z.enum(BrandingMode).nullable()),\n assets: tolerant(\n z\n .object({\n [BrandingAssetSlot.LogoLight]: tolerant(\n PatchAssetsSchema.shape.logoLight,\n ),\n [BrandingAssetSlot.LogoDark]: tolerant(\n PatchAssetsSchema.shape.logoDark,\n ),\n [BrandingAssetSlot.Mark]: tolerant(\n PatchAssetsSchema.shape.mark,\n ),\n [BrandingAssetSlot.EmailLogo]: tolerant(\n PatchAssetsSchema.shape.emailLogo,\n ),\n [BrandingAssetSlot.EmailBanner]: tolerant(\n PatchAssetsSchema.shape.emailBanner,\n ),\n })\n .nullable(),\n ),\n text: tolerant(\n z\n .object({\n productName: tolerant(PatchTextSchema.shape.productName),\n shortName: tolerant(PatchTextSchema.shape.shortName),\n description: tolerant(PatchTextSchema.shape.description),\n productTagline: tolerant(PatchTextSchema.shape.productTagline),\n companyName: tolerant(PatchTextSchema.shape.companyName),\n })\n .nullable(),\n ),\n})\n\n/**\n * The theme the code ships with: the compile-time colors of `packages/style`\n * and the product names of AGENTS.md. Assets are the bundled images. Frozen,\n * because every resolution starts from it.\n */\nexport const DEFAULT_BRANDING: Branding = deepFreeze({\n colors: {\n light: { brand: '#140e33', accent: '#9365ff', info: '#86c8fb' },\n dark: { brand: '#565676', accent: '#9365ff', info: '#86c8fb' },\n },\n mode: BrandingMode.System,\n assets: {\n [BrandingAssetSlot.LogoLight]: null,\n [BrandingAssetSlot.LogoDark]: null,\n [BrandingAssetSlot.Mark]: null,\n [BrandingAssetSlot.EmailLogo]: null,\n [BrandingAssetSlot.EmailBanner]: null,\n },\n text: {\n productName: 'Eight Wave Agent Studio',\n shortName: 'Agent Studio',\n description:\n 'Eight Wave platform to create and manage AI agents with a user-friendly interface.',\n productTagline: 'Eight Wave',\n companyName: null,\n },\n})\n\n/**\n * The theme a reader falls back on when the stored one cannot be read. The\n * deployment may be any company's, so the product gets a generic name and,\n * since that name is not the default one, no bundled image: an email or a\n * manifest goes out without a logo rather than with Eight Wave's.\n */\nexport const NEUTRAL_BRANDING: Branding = deepFreeze({\n ...DEFAULT_BRANDING,\n text: {\n productName: 'Agent Studio',\n shortName: 'Agent Studio',\n description: null,\n productTagline: null,\n companyName: null,\n },\n})\n\n/**\n * Whether a theme without an image of its own may show Eight Wave's: only\n * while it keeps the default product name. A renamed deployment gets a\n * neutral mark, or no image in an email, never another company's logo.\n */\nexport const usesBundledImages = (text: Pick<BrandingText, 'productName'>) =>\n text.productName === DEFAULT_BRANDING.text.productName\n\n/** WCAG relative luminance of a `#rrggbb` color. */\nfunction relativeLuminance(hex: string): number {\n const value = Number.parseInt(hex.slice(1), 16)\n const [r, g, b] = [value >> 16, (value >> 8) & 255, value & 255].map(\n (channel) => {\n const c = channel / 255\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4\n },\n )\n return 0.2126 * r + 0.7152 * g + 0.0722 * b\n}\n\n/**\n * Black or white, whichever reads better on a `#rrggbb` color: they tie at a\n * luminance of 0.179.\n */\nexport const inkOn = (hex: string) =>\n relativeLuminance(hex) > 0.179 ? '#000000' : '#ffffff'\n\n/**\n * The first letter or digit of a name, in capitals when that stays one\n * character (\"ß\" stays \"ß\"). Nothing else: a control character, which the\n * name schema allows, would make the SVG invalid XML, and markup characters\n * would need escaping.\n */\nfunction initialOf(name: string): string {\n const char = name.match(/[\\p{L}\\p{N}]/u)?.[0] ?? ''\n const upper = char.toUpperCase()\n return upper.length === char.length ? upper : char\n}\n\n/**\n * The square mark of a theme that uploaded none and may not show the bundled\n * one: the first letter of its name on its brand color, in black or white,\n * whichever reads better (they tie at a luminance of 0.179). With rounded\n * corners, unless an opaque icon draws it edge to edge, for a platform that\n * rounds or crops it to its own shape.\n */\nexport function neutralMarkSvg(\n name: string,\n color: string,\n { rounded = true }: { rounded?: boolean } = {},\n): string {\n const fill = HEX_COLOR_REGEX.test(color)\n ? color\n : DEFAULT_BRANDING.colors.light.brand\n const ink = inkOn(fill)\n const letter = initialOf(name)\n const radius = rounded ? ' rx=\"7\"' : ''\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\"><rect width=\"32\" height=\"32\"${radius} fill=\"${fill}\"/><text x=\"16\" y=\"16\" dy=\"0.35em\" text-anchor=\"middle\" font-family=\"system-ui, sans-serif\" font-size=\"18\" font-weight=\"600\" fill=\"${ink}\">${letter}</text></svg>`\n}\n\n/**\n * The neutral mark as a data URI, so an `<img>` and the favicon draw the\n * same thing.\n */\nexport const neutralMarkUrl = (name: string, color: string) =>\n `data:image/svg+xml,${encodeURIComponent(neutralMarkSvg(name, color))}`\n\nfunction deepFreeze<T>(value: T): T {\n if (value && typeof value === 'object') {\n for (const child of Object.values(value)) {\n deepFreeze(child)\n }\n Object.freeze(value)\n }\n return value\n}\n\n/**\n * Parse a stored patch, or null when it is missing or not an object. Values\n * that do not validate are dropped one by one, see `BrandingPatchReadSchema`.\n */\nexport function parseBrandingPatch(value: unknown): BrandingPatch | null {\n if (value === null || value === undefined) {\n return null\n }\n const parsed = BrandingPatchReadSchema.safeParse(value)\n return parsed.success ? parsed.data : null\n}\n\n/** The texts of the default theme that name Eight Wave itself. */\nconst EIGHT_WAVE_TEXTS = ['description', 'productTagline'] as const\n\n/**\n * Apply each patch in order on the default theme. A renamed theme does not\n * inherit the default tagline and description, which name Eight Wave: they\n * stay empty unless a patch sets them.\n */\nexport function resolveBranding(\n ...patches: (BrandingPatch | null | undefined)[]\n): Branding {\n const resolved: Branding = structuredClone(DEFAULT_BRANDING)\n const setTexts = new Set<keyof BrandingText>()\n for (const patch of patches) {\n if (!patch) {\n continue\n }\n if (patch.colors) {\n resolved.colors = structuredClone(patch.colors)\n }\n if (patch.mode) {\n resolved.mode = patch.mode\n }\n for (const slot of Object.values(BrandingAssetSlot)) {\n const asset = patch.assets?.[slot]\n if (asset) {\n resolved.assets[slot] = { ...asset }\n }\n }\n const text = patch.text\n if (text?.productName) {\n resolved.text.productName = text.productName\n }\n if (text?.shortName) {\n resolved.text.shortName = text.shortName\n }\n for (const key of [\n 'description',\n 'productTagline',\n 'companyName',\n ] as const) {\n const value = text?.[key]\n if (typeof value === 'string') {\n resolved.text[key] = value || null\n setTexts.add(key)\n }\n }\n }\n if (!usesBundledImages(resolved.text)) {\n for (const key of EIGHT_WAVE_TEXTS) {\n if (!setTexts.has(key)) {\n resolved.text[key] = null\n }\n }\n }\n return resolved\n}\n\n/** JSON with the keys sorted, so the same content always prints the same. */\nfunction canonicalJson(value: unknown): string {\n if (Array.isArray(value)) {\n return `[${value.map(canonicalJson).join(',')}]`\n }\n if (value && typeof value === 'object') {\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(',')}}`\n }\n return JSON.stringify(value)\n}\n\n/**\n * A short, stable hash of a string: an FNV-1a pass and a multiplicative pass\n * seeded with the length, 32 bits each, in plain code so any runtime computes\n * it the same way without a crypto module. Not a security hash.\n */\nexport function contentHash(input: string): string {\n let a = 0x811c9dc5\n let b = 0x01000193 ^ input.length\n for (let i = 0; i < input.length; i++) {\n const code = input.charCodeAt(i)\n a = Math.imul(a ^ code, 0x01000193) >>> 0\n b = Math.imul(b ^ code, 0x5bd1e995) >>> 0\n }\n return a.toString(16).padStart(8, '0') + b.toString(16).padStart(8, '0')\n}\n\n/**\n * The hash of a theme's content and of the stylesheet rendered from it: the\n * cache key of the clients for the whole theme. A release that renders the\n * same theme differently changes it by itself, with nothing to bump.\n */\nexport function brandingVersion(branding: Branding): string {\n return contentHash(\n `${brandingStylesheetVersion(branding)}:${canonicalJson(branding)}`,\n )\n}\n\n/**\n * Bumped whenever the icons rendered from a mark change: it is part of their\n * URL, which is cached as immutable.\n */\nexport const BRANDING_ICON_REVISION = 1\n\n/** Path of the public theme routes on the backend: the JSON, `.css` and the images. */\nexport const BRANDING_PUBLIC_PATH = '/api/v1/public/branding'\n\n/** Path of a stored theme image on the backend, under `/api/v1`. */\nexport const brandingAssetPath = (checksum: string) =>\n `${BRANDING_PUBLIC_PATH}/assets/${checksum}`\n\n/** Where a stored theme image is served, on a backend URL that may end in a slash. */\nexport const brandingAssetUrl = (backendUrl: string, checksum: string) =>\n `${backendUrl.replace(/\\/+$/, '')}${brandingAssetPath(checksum)}`\n\nconst PUBLIC_BRANDING_ROUTE = new RegExp(\n `^${BRANDING_PUBLIC_PATH}(?:\\\\.css|/manifest\\\\.webmanifest|/icon/(?:\\\\d+|maskable)|/assets/[0-9a-f]{64}(?:/icon/\\\\d+)?)?(?:\\\\?|$)`,\n)\n\n/**\n * Whether a request URL, query included, is one of the public theme routes:\n * the JSON, the stylesheet, the web app manifest, the theme's icons, an image\n * or an icon rendered from one. Anchored on each route, so a route that only\n * shares the prefix is not one of them.\n */\nexport const isPublicBrandingRoute = (url: string) =>\n PUBLIC_BRANDING_ROUTE.test(url)\n\n/**\n * The square icons rendered from an image: the favicon, the apple touch icon\n * and the two of the installed app.\n */\nexport const BRANDING_ICON_SIZES = [32, 180, 192, 512] as const\nexport type BrandingIconSize = (typeof BRANDING_ICON_SIZES)[number]\n\n/**\n * An icon of the theme: one of the sizes, or the installed app's maskable\n * icon, 512 px and opaque, which a launcher crops to its own shape.\n */\nexport type BrandingThemeIcon = BrandingIconSize | 'maskable'\n\n/**\n * Path of the theme's square icon: its mark, the neutral one of a renamed\n * theme without a mark, or a redirect to the frontend's bundled icons.\n */\nexport const brandingThemeIconPath = (icon: BrandingThemeIcon) =>\n `${BRANDING_PUBLIC_PATH}/icon/${icon}`\n\n/** Path of a square icon rendered from a stored image. */\nexport const brandingIconPath = (checksum: string, size: BrandingIconSize) =>\n `${brandingAssetPath(checksum)}/icon/${size}?r=${BRANDING_ICON_REVISION}`\n\n/**\n * The web app manifest of a theme, which the backend serves at\n * `${BRANDING_PUBLIC_PATH}/manifest.webmanifest` to a frontend that reads its\n * theme at runtime: the names, the description and the icons are the theme's.\n * The app is the root of the frontend's origin, as in the build's manifest,\n * written in full since the browser requires it on the page's origin; the\n * icons are relative to the manifest, the theme's icon routes, under its\n * version so a new theme is fetched again.\n */\nexport function brandingManifest(\n branding: ResolvedBranding,\n frontendUrl: string,\n) {\n const app = `${new URL(frontendUrl).origin}/`\n const { productName, shortName, description } = branding.text\n return {\n ...PWA_MANIFEST_BASE,\n id: app,\n name: productName,\n short_name: shortName,\n ...(description ? { description } : {}),\n start_url: app,\n scope: app,\n icons: pwaManifestIcons((icon) => `icon/${icon}?v=${branding.version}`),\n }\n}\n\n/** A theme with its version, as the endpoints serve it. */\nexport function toResolvedBranding(branding: Branding): ResolvedBranding {\n return {\n ...branding,\n version: brandingVersion(branding),\n }\n}\n\n/** The declarations of a palette, or none when any of its colors is invalid. */\nfunction paletteDeclarations(palette: BrandingPalette): string {\n if (!BrandingPaletteSchema.safeParse(palette).success) {\n return ''\n }\n return `--color-brand:${palette.brand};--color-accent:${palette.accent};--color-info:${palette.info};`\n}\n\n/**\n * The stylesheet of a theme: the rules that apply its colors over the design\n * system. The backend serves it, the widget puts it first, and the frontend\n * writes it into its `<style>` element and keeps it for the next load.\n *\n * The rules are not in a cascade layer, so they beat the layered tokens of\n * `@volverjs/style` whatever their specificity, and they target `.theme` as\n * well as `:root` because volver redeclares the tokens on every element with\n * that class (the chat preview stage, the widget roots). Their selectors are\n * in `:where()`, so they carry no specificity of their own: what comes after\n * them wins, the explicit theme classes over the media query (the user's\n * choice) and, in the widget, an agent's custom CSS over the theme.\n * `--color-tint` carries the light brand, which the neutrals derive from in\n * both themes, so it is declared once and never redeclared for dark.\n * A palette with an invalid color is left out whole: half a palette would mix\n * the theme's colors with the defaults.\n */\nexport function renderBrandingCss(branding: Branding): string {\n const light = paletteDeclarations(branding.colors.light)\n const dark = paletteDeclarations(branding.colors.dark)\n const tint = light ? `--color-tint:${branding.colors.light.brand};` : ''\n return [\n `:where(:root,.theme){${light}${tint}}`,\n `@media (prefers-color-scheme: dark){:where(:root:not(.theme--light),.theme:not(.theme--light)){${dark}}}`,\n `:where(.theme.theme--light){${light}}`,\n `:where(.theme.theme--dark){${dark}}`,\n ].join('\\n')\n}\n\n/**\n * The hash of a theme's stylesheet, part of its version (see brandingVersion):\n * a release that renders the same colors differently changes the version, and\n * the frontend writes its stored copy again. It depends on the colors alone,\n * like the stylesheet.\n */\nexport const brandingStylesheetVersion = (branding: Branding) =>\n contentHash(renderBrandingCss(branding))\n","import * as z from 'zod'\n\n/**\n * What the client knows about the device the conversation is happening on.\n *\n * Its own module rather than part of `Chat`: both the chat request and the\n * voice session request carry it, and `Chat` already imports `Agent`, so\n * keeping it there would make the two import each other.\n */\nexport const DeviceContextSchema = z.object({\n dateTime: z.string().optional(),\n timezone: z.string().optional(),\n language: z.string().optional(),\n languages: z.array(z.string()).optional(),\n url: z.string().optional(),\n pathname: z.string().optional(),\n pageTitle: z.string().optional(),\n referrer: z.string().optional(),\n screenWidth: z.number().optional(),\n screenHeight: z.number().optional(),\n viewportWidth: z.number().optional(),\n viewportHeight: z.number().optional(),\n devicePixelRatio: z.number().optional(),\n maxTouchPoints: z.number().optional(),\n hardwareConcurrency: z.number().optional(),\n deviceMemory: z.number().optional(),\n platform: z.string().optional(),\n connectionType: z.string().optional(),\n connectionEffectiveType: z.string().optional(),\n connectionDownlink: z.number().optional(),\n connectionRtt: z.number().optional(),\n saveData: z.boolean().optional(),\n darkMode: z.boolean().optional(),\n reducedMotion: z.boolean().optional(),\n historyLength: z.number().optional(),\n geolocationLatitude: z.number().optional(),\n geolocationLongitude: z.number().optional(),\n geolocationAccuracy: z.number().optional(),\n geolocationCity: z.string().optional(),\n})\n\nexport type DeviceContext = z.infer<typeof DeviceContextSchema>\n","import { z } from 'zod'\n\n// ===== Constants =====\n\nexport const MAX_FILE_SIZE = 100 * 1024 * 1024 // 100MB\n\n/**\n * The largest audio that is transcribed (spec `audio-file-transcription.md`,\n * D2): about seven hours of m4a at 32 kbps, ten minutes of CD quality wav.\n * The SDK sends it as base64 inside a JSON body, so a job holds about four\n * times this in memory. The upload alert\n * (`problemReasons.file-upload-validation.audio-too-large`) states it in MB.\n */\nexport const MAX_AUDIO_FILE_SIZE = MAX_FILE_SIZE\n\n/**\n * The largest audio a chat accepts, whatever the agent's own cap (spec\n * `audio-file-transcription.md`, D4, decided 2026-10-14): the turn transcribes\n * it before the answer starts, and 25 MB (about an hour and forty minutes of\n * m4a at 32 kbps) keeps that wait within a minute or two, short of what a\n * proxy tolerates before the first byte.\n */\nexport const MAX_CHAT_AUDIO_FILE_SIZE = 25 * 1024 * 1024\n\nexport const MIME_TYPE_REGEX = /^[a-z]+\\/[a-z0-9\\-+.]+$/i\n\nexport const SUPPORTED_IMAGE_TYPES = [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'image/svg+xml',\n] as const\n\nexport const SUPPORTED_VIDEO_TYPES = [\n 'video/mp4',\n 'video/webm',\n 'video/ogg',\n] as const\n\n/**\n * The audio a transcription model reads (spec `audio-file-transcription.md`,\n * D2), by every type a browser or a drive declares for it: an m4a arrives as\n * `audio/mp4` or `audio/x-m4a` depending on the system, a wav as any of three.\n * `audio/webm`, what a browser records, waits for a test.\n */\nexport const SUPPORTED_AUDIO_TYPES = [\n 'audio/mpeg',\n 'audio/mp4',\n 'audio/x-m4a',\n 'audio/aac',\n 'audio/wav',\n 'audio/x-wav',\n 'audio/wave',\n 'audio/ogg',\n 'audio/flac',\n 'audio/x-flac',\n] as const\n\n/**\n * Each extension of the audio in {@link SUPPORTED_AUDIO_TYPES} with a type it\n * is declared as: the one table both directions read (spec\n * `voice-notes-platform-channels.md`, D3). From a type to the extension its\n * stored file takes, the first pair with that type; from an extension to the\n * type of a file that came without one (Teams), the first pair with that\n * extension. `.oga` and `.opus` are ogg files no type names apart.\n */\nconst AUDIO_EXTENSION_TYPES: ReadonlyArray<\n readonly [\n extension: string,\n mimeType: (typeof SUPPORTED_AUDIO_TYPES)[number],\n ]\n> = [\n ['.mp3', 'audio/mpeg'],\n ['.m4a', 'audio/mp4'],\n ['.m4a', 'audio/x-m4a'],\n ['.aac', 'audio/aac'],\n ['.wav', 'audio/wav'],\n ['.wav', 'audio/x-wav'],\n ['.wav', 'audio/wave'],\n ['.ogg', 'audio/ogg'],\n ['.oga', 'audio/ogg'],\n ['.opus', 'audio/ogg'],\n ['.flac', 'audio/flac'],\n ['.flac', 'audio/x-flac'],\n]\n\n/** The extensions of {@link SUPPORTED_AUDIO_TYPES}, for a file whose type says nothing. */\nconst AUDIO_EXTENSIONS = new Set(\n AUDIO_EXTENSION_TYPES.map(([extension]) => extension),\n)\n\n/**\n * The extension a stored audio of this bare type takes (`.m4a` for\n * `audio/x-m4a`), or undefined for a type the transcription does not read.\n */\nexport const audioExtensionFor = (mimeType: string): string | undefined =>\n AUDIO_EXTENSION_TYPES.find(([, type]) => type === mimeType)?.[0]\n\n/**\n * The type of an audio named with this extension (`audio/ogg` for `.opus`),\n * or undefined for an extension the transcription does not read.\n */\nexport const audioMimeTypeFor = (extension: string): string | undefined =>\n AUDIO_EXTENSION_TYPES.find(([ext]) => ext === extension.toLowerCase())?.[1]\n\n/** Audio no transcription reads, still to keep away from a model. */\nconst OTHER_AUDIO_EXTENSIONS = new Set([\n '.amr',\n '.3ga',\n '.aif',\n '.aiff',\n '.caf',\n '.m4b',\n '.mka',\n '.weba',\n '.wma',\n])\n\n/** A MIME type without its parameters: `audio/ogg; codecs=opus` is `audio/ogg`. */\nconst bareMimeType = (mimeType?: string): string =>\n mimeType?.split(';')[0]?.trim().toLowerCase() ?? ''\n\nconst hasAudioExtension = (name = ''): boolean =>\n AUDIO_EXTENSIONS.has(getExtensionFromFilename(name))\n\n/**\n * Whether a file is audio of any kind, read or not: what a channel that does\n * not transcribe has to keep away from the model, since most models refuse an\n * audio part and the whole turn with it.\n */\nexport const isAudioFile = (name?: string, mimeType?: string): boolean => {\n const extension = getExtensionFromFilename(name ?? '')\n return (\n bareMimeType(mimeType).startsWith('audio/') ||\n AUDIO_EXTENSIONS.has(extension) ||\n OTHER_AUDIO_EXTENSIONS.has(extension)\n )\n}\n\n/**\n * Whether a file is audio the transcription reads: by its type, else by its\n * extension when the type says nothing (none, `application/octet-stream`) or\n * is another system's name for an audio of ours (`audio/mp3`,\n * `audio/vnd.wave`, `audio/opus`): the model reads the bytes, not the type.\n */\nexport const isTranscribableAudio = (\n name?: string,\n mimeType?: string,\n): boolean => {\n const bare = bareMimeType(mimeType)\n if ((SUPPORTED_AUDIO_TYPES as readonly string[]).includes(bare)) {\n return true\n }\n return (\n (bare === '' ||\n bare === 'application/octet-stream' ||\n bare.startsWith('audio/')) &&\n hasAudioExtension(name)\n )\n}\n\n/**\n * The type a file the transcription reads is handled as (spec\n * `voice-notes-platform-channels.md`, D1): its own without parameters\n * (`audio/ogg; codecs=opus` is `audio/ogg`), or the one its extension names\n * when {@link isTranscribableAudio} took it by the extension. Undefined for a\n * file the transcription does not read.\n */\nexport const transcribableAudioType = (\n name?: string,\n mimeType?: string,\n): string | undefined => {\n if (!isTranscribableAudio(name, mimeType)) {\n return undefined\n }\n const bare = bareMimeType(mimeType)\n return (SUPPORTED_AUDIO_TYPES as readonly string[]).includes(bare)\n ? bare\n : audioMimeTypeFor(getExtensionFromFilename(name ?? ''))\n}\n\n/**\n * Source code and structured text a chat takes as an attachment (the \"Code\"\n * category of an agent's file types, off until the admin turns it on), one\n * row per format: the extensions it goes by, the type it is allowed and\n * stored as, and the other names a browser or a system declares it with\n * (most systems call a `.ts` `video/mp2t`, and many send a `.py` with no type\n * at all). The model reads the content as text, never the file: a provider\n * takes a file part for images and PDFs, plain text at most.\n *\n * A format added here is not allowed on an agent that turned the category on\n * before: the settings show the category off there, until the admin turns it\n * on again.\n */\nconst CODE_FILE_FORMATS: ReadonlyArray<{\n extensions: readonly string[]\n mimeType: string\n aliases: readonly string[]\n}> = [\n { extensions: ['.html', '.htm'], mimeType: 'text/html', aliases: [] },\n { extensions: ['.css'], mimeType: 'text/css', aliases: [] },\n { extensions: ['.scss'], mimeType: 'text/x-scss', aliases: ['text/scss'] },\n {\n extensions: ['.js', '.mjs', '.cjs', '.jsx'],\n mimeType: 'text/javascript',\n aliases: [\n 'application/javascript',\n 'application/x-javascript',\n 'text/jsx',\n ],\n },\n {\n extensions: ['.ts', '.mts', '.cts', '.tsx'],\n mimeType: 'text/x-typescript',\n aliases: [\n 'application/typescript',\n 'application/x-typescript',\n 'text/typescript',\n 'text/tsx',\n 'video/mp2t',\n ],\n },\n { extensions: ['.vue'], mimeType: 'text/x-vue', aliases: [] },\n {\n extensions: ['.json'],\n mimeType: 'application/json',\n aliases: ['text/json', 'text/x-json'],\n },\n {\n extensions: ['.xml'],\n mimeType: 'application/xml',\n aliases: ['text/xml'],\n },\n {\n extensions: ['.yaml', '.yml'],\n mimeType: 'application/yaml',\n aliases: ['application/x-yaml', 'text/yaml', 'text/x-yaml'],\n },\n {\n extensions: ['.toml'],\n mimeType: 'application/toml',\n aliases: ['text/x-toml'],\n },\n {\n extensions: ['.py'],\n mimeType: 'text/x-python',\n aliases: ['text/x-python-script', 'application/x-python'],\n },\n {\n extensions: ['.java'],\n mimeType: 'text/x-java',\n aliases: ['text/x-java-source'],\n },\n { extensions: ['.kt'], mimeType: 'text/x-kotlin', aliases: [] },\n {\n extensions: ['.c', '.h'],\n mimeType: 'text/x-c',\n aliases: ['text/x-csrc', 'text/x-chdr'],\n },\n {\n extensions: ['.cpp', '.cc', '.cxx', '.hpp'],\n mimeType: 'text/x-c++',\n aliases: ['text/x-c++src', 'text/x-c++hdr'],\n },\n { extensions: ['.cs'], mimeType: 'text/x-csharp', aliases: [] },\n { extensions: ['.go'], mimeType: 'text/x-go', aliases: [] },\n {\n extensions: ['.rs'],\n mimeType: 'text/x-rust',\n aliases: ['application/rls-services+xml'],\n },\n {\n extensions: ['.rb'],\n mimeType: 'text/x-ruby',\n aliases: ['application/x-ruby'],\n },\n {\n extensions: ['.php'],\n mimeType: 'text/x-php',\n aliases: ['application/x-php', 'application/x-httpd-php'],\n },\n { extensions: ['.swift'], mimeType: 'text/x-swift', aliases: [] },\n {\n extensions: ['.sql'],\n mimeType: 'application/sql',\n aliases: ['application/x-sql', 'text/x-sql'],\n },\n {\n extensions: ['.sh', '.bash', '.zsh'],\n mimeType: 'text/x-sh',\n aliases: [\n 'application/x-sh',\n 'application/x-shellscript',\n 'text/x-shellscript',\n ],\n },\n]\n\n/** The types of {@link CODE_FILE_FORMATS}, what the \"Code\" category allows. */\nexport const SUPPORTED_CODE_TYPES: readonly string[] = CODE_FILE_FORMATS.map(\n (format) => format.mimeType,\n)\n\n/** The text a chat reads besides code: the \"Text\" category. */\nconst PLAIN_TEXT_TYPES = ['text/plain', 'text/markdown', 'text/csv']\n\n/**\n * Whether the model reads a chat attachment of this type as text: the\n * content goes into the message, the file never reaches the provider.\n */\nexport const isTextAttachmentType = (mimeType?: string): boolean => {\n const bare = bareMimeType(mimeType)\n return (\n PLAIN_TEXT_TYPES.includes(bare) || SUPPORTED_CODE_TYPES.includes(bare)\n )\n}\n\n/**\n * The extension a stored code file of this type takes (`.js` for\n * `text/javascript`), or undefined for a type that is not code.\n */\nexport const codeExtensionFor = (mimeType: string): string | undefined =>\n CODE_FILE_FORMATS.find((format) => format.mimeType === mimeType)\n ?.extensions[0]\n\n/**\n * The extensions of the code types among `mimeTypes`, for a file picker: a\n * browser filters by type, and knows few of these.\n */\nexport const codeExtensionsOf = (mimeTypes: readonly string[]): string[] =>\n CODE_FILE_FORMATS.filter((format) =>\n mimeTypes.includes(format.mimeType),\n ).flatMap((format) => format.extensions)\n\n/**\n * The type a chat upload is checked and stored as: the declared one when the\n * agent allows it. Otherwise, for a file whose extension names a code format\n * the agent allows, that format's type, when the declared one says nothing\n * (none, `application/octet-stream`, `text/plain`) or is another system's name\n * for it. Anything else keeps its declared type, which the allow-list then\n * refuses.\n */\nexport const chatUploadMimeType = (\n name: string | undefined,\n declaredMimeType: string | undefined,\n allowedMimeTypes: readonly string[],\n): string => {\n const bare = bareMimeType(declaredMimeType)\n if (allowedMimeTypes.includes(bare)) {\n return bare\n }\n const extension = getExtensionFromFilename(name ?? '')\n const format = CODE_FILE_FORMATS.find((candidate) =>\n candidate.extensions.includes(extension),\n )\n const saysNothing =\n bare === '' ||\n bare === 'application/octet-stream' ||\n bare === 'text/plain'\n return format &&\n allowedMimeTypes.includes(format.mimeType) &&\n (saysNothing || format.aliases.includes(bare))\n ? format.mimeType\n : (declaredMimeType ?? '')\n}\n\n/**\n * Whether a chat drop zone takes files of these types, read while they are\n * dragged and their names are still unknown: each one allowed, or, when the\n * agent allows code, a type a code file comes with (none,\n * `application/octet-stream`, another system's name for it). The upload\n * decides by the name ({@link chatUploadMimeType}).\n */\nexport const chatDropAccepts = (\n types: readonly string[],\n allowedMimeTypes: readonly string[],\n): boolean => {\n if (allowedMimeTypes.length === 0) {\n return true\n }\n const code = CODE_FILE_FORMATS.filter((format) =>\n allowedMimeTypes.includes(format.mimeType),\n )\n const loose = new Set(\n code.length > 0\n ? [\n '',\n 'application/octet-stream',\n 'text/plain',\n ...code.flatMap((format) => format.aliases),\n ]\n : [],\n )\n return (\n types.length > 0 &&\n types.every(\n (type) =>\n loose.has(bareMimeType(type)) ||\n allowedMimeTypes.some((allowed) => type.includes(allowed)),\n )\n )\n}\n\n/**\n * What a chat turn made of an audio the user attached (spec\n * `audio-file-transcription.md`, D4), kept on its file part\n * (`providerMetadata['8bot'].transcript`) and on its `chat_attachments` row:\n * the transcript in paragraphs opened by their time, or why there is none.\n * `off` is an organization that does not use the platform gateway, where\n * nothing is transcribed and nothing is charged.\n */\nexport const ChatAudioTranscriptSchema = z.object({\n status: z.enum(['ready', 'no-speech', 'failed', 'off']),\n text: z.string().optional(),\n /** ISO 639-1, when the model detected it. */\n language: z.string().optional(),\n durationSeconds: z.number().optional(),\n model: z.string().optional(),\n})\nexport type ChatAudioTranscript = z.infer<typeof ChatAudioTranscriptSchema>\n\n// ===== Enums =====\n\nexport enum StoragePolicy {\n DEFAULT = 'default',\n COLD = 'cold',\n HOT = 'hot',\n ARCHIVE = 'archive',\n}\n\nexport enum PreviewStatus {\n Pending = 'pending',\n Done = 'done',\n Failed = 'failed',\n}\n\n// ===== Storage Handle Schemas =====\n\nconst AzureBlobStorageHandleSchema = z.object({\n type: z.literal('azure-blob'),\n blobUri: z.url(),\n containerName: z.string().min(1),\n pathRelativeToContainer: z.string().min(1),\n})\n\nconst S3StorageHandleSchema = z.object({\n type: z.literal('s3'),\n bucket: z.string().min(1),\n key: z.string().min(1),\n region: z.string().min(1),\n})\n\nconst StorageHandleSchema = z.discriminatedUnion('type', [\n AzureBlobStorageHandleSchema,\n S3StorageHandleSchema,\n])\n\n// ===== Media Upload Schema =====\n\n/**\n * Media upload information for preparing a file upload\n */\nexport const MediaUploadSchema = z.object({\n /** Media type category (picture, video, audio, etc.) */\n type: z.string().min(1),\n /** Original filename */\n name: z.string().min(1),\n /** MIME type (e.g., 'image/jpeg') */\n mimeType: z.string().regex(MIME_TYPE_REGEX),\n /** File size in bytes (must be positive) */\n bytesCount: z.number().positive(),\n /** File extension with dot (e.g., '.jpg') */\n extension: z\n .string()\n .regex(/^\\.[a-zA-Z0-9]+$/)\n .overwrite((ext) => ext.toLowerCase()),\n /** Optional custom stored filename */\n storedFileName: z.string().optional(),\n /** Additional metadata key-value pairs */\n metadata: z.record(z.string(), z.string()).default({}),\n /** Storage tags for categorization */\n tags: z.record(z.string(), z.string()).default({}),\n})\nexport type MediaUpload = z.infer<typeof MediaUploadSchema>\n\n// ===== Media Source Schema =====\n\n/**\n * Complete media source information including storage details\n */\nexport const MediaSourceSchema = MediaUploadSchema.extend({\n /** Storage backend configuration */\n storageHandle: StorageHandleSchema,\n /** Storage tier/policy */\n storagePolicy: z.enum(StoragePolicy),\n /** Optional signature data for verification */\n signData: z.string().optional(),\n /** Actual stored filename (required) */\n storedFileName: z.string().min(1),\n})\nexport type MediaSource = z.infer<typeof MediaSourceSchema>\n\n// ===== Media Schema =====\n\n/**\n * Complete media object with source and optional variants\n */\nexport const MediaSchema = z.object({\n /** Display name for the media */\n name: z.string().min(1),\n /** Primary media source */\n src: MediaSourceSchema,\n /** Optional additional sources (e.g., different resolutions) */\n srcSet: z.array(MediaSourceSchema).default([]),\n /** Type-specific metadata (dimensions, duration, etc.) */\n rawOptions: z.custom<RawOptions>().optional(),\n})\nexport type Media = z.infer<typeof MediaSchema>\n\n// ===== Upload Handle Schema =====\n\n/**\n * Upload handle containing SAS URI and metadata for client-side upload\n */\nexport const MediaUploadHandleSchema = z.object({\n /** Media source information */\n src: MediaSourceSchema,\n /** Upload credentials and metadata */\n uploadHandle: z.object({\n /** Shared Access Signature URI for upload */\n uploadSasuri: z.url(),\n /** Metadata to attach to the blob */\n metadata: z.record(z.string(), z.string()).default({}),\n /** Tags to attach to the blob */\n tags: z.record(z.string(), z.string()).default({}),\n }),\n})\nexport type MediaUploadHandle = z.infer<typeof MediaUploadHandleSchema>\n\n// ===== Download Handle Schema =====\n\n/**\n * Download handle containing SAS URIs for different access patterns\n */\nexport const MediaDownloadHandleSchema = z.object({\n /** Media source information */\n src: MediaSourceSchema,\n /** Download credentials and URIs */\n downloadHandle: z.object({\n /** SAS URI for file download */\n downloadSasuri: z.url(),\n /** SAS URI for inline viewing */\n viewSasuri: z.url(),\n /** Optional SAS URI for preview thumbnail */\n previewSasuri: z.url().optional(),\n /** Expiration timestamp for the SAS URIs */\n expiresOn: z.string().datetime(),\n /** Storage backend type */\n type: z.string(),\n }),\n})\nexport type MediaDownloadHandle = z.infer<typeof MediaDownloadHandleSchema>\n\n// ===== Media Types =====\n\nexport enum MediaType {\n picture = 'picture',\n video = 'video',\n audio = 'audio',\n office = 'office',\n archive = 'archive',\n binary = 'binary',\n executable = 'executable',\n}\n\n// ===== Raw Options Schemas =====\n\nconst PictureRawOptionsSchema = z.object({\n type: z.literal(MediaType.picture),\n width: z.number().positive(),\n height: z.number().positive(),\n blurhash: z.string().optional(),\n})\n\nconst VideoRawOptionsSchema = z.object({\n type: z.literal(MediaType.video),\n width: z.number().positive(),\n height: z.number().positive(),\n duration: z.number().nonnegative(),\n})\n\nconst AudioRawOptionsSchema = z.object({\n type: z.literal(MediaType.audio),\n duration: z.number().nonnegative(),\n})\n\nconst OfficeRawOptionsSchema = z.object({\n type: z.literal(MediaType.office),\n})\n\nconst ArchiveRawOptionsSchema = z.object({\n type: z.literal(MediaType.archive),\n})\n\nconst BinaryRawOptionsSchema = z.object({\n type: z.literal(MediaType.binary),\n})\n\nconst ExecutableRawOptionsSchema = z.object({\n type: z.literal(MediaType.executable),\n})\n\nexport const RawOptionsSchema = z.discriminatedUnion('type', [\n PictureRawOptionsSchema,\n VideoRawOptionsSchema,\n AudioRawOptionsSchema,\n OfficeRawOptionsSchema,\n ArchiveRawOptionsSchema,\n BinaryRawOptionsSchema,\n ExecutableRawOptionsSchema,\n])\n\n// ===== Raw Options Types =====\n\n// ===== Raw Options Types =====\n\nexport type PictureRawOptions = z.infer<typeof PictureRawOptionsSchema>\nexport type VideoRawOptions = z.infer<typeof VideoRawOptionsSchema>\nexport type AudioRawOptions = z.infer<typeof AudioRawOptionsSchema>\nexport type OfficeRawOptions = z.infer<typeof OfficeRawOptionsSchema>\nexport type ArchiveRawOptions = z.infer<typeof ArchiveRawOptionsSchema>\nexport type BinaryRawOptions = z.infer<typeof BinaryRawOptionsSchema>\nexport type ExecutableRawOptions = z.infer<typeof ExecutableRawOptionsSchema>\n\nexport type RawOptions = z.infer<typeof RawOptionsSchema>\n\n// ===== Uploaded File Type =====\n\nexport type UploadedFile<Source = undefined> = Source extends undefined\n ? {\n name: string\n size: number\n type: string\n url: string\n lastModified?: number\n }\n : {\n name: string\n size: number\n type: string\n url: string\n lastModified?: number\n source: Source\n }\n\n// ===== Helper Functions =====\n\n/**\n * Check if a MIME type is a supported image format\n */\nexport const isSupportedImageType = (mimeType: string): boolean => {\n return mimeType.startsWith('image/')\n}\n\n/**\n * Check if a MIME type supports preview generation\n */\nexport const isSupportedPreviewType = (mimeType: string): boolean => {\n return mimeType.startsWith('image/') || mimeType === 'application/pdf'\n}\n\n/**\n * Determine MediaType from MIME type\n */\nexport const getMediaTypeFromMime = (mimeType: string): MediaType => {\n if (mimeType.startsWith('image/')) {\n return MediaType.picture\n }\n if (mimeType.startsWith('video/')) {\n return MediaType.video\n }\n if (mimeType.startsWith('audio/')) {\n return MediaType.audio\n }\n if (\n mimeType.startsWith('application/pdf') ||\n mimeType.startsWith('application/msword') ||\n mimeType.startsWith('application/vnd.openxmlformats') ||\n mimeType.startsWith('application/vnd.ms-')\n ) {\n return MediaType.office\n }\n if (\n mimeType === 'application/zip' ||\n mimeType === 'application/x-rar-compressed' ||\n mimeType === 'application/x-7z-compressed'\n ) {\n return MediaType.archive\n }\n if (\n mimeType.startsWith('application/x-') &&\n mimeType.includes('executable')\n ) {\n return MediaType.executable\n }\n return MediaType.binary\n}\n\n/**\n * Extract file extension from filename\n */\nexport const getExtensionFromFilename = (filename: string): string => {\n const lastDot = filename.lastIndexOf('.')\n return lastDot === -1 ? '' : filename.slice(lastDot).toLowerCase()\n}\n\n/**\n * Format bytes to human-readable string\n */\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) {\n return '0 Bytes'\n }\n const k = 1024\n const dm = decimals < 0 ? 0 : decimals\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`\n}\n\n// ===== Type Guards =====\n\nexport const isPictureOptions = (\n options: RawOptions,\n): options is PictureRawOptions => {\n return options.type === MediaType.picture\n}\n\nexport const isVideoOptions = (\n options: RawOptions,\n): options is VideoRawOptions => {\n return options.type === MediaType.video\n}\n\nexport const isAudioOptions = (\n options: RawOptions,\n): options is AudioRawOptions => {\n return options.type === MediaType.audio\n}\n\nexport const isOfficeOptions = (\n options: RawOptions,\n): options is OfficeRawOptions => {\n return options.type === MediaType.office\n}\n\nexport const isArchiveOptions = (\n options: RawOptions,\n): options is ArchiveRawOptions => {\n return options.type === MediaType.archive\n}\n\nexport const isBinaryOptions = (\n options: RawOptions,\n): options is BinaryRawOptions => {\n return options.type === MediaType.binary\n}\n\nexport const isExecutableOptions = (\n options: RawOptions,\n): options is ExecutableRawOptions => {\n return options.type === MediaType.executable\n}\n","import * as z from 'zod'\nimport { zodQs, jsonSchemaField, decodeOnly } from '../utils'\nimport { DeploymentBrandingSchema, HEX_COLOR_REGEX } from './Branding'\nimport { DeviceContextSchema } from './DeviceContext'\nimport { MediaSchema, MIME_TYPE_REGEX } from './Media'\n\nexport enum AgentStatus {\n Draft = 'draft',\n Active = 'active',\n Inactive = 'inactive',\n}\n\nexport enum AgentVisibility {\n Public = 'public',\n Private = 'private',\n Organization = 'organization',\n}\n\nexport enum AgentType {\n Chat = 'chat',\n Reasoning = 'reasoning',\n}\n\nexport enum AgentSearchMode {\n Semantic = 'semantic',\n Balanced = 'balanced',\n Keyword = 'keyword',\n}\n\n/**\n * Provider-specific reasoning configurations.\n *\n * Four providers have a reasoning API of their own to model:\n * - OpenAI (GPT-5, o-series): `reasoningEffort` + `reasoningSummary`\n * - Anthropic (Claude 4.6+): adaptive thinking with `effort` levels, or legacy `budgetTokens`\n * - Google (Gemini 3/3.1): `thinkingLevel`; Gemini 2.5: `thinkingBudget`\n * - DeepSeek: on/off thinking toggle\n *\n * Alibaba, Meta, Moonshot AI, xAI, Xiaomi and z.ai are one effort level and\n * share {@link GenericReasoningSchema}. Mistral has no configuration at all:\n * of its catalog models only Medium 3.5 (on a `none`/`high` scale) and Large 4\n * reason, so they run on the provider's own default.\n *\n * Only the matching provider's config is used at runtime (based on model prefix).\n * Admins can pre-configure multiple providers for easy model switching.\n */\n\n/**\n * Levels each provider accepts, exported so the agent form builds its fields\n * from the same list the request is validated against. They were written twice,\n * once here and once in the template, and the two drifted: `max` reached the\n * OpenAI API with the 5.6 family and was added to the form for Anthropic only,\n * so an OpenAI agent could not be configured for a level the provider had.\n */\nexport const OPENAI_REASONING_EFFORTS = [\n 'none',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n 'max',\n] as const\nexport const ANTHROPIC_THINKING_EFFORTS = [\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n 'max',\n] as const\nexport const GOOGLE_THINKING_LEVELS = [\n 'minimal',\n 'low',\n 'medium',\n 'high',\n] as const\nexport const OPENAI_REASONING_SUMMARIES = [\n 'auto',\n 'detailed',\n 'concise',\n] as const\n\nexport const OpenAIReasoningSchema = z.object({\n reasoningEffort: z.enum(OPENAI_REASONING_EFFORTS).optional(),\n reasoningSummary: z.enum(OPENAI_REASONING_SUMMARIES).optional(),\n})\nexport type OpenAIReasoning = z.infer<typeof OpenAIReasoningSchema>\n\nexport const AnthropicReasoningSchema = z.object({\n type: z.enum(['adaptive', 'enabled', 'disabled']).optional(),\n effort: z.enum(ANTHROPIC_THINKING_EFFORTS).optional(),\n display: z.enum(['summarized', 'omitted']).optional(),\n budgetTokens: z.number().int().positive().optional(),\n})\nexport type AnthropicReasoning = z.infer<typeof AnthropicReasoningSchema>\n\nexport const GoogleReasoningSchema = z.object({\n thinkingLevel: z.enum(GOOGLE_THINKING_LEVELS).optional(),\n thinkingBudget: z.number().int().optional(),\n includeThoughts: z.boolean().optional(),\n})\nexport type GoogleReasoning = z.infer<typeof GoogleReasoningSchema>\n\nexport const DeepSeekReasoningSchema = z.object({\n type: z.enum(['enabled', 'disabled']).optional(),\n})\nexport type DeepSeekReasoning = z.infer<typeof DeepSeekReasoningSchema>\n\n/**\n * Providers whose whole reasoning configuration is one effort level.\n *\n * They expose no reasoning API of their own to model: the standardized AI SDK\n * effort is the only knob, and the gateway maps it onto whatever each model\n * accepts. One shape covers them all, so a new brand costs a line here instead\n * of a schema, a runtime branch and a form.\n *\n * Verified against the gateway on 2026-08-25: every catalog model of these\n * families advertises the `reasoning` parameter, a family that only offers\n * `high`/`xhigh` clamps a lower level instead of rejecting the request, and\n * `none` does bring reasoning tokens to zero. Xiaomi joined on 2026-09-22 on\n * the listing alone: its models advertise `reasoning` and an effort scale that\n * includes `low`, but the clamp and `none` behaviour were not measured on it.\n */\nexport const GENERIC_REASONING_PROVIDERS = [\n 'alibaba',\n 'meta',\n 'moonshotai',\n 'spacexai',\n 'xiaomi',\n 'zai',\n] as const\n\nexport type GenericReasoningProvider =\n (typeof GENERIC_REASONING_PROVIDERS)[number]\n\nexport function isGenericReasoningProvider(\n provider: string,\n): provider is GenericReasoningProvider {\n return (GENERIC_REASONING_PROVIDERS as readonly string[]).includes(provider)\n}\n\n/**\n * The standardized AI SDK effort union minus `provider-default`, which is what\n * an absent configuration already means: offering it as a value would give the\n * form two ways to say the same thing.\n */\nexport const GENERIC_REASONING_EFFORTS = [\n 'none',\n 'minimal',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n] as const\n\nexport const GenericReasoningSchema = z.object({\n reasoningEffort: z.enum(GENERIC_REASONING_EFFORTS).optional(),\n})\nexport type GenericReasoning = z.infer<typeof GenericReasoningSchema>\n\n/**\n * A legacy value on the target provider's own scale, or `undefined` when that\n * scale cannot express it.\n *\n * The legacy format stored one OpenAI level for every provider and the\n * migration copied it over verbatim, so a value the target enum does not have\n * (`xhigh` on Google, `minimal` on OpenAI) failed the codec's own output\n * validation: reading such an agent threw instead of migrating it. Leaving the\n * provider out instead puts it on the platform default, which is a\n * configuration every provider accepts.\n */\nfunction legacyLevel<T extends string>(\n value: string | undefined,\n accepted: readonly T[],\n): T | undefined {\n return value && (accepted as readonly string[]).includes(value)\n ? (value as T)\n : undefined\n}\n\n/**\n * Migrates legacy format `{ effort: 'high', reasoningSummary: 'auto' }` to the new\n * per-provider format. Applied via preprocess so old DB data auto-migrates on parse.\n */\nconst AgentReasoningObjectSchema = z.object({\n openai: OpenAIReasoningSchema.optional(),\n anthropic: AnthropicReasoningSchema.optional(),\n google: GoogleReasoningSchema.optional(),\n deepseek: DeepSeekReasoningSchema.optional(),\n alibaba: GenericReasoningSchema.optional(),\n meta: GenericReasoningSchema.optional(),\n moonshotai: GenericReasoningSchema.optional(),\n spacexai: GenericReasoningSchema.optional(),\n xiaomi: GenericReasoningSchema.optional(),\n zai: GenericReasoningSchema.optional(),\n})\n\ntype AgentReasoningInput = z.input<typeof AgentReasoningObjectSchema>\n\nfunction migrateReasoningConfig(val: unknown): AgentReasoningInput {\n if (!val || typeof val !== 'object') {\n // Output validity is enforced by the codec's output schema at runtime.\n return val as AgentReasoningInput\n }\n const obj = val as Record<string, unknown>\n // Detect legacy format: has `effort` key with old enum values\n const isAlreadyMigrated = [\n 'openai',\n 'anthropic',\n 'google',\n 'deepseek',\n ...GENERIC_REASONING_PROVIDERS,\n ].some((provider) => provider in obj)\n if ('effort' in obj && !isAlreadyMigrated) {\n const effort = obj.effort as string | undefined\n const reasoningSummary = obj.reasoningSummary as string | undefined\n const migrated: Record<string, unknown> = {}\n\n // `off` is the legacy spelling of \"do not think\", `none` is the same\n // instruction in the vocabulary the providers ended up using: both must\n // reach the branch that disables, or an agent that asked for silence\n // starts reasoning again on every provider that has a default.\n const thinks = !!effort && effort !== 'off' && effort !== 'none'\n if (thinks) {\n const openaiEffort = legacyLevel(effort, OPENAI_REASONING_EFFORTS)\n const summary = legacyLevel(\n reasoningSummary,\n OPENAI_REASONING_SUMMARIES,\n )\n if (openaiEffort || summary) {\n migrated.openai = {\n ...(openaiEffort && { reasoningEffort: openaiEffort }),\n ...(summary && { reasoningSummary: summary }),\n }\n }\n const anthropicEffort = legacyLevel(\n effort,\n ANTHROPIC_THINKING_EFFORTS,\n )\n if (anthropicEffort) {\n migrated.anthropic = {\n type: 'adaptive' as const,\n effort: anthropicEffort,\n }\n }\n // Google's scale stops at `high`: `xhigh` and `max` are OpenAI\n // levels, so they land on the highest level it does have.\n const googleLevel = legacyLevel(\n effort === 'xhigh' || effort === 'max' ? 'high' : effort,\n GOOGLE_THINKING_LEVELS,\n )\n if (googleLevel) {\n migrated.google = { thinkingLevel: googleLevel }\n }\n migrated.deepseek = { type: 'enabled' as const }\n // Same for the single-level providers, whose highest level is\n // `xhigh`.\n const genericEffort = legacyLevel(\n effort === 'max' ? 'xhigh' : effort,\n GENERIC_REASONING_EFFORTS,\n )\n if (genericEffort) {\n for (const provider of GENERIC_REASONING_PROVIDERS) {\n migrated[provider] = { reasoningEffort: genericEffort }\n }\n }\n } else {\n // 'off' must stay off on every provider, not just the two that had\n // an explicit disable. Leaving anthropic and google absent made the\n // runtime send no directive at all (`getReasoningOptions` returns\n // nothing without a provider config), so switching such an agent to\n // Claude or Gemini silently turned thinking back on: the config said\n // off, the model reasoned, and the first token paid for it.\n migrated.openai = { reasoningEffort: 'none' }\n migrated.anthropic = { type: 'disabled' as const }\n // Gemini 3+ cannot disable thinking (the budget is clamped to >= 1),\n // so the lowest level available is what 'off' can mean there.\n migrated.google = { thinkingLevel: 'minimal' as const }\n migrated.deepseek = { type: 'disabled' as const }\n for (const provider of GENERIC_REASONING_PROVIDERS) {\n migrated[provider] = { reasoningEffort: 'none' as const }\n }\n }\n return migrated as AgentReasoningInput\n }\n return val as AgentReasoningInput\n}\n\n// Codec instead of z.preprocess: the legacy-format migration only runs on\n// decode, while encode (used by response serialization) is the identity.\n// `.optional()` wraps the codec (not the inner object) so a missing\n// `reasoning` key still parses, matching the old z.preprocess semantics.\nexport const AgentReasoningSchema = decodeOnly(\n z.unknown(),\n AgentReasoningObjectSchema,\n migrateReasoningConfig,\n).optional()\n\nexport type AgentReasoning = z.infer<typeof AgentReasoningSchema>\n\n/** Provider an agent model belongs to, from its `provider/model` id. */\nexport function modelProvider(model: string): string {\n const [provider = ''] = model.split('/')\n return provider\n}\n\n/**\n * Explicit reasoning configuration for an agent that has none for the provider\n * it is running on.\n *\n * Without it the request carries no reasoning directive at all and the provider\n * applies its own default, which on the current families means thinking is ON:\n * measured on the turn-latency bench, **each reasoning token costs about 8ms of\n * time to first token** (~125 tok/s of decode), so a default nobody chose is\n * worth seconds per turn. The lowest tier that still reasons is the deliberate\n * choice: tool selection and the presentation contract both degrade when a chat\n * agent stops deliberating entirely, and that is a worse trade than the latency\n * it would buy.\n *\n * The single-level providers are here for the same reason, and it is measured\n * on them too: on 2026-08-25 a one-token `hi` sent to `spacexai/grok-4.6` with no\n * directive came back having spent 37 reasoning tokens, and 0 with an explicit\n * `none`. They accept the level (out-of-range clamps, it does not 400), so\n * there is no reason to leave them on a default nobody chose.\n *\n * DeepSeek is deliberately absent: its thinking is model-intrinsic and its\n * configuration here is a bare on/off toggle, with no level to ask for, so a\n * blanket directive could contradict the model itself. It is now the only\n * provider left on the provider's own default, and it stays there until someone\n * measures that family.\n */\nexport const DEFAULT_REASONING_BY_PROVIDER: NonNullable<AgentReasoning> = {\n openai: { reasoningEffort: 'low' },\n anthropic: { type: 'adaptive', effort: 'low' },\n google: { thinkingLevel: 'low' },\n alibaba: { reasoningEffort: 'low' },\n meta: { reasoningEffort: 'low' },\n moonshotai: { reasoningEffort: 'low' },\n spacexai: { reasoningEffort: 'low' },\n xiaomi: { reasoningEffort: 'low' },\n zai: { reasoningEffort: 'low' },\n}\n\n/**\n * Whether a per-provider block actually configures something.\n *\n * A block whose every value is `undefined` says nothing, and it is not a\n * hypothetical: clearing a combobox in the agent settings writes\n * `{ thinkingLevel: undefined }`, which becomes `{}` once the row round-trips\n * through jsonb. Treating that as \"configured\" would leave exactly the agents\n * this default exists for on the provider's own default.\n */\nfunction configuresSomething(config: unknown): boolean {\n return (\n !!config &&\n typeof config === 'object' &&\n Object.values(config).some((value) => value !== undefined)\n )\n}\n\n/**\n * What will actually reach `provider`: the agent's own block when it configures\n * anything, otherwise the platform default.\n *\n * Shared on purpose. The runtime reaches it through\n * {@link resolveEffectiveReasoning}, and the agent form calls it directly to\n * display the value: a form that showed an empty level while the turn sends\n * `low` would describe a behaviour that does not exist.\n *\n * Returns the stored block **by identity** when there is one, so a caller can\n * tell a configured value from a default with `===`.\n */\nexport function effectiveProviderReasoning<\n P extends keyof NonNullable<AgentReasoning>,\n>(\n provider: P,\n reasoning: AgentReasoning | null | undefined,\n): NonNullable<AgentReasoning>[P] {\n const configured = reasoning?.[provider]\n if (configuresSomething(configured)) {\n return configured\n }\n return DEFAULT_REASONING_BY_PROVIDER[provider]\n}\n\n/**\n * The reasoning configuration that will actually reach the provider: the\n * agent's own when it has one for this model's provider, otherwise the explicit\n * default above.\n *\n * Cross-provider is the case that motivated it: an agent configured for OpenAI\n * and switched to Gemini has `reasoning.openai` set and `reasoning.google`\n * empty, so before this it silently inherited Gemini's default.\n */\nexport function resolveEffectiveReasoning(\n model: string,\n reasoning: AgentReasoning | null | undefined,\n): AgentReasoning {\n const provider = modelProvider(model) as keyof NonNullable<AgentReasoning>\n const effective = effectiveProviderReasoning(provider, reasoning)\n // Nothing to add: either the agent configured this provider, or there is no\n // default for it (DeepSeek).\n if (!effective || effective === reasoning?.[provider]) {\n return reasoning ?? undefined\n }\n // Merged, not replaced: the other providers' configurations stay intact for\n // the day the agent is switched back to one of them.\n return { ...reasoning, [provider]: effective }\n}\n\n/**\n * Whether reasoning is effectively enabled for the given model.\n *\n * Mirrors the runtime semantics of `getReasoningOptions` (backend): only the\n * provider config matching the model prefix is considered, and an agent with no\n * config for that provider gets {@link DEFAULT_REASONING_BY_PROVIDER}, exactly\n * as the turn does. Note: for Anthropic with `display: 'omitted'` reasoning runs\n * but no reasoning parts are streamed to the client.\n */\nexport function isReasoningEnabled(\n model: string,\n agentReasoning: AgentReasoning | null | undefined,\n): boolean {\n const reasoning = resolveEffectiveReasoning(model, agentReasoning)\n if (!reasoning) {\n return false\n }\n\n const provider = modelProvider(model)\n\n if (provider === 'openai') {\n const config = reasoning.openai\n return Boolean(\n config?.reasoningEffort && config.reasoningEffort !== 'none',\n )\n }\n\n if (provider === 'anthropic') {\n const config = reasoning.anthropic\n return Boolean(config && config.type !== 'disabled')\n }\n\n if (provider === 'google') {\n const config = reasoning.google\n if (!config || config.thinkingBudget === 0) {\n return false\n }\n return Boolean(\n (config.thinkingLevel && config.thinkingLevel !== 'minimal') ||\n config.thinkingBudget ||\n config.includeThoughts,\n )\n }\n\n if (provider === 'deepseek') {\n return reasoning.deepseek?.type === 'enabled'\n }\n\n if (isGenericReasoningProvider(provider)) {\n const effort = reasoning[provider]?.reasoningEffort\n return Boolean(effort && effort !== 'none')\n }\n\n return false\n}\n\nexport enum AgentBuiltInTool {\n Geocode = 'geocode',\n GetWeather = 'getWeather',\n ReadDocumentFile = 'readDocumentFile',\n RequestConfirm = 'requestConfirm',\n RequestGeolocation = 'requestGeolocation',\n RetrieveRevisedAnswers = 'retrieveRevisedAnswers',\n SearchInKnowledgeBase = 'searchInKnowledgeBase',\n SearchInUserFiles = 'searchInUserFiles',\n UserMemory = 'userMemory',\n /**\n * `readSpreadsheet`, `editSpreadsheet` and `querySpreadsheet`, on a chat\n * with an attached .xlsx.\n */\n Spreadsheet = 'spreadsheet',\n /** `querySpreadsheet` on the spreadsheets of the knowledge base. */\n QuerySpreadsheet = 'querySpreadsheet',\n RunWorker = 'runWorker',\n /** `scheduleWakeup`: the agent resumes this chat by itself after a delay. */\n ScheduleWakeup = 'scheduleWakeup',\n FetchTeamsChannelHistory = 'fetchTeamsChannelHistory',\n ShowArtifact = 'showArtifact',\n ShowCalendarEvent = 'showCalendarEvent',\n ShowComparison = 'showComparison',\n ShowContactForm = 'showContactForm',\n ShowDiagram = 'showDiagram',\n ShowEmail = 'showEmail',\n ShowImageGallery = 'showImageGallery',\n ShowLocation = 'showLocation',\n ShowMessage = 'showMessage',\n ShowForm = 'showForm',\n ShowProductList = 'showProductList',\n ShowQrCode = 'showQrCode',\n ShowSources = 'showSources',\n ShowSuggestedReply = 'showSuggestedReply',\n ShowVideo = 'showVideo',\n ShowWeather = 'showWeather',\n ShowWebPages = 'showWebPages',\n // deprecated tools - to be removed in favor of more specific tools above\n ShowMultipleChoice = 'showMultipleChoice',\n}\n\n/**\n * Prefixes the runtime tool set uses for the tools an agent configures. They are\n * part of a contract shared by three places: the services that build the tool\n * set, the approval list that matches names against it, and the backoffice UI\n * that writes those names. A mismatch is silent (a name matching no tool simply\n * never gates anything), so the prefixes live here and nowhere else.\n */\nexport const MCP_TOOL_PREFIX = 'mcp-'\nexport const API_TOOL_PREFIX = 'api-'\nexport const SUBAGENT_TOOL_PREFIX = 'subagent-'\n\n/** Tool-set key of an MCP tool, from the name the server advertises. */\nexport const mcpToolKey = (toolName: string) => `${MCP_TOOL_PREFIX}${toolName}`\n\n/** Tool-set key of an agent API tool, from its configured name. */\nexport const apiToolKey = (toolName: string) => `${API_TOOL_PREFIX}${toolName}`\n\n/** Tool-set key of a sub-agent, from its camel-cased name. */\nexport const subAgentToolKey = (subAgentName: string) =>\n `${SUBAGENT_TOOL_PREFIX}${subAgentName}`\n\n/**\n * The tool that brings back a group the working set hid (spec\n * tool-catalogue-working-set, F4). Not a built-in the agent switches: it\n * exists exactly when the working set is active and hid something.\n */\nexport const ENABLE_TOOLS_TOOL = 'enableTools'\n\n/**\n * Returns true if the tool can be put behind the user-approval gate\n * (`settings.tools.approval.tools`, see docs/specs/tool-approval-interface.md).\n *\n * Only tools that run server-side qualify: a presentation tool has nothing to\n * approve, and a client-resolved one (geolocation, OAuth connect) already asks\n * the user by construction, since it is the browser or the user who answers it.\n */\nexport function canRequireApproval(toolName: string): boolean {\n return (\n !isPresentationTool(toolName) &&\n toolName !== AgentBuiltInTool.RequestGeolocation\n )\n}\n\n/**\n * Returns true if the tool renders a UI element (card, form, list, etc.).\n * Used in `prepareStep` to prevent duplicate UI elements across streaming steps.\n */\nexport function isPresentationTool(toolName: string): boolean {\n return (\n toolName === AgentBuiltInTool.RequestConfirm ||\n toolName === AgentBuiltInTool.ShowArtifact ||\n toolName === AgentBuiltInTool.ShowCalendarEvent ||\n toolName === AgentBuiltInTool.ShowComparison ||\n toolName === AgentBuiltInTool.ShowContactForm ||\n toolName === AgentBuiltInTool.ShowDiagram ||\n toolName === AgentBuiltInTool.ShowEmail ||\n toolName === AgentBuiltInTool.ShowImageGallery ||\n toolName === AgentBuiltInTool.ShowLocation ||\n toolName === AgentBuiltInTool.ShowMessage ||\n toolName === AgentBuiltInTool.ShowForm ||\n toolName === AgentBuiltInTool.ShowMultipleChoice ||\n toolName === AgentBuiltInTool.ShowProductList ||\n toolName === AgentBuiltInTool.ShowQrCode ||\n toolName === AgentBuiltInTool.ShowSources ||\n toolName === AgentBuiltInTool.ShowSuggestedReply ||\n toolName === AgentBuiltInTool.ShowVideo ||\n toolName === AgentBuiltInTool.ShowWeather ||\n toolName === AgentBuiltInTool.ShowWebPages\n )\n}\n\n/**\n * Tools that render natively as cards on messaging platforms (Teams/WhatsApp).\n * Must mirror the coverage of the backend `platformToolRenderer` (the renderers\n * + the resumable confirm/form and the tappable suggested-reply). Tools not in\n * this set fall back to the model's plain-text reply on those channels.\n */\nexport const PLATFORM_RENDERED_TOOLS = new Set<string>([\n AgentBuiltInTool.RequestConfirm,\n AgentBuiltInTool.ShowArtifact,\n AgentBuiltInTool.ShowWeather,\n AgentBuiltInTool.ShowLocation,\n AgentBuiltInTool.ShowComparison,\n AgentBuiltInTool.ShowProductList,\n AgentBuiltInTool.ShowWebPages,\n AgentBuiltInTool.ShowImageGallery,\n AgentBuiltInTool.ShowVideo,\n AgentBuiltInTool.ShowSources,\n AgentBuiltInTool.ShowSuggestedReply,\n AgentBuiltInTool.ShowCalendarEvent,\n AgentBuiltInTool.ShowEmail,\n AgentBuiltInTool.ShowMessage,\n AgentBuiltInTool.ShowForm,\n])\n\n/** True if the tool renders natively on Teams/WhatsApp (not just web). */\nexport function isPlatformRenderedTool(toolName: string): boolean {\n return PLATFORM_RENDERED_TOOLS.has(toolName)\n}\n\n/**\n * Client tools whose CALL waits for the person to answer it: until they do,\n * the tool loop is suspended and the turn has not said its last word.\n *\n * Every other client tool renders from the call input and is never answered: a\n * sources list, an artifact, a product list have nothing to send back, and the\n * contact form posts its lead through its own endpoint. Two places need that\n * distinction, and both got it wrong before (reported 2026-08-27 on a\n * knowledge-base turn, whose forced sources closure lands in the same step as\n * a form):\n * - the web resume condition (`sendAutomaticallyWhen` in `useChatbotStore`),\n * which must require a tool OUTPUT from these and from nothing else, or the\n * answers the user just submitted stay in the browser;\n * - `computeRequiredClosures` server-side, which owes no closure to a turn left\n * waiting on one of them: the sources of an answer that is still a question.\n *\n * Membership is about what the CALL waits for, not about the surface that\n * renders it: whether the answer comes back as a browser tool output or as a\n * Teams dialog submit makes no difference here, and a spoken turn resolves\n * these tools server-side with a render acknowledgement (`withRenderAck`), so\n * it is never left waiting in the first place.\n *\n * `requestOAuthConnection` is not an `AgentBuiltInTool`: it is injected by the\n * MCP layer, not configured on the agent.\n */\nexport const USER_ANSWERED_TOOLS: ReadonlySet<string> = new Set([\n AgentBuiltInTool.RequestConfirm,\n AgentBuiltInTool.RequestGeolocation,\n AgentBuiltInTool.ShowForm,\n AgentBuiltInTool.ShowMultipleChoice,\n 'requestOAuthConnection',\n])\n\n/** True if this tool's call waits for an answer from the person on the other side. */\nexport function isUserAnsweredTool(toolName: string): boolean {\n return USER_ANSWERED_TOOLS.has(toolName)\n}\n\n/**\n * Transport a turn arrived through. Recorded on the chat metadata and on the\n * latency histograms, and it is what decides {@link ClientToolSurface}: the\n * transport is a fact of the request, not a per-agent setting.\n */\nexport enum ChatTransport {\n /** Web chat and embeddable widget: the reference surface. */\n Web = 'web',\n /** Messaging channels (Teams, WhatsApp) through the platform runner. */\n Platform = 'platform',\n /** OpenAI-compatible REST surface: automations, SDKs. */\n OpenAiApi = 'openai-api',\n /**\n * Spoken conversation: the request arrives on the same OpenAI-compatible\n * surface, but through a voice session opened by us, so the turn knows it\n * will be heard rather than read. Distinct from {@link OpenAiApi} because\n * that is what decides the answer style and what isolates voice in the\n * cost and latency reports.\n */\n Voice = 'voice',\n}\n\n/**\n * What the caller of a turn can actually DO with a client-side tool.\n *\n * Client tools have no `execute`: something on the other side has to render the\n * widget and post the result back. Offering one to a caller that cannot is not\n * a missing nicety, it is a defect with a measured cost: the model spends a\n * full round trip calling it (`showSuggestedReply` on every sample of the\n * turn-latency baseline), the call is never answered, and its guidance sits in\n * the system prompt of every turn.\n */\nexport enum ClientToolSurface {\n /** Full client runtime: every enabled client tool renders. */\n Web = 'web',\n /** Renders only {@link PLATFORM_RENDERED_TOOLS}; the rest never resolve. */\n Platform = 'platform',\n /**\n * Spoken answer, written conversation on screen: the widgets appear when the\n * client reloads the conversation after the turn, so everything that renders\n * without an answer works, and everything that waits for one does not.\n * See {@link VOICE_RENDERED_TOOLS}.\n */\n Voice = 'voice',\n /** No client runtime at all: the caller consumes text (and tool results). */\n Headless = 'headless',\n}\n\n/**\n * Presentation tools that need nothing back from the client DURING the turn.\n *\n * A voice turn is answered through the provider, so no tool call ever reaches\n * the browser live: what reaches it is the persisted message, reloaded when the\n * turn ends. Anything that renders and stops is therefore fine; anything that\n * would suspend the tool loop waiting for the model's answer (a confirmation, a\n * location request, a quick reply) would sit unanswered in a conversation the\n * user is not typing into.\n *\n * The ones that ask the caller something are here too, and they are not an\n * exception to the rule above: none of them answers the tool loop.\n * - the contact form posts its lead through its own endpoint. Asked to be\n * recontacted mid-call, an agent without it can only apologize (reported\n * 2026-08-06, and collecting the lead is what a voice agent is for);\n * - the forms, the quick replies, a confirmation and a position request are\n * answered on screen and go back to the agent as a spoken user message (see\n * {@link VOICE_RENDER_ACK_PREFIX}), so the caller taps and the agent replies\n * out loud, in the same call. On a screen a tap and a sentence are two roads\n * to the same turn.\n */\nexport const VOICE_RENDERED_TOOLS: ReadonlySet<string> = new Set([\n AgentBuiltInTool.RequestConfirm,\n AgentBuiltInTool.RequestGeolocation,\n AgentBuiltInTool.ShowArtifact,\n AgentBuiltInTool.ShowCalendarEvent,\n AgentBuiltInTool.ShowContactForm,\n AgentBuiltInTool.ShowComparison,\n AgentBuiltInTool.ShowDiagram,\n AgentBuiltInTool.ShowEmail,\n AgentBuiltInTool.ShowForm,\n AgentBuiltInTool.ShowImageGallery,\n AgentBuiltInTool.ShowLocation,\n AgentBuiltInTool.ShowMessage,\n AgentBuiltInTool.ShowMultipleChoice,\n AgentBuiltInTool.ShowProductList,\n AgentBuiltInTool.ShowQrCode,\n AgentBuiltInTool.ShowSources,\n AgentBuiltInTool.ShowSuggestedReply,\n AgentBuiltInTool.ShowVideo,\n AgentBuiltInTool.ShowWeather,\n AgentBuiltInTool.ShowWebPages,\n])\n\n/**\n * The provider's own system tool for hanging up: it watches our completion\n * stream for a call by this exact name, speaks its `message` argument and\n * closes the line. Shared here because three places must agree on the spelling:\n * the tool we offer the model, the stream that forwards the call, and the\n * refusal we speak when a turn cannot run at all.\n */\nexport const VOICE_END_CALL_TOOL = 'end_call'\n\n/**\n * Opening of the output a voice turn gives itself for a widget the client draws\n * (see `withRenderAck` in the backend tool set).\n *\n * It is the model's evidence that the screen was written to, and on the client\n * it is the opposite of an answer: a form carrying it has been drawn and not\n * filled in, so it must stay interactive rather than render as answered with\n * this sentence in place of the caller's reply.\n *\n * It is deliberately a label and not a sentence. The wording it replaced,\n * \"Shown on the caller's screen\", was read back by the model as content it had\n * produced: quick replies are acknowledged the same way as a document, so a\n * turn whose only widget was three chips still ended in \"I have prepared a\n * summary on your screen\", with nothing there (measured 2026-08-07, twelve\n * times in one call). What was on screen now comes after the label, per tool.\n */\nexport const VOICE_RENDER_ACK_PREFIX = 'Voice turn note'\n\n/** The pre 2026-08-07 wording, still sitting in persisted conversations. */\nconst LEGACY_VOICE_RENDER_ACK_PREFIX = \"Shown on the caller's screen\"\n\n/**\n * The output {@link VOICE_RENDER_ACK_PREFIX} describes, for one tool.\n *\n * Three shapes, because three things happen. A presentation tool puts something\n * the caller can read on the screen, and the note ends by telling the model not\n * to say its sentence again: being told \"it was drawn\" is exactly what made it\n * restate the whole answer in the next step, heard twice on a call and printed\n * twice in the conversation (measured 2026-08-07). Quick replies put nothing\n * there at all, so their note says so, in the words the model would otherwise\n * use to claim the opposite.\n *\n * Sources are the one card worth naming out loud: on a call nobody is watching\n * the screen, so a silent list is a list nobody opens. Their note grants ONE\n * short mention, and the grant stays narrow (no reading the list, no naming\n * documents, no restating the answer) because the wording that let the model\n * talk freely about the screen is the wording that made it invent what was on\n * it.\n *\n * That note is the secondary lever, not the main one: in the turn shape the\n * voice prompt asks for (spoken sentence and presentation call in the SAME\n * reply) the model never reads it, because the turn ends on that very step.\n * The spoken mention is therefore asked for in `<voice_turn>` as well, where\n * it costs no round trip; this note covers only the turns that go on after the\n * tool.\n */\nexport const voiceRenderAck = (toolName: string): string => {\n if (toolName === AgentBuiltInTool.ShowSuggestedReply) {\n return `${VOICE_RENDER_ACK_PREFIX} (${toolName}): the quick replies are attached to your message. They are taps, not content: NOTHING was written on the caller's screen by this call, so do not say you showed, prepared, summarized or wrote anything, and do not mention the replies out loud.`\n }\n if (toolName === AgentBuiltInTool.ShowSources) {\n return `${VOICE_RENDER_ACK_PREFIX} (${toolName}): the sources of the answer you just gave are listed in the chat, where the caller can read them. If you have not said so already, you MAY tell them once, in a few words. Nothing more: do not read the list out loud, do not name the documents, and do not repeat or summarize the answer itself.`\n }\n return `${VOICE_RENDER_ACK_PREFIX} (${toolName}): drawn in the conversation, where the caller can read it. You have already said your sentence out loud: do not say it again, either add something new or stop here.`\n}\n\n/** True when a tool output is our own \"it was drawn\" note and not a result. */\nexport function isVoiceRenderAck(output: unknown): boolean {\n return (\n typeof output === 'string' &&\n (output.startsWith(VOICE_RENDER_ACK_PREFIX) ||\n output.startsWith(LEGACY_VOICE_RENDER_ACK_PREFIX))\n )\n}\n\n/** True if the tool shows something on screen during a call and needs no reply. */\nexport function isVoiceRenderedTool(toolName: string): boolean {\n return VOICE_RENDERED_TOOLS.has(toolName)\n}\n\n/** Single availability rule for a client tool, shared by tool set and prompt. */\nexport function supportsClientTool(\n surface: ClientToolSurface,\n toolName: string,\n): boolean {\n if (surface === ClientToolSurface.Headless) {\n return false\n }\n if (surface === ClientToolSurface.Platform) {\n return isPlatformRenderedTool(toolName)\n }\n if (surface === ClientToolSurface.Voice) {\n return isVoiceRenderedTool(toolName)\n }\n return true\n}\n\n/**\n * Surface of a transport. Unknown transports are treated as Web, which is the\n * historical behaviour: a new caller has to opt into being headless, so adding\n * one can never silently strip the widgets from an existing channel.\n */\nexport function clientToolSurfaceOf(\n transport: ChatTransport | string | undefined,\n): ClientToolSurface {\n switch (transport) {\n case ChatTransport.OpenAiApi:\n return ClientToolSurface.Headless\n // Voice is not headless: the caller hears the answer and reads the same\n // conversation on screen, where the client reloads it once the turn is\n // over. The provider never sees the tool calls (they are not forwarded\n // on the callback stream), the persisted message carries them.\n case ChatTransport.Voice:\n return ClientToolSurface.Voice\n case ChatTransport.Platform:\n return ClientToolSurface.Platform\n default:\n return ClientToolSurface.Web\n }\n}\n\n/**\n * True when nobody is watching the response render: the transport delivers text\n * to a program (or to a speech synthesizer), so anything that paces the stream\n * for the human eye is pure added latency.\n */\nexport function isHeadlessTransport(\n transport: ChatTransport | string | undefined,\n): boolean {\n // Voice counts here even though it renders widgets: nobody watches the\n // stream arrive, a synthesizer consumes it, and the widgets appear with the\n // reload at the end of the turn. Pacing the deltas would only delay speech.\n return (\n transport === ChatTransport.Voice ||\n clientToolSurfaceOf(transport) === ClientToolSurface.Headless\n )\n}\n\n/**\n * Shape of the forms `showForm` asks for. Both values GUIDE the model from the\n * tool's descriptions: they are not bounds of its inputSchema, because a cap\n * there refuses the whole call instead of trimming it and there is no repair\n * for it (see `showForm.tool.ts` and the gotchas entry \"A configurable cap does\n * not belong in an inputSchema\"). Their own `.max(10)` is what the tool keeps\n * as its hard ceiling, so a configuration can reach it but never exceed it.\n */\nexport const AgentFormSettingsSchema = z.object({\n maxSteps: z.number().int().min(1).max(10).optional().default(5),\n maxOptionsPerStep: z.number().int().min(2).max(10).optional().default(5),\n})\nexport type AgentFormSettings = z.infer<typeof AgentFormSettingsSchema>\n\n/*\n * The two closure \"mode\" settings (suggestedReply.mode and showSources.mode)\n * were removed on 2026-09-01. Neither said what it looked like it said: the\n * prompt demands both closures whenever their tool is enabled, so the mode\n * only decided whether the SERVER repaired an omission, and nobody wants an\n * agent configured to leave the user without the widget the prompt promised.\n * A closure is unavailable by disabling its tool, as for any other tool.\n * showSources is therefore repaired on every answered turn that used the\n * knowledge base (it fired 321 times in the 7 days to 2026-09-01), and\n * showSuggestedReply is drawn whenever the model calls it with its answer (see\n * `createClosureAcceptance` in the backend), never synthesized.\n * Zod strips unknown keys, so the values still stored in `settings` are\n * ignored on read and disappear on the next save.\n */\n\nexport const DEFAULT_MAX_STEP_COUNT = 10\nexport const DEFAULT_SUB_AGENT_MAX_STEP_COUNT = 6\nexport const DEFAULT_ENDPOINT_MAX_STEP_COUNT = 5\n\n/**\n * Ceiling on the tool steps of a SPOKEN turn, whatever the agent allows in\n * writing.\n *\n * Every step is another round trip carrying the whole accumulated context, and\n * the caller hears all of it as silence. Six is what a call can spend: enough\n * for a retrieval, a check and a widget, and short of the marathons that reach\n * a minute (measured 2026-08-07: a turn that searched for about fifty seconds\n * was dropped by the provider with \"Generating the LLM response took too long\",\n * and the caller heard the waiting sentence four times and no answer).\n */\nexport const VOICE_MAX_STEP_COUNT = 6\n\nexport enum WebSearchProvider {\n Perplexity = 'perplexity',\n Parallel = 'parallel',\n Native = 'native',\n}\n\nexport const PerplexitySearchConfigSchema = z.object({\n maxResults: z.number().int().min(1).max(20).optional(),\n maxTokens: z.number().int().positive().max(1_000_000).optional(),\n maxTokensPerPage: z.number().int().positive().optional(),\n country: z.string().max(2).optional(),\n searchLanguageFilter: z.array(z.string().max(5)).max(10).optional(),\n searchDomainFilter: z.array(z.string()).max(20).optional(),\n searchRecencyFilter: z.enum(['day', 'week', 'month', 'year']).optional(),\n})\nexport type PerplexitySearchConfig = z.infer<\n typeof PerplexitySearchConfigSchema\n>\n\nexport const ParallelSearchConfigSchema = z.object({\n mode: z.enum(['one-shot', 'agentic']).optional(),\n maxResults: z.number().int().min(1).max(20).optional(),\n sourcePolicy: z\n .object({\n includeDomains: z.array(z.string()).optional(),\n excludeDomains: z.array(z.string()).optional(),\n afterDate: z.string().optional(),\n })\n .optional(),\n excerpts: z\n .object({\n maxCharsPerResult: z.number().int().positive().optional(),\n maxCharsTotal: z.number().int().positive().optional(),\n })\n .optional(),\n fetchPolicy: z\n .object({\n maxAgeSeconds: z.number().int().positive().optional(),\n })\n .optional(),\n})\nexport type ParallelSearchConfig = z.infer<typeof ParallelSearchConfigSchema>\n\nexport const NativeWebSearchConfigSchema = z.object({\n openai: z.object({}).optional(),\n anthropic: z\n .object({\n maxUses: z.number().int().positive().optional(),\n allowedDomains: z.array(z.string()).optional(),\n blockedDomains: z.array(z.string()).optional(),\n userLocation: z\n .object({\n type: z.literal('approximate').optional(),\n country: z.string().optional(),\n region: z.string().optional(),\n city: z.string().optional(),\n timezone: z.string().optional(),\n })\n .optional(),\n })\n .optional(),\n google: z.object({}).optional(),\n})\nexport type NativeWebSearchConfig = z.infer<typeof NativeWebSearchConfigSchema>\n\nexport const AgentWebSearchSchema = z.object({\n enabled: z.boolean().default(false),\n provider: z\n .enum(WebSearchProvider)\n .optional()\n .default(WebSearchProvider.Native),\n perplexity: PerplexitySearchConfigSchema.optional(),\n parallel: ParallelSearchConfigSchema.optional(),\n native: NativeWebSearchConfigSchema.optional(),\n})\nexport type AgentWebSearch = z.infer<typeof AgentWebSearchSchema>\n\n// Cross-agent personalization sub-options. Default OFF = current agent-bound\n// behavior. Only meaningful when the parent tool (UserMemory / SearchInUserFiles)\n// is enabled in `disabled`.\nexport const AgentUserMemorySchema = z.object({\n // Read the user's memories across all their agents of this organization\n // (aggregated), not just this agent's, and never another organization's.\n // Writes stay per-agent (scope='agent').\n useAllUserKb: z.boolean().default(false),\n})\nexport type AgentUserMemory = z.infer<typeof AgentUserMemorySchema>\n\nexport const AgentUserFilesSchema = z.object({\n // Search ALL the user's files, not just those pinned to this agent\n // (or globally shared agent_id IS NULL).\n useAllUserFiles: z.boolean().default(false),\n})\nexport type AgentUserFiles = z.infer<typeof AgentUserFilesSchema>\n\n/**\n * Human-in-the-loop approval settings. Lists the tools whose calls must be\n * approved by the user before they execute. Names are matched against the tool\n * set of the turn, so any tool can be listed: built-in (`sendEmail`), API tools\n * (`api-<name>`) and MCP tools (`mcp-<server>_<tool>`).\n *\n * The gate is UX, not security: it only suspends execution on interactive\n * channels. On non-interactive ones (messaging platforms, API, scheduled runs)\n * a listed tool is denied instead of hanging forever, see `toolApproval.ts`.\n */\nexport const AgentToolApprovalSchema = z.object({\n tools: z.array(z.string()).default([]),\n})\nexport type AgentToolApproval = z.infer<typeof AgentToolApprovalSchema>\n\nexport const AgentToolsSchema = z.object({\n // New agents start with user memory, user-files search, the generic\n // worker and the wakeups OFF (opt-in). Existing agents keep whatever\n // `disabled` they stored: a migration has to add a new opt-in tool there.\n disabled: z\n .array(z.enum(AgentBuiltInTool))\n .default([\n AgentBuiltInTool.UserMemory,\n AgentBuiltInTool.SearchInUserFiles,\n AgentBuiltInTool.RunWorker,\n AgentBuiltInTool.FetchTeamsChannelHistory,\n AgentBuiltInTool.ScheduleWakeup,\n ]),\n showForm: AgentFormSettingsSchema.optional().default(() =>\n AgentFormSettingsSchema.parse({}),\n ),\n webSearch: AgentWebSearchSchema.optional().default(() =>\n AgentWebSearchSchema.parse({}),\n ),\n userMemory: AgentUserMemorySchema.optional().default(() =>\n AgentUserMemorySchema.parse({}),\n ),\n userFiles: AgentUserFilesSchema.optional().default(() =>\n AgentUserFilesSchema.parse({}),\n ),\n approval: AgentToolApprovalSchema.optional().default(() =>\n AgentToolApprovalSchema.parse({}),\n ),\n})\nexport type AgentTools = z.infer<typeof AgentToolsSchema>\n\n/**\n * Ranking configuration schema for smart chunk retrieval.\n * Controls freshness boost, document priority, and MMR.\n * Semantic deduplication is always applied at sync time (not configurable per-agent).\n */\nexport const AgentRankingSchema = z\n .object({\n freshness: z\n .object({\n enabled: z.boolean().default(false),\n /** Half-life in seconds (1 day – 1 year) */\n scale: z\n .number()\n .int()\n .min(86400)\n .max(31536000)\n .default(7776000),\n /** Weight multiplier for freshness boost in formula */\n weight: z.number().min(0.05).max(0.5).default(0.1),\n })\n .prefault({}),\n priority: z\n .object({\n /** Always enabled by default — priority is per-document, not per-agent */\n enabled: z.boolean().default(true),\n })\n .prefault({}),\n mmr: z\n .object({\n enabled: z.boolean().default(false),\n /** Diversity tradeoff (0.0 = relevance only, 1.0 = diversity only) */\n diversity: z.number().min(0.0).max(1.0).default(0.3),\n /**\n * Candidates pre-selected before MMR. Capped at 100: in\n * balanced mode the RRF fusion of two 50-candidate prefetch\n * legs can never yield more. The pool is diversified by\n * Qdrant's native MMR, so no vector crosses the wire for it\n * (it used to, at 38 KB each, when MMR ran in JavaScript).\n */\n candidatesLimit: z.number().int().min(20).max(100).default(50),\n })\n .prefault({}),\n })\n .prefault({})\nexport type AgentRanking = z.infer<typeof AgentRankingSchema>\n\nexport const AgentModelSchema = z.object({\n prompt: z.string().optional(),\n temperature: z.number().min(0).max(2).optional().default(0.6),\n maxOutputTokens: z.number().positive().optional(),\n presencePenalty: z.number().min(-2).max(2).optional(),\n frequencyPenalty: z.number().min(-2).max(2).optional(),\n searchMode: z\n .enum(AgentSearchMode)\n .optional()\n .default(AgentSearchMode.Balanced),\n limit: z.number().positive().max(100).optional().default(10),\n maxStepCount: z\n .number()\n .int()\n .min(1)\n .max(40)\n .optional()\n .default(DEFAULT_MAX_STEP_COUNT),\n reasoning: AgentReasoningSchema,\n /** Smart ranking configuration (freshness, priority, MMR) */\n ranking: AgentRankingSchema.optional().default(() =>\n AgentRankingSchema.parse({}),\n ),\n})\nexport type AgentModel = z.infer<typeof AgentModelSchema>\n\nexport const LocalizedStringSchema = decodeOnly(\n z.unknown(),\n z.record(z.string(), z.string()),\n // Output validity is enforced by the codec's output schema at runtime.\n (val) =>\n (typeof val === 'string' ? { it: val } : val) as Record<string, string>,\n)\nexport type LocalizedString = z.infer<typeof LocalizedStringSchema>\n\nexport const DEFAULT_WIDGET_URL =\n 'https://cdn.jsdelivr.net/npm/@8wave/ai-elements/dist/ai-elements.es.js'\n\nexport enum AgentLoaderStrategy {\n InlineModule = 'inline-module',\n ScriptSrc = 'script-src',\n DynamicImport = 'dynamic-import',\n}\n\nexport enum AgentChannel {\n Frontoffice = 'frontoffice',\n App = 'app',\n Widget = 'widget',\n}\n\nexport const ALL_AGENT_CHANNELS = Object.values(AgentChannel) as AgentChannel[]\n\n/** A host name: labels of letters, digits and hyphens, joined by dots. */\nconst IMAGE_HOST_PATTERN = /^(?=.{1,253}$)([a-z0-9-]+\\.)*[a-z0-9-]+$/\n\n/**\n * An image host as an agent lists it: lower case, without scheme, port or\n * path, so `https://Images.Example.com/a.png` and `images.example.com` are the\n * same entry and compare equal to `URL.hostname`.\n */\nexport function normalizeImageHost(value: string): string {\n const trimmed = value.trim().toLowerCase()\n if (!trimmed) {\n return ''\n }\n try {\n return new URL(trimmed.includes('://') ? trimmed : `https://${trimmed}`)\n .hostname\n } catch {\n return trimmed\n }\n}\n\nexport const AgentInterfaceSchema = z.object({\n media: MediaSchema.optional(),\n logo: z.string().optional(),\n theme: z.enum(['light', 'dark', 'auto']).optional().default('auto'),\n mainColor: z.string().regex(HEX_COLOR_REGEX).optional().default('#000000'),\n textColor: z.enum(['auto', 'white', 'black']).optional().default('auto'),\n useColorsForAgentHeader: z.boolean().optional().default(false),\n initialMessage: LocalizedStringSchema.optional(),\n greeting: z.array(LocalizedStringSchema).min(1).max(10).optional(),\n messagePlaceholder: LocalizedStringSchema.optional(),\n dismissableNotice: LocalizedStringSchema.optional(),\n footerMessage: LocalizedStringSchema.optional(),\n privacyPolicyNotice: LocalizedStringSchema.optional(),\n /**\n * (A) Voluntary self-service sign-in for anonymous users of PUBLIC agents.\n * When false, the in-chat \"sign in\" menu item and the `view-auth` slot are\n * hidden. Does not touch the external token flow, nor the required login\n * gate of private/organization agents (there it is a no-op). Default true\n * for backward compatibility.\n */\n interactiveLogin: z.boolean().optional().default(true),\n welcomePopup: z.boolean().optional().default(false),\n floatingButtonPosition: z\n .enum(['left', 'right'])\n .optional()\n .default('right'),\n maxMessageLength: z.number().int().positive().optional(),\n widgetUrl: z.url().default(DEFAULT_WIDGET_URL),\n loadDelay: z.number().int().min(0).max(30000).optional().default(0),\n loaderStrategy: z\n .enum(AgentLoaderStrategy)\n .optional()\n .default(AgentLoaderStrategy.InlineModule),\n customCss: z.string().optional(),\n smoothStream: z.boolean().optional().default(false),\n /**\n * Show every agent step (reasoning, tool calls) as an expanded timeline\n * in the chat instead of the compact activity indicator. Only meaningful\n * when reasoning is enabled on the agent model.\n */\n showExtendedSteps: z.boolean().optional().default(false),\n /**\n * Hosts an answer or a tool card may load images from by itself, besides\n * the platform's own (hole 20 of docs/specs/organization-isolation.md).\n * The model writes those urls, and a prompt injected through a document\n * or a tool result can carry text out in one: an image from any other\n * host waits for a click. Kept as bare host names, see\n * {@link normalizeImageHost}.\n */\n imageHosts: z\n .array(\n z\n .string()\n .overwrite(normalizeImageHost)\n .refine(\n (host) => host === '' || IMAGE_HOST_PATTERN.test(host),\n { message: 'Enter a host name, like images.example.com' },\n ),\n )\n .overwrite((hosts) => [...new Set(hosts.filter(Boolean))])\n .default([]),\n})\nexport type AgentInterface = z.infer<typeof AgentInterfaceSchema>\n\nexport const CHAT_FILE_UPLOAD_DEFAULT_MIME_TYPES = [\n 'image/jpeg',\n 'image/png',\n 'image/gif',\n 'image/webp',\n 'application/pdf',\n 'text/plain',\n 'text/markdown',\n 'text/csv',\n] as const\n\nexport type ChatFileUploadMimeType =\n (typeof CHAT_FILE_UPLOAD_DEFAULT_MIME_TYPES)[number]\n\n/**\n * An Excel workbook (.xlsx). Opt-in, never in the defaults: an agent accepts it\n * when its admin turns spreadsheets on, and the model then reads and edits it\n * through the spreadsheet tools instead of receiving the file (spec\n * `chat-spreadsheet-editing.md`).\n */\nexport const SPREADSHEET_MIME_TYPE =\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\n\nexport const CHAT_FILE_UPLOAD_MAX_FILE_SIZE_BYTES = 104_857_600 // 100 MB\n\nexport const AgentFileUploadSchema = z.object({\n enabled: z.boolean().default(false),\n maxFileSizeBytes: z\n .number()\n .int()\n .positive()\n .max(CHAT_FILE_UPLOAD_MAX_FILE_SIZE_BYTES)\n .optional()\n .default(20_971_520),\n allowedMimeTypes: z\n .array(z.string().regex(MIME_TYPE_REGEX))\n .optional()\n .default([...CHAT_FILE_UPLOAD_DEFAULT_MIME_TYPES]),\n maxFilesPerMessage: z\n .number()\n .int()\n .positive()\n .max(10)\n .optional()\n .default(5),\n maxFilesPerChat: z.number().int().positive().max(50).optional().default(20),\n})\nexport type AgentFileUpload = z.infer<typeof AgentFileUploadSchema>\n\nexport const AgentGatewayOptionsSchema = z.object({\n zeroDataRetention: z.boolean().default(true),\n disallowPromptTraining: z.boolean().default(true),\n providerTimeoutMs: z.number().int().min(1000).max(789000).optional(),\n})\nexport type AgentGatewayOptions = z.infer<typeof AgentGatewayOptionsSchema>\n\n/**\n * Exposure of the agent through the OpenAI-compatible surface\n * (`/api/openai/v1`), where any third-party client that speaks chat\n * completions can consume it as if it were a model. Off by default: turning it\n * on makes the agent reachable with an organization API key.\n */\nexport const AgentOpenAiApiSchema = z.object({\n enabled: z.boolean().default(false),\n})\nexport type AgentOpenAiApi = z.infer<typeof AgentOpenAiApiSchema>\n\n/**\n * Working set of the tool catalogue (spec tool-catalogue-working-set, F4):\n * before the first step an evaluation model decides which MCP servers, API\n * tools and sub-agents the turn needs, and the model sees only those plus a\n * tool to enable the others.\n * - `off`: every tool is exposed, as before;\n * - `shadow`: the decision is taken and recorded on the message, every tool\n * is still exposed, so it can be read against the tools the model called;\n * - `active`: the decision is applied.\n *\n * The evaluation model is served only by the gateway: the setting needs the\n * organization's `gateway` feature, and an agent on the organization's own\n * endpoint keeps it off.\n */\nexport enum AgentToolWorkingSetMode {\n Off = 'off',\n Shadow = 'shadow',\n Active = 'active',\n}\n\nexport const AgentToolWorkingSetSchema = z.object({\n mode: z.enum(AgentToolWorkingSetMode).default(AgentToolWorkingSetMode.Off),\n})\nexport type AgentToolWorkingSet = z.infer<typeof AgentToolWorkingSetSchema>\n\n/**\n * Shortest first-token deadline the provider actually honours. Below it the\n * turn does not fall back on their model, it fails outright with \"LLM Cascade\n * Error: Brain returned no response\" (production, 2026-08-27).\n */\nexport const VOICE_MIN_CASCADE_TIMEOUT_SECONDS = 5\n\n/** And the longest they accept: their own ceiling, measured 2026-08-06. */\nexport const VOICE_MAX_CASCADE_TIMEOUT_SECONDS = 15\n\n/**\n * Name prefix of the API key the voice channel mints for the provider's\n * callbacks, in the name of the agent's creator. It is how a key list tells\n * that key apart: revoking it silences the agent's voice until the voice is\n * turned off and on again, which mints a new one.\n */\nexport const VOICE_API_KEY_NAME_PREFIX = '[voice] '\n\n/**\n * Voice conversation through ElevenLabs Agents, which provides the voice layer\n * (ASR, turn taking, barge-in, TTS) and calls back into our own turn as a\n * custom LLM on `/api/openai/v1`. Everything that makes the turn worth having\n * (RAG, MCP, memory, credits, persistence) therefore stays where it already is.\n *\n * The provider-side agent is created and kept in sync by the backend, so\n * `providerAgentId` is written by us and is not part of the editable surface.\n * See docs/specs/voice-channel.md.\n */\nexport const AgentVoiceSchema = z.object({\n enabled: z.boolean().default(false),\n /** Provider voice id. Empty means the provider default. */\n voiceId: z.string().optional(),\n /** Language passed to the provider's ASR and TTS. */\n language: z.string().min(2).max(5).default('it'),\n /** Hard server-side cap on a single voice session. */\n maxSessionSeconds: z.number().int().min(30).max(3600).default(600),\n /**\n * How long the provider waits for our first token before falling back to\n * its own model.\n *\n * It has to cover more than the model: our first byte goes out only once\n * the turn has been SET UP (agent read, credit, session, prompt, tool\n * loading, and MCP servers are the slow part), so everything before the\n * first chunk counts against this deadline. Ten seconds was not enough for\n * a heavy agent in production (2026-08-27), so the default is now the\n * provider's own ceiling and the room to go lower is a knob, not a\n * default.\n *\n * Never below {@link VOICE_MIN_CASCADE_TIMEOUT_SECONDS}. Clamped rather\n * than refused, because agents were saved with less before we knew: a\n * stored 3 must keep the voice working, not fail every session on\n * validation.\n */\n cascadeTimeoutSeconds: z\n .number()\n .min(1)\n .max(VOICE_MAX_CASCADE_TIMEOUT_SECONDS)\n .default(VOICE_MAX_CASCADE_TIMEOUT_SECONDS)\n .transform((seconds) =>\n Math.max(VOICE_MIN_CASCADE_TIMEOUT_SECONDS, seconds),\n ),\n /**\n * Seconds before the agent says it is working, while the real answer is\n * still coming. Spoken by our own stream, not by the provider: measured on\n * 2026-08-06, a turn that retrieves takes far longer than any deadline they\n * accept, and the keepalive that keeps it alive also disarms their filler.\n * Four seconds when left empty, which a fast turn never reaches.\n */\n fillerAfterSeconds: z.number().min(0.5).max(8).optional(),\n /**\n * Said while waiting. Empty means a default sentence in the agent's voice\n * language (\"Un attimo, sto controllando\").\n */\n fillerMessage: z.string().max(200).optional(),\n /**\n * Ignore voices that are not the person talking to the agent. Off on the\n * provider side, which in a room with other people (or a television) leaves\n * the turn open on noise: the agent hears \"someone is still speaking\" and\n * waits. On by default here, because the browser is rarely a quiet booth.\n */\n ignoreBackgroundVoices: z.boolean().default(true),\n /**\n * How readily the provider decides the user has finished speaking.\n * `eager` cuts the wait at the price of interrupting a slow speaker,\n * `patient` is for people who pause mid-sentence.\n */\n turnEagerness: z.enum(['patient', 'normal', 'eager']).default('normal'),\n /**\n * How long the agent waits for speech before taking the turn back. The\n * provider default is 7 seconds, which is the silence that reads as \"it\n * hung\": 5 still leaves room to think.\n */\n turnTimeoutSeconds: z.number().min(1).max(30).default(5),\n /**\n * Spoken as soon as the session opens, before the user says anything. It\n * also covers the cold start of the first turn, which is the slowest one\n * (measured p50 4598ms against 2592ms for the rest).\n */\n firstMessage: z.string().max(300).optional(),\n /** Id of the provider-side agent, written by the backend on sync. */\n providerAgentId: z.string().optional(),\n /**\n * Id of the provider-side secret holding the API key it calls us back with.\n * The key itself is never stored here, nor anywhere else on our side.\n */\n providerSecretId: z.string().optional(),\n /**\n * Our own id for that API key, kept so it can be revoked when the voice is\n * turned off or the agent is deleted. Without it the key is unreachable:\n * the value never comes back from the provider, and nothing else on the row\n * says which of the organization's keys belongs to this agent's voice.\n */\n providerApiKeyId: z.string().optional(),\n})\nexport type AgentVoice = z.infer<typeof AgentVoiceSchema>\n\n/**\n * What a chat client needs to know about voice: whether it is offered. The voice\n * id, the timeouts and the provider ids stay server-side, so this is also what\n * the public agent payload carries. Structurally a subset of\n * {@link AgentVoiceSchema}, so a backoffice caller can pass the full block.\n */\nexport const AgentVoiceCapabilitySchema = z.object({\n enabled: z.boolean(),\n})\nexport type AgentVoiceCapability = z.infer<typeof AgentVoiceCapabilitySchema>\n\n/** Body of a voice session request: which conversation to talk into. */\nexport const VoiceSessionRequestSchema = z.object({\n /**\n * Conversation the spoken turns are persisted into. Optional: without one\n * the backend opens a new conversation and returns its id, which is what\n * makes the switch back to typing land in the same thread.\n */\n chatId: z.string().min(1).optional(),\n /**\n * The browser the call is made from, sent once when the session opens and\n * then stamped on every spoken turn.\n *\n * A spoken turn reaches the backend from the voice provider, not from this\n * browser, so it is the only chance to know the device: without it the same\n * conversation shows the context of what the person typed and nothing at\n * all for what they said.\n */\n deviceContext: DeviceContextSchema.optional(),\n /**\n * What the host application knows about this visitor, sent once for the\n * same reason as {@link VoiceSessionRequestSchema.shape.deviceContext}: the\n * turn arrives from the provider and carries nothing of the page.\n *\n * Validated per turn against the agent's `externalContextSchema`, exactly\n * as a typed turn is: keeping it in the session record decides only where\n * it comes from, never what is trusted.\n */\n externalContext: z.record(z.string(), z.unknown()).optional(),\n})\nexport type VoiceSessionRequest = z.infer<typeof VoiceSessionRequestSchema>\n\n/**\n * What the client receives to open a voice session. The signed URL is\n * short-lived and issued per session, so no provider credential ever reaches\n * the browser.\n */\nexport const VoiceSessionSchema = z.object({\n /**\n * Opaque id of the server-side session record. The client echoes it back\n * through the provider (`custom_llm_extra_body`), and it is what binds a\n * spoken turn to its conversation: the chat id is never taken from the\n * client, because a browser could then name someone else's conversation.\n */\n sessionId: z.string(),\n signedUrl: z.string(),\n providerAgentId: z.string(),\n /** Conversation the turns of this session are persisted into. */\n chatId: z.string(),\n maxSessionSeconds: z.number().int(),\n})\nexport type VoiceSession = z.infer<typeof VoiceSessionSchema>\n\n/** A provider voice, as offered in the agent configuration. */\nexport const VoiceOptionSchema = z.object({\n voiceId: z.string(),\n name: z.string(),\n /** Provider category (premade, professional, generated): shown as a chip. */\n category: z.string().optional(),\n /** Short sample, for the preview button in the configuration panel. */\n previewUrl: z.string().optional(),\n /** Provider labels (accent, gender, use case): free-form, shown as chips. */\n labels: z.record(z.string(), z.string()).optional(),\n})\nexport type VoiceOption = z.infer<typeof VoiceOptionSchema>\n\nexport const VoiceOptionListSchema = z.array(VoiceOptionSchema)\n\nexport const AgentSettingsSchema = z.object({\n model: AgentModelSchema,\n interface: AgentInterfaceSchema,\n tools: AgentToolsSchema.optional().default(() =>\n AgentToolsSchema.parse({}),\n ),\n fileUpload: AgentFileUploadSchema.optional().default(() =>\n AgentFileUploadSchema.parse({}),\n ),\n gatewayOptions: AgentGatewayOptionsSchema.optional().default(() =>\n AgentGatewayOptionsSchema.parse({}),\n ),\n channels: z\n .array(z.enum(AgentChannel))\n .optional()\n .default(() => [...ALL_AGENT_CHANNELS]),\n /**\n * JSON Schema definition for the `externalContext` field accepted in chat\n * requests. Only top-level string-keyed properties that match this schema\n * will be forwarded to the LLM. When absent, all external context is\n * silently ignored (deny-by-default).\n */\n externalContextSchema: jsonSchemaField.optional(),\n openaiApi: AgentOpenAiApiSchema.optional().default(() =>\n AgentOpenAiApiSchema.parse({}),\n ),\n voice: AgentVoiceSchema.optional().default(() =>\n AgentVoiceSchema.parse({}),\n ),\n toolWorkingSet: AgentToolWorkingSetSchema.optional().default(() =>\n AgentToolWorkingSetSchema.parse({}),\n ),\n})\nexport type AgentSettings = z.infer<typeof AgentSettingsSchema>\n\nexport const AgentSecuritySchema = z.object({\n rateLimits: z.object({\n minuteRateLimit: z.number().int().min(0).optional(),\n hourRateLimit: z.number().int().min(0).optional(),\n dayRateLimit: z.number().int().min(0).optional(),\n monthRateLimit: z.number().int().min(0).optional(),\n }),\n trustedOrigins: z\n .object({\n origins: z\n .array(z.url().or(z.literal('')))\n .overwrite((items) => {\n return items?.filter((item) => item?.trim())\n })\n .default([]),\n })\n .default({ origins: [] }),\n})\nexport type AgentSecurity = z.infer<typeof AgentSecuritySchema>\n\nexport const AgentDtoSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n prompt: z.string().optional(),\n /**\n * Left out means \"whatever this organization chose\": the server fills it\n * from the organization's default, which a constant here could not know.\n */\n model: z.string().optional(),\n fallbackModels: z.array(z.string()).default([]),\n status: z.enum(AgentStatus).default(AgentStatus.Draft),\n visibility: z.enum(AgentVisibility).default(AgentVisibility.Organization),\n settings: AgentSettingsSchema,\n security: AgentSecuritySchema.nullish(),\n type: z.enum(AgentType).default(AgentType.Chat),\n organizationId: z.string(),\n})\n\nexport const AgentSchema = z.lazy(() =>\n z.object({\n id: z.string(),\n name: z.string(),\n prompt: z.string(),\n model: z.string(),\n fallbackModels: z.array(z.string()).nullable().default([]),\n status: z.enum(AgentStatus).default(AgentStatus.Draft),\n visibility: z\n .enum(AgentVisibility)\n .default(AgentVisibility.Organization),\n settings: AgentSettingsSchema,\n security: AgentSecuritySchema.nullable(),\n type: z.enum(AgentType).default(AgentType.Chat),\n organizationId: z.string(),\n createdAt: z.coerce.date(),\n createdBy: z.string(),\n updatedAt: z.coerce.date(),\n updatedBy: z.string(),\n deleted: z.boolean(),\n deletedAt: z.coerce.date().nullable(),\n deletedBy: z.string().nullable(),\n outOfBudget: z.boolean().optional().default(false),\n outOfBudgetReason: z.string().optional().default(''),\n }),\n)\n\n/* -------------------------------------------------------------------------- *\n * Agent exposure tiers\n *\n * The same agent is serialized at decreasing levels of detail depending on\n * who is asking. Each tier is a strict narrowing of the one above it:\n *\n * Agent Full internal entity — prompt, model, settings, security.\n * Never leaves the trusted (admin/backoffice) boundary.\n * AgentPublic Client view for a viewer who ALREADY HAS ACCESS. \"Public\"\n * means \"safe to expose to the client\", NOT \"visibility =\n * public\": a private/organization agent is still served as\n * AgentPublic once the viewer is authorized.\n * AgentBranding Minimal, safe subset shown to ANONYMOUS viewers on the\n * pre-login screen — just enough to render branded chrome.\n * AgentAccess Envelope returned by the `/access` endpoint: a discriminated\n * union on `requiresAuth` that resolves to either an\n * AgentPublic (access granted) or an AgentBranding (login\n * required), plus the available auth methods.\n * -------------------------------------------------------------------------- */\n\nexport const AgentPublicSchema = z.object({\n id: z.string(),\n name: z.string(),\n status: z.enum(AgentStatus),\n visibility: z.enum(AgentVisibility),\n organizationId: z.string(),\n interface: AgentInterfaceSchema,\n createdAt: z.coerce.date(),\n updatedAt: z.coerce.date(),\n capabilities: z.object({\n fileUpload: AgentFileUploadSchema,\n voice: AgentVoiceCapabilitySchema,\n }),\n channels: z\n .array(z.enum(AgentChannel))\n .default(() => [...ALL_AGENT_CHANNELS]),\n})\n\n/**\n * Safe subset of `AgentInterface` exposed to anonymous users on the public\n * \"access\" endpoint to render a branded login screen. Mirrors the field names\n * of `AgentInterfaceSchema` (via `pick`) so consumers can read branding the\n * same way for both `AgentPublic.interface` and `AgentBranding.interface`.\n *\n * 🔒 NEVER add sensitive fields here (system prompt, models, tools, …).\n */\nexport const AgentBrandingInterfaceSchema = AgentInterfaceSchema.pick({\n logo: true,\n mainColor: true,\n textColor: true,\n theme: true,\n floatingButtonPosition: true,\n customCss: true,\n})\nexport type AgentBrandingInterface = z.infer<\n typeof AgentBrandingInterfaceSchema\n>\n\nexport const AgentBrandingSchema = AgentPublicSchema.pick({\n id: true,\n name: true,\n organizationId: true,\n}).extend({\n interface: AgentBrandingInterfaceSchema,\n})\nexport type AgentBranding = z.infer<typeof AgentBrandingSchema>\n\nexport const AuthMethodsSchema = z.object({\n emailPassword: z.boolean(),\n google: z.boolean(),\n microsoft: z.boolean(),\n})\nexport type AuthMethods = z.infer<typeof AuthMethodsSchema>\n\n/**\n * Access decision for an agent, WITHOUT the auth methods.\n *\n * Discriminated on `requiresAuth` so the two outcomes are mutually exclusive at\n * the type level — no caller has to null-check `agent`/`branding` by hand:\n * - `requiresAuth: false` → access granted, full `agent` is present.\n * - `requiresAuth: true` → login required, only `branding` is present.\n *\n * This is what the service returns; the controller layers `authMethods` on top\n * to produce {@link AgentAccessSchema}.\n */\nexport const AgentAccessGrantedSchema = z.object({\n requiresAuth: z.literal(false),\n agent: AgentPublicSchema,\n branding: z.null(),\n})\n\nexport const AgentAccessRequiresAuthSchema = z.object({\n requiresAuth: z.literal(true),\n agent: z.null(),\n branding: AgentBrandingSchema,\n})\n\nexport const AgentAccessDecisionSchema = z.discriminatedUnion('requiresAuth', [\n AgentAccessGrantedSchema,\n AgentAccessRequiresAuthSchema,\n])\nexport type AgentAccessDecision = z.infer<typeof AgentAccessDecisionSchema>\n\nconst AgentAccessExtrasSchema = z.object({\n authMethods: AuthMethodsSchema,\n /**\n * The deployment theme for the widget's shadow root, which the page's\n * stylesheet cannot reach. Null while the deployment keeps the default.\n */\n deploymentBranding: DeploymentBrandingSchema.nullish(),\n})\n\n/**\n * Full payload returned by the public `/access` endpoint: the\n * {@link AgentAccessDecisionSchema} plus the auth methods the client may offer\n * on the login screen and the deployment theme.\n */\nexport const AgentAccessSchema = z.discriminatedUnion('requiresAuth', [\n AgentAccessGrantedSchema.extend(AgentAccessExtrasSchema.shape),\n AgentAccessRequiresAuthSchema.extend(AgentAccessExtrasSchema.shape),\n])\nexport type AgentAccess = z.infer<typeof AgentAccessSchema>\n\n/**\n * Per-member allowlist of `organization`-visibility agents. An empty `agentIds`\n * means \"no restriction\" — the member can use every organization agent (the\n * default). A non-empty list limits the member to those agents. Owners/admins\n * always bypass it. `id` is the member's user id, so the resource can be\n * cached/updated as a keyed entity by the frontend store. Used as both the GET\n * response and the PUT body of the backoffice `/members/:userId/agent-access`\n * endpoint.\n */\nexport const MemberAgentAccessSchema = z.object({\n id: z.uuid(),\n agentIds: z.array(z.uuid()),\n})\nexport type MemberAgentAccess = z.infer<typeof MemberAgentAccessSchema>\n\nexport const AgentsQuerystringSchema = z.object({\n ...zodQs.pagination(),\n ...zodQs.sort([\n 'id',\n 'updatedAt',\n 'createdAt',\n 'name',\n 'type',\n 'status',\n 'visibility',\n 'model',\n ]),\n ...zodQs.filters(['done', 'type']),\n ...zodQs.filter('id'),\n ...zodQs.fullText(),\n ...zodQs.ids(),\n})\n\nexport type AgentDto = z.infer<typeof AgentDtoSchema>\nexport type Agent = z.infer<typeof AgentSchema>\nexport type AgentPublic = z.infer<typeof AgentPublicSchema>\n\nexport type AgentQuerystring = z.infer<typeof AgentsQuerystringSchema>\n"],"mappings":"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"}
|
|
@@ -100,7 +100,7 @@ var T = [
|
|
|
100
100
|
}
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
|
-
test: /json|javascript|typescript|xml|html|x-sh|
|
|
103
|
+
test: /json|javascript|typescript|xml|html|css|yaml|toml|sql|x-(?:sh|python|java|kotlin|c|csharp|go|rust|ruby|php|swift|vue)\b/,
|
|
104
104
|
kind: {
|
|
105
105
|
icon: "ri:file-code-line",
|
|
106
106
|
accent: "#0d9488",
|
|
@@ -253,4 +253,4 @@ var T = [
|
|
|
253
253
|
//#endregion
|
|
254
254
|
export { B as t };
|
|
255
255
|
|
|
256
|
-
//# sourceMappingURL=PkChatbotFilePreview-
|
|
256
|
+
//# sourceMappingURL=PkChatbotFilePreview-Bdi4_IFu.js.map
|