@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
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Agent-DU1WWaHR.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.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","union","uuid","string","url","number","codec","literal","array","lazy","_enum","boolean","discriminatedUnion","object","unknown","record","MediaSchema","date","MIME_TYPE_REGEX","decodeOnly","input","output","value","MAX_SCHEMA_SIZE_BYTES","jsonSchemaField","val","makeSortEnum","makeSortEnums","i","zodQs","v","defaultNumber","defaultSize","a","b","sortEnums","sort","stripInventedNamespace","toolName","resolveToolName","known","names","cleaned","matches","name","HEX_COLOR_REGEX","BrandingPaletteSchema","BrandingColorsSchema","sameBrandingColors","BrandingMode","\"System\"","\"ForceLight\"","\"ForceDark\"","BrandingAssetSlot","\"LogoLight\"","\"LogoDark\"","\"Mark\"","\"EmailLogo\"","\"EmailBanner\"","BrandingAssetRefSchema","BrandingAssetsSchema","BrandingTextSchema","DeploymentBrandingSchema","PatchAssetsSchema","PatchTextSchema","BrandingPatchSchema","tolerant","schema","DEFAULT_BRANDING","deepFreeze","usesBundledImages","text","relativeLuminance","hex","r","g","c","channel","initialOf","char","upper","neutralMarkSvg","fill","color","ink","letter","rounded","neutralMarkUrl","child","canonicalJson","k","contentHash","code","brandingVersion","brandingStylesheetVersion","branding","BRANDING_PUBLIC_PATH","brandingAssetPath","checksum","brandingAssetUrl","backendUrl","toResolvedBranding","paletteDeclarations","palette","renderBrandingCss","light","dark","DeviceContextSchema","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","isGenericReasoningProvider","provider","GENERIC_REASONING_EFFORTS","GenericReasoningSchema","legacyLevel","accepted","AgentReasoningObjectSchema","migrateReasoningConfig","obj","isAlreadyMigrated","effort","reasoningSummary","migrated","openaiEffort","summary","anthropicEffort","googleLevel","genericEffort","AgentReasoningSchema","DEFAULT_REASONING_BY_PROVIDER","configuresSomething","config","effectiveProviderReasoning","configured","reasoning","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","ENABLE_TOOLS_TOOL","canRequireApproval","isPresentationTool","PLATFORM_RENDERED_TOOLS","isPlatformRenderedTool","USER_ANSWERED_TOOLS","isUserAnsweredTool","ChatTransport","\"Web\"","\"Platform\"","\"OpenAiApi\"","\"Voice\"","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","_null","AgentAccessRequiresAuthSchema","AgentAccessExtrasSchema"],"sources":["../../../../packages/models/src/utils.ts","../../../../packages/models/src/schema/Branding.ts","../../../../packages/models/src/schema/DeviceContext.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 * 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 = relativeLuminance(fill) > 0.179 ? '#000000' : '#ffffff'\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 * 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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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Document-Cto-Qws0.js","names":["z.object","z.string","z.array","z.boolean","z.object","z.string","z.number","z.enum","z.array","z.record","z.unknown","z.boolean","z.object","z.enum","z.string","z.boolean","z.number","z.literal","z.uuid","z.preprocess","z.discriminatedUnion","z.array","z.union","z.unknown","z.url","z.record","z.coerce.date","union","uuid","string","url","number","preprocess","literal","array","_enum","boolean","discriminatedUnion","object","unknown","record","MediaSchema","date","decodeOnly","zodQs","GATEWAY_MODELS","PER_MILLION_TOKENS","EMBED_MODEL","\"textEmbedding3Small\"","\"textEmbedding3Large\"","\"geminiEmbedding2\"","EmbeddingModel","EVALUATION_MODEL","SupportedLanguage","\"it\"","\"en\"","\"es\"","\"fr\"","\"de\"","ExtractionStrategy","\"READABILITY\"","\"AI\"","BrowserEngine","\"FETCH\"","\"PUPPETEER\"","\"REMOTE\"","BYOK_MODEL_PREFIX","isByokModel","id","HeaderSchema","HeadesSchema","headers","header","key","TabularColumnSchema","TabularTableSchema","TabularSkippedSheetSchema","TabularConversionSchema","DocumentTabularSchema","IndexStatus","\"Pending\"","\"Processing\"","\"Success\"","\"Failed\"","SearchIndexStatus","\"Indexed\"","\"Unavailable\"","\"Empty\"","DocumentListStatus","\"Preparing\"","\"NotIndexed\"","ConversionOptionsSchema","DocumentSourceProvider","\"Web\"","\"SharePoint\"","\"GoogleDrive\"","DocumentRefreshResult","\"Updated\"","\"Unchanged\"","\"Shrunk\"","\"Gone\"","DocumentRefreshInterval","\"Daily\"","\"Weekly\"","\"Monthly\"","DocumentLastRefreshSchema","commonSourceFields","WebDocumentSourceSchema","cloudSourceFields","SharePointDocumentSourceSchema","GoogleDriveDocumentSourceSchema","DocumentSourceSchema","value","DOCUMENT_REFUSAL_REASONS","UNPROCESSABLE_FILE_REASONS","DocumentIndexErrorSchema","DocumentMetadataSchema","val","DocumentType","\"File\"","\"Url\"","\"RevisedAnswer\"","\"PlainText\"","DocumentSchema","data","ctx","getTypeIcon","type","getFileIcon","extension","isImageMime","mimeType","isInlineViewable","fileKindForMime","mime","fileIconForMime"],"sources":["../../../../packages/models/src/schema/constants.ts","../../../../packages/models/src/schema/Header.ts","../../../../packages/models/src/schema/Tabular.ts","../../../../packages/models/src/schema/Document.ts"],"sourcesContent":["/**\n * The models an agent of this platform may be pointed at.\n *\n * The gateway listing DESCRIBES what exists, this list PERMITS. They are two\n * different questions, and conflating them broke production once: on\n * 2026-07-23 two models entered the catalog before the installed\n * `@ai-sdk/gateway` knew them, and their tool calls failed under the generic\n * handling. Exposing every model the day the listing shows it would reproduce\n * that by construction.\n *\n * Adding one is a line here, after the checklist in\n * `docs/agents/llm-integration.md`: it must be `type: language` in the\n * listing, produce text and carry the `tool-use` tag. Everything else about\n * it, the commercial name, the price, the context window, the two privacy\n * flags, comes from the listing and is never written down twice.\n *\n * A test checks every id against a saved copy of the listing, which is what\n * replaces the by-hand verification that missed a model on 2026-09-18.\n */\nexport const GATEWAY_MODELS = [\n // OpenAI\n 'openai/gpt-5-nano',\n 'openai/gpt-5-mini',\n 'openai/gpt-5.1-thinking',\n 'openai/gpt-5.2',\n 'openai/gpt-5.4-nano',\n 'openai/gpt-5.4-mini',\n 'openai/gpt-5.4',\n 'openai/gpt-5.4-pro',\n 'openai/gpt-5.5',\n 'openai/gpt-5.5-pro',\n 'openai/gpt-5.6-luna',\n 'openai/gpt-5.6-terra',\n 'openai/gpt-5.6-sol',\n 'openai/gpt-5.6-luna-fast',\n 'openai/gpt-5.6-terra-fast',\n 'openai/gpt-5.6-sol-fast',\n 'openai/gpt-6-astra',\n 'openai/gpt-6-astra-fast',\n 'openai/gpt-6-sol',\n 'openai/gpt-6-sol-fast',\n 'openai/gpt-6-luna',\n 'openai/gpt-6-luna-fast',\n 'openai/gpt-6.1-sol',\n 'openai/gpt-6.1-sol-fast',\n // Google Gemini\n 'google/gemini-2.5-flash-lite',\n 'google/gemini-2.5-flash',\n 'google/gemini-2.5-pro',\n 'google/gemini-3-flash',\n 'google/gemini-3.1-pro-preview',\n 'google/gemini-3.1-flash-lite',\n 'google/gemini-3.5-flash',\n 'google/gemini-3.5-flash-lite',\n 'google/gemini-3.6-flash',\n 'google/gemini-3.7-flash',\n 'google/gemini-3.8-flash',\n 'google/gemini-4-argon',\n // Anthropic Claude\n 'anthropic/claude-haiku-4.5',\n 'anthropic/claude-haiku-5.5',\n 'anthropic/claude-sonnet-4.6',\n 'anthropic/claude-sonnet-5',\n 'anthropic/claude-sonnet-5.5',\n 'anthropic/claude-opus-4.6',\n 'anthropic/claude-opus-4.7',\n 'anthropic/claude-opus-4.8',\n 'anthropic/claude-opus-5',\n 'anthropic/claude-opus-5-fast',\n 'anthropic/claude-opus-5.5',\n 'anthropic/claude-opus-5.5-fast',\n 'anthropic/claude-fable-5',\n 'anthropic/claude-fable-5.1',\n // Deepseek\n 'deepseek/deepseek-v3.2',\n 'deepseek/deepseek-v4-flash-0731',\n 'deepseek/deepseek-v4.1-flash',\n 'deepseek/deepseek-v4-pro-0813',\n // Alibaba\n 'alibaba/qwen3.6-plus',\n 'alibaba/qwen3.7-max',\n 'alibaba/qwen3.7-plus',\n 'alibaba/qwen3.7-flash',\n 'alibaba/qwen3.8-flash',\n 'alibaba/qwen3.8-max',\n 'alibaba/qwen3.8-27b',\n 'alibaba/qwen3.8-max-0902',\n 'alibaba/qwen3.8-omni-flash',\n 'alibaba/qwen3.8-max-prime',\n // SpaceXAI\n 'spacexai/grok-4.3',\n 'spacexai/grok-4.6',\n 'spacexai/grok-4.7',\n // z.ai\n 'zai/glm-5.2',\n 'zai/glm-5.2-fast',\n 'zai/glm-5.3',\n 'zai/glm-5.3-flash',\n 'zai/glm-5.3-fast',\n 'zai/glm-5.3-flashx',\n // Meta\n 'meta/muse-spark-1.1',\n 'meta/muse-spark-1.2',\n 'meta/muse-spark-1.3',\n 'meta/muse-wonder-1.0',\n // Moonshot AI\n 'moonshotai/kimi-k3',\n 'moonshotai/kimi-k3-fast',\n // Mistral\n 'mistral/ministral-14b',\n 'mistral/mistral-small',\n 'mistral/mistral-medium-3.5',\n 'mistral/mistral-large-3',\n 'mistral/mistral-large-4',\n // Xiaomi\n 'xiaomi/mimo-v2.6-flash',\n 'xiaomi/mimo-v2.6-pro',\n 'xiaomi/mimo-v2.6-pro-ultraspeed',\n] as const satisfies readonly string[]\n\n/**\n * A model id: an entry of {@link GATEWAY_MODELS}, or a `byok/` id served by an\n * organization's own endpoint. A plain string on purpose, because the second\n * half cannot be enumerated.\n */\nexport type ModelId = string\n\n/**\n * Prices are stored per token, the unit the gateway listing publishes, and\n * shown per million, the unit every price page uses. One copy, so the page,\n * its dialogs and the picker never disagree on the factor.\n */\nexport const PER_MILLION_TOKENS = 1_000_000\n\n/**\n * The models the platform falls back to when an organization has expressed no\n * preference. The only model ids written in the code besides the curated list.\n */\nexport const PLATFORM_MODEL_DEFAULTS = {\n /** New agents, and the runtime fallback of an agent with no model. */\n agentModel: 'openai/gpt-5.6-terra',\n /** Question reformulation, JSON to schema, memory reconciliation. */\n utilityModel: 'google/gemini-3-flash',\n} as const\n\n/**\n * Models used to vectorize text, never to answer. Kept apart from\n * {@link GATEWAY_MODELS} so an embedding id cannot reach the chat plumbing,\n * and out of the catalog for the same reason: they are not selectable.\n */\nexport enum EmbeddingModel {\n textEmbedding3Small = 'openai/text-embedding-3-small',\n textEmbedding3Large = 'openai/text-embedding-3-large',\n geminiEmbedding2 = 'google/gemini-embedding-2',\n}\n\nexport const EMBED_MODEL = EmbeddingModel.geminiEmbedding2\n\n/**\n * Model that answers typed questions (yes/no, choice, score) with calibrated\n * probabilities instead of text, through the gateway's `experimental_evaluate`\n * (TypeSafe Jev). Out of the catalog like the embeddings: it decides for the\n * platform, it never answers the user. Its gateway listing reports no ZDR,\n * yet a ZDR request is served, routed to TypeSafe alone (measured\n * 2026-09-28, scripts/spikeJevEvaluation.ts).\n */\nexport const EVALUATION_MODEL = 'typesafe-ai/jev'\n\n/**\n * Supported languages for documents and revised answers\n */\nexport enum SupportedLanguage {\n it = 'it',\n en = 'en',\n es = 'es',\n fr = 'fr',\n de = 'de',\n}\n\n/**\n * Language display names (i18n keys)\n */\nexport const LANGUAGE_NAMES: Record<SupportedLanguage, string> = {\n [SupportedLanguage.it]: 'language.italian',\n [SupportedLanguage.en]: 'language.english',\n [SupportedLanguage.es]: 'language.spanish',\n [SupportedLanguage.fr]: 'language.french',\n [SupportedLanguage.de]: 'language.german',\n}\n\n/**\n * Content extraction strategies for URL scraping\n */\nexport enum ExtractionStrategy {\n /** Use Mozilla Readability for content extraction (fast, free, no API calls) */\n READABILITY = 'readability',\n /** Use AI-based extraction (better for complex layouts, requires API calls) */\n AI = 'ai',\n}\n\n/**\n * Browser engine options for URL scraping\n */\nexport enum BrowserEngine {\n /** Use simple HTTP fetch (fast, lightweight, no JavaScript support) */\n FETCH = 'fetch',\n /** Use Puppeteer with headless Chrome (full browser, JavaScript support) */\n PUPPETEER = 'puppeteer',\n /** Delegate browser rendering to an external pdf-image-generator service */\n REMOTE = 'remote',\n}\n\n/**\n * Which report family has to account for a credit charge.\n *\n * The hourly reconciliation trusts `cost_reports` (the gateway's own billing,\n * copied in house) as the source of truth for what an organization spent. A\n * charge whose supplier is not the gateway has no counterpart there, so it must\n * be told apart or the reconciliation forgives it: that is what happened to the\n * voice minutes until 2026-08-31.\n *\n * Declared here, written on the ledger row at charge time, never inferred from\n * `source` downstream: the next non-gateway supplier must be a compile-time\n * decision, not a string nobody remembered to add to a list.\n */\nexport enum BillingSource {\n /** Billed by the AI gateway, so it lands in `cost_reports`. */\n GATEWAY = 'gateway',\n /** Billed by another supplier (voice minutes, OCR): the ledger is the only record. */\n INTERNAL = 'internal',\n}\n\n/**\n * Kinds of row on the credit ledger.\n *\n * It used to be a free string with exactly one value ever written, `debit`.\n * Adding a second one is not free: the hourly reconciliation sums debits to\n * rebuild the real-time estimate, and the analytics endpoint sums the ledger to\n * chart spend, so a new type that nobody filters out is a number silently\n * doubled.\n */\nexport enum CreditTransactionType {\n /** A charge for something consumed, written in real time. */\n DEBIT = 'debit',\n /** The hourly settlement against the gateway report: the audit trail of a balance move. */\n RECONCILIATION = 'reconciliation',\n}\n\n/**\n * Prefix that marks a model served by the organization's own OpenAI compatible\n * endpoint rather than by the gateway.\n *\n * It is not a gateway brand, which is the point: every switch on the provider\n * (reasoning options, the Google thought signature repair, the per-provider\n * timeouts, the native web search tools) falls into its default branch without\n * any of them having to learn about BYOK.\n */\nexport const BYOK_MODEL_PREFIX = 'byok/'\n\nexport const isByokModel = (id?: string | null): boolean =>\n Boolean(id?.startsWith(BYOK_MODEL_PREFIX))\n\n/**\n * The id as the endpoint wants it, with the prefix removed. The remainder may\n * itself contain slashes (`byok/meta-llama/Llama-3.3-70B`), so this cuts the\n * prefix and does not split.\n */\nexport const byokModelId = (id: string): string =>\n id.startsWith(BYOK_MODEL_PREFIX) ? id.slice(BYOK_MODEL_PREFIX.length) : id\n","import * as z from 'zod'\nimport { decodeOnly } from '../utils'\n\nexport const HeaderSchema = z.object({\n key: z.string().optional(),\n value: z.string().optional(),\n})\n\nexport const HeadesSchema = decodeOnly(\n z.array(HeaderSchema),\n z.array(z.object({ key: z.string(), value: z.string() })),\n (headers) =>\n headers?.filter(\n (header) => header.key?.trim() && header.value?.trim(),\n ) as Array<{ key: string; value: string }>,\n)\n\nexport type Header = z.infer<typeof HeaderSchema>\nexport type Headers = z.infer<typeof HeadesSchema>\n\n/** Upper bound of a secret value, so a form cannot store an arbitrarily large blob. */\nexport const MAX_SECRET_VALUE_LENGTH = 4096\n\n/**\n * A header that carries a credential, as the API returns it: its name, and\n * whether a value is stored. The headers of API tools and MCP servers carry\n * the keys of the services they call (`Authorization`, `X-Api-Key`), so the\n * value never leaves the backend, the contract of the headers of the\n * organization's model provider.\n */\nexport const SecretHeaderSchema = z.object({\n key: z.string(),\n hasValue: z.boolean(),\n})\n\n/**\n * Secret headers as a save sends them. On an update an empty value keeps the\n * one stored under the same name, while the URL keeps its origin; a name left\n * out is removed. A row without a name is an empty row of the form, and\n * dropped. Two names that differ only in case are one HTTP header, so they\n * are refused: a kept value would match the first and the request send the\n * last.\n */\nexport const SecretHeaderListSchema = decodeOnly(\n z.array(\n z.object({\n key: z.string().optional(),\n value: z.string().max(MAX_SECRET_VALUE_LENGTH).optional(),\n }),\n ),\n z\n .array(z.object({ key: z.string(), value: z.string().optional() }))\n .refine(\n (headers) =>\n new Set(headers.map(({ key }) => key.toLowerCase())).size ===\n headers.length,\n { params: { i18n: 'validation.duplicateHeader' } },\n ),\n (headers) =>\n headers\n .filter((header) => header.key?.trim())\n .map(({ key, value }) => ({ key: key!.trim(), value })),\n)\n\nexport type SecretHeader = z.infer<typeof SecretHeaderSchema>\nexport type SecretHeaderDto = z.infer<typeof SecretHeaderListSchema>[number]\n/**\n * A secret header as stored (`agent_api_tools.headers`, `mcp_server.headers`),\n * with `value` encrypted by `encryptSecret`; rows saved before 0.115.0 hold it\n * in clear until their next save. Backend only: it never reaches a response.\n */\nexport type StoredSecretHeader = { key: string; value: string }\n","import * as z from 'zod'\n\n// Spreadsheets converted for SQL: the schema of each table, shared by the\n// converter (Azure Function), the query tool (backend) and the two places that\n// keep it (spec `tabular-data-sql-query.md`, \"Modello dati\").\n\nexport const TabularColumnSchema = z.object({\n /** The name in SQL: the header text, made unique. */\n name: z.string(),\n /** The DuckDB type. */\n type: z.string(),\n /** The Excel column letter, so a found record can be edited by address. */\n column: z.string().optional(),\n /** How many values are formula results, as stored in the file. */\n formulas: z.number().optional(),\n /**\n * A text column whose values are almost all of one other kind: dates with\n * a few notes in between, as in a real fleet export.\n */\n mostly: z\n .object({\n kind: z.enum(['date', 'number', 'boolean']),\n share: z.string(),\n })\n .optional(),\n})\n\nexport const TabularTableSchema = z.object({\n sheet: z.string(),\n /** The SQL name of the table. */\n table: z.string(),\n /** The Excel row of the header; the records start below it. */\n headerRow: z.number().optional(),\n rowCount: z.number(),\n columns: z.array(TabularColumnSchema),\n /** The first records, as JSON values. */\n sample: z.array(z.record(z.string(), z.unknown())),\n})\n\nexport const TabularSkippedSheetSchema = z.object({\n sheet: z.string(),\n /**\n * `chart` is a chart sheet; `no-table` has no header row among its first\n * thirty (a form, a summary, an empty sheet); `too-wide` has more columns\n * than a table takes; `unreadable` failed to convert.\n */\n reason: z.enum(['chart', 'no-table', 'too-wide', 'unreadable']),\n})\n\nexport const TabularConversionSchema = z.object({\n /** A conversion by an older converter is redone instead of trusted. */\n converterVersion: z.number(),\n tables: z.array(TabularTableSchema),\n skipped: z.array(TabularSkippedSheetSchema),\n /**\n * The workbook asks Excel to recalculate on open, as every version the\n * chat writes does: the formula results it stores may be stale.\n */\n staleFormulas: z.boolean(),\n})\n\nexport type TabularColumn = z.infer<typeof TabularColumnSchema>\nexport type TabularTable = z.infer<typeof TabularTableSchema>\nexport type TabularSkippedSheet = z.infer<typeof TabularSkippedSheetSchema>\nexport type TabularConversion = z.infer<typeof TabularConversionSchema>\n\n/** The conversion of a chat attachment, in `chat_attachments.tabular`. */\nexport const TabularStateSchema = z.object({\n status: z.enum(['pending', 'ready', 'failed']),\n /** When the conversion was last asked for, ISO. */\n requestedAt: z.string(),\n conversion: TabularConversionSchema.optional(),\n /** Why it failed, worded for the model to pass on. */\n failure: z.string().optional(),\n /** The converter that failed: a newer one tries again. */\n failedConverterVersion: z.number().optional(),\n})\n\nexport type TabularState = z.infer<typeof TabularStateSchema>\n\n/** The conversion of a knowledge-base file, in `documents.metadata.tabular`. */\nexport const DocumentTabularSchema = TabularConversionSchema.extend({\n /**\n * sha256 of the converter version and the file: a refresh with the same\n * file, converted the same way, changes nothing.\n */\n sourceHash: z.string(),\n})\n\nexport type DocumentTabular = z.infer<typeof DocumentTabularSchema>\n\n/** A knowledge-base spreadsheet an agent can query, with its schema. */\nexport interface TabularDocument {\n id: string\n name: string\n tabular: DocumentTabular\n}\n\n/**\n * The `document-processing` message that asks for the conversion of a chat\n * attachment, an uploaded spreadsheet or a version the agent wrote. It shares\n * the documents' queue, so no new queue is needed in Azure.\n */\nexport interface SpreadsheetConversionJob {\n kind: 'spreadsheet'\n attachmentId: string\n}\n","import * as z from 'zod'\nimport { zodQs, decodeOnly } from '../utils'\nimport {\n SupportedLanguage,\n ExtractionStrategy,\n BrowserEngine,\n} from './constants'\nimport { MediaSchema } from './Media'\nimport { HeadesSchema } from './Header'\nimport { DocumentTabularSchema, type SpreadsheetConversionJob } from './Tabular'\n\n/**\n * Status of the document pipeline: conversion and chunking. `Success` does not\n * say the chunks are in the index: that is {@link SearchIndexStatus}.\n */\nexport enum IndexStatus {\n Pending = 'pending',\n Processing = 'processing',\n Success = 'success',\n Failed = 'failed',\n}\n\n/**\n * Whether the search can find a document's chunks, apart from the pipeline\n * that produced them: `IndexStatus.Success` means converted and cut, and the\n * chunks reach the index afterwards, through the chunk sync\n * (docs/specs/kb-index-integrity.md, K1).\n */\nexport enum SearchIndexStatus {\n /** Every chunk has its point, as Qdrant confirmed to the sync. */\n Indexed = 'indexed',\n /** Chunks waiting for the sync. */\n Pending = 'pending',\n /** The sync gave up on these chunks; a reprocess tries again. */\n Failed = 'failed',\n /** The organization cannot compute embeddings right now. */\n Unavailable = 'unavailable',\n /** No chunk at all: there is nothing for the search to find. */\n Empty = 'empty',\n}\n\n/** What {@link searchIndexStatusOf} needs to know about one document. */\nexport interface SearchIndexFacts {\n /** Chunk rows of the document. */\n chunks: number\n /** Of those, the rows whose point the sync wrote and Qdrant confirmed. */\n syncedChunks: number\n /** When the newest chunk row was written, in epoch milliseconds. */\n newestChunkAt: number | null\n /** `metadata.searchIndexError.at`, written when a sync dead-letters. */\n searchIndexFailedAt: string | null | undefined\n /** Whether the organization can compute embeddings right now. */\n canEmbed: boolean\n /**\n * A spreadsheet read as tables and converted (`metadata.tabular`, index\n * status `success`): the agent queries it with SQL, and it has no chunks\n * by design.\n */\n tabular?: boolean\n}\n\n/**\n * The searchability of a document, from its chunk flags.\n *\n * The flag is the one source: the sync sets it only after Qdrant has counted\n * the points it wrote, and every path that rewrites or revives chunks clears\n * it. A recorded failure counts only against the chunks it was about: rows\n * written after it belong to a newer sync, still to come.\n */\nexport function searchIndexStatusOf(\n facts: SearchIndexFacts,\n): SearchIndexStatus {\n // Available as soon as it is converted: without chunks it would read as\n // empty, while its tables are what the agent searches.\n if (facts.tabular) {\n return SearchIndexStatus.Indexed\n }\n if (facts.chunks === 0) {\n return SearchIndexStatus.Empty\n }\n if (facts.syncedChunks >= facts.chunks) {\n return SearchIndexStatus.Indexed\n }\n if (searchIndexGaveUp(facts.searchIndexFailedAt, facts.newestChunkAt)) {\n return SearchIndexStatus.Failed\n }\n return facts.canEmbed\n ? SearchIndexStatus.Pending\n : SearchIndexStatus.Unavailable\n}\n\n/**\n * Whether the record of a sync that gave up still speaks for the chunks of a\n * document out of the index: only when none of them is newer than it. The\n * documents list asks it of the rows it filters by state, so that the filter\n * reads the record the way the badge does.\n */\nexport function searchIndexGaveUp(\n searchIndexFailedAt: string | null | undefined,\n newestChunkAt: number | null,\n): boolean {\n const failedAt = searchIndexFailedAt\n ? Date.parse(searchIndexFailedAt)\n : Number.NaN\n return (\n Number.isFinite(failedAt) &&\n newestChunkAt !== null &&\n newestChunkAt <= failedAt\n )\n}\n\n/**\n * What the badge of a row in the documents list reads, which is what the list\n * filters by (`filter[status]`): the conversion until it has succeeded, then\n * whether the search finds the document. Two words would mean different\n * things in the two stages, so the search values are named after their label:\n * its `pending` reads \"Preparing\", its `failed` \"Not indexed\".\n */\nexport enum DocumentListStatus {\n Pending = 'pending',\n Processing = 'processing',\n Failed = 'failed',\n Preparing = 'preparing',\n Indexed = 'indexed',\n NotIndexed = 'not-indexed',\n Unavailable = 'unavailable',\n Empty = 'empty',\n}\n\n// ===== Document Source Types =====\n\n/**\n * Conversion options for document processing\n * Used when creating or reprocessing documents\n */\nexport const ConversionOptionsSchema = z.object({\n extractionStrategy: z.enum(ExtractionStrategy).optional(),\n browserEngine: z\n .enum(BrowserEngine)\n .optional()\n .default(BrowserEngine.FETCH),\n headers: HeadesSchema.nullish(),\n aiDescriptionModel: z.string().optional(),\n aiDescriptionPrompt: z.string().max(5000).optional(),\n language: z.string().optional(),\n forceOcr: z.boolean().default(false),\n pages: z\n .string()\n .max(100)\n .regex(/^\\d+(\\s*-\\s*\\d+)?(\\s*,\\s*\\d+(\\s*-\\s*\\d+)?)*$/)\n .optional(),\n /**\n * `false` keeps a spreadsheet as text, chunked like any other file: a\n * user's file, searched with the others in \"My files\", which\n * `querySpreadsheet` does not reach. A spreadsheet otherwise becomes tables.\n */\n asTables: z.boolean().optional(),\n})\n\nexport type ConversionOptions = z.infer<typeof ConversionOptionsSchema>\n\n// ===== Document Source (metadata.source) =====\n\n/**\n * Who keeps a document's content up to date.\n *\n * `web` is a page the platform re-reads on its own; the others are cloud\n * document sources. Distinct from `documents.source_provider`, which carries\n * only the providers that OWN their documents (the cloud ones) and is null for\n * everything else: a web page discovered by a source stays editable.\n */\nexport enum DocumentSourceProvider {\n Web = 'web',\n SharePoint = 'sharepoint',\n GoogleDrive = 'google-drive',\n}\n\n/**\n * Outcome of the last pass over a document's source.\n *\n * `unchanged` is the one that pays for the whole mechanism: the source was read\n * and produced the same text, so no chunk was rewritten and no embedding was\n * charged. `shrunk` is a refusal, not a failure: the page answered but with far\n * less content than before, so the good version was kept.\n */\nexport enum DocumentRefreshResult {\n Updated = 'updated',\n Unchanged = 'unchanged',\n Failed = 'failed',\n Shrunk = 'shrunk',\n Gone = 'gone',\n}\n\n/**\n * How often a document re-reads its source on its own.\n *\n * `null` is the fourth value and the default: manual, which is what every\n * document is today and what every type other than `url` can ever be.\n */\nexport enum DocumentRefreshInterval {\n Daily = 'daily',\n Weekly = 'weekly',\n Monthly = 'monthly',\n}\n\n/**\n * The Postgres interval each trigger advances by.\n *\n * One table, read by the two places that move a deadline: the service, when\n * somebody sets or changes the trigger, and the timer, when a due document has\n * been queued. Written as literals rather than composed at the call site\n * because they end up inside SQL.\n */\nexport const REFRESH_INTERVAL_SQL: Record<DocumentRefreshInterval, string> = {\n [DocumentRefreshInterval.Daily]: '1 day',\n [DocumentRefreshInterval.Weekly]: '7 days',\n [DocumentRefreshInterval.Monthly]: '1 month',\n}\n\n/**\n * Hours after which a document left `processing` is treated as abandoned.\n *\n * Only a claim writes `processing`, and a worker killed mid-run (heap\n * exhausted, host recycled, revision deactivated) leaves it behind with nothing\n * else to move it. Two timers act on this window: `dlqSweep` marks the document\n * `failed` and tells its owner (`failStaleProcessingDocuments`), and the\n * refresh timer, which otherwise claims only `success` and `failed`, takes a\n * due page anyway.\n *\n * Derived from the bound a run cannot outlive: `host.json` leaves\n * `functionTimeout` at its Container Apps default of 30 minutes, past which the\n * host stops the run, and every claim, a redelivery's included, moves\n * `updated_at`. A row whose last claim is an hour old has outlived the longest\n * possible run twice over. The backend claims too, and stays inside the bound:\n * a text edited by hand only rewrites its chunks there (seconds, embeddings go\n * to the queue), and a whole conversion runs inline only with no Service Bus,\n * which is local development, where no function app consumes its documents.\n */\nexport const STALE_PROCESSING_HOURS = 1\n\nexport const DocumentLastRefreshSchema = z.object({\n at: z.string(),\n result: z.enum(DocumentRefreshResult),\n httpStatus: z.number().optional(),\n error: z.string().optional(),\n /** Reset by the first good outcome; the notification threshold reads it. */\n consecutiveFailures: z.number().optional(),\n /**\n * Words before and after, written by the shrink guard. They are kept rather\n * than only compared because the guard's thresholds are a starting point:\n * after a month of real pages one can tell whether they cut too much.\n */\n previousWordCount: z.number().optional(),\n newWordCount: z.number().optional(),\n})\n\nexport type DocumentLastRefresh = z.infer<typeof DocumentLastRefreshSchema>\n\n/** Fields every source branch shares, whatever keeps the document up to date. */\nconst commonSourceFields = {\n /**\n * Hash of the text that actually reaches the chunks, so an unchanged source\n * costs no chunking and no embedding. Written by the processor on every\n * pass, which is what lets a document imported before this existed start\n * comparing from its second pass on.\n */\n contentHash: z.string().optional(),\n lastRefresh: DocumentLastRefreshSchema.optional(),\n}\n\nconst WebDocumentSourceSchema = z.object({\n provider: z.literal(DocumentSourceProvider.Web),\n url: z.string(),\n // Written by a successful conversion, and only then: at insert time the\n // page has not been read yet, so a value here would attest a scrape that\n // never happened.\n lastScrapedAt: z.string().optional(),\n /**\n * Hash of the deterministic text handed to the extraction step, before the\n * model. With `extractionStrategy: 'ai'` the model's output differs on every\n * call, so comparing the final markdown would always say \"changed\" and\n * every interval would pay conversion, chunking and embedding. This is what\n * the AI path compares, and it decides whether to call the model at all.\n */\n extractionInputHash: z.string().optional(),\n /**\n * Where the last successful pass actually landed after redirects.\n *\n * The shrink guard compares this with the new final URL, and not with `url`\n * on purpose: plenty of sites always redirect (a locale prefix, a trailing\n * slash, http to https), so comparing against the stored URL would refuse\n * every update of those pages forever. What says a page is gone is its\n * destination changing from the one it has been landing on.\n */\n finalUrl: z.string().optional(),\n /**\n * The web source that discovered this page. It says who found it, not who\n * governs it: the page stays editable like any other. Editing the text by\n * hand takes it off, and the page stops belonging to the source.\n */\n sourceId: z.uuid().optional(),\n /**\n * The last run of that source that found the page listed.\n *\n * Not the last successful read of the page, which is `lastScrapedAt`:\n * this is the marker the removal option reads, named like the cloud\n * field because the same reconciliation reads both. A page without one is\n * never removed.\n */\n lastSyncedAt: z.string().optional(),\n /**\n * The `<lastmod>` the sitemap declared the last time the source read it.\n * A change that is newer than `lastScrapedAt` queues an early refresh.\n */\n lastmod: z.string().optional(),\n ...commonSourceFields,\n})\n\n/** Coordinates a cloud adapter needs to find the item again, plus its content fingerprint. */\nconst cloudSourceFields = {\n /** The `document_sync_sources` row that owns this document. */\n sourceId: z.uuid(),\n remoteId: z.string(),\n webUrl: z.string(),\n path: z.string(),\n /**\n * The provider's own content fingerprint, compared for equality only and\n * never interpreted. It is what lets a sync skip the download entirely.\n */\n fingerprint: z.string(),\n /** Marks the document as seen by a run: the reconciliation after a resync reads it. */\n lastSyncedAt: z.string(),\n /** When the provider says the item last changed. Shown, never compared: the fingerprint decides. */\n lastModified: z.string().optional(),\n /**\n * A newly downloaded blob waiting to be converted. It sits here instead of\n * replacing `metadata.media` so that a conversion failure cannot destroy the\n * version that works: the processor promotes it only on success.\n */\n candidate: z\n .object({\n media: MediaSchema,\n fingerprint: z.string(),\n name: z.string(),\n webUrl: z.string(),\n path: z.string(),\n lastModified: z.string().optional(),\n })\n .optional(),\n ...commonSourceFields,\n}\n\nconst SharePointDocumentSourceSchema = z.object({\n provider: z.literal(DocumentSourceProvider.SharePoint),\n ...cloudSourceFields,\n})\n\nconst GoogleDriveDocumentSourceSchema = z.object({\n provider: z.literal(DocumentSourceProvider.GoogleDrive),\n ...cloudSourceFields,\n})\n\n/**\n * `metadata.source`, discriminated on `provider`.\n *\n * One object cannot hold both shapes: a web page has a URL and a scrape date, a\n * cloud file has remote coordinates and a fingerprint, and making every field\n * optional to fit both is the same as having no schema. Rows written before the\n * discriminator existed carry no `provider`, so they are normalized to the web\n * branch before routing: that is the only shape that could have been written.\n *\n * The normalization runs on parse, and responses are serialized by the\n * parse-based compiler (see `apps/backend/src/utils/responseSerializer.ts`), so\n * a legacy row still comes out of the API intact.\n */\nexport const DocumentSourceSchema = z.preprocess(\n (value) => {\n if (\n value &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n !('provider' in value)\n ) {\n return { provider: DocumentSourceProvider.Web, ...value }\n }\n return value\n },\n z.discriminatedUnion('provider', [\n WebDocumentSourceSchema,\n SharePointDocumentSourceSchema,\n GoogleDriveDocumentSourceSchema,\n ]),\n)\n\nexport type DocumentSource = z.infer<typeof DocumentSourceSchema>\nexport type WebDocumentSource = z.infer<typeof WebDocumentSourceSchema>\n\n/**\n * The page URL of a document's source, when its source is a web page.\n *\n * One place to narrow the union, so the views that show \"where this came from\"\n * do not each grow their own check, and a cloud-synced document returns nothing\n * here instead of a broken link: its address is `webUrl` on the remote item,\n * which is a different thing to show and to say.\n */\nexport function documentSourceUrl(source?: DocumentSource): string | undefined {\n return source && 'url' in source ? source.url : undefined\n}\n\n// ===== Processing queue contract =====\n\n/**\n * Why a document is being processed again. Absent means the ingestion of a new\n * document, which is the only case whose natural key is the document id alone.\n */\nexport type DocumentProcessingKind = 'refresh' | 'reprocess' | 'reindex'\n\n/**\n * The `document-processing` queue message.\n *\n * Lives here because two processes read it: the backend publishes it and the\n * Azure Function consumes it. It used to be declared in each, and the copy in\n * the function app was already a field behind.\n */\nexport interface DocumentProcessingJob {\n documentId: string\n conversionOptions?: ConversionOptions\n /**\n * Set by every caller that processes a document which already exists. It\n * shapes the message id (see `publishProcessingJob`) and, for `refresh`,\n * turns on the refresh mode of the processor.\n */\n kind?: DocumentProcessingKind\n /**\n * Only a scheduled refresh enforces the shrink guard. A person who clicked\n * \"refresh now\" is looking at the result and may well be refreshing a page\n * that really did get shorter, so the guard would only stand in their way.\n */\n guarded?: boolean\n /**\n * The web source whose sitemap asked for this early refresh. Nobody is\n * watching it either, so it enforces the shrink guard; and it is void if\n * the page no longer belongs to that source, which is what editing its text\n * by hand does. Not `guarded`, which also voids a page without a trigger:\n * a source reads its pages whether they have one or not.\n */\n sourceId?: string\n}\n\n/** Everything the `document-processing` queue carries. */\nexport type DocumentQueueMessage =\n DocumentProcessingJob | SpreadsheetConversionJob\n\n/**\n * Why a document is not processed because of the organization's AI settings,\n * as `DocumentRefusal` in `database/documentAi` says.\n */\nexport const DOCUMENT_REFUSAL_REASONS = [\n /** What it needs runs on the gateway, which the organization does not use. */\n 'gateway-disabled',\n /** What it needs runs on the organization's endpoint, which is off. */\n 'endpoint-off',\n /**\n * The model it names is not switched on: on the endpoint, or among the\n * organization's gateway models, with no platform model to take its place.\n */\n 'model-unavailable',\n /** No model to run the AI on: none chosen, none in the environment. */\n 'no-model',\n /** An endpoint model is asked to read a format it cannot be sent. */\n 'format-unsupported',\n /** OCR is ours, and without the gateway nothing else stops at zero. */\n 'credit-exhausted',\n /**\n * An audio, which only the gateway transcribes, in an organization that\n * does not use it: its own reason, because the advice of\n * `gateway-disabled` (the embedding, the AI model) does not help it.\n */\n 'transcription-off',\n] as const\n\nexport type DocumentRefusalReason = (typeof DOCUMENT_REFUSAL_REASONS)[number]\n\n/**\n * Why a file is refused for what it is, as `UnprocessableFileError` in the\n * document processor says.\n */\nexport const UNPROCESSABLE_FILE_REASONS = [\n /** Damaged, or not the format its name says. */\n 'file-unreadable',\n /** Protected by a password. */\n 'file-protected',\n /** A type nothing here converts. */\n 'file-type-unsupported',\n /** Encrypted, or an old .xls renamed to .xlsx. */\n 'spreadsheet-protected',\n /** Not a valid .xlsx package. */\n 'spreadsheet-unreadable',\n 'spreadsheet-macros',\n /** Over the cap on what a read inflates, `limitBytes` says which. */\n 'spreadsheet-too-large',\n /** No sheet with a header row, so nothing to query. */\n 'spreadsheet-no-table',\n /** An audio file with no speech the transcription could hear. */\n 'audio-no-speech',\n /** An audio file over the cap on what is transcribed, `limitBytes` says which. */\n 'audio-too-large',\n /**\n * A web page too heavy to read: over the cap on its HTML, or past the\n * memory its reading is allowed.\n */\n 'page-too-large',\n] as const\n\nexport type UnprocessableFileReason =\n (typeof UNPROCESSABLE_FILE_REASONS)[number]\n\n/** Every `reason` a failed document can carry in `metadata.lastIndexError`. */\nexport const DOCUMENT_INDEX_ERROR_REASONS: readonly (\n DocumentRefusalReason | UnprocessableFileReason\n)[] = [...DOCUMENT_REFUSAL_REASONS, ...UNPROCESSABLE_FILE_REASONS]\n\n/**\n * Why the last run of a document failed in a way no other attempt can change,\n * as the processor records it in `metadata.lastIndexError`. A dead source URL\n * carries its HTTP `status` and `url`; anything else one of the\n * {@link DOCUMENT_INDEX_ERROR_REASONS}, with the `limitBytes` it went past\n * when it is too large. `reason` stays a string here, so a row written by a\n * newer processor still reads. `message` is the English one of the logs.\n */\nexport const DocumentIndexErrorSchema = z\n .object({\n reason: z.string().optional(),\n status: z.number().optional(),\n url: z.string().optional(),\n limitBytes: z.number().optional(),\n message: z.string().optional(),\n at: z.string().optional(),\n })\n .loose()\n\nexport type DocumentIndexError = z.infer<typeof DocumentIndexErrorSchema>\n\n/**\n * Metadata structure for document.metadata column\n * Consolidates all metadata from converters and source info\n */\nexport const DocumentMetadataSchema = z\n .object({\n // === Source Info (URL and synced documents) ===\n source: DocumentSourceSchema.optional(),\n\n // === Media Info (File documents only) ===\n media: MediaSchema.optional(),\n\n // === Common Fields (all document types) ===\n title: z.string().optional(),\n author: z.string().optional(),\n description: z.string().optional(),\n summary: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n\n // === PDF Specific ===\n subject: z.string().optional(),\n creator: z.string().optional(), // Original application\n producer: z.string().optional(), // PDF generator software\n creationDate: z.string().optional(),\n modificationDate: z.string().optional(),\n pageCount: decodeOnly(\n z.union([z.number(), z.array(z.unknown())]),\n z.number(),\n (val) => (Array.isArray(val) ? val.length : val),\n ).optional(),\n encrypted: z.boolean().optional(),\n\n // === DOCX Specific ===\n characterCount: z.number().optional(),\n lineCount: z.number().optional(),\n\n // === URL Specific ===\n siteName: z.string().optional(),\n canonicalUrl: z.url().optional(),\n imageUrl: z.url().optional(),\n favicon: z.url().optional(),\n type: z.string().optional(), // og:type (article, website, etc.)\n locale: z.string().optional(),\n tags: z.array(z.string()).optional(),\n publishedTime: z.string().optional(),\n modifiedTime: z.string().optional(),\n\n // === Metrics (all document types) ===\n wordCount: z.number().optional(),\n paragraphCount: z.number().optional(),\n readingTime: z.number().optional(), // in minutes\n\n // === OCR (PDF documents) ===\n ocrUsed: z.boolean().optional(),\n ocrProvider: z.string().optional(),\n ocrModel: z.string().optional(),\n ocrPages: z.string().optional(),\n ocrCost: z.number().optional(),\n ocrError: z.string().optional(),\n\n // === RAG / Duplicates / Sync Info ===\n chunksCount: z.number().optional(),\n redundantChunksCount: z.number().optional(),\n hasRedundantChunks: z.boolean().optional(),\n /**\n * The chunk sync of this document dead-lettered: written by the DLQ\n * drain, read by `searchIndexStatusOf` against the chunks' age.\n */\n searchIndexError: z.object({ at: z.string() }).optional(),\n\n // === Conversion Options (for reprocessing) ===\n conversionOptions: ConversionOptionsSchema.optional(),\n\n // === Spreadsheets queried with SQL instead of chunked ===\n tabular: DocumentTabularSchema.optional(),\n\n // === Why the last run failed for good, removed by a success ===\n // A shape nobody expected drops the reason, not the whole response.\n lastIndexError: DocumentIndexErrorSchema.optional().catch(undefined),\n })\n .loose() // Allow additional custom fields\n\nexport type DocumentMetadata = z.infer<typeof DocumentMetadataSchema>\n\n/**\n * Document type enum\n *\n * - 'file': Document created from uploaded file (PDF, DOCX)\n * - 'url': Document created from web scraping\n * - 'revised-answer': Document created from revised AI answer\n * - 'plain-text': Document created from plain text input\n */\nexport enum DocumentType {\n File = 'file',\n Url = 'url',\n RevisedAnswer = 'revised-answer',\n PlainText = 'plain-text',\n}\n\n// ===== Schemas =====\n\n/**\n * Full document schema from database\n * Extended with computed field chunksCount\n */\nconst BaseDocumentSchema = z.object({\n id: z.string(),\n externalId: z.string().nullable(),\n name: z.string(),\n content: z.string(),\n type: z.string(),\n language: z.string(),\n metadata: z.record(z.string(), z.unknown()),\n indexStatus: z.string(),\n processedAt: z.coerce.date().nullable(),\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 organizationId: z.string(),\n priority: z.number().int().min(1).max(5).default(3),\n /** The automatic refresh trigger; null is manual, and only `url` can have one. */\n refreshInterval: z.enum(DocumentRefreshInterval).nullable().optional(),\n /**\n * When the trigger next comes due. Null with an interval set means paused:\n * the source answered that the page is gone for good.\n */\n nextRefreshAt: z.coerce.date().nullable().optional(),\n /**\n * Which sync source owns this document, when one does.\n *\n * Null is the ordinary case. A non-null value means a job keeps the\n * document up to date, which is what makes it read only: editing it, moving\n * it or deleting it by hand would be undone at the next run, silently.\n * Written only by providers that own their documents, never by a crawl that\n * merely discovered a page.\n */\n sourceProvider: z.enum(DocumentSourceProvider).nullable().optional(),\n})\n\nexport const DocumentSchema = BaseDocumentSchema.extend({\n type: z.enum(DocumentType),\n indexStatus: z.enum(IndexStatus),\n metadata: DocumentMetadataSchema,\n // Add computed field for chunks count (populated by service layer)\n chunksCount: z.number().optional(),\n // Computed fields for redundancy tracking\n redundantChunksCount: z.number().optional(),\n hasRedundantChunks: z.boolean().optional(),\n /** Whether the search can find the chunks (K1), apart from `indexStatus`. */\n searchStatus: z.enum(SearchIndexStatus).optional(),\n // Agent IDs associated with this document (populated in single-item reads)\n agentIds: z.array(z.string()).optional(),\n // Folder ID for this document within an agent context (populated in agent-scoped reads)\n folderId: z.string().nullable().optional(),\n // Full folder path string e.g. \"Parent / Child\" (populated in list reads when agentId is set)\n folderPath: z.string().nullable().optional(),\n /** Who sent the document to the trash, by name (populated in trash reads). */\n deletedByName: z.string().nullable().optional(),\n})\n\n/**\n * The document types the trash holds: the ones a person adds to a knowledge\n * base by hand. A revised answer lives and dies with its own page, so it is\n * never listed, restored or emptied from here.\n */\nexport const DOCUMENT_TRASH_TYPES = [\n DocumentType.File,\n DocumentType.Url,\n DocumentType.PlainText,\n] as const\n\n/**\n * Why a restore was refused (docs/specs/document-trash.md, Decision 3), sent\n * as `additionalData.reason` of a `conflict` problem. The third case of the\n * decision, a folder that no longer exists, is not a refusal: the document\n * goes back to the root and the answer says so.\n */\nexport enum DocumentRestoreRefusal {\n /** Every agent the document belonged to has been deleted. */\n AgentGone = 'agent-gone',\n /**\n * A live document of the same source holds its remote identity; its id\n * travels as `additionalData.documentId`.\n */\n IdentityTaken = 'identity-taken',\n}\n\nexport const DocumentRestoreResultSchema = z.object({\n document: DocumentSchema,\n /** Its folder was gone, so it went back to the root of its agent. */\n returnedToRoot: z.boolean(),\n})\n\nexport const DocumentTrashSummarySchema = z.object({\n /** Documents in the trash of the agent, the ones it can restore. */\n count: z.number().int(),\n /**\n * Days a document stays in the trash before it is destroyed for good,\n * `0` when nothing destroys it (`trashRetentionDaysOf`).\n */\n retentionDays: z.number().int().min(0),\n})\n\nexport const DocumentEmptyTrashDtoSchema = z.object({\n agentId: z.uuid(),\n})\n\nexport const DocumentEmptyTrashResultSchema = z.object({\n purged: z.number().int(),\n /** Still in the trash: one call empties a batch, the caller asks again. */\n remaining: z.number().int(),\n})\n\n/**\n * Query parameters for listing documents with pagination, sorting, and filters\n */\nexport const DocumentQuerystringSchema = z.object({\n ...zodQs.pagination(),\n ...zodQs.sort(['id', 'updatedAt', 'createdAt', 'name', 'deletedAt']),\n ...zodQs.filters(['type', 'language', 'agentId', 'indexStatus']),\n // 'true' lists the trash instead of the knowledge base: a flat list, by\n // agent, of what that agent can restore. Every other read keeps ignoring\n // deleted documents.\n 'filter[deleted]': z.enum(['true', 'false']).optional(),\n ...zodQs.fullText(),\n ...zodQs.ids(),\n 'filter[similarity]': z.string().optional(),\n // UUID = documents in that folder; 'null' = documents at root (no folder); absent = all documents\n 'filter[folderId]': z.string().optional(),\n 'filter[hasRedundantChunks]': z.string().optional(),\n // One of the intervals, 'null' for the documents left on manual, 'auto' for\n // any of the three. Same convention as `filter[folderId]`, and handled\n // outside `getFilters` for the same reason: `inArray` cannot say IS NULL.\n 'filter[refreshInterval]': z.string().optional(),\n // A provider, 'null' for the documents nobody syncs, 'any' for the ones a\n // source owns whoever it is. Same convention and the same reason as above.\n 'filter[sourceProvider]': z.string().optional(),\n // What the badge of the row reads. An enum, not a list: a value nobody\n // offers is refused rather than answered with an empty page.\n 'filter[status]': z.enum(DocumentListStatus).optional(),\n})\n\n/**\n * Document creation schema for POST /documents endpoint\n *\n * Supports three types:\n * - 'file': Requires media object with uploaded file info\n * - 'url': Requires url string for web scraping\n * - 'revised-answer': Requires content (created from revisedAnswer service)\n */\nexport const DocumentCreateDtoSchema = z\n .object({\n type: z.enum(DocumentType).default(DocumentType.File),\n name: z.string().min(1).max(255).optional(),\n language: z.enum(SupportedLanguage).optional(),\n organizationId: z.string(),\n agentIds: z.array(z.string()).min(1, 'At least one agent is required'),\n folderId: z.uuid().nullable().optional(),\n media: MediaSchema.optional(),\n url: z.url().optional(),\n content: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n extractionStrategy: z.enum(ExtractionStrategy).optional(),\n browserEngine: z.enum(BrowserEngine).optional(),\n headers: HeadesSchema.nullish().default([]),\n aiDescriptionModel: z.string().optional(),\n aiDescriptionPrompt: z.string().max(5000).optional(),\n forceOcr: z.boolean().default(false),\n pages: z\n .string()\n .max(100)\n .regex(/^\\d+(\\s*-\\s*\\d+)?(\\s*,\\s*\\d+(\\s*-\\s*\\d+)?)*$/)\n .optional(),\n priority: z.number().int().min(1).max(5).default(3).optional(),\n refreshInterval: z.enum(DocumentRefreshInterval).nullable().optional(),\n /**\n * The web source this page is imported for: the pages ticked in the\n * crawler dialog when it also creates a source. They land in the\n * source's folder as pages the source discovered, so its removal\n * option and its early refresh apply to them from the first run.\n */\n syncSourceId: z.uuid().optional(),\n })\n .superRefine((data, ctx) => {\n if (data.syncSourceId && data.type !== DocumentType.Url) {\n ctx.addIssue({\n code: 'custom',\n params: {\n i18n: 'errors.syncSourceUrlOnly',\n },\n path: ['syncSourceId'],\n })\n }\n if (data.type === DocumentType.File && !data.media) {\n ctx.addIssue({\n code: 'custom',\n params: {\n i18n: 'errors.required',\n },\n path: ['media'],\n })\n return\n }\n if (data.type === DocumentType.Url && !data.url) {\n ctx.addIssue({\n code: 'custom',\n params: {\n i18n: 'errors.required',\n },\n path: ['url'],\n })\n }\n // The database has the same CHECK, but a 400 saying which field is\n // wrong beats a constraint violation surfacing as a 500.\n if (data.refreshInterval && data.type !== DocumentType.Url) {\n ctx.addIssue({\n code: 'custom',\n params: {\n i18n: 'errors.refreshIntervalUrlOnly',\n },\n path: ['refreshInterval'],\n })\n }\n if (\n data.type === DocumentType.PlainText &&\n !(data.name || data.language)\n ) {\n if (!data.name) {\n ctx.addIssue({\n code: 'custom',\n params: {\n i18n: 'errors.required',\n },\n path: ['name'],\n })\n }\n if (!data.language) {\n ctx.addIssue({\n code: 'custom',\n params: {\n i18n: 'errors.required',\n },\n path: ['language'],\n })\n }\n }\n })\n\n/**\n * Document update schema for PUT /documents/:id endpoint\n *\n * All fields are optional, but at least one must be provided\n */\nexport const DocumentUpdateDtoSchema = z.object({\n id: z.string(),\n organizationId: z.string(),\n content: z.string().optional(),\n name: z.string().min(1).max(255).optional(),\n language: z.enum(SupportedLanguage).optional(),\n priority: z.number().int().min(1).max(5).optional(),\n agentIds: z.array(z.string()).min(1).optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n refreshInterval: z.enum(DocumentRefreshInterval).nullable().optional(),\n})\n\n/** Body of `PATCH /documents/:id/refresh-interval`, twin of the priority route. */\nexport const DocumentRefreshIntervalDtoSchema = z.object({\n refreshInterval: z.enum(DocumentRefreshInterval).nullable(),\n})\n\n/** Body of `POST /documents/bulk-refresh-interval`. */\nexport const DocumentBulkRefreshIntervalDtoSchema = z.object({\n ids: z.array(z.uuid()).min(1).max(100),\n refreshInterval: z.enum(DocumentRefreshInterval).nullable(),\n})\n\n/** Body of `POST /documents/bulk-refresh`, twin of `bulk-reprocess`. */\nexport const DocumentBulkRefreshDtoSchema = z.object({\n ids: z.array(z.uuid()).min(1).max(100),\n})\n\n// ===== Type Exports =====\n\nexport type Document = z.infer<typeof DocumentSchema>\nexport type DocumentQuerystring = z.infer<typeof DocumentQuerystringSchema>\nexport type DocumentCreateDto = z.infer<typeof DocumentCreateDtoSchema>\nexport type DocumentUpdateDto = z.infer<typeof DocumentUpdateDtoSchema>\nexport type DocumentRefreshIntervalDto = z.infer<\n typeof DocumentRefreshIntervalDtoSchema\n>\nexport type DocumentBulkRefreshIntervalDto = z.infer<\n typeof DocumentBulkRefreshIntervalDtoSchema\n>\nexport type DocumentBulkRefreshDto = z.infer<\n typeof DocumentBulkRefreshDtoSchema\n>\nexport type DocumentRestoreResult = z.infer<typeof DocumentRestoreResultSchema>\nexport type DocumentTrashSummary = z.infer<typeof DocumentTrashSummarySchema>\nexport type DocumentEmptyTrashDto = z.infer<typeof DocumentEmptyTrashDtoSchema>\nexport type DocumentEmptyTrashResult = z.infer<\n typeof DocumentEmptyTrashResultSchema\n>\n\n// ===== Helper Functions =====\n\nexport const getStatusColor = (status: IndexStatus) => {\n switch (status) {\n case IndexStatus.Success:\n return 'success'\n case IndexStatus.Failed:\n return 'danger'\n case IndexStatus.Processing:\n return 'warning'\n default:\n return 'info'\n }\n}\n\nexport const getStatusIcon = (status: IndexStatus) => {\n switch (status) {\n case IndexStatus.Success:\n return 'ri:check-line'\n case IndexStatus.Failed:\n return 'ri:error-warning-line'\n case IndexStatus.Processing:\n return 'ri:hourglass-line'\n default:\n return 'ri:time-line'\n }\n}\n\n/**\n * The color of a search state: green when the agents find the document, the\n * wait and the fixable ones in warning, the failure in danger, and gray where\n * there is nothing to find.\n */\nexport const getSearchStatusColor = (status: SearchIndexStatus) => {\n switch (status) {\n case SearchIndexStatus.Indexed:\n return 'success'\n case SearchIndexStatus.Failed:\n return 'danger'\n case SearchIndexStatus.Empty:\n return 'gray'\n default:\n return 'warning'\n }\n}\n\nexport const getSearchStatusIcon = (status: SearchIndexStatus) => {\n switch (status) {\n case SearchIndexStatus.Indexed:\n return 'ri:check-line'\n case SearchIndexStatus.Pending:\n return 'ri:hourglass-line'\n case SearchIndexStatus.Empty:\n return 'ri:indeterminate-circle-line'\n default:\n return 'ri:error-warning-line'\n }\n}\n\nexport const getTypeIcon = (type: DocumentType) => {\n switch (type) {\n case DocumentType.File:\n return 'ri:file-line'\n case DocumentType.Url:\n return 'ri:link'\n case DocumentType.RevisedAnswer:\n return 'ri:feedback-line'\n default:\n return 'ri:input-method-line'\n }\n}\n\nexport const getFileIcon = (extension: string) => {\n const ext = (\n extension.startsWith('.') ? extension.slice(1) : extension\n ).toLowerCase()\n switch (ext) {\n case 'pdf':\n return 'ri:file-pdf-2-line'\n case 'doc':\n case 'docx':\n return 'ri:file-word-line'\n case 'xls':\n case 'xlsx':\n return 'ri:file-excel-line'\n case 'ppt':\n case 'pptx':\n return 'ri:file-ppt-line'\n case 'txt':\n return 'ri:file-text-line'\n case 'mp3':\n case 'wav':\n case 'ogg':\n return 'ri:file-music-line'\n case 'mp4':\n case 'avi':\n case 'mkv':\n return 'ri:file-video-line'\n case 'jpg':\n case 'jpeg':\n case 'png':\n case 'gif':\n case 'bmp':\n case 'svg':\n return 'ri:file-image-line'\n case 'zip':\n case 'rar':\n case '7z':\n return 'ri:file-zip-line'\n default:\n return 'ri:file-line'\n }\n}\n\n/** Whether a MIME type is an image. */\nexport const isImageMime = (mimeType?: string | null): boolean =>\n (mimeType ?? '').startsWith('image/')\n\n/** Whether a file MIME type can be previewed inline in the browser (image or\n * PDF) instead of being forced as a download. Shared by every file-list surface\n * so the preview/download decision stays consistent. */\nexport const isInlineViewable = (mimeType?: string | null): boolean =>\n isImageMime(mimeType) || mimeType === 'application/pdf'\n\n/** File-type identity for list rows and previews: icon, accent color\n * (CSS value driving glyph and tile tint) and a short human kind label. */\nexport interface FileKind {\n icon: string\n accent: string\n label: string\n}\n\n/** File-type identity derived from a MIME type. Accents match the chat\n * attachment cards (PkChatbotFilePreview) so files read the same everywhere. */\nexport const fileKindForMime = (mimeType?: string | null): FileKind => {\n const mime = mimeType ?? ''\n if (isImageMime(mime)) {\n return { icon: 'ri:image-line', accent: '#ec4899', label: 'Image' }\n }\n if (mime === 'application/pdf') {\n return { icon: 'ri:file-pdf-2-line', accent: '#e2483d', label: 'PDF' }\n }\n if (mime === 'application/msword' || mime.includes('wordprocessingml')) {\n return { icon: 'ri:file-word-line', accent: '#2b7de9', label: 'Word' }\n }\n if (mime === 'application/vnd.ms-excel' || mime.includes('spreadsheetml')) {\n return {\n icon: 'ri:file-excel-line',\n accent: '#1f9d57',\n label: 'Spreadsheet',\n }\n }\n if (\n mime === 'application/vnd.ms-powerpoint' ||\n mime.includes('presentationml')\n ) {\n return {\n icon: 'ri:file-ppt-line',\n accent: '#d98324',\n label: 'Presentation',\n }\n }\n if (mime.startsWith('audio/')) {\n return { icon: 'ri:file-music-line', accent: '#8b5cf6', label: 'Audio' }\n }\n if (mime.startsWith('video/')) {\n return { icon: 'ri:file-video-line', accent: '#6366f1', label: 'Video' }\n }\n if (\n mime === 'application/zip' ||\n mime === 'application/x-rar-compressed' ||\n mime === 'application/x-7z-compressed'\n ) {\n return { icon: 'ri:file-zip-line', accent: '#c08a1e', label: 'Archive' }\n }\n if (mime.startsWith('text/')) {\n return { icon: 'ri:file-text-line', accent: '#64748b', label: 'Text' }\n }\n return { icon: 'ri:file-line', accent: '#64748b', label: 'File' }\n}\n\n/** Icon for a file-list row, derived from its MIME type. */\nexport const fileIconForMime = (mimeType?: string | null): string =>\n fileKindForMime(mimeType).icon\n"],"mappings":"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"}
|