@iblai/iblai-js 2.39.0 → 2.40.0

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.
@@ -256448,6 +256448,35 @@ function trimTrailingSlashes(value) {
256448
256448
  end -= 1;
256449
256449
  return end === value.length ? value : value.slice(0, end);
256450
256450
  }
256451
+ /**
256452
+ * Point a backend media link at the DM mount it is actually served from. When
256453
+ * DM sits behind a path prefix on the host app (`https://os.ibl.ai/backend/dm`),
256454
+ * the backend builds media URLs from the proxied request and drops that prefix
256455
+ * (`https://os.ibl.ai/media/...`, or a bare `/media/...`), which 404s. Only
256456
+ * `/media/` links on the DM host are rewritten; everything else passes through.
256457
+ */
256458
+ function resolveDmMediaUrl(url, dmUrl) {
256459
+ if (!url || !dmUrl)
256460
+ return url;
256461
+ const isRootRelative = url.startsWith('/') && !url.startsWith('//');
256462
+ if (!isRootRelative && !/^https?:\/\//i.test(url))
256463
+ return url;
256464
+ let dm;
256465
+ let target;
256466
+ try {
256467
+ dm = new URL(dmUrl);
256468
+ target = new URL(url, dm.origin);
256469
+ }
256470
+ catch (_a) {
256471
+ return url;
256472
+ }
256473
+ // Host, not origin: behind a TLS-terminating proxy the backend may build http:// links.
256474
+ if (target.host !== dm.host || !target.pathname.startsWith('/media/'))
256475
+ return url;
256476
+ target.protocol = dm.protocol;
256477
+ target.pathname = `${trimTrailingSlashes(dm.pathname)}${target.pathname}`;
256478
+ return target.href;
256479
+ }
256451
256480
 
256452
256481
  // Pure logic behind the application form (questions) editor. No React here so
256453
256482
  // it stays unit testable. The backend validates schemas on save and remains
@@ -260860,6 +260889,7 @@ function AgentSettingsProvider({ children, ...value }) {
260860
260889
  value.rbacPermissions,
260861
260890
  value.executeGatedAction,
260862
260891
  value.visibilityOptions,
260892
+ value.dmUrl,
260863
260893
  ]);
260864
260894
  return jsx(AgentSettingsContext.Provider, { value: ctx, children: children });
260865
260895
  }
@@ -285443,6 +285473,7 @@ const OutsideButtons = ({
285443
285473
  const UploadMenu = ({ onFileInputTrigger, onCameraTrigger, disabled = false, mentorId, tenantKey, isPublicRoute, }) => {
285444
285474
  const t = useChatT();
285445
285475
  const host = useChatHost();
285476
+ const cameraPickedRef = useRef(false);
285446
285477
  const showAttachment = useShowAttachment({
285447
285478
  mentorId: mentorId || host.mentorId,
285448
285479
  tenantKey: tenantKey || host.tenantKey,
@@ -285458,7 +285489,9 @@ const UploadMenu = ({ onFileInputTrigger, onCameraTrigger, disabled = false, men
285458
285489
  {
285459
285490
  labelKey: 'camera',
285460
285491
  icon: jsx(Camera, { className: "h-5 w-5 text-gray-600" }),
285461
- action: onCameraTrigger,
285492
+ action: () => {
285493
+ cameraPickedRef.current = true;
285494
+ },
285462
285495
  isEnabled: host.features.camera,
285463
285496
  },
285464
285497
  // {
@@ -285488,7 +285521,16 @@ const UploadMenu = ({ onFileInputTrigger, onCameraTrigger, disabled = false, men
285488
285521
  if (!showAttachment || uploadMenuItems.length === 0) {
285489
285522
  return null;
285490
285523
  }
285491
- return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: jsxs(Button$1, { variant: "ghost", size: "icon", disabled: disabled, "aria-label": t('chat.chatInputFormUploadMenu.attachFile'), className: "h-8 w-8 rounded-lg text-gray-600 transition-all duration-200 hover:border hover:border-[#38A1E5] hover:bg-[#F5F8FF] disabled:cursor-not-allowed disabled:opacity-50", children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "sr-only", children: t('chat.chatInputFormUploadMenu.attachFile') })] }) }), jsx(DropdownMenuContent, { align: "start", className: "z-50 w-56 p-2", children: uploadMenuItems.map((item) => (jsxs(DropdownMenuItem, { onClick: item.action, className: "flex cursor-pointer items-center gap-3 rounded-lg p-3 hover:border-[#38A1E5] hover:bg-gray-50", children: [item.icon, jsx("span", { className: "text-gray-700", children: t(`chat.chatInputFormUploadMenu.${item.labelKey}`) })] }, item.labelKey))) })] }));
285524
+ return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: jsxs(Button$1, { variant: "ghost", size: "icon", disabled: disabled, "aria-label": t('chat.chatInputFormUploadMenu.attachFile'), className: "h-8 w-8 rounded-lg text-gray-600 transition-all duration-200 hover:border hover:border-[#38A1E5] hover:bg-[#F5F8FF] disabled:cursor-not-allowed disabled:opacity-50", children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "sr-only", children: t('chat.chatInputFormUploadMenu.attachFile') })] }) }), jsx(DropdownMenuContent, { align: "start", className: "z-50 w-56 p-2",
285525
+ // Opening the camera dialog (a separate Radix copy) while this menu is
285526
+ // mounted leaves <body> stuck at `pointer-events: none`; this fires after
285527
+ // the menu has unmounted.
285528
+ onCloseAutoFocus: () => {
285529
+ if (!cameraPickedRef.current)
285530
+ return;
285531
+ cameraPickedRef.current = false;
285532
+ onCameraTrigger();
285533
+ }, children: uploadMenuItems.map((item) => (jsxs(DropdownMenuItem, { onClick: item.action, className: "flex cursor-pointer items-center gap-3 rounded-lg p-3 hover:border-[#38A1E5] hover:bg-gray-50", children: [item.icon, jsx("span", { className: "text-gray-700", children: t(`chat.chatInputFormUploadMenu.${item.labelKey}`) })] }, item.labelKey))) })] }));
285492
285534
  };
285493
285535
 
285494
285536
  const CameraCaptureDialog = ({ open, onOpenChange, onCapture, facingMode = 'user', }) => {
@@ -286524,6 +286566,7 @@ function ComposerPlusMenu({ isMobile, disabled = false, attachDisabled = false,
286524
286566
  const [memoryOpen, setMemoryOpen] = useState(false);
286525
286567
  const [sheetPage, setSheetPage] = useState(null);
286526
286568
  const [sheetProvider, setSheetProvider] = useState(null);
286569
+ const cameraPickedRef = useRef(false);
286527
286570
  const showAttach = showUpload || showCamera;
286528
286571
  const showTools = tools.length > 0;
286529
286572
  const showSkills = skills.length > 0;
@@ -286583,7 +286626,19 @@ function ComposerPlusMenu({ isMobile, disabled = false, attachDisabled = false,
286583
286626
  }
286584
286627
  // --------------------------------------------------------------- desktop
286585
286628
  const hasListAfterAttach = showTools || showSkills || showModel || showPrompts || showMemory;
286586
- return (jsxs(Popover, { open: memoryOpen, onOpenChange: setMemoryOpen, children: [jsx(PopoverAnchor, { asChild: true, children: jsx("div", { className: "flex shrink-0", children: jsxs(DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: trigger }), jsxs(DropdownMenuContent, { align: "start", sideOffset: 8, collisionPadding: 8, "data-testid": "composer-plus-menu", className: cn(POP_CLASS, 'flex w-[248px] flex-col gap-0.5'), children: [showUpload && (jsxs(DropdownMenuItem, { className: ROW_CLASS, disabled: attachDisabled, onSelect: onUploadFile, children: [jsx(Paperclip, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatInputFormUploadMenu.uploadFile') })] })), showCamera && (jsxs(DropdownMenuItem, { className: ROW_CLASS, disabled: attachDisabled, onSelect: onCamera, children: [jsx(Camera, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatInputFormUploadMenu.camera') })] })), showAttach && hasListAfterAttach && (jsx(DropdownMenuSeparator, { className: "mx-1.5 my-1 bg-gray-200" })), showTools && (jsxs(DropdownMenuSub, { children: [jsx(SubTrigger, { icon: jsx(SlidersHorizontal, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), label: t('chat.chatComposer.tools'), count: activeToolCount, countLabel: t('chat.chatComposer.activeCount', { count: activeToolCount }), testId: "composer-tools-trigger" }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "composer-tools-menu", "aria-label": t('chat.chatComposer.tools'), className: cn(POP_CLASS, 'flex max-h-[min(70vh,30rem)] w-56 flex-col gap-0.5 overflow-y-auto'), children: [modes.map((tool) => (jsx(ToolCheckboxItem, { tool: tool, label: toolLabel(tool) }, tool.key))), modes.length > 0 && plainTools.length > 0 && (jsx(DropdownMenuSeparator, { className: "mx-1.5 my-1 bg-gray-200" })), plainTools.map((tool) => (jsx(ToolCheckboxItem, { tool: tool, label: toolLabel(tool) }, tool.key)))] }) })] })), showSkills && (jsxs(DropdownMenuSub, { children: [jsx(SubTrigger, { icon: jsx(Zap, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), label: t('chat.chatInputFormInsideButtons.skills'), count: activeSkillCount, countLabel: t('chat.chatComposer.activeCount', { count: activeSkillCount }), testId: "skills-menu-trigger" }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "skills-menu-content", "aria-label": t('chat.chatInputFormInsideButtons.skills'), onScroll: handleSkillsScroll, className: cn(POP_CLASS, 'flex max-h-[min(60vh,20rem)] w-56 flex-col gap-0.5 overflow-y-auto'), children: [skills.map((skill) => {
286629
+ return (jsxs(Popover, { open: memoryOpen, onOpenChange: setMemoryOpen, children: [jsx(PopoverAnchor, { asChild: true, children: jsx("div", { className: "flex shrink-0", children: jsxs(DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: trigger }), jsxs(DropdownMenuContent, { align: "start", sideOffset: 8, collisionPadding: 8, "data-testid": "composer-plus-menu", className: cn(POP_CLASS, 'flex w-[248px] flex-col gap-0.5'),
286630
+ // The camera dialog's DismissableLayer is a separate Radix copy from
286631
+ // this menu's: opened while the menu is mounted it records the menu's
286632
+ // `pointer-events: none` on <body> as the original and restores it on
286633
+ // close, freezing the page. This fires after the menu has unmounted.
286634
+ onCloseAutoFocus: () => {
286635
+ if (!cameraPickedRef.current)
286636
+ return;
286637
+ cameraPickedRef.current = false;
286638
+ onCamera();
286639
+ }, children: [showUpload && (jsxs(DropdownMenuItem, { className: ROW_CLASS, disabled: attachDisabled, onSelect: onUploadFile, children: [jsx(Paperclip, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatInputFormUploadMenu.uploadFile') })] })), showCamera && (jsxs(DropdownMenuItem, { className: ROW_CLASS, disabled: attachDisabled, onSelect: () => {
286640
+ cameraPickedRef.current = true;
286641
+ }, children: [jsx(Camera, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatInputFormUploadMenu.camera') })] })), showAttach && hasListAfterAttach && (jsx(DropdownMenuSeparator, { className: "mx-1.5 my-1 bg-gray-200" })), showTools && (jsxs(DropdownMenuSub, { children: [jsx(SubTrigger, { icon: jsx(SlidersHorizontal, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), label: t('chat.chatComposer.tools'), count: activeToolCount, countLabel: t('chat.chatComposer.activeCount', { count: activeToolCount }), testId: "composer-tools-trigger" }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "composer-tools-menu", "aria-label": t('chat.chatComposer.tools'), className: cn(POP_CLASS, 'flex max-h-[min(70vh,30rem)] w-56 flex-col gap-0.5 overflow-y-auto'), children: [modes.map((tool) => (jsx(ToolCheckboxItem, { tool: tool, label: toolLabel(tool) }, tool.key))), modes.length > 0 && plainTools.length > 0 && (jsx(DropdownMenuSeparator, { className: "mx-1.5 my-1 bg-gray-200" })), plainTools.map((tool) => (jsx(ToolCheckboxItem, { tool: tool, label: toolLabel(tool) }, tool.key)))] }) })] })), showSkills && (jsxs(DropdownMenuSub, { children: [jsx(SubTrigger, { icon: jsx(Zap, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), label: t('chat.chatInputFormInsideButtons.skills'), count: activeSkillCount, countLabel: t('chat.chatComposer.activeCount', { count: activeSkillCount }), testId: "skills-menu-trigger" }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "skills-menu-content", "aria-label": t('chat.chatInputFormInsideButtons.skills'), onScroll: handleSkillsScroll, className: cn(POP_CLASS, 'flex max-h-[min(60vh,20rem)] w-56 flex-col gap-0.5 overflow-y-auto'), children: [skills.map((skill) => {
286587
286642
  const armed = activeSkillSlugs.has(skill.slug);
286588
286643
  return (jsxs(CheckboxItem2, { checked: armed, "data-testid": `skills-menu-item-${skill.slug}`, title: `/${skill.slug}`, className: cn(ROW_CLASS, 'h-auto min-h-9 py-1.5'), onSelect: () => onToggleSkill(skill), children: [jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [jsx("span", { "data-testid": "skills-menu-item-name", className: "break-words", children: skill.name }), jsxs("span", { "data-testid": "skills-menu-item-slug", className: "text-xs break-all text-gray-500", children: ["/", skill.slug] })] }), armed && (jsx(Check, { className: "h-4 w-4 text-[#2563eb]", "aria-hidden": "true" }))] }, skill.unique_id));
286589
286644
  }), loadingMoreRow] }) })] })), models && (jsxs(DropdownMenuSub, { children: [jsxs(DropdownMenuSubTrigger, { "data-testid": "composer-model-trigger", className: cn(ROW_CLASS, '[&>svg:last-child]:h-3.5 [&>svg:last-child]:w-3.5 [&>svg:last-child]:text-gray-500'), children: [jsx(Cpu, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatComposer.model') }), jsx("span", { className: "max-w-[96px] truncate text-[13px] text-gray-500", children: models.current.label })] }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "composer-model-providers", "aria-label": t('chat.chatComposer.modelForThisChat'), className: cn(POP_CLASS, 'flex max-h-[min(70vh,30rem)] w-[272px] flex-col gap-0.5 overflow-y-auto'), children: [jsxs("div", { className: "shrink-0 px-2.5 pt-2 pb-1.5", children: [jsx("div", { className: "text-sm font-semibold text-gray-900", children: t('chat.chatComposer.modelForThisChat') }), jsx("div", { className: "text-xs text-gray-600", children: t('chat.chatComposer.newChatsUseDefault', {
@@ -287660,7 +287715,7 @@ const ProjectFilesModal$1 = lazy(() => Promise.resolve().then(function () { retu
287660
287715
  const AddMentorToProjectModal$1 = lazy(() => Promise.resolve().then(function () { return addMentorToProjectModal; }).then((mod) => ({
287661
287716
  default: mod.AddMentorToProjectModal,
287662
287717
  })));
287663
- function ProjectLandingPage({ project, mentorName, sessionId, onSubmit, onScreenSharingClick, isScreenSharingModalOpen, onPhoneCallClick, stopGenerating, tenantKey, username, enableSafetyDisclaimer, enableWebBrowsing, isStreaming, updateSessionTools, setSessionTools, activeTools, screenSharing, deepResearch, studyMode, imageGeneration, codeInterpreter, promptsIsEnabled, isPreviewMode, setMessage, mentorId, mentorUniqueId, projectId, googleSlidesIsEnabled, googleDocumentIsEnabled, artifactsEnabled, userIsStudent, isPublicRoute, navigateToProject, showExploreMentors = false, disabledResourceTypes, maxUploadSizeMb, dropboxExtensions, }) {
287718
+ function ProjectLandingPage({ project, mentorName, sessionId, onSubmit, onScreenSharingClick, isScreenSharingModalOpen, onPhoneCallClick, stopGenerating, tenantKey, username, enableSafetyDisclaimer, enableWebBrowsing, isStreaming, updateSessionTools, setSessionTools, activeTools, screenSharing, deepResearch, studyMode, imageGeneration, codeInterpreter, promptsIsEnabled, isPreviewMode, setMessage, mentorId, mentorUniqueId, projectId, googleSlidesIsEnabled, googleDocumentIsEnabled, artifactsEnabled, userIsStudent, isPublicRoute, navigateToProject, showExploreMentors = false, disabledResourceTypes, maxUploadSizeMb, dropboxExtensions, dmUrl, }) {
287664
287719
  const [isInstructionsModalOpen, setIsInstructionsModalOpen] = useState(false);
287665
287720
  const [isFilesModalOpen, setIsFilesModalOpen] = useState(false);
287666
287721
  const [isAddMentorModalOpen, setIsAddMentorModalOpen] = useState(false);
@@ -287686,7 +287741,7 @@ function ProjectLandingPage({ project, mentorName, sessionId, onSubmit, onScreen
287686
287741
  jsxs("div", { className: "flex h-full w-full flex-col", "data-testid": "project-landing-page", children: [jsxs("div", { className: "scrollbar-none flex min-h-0 flex-1 flex-col justify-center-safe gap-5 overflow-y-auto px-2 pt-2 pb-4", children: [header, context] }), jsx("div", { className: "w-full shrink-0", children: composer })] })) : (
287687
287742
  // Desktop: one centred 640px column — header, disclaimer + composer, then
287688
287743
  // the project's files, instructions and agents.
287689
- jsxs("div", { className: "scrollbar-none flex h-full w-full flex-col items-center justify-center-safe overflow-y-auto px-4 py-6", "data-testid": "project-landing-page", children: [header, jsx("div", { className: "w-full max-w-[640px] shrink-0", children: composer }), jsx("div", { className: "mt-5 flex w-full max-w-[640px] shrink-0 flex-col gap-7", children: context })] })), isInstructionsModalOpen && (jsx(Suspense, { fallback: null, children: jsx(ProjectInstructionsModal$1, { isOpen: isInstructionsModalOpen, onClose: () => setIsInstructionsModalOpen(false), tenantKey: tenantKey, projectId: projectId, username: username }) })), isFilesModalOpen && (jsx(Suspense, { fallback: null, children: jsx(ProjectFilesModal$1, { isOpen: isFilesModalOpen, onClose: () => setIsFilesModalOpen(false), tenantKey: tenantKey, mentorId: mentorId, username: username, disabledResourceTypes: disabledResourceTypes, maxUploadSizeMb: maxUploadSizeMb, dropboxExtensions: dropboxExtensions }) })), isAddMentorModalOpen && (jsx(Suspense, { fallback: null, children: jsx(AddMentorToProjectModal$1, { isOpen: isAddMentorModalOpen, onClose: () => setIsAddMentorModalOpen(false), projectName: project.name, tenantKey: tenantKey, projectId: projectId, username: username, isPublicRoute: isPublicRoute }) }))] }));
287744
+ jsxs("div", { className: "scrollbar-none flex h-full w-full flex-col items-center justify-center-safe overflow-y-auto px-4 py-6", "data-testid": "project-landing-page", children: [header, jsx("div", { className: "w-full max-w-[640px] shrink-0", children: composer }), jsx("div", { className: "mt-5 flex w-full max-w-[640px] shrink-0 flex-col gap-7", children: context })] })), isInstructionsModalOpen && (jsx(Suspense, { fallback: null, children: jsx(ProjectInstructionsModal$1, { isOpen: isInstructionsModalOpen, onClose: () => setIsInstructionsModalOpen(false), tenantKey: tenantKey, projectId: projectId, username: username }) })), isFilesModalOpen && (jsx(Suspense, { fallback: null, children: jsx(ProjectFilesModal$1, { isOpen: isFilesModalOpen, onClose: () => setIsFilesModalOpen(false), tenantKey: tenantKey, mentorId: mentorId, username: username, disabledResourceTypes: disabledResourceTypes, maxUploadSizeMb: maxUploadSizeMb, dropboxExtensions: dropboxExtensions, dmUrl: dmUrl }) })), isAddMentorModalOpen && (jsx(Suspense, { fallback: null, children: jsx(AddMentorToProjectModal$1, { isOpen: isAddMentorModalOpen, onClose: () => setIsAddMentorModalOpen(false), projectName: project.name, tenantKey: tenantKey, projectId: projectId, username: username, isPublicRoute: isPublicRoute }) }))] }));
287690
287745
  }
287691
287746
 
287692
287747
  function MinimumMentorAlert({ open, onOpenChange }) {
@@ -287984,7 +288039,7 @@ function DatasetItem({ dataset, onSelect, isSelected, labels }) {
287984
288039
  const [isDeleteDatasetModalOpen, setIsDeleteDatasetModalOpen] = React__default.useState(false);
287985
288040
  const [isRetrainScheduleModalOpen, setIsRetrainScheduleModalOpen] = React__default.useState(false);
287986
288041
  const [isTrainOrDeleteModalOpen, setIsTrainOrDeleteModalOpen] = React__default.useState(false);
287987
- const { tenantKey, username } = useAgentSettings();
288042
+ const { tenantKey, username, dmUrl } = useAgentSettings();
287988
288043
  const [editTrainingDocument, { isLoading: isEditTrainingDocumentLoading }] = useEditTrainingDocumentMutation();
287989
288044
  const handleEditTrainingDocument = async (data, callback) => {
287990
288045
  try {
@@ -288030,7 +288085,7 @@ function DatasetItem({ dataset, onSelect, isSelected, labels }) {
288030
288085
  };
288031
288086
  return (jsxs(Fragment$1, { children: [jsxs(TableRow, { className: `border-b last:border-0 ${onSelect ? 'hover:bg-muted/50 cursor-pointer' : ''} ${isSelected ? 'bg-blue-50' : ''}`, onClick: onSelect ? () => onSelect(dataset) : undefined, children: [jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsx(TableCell, { className: "max-w-[200px] truncate p-3 font-medium whitespace-nowrap text-[#646464]", children: jsx(WithFormPermissions, { name: ['document_name', 'url'],
288032
288087
  // @ts-ignore
288033
- permissions: (_a = dataset === null || dataset === void 0 ? void 0 : dataset.permissions) === null || _a === void 0 ? void 0 : _a.field, children: () => (jsx("a", { href: dataset.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:text-blue-800 hover:underline", children: dataset.document_name || dataset.url })) }) }) }), jsx(TooltipContent, { className: "bg-gray-700 px-3 py-2 text-sm font-medium whitespace-nowrap text-white shadow-sm transition-opacity duration-300", children: jsx("p", { children: dataset.document_name || dataset.url }) })] }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: jsx(WithFormPermissions, { name: "document_type",
288088
+ permissions: (_a = dataset === null || dataset === void 0 ? void 0 : dataset.permissions) === null || _a === void 0 ? void 0 : _a.field, children: () => (jsx("a", { href: resolveDmMediaUrl(dataset.url, dmUrl), target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:text-blue-800 hover:underline", children: dataset.document_name || dataset.url })) }) }) }), jsx(TooltipContent, { className: "bg-gray-700 px-3 py-2 text-sm font-medium whitespace-nowrap text-white shadow-sm transition-opacity duration-300", children: jsx("p", { children: dataset.document_name || dataset.url }) })] }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: jsx(WithFormPermissions, { name: "document_type",
288034
288089
  // @ts-ignore
288035
288090
  permissions: (_b = dataset === null || dataset === void 0 ? void 0 : dataset.permissions) === null || _b === void 0 ? void 0 : _b.field, children: () => {
288036
288091
  var _a, _b;
@@ -289641,7 +289696,7 @@ const PROJECT_FILES_DATASET_LABELS = resolveDatasetsTabLabels({
289641
289696
  table: { emptyState: 'No files found' },
289642
289697
  });
289643
289698
  function ProjectFilesModal(props) {
289644
- return (jsx(AgentSettingsProvider, { tenantKey: props.tenantKey, mentorId: props.mentorId, username: props.username, enableRBAC: false, children: jsx(ProjectFilesModalInner, { ...props }) }));
289699
+ return (jsx(AgentSettingsProvider, { tenantKey: props.tenantKey, mentorId: props.mentorId, username: props.username, enableRBAC: false, dmUrl: props.dmUrl, children: jsx(ProjectFilesModalInner, { ...props }) }));
289645
289700
  }
289646
289701
  function ProjectFilesModalInner({ isOpen, onClose, disabledResourceTypes, maxUploadSizeMb, dropboxExtensions, }) {
289647
289702
  var _a;
@@ -288317,6 +288317,35 @@ function trimTrailingSlashes(value) {
288317
288317
  end -= 1;
288318
288318
  return end === value.length ? value : value.slice(0, end);
288319
288319
  }
288320
+ /**
288321
+ * Point a backend media link at the DM mount it is actually served from. When
288322
+ * DM sits behind a path prefix on the host app (`https://os.ibl.ai/backend/dm`),
288323
+ * the backend builds media URLs from the proxied request and drops that prefix
288324
+ * (`https://os.ibl.ai/media/...`, or a bare `/media/...`), which 404s. Only
288325
+ * `/media/` links on the DM host are rewritten; everything else passes through.
288326
+ */
288327
+ function resolveDmMediaUrl(url, dmUrl) {
288328
+ if (!url || !dmUrl)
288329
+ return url;
288330
+ const isRootRelative = url.startsWith('/') && !url.startsWith('//');
288331
+ if (!isRootRelative && !/^https?:\/\//i.test(url))
288332
+ return url;
288333
+ let dm;
288334
+ let target;
288335
+ try {
288336
+ dm = new URL(dmUrl);
288337
+ target = new URL(url, dm.origin);
288338
+ }
288339
+ catch (_a) {
288340
+ return url;
288341
+ }
288342
+ // Host, not origin: behind a TLS-terminating proxy the backend may build http:// links.
288343
+ if (target.host !== dm.host || !target.pathname.startsWith('/media/'))
288344
+ return url;
288345
+ target.protocol = dm.protocol;
288346
+ target.pathname = `${trimTrailingSlashes(dm.pathname)}${target.pathname}`;
288347
+ return target.href;
288348
+ }
288320
288349
 
288321
288350
  // Pure logic behind the application form (questions) editor. No React here so
288322
288351
  // it stays unit testable. The backend validates schemas on save and remains
@@ -292645,6 +292674,7 @@ function AgentSettingsProvider({ children, ...value }) {
292645
292674
  value.rbacPermissions,
292646
292675
  value.executeGatedAction,
292647
292676
  value.visibilityOptions,
292677
+ value.dmUrl,
292648
292678
  ]);
292649
292679
  return jsx(AgentSettingsContext.Provider, { value: ctx, children: children });
292650
292680
  }
@@ -304920,6 +304950,7 @@ const OutsideButtons = ({
304920
304950
  const UploadMenu = ({ onFileInputTrigger, onCameraTrigger, disabled = false, mentorId, tenantKey, isPublicRoute, }) => {
304921
304951
  const t = useChatT();
304922
304952
  const host = useChatHost();
304953
+ const cameraPickedRef = useRef(false);
304923
304954
  const showAttachment = useShowAttachment({
304924
304955
  mentorId: mentorId || host.mentorId,
304925
304956
  tenantKey: tenantKey || host.tenantKey,
@@ -304935,7 +304966,9 @@ const UploadMenu = ({ onFileInputTrigger, onCameraTrigger, disabled = false, men
304935
304966
  {
304936
304967
  labelKey: 'camera',
304937
304968
  icon: jsx(Camera, { className: "h-5 w-5 text-gray-600" }),
304938
- action: onCameraTrigger,
304969
+ action: () => {
304970
+ cameraPickedRef.current = true;
304971
+ },
304939
304972
  isEnabled: host.features.camera,
304940
304973
  },
304941
304974
  // {
@@ -304965,7 +304998,16 @@ const UploadMenu = ({ onFileInputTrigger, onCameraTrigger, disabled = false, men
304965
304998
  if (!showAttachment || uploadMenuItems.length === 0) {
304966
304999
  return null;
304967
305000
  }
304968
- return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: jsxs(Button$1, { variant: "ghost", size: "icon", disabled: disabled, "aria-label": t('chat.chatInputFormUploadMenu.attachFile'), className: "h-8 w-8 rounded-lg text-gray-600 transition-all duration-200 hover:border hover:border-[#38A1E5] hover:bg-[#F5F8FF] disabled:cursor-not-allowed disabled:opacity-50", children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "sr-only", children: t('chat.chatInputFormUploadMenu.attachFile') })] }) }), jsx(DropdownMenuContent, { align: "start", className: "z-50 w-56 p-2", children: uploadMenuItems.map((item) => (jsxs(DropdownMenuItem, { onClick: item.action, className: "flex cursor-pointer items-center gap-3 rounded-lg p-3 hover:border-[#38A1E5] hover:bg-gray-50", children: [item.icon, jsx("span", { className: "text-gray-700", children: t(`chat.chatInputFormUploadMenu.${item.labelKey}`) })] }, item.labelKey))) })] }));
305001
+ return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: jsxs(Button$1, { variant: "ghost", size: "icon", disabled: disabled, "aria-label": t('chat.chatInputFormUploadMenu.attachFile'), className: "h-8 w-8 rounded-lg text-gray-600 transition-all duration-200 hover:border hover:border-[#38A1E5] hover:bg-[#F5F8FF] disabled:cursor-not-allowed disabled:opacity-50", children: [jsx(Plus, { className: "h-4 w-4" }), jsx("span", { className: "sr-only", children: t('chat.chatInputFormUploadMenu.attachFile') })] }) }), jsx(DropdownMenuContent, { align: "start", className: "z-50 w-56 p-2",
305002
+ // Opening the camera dialog (a separate Radix copy) while this menu is
305003
+ // mounted leaves <body> stuck at `pointer-events: none`; this fires after
305004
+ // the menu has unmounted.
305005
+ onCloseAutoFocus: () => {
305006
+ if (!cameraPickedRef.current)
305007
+ return;
305008
+ cameraPickedRef.current = false;
305009
+ onCameraTrigger();
305010
+ }, children: uploadMenuItems.map((item) => (jsxs(DropdownMenuItem, { onClick: item.action, className: "flex cursor-pointer items-center gap-3 rounded-lg p-3 hover:border-[#38A1E5] hover:bg-gray-50", children: [item.icon, jsx("span", { className: "text-gray-700", children: t(`chat.chatInputFormUploadMenu.${item.labelKey}`) })] }, item.labelKey))) })] }));
304969
305011
  };
304970
305012
 
304971
305013
  const CameraCaptureDialog = ({ open, onOpenChange, onCapture, facingMode = 'user', }) => {
@@ -306597,6 +306639,7 @@ function ComposerPlusMenu({ isMobile, disabled = false, attachDisabled = false,
306597
306639
  const [memoryOpen, setMemoryOpen] = useState(false);
306598
306640
  const [sheetPage, setSheetPage] = useState(null);
306599
306641
  const [sheetProvider, setSheetProvider] = useState(null);
306642
+ const cameraPickedRef = useRef(false);
306600
306643
  const showAttach = showUpload || showCamera;
306601
306644
  const showTools = tools.length > 0;
306602
306645
  const showSkills = skills.length > 0;
@@ -306656,7 +306699,19 @@ function ComposerPlusMenu({ isMobile, disabled = false, attachDisabled = false,
306656
306699
  }
306657
306700
  // --------------------------------------------------------------- desktop
306658
306701
  const hasListAfterAttach = showTools || showSkills || showModel || showPrompts || showMemory;
306659
- return (jsxs(Popover, { open: memoryOpen, onOpenChange: setMemoryOpen, children: [jsx(PopoverAnchor, { asChild: true, children: jsx("div", { className: "flex shrink-0", children: jsxs(DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: trigger }), jsxs(DropdownMenuContent, { align: "start", sideOffset: 8, collisionPadding: 8, "data-testid": "composer-plus-menu", className: cn(POP_CLASS, 'flex w-[248px] flex-col gap-0.5'), children: [showUpload && (jsxs(DropdownMenuItem, { className: ROW_CLASS, disabled: attachDisabled, onSelect: onUploadFile, children: [jsx(Paperclip, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatInputFormUploadMenu.uploadFile') })] })), showCamera && (jsxs(DropdownMenuItem, { className: ROW_CLASS, disabled: attachDisabled, onSelect: onCamera, children: [jsx(Camera, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatInputFormUploadMenu.camera') })] })), showAttach && hasListAfterAttach && (jsx(DropdownMenuSeparator, { className: "mx-1.5 my-1 bg-gray-200" })), showTools && (jsxs(DropdownMenuSub, { children: [jsx(SubTrigger, { icon: jsx(SlidersHorizontal, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), label: t('chat.chatComposer.tools'), count: activeToolCount, countLabel: t('chat.chatComposer.activeCount', { count: activeToolCount }), testId: "composer-tools-trigger" }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "composer-tools-menu", "aria-label": t('chat.chatComposer.tools'), className: cn(POP_CLASS, 'flex max-h-[min(70vh,30rem)] w-56 flex-col gap-0.5 overflow-y-auto'), children: [modes.map((tool) => (jsx(ToolCheckboxItem, { tool: tool, label: toolLabel(tool) }, tool.key))), modes.length > 0 && plainTools.length > 0 && (jsx(DropdownMenuSeparator, { className: "mx-1.5 my-1 bg-gray-200" })), plainTools.map((tool) => (jsx(ToolCheckboxItem, { tool: tool, label: toolLabel(tool) }, tool.key)))] }) })] })), showSkills && (jsxs(DropdownMenuSub, { children: [jsx(SubTrigger, { icon: jsx(Zap, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), label: t('chat.chatInputFormInsideButtons.skills'), count: activeSkillCount, countLabel: t('chat.chatComposer.activeCount', { count: activeSkillCount }), testId: "skills-menu-trigger" }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "skills-menu-content", "aria-label": t('chat.chatInputFormInsideButtons.skills'), onScroll: handleSkillsScroll, className: cn(POP_CLASS, 'flex max-h-[min(60vh,20rem)] w-56 flex-col gap-0.5 overflow-y-auto'), children: [skills.map((skill) => {
306702
+ return (jsxs(Popover, { open: memoryOpen, onOpenChange: setMemoryOpen, children: [jsx(PopoverAnchor, { asChild: true, children: jsx("div", { className: "flex shrink-0", children: jsxs(DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [jsx(DropdownMenuTrigger, { asChild: true, disabled: disabled, children: trigger }), jsxs(DropdownMenuContent, { align: "start", sideOffset: 8, collisionPadding: 8, "data-testid": "composer-plus-menu", className: cn(POP_CLASS, 'flex w-[248px] flex-col gap-0.5'),
306703
+ // The camera dialog's DismissableLayer is a separate Radix copy from
306704
+ // this menu's: opened while the menu is mounted it records the menu's
306705
+ // `pointer-events: none` on <body> as the original and restores it on
306706
+ // close, freezing the page. This fires after the menu has unmounted.
306707
+ onCloseAutoFocus: () => {
306708
+ if (!cameraPickedRef.current)
306709
+ return;
306710
+ cameraPickedRef.current = false;
306711
+ onCamera();
306712
+ }, children: [showUpload && (jsxs(DropdownMenuItem, { className: ROW_CLASS, disabled: attachDisabled, onSelect: onUploadFile, children: [jsx(Paperclip, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatInputFormUploadMenu.uploadFile') })] })), showCamera && (jsxs(DropdownMenuItem, { className: ROW_CLASS, disabled: attachDisabled, onSelect: () => {
306713
+ cameraPickedRef.current = true;
306714
+ }, children: [jsx(Camera, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatInputFormUploadMenu.camera') })] })), showAttach && hasListAfterAttach && (jsx(DropdownMenuSeparator, { className: "mx-1.5 my-1 bg-gray-200" })), showTools && (jsxs(DropdownMenuSub, { children: [jsx(SubTrigger, { icon: jsx(SlidersHorizontal, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), label: t('chat.chatComposer.tools'), count: activeToolCount, countLabel: t('chat.chatComposer.activeCount', { count: activeToolCount }), testId: "composer-tools-trigger" }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "composer-tools-menu", "aria-label": t('chat.chatComposer.tools'), className: cn(POP_CLASS, 'flex max-h-[min(70vh,30rem)] w-56 flex-col gap-0.5 overflow-y-auto'), children: [modes.map((tool) => (jsx(ToolCheckboxItem, { tool: tool, label: toolLabel(tool) }, tool.key))), modes.length > 0 && plainTools.length > 0 && (jsx(DropdownMenuSeparator, { className: "mx-1.5 my-1 bg-gray-200" })), plainTools.map((tool) => (jsx(ToolCheckboxItem, { tool: tool, label: toolLabel(tool) }, tool.key)))] }) })] })), showSkills && (jsxs(DropdownMenuSub, { children: [jsx(SubTrigger, { icon: jsx(Zap, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), label: t('chat.chatInputFormInsideButtons.skills'), count: activeSkillCount, countLabel: t('chat.chatComposer.activeCount', { count: activeSkillCount }), testId: "skills-menu-trigger" }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "skills-menu-content", "aria-label": t('chat.chatInputFormInsideButtons.skills'), onScroll: handleSkillsScroll, className: cn(POP_CLASS, 'flex max-h-[min(60vh,20rem)] w-56 flex-col gap-0.5 overflow-y-auto'), children: [skills.map((skill) => {
306660
306715
  const armed = activeSkillSlugs.has(skill.slug);
306661
306716
  return (jsxs(CheckboxItem2, { checked: armed, "data-testid": `skills-menu-item-${skill.slug}`, title: `/${skill.slug}`, className: cn(ROW_CLASS, 'h-auto min-h-9 py-1.5'), onSelect: () => onToggleSkill(skill), children: [jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [jsx("span", { "data-testid": "skills-menu-item-name", className: "break-words", children: skill.name }), jsxs("span", { "data-testid": "skills-menu-item-slug", className: "text-xs break-all text-gray-500", children: ["/", skill.slug] })] }), armed && (jsx(Check, { className: "h-4 w-4 text-[#2563eb]", "aria-hidden": "true" }))] }, skill.unique_id));
306662
306717
  }), loadingMoreRow] }) })] })), models && (jsxs(DropdownMenuSub, { children: [jsxs(DropdownMenuSubTrigger, { "data-testid": "composer-model-trigger", className: cn(ROW_CLASS, '[&>svg:last-child]:h-3.5 [&>svg:last-child]:w-3.5 [&>svg:last-child]:text-gray-500'), children: [jsx(Cpu, { className: "h-4 w-4 text-gray-600", "aria-hidden": "true" }), jsx("span", { className: "flex-1", children: t('chat.chatComposer.model') }), jsx("span", { className: "max-w-[96px] truncate text-[13px] text-gray-500", children: models.current.label })] }), jsx(Portal2$1, { container: portalContainer !== null && portalContainer !== void 0 ? portalContainer : undefined, children: jsxs(DropdownMenuSubContent, { sideOffset: 6, alignOffset: -7, collisionPadding: 8, "data-testid": "composer-model-providers", "aria-label": t('chat.chatComposer.modelForThisChat'), className: cn(POP_CLASS, 'flex max-h-[min(70vh,30rem)] w-[272px] flex-col gap-0.5 overflow-y-auto'), children: [jsxs("div", { className: "shrink-0 px-2.5 pt-2 pb-1.5", children: [jsx("div", { className: "text-sm font-semibold text-gray-900", children: t('chat.chatComposer.modelForThisChat') }), jsx("div", { className: "text-xs text-gray-600", children: t('chat.chatComposer.newChatsUseDefault', {
@@ -307733,7 +307788,7 @@ const ProjectFilesModal$1 = lazy(() => Promise.resolve().then(function () { retu
307733
307788
  const AddMentorToProjectModal$1 = lazy(() => Promise.resolve().then(function () { return addMentorToProjectModal; }).then((mod) => ({
307734
307789
  default: mod.AddMentorToProjectModal,
307735
307790
  })));
307736
- function ProjectLandingPage({ project, mentorName, sessionId, onSubmit, onScreenSharingClick, isScreenSharingModalOpen, onPhoneCallClick, stopGenerating, tenantKey, username, enableSafetyDisclaimer, enableWebBrowsing, isStreaming, updateSessionTools, setSessionTools, activeTools, screenSharing, deepResearch, studyMode, imageGeneration, codeInterpreter, promptsIsEnabled, isPreviewMode, setMessage, mentorId, mentorUniqueId, projectId, googleSlidesIsEnabled, googleDocumentIsEnabled, artifactsEnabled, userIsStudent, isPublicRoute, navigateToProject, showExploreMentors = false, disabledResourceTypes, maxUploadSizeMb, dropboxExtensions, }) {
307791
+ function ProjectLandingPage({ project, mentorName, sessionId, onSubmit, onScreenSharingClick, isScreenSharingModalOpen, onPhoneCallClick, stopGenerating, tenantKey, username, enableSafetyDisclaimer, enableWebBrowsing, isStreaming, updateSessionTools, setSessionTools, activeTools, screenSharing, deepResearch, studyMode, imageGeneration, codeInterpreter, promptsIsEnabled, isPreviewMode, setMessage, mentorId, mentorUniqueId, projectId, googleSlidesIsEnabled, googleDocumentIsEnabled, artifactsEnabled, userIsStudent, isPublicRoute, navigateToProject, showExploreMentors = false, disabledResourceTypes, maxUploadSizeMb, dropboxExtensions, dmUrl, }) {
307737
307792
  const [isInstructionsModalOpen, setIsInstructionsModalOpen] = useState(false);
307738
307793
  const [isFilesModalOpen, setIsFilesModalOpen] = useState(false);
307739
307794
  const [isAddMentorModalOpen, setIsAddMentorModalOpen] = useState(false);
@@ -307759,7 +307814,7 @@ function ProjectLandingPage({ project, mentorName, sessionId, onSubmit, onScreen
307759
307814
  jsxs("div", { className: "flex h-full w-full flex-col", "data-testid": "project-landing-page", children: [jsxs("div", { className: "scrollbar-none flex min-h-0 flex-1 flex-col justify-center-safe gap-5 overflow-y-auto px-2 pt-2 pb-4", children: [header, context] }), jsx("div", { className: "w-full shrink-0", children: composer })] })) : (
307760
307815
  // Desktop: one centred 640px column — header, disclaimer + composer, then
307761
307816
  // the project's files, instructions and agents.
307762
- jsxs("div", { className: "scrollbar-none flex h-full w-full flex-col items-center justify-center-safe overflow-y-auto px-4 py-6", "data-testid": "project-landing-page", children: [header, jsx("div", { className: "w-full max-w-[640px] shrink-0", children: composer }), jsx("div", { className: "mt-5 flex w-full max-w-[640px] shrink-0 flex-col gap-7", children: context })] })), isInstructionsModalOpen && (jsx(Suspense, { fallback: null, children: jsx(ProjectInstructionsModal$1, { isOpen: isInstructionsModalOpen, onClose: () => setIsInstructionsModalOpen(false), tenantKey: tenantKey, projectId: projectId, username: username }) })), isFilesModalOpen && (jsx(Suspense, { fallback: null, children: jsx(ProjectFilesModal$1, { isOpen: isFilesModalOpen, onClose: () => setIsFilesModalOpen(false), tenantKey: tenantKey, mentorId: mentorId, username: username, disabledResourceTypes: disabledResourceTypes, maxUploadSizeMb: maxUploadSizeMb, dropboxExtensions: dropboxExtensions }) })), isAddMentorModalOpen && (jsx(Suspense, { fallback: null, children: jsx(AddMentorToProjectModal$1, { isOpen: isAddMentorModalOpen, onClose: () => setIsAddMentorModalOpen(false), projectName: project.name, tenantKey: tenantKey, projectId: projectId, username: username, isPublicRoute: isPublicRoute }) }))] }));
307817
+ jsxs("div", { className: "scrollbar-none flex h-full w-full flex-col items-center justify-center-safe overflow-y-auto px-4 py-6", "data-testid": "project-landing-page", children: [header, jsx("div", { className: "w-full max-w-[640px] shrink-0", children: composer }), jsx("div", { className: "mt-5 flex w-full max-w-[640px] shrink-0 flex-col gap-7", children: context })] })), isInstructionsModalOpen && (jsx(Suspense, { fallback: null, children: jsx(ProjectInstructionsModal$1, { isOpen: isInstructionsModalOpen, onClose: () => setIsInstructionsModalOpen(false), tenantKey: tenantKey, projectId: projectId, username: username }) })), isFilesModalOpen && (jsx(Suspense, { fallback: null, children: jsx(ProjectFilesModal$1, { isOpen: isFilesModalOpen, onClose: () => setIsFilesModalOpen(false), tenantKey: tenantKey, mentorId: mentorId, username: username, disabledResourceTypes: disabledResourceTypes, maxUploadSizeMb: maxUploadSizeMb, dropboxExtensions: dropboxExtensions, dmUrl: dmUrl }) })), isAddMentorModalOpen && (jsx(Suspense, { fallback: null, children: jsx(AddMentorToProjectModal$1, { isOpen: isAddMentorModalOpen, onClose: () => setIsAddMentorModalOpen(false), projectName: project.name, tenantKey: tenantKey, projectId: projectId, username: username, isPublicRoute: isPublicRoute }) }))] }));
307763
307818
  }
307764
307819
 
307765
307820
  function MinimumMentorAlert({ open, onOpenChange }) {
@@ -308057,7 +308112,7 @@ function DatasetItem({ dataset, onSelect, isSelected, labels }) {
308057
308112
  const [isDeleteDatasetModalOpen, setIsDeleteDatasetModalOpen] = React__default.useState(false);
308058
308113
  const [isRetrainScheduleModalOpen, setIsRetrainScheduleModalOpen] = React__default.useState(false);
308059
308114
  const [isTrainOrDeleteModalOpen, setIsTrainOrDeleteModalOpen] = React__default.useState(false);
308060
- const { tenantKey, username } = useAgentSettings();
308115
+ const { tenantKey, username, dmUrl } = useAgentSettings();
308061
308116
  const [editTrainingDocument, { isLoading: isEditTrainingDocumentLoading }] = useEditTrainingDocumentMutation();
308062
308117
  const handleEditTrainingDocument = async (data, callback) => {
308063
308118
  try {
@@ -308103,7 +308158,7 @@ function DatasetItem({ dataset, onSelect, isSelected, labels }) {
308103
308158
  };
308104
308159
  return (jsxs(Fragment$1, { children: [jsxs(TableRow, { className: `border-b last:border-0 ${onSelect ? 'hover:bg-muted/50 cursor-pointer' : ''} ${isSelected ? 'bg-blue-50' : ''}`, onClick: onSelect ? () => onSelect(dataset) : undefined, children: [jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { asChild: true, children: jsx(TableCell, { className: "max-w-[200px] truncate p-3 font-medium whitespace-nowrap text-[#646464]", children: jsx(WithFormPermissions, { name: ['document_name', 'url'],
308105
308160
  // @ts-ignore
308106
- permissions: (_a = dataset === null || dataset === void 0 ? void 0 : dataset.permissions) === null || _a === void 0 ? void 0 : _a.field, children: () => (jsx("a", { href: dataset.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:text-blue-800 hover:underline", children: dataset.document_name || dataset.url })) }) }) }), jsx(TooltipContent, { className: "bg-gray-700 px-3 py-2 text-sm font-medium whitespace-nowrap text-white shadow-sm transition-opacity duration-300", children: jsx("p", { children: dataset.document_name || dataset.url }) })] }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: jsx(WithFormPermissions, { name: "document_type",
308161
+ permissions: (_a = dataset === null || dataset === void 0 ? void 0 : dataset.permissions) === null || _a === void 0 ? void 0 : _a.field, children: () => (jsx("a", { href: resolveDmMediaUrl(dataset.url, dmUrl), target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:text-blue-800 hover:underline", children: dataset.document_name || dataset.url })) }) }) }), jsx(TooltipContent, { className: "bg-gray-700 px-3 py-2 text-sm font-medium whitespace-nowrap text-white shadow-sm transition-opacity duration-300", children: jsx("p", { children: dataset.document_name || dataset.url }) })] }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: jsx(WithFormPermissions, { name: "document_type",
308107
308162
  // @ts-ignore
308108
308163
  permissions: (_b = dataset === null || dataset === void 0 ? void 0 : dataset.permissions) === null || _b === void 0 ? void 0 : _b.field, children: () => {
308109
308164
  var _a, _b;
@@ -309714,7 +309769,7 @@ const PROJECT_FILES_DATASET_LABELS = resolveDatasetsTabLabels({
309714
309769
  table: { emptyState: 'No files found' },
309715
309770
  });
309716
309771
  function ProjectFilesModal(props) {
309717
- return (jsx(AgentSettingsProvider, { tenantKey: props.tenantKey, mentorId: props.mentorId, username: props.username, enableRBAC: false, children: jsx(ProjectFilesModalInner, { ...props }) }));
309772
+ return (jsx(AgentSettingsProvider, { tenantKey: props.tenantKey, mentorId: props.mentorId, username: props.username, enableRBAC: false, dmUrl: props.dmUrl, children: jsx(ProjectFilesModalInner, { ...props }) }));
309718
309773
  }
309719
309774
  function ProjectFilesModalInner({ isOpen, onClose, disabledResourceTypes, maxUploadSizeMb, dropboxExtensions, }) {
309720
309775
  var _a;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iblai/iblai-js",
3
- "version": "2.39.0",
3
+ "version": "2.40.0",
4
4
  "description": "Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package",
5
5
  "type": "module",
6
6
  "engines": {
@@ -76,9 +76,9 @@
76
76
  "axios": "1.13.6",
77
77
  "dotenv": "16.6.1",
78
78
  "winston": "3.19.0",
79
+ "@iblai/mcp": "1.31.0",
80
+ "@iblai/web-containers": "1.44.0",
79
81
  "@iblai/data-layer": "1.30.1",
80
- "@iblai/mcp": "1.30.0",
81
- "@iblai/web-containers": "1.43.0",
82
82
  "@iblai/web-utils": "2.9.0"
83
83
  },
84
84
  "peerDependencies": {