@iblai/iblai-js 2.3.9 → 2.3.11
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.
|
@@ -1134,7 +1134,9 @@ function useCuaDriver() {
|
|
|
1134
1134
|
// treating null as denied would make Cowork unusable on Linux and Windows.
|
|
1135
1135
|
const [accessibilityPermission, setAccessibilityPermission] = useState(null);
|
|
1136
1136
|
const [screenRecordingPermission, setScreenRecordingPermission] = useState(null);
|
|
1137
|
-
|
|
1137
|
+
// True once the host has answered a status check this mount — the retry
|
|
1138
|
+
// loop's stop condition, NOT a "ran once" guard (that was the bug).
|
|
1139
|
+
const statusSettled = useRef(false);
|
|
1138
1140
|
/**
|
|
1139
1141
|
* Read one permission. Checking never prompts (`AXIsProcessTrusted` /
|
|
1140
1142
|
* `CGPreflightScreenCaptureAccess`), which is what makes it safe to do on mount.
|
|
@@ -1232,11 +1234,13 @@ function useCuaDriver() {
|
|
|
1232
1234
|
}));
|
|
1233
1235
|
}, [setState]);
|
|
1234
1236
|
/**
|
|
1235
|
-
* Query driver install status + session support from the host.
|
|
1237
|
+
* Query driver install status + session support from the host. Returns
|
|
1238
|
+
* whether the host actually answered — the mount effect retries on `false`,
|
|
1239
|
+
* because one failed check must not disable Cowork for the whole session.
|
|
1236
1240
|
*/
|
|
1237
1241
|
const checkStatus = useCallback(async () => {
|
|
1238
1242
|
if (!isAvailable)
|
|
1239
|
-
return;
|
|
1243
|
+
return false;
|
|
1240
1244
|
// Refresh both permissions alongside install status (independent, no prompt).
|
|
1241
1245
|
refreshPermissions();
|
|
1242
1246
|
try {
|
|
@@ -1249,10 +1253,12 @@ function useCuaDriver() {
|
|
|
1249
1253
|
progress: result.installed ? 100 : prev.progress,
|
|
1250
1254
|
lastUpdated: new Date().toISOString(),
|
|
1251
1255
|
}));
|
|
1256
|
+
return true;
|
|
1252
1257
|
}
|
|
1253
1258
|
catch (error) {
|
|
1254
1259
|
console.error('[useCuaDriver] Failed to check status:', error);
|
|
1255
1260
|
setState((prev) => ({ ...prev, status: 'idle' }));
|
|
1261
|
+
return false;
|
|
1256
1262
|
}
|
|
1257
1263
|
}, [isAvailable, invoke, setState, refreshPermissions]);
|
|
1258
1264
|
/**
|
|
@@ -1372,12 +1378,41 @@ function useCuaDriver() {
|
|
|
1372
1378
|
};
|
|
1373
1379
|
// Only re-subscribe if the host itself changes — never on state.
|
|
1374
1380
|
}, [isAvailable, listen]);
|
|
1375
|
-
// Check status
|
|
1381
|
+
// Check status on mount, and RETRY until the host answers once.
|
|
1382
|
+
//
|
|
1383
|
+
// This used to be one-shot behind a ref, which is why a built app could show
|
|
1384
|
+
// Cowork grey for a whole session: the single check raced the IPC bridge
|
|
1385
|
+
// being injected into the (remote) app origin, failed, and nothing ever asked
|
|
1386
|
+
// again — `status` stayed null and null renders as "not supported". Dev never
|
|
1387
|
+
// showed it because fast-refresh remounts re-ran the check constantly; a
|
|
1388
|
+
// production build gets exactly one mount, so it retries with backoff instead.
|
|
1389
|
+
// Capped: a host that still hasn't answered after ~75s is genuinely broken,
|
|
1390
|
+
// and install()/stop() re-check on their own paths anyway.
|
|
1376
1391
|
useEffect(() => {
|
|
1377
|
-
if (!isAvailable
|
|
1392
|
+
if (!isAvailable)
|
|
1378
1393
|
return;
|
|
1379
|
-
|
|
1380
|
-
|
|
1394
|
+
let cancelled = false;
|
|
1395
|
+
let timer;
|
|
1396
|
+
let attempt = 0;
|
|
1397
|
+
const MAX_ATTEMPTS = 8;
|
|
1398
|
+
const run = async () => {
|
|
1399
|
+
if (cancelled || statusSettled.current)
|
|
1400
|
+
return;
|
|
1401
|
+
if (await checkStatus()) {
|
|
1402
|
+
statusSettled.current = true;
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
attempt += 1;
|
|
1406
|
+
if (cancelled || attempt >= MAX_ATTEMPTS)
|
|
1407
|
+
return;
|
|
1408
|
+
timer = setTimeout(run, Math.min(1000 * 2 ** attempt, 15000));
|
|
1409
|
+
};
|
|
1410
|
+
run();
|
|
1411
|
+
return () => {
|
|
1412
|
+
cancelled = true;
|
|
1413
|
+
if (timer)
|
|
1414
|
+
clearTimeout(timer);
|
|
1415
|
+
};
|
|
1381
1416
|
}, [isAvailable, checkStatus]);
|
|
1382
1417
|
// Only expose the feature as available inside the desktop (Tauri) app.
|
|
1383
1418
|
const finalIsAvailable = isAvailable && isTauriApp();
|
|
@@ -155392,6 +155427,19 @@ function StringSettingInput({ value, defaultValue, disabled, onSave, }) {
|
|
|
155392
155427
|
};
|
|
155393
155428
|
return (jsxs("div", { className: "flex items-center gap-2", children: [isDirty && (jsx(Button$1, { type: "button", size: "sm", onClick: handleSave, disabled: disabled, className: "h-8 bg-blue-500 hover:bg-blue-600 text-white", children: t('advancedAdvanced.save') })), jsx(Input, { value: localValue, onChange: (e) => setLocalValue(e.target.value), disabled: disabled, className: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464] text-sm" }), disabled && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] }));
|
|
155394
155429
|
}
|
|
155430
|
+
/**
|
|
155431
|
+
* A setting whose value is constrained to a fixed list of options declared in the
|
|
155432
|
+
* tenant metadata config, rendered as a dropdown.
|
|
155433
|
+
*/
|
|
155434
|
+
function hasSelectableOptions(metadataItem) {
|
|
155435
|
+
return Array.isArray(metadataItem.options) && metadataItem.options.length > 0;
|
|
155436
|
+
}
|
|
155437
|
+
function SelectSettingInput({ label, options, value, defaultValue, disabled, triggerClassName, onSelect, }) {
|
|
155438
|
+
// Values saved before an option was renamed/removed fall back to the default
|
|
155439
|
+
// so the trigger never renders an empty selection.
|
|
155440
|
+
const selectedValue = options.some((option) => option.value === value) ? value : defaultValue;
|
|
155441
|
+
return (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: selectedValue, onValueChange: onSelect, disabled: disabled, children: [jsx(SelectTrigger, { "aria-label": label, className: triggerClassName, children: jsx(SelectValue, {}) }), jsx(SelectContent, { className: "font-medium text-[#646464]", children: options.map((option) => (jsx(SelectItem, { value: option.value, children: option.label }, option.value))) })] }), disabled && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] }));
|
|
155442
|
+
}
|
|
155395
155443
|
function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatformBaseDomain, }) {
|
|
155396
155444
|
const t = useT();
|
|
155397
155445
|
const [updateTenantMetadata, { isLoading: isUpdatingTenantMetadata }] = useUpdateTenantMetadataMutation();
|
|
@@ -155427,33 +155475,35 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
155427
155475
|
'enable_profile_screen_on_start_page',
|
|
155428
155476
|
'enable_get_started_screen_on_start_page',
|
|
155429
155477
|
];
|
|
155478
|
+
// String settings rendered as a free-text input; every other string setting is
|
|
155479
|
+
// either handled by a dedicated component or exposed through its own options list
|
|
155480
|
+
const stringSettingSlugs = [
|
|
155481
|
+
'overall_default_mentor',
|
|
155482
|
+
'help_center_url',
|
|
155483
|
+
'monetization_base_path',
|
|
155484
|
+
'skills_welcome_tagline',
|
|
155485
|
+
];
|
|
155486
|
+
const getConfigurableMetadatas = () => {
|
|
155487
|
+
// Include boolean, select and whitelisted string settings, but exclude start
|
|
155488
|
+
// screen settings which are handled by the StartScreenContent component
|
|
155489
|
+
const configurableMetadatas = getAllMetadatas().filter((metadata) => (typeof metadata.defaultValue === 'boolean' ||
|
|
155490
|
+
hasSelectableOptions(metadata) ||
|
|
155491
|
+
(typeof metadata.defaultValue === 'string' &&
|
|
155492
|
+
stringSettingSlugs.includes(metadata.slug))) &&
|
|
155493
|
+
!startScreenSlugs.includes(metadata.slug));
|
|
155494
|
+
// Show all configurable settings when no SPA is specified
|
|
155495
|
+
if (!currentSPA)
|
|
155496
|
+
return configurableMetadatas;
|
|
155497
|
+
// Filter by current SPA if specified (case-insensitive partial matching)
|
|
155498
|
+
return configurableMetadatas.filter((metadata) => {
|
|
155499
|
+
const spaName = String(metadata.SPA || '').toLowerCase();
|
|
155500
|
+
const searchTerm = String(currentSPA).toLowerCase();
|
|
155501
|
+
return spaName.includes(searchTerm) || searchTerm.includes(spaName);
|
|
155502
|
+
});
|
|
155503
|
+
};
|
|
155430
155504
|
useEffect(() => {
|
|
155431
155505
|
if (metadataLoaded) {
|
|
155432
|
-
|
|
155433
|
-
// Include both boolean and string settings, but exclude start screen settings
|
|
155434
|
-
// which are handled by the StartScreenContent component
|
|
155435
|
-
const stringSettingSlugs = [
|
|
155436
|
-
'overall_default_mentor',
|
|
155437
|
-
'help_center_url',
|
|
155438
|
-
'monetization_base_path',
|
|
155439
|
-
'skills_welcome_tagline',
|
|
155440
|
-
];
|
|
155441
|
-
const configurableMetadatas = allMetadatas.filter((metadata) => (typeof metadata.defaultValue === 'boolean' ||
|
|
155442
|
-
(typeof metadata.defaultValue === 'string' &&
|
|
155443
|
-
stringSettingSlugs.includes(metadata.slug))) &&
|
|
155444
|
-
!startScreenSlugs.includes(metadata.slug));
|
|
155445
|
-
if (currentSPA) {
|
|
155446
|
-
// Filter by current SPA if specified (case-insensitive partial matching)
|
|
155447
|
-
setFlagTenantMetadatas(configurableMetadatas.filter((metadata) => {
|
|
155448
|
-
const spaName = String(metadata.SPA || '').toLowerCase();
|
|
155449
|
-
const searchTerm = String(currentSPA).toLowerCase();
|
|
155450
|
-
return spaName.includes(searchTerm) || searchTerm.includes(spaName);
|
|
155451
|
-
}));
|
|
155452
|
-
}
|
|
155453
|
-
else {
|
|
155454
|
-
// Show all configurable settings when no SPA is specified
|
|
155455
|
-
setFlagTenantMetadatas(configurableMetadatas);
|
|
155456
|
-
}
|
|
155506
|
+
setFlagTenantMetadatas(getConfigurableMetadatas());
|
|
155457
155507
|
}
|
|
155458
155508
|
}, [metadataLoaded, currentSPA]);
|
|
155459
155509
|
const updateOrganizationMetadata = async (key, value, callback) => {
|
|
@@ -155497,8 +155547,7 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
155497
155547
|
updateOrganizationMetadata(slug, newValue, () => {
|
|
155498
155548
|
toast.success(t('advancedAdvanced.settingUpdatedSuccessfully'));
|
|
155499
155549
|
// Update local state by refreshing the metadata
|
|
155500
|
-
setFlagTenantMetadatas(
|
|
155501
|
-
typeof metadata.defaultValue === 'boolean'));
|
|
155550
|
+
setFlagTenantMetadatas(getConfigurableMetadatas());
|
|
155502
155551
|
});
|
|
155503
155552
|
};
|
|
155504
155553
|
const handleMentorSelection = async (slug, mentorUniqueId) => {
|
|
@@ -155550,6 +155599,13 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
155550
155599
|
toast.success(t('advancedAdvanced.settingUpdatedSuccessfully'));
|
|
155551
155600
|
});
|
|
155552
155601
|
};
|
|
155602
|
+
const handleSelectSettingUpdate = async (slug, value) => {
|
|
155603
|
+
updateOrganizationMetadata(slug, value, () => {
|
|
155604
|
+
toast.success(t('advancedAdvanced.settingUpdatedSuccessfully'));
|
|
155605
|
+
// Update local state so the dropdown reflects the saved value
|
|
155606
|
+
setFlagTenantMetadatas(getConfigurableMetadatas());
|
|
155607
|
+
});
|
|
155608
|
+
};
|
|
155553
155609
|
// Helper function to get mentor name from JSON string, object, or unique_id
|
|
155554
155610
|
const getMentorName = (mentorValue) => {
|
|
155555
155611
|
var _a;
|
|
@@ -155584,11 +155640,17 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
155584
155640
|
? 'None'
|
|
155585
155641
|
: ((_a = metadataItem.value) !== null && _a !== void 0 ? _a : metadataItem.defaultValue);
|
|
155586
155642
|
const isMentorSetting = metadataItem.slug === 'overall_default_mentor';
|
|
155587
|
-
const
|
|
155588
|
-
|
|
155643
|
+
const selectOptions = hasSelectableOptions(metadataItem)
|
|
155644
|
+
? metadataItem.options
|
|
155645
|
+
: null;
|
|
155646
|
+
const isSelectSetting = selectOptions !== null;
|
|
155647
|
+
const isStringSetting = typeof metadataItem.defaultValue === 'string' &&
|
|
155648
|
+
!isMentorSetting &&
|
|
155649
|
+
!isSelectSetting;
|
|
155650
|
+
return (jsxs("div", { className: `flex items-center justify-between rounded-lg border px-6 ${isMentorSetting || isStringSetting || isSelectSetting ? 'py-4' : 'py-6'}`, style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: metadataItem.label }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": t('advancedAdvanced.moreInfoAbout', {
|
|
155589
155651
|
label: metadataItem.label,
|
|
155590
155652
|
}), className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "rounded-lg bg-gray-700 px-3 py-2 text-sm font-medium whitespace-nowrap text-white shadow-sm transition-opacity duration-300 z-50", children: jsx("p", { children: metadataItem.description ||
|
|
155591
|
-
t('advancedAdvanced.noDescriptionAvailable') }) })] }) })] }), jsx("div", { className: "flex items-center gap-2", children: isMentorSetting ? (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: currentValue || '', onValueChange: (value) => handleMentorSelection(metadataItem.slug, value), disabled: isUpdatingTenantMetadata, children: [jsx(SelectTrigger, { className: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464]", children: jsx(SelectValue, { placeholder: t('advancedAdvanced.selectAgent'), children: currentValue ? getMentorName(currentValue) : '' }) }), jsxs(SelectContent, { className: "font-medium text-[#646464]", children: [jsx("div", { className: "p-2", children: jsx(Input, { placeholder: t('advancedAdvanced.searchAgents'), value: mentorSearchQuery, onChange: (e) => handleMentorSearch(e.target.value), className: "mb-2 font-medium text-[#646464]" }) }), jsx(SelectItem, { value: "none", children: t('advancedAdvanced.none') }), isMentorsLoading ? (jsx(SelectItem, { "aria-label": t('advancedAdvanced.loadingAgents'), value: "loading", disabled: true, children: t('advancedAdvanced.loadingAgents') })) : ((_b = mentorsData === null || mentorsData === void 0 ? void 0 : mentorsData.results) === null || _b === void 0 ? void 0 : _b.length) ? (mentorsData.results.map((mentor) => (jsx(SelectItem, { value: mentor.unique_id, children: mentor.name }, mentor.unique_id)))) : (jsx(SelectItem, { value: "no-results", disabled: true, children: t('advancedAdvanced.noAgentsFound') }))] })] }), isUpdatingTenantMetadata && (jsx("div", { "aria-label": t('advancedAdvanced.updatingAgentSelection'), role: "status", className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) : isStringSetting ? (jsx(StringSettingInput, { value: currentValue, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, onSave: (value) => handleStringSettingUpdate(metadataItem.slug, value) })) : (jsxs(Fragment$1, { children: [jsx(Switch, { checked: currentValue, onCheckedChange: async () => {
|
|
155653
|
+
t('advancedAdvanced.noDescriptionAvailable') }) })] }) })] }), jsx("div", { className: "flex items-center gap-2", children: isMentorSetting ? (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: currentValue || '', onValueChange: (value) => handleMentorSelection(metadataItem.slug, value), disabled: isUpdatingTenantMetadata, children: [jsx(SelectTrigger, { className: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464]", children: jsx(SelectValue, { placeholder: t('advancedAdvanced.selectAgent'), children: currentValue ? getMentorName(currentValue) : '' }) }), jsxs(SelectContent, { className: "font-medium text-[#646464]", children: [jsx("div", { className: "p-2", children: jsx(Input, { placeholder: t('advancedAdvanced.searchAgents'), value: mentorSearchQuery, onChange: (e) => handleMentorSearch(e.target.value), className: "mb-2 font-medium text-[#646464]" }) }), jsx(SelectItem, { value: "none", children: t('advancedAdvanced.none') }), isMentorsLoading ? (jsx(SelectItem, { "aria-label": t('advancedAdvanced.loadingAgents'), value: "loading", disabled: true, children: t('advancedAdvanced.loadingAgents') })) : ((_b = mentorsData === null || mentorsData === void 0 ? void 0 : mentorsData.results) === null || _b === void 0 ? void 0 : _b.length) ? (mentorsData.results.map((mentor) => (jsx(SelectItem, { value: mentor.unique_id, children: mentor.name }, mentor.unique_id)))) : (jsx(SelectItem, { value: "no-results", disabled: true, children: t('advancedAdvanced.noAgentsFound') }))] })] }), isUpdatingTenantMetadata && (jsx("div", { "aria-label": t('advancedAdvanced.updatingAgentSelection'), role: "status", className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) : selectOptions ? (jsx(SelectSettingInput, { label: metadataItem.label, options: selectOptions, value: metadataItem.value, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, triggerClassName: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464]", onSelect: (value) => handleSelectSettingUpdate(metadataItem.slug, value) })) : isStringSetting ? (jsx(StringSettingInput, { value: currentValue, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, onSave: (value) => handleStringSettingUpdate(metadataItem.slug, value) })) : (jsxs(Fragment$1, { children: [jsx(Switch, { checked: currentValue, onCheckedChange: async () => {
|
|
155592
155654
|
await handleToggleSetting(metadataItem.slug, currentValue);
|
|
155593
155655
|
}, disabled: isUpdatingTenantMetadata, "aria-label": `${metadataItem.label} ${currentValue ? t('advancedAdvanced.enabled') : t('advancedAdvanced.disabled')}`, className: "cursor-pointer data-[state=checked]:bg-blue-500" }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) })] }, metadataItem.slug));
|
|
155594
155656
|
}) })) : (
|
|
@@ -155606,11 +155668,17 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
155606
155668
|
var _a, _b;
|
|
155607
155669
|
const currentValue = (_a = metadataItem.value) !== null && _a !== void 0 ? _a : metadataItem.defaultValue;
|
|
155608
155670
|
const isMentorSetting = metadataItem.slug === 'overall_default_mentor';
|
|
155609
|
-
const
|
|
155610
|
-
|
|
155671
|
+
const selectOptions = hasSelectableOptions(metadataItem)
|
|
155672
|
+
? metadataItem.options
|
|
155673
|
+
: null;
|
|
155674
|
+
const isSelectSetting = selectOptions !== null;
|
|
155675
|
+
const isStringSetting = typeof metadataItem.defaultValue === 'string' &&
|
|
155676
|
+
!isMentorSetting &&
|
|
155677
|
+
!isSelectSetting;
|
|
155678
|
+
return (jsxs("div", { className: `flex items-center justify-between rounded-lg border px-6 ${isMentorSetting || isStringSetting || isSelectSetting ? 'py-4' : 'py-6'}`, style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: metadataItem.label }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": t('advancedAdvanced.moreInfoAbout', {
|
|
155611
155679
|
label: metadataItem.label,
|
|
155612
155680
|
}), className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "ibl-tooltip-content", children: jsx("p", { children: metadataItem.description ||
|
|
155613
|
-
t('advancedAdvanced.noDescriptionAvailable') }) })] }) })] }), jsx("div", { className: "flex items-center gap-2", children: isMentorSetting ? (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: currentValue || '', onValueChange: (value) => handleMentorSelection(metadataItem.slug, value), disabled: isUpdatingTenantMetadata, children: [jsx(SelectTrigger, { className: "max-w-[240px] w-[230px] sm:w-[150px] font-medium text-[#646464]", children: jsx(SelectValue, { placeholder: t('advancedAdvanced.selectAgent'), children: currentValue ? getMentorName(currentValue) : '' }) }), jsxs(SelectContent, { className: "font-medium text-[#646464]", children: [jsx("div", { className: "p-2", children: jsx(Input, { placeholder: t('advancedAdvanced.searchAgents'), value: mentorSearchQuery, onChange: (e) => handleMentorSearch(e.target.value), className: "mb-2 font-medium text-[#646464]" }) }), jsx(SelectItem, { value: "none", children: t('advancedAdvanced.none') }), isMentorsLoading ? (jsx(SelectItem, { value: "loading", disabled: true, children: t('advancedAdvanced.loadingAgents') })) : ((_b = mentorsData === null || mentorsData === void 0 ? void 0 : mentorsData.results) === null || _b === void 0 ? void 0 : _b.length) ? (mentorsData.results.map((mentor) => (jsx(SelectItem, { value: mentor.unique_id, children: mentor.name }, mentor.unique_id)))) : (jsx(SelectItem, { value: "no-results", disabled: true, children: t('advancedAdvanced.noAgentsFound') }))] })] }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) : isStringSetting ? (jsx(StringSettingInput, { value: currentValue, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, onSave: (value) => handleStringSettingUpdate(metadataItem.slug, value) })) : (jsxs(Fragment$1, { children: [jsx(Switch, { checked: currentValue, onCheckedChange: async () => {
|
|
155681
|
+
t('advancedAdvanced.noDescriptionAvailable') }) })] }) })] }), jsx("div", { className: "flex items-center gap-2", children: isMentorSetting ? (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: currentValue || '', onValueChange: (value) => handleMentorSelection(metadataItem.slug, value), disabled: isUpdatingTenantMetadata, children: [jsx(SelectTrigger, { className: "max-w-[240px] w-[230px] sm:w-[150px] font-medium text-[#646464]", children: jsx(SelectValue, { placeholder: t('advancedAdvanced.selectAgent'), children: currentValue ? getMentorName(currentValue) : '' }) }), jsxs(SelectContent, { className: "font-medium text-[#646464]", children: [jsx("div", { className: "p-2", children: jsx(Input, { placeholder: t('advancedAdvanced.searchAgents'), value: mentorSearchQuery, onChange: (e) => handleMentorSearch(e.target.value), className: "mb-2 font-medium text-[#646464]" }) }), jsx(SelectItem, { value: "none", children: t('advancedAdvanced.none') }), isMentorsLoading ? (jsx(SelectItem, { value: "loading", disabled: true, children: t('advancedAdvanced.loadingAgents') })) : ((_b = mentorsData === null || mentorsData === void 0 ? void 0 : mentorsData.results) === null || _b === void 0 ? void 0 : _b.length) ? (mentorsData.results.map((mentor) => (jsx(SelectItem, { value: mentor.unique_id, children: mentor.name }, mentor.unique_id)))) : (jsx(SelectItem, { value: "no-results", disabled: true, children: t('advancedAdvanced.noAgentsFound') }))] })] }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) : selectOptions ? (jsx(SelectSettingInput, { label: metadataItem.label, options: selectOptions, value: metadataItem.value, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, triggerClassName: "max-w-[240px] w-[230px] sm:w-[150px] font-medium text-[#646464]", onSelect: (value) => handleSelectSettingUpdate(metadataItem.slug, value) })) : isStringSetting ? (jsx(StringSettingInput, { value: currentValue, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, onSave: (value) => handleStringSettingUpdate(metadataItem.slug, value) })) : (jsxs(Fragment$1, { children: [jsx(Switch, { checked: currentValue, onCheckedChange: async () => {
|
|
155614
155682
|
await handleToggleSetting(metadataItem.slug, currentValue);
|
|
155615
155683
|
}, disabled: isUpdatingTenantMetadata, "aria-label": `${metadataItem.label} ${currentValue ? t('advancedAdvanced.enabled') : t('advancedAdvanced.disabled')}`, className: "cursor-pointer data-[state=checked]:bg-blue-500" }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) })] }, metadataItem.slug));
|
|
155616
155684
|
}) })] }, spa)));
|
|
@@ -189684,6 +189684,19 @@ function StringSettingInput({ value, defaultValue, disabled, onSave, }) {
|
|
|
189684
189684
|
};
|
|
189685
189685
|
return (jsxs("div", { className: "flex items-center gap-2", children: [isDirty && (jsx(Button$1, { type: "button", size: "sm", onClick: handleSave, disabled: disabled, className: "h-8 bg-blue-500 hover:bg-blue-600 text-white", children: t('advancedAdvanced.save') })), jsx(Input, { value: localValue, onChange: (e) => setLocalValue(e.target.value), disabled: disabled, className: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464] text-sm" }), disabled && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] }));
|
|
189686
189686
|
}
|
|
189687
|
+
/**
|
|
189688
|
+
* A setting whose value is constrained to a fixed list of options declared in the
|
|
189689
|
+
* tenant metadata config, rendered as a dropdown.
|
|
189690
|
+
*/
|
|
189691
|
+
function hasSelectableOptions(metadataItem) {
|
|
189692
|
+
return Array.isArray(metadataItem.options) && metadataItem.options.length > 0;
|
|
189693
|
+
}
|
|
189694
|
+
function SelectSettingInput({ label, options, value, defaultValue, disabled, triggerClassName, onSelect, }) {
|
|
189695
|
+
// Values saved before an option was renamed/removed fall back to the default
|
|
189696
|
+
// so the trigger never renders an empty selection.
|
|
189697
|
+
const selectedValue = options.some((option) => option.value === value) ? value : defaultValue;
|
|
189698
|
+
return (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: selectedValue, onValueChange: onSelect, disabled: disabled, children: [jsx(SelectTrigger, { "aria-label": label, className: triggerClassName, children: jsx(SelectValue, {}) }), jsx(SelectContent, { className: "font-medium text-[#646464]", children: options.map((option) => (jsx(SelectItem, { value: option.value, children: option.label }, option.value))) })] }), disabled && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] }));
|
|
189699
|
+
}
|
|
189687
189700
|
function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatformBaseDomain, }) {
|
|
189688
189701
|
const t = useT();
|
|
189689
189702
|
const [updateTenantMetadata, { isLoading: isUpdatingTenantMetadata }] = useUpdateTenantMetadataMutation();
|
|
@@ -189719,33 +189732,35 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
189719
189732
|
'enable_profile_screen_on_start_page',
|
|
189720
189733
|
'enable_get_started_screen_on_start_page',
|
|
189721
189734
|
];
|
|
189735
|
+
// String settings rendered as a free-text input; every other string setting is
|
|
189736
|
+
// either handled by a dedicated component or exposed through its own options list
|
|
189737
|
+
const stringSettingSlugs = [
|
|
189738
|
+
'overall_default_mentor',
|
|
189739
|
+
'help_center_url',
|
|
189740
|
+
'monetization_base_path',
|
|
189741
|
+
'skills_welcome_tagline',
|
|
189742
|
+
];
|
|
189743
|
+
const getConfigurableMetadatas = () => {
|
|
189744
|
+
// Include boolean, select and whitelisted string settings, but exclude start
|
|
189745
|
+
// screen settings which are handled by the StartScreenContent component
|
|
189746
|
+
const configurableMetadatas = getAllMetadatas().filter((metadata) => (typeof metadata.defaultValue === 'boolean' ||
|
|
189747
|
+
hasSelectableOptions(metadata) ||
|
|
189748
|
+
(typeof metadata.defaultValue === 'string' &&
|
|
189749
|
+
stringSettingSlugs.includes(metadata.slug))) &&
|
|
189750
|
+
!startScreenSlugs.includes(metadata.slug));
|
|
189751
|
+
// Show all configurable settings when no SPA is specified
|
|
189752
|
+
if (!currentSPA)
|
|
189753
|
+
return configurableMetadatas;
|
|
189754
|
+
// Filter by current SPA if specified (case-insensitive partial matching)
|
|
189755
|
+
return configurableMetadatas.filter((metadata) => {
|
|
189756
|
+
const spaName = String(metadata.SPA || '').toLowerCase();
|
|
189757
|
+
const searchTerm = String(currentSPA).toLowerCase();
|
|
189758
|
+
return spaName.includes(searchTerm) || searchTerm.includes(spaName);
|
|
189759
|
+
});
|
|
189760
|
+
};
|
|
189722
189761
|
useEffect(() => {
|
|
189723
189762
|
if (metadataLoaded) {
|
|
189724
|
-
|
|
189725
|
-
// Include both boolean and string settings, but exclude start screen settings
|
|
189726
|
-
// which are handled by the StartScreenContent component
|
|
189727
|
-
const stringSettingSlugs = [
|
|
189728
|
-
'overall_default_mentor',
|
|
189729
|
-
'help_center_url',
|
|
189730
|
-
'monetization_base_path',
|
|
189731
|
-
'skills_welcome_tagline',
|
|
189732
|
-
];
|
|
189733
|
-
const configurableMetadatas = allMetadatas.filter((metadata) => (typeof metadata.defaultValue === 'boolean' ||
|
|
189734
|
-
(typeof metadata.defaultValue === 'string' &&
|
|
189735
|
-
stringSettingSlugs.includes(metadata.slug))) &&
|
|
189736
|
-
!startScreenSlugs.includes(metadata.slug));
|
|
189737
|
-
if (currentSPA) {
|
|
189738
|
-
// Filter by current SPA if specified (case-insensitive partial matching)
|
|
189739
|
-
setFlagTenantMetadatas(configurableMetadatas.filter((metadata) => {
|
|
189740
|
-
const spaName = String(metadata.SPA || '').toLowerCase();
|
|
189741
|
-
const searchTerm = String(currentSPA).toLowerCase();
|
|
189742
|
-
return spaName.includes(searchTerm) || searchTerm.includes(spaName);
|
|
189743
|
-
}));
|
|
189744
|
-
}
|
|
189745
|
-
else {
|
|
189746
|
-
// Show all configurable settings when no SPA is specified
|
|
189747
|
-
setFlagTenantMetadatas(configurableMetadatas);
|
|
189748
|
-
}
|
|
189763
|
+
setFlagTenantMetadatas(getConfigurableMetadatas());
|
|
189749
189764
|
}
|
|
189750
189765
|
}, [metadataLoaded, currentSPA]);
|
|
189751
189766
|
const updateOrganizationMetadata = async (key, value, callback) => {
|
|
@@ -189789,8 +189804,7 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
189789
189804
|
updateOrganizationMetadata(slug, newValue, () => {
|
|
189790
189805
|
toast.success(t('advancedAdvanced.settingUpdatedSuccessfully'));
|
|
189791
189806
|
// Update local state by refreshing the metadata
|
|
189792
|
-
setFlagTenantMetadatas(
|
|
189793
|
-
typeof metadata.defaultValue === 'boolean'));
|
|
189807
|
+
setFlagTenantMetadatas(getConfigurableMetadatas());
|
|
189794
189808
|
});
|
|
189795
189809
|
};
|
|
189796
189810
|
const handleMentorSelection = async (slug, mentorUniqueId) => {
|
|
@@ -189842,6 +189856,13 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
189842
189856
|
toast.success(t('advancedAdvanced.settingUpdatedSuccessfully'));
|
|
189843
189857
|
});
|
|
189844
189858
|
};
|
|
189859
|
+
const handleSelectSettingUpdate = async (slug, value) => {
|
|
189860
|
+
updateOrganizationMetadata(slug, value, () => {
|
|
189861
|
+
toast.success(t('advancedAdvanced.settingUpdatedSuccessfully'));
|
|
189862
|
+
// Update local state so the dropdown reflects the saved value
|
|
189863
|
+
setFlagTenantMetadatas(getConfigurableMetadatas());
|
|
189864
|
+
});
|
|
189865
|
+
};
|
|
189845
189866
|
// Helper function to get mentor name from JSON string, object, or unique_id
|
|
189846
189867
|
const getMentorName = (mentorValue) => {
|
|
189847
189868
|
var _a;
|
|
@@ -189876,11 +189897,17 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
189876
189897
|
? 'None'
|
|
189877
189898
|
: ((_a = metadataItem.value) !== null && _a !== void 0 ? _a : metadataItem.defaultValue);
|
|
189878
189899
|
const isMentorSetting = metadataItem.slug === 'overall_default_mentor';
|
|
189879
|
-
const
|
|
189880
|
-
|
|
189900
|
+
const selectOptions = hasSelectableOptions(metadataItem)
|
|
189901
|
+
? metadataItem.options
|
|
189902
|
+
: null;
|
|
189903
|
+
const isSelectSetting = selectOptions !== null;
|
|
189904
|
+
const isStringSetting = typeof metadataItem.defaultValue === 'string' &&
|
|
189905
|
+
!isMentorSetting &&
|
|
189906
|
+
!isSelectSetting;
|
|
189907
|
+
return (jsxs("div", { className: `flex items-center justify-between rounded-lg border px-6 ${isMentorSetting || isStringSetting || isSelectSetting ? 'py-4' : 'py-6'}`, style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: metadataItem.label }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": t('advancedAdvanced.moreInfoAbout', {
|
|
189881
189908
|
label: metadataItem.label,
|
|
189882
189909
|
}), className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "rounded-lg bg-gray-700 px-3 py-2 text-sm font-medium whitespace-nowrap text-white shadow-sm transition-opacity duration-300 z-50", children: jsx("p", { children: metadataItem.description ||
|
|
189883
|
-
t('advancedAdvanced.noDescriptionAvailable') }) })] }) })] }), jsx("div", { className: "flex items-center gap-2", children: isMentorSetting ? (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: currentValue || '', onValueChange: (value) => handleMentorSelection(metadataItem.slug, value), disabled: isUpdatingTenantMetadata, children: [jsx(SelectTrigger, { className: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464]", children: jsx(SelectValue, { placeholder: t('advancedAdvanced.selectAgent'), children: currentValue ? getMentorName(currentValue) : '' }) }), jsxs(SelectContent, { className: "font-medium text-[#646464]", children: [jsx("div", { className: "p-2", children: jsx(Input, { placeholder: t('advancedAdvanced.searchAgents'), value: mentorSearchQuery, onChange: (e) => handleMentorSearch(e.target.value), className: "mb-2 font-medium text-[#646464]" }) }), jsx(SelectItem, { value: "none", children: t('advancedAdvanced.none') }), isMentorsLoading ? (jsx(SelectItem, { "aria-label": t('advancedAdvanced.loadingAgents'), value: "loading", disabled: true, children: t('advancedAdvanced.loadingAgents') })) : ((_b = mentorsData === null || mentorsData === void 0 ? void 0 : mentorsData.results) === null || _b === void 0 ? void 0 : _b.length) ? (mentorsData.results.map((mentor) => (jsx(SelectItem, { value: mentor.unique_id, children: mentor.name }, mentor.unique_id)))) : (jsx(SelectItem, { value: "no-results", disabled: true, children: t('advancedAdvanced.noAgentsFound') }))] })] }), isUpdatingTenantMetadata && (jsx("div", { "aria-label": t('advancedAdvanced.updatingAgentSelection'), role: "status", className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) : isStringSetting ? (jsx(StringSettingInput, { value: currentValue, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, onSave: (value) => handleStringSettingUpdate(metadataItem.slug, value) })) : (jsxs(Fragment$1, { children: [jsx(Switch, { checked: currentValue, onCheckedChange: async () => {
|
|
189910
|
+
t('advancedAdvanced.noDescriptionAvailable') }) })] }) })] }), jsx("div", { className: "flex items-center gap-2", children: isMentorSetting ? (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: currentValue || '', onValueChange: (value) => handleMentorSelection(metadataItem.slug, value), disabled: isUpdatingTenantMetadata, children: [jsx(SelectTrigger, { className: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464]", children: jsx(SelectValue, { placeholder: t('advancedAdvanced.selectAgent'), children: currentValue ? getMentorName(currentValue) : '' }) }), jsxs(SelectContent, { className: "font-medium text-[#646464]", children: [jsx("div", { className: "p-2", children: jsx(Input, { placeholder: t('advancedAdvanced.searchAgents'), value: mentorSearchQuery, onChange: (e) => handleMentorSearch(e.target.value), className: "mb-2 font-medium text-[#646464]" }) }), jsx(SelectItem, { value: "none", children: t('advancedAdvanced.none') }), isMentorsLoading ? (jsx(SelectItem, { "aria-label": t('advancedAdvanced.loadingAgents'), value: "loading", disabled: true, children: t('advancedAdvanced.loadingAgents') })) : ((_b = mentorsData === null || mentorsData === void 0 ? void 0 : mentorsData.results) === null || _b === void 0 ? void 0 : _b.length) ? (mentorsData.results.map((mentor) => (jsx(SelectItem, { value: mentor.unique_id, children: mentor.name }, mentor.unique_id)))) : (jsx(SelectItem, { value: "no-results", disabled: true, children: t('advancedAdvanced.noAgentsFound') }))] })] }), isUpdatingTenantMetadata && (jsx("div", { "aria-label": t('advancedAdvanced.updatingAgentSelection'), role: "status", className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) : selectOptions ? (jsx(SelectSettingInput, { label: metadataItem.label, options: selectOptions, value: metadataItem.value, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, triggerClassName: "max-w-[240px] w-[110px] sm:w-[230px] font-medium text-[#646464]", onSelect: (value) => handleSelectSettingUpdate(metadataItem.slug, value) })) : isStringSetting ? (jsx(StringSettingInput, { value: currentValue, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, onSave: (value) => handleStringSettingUpdate(metadataItem.slug, value) })) : (jsxs(Fragment$1, { children: [jsx(Switch, { checked: currentValue, onCheckedChange: async () => {
|
|
189884
189911
|
await handleToggleSetting(metadataItem.slug, currentValue);
|
|
189885
189912
|
}, disabled: isUpdatingTenantMetadata, "aria-label": `${metadataItem.label} ${currentValue ? t('advancedAdvanced.enabled') : t('advancedAdvanced.disabled')}`, className: "cursor-pointer data-[state=checked]:bg-blue-500" }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) })] }, metadataItem.slug));
|
|
189886
189913
|
}) })) : (
|
|
@@ -189898,11 +189925,17 @@ function AdvancedTab({ platformKey, username, currentSPA, authURL, currentPlatfo
|
|
|
189898
189925
|
var _a, _b;
|
|
189899
189926
|
const currentValue = (_a = metadataItem.value) !== null && _a !== void 0 ? _a : metadataItem.defaultValue;
|
|
189900
189927
|
const isMentorSetting = metadataItem.slug === 'overall_default_mentor';
|
|
189901
|
-
const
|
|
189902
|
-
|
|
189928
|
+
const selectOptions = hasSelectableOptions(metadataItem)
|
|
189929
|
+
? metadataItem.options
|
|
189930
|
+
: null;
|
|
189931
|
+
const isSelectSetting = selectOptions !== null;
|
|
189932
|
+
const isStringSetting = typeof metadataItem.defaultValue === 'string' &&
|
|
189933
|
+
!isMentorSetting &&
|
|
189934
|
+
!isSelectSetting;
|
|
189935
|
+
return (jsxs("div", { className: `flex items-center justify-between rounded-lg border px-6 ${isMentorSetting || isStringSetting || isSelectSetting ? 'py-4' : 'py-6'}`, style: { borderColor: 'oklch(.922 0 0)' }, children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "text-sm font-medium text-[#646464]", children: metadataItem.label }), jsx(TooltipProvider, { children: jsxs(Tooltip$1, { children: [jsx(TooltipTrigger, { "aria-label": t('advancedAdvanced.moreInfoAbout', {
|
|
189903
189936
|
label: metadataItem.label,
|
|
189904
189937
|
}), className: "hidden sm:block", children: jsx(Info$3, { className: "h-4 w-4 text-gray-400" }) }), jsx(TooltipContent, { className: "ibl-tooltip-content", children: jsx("p", { children: metadataItem.description ||
|
|
189905
|
-
t('advancedAdvanced.noDescriptionAvailable') }) })] }) })] }), jsx("div", { className: "flex items-center gap-2", children: isMentorSetting ? (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: currentValue || '', onValueChange: (value) => handleMentorSelection(metadataItem.slug, value), disabled: isUpdatingTenantMetadata, children: [jsx(SelectTrigger, { className: "max-w-[240px] w-[230px] sm:w-[150px] font-medium text-[#646464]", children: jsx(SelectValue, { placeholder: t('advancedAdvanced.selectAgent'), children: currentValue ? getMentorName(currentValue) : '' }) }), jsxs(SelectContent, { className: "font-medium text-[#646464]", children: [jsx("div", { className: "p-2", children: jsx(Input, { placeholder: t('advancedAdvanced.searchAgents'), value: mentorSearchQuery, onChange: (e) => handleMentorSearch(e.target.value), className: "mb-2 font-medium text-[#646464]" }) }), jsx(SelectItem, { value: "none", children: t('advancedAdvanced.none') }), isMentorsLoading ? (jsx(SelectItem, { value: "loading", disabled: true, children: t('advancedAdvanced.loadingAgents') })) : ((_b = mentorsData === null || mentorsData === void 0 ? void 0 : mentorsData.results) === null || _b === void 0 ? void 0 : _b.length) ? (mentorsData.results.map((mentor) => (jsx(SelectItem, { value: mentor.unique_id, children: mentor.name }, mentor.unique_id)))) : (jsx(SelectItem, { value: "no-results", disabled: true, children: t('advancedAdvanced.noAgentsFound') }))] })] }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) : isStringSetting ? (jsx(StringSettingInput, { value: currentValue, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, onSave: (value) => handleStringSettingUpdate(metadataItem.slug, value) })) : (jsxs(Fragment$1, { children: [jsx(Switch, { checked: currentValue, onCheckedChange: async () => {
|
|
189938
|
+
t('advancedAdvanced.noDescriptionAvailable') }) })] }) })] }), jsx("div", { className: "flex items-center gap-2", children: isMentorSetting ? (jsxs("div", { className: "flex items-center gap-2", children: [jsxs(Select$1, { value: currentValue || '', onValueChange: (value) => handleMentorSelection(metadataItem.slug, value), disabled: isUpdatingTenantMetadata, children: [jsx(SelectTrigger, { className: "max-w-[240px] w-[230px] sm:w-[150px] font-medium text-[#646464]", children: jsx(SelectValue, { placeholder: t('advancedAdvanced.selectAgent'), children: currentValue ? getMentorName(currentValue) : '' }) }), jsxs(SelectContent, { className: "font-medium text-[#646464]", children: [jsx("div", { className: "p-2", children: jsx(Input, { placeholder: t('advancedAdvanced.searchAgents'), value: mentorSearchQuery, onChange: (e) => handleMentorSearch(e.target.value), className: "mb-2 font-medium text-[#646464]" }) }), jsx(SelectItem, { value: "none", children: t('advancedAdvanced.none') }), isMentorsLoading ? (jsx(SelectItem, { value: "loading", disabled: true, children: t('advancedAdvanced.loadingAgents') })) : ((_b = mentorsData === null || mentorsData === void 0 ? void 0 : mentorsData.results) === null || _b === void 0 ? void 0 : _b.length) ? (mentorsData.results.map((mentor) => (jsx(SelectItem, { value: mentor.unique_id, children: mentor.name }, mentor.unique_id)))) : (jsx(SelectItem, { value: "no-results", disabled: true, children: t('advancedAdvanced.noAgentsFound') }))] })] }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) : selectOptions ? (jsx(SelectSettingInput, { label: metadataItem.label, options: selectOptions, value: metadataItem.value, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, triggerClassName: "max-w-[240px] w-[230px] sm:w-[150px] font-medium text-[#646464]", onSelect: (value) => handleSelectSettingUpdate(metadataItem.slug, value) })) : isStringSetting ? (jsx(StringSettingInput, { value: currentValue, defaultValue: metadataItem.defaultValue, disabled: isUpdatingTenantMetadata, onSave: (value) => handleStringSettingUpdate(metadataItem.slug, value) })) : (jsxs(Fragment$1, { children: [jsx(Switch, { checked: currentValue, onCheckedChange: async () => {
|
|
189906
189939
|
await handleToggleSetting(metadataItem.slug, currentValue);
|
|
189907
189940
|
}, disabled: isUpdatingTenantMetadata, "aria-label": `${metadataItem.label} ${currentValue ? t('advancedAdvanced.enabled') : t('advancedAdvanced.disabled')}`, className: "cursor-pointer data-[state=checked]:bg-blue-500" }), isUpdatingTenantMetadata && (jsx("div", { className: "w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" }))] })) })] }, metadataItem.slug));
|
|
189908
189941
|
}) })] }, spa)));
|
|
@@ -255692,7 +255725,9 @@ function useCuaDriver() {
|
|
|
255692
255725
|
// treating null as denied would make Cowork unusable on Linux and Windows.
|
|
255693
255726
|
const [accessibilityPermission, setAccessibilityPermission] = useState(null);
|
|
255694
255727
|
const [screenRecordingPermission, setScreenRecordingPermission] = useState(null);
|
|
255695
|
-
|
|
255728
|
+
// True once the host has answered a status check this mount — the retry
|
|
255729
|
+
// loop's stop condition, NOT a "ran once" guard (that was the bug).
|
|
255730
|
+
const statusSettled = useRef(false);
|
|
255696
255731
|
/**
|
|
255697
255732
|
* Read one permission. Checking never prompts (`AXIsProcessTrusted` /
|
|
255698
255733
|
* `CGPreflightScreenCaptureAccess`), which is what makes it safe to do on mount.
|
|
@@ -255790,11 +255825,13 @@ function useCuaDriver() {
|
|
|
255790
255825
|
}));
|
|
255791
255826
|
}, [setState]);
|
|
255792
255827
|
/**
|
|
255793
|
-
* Query driver install status + session support from the host.
|
|
255828
|
+
* Query driver install status + session support from the host. Returns
|
|
255829
|
+
* whether the host actually answered — the mount effect retries on `false`,
|
|
255830
|
+
* because one failed check must not disable Cowork for the whole session.
|
|
255794
255831
|
*/
|
|
255795
255832
|
const checkStatus = useCallback(async () => {
|
|
255796
255833
|
if (!isAvailable)
|
|
255797
|
-
return;
|
|
255834
|
+
return false;
|
|
255798
255835
|
// Refresh both permissions alongside install status (independent, no prompt).
|
|
255799
255836
|
refreshPermissions();
|
|
255800
255837
|
try {
|
|
@@ -255807,10 +255844,12 @@ function useCuaDriver() {
|
|
|
255807
255844
|
progress: result.installed ? 100 : prev.progress,
|
|
255808
255845
|
lastUpdated: new Date().toISOString(),
|
|
255809
255846
|
}));
|
|
255847
|
+
return true;
|
|
255810
255848
|
}
|
|
255811
255849
|
catch (error) {
|
|
255812
255850
|
console.error('[useCuaDriver] Failed to check status:', error);
|
|
255813
255851
|
setState((prev) => ({ ...prev, status: 'idle' }));
|
|
255852
|
+
return false;
|
|
255814
255853
|
}
|
|
255815
255854
|
}, [isAvailable, invoke, setState, refreshPermissions]);
|
|
255816
255855
|
/**
|
|
@@ -255930,12 +255969,41 @@ function useCuaDriver() {
|
|
|
255930
255969
|
};
|
|
255931
255970
|
// Only re-subscribe if the host itself changes — never on state.
|
|
255932
255971
|
}, [isAvailable, listen]);
|
|
255933
|
-
// Check status
|
|
255972
|
+
// Check status on mount, and RETRY until the host answers once.
|
|
255973
|
+
//
|
|
255974
|
+
// This used to be one-shot behind a ref, which is why a built app could show
|
|
255975
|
+
// Cowork grey for a whole session: the single check raced the IPC bridge
|
|
255976
|
+
// being injected into the (remote) app origin, failed, and nothing ever asked
|
|
255977
|
+
// again — `status` stayed null and null renders as "not supported". Dev never
|
|
255978
|
+
// showed it because fast-refresh remounts re-ran the check constantly; a
|
|
255979
|
+
// production build gets exactly one mount, so it retries with backoff instead.
|
|
255980
|
+
// Capped: a host that still hasn't answered after ~75s is genuinely broken,
|
|
255981
|
+
// and install()/stop() re-check on their own paths anyway.
|
|
255934
255982
|
useEffect(() => {
|
|
255935
|
-
if (!isAvailable
|
|
255983
|
+
if (!isAvailable)
|
|
255936
255984
|
return;
|
|
255937
|
-
|
|
255938
|
-
|
|
255985
|
+
let cancelled = false;
|
|
255986
|
+
let timer;
|
|
255987
|
+
let attempt = 0;
|
|
255988
|
+
const MAX_ATTEMPTS = 8;
|
|
255989
|
+
const run = async () => {
|
|
255990
|
+
if (cancelled || statusSettled.current)
|
|
255991
|
+
return;
|
|
255992
|
+
if (await checkStatus()) {
|
|
255993
|
+
statusSettled.current = true;
|
|
255994
|
+
return;
|
|
255995
|
+
}
|
|
255996
|
+
attempt += 1;
|
|
255997
|
+
if (cancelled || attempt >= MAX_ATTEMPTS)
|
|
255998
|
+
return;
|
|
255999
|
+
timer = setTimeout(run, Math.min(1000 * 2 ** attempt, 15000));
|
|
256000
|
+
};
|
|
256001
|
+
run();
|
|
256002
|
+
return () => {
|
|
256003
|
+
cancelled = true;
|
|
256004
|
+
if (timer)
|
|
256005
|
+
clearTimeout(timer);
|
|
256006
|
+
};
|
|
255939
256007
|
}, [isAvailable, checkStatus]);
|
|
255940
256008
|
// Only expose the feature as available inside the desktop (Tauri) app.
|
|
255941
256009
|
const finalIsAvailable = isAvailable && isTauriApp$1();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iblai/iblai-js",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.11",
|
|
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,10 +76,10 @@
|
|
|
76
76
|
"axios": "1.13.6",
|
|
77
77
|
"dotenv": "16.6.1",
|
|
78
78
|
"winston": "3.19.0",
|
|
79
|
+
"@iblai/mcp": "1.8.11",
|
|
79
80
|
"@iblai/data-layer": "1.12.3",
|
|
80
|
-
"@iblai/
|
|
81
|
-
"@iblai/web-
|
|
82
|
-
"@iblai/web-utils": "2.1.11"
|
|
81
|
+
"@iblai/web-containers": "1.16.7",
|
|
82
|
+
"@iblai/web-utils": "2.1.12"
|
|
83
83
|
},
|
|
84
84
|
"peerDependencies": {
|
|
85
85
|
"@iblai/iblai-api": "4.166.0-ai",
|