@iblai/iblai-js 2.18.0 → 2.19.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.
|
@@ -2121,6 +2121,7 @@ var analyticsAccessTimeHeatmap$3 = {
|
|
|
2121
2121
|
tooltipActiveUsers: "{count} active users"
|
|
2122
2122
|
};
|
|
2123
2123
|
var analyticsAnalyticsAuditLogStats$3 = {
|
|
2124
|
+
anonymous: "Anonymous",
|
|
2124
2125
|
scopeAgent: "Agent",
|
|
2125
2126
|
scopeAriaLabel: "Audit log scope",
|
|
2126
2127
|
scopePlatform: "Platform",
|
|
@@ -2249,6 +2250,7 @@ var analyticsAgentScopeLink$3 = {
|
|
|
2249
2250
|
scopeToAgent: "View analytics for {name}"
|
|
2250
2251
|
};
|
|
2251
2252
|
var analyticsAnalyticsMemoryStats$3 = {
|
|
2253
|
+
anonymous: "Anonymous",
|
|
2252
2254
|
noPermission: "You do not have permission to view user memories.",
|
|
2253
2255
|
scopeLabel: "Memory scope",
|
|
2254
2256
|
scopeMentor: "This Agent",
|
|
@@ -2463,6 +2465,7 @@ var analyticsAnalyticsTopicsStats$3 = {
|
|
|
2463
2465
|
topicsRankedFooter: "{shown} of {total} topics · ranked by message volume"
|
|
2464
2466
|
};
|
|
2465
2467
|
var analyticsAnalyticsTranscriptsStats$3 = {
|
|
2468
|
+
anonymous: "Anonymous",
|
|
2466
2469
|
justNow: "Just now",
|
|
2467
2470
|
minutesAgo: "{count} min ago",
|
|
2468
2471
|
hoursAgo: "{count} hour{count, plural, one {} other {s}} ago",
|
|
@@ -9402,6 +9405,7 @@ var analyticsAccessTimeHeatmap$2 = {
|
|
|
9402
9405
|
tooltipActiveUsers: "{count} utilisateurs actifs"
|
|
9403
9406
|
};
|
|
9404
9407
|
var analyticsAnalyticsAuditLogStats$2 = {
|
|
9408
|
+
anonymous: "Anonyme",
|
|
9405
9409
|
scopeAgent: "Agent",
|
|
9406
9410
|
scopeAriaLabel: "Portée du journal d'audit",
|
|
9407
9411
|
scopePlatform: "Plateforme",
|
|
@@ -9530,6 +9534,7 @@ var analyticsAgentScopeLink$2 = {
|
|
|
9530
9534
|
scopeToAgent: "Voir les analyses de {name}"
|
|
9531
9535
|
};
|
|
9532
9536
|
var analyticsAnalyticsMemoryStats$2 = {
|
|
9537
|
+
anonymous: "Anonyme",
|
|
9533
9538
|
noPermission: "Vous n'avez pas l'autorisation de consulter les mémoires des utilisateurs.",
|
|
9534
9539
|
scopeLabel: "Portée de la mémoire",
|
|
9535
9540
|
scopeMentor: "Cet agent",
|
|
@@ -9744,6 +9749,7 @@ var analyticsAnalyticsTopicsStats$2 = {
|
|
|
9744
9749
|
topicsRankedFooter: "{shown} sur {total} sujets · classés par volume de messages"
|
|
9745
9750
|
};
|
|
9746
9751
|
var analyticsAnalyticsTranscriptsStats$2 = {
|
|
9752
|
+
anonymous: "Anonyme",
|
|
9747
9753
|
justNow: "À l'instant",
|
|
9748
9754
|
minutesAgo: "Il y a {count} min",
|
|
9749
9755
|
hoursAgo: "Il y a {count} heure{count, plural, one {} other {s}}",
|
|
@@ -16683,6 +16689,7 @@ var analyticsAccessTimeHeatmap$1 = {
|
|
|
16683
16689
|
tooltipActiveUsers: "{count} usuarios activos"
|
|
16684
16690
|
};
|
|
16685
16691
|
var analyticsAnalyticsAuditLogStats$1 = {
|
|
16692
|
+
anonymous: "Anónimo",
|
|
16686
16693
|
scopeAgent: "Agente",
|
|
16687
16694
|
scopeAriaLabel: "Alcance del registro de auditoría",
|
|
16688
16695
|
scopePlatform: "Plataforma",
|
|
@@ -16811,6 +16818,7 @@ var analyticsAgentScopeLink$1 = {
|
|
|
16811
16818
|
scopeToAgent: "Ver analíticas de {name}"
|
|
16812
16819
|
};
|
|
16813
16820
|
var analyticsAnalyticsMemoryStats$1 = {
|
|
16821
|
+
anonymous: "Anónimo",
|
|
16814
16822
|
noPermission: "No tienes permiso para ver los recuerdos de los usuarios.",
|
|
16815
16823
|
scopeLabel: "Alcance de la memoria",
|
|
16816
16824
|
scopeMentor: "Este agente",
|
|
@@ -17025,6 +17033,7 @@ var analyticsAnalyticsTopicsStats$1 = {
|
|
|
17025
17033
|
topicsRankedFooter: "{shown} de {total} temas · ordenados por volumen de mensajes"
|
|
17026
17034
|
};
|
|
17027
17035
|
var analyticsAnalyticsTranscriptsStats$1 = {
|
|
17036
|
+
anonymous: "Anónimo",
|
|
17028
17037
|
justNow: "Ahora mismo",
|
|
17029
17038
|
minutesAgo: "Hace {count} min",
|
|
17030
17039
|
hoursAgo: "Hace {count} hora{count, plural, one {} other {s}}",
|
|
@@ -23964,6 +23973,7 @@ var analyticsAccessTimeHeatmap = {
|
|
|
23964
23973
|
tooltipActiveUsers: "{count} 位活跃用户"
|
|
23965
23974
|
};
|
|
23966
23975
|
var analyticsAnalyticsAuditLogStats = {
|
|
23976
|
+
anonymous: "匿名",
|
|
23967
23977
|
scopeAgent: "智能体",
|
|
23968
23978
|
scopeAriaLabel: "审计日志范围",
|
|
23969
23979
|
scopePlatform: "平台",
|
|
@@ -24092,6 +24102,7 @@ var analyticsAgentScopeLink = {
|
|
|
24092
24102
|
scopeToAgent: "查看 {name} 的分析"
|
|
24093
24103
|
};
|
|
24094
24104
|
var analyticsAnalyticsMemoryStats = {
|
|
24105
|
+
anonymous: "匿名",
|
|
24095
24106
|
noPermission: "您没有查看用户记忆的权限。",
|
|
24096
24107
|
scopeLabel: "记忆范围",
|
|
24097
24108
|
scopeMentor: "当前智能体",
|
|
@@ -24306,6 +24317,7 @@ var analyticsAnalyticsTopicsStats = {
|
|
|
24306
24317
|
topicsRankedFooter: "共 {total} 个主题,显示 {shown} 个 · 按消息量排序"
|
|
24307
24318
|
};
|
|
24308
24319
|
var analyticsAnalyticsTranscriptsStats = {
|
|
24320
|
+
anonymous: "匿名",
|
|
24309
24321
|
justNow: "刚刚",
|
|
24310
24322
|
minutesAgo: "{count} 分钟前",
|
|
24311
24323
|
hoursAgo: "{count} 小时前",
|
|
@@ -189484,7 +189496,7 @@ function RetrievedDocumentsButton({ sessionId = '', documents, className, label,
|
|
|
189484
189496
|
// Safe inside clickable transcript rows: the row must not react.
|
|
189485
189497
|
event.stopPropagation();
|
|
189486
189498
|
setIsOpen(true);
|
|
189487
|
-
}, "data-testid": "retrieved-documents-button", children: [jsx(FileText, { className: "h-4 w-4 text-blue-600" }), jsx("span", { children: label !== null && label !== void 0 ? label : t('retrievedDocumentsButton.title') })] }), jsx(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: jsxs(DialogContent, { className: "flex max-h-[80vh] flex-col gap-0 p-0 sm:max-w-[425px] md:max-w-[600px]", children: [jsx(DialogHeader, { className: "border-b px-4 py-2", children: jsxs(DialogTitle, { className: "flex items-center gap-2 text-base font-medium text-[#646464]", children: [jsx(FileText, { className: "h-5 w-5 text-blue-600" }), t('retrievedDocumentsButton.title')] }) }), jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", "data-testid": "retrieved-documents-scroll", children: jsx(DocumentSidebar, { isModal: true, sessionId: sessionId, documents: documents }) })] }) })] }));
|
|
189499
|
+
}, "data-testid": "retrieved-documents-button", children: [jsx(FileText, { className: "h-4 w-4 text-blue-600" }), jsx("span", { children: label !== null && label !== void 0 ? label : t('retrievedDocumentsButton.title') })] }), jsx(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: jsxs(DialogContent, { className: "flex max-h-[80vh] flex-col gap-0 p-0 sm:max-w-[425px] md:max-w-[600px]", children: [jsx(DialogHeader, { className: "border-b border-gray-200 px-4 py-2", children: jsxs(DialogTitle, { className: "flex items-center gap-2 text-base font-medium text-[#646464]", children: [jsx(FileText, { className: "h-5 w-5 text-blue-600" }), t('retrievedDocumentsButton.title')] }) }), jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", "data-testid": "retrieved-documents-scroll", children: jsx(DocumentSidebar, { isModal: true, sessionId: sessionId, documents: documents }) })] }) })] }));
|
|
189488
189500
|
}
|
|
189489
189501
|
|
|
189490
189502
|
var COLLAPSIBLE_NAME = "Collapsible";
|
|
@@ -189734,6 +189746,11 @@ function ToolCallIndicator({ toolCalls, isActive = false, showResults = false, }
|
|
|
189734
189746
|
* white circle (the catalogue's artwork, or the bot icon when it has none)
|
|
189735
189747
|
* beside the model's display name. Read-only; used on admin transcripts to
|
|
189736
189748
|
* name the model a turn ran on.
|
|
189749
|
+
*
|
|
189750
|
+
* It sets no font size, weight or colour of its own and sizes the logo in
|
|
189751
|
+
* `em`, so it reads as one more fact in whatever row holds it — a `text-xs
|
|
189752
|
+
* text-gray-500` transcript card or the details panel — rather than as a
|
|
189753
|
+
* larger, bolder pill beside them. Pass `className` for the nav bar's look.
|
|
189737
189754
|
*/
|
|
189738
189755
|
function LlmModelBadge({ model, provider, tenantKey, mentorId, className, }) {
|
|
189739
189756
|
var _a, _b;
|
|
@@ -189754,9 +189771,9 @@ function LlmModelBadge({ model, provider, tenantKey, mentorId, className, }) {
|
|
|
189754
189771
|
const label = displayName || providerDetails.displayName;
|
|
189755
189772
|
if (!label)
|
|
189756
189773
|
return null;
|
|
189757
|
-
return (jsxs("span", { className: cn('inline-flex max-w-full items-center gap-
|
|
189774
|
+
return (jsxs("span", { className: cn('inline-flex max-w-full items-center gap-[0.5em] align-middle', className), title: providerDetails.displayName && providerDetails.displayName !== label
|
|
189758
189775
|
? `${label} · ${providerDetails.displayName}`
|
|
189759
|
-
: label, "data-testid": "llm-model-badge", children: [jsx("span", { className: "flex h-
|
|
189776
|
+
: label, "data-testid": "llm-model-badge", children: [jsx("span", { className: "flex h-[1.5em] w-[1.5em] flex-shrink-0 items-center justify-center rounded-full bg-white", children: providerDetails.logo ? (jsx("img", { src: providerDetails.logo, alt: `${label} model logo`, className: "h-[1.25em] w-[1.25em] object-contain", height: 32, width: 32, loading: "lazy" })) : (jsx(Bot, { className: "h-[1em] w-[1em]", "aria-hidden": "true" })) }), jsx("span", { className: "max-w-[220px] truncate", children: label })] }));
|
|
189760
189777
|
}
|
|
189761
189778
|
|
|
189762
189779
|
/** SPAs whose users have coursework, so the profile leads with a Gradebook tab. */
|
|
@@ -189802,17 +189819,18 @@ function UserProfileDialog({ tenantKey, username, isOpen, onClose, customization
|
|
|
189802
189819
|
function UserProfileLink({ tenantKey, username, display, className, testId, customization, currentSPA, }) {
|
|
189803
189820
|
const t = useT();
|
|
189804
189821
|
const [isOpen, setIsOpen] = React__default.useState(false);
|
|
189822
|
+
// The text truncates inside an `inline-flex` box: an `inline-block` with
|
|
189823
|
+
// hidden overflow puts its baseline on its bottom edge, so the value would
|
|
189824
|
+
// ride above the "User:" label beside it.
|
|
189805
189825
|
if (!username) {
|
|
189806
|
-
|
|
189807
|
-
// an inline box takes its width from its own text.
|
|
189808
|
-
return (jsx("span", { className: cn('inline-block max-w-full truncate', className), "data-testid": testId, children: display }));
|
|
189826
|
+
return (jsx("span", { className: cn('inline-flex max-w-full', className), "data-testid": testId, children: jsx("span", { className: "min-w-0 truncate", children: display }) }));
|
|
189809
189827
|
}
|
|
189810
189828
|
return (jsxs(Fragment$1, { children: [jsx("button", { type: "button", onClick: (event) => {
|
|
189811
189829
|
event.stopPropagation();
|
|
189812
189830
|
setIsOpen(true);
|
|
189813
189831
|
},
|
|
189814
189832
|
// Rows that open on Enter/Space would otherwise swallow the key press.
|
|
189815
|
-
onKeyDown: (event) => event.stopPropagation(), className: cn('max-w-full cursor-pointer
|
|
189833
|
+
onKeyDown: (event) => event.stopPropagation(), className: cn('inline-flex max-w-full cursor-pointer text-left hover:text-blue-600 hover:underline focus:text-blue-600 focus:outline-none', className), "aria-label": t('tabsUserstab.viewProfileAriaLabel', { name: display }), "data-testid": testId, children: jsx("span", { className: "min-w-0 truncate", children: display }) }), jsx(UserProfileDialog, { tenantKey: tenantKey, username: username, isOpen: isOpen, onClose: () => setIsOpen(false), customization: customization, currentSPA: currentSPA })] }));
|
|
189816
189834
|
}
|
|
189817
189835
|
|
|
189818
189836
|
const AdvancedPagination = ({ currentPage, totalPages, onPageChange, totalCount, itemsPerPage, itemLabel = 'items', variant = 'default', className, }) => {
|
|
@@ -232420,6 +232438,154 @@ const useFinancial = ({ tenantKey, mentorId, userId, }) => {
|
|
|
232420
232438
|
};
|
|
232421
232439
|
};
|
|
232422
232440
|
|
|
232441
|
+
/**
|
|
232442
|
+
* One place that decides how a user is shown.
|
|
232443
|
+
*
|
|
232444
|
+
* Backend payloads name their user in a dozen ways — `email` / `lti_email` /
|
|
232445
|
+
* `user_email`, `username` / `student` / `lti_username`, `name` /
|
|
232446
|
+
* `full_name` / `user_full_name`, or a nested `user` object — and most of
|
|
232447
|
+
* them can be empty, `null`, or a placeholder like "None". Every surface used
|
|
232448
|
+
* to pick through those on its own. `resolveUserIdentity()` takes whatever
|
|
232449
|
+
* the payload is and returns what to show, what to open a profile on, and
|
|
232450
|
+
* the avatar initial, so the rule lives here and can be tweaked once.
|
|
232451
|
+
*
|
|
232452
|
+
* Default rule: a real full name first (see {@link hasDistinctName}), else
|
|
232453
|
+
* email → username → the anonymous label.
|
|
232454
|
+
*/
|
|
232455
|
+
const DEFAULT_USER_IDENTITY_ORDER = ['email', 'name', 'username'];
|
|
232456
|
+
/** Order used when the payload carries a real name (see {@link hasDistinctName}). */
|
|
232457
|
+
const NAME_FIRST_ORDER = ['name', 'email', 'username'];
|
|
232458
|
+
/**
|
|
232459
|
+
* Lower-case letters and digits of any script, accents and punctuation dropped,
|
|
232460
|
+
* so "Conrad Mugabe" / "conrad.mugabe" and "José" / "jose" compare equal.
|
|
232461
|
+
*/
|
|
232462
|
+
const identityKey = (value) => (value !== null && value !== void 0 ? value : '')
|
|
232463
|
+
.normalize('NFKD')
|
|
232464
|
+
.replace(/[^\p{L}\p{N}]/gu, '')
|
|
232465
|
+
.toLowerCase();
|
|
232466
|
+
/**
|
|
232467
|
+
* Whether `name` is a real name rather than a restatement of the username.
|
|
232468
|
+
*
|
|
232469
|
+
* Many payloads fill the name field with the username ("conradmugabe" →
|
|
232470
|
+
* "Conrad Mugabe", "fayyaz_4_ibleducation_com"), which tells an admin nothing
|
|
232471
|
+
* the email does not. A name that matches none of the usernames on the record
|
|
232472
|
+
* is the most recognisable thing on it — including for LTI learners, whose
|
|
232473
|
+
* minted `<opaque-id>@edx-lti-1p3.com` address and username identify nobody.
|
|
232474
|
+
*/
|
|
232475
|
+
function hasDistinctName(name, ...usernames) {
|
|
232476
|
+
const key = identityKey(name);
|
|
232477
|
+
if (!key)
|
|
232478
|
+
return false;
|
|
232479
|
+
return usernames.every((username) => key !== identityKey(username));
|
|
232480
|
+
}
|
|
232481
|
+
const DEFAULT_ANONYMOUS_LABEL = 'Anonymous';
|
|
232482
|
+
/** Values backends emit instead of "nothing". Compared case-insensitively. */
|
|
232483
|
+
const PLACEHOLDERS = new Set([
|
|
232484
|
+
'',
|
|
232485
|
+
'none',
|
|
232486
|
+
'null',
|
|
232487
|
+
'undefined',
|
|
232488
|
+
'n/a',
|
|
232489
|
+
'na',
|
|
232490
|
+
'-',
|
|
232491
|
+
'anonymous',
|
|
232492
|
+
'anonymoususer',
|
|
232493
|
+
]);
|
|
232494
|
+
/**
|
|
232495
|
+
* `local@domain.tld` with no whitespace, checked with a single pass rather than
|
|
232496
|
+
* a backtracking pattern (CodeQL flags `[^@]+@[^@]+\.[^@]+` as polynomial on
|
|
232497
|
+
* adversarial input).
|
|
232498
|
+
*/
|
|
232499
|
+
const isEmailLike = (value) => {
|
|
232500
|
+
const text = value.trim();
|
|
232501
|
+
if (!text || /\s/.test(text))
|
|
232502
|
+
return false;
|
|
232503
|
+
const at = text.indexOf('@');
|
|
232504
|
+
if (at <= 0 || at !== text.lastIndexOf('@') || at === text.length - 1)
|
|
232505
|
+
return false;
|
|
232506
|
+
const domain = text.slice(at + 1);
|
|
232507
|
+
const dot = domain.indexOf('.');
|
|
232508
|
+
// A dot somewhere inside the domain, with something after the last one.
|
|
232509
|
+
return dot > 0 && !domain.endsWith('.');
|
|
232510
|
+
};
|
|
232511
|
+
/** Trimmed string, or undefined for blanks, non-strings and placeholders. */
|
|
232512
|
+
const clean = (value) => {
|
|
232513
|
+
if (typeof value !== 'string')
|
|
232514
|
+
return undefined;
|
|
232515
|
+
const trimmed = value.trim();
|
|
232516
|
+
return PLACEHOLDERS.has(trimmed.toLowerCase()) ? undefined : trimmed;
|
|
232517
|
+
};
|
|
232518
|
+
const firstOf = (...candidates) => {
|
|
232519
|
+
for (const candidate of candidates) {
|
|
232520
|
+
const value = clean(candidate);
|
|
232521
|
+
if (value)
|
|
232522
|
+
return value;
|
|
232523
|
+
}
|
|
232524
|
+
return undefined;
|
|
232525
|
+
};
|
|
232526
|
+
const nested = (source) => source.user && typeof source.user === 'object' ? source.user : undefined;
|
|
232527
|
+
/**
|
|
232528
|
+
* Resolve how a user should be displayed from any payload that names one.
|
|
232529
|
+
*
|
|
232530
|
+
* - `email`: `lti_email`, `email`, `user_email`, the nested `user`'s email —
|
|
232531
|
+
* or a username field that turns out to hold an email address.
|
|
232532
|
+
* - `username`: `lti_username`, `username`, `student`, `user_username`, the
|
|
232533
|
+
* nested `user`'s username, or a bare string `user` value (a numeric id is
|
|
232534
|
+
* ignored).
|
|
232535
|
+
* - `name`: `user_full_name`, `full_name`, `name`, `first_name last_name`, or
|
|
232536
|
+
* the nested `user`'s name.
|
|
232537
|
+
* - `profileUsername`: the first *platform* username (never an LTI claim).
|
|
232538
|
+
*
|
|
232539
|
+
* A string source is treated as an email when it looks like one, else as a
|
|
232540
|
+
* username. Placeholder strings ("None", "-", "anonymous"…) count as absent.
|
|
232541
|
+
*
|
|
232542
|
+
* The default order flips to name → email → username when the record carries a
|
|
232543
|
+
* real name (see {@link hasDistinctName}): "Joseph Oti" is more use to an admin
|
|
232544
|
+
* than his address, while a name that merely repeats the username is not, so
|
|
232545
|
+
* those records keep showing the email. An explicit `order` is always obeyed.
|
|
232546
|
+
*/
|
|
232547
|
+
function resolveUserIdentity(source, options = {}) {
|
|
232548
|
+
var _a, _b;
|
|
232549
|
+
const anonymousLabel = options.anonymousLabel || DEFAULT_ANONYMOUS_LABEL;
|
|
232550
|
+
const order = ((_a = options.order) === null || _a === void 0 ? void 0 : _a.length) ? options.order : DEFAULT_USER_IDENTITY_ORDER;
|
|
232551
|
+
const record = source && typeof source === 'object' ? source : { user: source !== null && source !== void 0 ? source : null };
|
|
232552
|
+
const inner = nested(record);
|
|
232553
|
+
// A bare `user` value is a username — unless it is a numeric id, which
|
|
232554
|
+
// names nobody: transcript rows carry `user: 1` beside `username: null`,
|
|
232555
|
+
// and showing "1" for that person is worse than "Anonymous".
|
|
232556
|
+
const bareString = typeof record.user === 'string' ? clean(record.user) : undefined;
|
|
232557
|
+
const bareUser = bareString && !/^\d+$/.test(bareString) ? bareString : undefined;
|
|
232558
|
+
let email = firstOf(record.lti_email, record.email, record.user_email, inner === null || inner === void 0 ? void 0 : inner.lti_email, inner === null || inner === void 0 ? void 0 : inner.email, inner === null || inner === void 0 ? void 0 : inner.user_email);
|
|
232559
|
+
const platformUsername = firstOf(record.username, record.student, record.user_username, inner === null || inner === void 0 ? void 0 : inner.username, inner === null || inner === void 0 ? void 0 : inner.student, inner === null || inner === void 0 ? void 0 : inner.user_username, bareUser && !isEmailLike(bareUser) ? bareUser : undefined);
|
|
232560
|
+
let username = firstOf(record.lti_username, inner === null || inner === void 0 ? void 0 : inner.lti_username, platformUsername);
|
|
232561
|
+
const composed = [clean(record.first_name), clean(record.last_name)].filter(Boolean).join(' ');
|
|
232562
|
+
const name = firstOf(record.user_full_name, record.full_name, record.name, composed, inner === null || inner === void 0 ? void 0 : inner.user_full_name, inner === null || inner === void 0 ? void 0 : inner.full_name, inner === null || inner === void 0 ? void 0 : inner.name);
|
|
232563
|
+
// A bare string that looks like an email is an email, and so is a
|
|
232564
|
+
// "username" field that actually carries one.
|
|
232565
|
+
if (!email && bareUser && isEmailLike(bareUser))
|
|
232566
|
+
email = bareUser;
|
|
232567
|
+
if (!email && username && isEmailLike(username)) {
|
|
232568
|
+
email = username;
|
|
232569
|
+
username = undefined;
|
|
232570
|
+
}
|
|
232571
|
+
const facts = { email, username, name };
|
|
232572
|
+
// Every username on the record counts: the platform one a profile opens on
|
|
232573
|
+
// and the LTI claim that would be displayed.
|
|
232574
|
+
const labelOrder = !((_b = options.order) === null || _b === void 0 ? void 0 : _b.length) && hasDistinctName(name, platformUsername, username)
|
|
232575
|
+
? NAME_FIRST_ORDER
|
|
232576
|
+
: order;
|
|
232577
|
+
const label = labelOrder.map((field) => facts[field]).find(Boolean);
|
|
232578
|
+
return {
|
|
232579
|
+
label: label !== null && label !== void 0 ? label : anonymousLabel,
|
|
232580
|
+
email,
|
|
232581
|
+
username,
|
|
232582
|
+
name,
|
|
232583
|
+
profileUsername: platformUsername,
|
|
232584
|
+
initial: (label !== null && label !== void 0 ? label : anonymousLabel).charAt(0).toUpperCase() || 'A',
|
|
232585
|
+
isAnonymous: !label,
|
|
232586
|
+
};
|
|
232587
|
+
}
|
|
232588
|
+
|
|
232423
232589
|
const TONES = {
|
|
232424
232590
|
amber: {
|
|
232425
232591
|
container: 'border-amber-200 bg-amber-50 text-amber-800',
|
|
@@ -232777,6 +232943,10 @@ const costTick = (value) => {
|
|
|
232777
232943
|
function SpendTab({ tenantKey, currentSPA, mentorId: currentMentorId, userId, onOpenUserTraces, }) {
|
|
232778
232944
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
232779
232945
|
const t = useT();
|
|
232946
|
+
// The label a cost row shows for its user, by the shared identity rule.
|
|
232947
|
+
const identify = React__default.useCallback((row) => resolveUserIdentity(row, {
|
|
232948
|
+
anonymousLabel: t('analyticsAnalyticsFinancialStats.anonymous'),
|
|
232949
|
+
}), [t]);
|
|
232780
232950
|
const { weeklyCostData, isLoadingWeeklyCostData, isErrorWeeklyCostData, monthlyCostData, isLoadingMonthlyCostData, isErrorMonthlyCostData, totalCostData, isLoadingTotalCostData, isErrorTotalCostData, detailedCostPerDayData, isLoadingDetailedCostPerDayData, detailedCostPerDayFilters, setDetailedCostPerDayFilters, detailedCostPerProviderData, isLoadingDetailedCostPerProviderData, detailedCostPerProviderFilters, setDetailedCostPerProviderFilters, detailedCostPerUserData, isLoadingDetailedCostPerUserData, detailedCostPerUserFilters, setDetailedCostPerUserFilters, costPerUserPage, setCostPerUserPage, costPerUserLimit, providerColors, detailedLLMCostData, isLoadingDetailedLLMCostData, detailedLLMCostFilters, setDetailedLLMCostFilters, } = useFinancial({ tenantKey, mentorId: currentMentorId, userId });
|
|
232781
232951
|
// Pagination handlers
|
|
232782
232952
|
const handleFirstPage = () => {
|
|
@@ -232871,7 +233041,7 @@ function SpendTab({ tenantKey, currentSPA, mentorId: currentMentorId, userId, on
|
|
|
232871
233041
|
shown: (_p = (_o = detailedLLMCostData === null || detailedLLMCostData === void 0 ? void 0 : detailedLLMCostData.rows) === null || _o === void 0 ? void 0 : _o.length) !== null && _p !== void 0 ? _p : 0,
|
|
232872
233042
|
}) })) : (jsx(EmptyStats, {})) })] }), jsx("div", { className: "grid grid-cols-1 gap-6", children: jsx(ChartCardWrapper, { title: t('analyticsAnalyticsFinancialStats.costPerUserTitle'), source: "clickhouse", label: t('analyticsAnalyticsFinancialStats.costPerUserLabel'), filters: detailedCostPerUserFilters, setOutsideFilters: setDetailedCostPerUserFilters, overflowAuto: true, height: "450px", description: t('analyticsAnalyticsFinancialStats.costPerUserDescription'), children: jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "rounded-md", style: { borderColor: 'oklch(.922 0 0)', borderWidth: '1px' }, children: jsxs(Table, { children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "h-[48px]", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableHead, { className: "w-[250px]", children: t('analyticsAnalyticsFinancialStats.tableHeaderUserEmail') }), jsx(TableHead, { className: "w-[120px]", children: t('analyticsAnalyticsFinancialStats.tableHeaderTotalCost') }), hasSessions && (jsx(TableHead, { children: t('analyticsAnalyticsFinancialStats.tableHeaderSessions') })), hasLastActive && (jsx(TableHead, { className: "text-right", children: t('analyticsAnalyticsFinancialStats.tableHeaderLastActive') })), onOpenUserTraces && jsx(TableHead, { className: "w-[90px]" })] }) }), jsx(TableBody, { children: (_q = detailedCostPerUserData === null || detailedCostPerUserData === void 0 ? void 0 : detailedCostPerUserData.rows) === null || _q === void 0 ? void 0 : _q.map((user, index) => {
|
|
232873
233043
|
var _a;
|
|
232874
|
-
return (jsxs(TableRow, { className: cn(index % 2 === 0 ? 'bg-gray-50' : '', 'h-[48px]'), style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableCell, { className: "font-medium", children: jsx("div", { className: "flex items-center", children:
|
|
233044
|
+
return (jsxs(TableRow, { className: cn(index % 2 === 0 ? 'bg-gray-50' : '', 'h-[48px]'), style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx(TableCell, { className: "font-medium", children: jsx("div", { className: "flex items-center", children: jsx(UserProfileLink, { tenantKey: tenantKey, currentSPA: currentSPA, username: user.username, display: identify(user).label }) }) }), jsxs(TableCell, { className: "font-medium", children: ["$", Number(user.total_cost || 0).toFixed(2)] }), hasSessions && jsx(TableCell, { children: (_a = user.sessions) !== null && _a !== void 0 ? _a : '\u2014' }), hasLastActive && (jsx(TableCell, { className: "text-right", children: user.last_active ? formatRelativeTime$2(user.last_active) : '-' })), onOpenUserTraces && (jsx(TableCell, { className: "text-right", children: (user === null || user === void 0 ? void 0 : user.username) || (user === null || user === void 0 ? void 0 : user.user_email) || (user === null || user === void 0 ? void 0 : user.email) ? (jsx("button", { type: "button", className: "cursor-pointer text-sm font-semibold text-blue-600 hover:text-blue-700 hover:underline", onClick: () => onOpenUserTraces(String(user.username || user.user_email || user.email)), children: t('analyticsAnalyticsFinancialStats.viewTraces') })) : null }))] }, index));
|
|
232875
233045
|
}) })] }) }), isLoadingDetailedCostPerUserData && (jsx("div", { className: "h-[60px]", children: jsx(ChartLoading, {}) })), !isLoadingDetailedCostPerUserData &&
|
|
232876
233046
|
(!((_r = detailedCostPerUserData === null || detailedCostPerUserData === void 0 ? void 0 : detailedCostPerUserData.rows) === null || _r === void 0 ? void 0 : _r.length) ||
|
|
232877
233047
|
((_s = detailedCostPerUserData === null || detailedCostPerUserData === void 0 ? void 0 : detailedCostPerUserData.rows) === null || _s === void 0 ? void 0 : _s.length) === 0) && (jsx("div", { className: "h-[60px]", children: jsx(EmptyStats, {}) })), detailedCostPerUserData && detailedCostPerUserData.total_pages > 1 && (jsxs("div", { className: "flex items-center justify-between py-3", children: [jsx("div", { className: "text-sm text-gray-700", children: t('analyticsAnalyticsFinancialStats.paginationShowing', {
|
|
@@ -233002,19 +233172,22 @@ const useTranscripts = ({ tenantKey, mentorId, usergroupIds, }) => {
|
|
|
233002
233172
|
* from the data instead of from a search box.
|
|
233003
233173
|
*
|
|
233004
233174
|
* It renders as plain text wherever re-scoping is impossible or pointless: on
|
|
233005
|
-
* per-agent pages (no picker, so nothing would visibly change),
|
|
233006
|
-
*
|
|
233007
|
-
*
|
|
233175
|
+
* per-agent pages (no picker, so nothing would visibly change), on rows whose
|
|
233176
|
+
* agent the payload identifies by name alone, and on rows of the agent the
|
|
233177
|
+
* page is already scoped to (every row, once the picker names one agent — a
|
|
233178
|
+
* blue link there promised something and delivered nothing). Safe inside
|
|
233179
|
+
* clickable rows and cards — neither its clicks nor its key presses reach
|
|
233180
|
+
* their handlers.
|
|
233008
233181
|
*/
|
|
233009
233182
|
function AgentScopeLink({ uniqueId, name, fallback = '-', onScoped, className, testId, }) {
|
|
233010
233183
|
const t = useT();
|
|
233011
233184
|
const setScopedMentor = useAnalyticsScopeSetter();
|
|
233012
233185
|
const { scopedMentor } = useAnalyticsScope();
|
|
233013
233186
|
const display = name || uniqueId || fallback;
|
|
233014
|
-
|
|
233187
|
+
const isCurrent = !!uniqueId && (scopedMentor === null || scopedMentor === void 0 ? void 0 : scopedMentor.uniqueId) === uniqueId;
|
|
233188
|
+
if (!setScopedMentor || !uniqueId || isCurrent) {
|
|
233015
233189
|
return (jsx("span", { className: className, "data-testid": testId, children: display }));
|
|
233016
233190
|
}
|
|
233017
|
-
const isCurrent = (scopedMentor === null || scopedMentor === void 0 ? void 0 : scopedMentor.uniqueId) === uniqueId;
|
|
233018
233191
|
return (jsx("button", { type: "button", onClick: (event) => {
|
|
233019
233192
|
event.stopPropagation();
|
|
233020
233193
|
// No `dbId`: these payloads carry the `unique_id` only. AnalyticsLayout
|
|
@@ -233024,7 +233197,10 @@ function AgentScopeLink({ uniqueId, name, fallback = '-', onScoped, className, t
|
|
|
233024
233197
|
onScoped === null || onScoped === void 0 ? void 0 : onScoped();
|
|
233025
233198
|
},
|
|
233026
233199
|
// Rows that open on Enter/Space would otherwise swallow the key press.
|
|
233027
|
-
onKeyDown: (event) => event.stopPropagation(),
|
|
233200
|
+
onKeyDown: (event) => event.stopPropagation(),
|
|
233201
|
+
// Truncates inside an `inline-flex` box so the name keeps the baseline
|
|
233202
|
+
// of the "Agent:" label beside it (see UserProfileLink).
|
|
233203
|
+
className: cn('inline-flex max-w-full cursor-pointer text-left hover:text-blue-600 hover:underline focus:text-blue-600 focus:outline-none', className), "aria-label": t('analyticsAgentScopeLink.scopeToAgent', { name: display }), "data-testid": testId, children: jsx("span", { className: "min-w-0 truncate", children: display }) }));
|
|
233028
233204
|
}
|
|
233029
233205
|
|
|
233030
233206
|
/**
|
|
@@ -233362,7 +233538,7 @@ function SectionHeading({ icon, children }) {
|
|
|
233362
233538
|
return (jsxs("h4", { className: "mb-2 flex items-center gap-1.5 text-xs font-semibold tracking-wide text-gray-700 uppercase", children: [icon, children] }));
|
|
233363
233539
|
}
|
|
233364
233540
|
const MODEL_KEYS = new Set(['llm_model', 'llm_provider']);
|
|
233365
|
-
function MetadataSection({ metadata, renderModel, }) {
|
|
233541
|
+
function MetadataSection({ metadata, renderModel, tenantKey, mentorId, }) {
|
|
233366
233542
|
var _a, _b;
|
|
233367
233543
|
const t = useT();
|
|
233368
233544
|
const labelFor = useFieldLabels();
|
|
@@ -233370,7 +233546,9 @@ function MetadataSection({ metadata, renderModel, }) {
|
|
|
233370
233546
|
const model = ((_a = metadata.llm_model) !== null && _a !== void 0 ? _a : '').trim() || undefined;
|
|
233371
233547
|
const provider = ((_b = metadata.llm_provider) !== null && _b !== void 0 ? _b : '').trim() || undefined;
|
|
233372
233548
|
const hasModel = !!(model || provider);
|
|
233373
|
-
return (jsxs("section", { "data-testid": "transcript-turn-metadata", children: [jsx(SectionHeading, { icon: jsx(Info$3, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), children: t('analyticsTranscriptTurnDetails.metadata') }), hasModel && (jsx("div", { "data-testid": "transcript-turn-model", className: "mb-2", children:
|
|
233549
|
+
return (jsxs("section", { "data-testid": "transcript-turn-metadata", children: [jsx(SectionHeading, { icon: jsx(Info$3, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), children: t('analyticsTranscriptTurnDetails.metadata') }), hasModel && (jsx("div", { "data-testid": "transcript-turn-model", className: "mb-2", children: renderModel
|
|
233550
|
+
? renderModel({ model, provider })
|
|
233551
|
+
: defaultRenderModel({ model, provider, tenantKey, mentorId }) })), jsx(DetailRows, { entries: rest, labelFor: labelFor })] }));
|
|
233374
233552
|
}
|
|
233375
233553
|
function RequestContextSection({ requestContext }) {
|
|
233376
233554
|
const t = useT();
|
|
@@ -233385,7 +233563,7 @@ function RequestContextSection({ requestContext }) {
|
|
|
233385
233563
|
*/
|
|
233386
233564
|
const defaultRenderDocuments = (documents) => (jsx(RetrievedDocumentsButton, { documents: toRetrievedDocuments(documents) }));
|
|
233387
233565
|
const defaultRenderToolCalls = (toolCalls) => (jsx(ToolCallIndicator, { toolCalls: toToolCallInfos(toolCalls), showResults: true }));
|
|
233388
|
-
const defaultRenderModel = ({ model, provider }) =>
|
|
233566
|
+
const defaultRenderModel = ({ model, provider, tenantKey, mentorId, }) => jsx(LlmModelBadge, { model: model, provider: provider, tenantKey: tenantKey, mentorId: mentorId });
|
|
233389
233567
|
const defaultRenderFiles = (files) => (jsx(TranscriptFileCards, { files: files }));
|
|
233390
233568
|
/**
|
|
233391
233569
|
* Collapsible "Sources / Tools / Metadata" panel for one AI turn of an admin
|
|
@@ -233395,7 +233573,7 @@ const defaultRenderFiles = (files) => (jsx(TranscriptFileCards, { files: files }
|
|
|
233395
233573
|
* renders nothing at all when every field is null or empty, so it is safe to
|
|
233396
233574
|
* drop under every AI bubble.
|
|
233397
233575
|
*/
|
|
233398
|
-
function TranscriptTurnDetails({ turn, className, defaultOpen = false, renderDocuments, renderToolCalls, renderModel, renderFiles, }) {
|
|
233576
|
+
function TranscriptTurnDetails({ turn, className, defaultOpen = false, renderDocuments, renderToolCalls, renderModel, renderFiles, tenantKey, mentorId, }) {
|
|
233399
233577
|
const t = useT();
|
|
233400
233578
|
const labelFor = useFieldLabels();
|
|
233401
233579
|
const [open, setOpen] = React__default.useState(defaultOpen);
|
|
@@ -233409,7 +233587,7 @@ function TranscriptTurnDetails({ turn, className, defaultOpen = false, renderDoc
|
|
|
233409
233587
|
const requestContext = hasEntries(turn === null || turn === void 0 ? void 0 : turn.request_context) ? turn === null || turn === void 0 ? void 0 : turn.request_context : null;
|
|
233410
233588
|
return (jsx(DetailCtx.Provider, { value: detailContext, children: jsxs(Collapsible, { open: open, onOpenChange: setOpen, className: cn('mt-2', className), "data-testid": "transcript-turn-details", children: [jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [jsx(CollapsibleTrigger, { asChild: true, children: jsxs(Button$1, { type: "button", variant: "outline", size: "sm", className: "flex items-center gap-2 border-gray-200 bg-white text-gray-700 hover:bg-gray-50", "aria-expanded": open, children: [jsx(ChevronDown, { className: cn('h-4 w-4 transition-transform', open && 'rotate-180'), "aria-hidden": "true" }), open
|
|
233411
233589
|
? t('analyticsTranscriptTurnDetails.hideDetails')
|
|
233412
|
-
: t('analyticsTranscriptTurnDetails.showDetails')] }) }), documents.length > 0 && (jsx("div", { "data-testid": "transcript-turn-sources", className: "contents", children: (renderDocuments !== null && renderDocuments !== void 0 ? renderDocuments : defaultRenderDocuments)(documents) })), jsx(TranscriptRollupBadges, { documentsCount: 0, toolCallsCount: toolCalls.length })] }), jsxs(CollapsibleContent, { className: "mt-2 space-y-5 rounded-lg border border-gray-200 bg-white p-3", children: [toolCalls.length > 0 && (jsx("div", { "data-testid": "transcript-turn-tools", children: (renderToolCalls !== null && renderToolCalls !== void 0 ? renderToolCalls : defaultRenderToolCalls)(toolCalls) })), metadata && jsx(MetadataSection, { metadata: metadata, renderModel: renderModel }), requestContext && jsx(RequestContextSection, { requestContext: requestContext })] })] }) }));
|
|
233590
|
+
: t('analyticsTranscriptTurnDetails.showDetails')] }) }), documents.length > 0 && (jsx("div", { "data-testid": "transcript-turn-sources", className: "contents", children: (renderDocuments !== null && renderDocuments !== void 0 ? renderDocuments : defaultRenderDocuments)(documents) })), jsx(TranscriptRollupBadges, { documentsCount: 0, toolCallsCount: toolCalls.length })] }), jsxs(CollapsibleContent, { className: "mt-2 space-y-5 rounded-lg border border-gray-200 bg-white p-3", children: [toolCalls.length > 0 && (jsx("div", { "data-testid": "transcript-turn-tools", children: (renderToolCalls !== null && renderToolCalls !== void 0 ? renderToolCalls : defaultRenderToolCalls)(toolCalls) })), metadata && (jsx(MetadataSection, { metadata: metadata, renderModel: renderModel, tenantKey: tenantKey, mentorId: mentorId })), requestContext && jsx(RequestContextSection, { requestContext: requestContext })] })] }) }));
|
|
233413
233591
|
}
|
|
233414
233592
|
/**
|
|
233415
233593
|
* "Documents · N" / "Tools · N" chips for a conversation row, from the
|
|
@@ -233425,118 +233603,6 @@ function TranscriptRollupBadges({ documentsCount, toolCallsCount, className, })
|
|
|
233425
233603
|
return (jsxs("span", { className: cn('inline-flex flex-wrap items-center gap-1.5', className), "data-testid": "transcript-rollup-badges", children: [documents > 0 && (jsxs(Badge, { variant: "outline", className: "gap-1 border-transparent bg-blue-50 font-normal text-blue-700", "data-testid": "transcript-sources-badge", children: [jsx(FileText, { className: "h-3 w-3", "aria-hidden": "true" }), t('analyticsTranscriptTurnDetails.sourcesBadge', { count: documents })] })), tools > 0 && (jsxs(Badge, { variant: "outline", className: "gap-1 border-transparent bg-amber-50 font-normal text-amber-800", "data-testid": "transcript-tools-badge", children: [jsx(Wrench, { className: "h-3 w-3", "aria-hidden": "true" }), t('analyticsTranscriptTurnDetails.toolsBadge', { count: tools })] }))] }));
|
|
233426
233604
|
}
|
|
233427
233605
|
|
|
233428
|
-
/**
|
|
233429
|
-
* One place that decides how a user is shown.
|
|
233430
|
-
*
|
|
233431
|
-
* Backend payloads name their user in a dozen ways — `email` / `lti_email` /
|
|
233432
|
-
* `user_email`, `username` / `student` / `lti_username`, `name` /
|
|
233433
|
-
* `full_name` / `user_full_name`, or a nested `user` object — and most of
|
|
233434
|
-
* them can be empty, `null`, or a placeholder like "None". Every surface used
|
|
233435
|
-
* to pick through those on its own. `resolveUserIdentity()` takes whatever
|
|
233436
|
-
* the payload is and returns what to show, what to open a profile on, and
|
|
233437
|
-
* the avatar initial, so the rule lives here and can be tweaked once.
|
|
233438
|
-
*
|
|
233439
|
-
* Default rule: email → full name → username → the anonymous label.
|
|
233440
|
-
*/
|
|
233441
|
-
const DEFAULT_USER_IDENTITY_ORDER = ['email', 'name', 'username'];
|
|
233442
|
-
const DEFAULT_ANONYMOUS_LABEL = 'Anonymous';
|
|
233443
|
-
/** Values backends emit instead of "nothing". Compared case-insensitively. */
|
|
233444
|
-
const PLACEHOLDERS = new Set([
|
|
233445
|
-
'',
|
|
233446
|
-
'none',
|
|
233447
|
-
'null',
|
|
233448
|
-
'undefined',
|
|
233449
|
-
'n/a',
|
|
233450
|
-
'na',
|
|
233451
|
-
'-',
|
|
233452
|
-
'anonymous',
|
|
233453
|
-
'anonymoususer',
|
|
233454
|
-
]);
|
|
233455
|
-
/**
|
|
233456
|
-
* `local@domain.tld` with no whitespace, checked with a single pass rather than
|
|
233457
|
-
* a backtracking pattern (CodeQL flags `[^@]+@[^@]+\.[^@]+` as polynomial on
|
|
233458
|
-
* adversarial input).
|
|
233459
|
-
*/
|
|
233460
|
-
const isEmailLike = (value) => {
|
|
233461
|
-
const text = value.trim();
|
|
233462
|
-
if (!text || /\s/.test(text))
|
|
233463
|
-
return false;
|
|
233464
|
-
const at = text.indexOf('@');
|
|
233465
|
-
if (at <= 0 || at !== text.lastIndexOf('@') || at === text.length - 1)
|
|
233466
|
-
return false;
|
|
233467
|
-
const domain = text.slice(at + 1);
|
|
233468
|
-
const dot = domain.indexOf('.');
|
|
233469
|
-
// A dot somewhere inside the domain, with something after the last one.
|
|
233470
|
-
return dot > 0 && !domain.endsWith('.');
|
|
233471
|
-
};
|
|
233472
|
-
/** Trimmed string, or undefined for blanks, non-strings and placeholders. */
|
|
233473
|
-
const clean = (value) => {
|
|
233474
|
-
if (typeof value !== 'string')
|
|
233475
|
-
return undefined;
|
|
233476
|
-
const trimmed = value.trim();
|
|
233477
|
-
return PLACEHOLDERS.has(trimmed.toLowerCase()) ? undefined : trimmed;
|
|
233478
|
-
};
|
|
233479
|
-
const firstOf = (...candidates) => {
|
|
233480
|
-
for (const candidate of candidates) {
|
|
233481
|
-
const value = clean(candidate);
|
|
233482
|
-
if (value)
|
|
233483
|
-
return value;
|
|
233484
|
-
}
|
|
233485
|
-
return undefined;
|
|
233486
|
-
};
|
|
233487
|
-
const nested = (source) => source.user && typeof source.user === 'object' ? source.user : undefined;
|
|
233488
|
-
/**
|
|
233489
|
-
* Resolve how a user should be displayed from any payload that names one.
|
|
233490
|
-
*
|
|
233491
|
-
* - `email`: `lti_email`, `email`, `user_email`, the nested `user`'s email —
|
|
233492
|
-
* or a username field that turns out to hold an email address.
|
|
233493
|
-
* - `username`: `lti_username`, `username`, `student`, `user_username`, the
|
|
233494
|
-
* nested `user`'s username, or a bare string/number `user` value.
|
|
233495
|
-
* - `name`: `user_full_name`, `full_name`, `name`, `first_name last_name`, or
|
|
233496
|
-
* the nested `user`'s name.
|
|
233497
|
-
* - `profileUsername`: the first *platform* username (never an LTI claim).
|
|
233498
|
-
*
|
|
233499
|
-
* A string source is treated as an email when it looks like one, else as a
|
|
233500
|
-
* username. Placeholder strings ("None", "-", "anonymous"…) count as absent.
|
|
233501
|
-
*/
|
|
233502
|
-
function resolveUserIdentity(source, options = {}) {
|
|
233503
|
-
var _a;
|
|
233504
|
-
const anonymousLabel = options.anonymousLabel || DEFAULT_ANONYMOUS_LABEL;
|
|
233505
|
-
const order = ((_a = options.order) === null || _a === void 0 ? void 0 : _a.length) ? options.order : DEFAULT_USER_IDENTITY_ORDER;
|
|
233506
|
-
const record = source && typeof source === 'object' ? source : { user: source !== null && source !== void 0 ? source : null };
|
|
233507
|
-
const inner = nested(record);
|
|
233508
|
-
// A bare `user` value is an id or username; numeric ids are still shown.
|
|
233509
|
-
const bareUser = typeof record.user === 'number' && Number.isFinite(record.user)
|
|
233510
|
-
? String(record.user)
|
|
233511
|
-
: typeof record.user === 'string'
|
|
233512
|
-
? clean(record.user)
|
|
233513
|
-
: undefined;
|
|
233514
|
-
let email = firstOf(record.lti_email, record.email, record.user_email, inner === null || inner === void 0 ? void 0 : inner.lti_email, inner === null || inner === void 0 ? void 0 : inner.email, inner === null || inner === void 0 ? void 0 : inner.user_email);
|
|
233515
|
-
const platformUsername = firstOf(record.username, record.student, record.user_username, inner === null || inner === void 0 ? void 0 : inner.username, inner === null || inner === void 0 ? void 0 : inner.student, inner === null || inner === void 0 ? void 0 : inner.user_username, bareUser && !isEmailLike(bareUser) ? bareUser : undefined);
|
|
233516
|
-
let username = firstOf(record.lti_username, inner === null || inner === void 0 ? void 0 : inner.lti_username, platformUsername);
|
|
233517
|
-
const composed = [clean(record.first_name), clean(record.last_name)].filter(Boolean).join(' ');
|
|
233518
|
-
const name = firstOf(record.user_full_name, record.full_name, record.name, composed, inner === null || inner === void 0 ? void 0 : inner.user_full_name, inner === null || inner === void 0 ? void 0 : inner.full_name, inner === null || inner === void 0 ? void 0 : inner.name);
|
|
233519
|
-
// A bare string that looks like an email is an email, and so is a
|
|
233520
|
-
// "username" field that actually carries one.
|
|
233521
|
-
if (!email && bareUser && isEmailLike(bareUser))
|
|
233522
|
-
email = bareUser;
|
|
233523
|
-
if (!email && username && isEmailLike(username)) {
|
|
233524
|
-
email = username;
|
|
233525
|
-
username = undefined;
|
|
233526
|
-
}
|
|
233527
|
-
const facts = { email, username, name };
|
|
233528
|
-
const label = order.map((field) => facts[field]).find(Boolean);
|
|
233529
|
-
return {
|
|
233530
|
-
label: label !== null && label !== void 0 ? label : anonymousLabel,
|
|
233531
|
-
email,
|
|
233532
|
-
username,
|
|
233533
|
-
name,
|
|
233534
|
-
profileUsername: platformUsername,
|
|
233535
|
-
initial: (label !== null && label !== void 0 ? label : anonymousLabel).charAt(0).toUpperCase() || 'A',
|
|
233536
|
-
isAnonymous: !label,
|
|
233537
|
-
};
|
|
233538
|
-
}
|
|
233539
|
-
|
|
233540
233606
|
// Utility function to format relative time
|
|
233541
233607
|
const formatRelativeTime = (dateString, t) => {
|
|
233542
233608
|
const date = new Date(dateString);
|
|
@@ -233576,14 +233642,12 @@ const getMessageContent = (content) => {
|
|
|
233576
233642
|
return '';
|
|
233577
233643
|
};
|
|
233578
233644
|
/**
|
|
233579
|
-
*
|
|
233580
|
-
*
|
|
233581
|
-
*
|
|
233582
|
-
*
|
|
233645
|
+
* The model as the nav bar shows it (logo + display name); hosts may override
|
|
233646
|
+
* via `turnDetails.renderModel`. The catalogue is read for the tenant and the
|
|
233647
|
+
* agent the conversation ran on — route params only carry those on the mentor
|
|
233648
|
+
* SPA, so analytics passes them explicitly.
|
|
233583
233649
|
*/
|
|
233584
|
-
const
|
|
233585
|
-
/** The model as the nav bar shows it (logo + display name); hosts may override via `turnDetails.renderModel`. */
|
|
233586
|
-
const renderModelBadge = ({ model, provider }) => (jsx(LlmModelBadge, { model: model, provider: provider }));
|
|
233650
|
+
const renderModelBadge = ({ model, provider, tenantKey, mentorId, }) => jsx(LlmModelBadge, { model: model, provider: provider, tenantKey: tenantKey, mentorId: mentorId });
|
|
233587
233651
|
/** Newer deployments name the provider on rows and summaries; older ones only the model. */
|
|
233588
233652
|
const providerOf = (source) => {
|
|
233589
233653
|
const value = source === null || source === void 0 ? void 0 : source.llm_provider;
|
|
@@ -233619,14 +233683,24 @@ function TranscriptDocumentsButton({ detail, className, }) {
|
|
|
233619
233683
|
return (jsx(RetrievedDocumentsButton, { sessionId: sessionId, documents: documents.length > 0 ? documents : undefined, className: className }));
|
|
233620
233684
|
}
|
|
233621
233685
|
function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMentorId, usergroupIds, turnDetails, }) {
|
|
233622
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
233686
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
233623
233687
|
const t = useT();
|
|
233688
|
+
// Who a row belongs to, by the shared identity rule: the translated
|
|
233689
|
+
// "Anonymous" when the row names nobody (a bare "-" read as missing data).
|
|
233690
|
+
const identifyUser = React__default.useCallback((source, order) => resolveUserIdentity(source, {
|
|
233691
|
+
order,
|
|
233692
|
+
anonymousLabel: t('analyticsAnalyticsTranscriptsStats.anonymous'),
|
|
233693
|
+
}).label, [t]);
|
|
233624
233694
|
const currentMentorId = useScopedMentorId(selectedMentorId, mentorId);
|
|
233625
233695
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
233626
233696
|
const searchParams = useSearchParams();
|
|
233627
233697
|
const router = useRouter();
|
|
233628
233698
|
const pathname = usePathname();
|
|
233629
233699
|
const { transcriptsMessagesData, isLoadingTranscriptsMessagesData, isFetchingTranscriptsMessagesData, filters, setFilters, handleClearFilters, currentPage, handlePageChange, selectedTranscript, setSelectedTranscript, transcriptsMessagesDetailsData, isLoadingTranscriptsMessagesDetailsData, isErrorTranscriptsMessagesDetailsData, transcriptsConversationHeadlineData, isLoadingTranscriptsConversationHeadlineData, } = useTranscripts({ tenantKey, mentorId: currentMentorId, usergroupIds });
|
|
233700
|
+
// The agent the open transcript ran on — the catalogue scope for its model
|
|
233701
|
+
// badge. Hosts that browse across agents (the LMS analytics route) pass no
|
|
233702
|
+
// mentorId, so the transcript's own agent is the only correct scope.
|
|
233703
|
+
const detailMentorId = ((_a = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _a === void 0 ? void 0 : _a.mentor_unique_id) || currentMentorId;
|
|
233630
233704
|
// Read session_id from URL on mount and select the transcript
|
|
233631
233705
|
useEffect(() => {
|
|
233632
233706
|
const sessionIdParam = searchParams === null || searchParams === void 0 ? void 0 : searchParams.get('session_id');
|
|
@@ -233739,15 +233813,17 @@ function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMe
|
|
|
233739
233813
|
? ((_e = turnDetails === null || turnDetails === void 0 ? void 0 : turnDetails.renderModel) !== null && _e !== void 0 ? _e : renderModelBadge)({
|
|
233740
233814
|
model: transcriptsMessagesDetailsData.summary.model,
|
|
233741
233815
|
provider: (_f = providerOf(transcriptsMessagesDetailsData.summary)) !== null && _f !== void 0 ? _f : providerOfTurns(transcriptsMessagesDetailsData.messages),
|
|
233816
|
+
tenantKey,
|
|
233817
|
+
mentorId: detailMentorId,
|
|
233742
233818
|
})
|
|
233743
233819
|
: '-'] }), jsx(TranscriptDocumentsButton, { detail: transcriptsMessagesDetailsData, className: "mt-2" })] })] }), jsx("div", { className: "flex-1 overflow-y-auto space-y-4 min-h-0", children: ((_g = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.messages) === null || _g === void 0 ? void 0 : _g.length) > 0 ? ((_h = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.messages) === null || _h === void 0 ? void 0 : _h.map((message, index) => {
|
|
233744
233820
|
var _a, _b;
|
|
233745
|
-
return (jsxs(React__default.Fragment, { children: [((message === null || message === void 0 ? void 0 : message.human) || !!((_a = message === null || message === void 0 ? void 0 : message.human_files) === null || _a === void 0 ? void 0 : _a.length)) && (jsxs("div", { className: `p-3 rounded-lg bg-blue-100 ml-4`, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleUser') }) }), message.human && (jsx("p", { className: "text-sm", children: getMessageContent(message.human) })), jsx(TranscriptFiles, { files: message.human_files })] }, `${index}-human`)), ((message === null || message === void 0 ? void 0 : message.ai) || !!((_b = message === null || message === void 0 ? void 0 : message.ai_files) === null || _b === void 0 ? void 0 : _b.length)) && (jsxs("div", { className: `p-3 rounded-lg bg-white mr-4`, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleAgent') }) }), message.ai && jsx(Markdown, { children: getMessageContent(message.ai) }), jsx(TranscriptFiles, { files: message.ai_files }), jsx(TranscriptTurnDetails, { turn: message, ...turnDetails })] }, `${index}-ai`))] }, index));
|
|
233821
|
+
return (jsxs(React__default.Fragment, { children: [((message === null || message === void 0 ? void 0 : message.human) || !!((_a = message === null || message === void 0 ? void 0 : message.human_files) === null || _a === void 0 ? void 0 : _a.length)) && (jsxs("div", { className: `p-3 rounded-lg bg-blue-100 ml-4`, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleUser') }) }), message.human && (jsx("p", { className: "text-sm", children: getMessageContent(message.human) })), jsx(TranscriptFiles, { files: message.human_files })] }, `${index}-human`)), ((message === null || message === void 0 ? void 0 : message.ai) || !!((_b = message === null || message === void 0 ? void 0 : message.ai_files) === null || _b === void 0 ? void 0 : _b.length)) && (jsxs("div", { className: `p-3 rounded-lg bg-white mr-4`, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleAgent') }) }), message.ai && jsx(Markdown, { children: getMessageContent(message.ai) }), jsx(TranscriptFiles, { files: message.ai_files }), jsx(TranscriptTurnDetails, { turn: message, tenantKey: tenantKey, mentorId: detailMentorId, ...turnDetails })] }, `${index}-ai`))] }, index));
|
|
233746
233822
|
})) : (jsx("div", { className: "text-center text-gray-500 py-8", children: jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.noMessages') }) })) })] })) }));
|
|
233747
233823
|
};
|
|
233748
|
-
return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 mb-6", children: [jsx(StatCard, { title: t('analyticsAnalyticsTranscriptsStats.avgMessagesPerConversation'), value: ((
|
|
233749
|
-
undefined, loading: isLoadingTranscriptsConversationHeadlineData, description: t('analyticsAnalyticsTranscriptsStats.avgMessagesPerConversationDescription') }), jsx(StatCard, { title: t('analyticsAnalyticsTranscriptsStats.avgCostPerConversation'), value: Number(((
|
|
233750
|
-
undefined, showDollarSign: true, loading: isLoadingTranscriptsConversationHeadlineData, description: t('analyticsAnalyticsTranscriptsStats.avgCostPerConversationDescription') }), jsx(StatCard, { title: t('analyticsAnalyticsTranscriptsStats.avgRating'), value: ((
|
|
233824
|
+
return (jsxs("div", { className: "space-y-8", children: [jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 mb-6", children: [jsx(StatCard, { title: t('analyticsAnalyticsTranscriptsStats.avgMessagesPerConversation'), value: ((_b = transcriptsConversationHeadlineData === null || transcriptsConversationHeadlineData === void 0 ? void 0 : transcriptsConversationHeadlineData.avg_messages_per_conversation) === null || _b === void 0 ? void 0 : _b.value) || 0, percentage: ((_c = transcriptsConversationHeadlineData === null || transcriptsConversationHeadlineData === void 0 ? void 0 : transcriptsConversationHeadlineData.avg_messages_per_conversation) === null || _c === void 0 ? void 0 : _c.percentage_change) ||
|
|
233825
|
+
undefined, loading: isLoadingTranscriptsConversationHeadlineData, description: t('analyticsAnalyticsTranscriptsStats.avgMessagesPerConversationDescription') }), jsx(StatCard, { title: t('analyticsAnalyticsTranscriptsStats.avgCostPerConversation'), value: Number(((_d = transcriptsConversationHeadlineData === null || transcriptsConversationHeadlineData === void 0 ? void 0 : transcriptsConversationHeadlineData.avg_cost_per_conversation) === null || _d === void 0 ? void 0 : _d.value) || 0).toFixed(2), percentage: ((_e = transcriptsConversationHeadlineData === null || transcriptsConversationHeadlineData === void 0 ? void 0 : transcriptsConversationHeadlineData.avg_cost_per_conversation) === null || _e === void 0 ? void 0 : _e.percentage_change) ||
|
|
233826
|
+
undefined, showDollarSign: true, loading: isLoadingTranscriptsConversationHeadlineData, description: t('analyticsAnalyticsTranscriptsStats.avgCostPerConversationDescription') }), jsx(StatCard, { title: t('analyticsAnalyticsTranscriptsStats.avgRating'), value: ((_f = transcriptsConversationHeadlineData === null || transcriptsConversationHeadlineData === void 0 ? void 0 : transcriptsConversationHeadlineData.avg_rating) === null || _f === void 0 ? void 0 : _f.value) || 0, percentage: ((_g = transcriptsConversationHeadlineData === null || transcriptsConversationHeadlineData === void 0 ? void 0 : transcriptsConversationHeadlineData.avg_rating) === null || _g === void 0 ? void 0 : _g.percentage_change) || undefined, loading: isLoadingTranscriptsConversationHeadlineData, description: t('analyticsAnalyticsTranscriptsStats.avgRatingDescription') })] }), jsxs("div", { className: "flex h-[calc(100vh-120px)]", children: [jsxs("div", { className: "w-full md:w-2/3 md:pr-6 overflow-y-auto md:border-r border-gray-200 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]", children: [jsx("div", { className: "mb-6", children: jsxs("div", { className: "flex gap-2 mb-4 items-center", children: [jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-4 w-4" }), jsx(Input, { placeholder: t('analyticsAnalyticsTranscriptsStats.placeholderTopics'), value: filters.topicSearch, onChange: (e) => setFilters({ ...filters, topicSearch: e.target.value }), className: "pl-10 w-[200px]" })] }), jsx("div", { className: "w-[200px]", children: jsx(UserFilterSelect, { tenantKey: tenantKey, value: filters.userSearch, onChange: (username) => setFilters({ ...filters, userSearch: username }), showSelfOption: false, className: "bg-transparent" }) }), isFetchingTranscriptsMessagesData && (filters.userSearch || filters.topicSearch) ? (jsx("div", { className: "animate-spin rounded-full h-5 w-5 border-b-2 border-blue-500 ml-2", "aria-hidden": "true" })) : (jsx(Button$1, { variant: "outline", onClick: handleClearFilters, className: "whitespace-nowrap", children: t('analyticsAnalyticsTranscriptsStats.clearAll') }))] }) }), jsxs("div", { className: "bg-gray-50 p-4 rounded-lg mb-6", children: [jsxs("div", { className: "flex flex-wrap gap-x-8 gap-y-2 text-sm text-gray-600", children: [jsxs("div", { "aria-label": t('analyticsAnalyticsTranscriptsStats.ariaTotalConversations'), children: [transcriptsMessagesData === null || transcriptsMessagesData === void 0 ? void 0 : transcriptsMessagesData.summary.total_conversations, ' ', t('analyticsAnalyticsTranscriptsStats.conversations')] }), jsx("div", { children: "\u2022" }), jsxs("div", { children: [transcriptsMessagesData === null || transcriptsMessagesData === void 0 ? void 0 : transcriptsMessagesData.summary.user_queries, ' ', t('analyticsAnalyticsTranscriptsStats.userQueries')] }), jsx("div", { children: "\u2022" }), jsxs("div", { children: [transcriptsMessagesData === null || transcriptsMessagesData === void 0 ? void 0 : transcriptsMessagesData.summary.assistant_responses, ' ', t('analyticsAnalyticsTranscriptsStats.assistantResponses')] })] }), jsx("div", { className: "flex flex-wrap gap-x-8 gap-y-2 text-sm text-gray-600 mt-2", children: jsxs("div", { children: [transcriptsMessagesData === null || transcriptsMessagesData === void 0 ? void 0 : transcriptsMessagesData.summary.average_sentiment_score, ' ', t('analyticsAnalyticsTranscriptsStats.averageSentimentScore')] }) })] }), jsx("div", { className: "flex flex-col gap-4", children: isLoadingTranscriptsMessagesData ? (
|
|
233751
233827
|
// Loading state
|
|
233752
233828
|
jsx("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, index) => (jsxs(Card$1, { className: "p-4 animate-pulse", children: [jsx("div", { className: "mb-3", children: jsx("div", { className: "h-4 bg-gray-200 rounded w-3/4" }) }), jsxs("div", { className: "flex flex-wrap gap-2 mb-3", children: [jsx("div", { className: "h-6 bg-gray-200 rounded w-16" }), jsx("div", { className: "h-6 bg-gray-200 rounded w-20" })] }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2 mb-2", children: [jsx("div", { className: "h-4 bg-gray-200 rounded w-24" }), jsx("div", { className: "h-4 bg-gray-200 rounded w-20" })] }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2", children: [jsx("div", { className: "h-4 bg-gray-200 rounded w-20" }), jsx("div", { className: "h-4 bg-gray-200 rounded w-24" })] })] }, index))) })) : (transcriptsMessagesData === null || transcriptsMessagesData === void 0 ? void 0 : transcriptsMessagesData.results) && transcriptsMessagesData.results.length > 0 ? (
|
|
233753
233829
|
// Results
|
|
@@ -233764,10 +233840,12 @@ function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMe
|
|
|
233764
233840
|
? t('analyticsAnalyticsTranscriptsStats.sentimentNegative')
|
|
233765
233841
|
: transcript.sentiment === 'positive'
|
|
233766
233842
|
? t('analyticsAnalyticsTranscriptsStats.sentimentPositive')
|
|
233767
|
-
: t('analyticsAnalyticsTranscriptsStats.sentimentNeutral'), ' ', t('analyticsAnalyticsTranscriptsStats.userSentiment')] })] }) }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-500 mb-2", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelUser'), ' ', jsx(UserProfileLink, { currentSPA: currentSPA, tenantKey: tenantKey, username: transcript === null || transcript === void 0 ? void 0 : transcript.username, display: identifyUser(transcript) })] }), jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelAgent'), ' ', jsx(AgentScopeLink, { uniqueId: transcript === null || transcript === void 0 ? void 0 : transcript.mentor_unique_id, name: transcript === null || transcript === void 0 ? void 0 : transcript.mentor })] })] }), jsx("div", { className: "flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-500 mb-2", children: jsxs("div", { className: "inline-flex flex-wrap items-center gap-1.5", children: [t('analyticsAnalyticsTranscriptsStats.labelModelCard'), ' ', (transcript === null || transcript === void 0 ? void 0 : transcript.model)
|
|
233843
|
+
: t('analyticsAnalyticsTranscriptsStats.sentimentNeutral'), ' ', t('analyticsAnalyticsTranscriptsStats.userSentiment')] })] }) }), jsxs("div", { className: "flex flex-wrap items-baseline gap-x-6 gap-y-2 text-xs text-gray-500 mb-2", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelUser'), ' ', jsx(UserProfileLink, { currentSPA: currentSPA, tenantKey: tenantKey, username: transcript === null || transcript === void 0 ? void 0 : transcript.username, display: identifyUser(transcript) })] }), jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelAgent'), ' ', jsx(AgentScopeLink, { uniqueId: transcript === null || transcript === void 0 ? void 0 : transcript.mentor_unique_id, name: transcript === null || transcript === void 0 ? void 0 : transcript.mentor })] })] }), jsx("div", { className: "flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-500 mb-2", children: jsxs("div", { className: "inline-flex flex-wrap items-center gap-1.5", children: [t('analyticsAnalyticsTranscriptsStats.labelModelCard'), ' ', (transcript === null || transcript === void 0 ? void 0 : transcript.model)
|
|
233768
233844
|
? ((_c = turnDetails === null || turnDetails === void 0 ? void 0 : turnDetails.renderModel) !== null && _c !== void 0 ? _c : renderModelBadge)({
|
|
233769
233845
|
model: transcript.model,
|
|
233770
233846
|
provider: providerOf(transcript),
|
|
233847
|
+
tenantKey,
|
|
233848
|
+
mentorId: (transcript === null || transcript === void 0 ? void 0 : transcript.mentor_unique_id) || currentMentorId,
|
|
233771
233849
|
})
|
|
233772
233850
|
: '-'] }) }), jsxs("div", { className: "flex flex-wrap gap-x-6 gap-y-2 text-xs text-gray-500", children: [jsxs("div", { children: [transcript.message_count, " ", t('analyticsAnalyticsTranscriptsStats.messages')] }), jsx("div", { children: "\u2022" }), jsxs("div", { children: ["$", Number((transcript === null || transcript === void 0 ? void 0 : transcript.cost) || 0).toFixed(2), ' ', t('analyticsAnalyticsTranscriptsStats.estimatedCost')] }), (transcript === null || transcript === void 0 ? void 0 : transcript.created_at) && (jsxs(Fragment$1, { children: [jsx("div", { children: "\u2022" }), jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.created'), ' ', formatRelativeTime(transcript.created_at, t)] })] }))] })] }, transcript.session));
|
|
233773
233851
|
})) : (
|
|
@@ -233805,14 +233883,16 @@ function AnalyticsTranscriptsStats({ tenantKey, currentSPA, mentorId, selectedMe
|
|
|
233805
233883
|
/* Error or no data state */
|
|
233806
233884
|
jsx("div", { className: "flex items-center justify-center h-full text-gray-400", children: jsxs("div", { className: "text-center", children: [jsx(X$1, { className: "h-6 w-6 mx-auto mb-2 text-red-400" }), jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.noTranscriptDetails') }), jsx("p", { className: "text-sm mt-1", children: t('analyticsAnalyticsTranscriptsStats.unableToLoadTranscript') })] }) })) : (
|
|
233807
233885
|
/* Data loaded successfully */
|
|
233808
|
-
jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "mb-4", children: jsxs("div", { className: "text-sm text-gray-500 space-y-1", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelUser'), ' ', jsx(UserProfileLink, { currentSPA: currentSPA, tenantKey: tenantKey, username: (
|
|
233809
|
-
? ((
|
|
233886
|
+
jsxs("div", { className: "space-y-4", children: [jsx("div", { className: "mb-4", children: jsxs("div", { className: "text-sm text-gray-500 space-y-1", children: [jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelUser'), ' ', jsx(UserProfileLink, { currentSPA: currentSPA, tenantKey: tenantKey, username: (_h = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _h === void 0 ? void 0 : _h.username, display: identifyUser(transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) })] }), jsxs("div", { children: [t('analyticsAnalyticsTranscriptsStats.labelAgent'), ' ', jsx(AgentScopeLink, { uniqueId: (_j = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _j === void 0 ? void 0 : _j.mentor_unique_id, name: (_k = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _k === void 0 ? void 0 : _k.mentor })] }), jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [t('analyticsAnalyticsTranscriptsStats.labelModel'), ' ', ((_l = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.summary) === null || _l === void 0 ? void 0 : _l.model)
|
|
233887
|
+
? ((_m = turnDetails === null || turnDetails === void 0 ? void 0 : turnDetails.renderModel) !== null && _m !== void 0 ? _m : renderModelBadge)({
|
|
233810
233888
|
model: transcriptsMessagesDetailsData.summary.model,
|
|
233811
|
-
provider: (
|
|
233889
|
+
provider: (_o = providerOf(transcriptsMessagesDetailsData.summary)) !== null && _o !== void 0 ? _o : providerOfTurns(transcriptsMessagesDetailsData.messages),
|
|
233890
|
+
tenantKey,
|
|
233891
|
+
mentorId: detailMentorId,
|
|
233812
233892
|
})
|
|
233813
|
-
: '-'] }), jsx(TranscriptDocumentsButton, { detail: transcriptsMessagesDetailsData, className: "mt-2" })] }) }), jsx("div", { className: "space-y-4 pb-4", children: ((
|
|
233893
|
+
: '-'] }), jsx(TranscriptDocumentsButton, { detail: transcriptsMessagesDetailsData, className: "mt-2" })] }) }), jsx("div", { className: "space-y-4 pb-4", children: ((_p = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.messages) === null || _p === void 0 ? void 0 : _p.length) > 0 ? ((_q = transcriptsMessagesDetailsData === null || transcriptsMessagesDetailsData === void 0 ? void 0 : transcriptsMessagesDetailsData.messages) === null || _q === void 0 ? void 0 : _q.map((message, index) => {
|
|
233814
233894
|
var _a, _b;
|
|
233815
|
-
return (jsxs(React__default.Fragment, { children: [((message === null || message === void 0 ? void 0 : message.human) || !!((_a = message === null || message === void 0 ? void 0 : message.human_files) === null || _a === void 0 ? void 0 : _a.length)) && (jsxs("div", { className: "p-3 rounded-lg bg-blue-100 ml-4", children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleUser') }) }), message.human && (jsx("p", { className: "text-sm", children: getMessageContent(message.human) })), jsx(TranscriptFiles, { files: message.human_files })] })), ((message === null || message === void 0 ? void 0 : message.ai) || !!((_b = message === null || message === void 0 ? void 0 : message.ai_files) === null || _b === void 0 ? void 0 : _b.length)) && (jsxs("div", { className: "p-3 rounded-lg bg-white mr-4 border", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleAgent') }) }), message.ai && jsx(Markdown, { children: getMessageContent(message.ai) }), jsx(TranscriptFiles, { files: message.ai_files }), jsx(TranscriptTurnDetails, { turn: message, ...turnDetails })] }))] }, index));
|
|
233895
|
+
return (jsxs(React__default.Fragment, { children: [((message === null || message === void 0 ? void 0 : message.human) || !!((_a = message === null || message === void 0 ? void 0 : message.human_files) === null || _a === void 0 ? void 0 : _a.length)) && (jsxs("div", { className: "p-3 rounded-lg bg-blue-100 ml-4", children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleUser') }) }), message.human && (jsx("p", { className: "text-sm", children: getMessageContent(message.human) })), jsx(TranscriptFiles, { files: message.human_files })] })), ((message === null || message === void 0 ? void 0 : message.ai) || !!((_b = message === null || message === void 0 ? void 0 : message.ai_files) === null || _b === void 0 ? void 0 : _b.length)) && (jsxs("div", { className: "p-3 rounded-lg bg-white mr-4 border", style: { borderColor: 'oklch(.922 0 0)' }, children: [jsx("div", { className: "flex justify-between items-start mb-1", children: jsx("span", { className: "font-medium text-sm", children: t('analyticsAnalyticsTranscriptsStats.roleAgent') }) }), message.ai && jsx(Markdown, { children: getMessageContent(message.ai) }), jsx(TranscriptFiles, { files: message.ai_files }), jsx(TranscriptTurnDetails, { turn: message, tenantKey: tenantKey, mentorId: detailMentorId, ...turnDetails })] }))] }, index));
|
|
233816
233896
|
})) : (jsx("div", { className: "text-center text-gray-500 py-8", children: jsx("p", { children: t('analyticsAnalyticsTranscriptsStats.noMessages') }) })) })] })) })] }) }))] }));
|
|
233817
233897
|
}
|
|
233818
233898
|
|
|
@@ -236507,7 +236587,7 @@ function AgentAuditLogView({ tenantKey, mentorId, userId, selectedMentorId, curr
|
|
|
236507
236587
|
}, numberOfMonths: 2 }) })] }), jsx("div", { className: "min-w-[160px]", children: jsxs(Select$1, { value: actionFilter !== undefined ? String(actionFilter) : 'all', onValueChange: (val) => {
|
|
236508
236588
|
setActionFilter(val === 'all' ? undefined : Number(val));
|
|
236509
236589
|
setPage(1);
|
|
236510
|
-
}, children: [jsx(SelectTrigger, { className: "w-full font-normal bg-white h-9", children: jsx(SelectValue, { placeholder: t('analyticsAnalyticsAuditLogStats.allActions') }) }), jsx(SelectContent, { children: ACTION_FILTER_OPTIONS.map((opt) => (jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value))) })] }) })] }) }), jsx("div", { className: "overflow-hidden rounded-md border border-[oklch(0.922_0_0)] bg-white", children: jsx("div", { className: "overflow-x-auto", children: jsx("div", { className: "inline-block min-w-full align-middle", children: isLoading ? (jsx("div", { className: "flex items-center justify-center w-full py-10", children: jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-blue-600 border-t-transparent" }) })) : error && !is403 ? (jsx("div", { className: "py-8 text-center text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.loadError') })) : !((_a = data === null || data === void 0 ? void 0 : data.results) === null || _a === void 0 ? void 0 : _a.length) ? (jsx("div", { className: "h-[120px]", children: jsx(EmptyStats, { title: t('analyticsAnalyticsAuditLogStats.noEntries') }) })) : (jsxs(Table, { className: "min-w-full", children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "bg-muted/50 border-b border-[oklch(0.922_0_0)]", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colUser') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colAction') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colTime') })] }) }), jsx(TableBody, { children: data.results.map((entry) => (jsxs(TableRow, { className: "border-b border-[oklch(0.922_0_0)] last:border-0", children: [jsx(TableCell, { className: "p-3 font-medium whitespace-nowrap text-[#646464]", children: jsx(UserProfileLink, { tenantKey: tenantKey, currentSPA: currentSPA, username: entry.actor_username, display: entry.actor_email
|
|
236590
|
+
}, children: [jsx(SelectTrigger, { className: "w-full font-normal bg-white h-9", children: jsx(SelectValue, { placeholder: t('analyticsAnalyticsAuditLogStats.allActions') }) }), jsx(SelectContent, { children: ACTION_FILTER_OPTIONS.map((opt) => (jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value))) })] }) })] }) }), jsx("div", { className: "overflow-hidden rounded-md border border-[oklch(0.922_0_0)] bg-white", children: jsx("div", { className: "overflow-x-auto", children: jsx("div", { className: "inline-block min-w-full align-middle", children: isLoading ? (jsx("div", { className: "flex items-center justify-center w-full py-10", children: jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-blue-600 border-t-transparent" }) })) : error && !is403 ? (jsx("div", { className: "py-8 text-center text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.loadError') })) : !((_a = data === null || data === void 0 ? void 0 : data.results) === null || _a === void 0 ? void 0 : _a.length) ? (jsx("div", { className: "h-[120px]", children: jsx(EmptyStats, { title: t('analyticsAnalyticsAuditLogStats.noEntries') }) })) : (jsxs(Table, { className: "min-w-full", children: [jsx(TableHeader, { children: jsxs(TableRow, { className: "bg-muted/50 border-b border-[oklch(0.922_0_0)]", children: [jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colUser') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colAction') }), jsx(TableHead, { className: "p-3 text-left text-sm whitespace-nowrap text-[#646464]", children: t('analyticsAnalyticsAuditLogStats.colTime') })] }) }), jsx(TableBody, { children: data.results.map((entry) => (jsxs(TableRow, { className: "border-b border-[oklch(0.922_0_0)] last:border-0", children: [jsx(TableCell, { className: "p-3 font-medium whitespace-nowrap text-[#646464]", children: jsx(UserProfileLink, { tenantKey: tenantKey, currentSPA: currentSPA, username: entry.actor_username, display: resolveUserIdentity({ email: entry.actor_email, username: entry.actor_username }, { anonymousLabel: t('analyticsAnalyticsAuditLogStats.anonymous') }).label }) }), jsx(TableCell, { className: "min-w-[250px] p-3 text-[#646464]", children: summarizeChanges(entry) }), jsx(TableCell, { className: "p-3 whitespace-nowrap text-[#646464]", children: formatDistanceToNow(new Date(entry.timestamp), { addSuffix: true }) })] }, entry.id))) })] })) }) }) }), jsx(IblPagination, { currentPage: page, totalPages: totalPages, onPageChange: setPage, disabled: isLoading })] }));
|
|
236511
236591
|
}
|
|
236512
236592
|
function AnalyticsAuditLogStats({ tenantKey, currentSPA, mentorId, userId, selectedMentorId, defaultScope = 'agent', timezone, canViewPlatformAudit, }) {
|
|
236513
236593
|
const t = useT();
|
|
@@ -236547,14 +236627,14 @@ const formatDate = (date) => date ? date.toISOString().split('T')[0] : undefined
|
|
|
236547
236627
|
function isForbiddenError(error) {
|
|
236548
236628
|
return !!error && 'status' in error && error.status === 403;
|
|
236549
236629
|
}
|
|
236550
|
-
function toRowFromMentorMemory(memory) {
|
|
236630
|
+
function toRowFromMentorMemory(memory, anonymousLabel) {
|
|
236551
236631
|
var _a, _b, _c, _d, _e, _f;
|
|
236552
236632
|
return {
|
|
236553
236633
|
id: memory.id,
|
|
236554
236634
|
content: memory.content,
|
|
236555
236635
|
categoryName: (_b = (_a = memory.category) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : null,
|
|
236556
236636
|
categorySlug: (_d = (_c = memory.category) === null || _c === void 0 ? void 0 : _c.slug) !== null && _d !== void 0 ? _d : null,
|
|
236557
|
-
learner: memory
|
|
236637
|
+
learner: resolveUserIdentity(memory, { anonymousLabel }).label,
|
|
236558
236638
|
username: memory.username,
|
|
236559
236639
|
email: memory.email || null,
|
|
236560
236640
|
mentorId: (_e = memory.mentor_id) !== null && _e !== void 0 ? _e : null,
|
|
@@ -236564,13 +236644,13 @@ function toRowFromMentorMemory(memory) {
|
|
|
236564
236644
|
createdAt: memory.created_at,
|
|
236565
236645
|
};
|
|
236566
236646
|
}
|
|
236567
|
-
function toRowFromGlobalMemory(memory) {
|
|
236647
|
+
function toRowFromGlobalMemory(memory, anonymousLabel) {
|
|
236568
236648
|
return {
|
|
236569
236649
|
id: memory.id,
|
|
236570
236650
|
content: memory.content,
|
|
236571
236651
|
categoryName: null,
|
|
236572
236652
|
categorySlug: null,
|
|
236573
|
-
learner: memory.
|
|
236653
|
+
learner: resolveUserIdentity(memory, { anonymousLabel }).label,
|
|
236574
236654
|
username: memory.username,
|
|
236575
236655
|
email: null,
|
|
236576
236656
|
mentorId: null,
|
|
@@ -236674,14 +236754,18 @@ const useMemory = ({ tenantKey, userId, mentorId, myMemory = false, }) => {
|
|
|
236674
236754
|
}), [page, learnerFilter, contentFilter, startDate, endDate]);
|
|
236675
236755
|
const { data: globalMemories, isLoading: isLoadingGlobal, isFetching: isFetchingGlobal, error: globalError, } = useGetGlobalMemoriesQuery({ org: tenantKey, userId, params: globalParams }, { skip: !hasIdentity || !isGlobalScope });
|
|
236676
236756
|
const { data: adminCategories } = useGetMemoryCategoriesAdminQuery({ org: tenantKey, mentorId: mentorId !== null && mentorId !== void 0 ? mentorId : '' }, { skip: !tenantKey || !hasMentor });
|
|
236757
|
+
const t = useT();
|
|
236758
|
+
// The learner label when a memory names nobody — the same translated word
|
|
236759
|
+
// the other analytics tabs use.
|
|
236760
|
+
const anonymousLabel = t('analyticsAnalyticsMemoryStats.anonymous');
|
|
236677
236761
|
const rows = useMemo(() => {
|
|
236678
236762
|
var _a, _b, _c;
|
|
236679
236763
|
if (isMentorScope)
|
|
236680
|
-
return ((_a = mentorList === null || mentorList === void 0 ? void 0 : mentorList.results) !== null && _a !== void 0 ? _a : []).map(toRowFromMentorMemory);
|
|
236764
|
+
return ((_a = mentorList === null || mentorList === void 0 ? void 0 : mentorList.results) !== null && _a !== void 0 ? _a : []).map((memory) => toRowFromMentorMemory(memory, anonymousLabel));
|
|
236681
236765
|
if (isAllMentorsScope)
|
|
236682
|
-
return ((_b = allMentors === null || allMentors === void 0 ? void 0 : allMentors.results) !== null && _b !== void 0 ? _b : []).map(toRowFromMentorMemory);
|
|
236683
|
-
return ((_c = globalMemories === null || globalMemories === void 0 ? void 0 : globalMemories.results) !== null && _c !== void 0 ? _c : []).map(toRowFromGlobalMemory);
|
|
236684
|
-
}, [isMentorScope, isAllMentorsScope, mentorList, allMentors, globalMemories]);
|
|
236766
|
+
return ((_b = allMentors === null || allMentors === void 0 ? void 0 : allMentors.results) !== null && _b !== void 0 ? _b : []).map((memory) => toRowFromMentorMemory(memory, anonymousLabel));
|
|
236767
|
+
return ((_c = globalMemories === null || globalMemories === void 0 ? void 0 : globalMemories.results) !== null && _c !== void 0 ? _c : []).map((memory) => toRowFromGlobalMemory(memory, anonymousLabel));
|
|
236768
|
+
}, [isMentorScope, isAllMentorsScope, mentorList, allMentors, globalMemories, anonymousLabel]);
|
|
236685
236769
|
const totalCount = useMemo(() => {
|
|
236686
236770
|
var _a, _b, _c;
|
|
236687
236771
|
if (isMentorScope)
|
|
@@ -236704,7 +236788,7 @@ const useMemory = ({ tenantKey, userId, mentorId, myMemory = false, }) => {
|
|
|
236704
236788
|
let totalMemories = 0;
|
|
236705
236789
|
const categories = groups.map((group) => {
|
|
236706
236790
|
group.memories.forEach((memory) => {
|
|
236707
|
-
learners.add(memory
|
|
236791
|
+
learners.add(resolveUserIdentity(memory, { anonymousLabel }).label);
|
|
236708
236792
|
if (memory.is_auto_generated)
|
|
236709
236793
|
autoCaptured += 1;
|
|
236710
236794
|
});
|
|
@@ -236721,7 +236805,7 @@ const useMemory = ({ tenantKey, userId, mentorId, myMemory = false, }) => {
|
|
|
236721
236805
|
learners: learners.size,
|
|
236722
236806
|
categories: categories.sort((a, b) => b.count - a.count),
|
|
236723
236807
|
};
|
|
236724
|
-
}, [isMentorScope, mentorGrouped, categoryFilter]);
|
|
236808
|
+
}, [isMentorScope, mentorGrouped, categoryFilter, anonymousLabel]);
|
|
236725
236809
|
const error = isMentorScope ? mentorListError : isAllMentorsScope ? allMentorsError : globalError;
|
|
236726
236810
|
const isLoading = isMentorScope
|
|
236727
236811
|
? isLoadingMentorList || isLoadingMentorGrouped
|
|
@@ -248212,5 +248296,5 @@ var trainOrDeleteModal = /*#__PURE__*/Object.freeze({
|
|
|
248212
248296
|
TrainOrDeleteModal: TrainOrDeleteModal
|
|
248213
248297
|
});
|
|
248214
248298
|
|
|
248215
|
-
export { ACCESS_COURSE_LABEL, ALL_CATEGORIES, AccessTimeHeatmap, AccessiblePaginate, AddMentorToProjectModal, AddSkillDialog, Admin, AdvancedTab, AgentConfigPrompts, AgentScopeLink, AgentSkills, AlertsTab, AnalyticsAgentPicker, AnalyticsAreaChart, AnalyticsAuditLogStats, AnalyticsBarChart, AnalyticsControlBar, AnalyticsCourseDetail, AnalyticsCourses, AnalyticsFinancialStats, AnalyticsGlobalFiltersProvider, AnalyticsLayout, AnalyticsLlmUsageStats, AnalyticsMemoryStats, AnalyticsMonetizationStats, AnalyticsNotice, AnalyticsOverview, AnalyticsPlatformAuditLog, AnalyticsProgramDetail, AnalyticsPrograms, AnalyticsReportDownload, AnalyticsReports, AnalyticsScopeProvider, AnalyticsSettingsProvider, AnalyticsTopicsStats, AnalyticsTraces, AnalyticsTranscriptsStats, AnalyticsUsersStats, AppleRestrictionModal, ApplyWizard, AuditLogChangesView, AuditLogJsonView, BUY_NOW_LABEL, BillingTab, CATALOGS, CHART_ORDINAL_RAMP, CHART_SERIES_COLORS, CHART_SINGLE_SERIES_COLOR, CREATE_AGENT_LABELS, CUA_DRIVER_REPO_URL, CUA_DRIVER_TAURI_COMMANDS, CUA_DRIVER_TAURI_EVENTS, CardInfoIcon, CategorizedDropdownMenu, ChartCardWrapper, ChartFiltersProvider, ChartLoading, ChartTooltipCard, ChatContext, ChatPrivacyToggle, ChatProvider, CompanyDialog, ConnectorManagementDialog, CopyButtonIcon, CourseAccessGuard, CourseCardSkeleton, CourseContentLoading, CourseOutline, CourseOutlineContext, CourseOutlineDrawer, CreateAgentForm, CreateAgentModal, CreateProjectModal, CreateWorkflowModal, CredentialBox, CredentialMiniBoxSkeleton, CredentialsList, CreditBalance, CustomDateRangePicker, CustomTooltip, DEFAULT_COWORK_REQUIRED_SIZE_GB, DEFAULT_LOCALE, DEFAULT_USER_IDENTITY_ORDER, DefaultEmptyBox, DeleteProjectModal, DeleteWorkflowModal, DiscoverContentCard, DiscoverFacetsFilter, DiscoverFilterDrawer, DocumentSidebar, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENROLL_NOW_COURSE_STARTING_SOON_LABEL, ENROLL_NOW_LABEL, EditAlertDialog, EducationBox, EducationDialog, EducationTab, EdxIframeContext, EmptyStats, ExperienceBox, ExperienceDialog, ExperienceTab, FacetFilterContext, Footer, GradebookTab, GroupsFilterDropdown, INVITATION_ONLY_LABEL, InstitutionDialog, IntegrationsTab, InviteUserContent, InviteUserDialog, InvitedUsersDialog, LOCAL_LLM_CHANGED_EVENT, LOCAL_MODELS, LlmModelBadge, Loader, LocalLLMTab, LocalModelsContent, LoginButton, MACOS_PERMISSIONS_COMMANDS, MEMORY_PAGE_SIZE, Markdown, MemoryAdminTab, MinimumMentorAlert, MonetizationTab, NotificationDisplay, NotificationDropdown, ONBOARDING_FIELD_TYPES, ONBOARDING_SECTORS, OnboardingField, OnboardingShell, OnboardingWizard, PLATFORM_AUDIT_DEEP_PAGING_THRESHOLD, PLATFORM_AUDIT_PAGE_SIZE, PaywallModal, PlacementExam, PlacementExamsDropdown, PlatformAuditLogDetailSheet, PlatformNavbar, PlatformNavbarSearch, Profile, ProfileTimeChart, ProgressDots, ProjectActionButtons, ProjectFilesModal, ProjectInstructionsModal, ProjectLandingPage, ProjectMentorsList, ProjectsPage, REQUEST_ACCESS_COURSE_STARTING_SOON_LABEL, REQUEST_ACCESS_LABEL, RankedBars, RenameProjectModal, ResumeBox, ResumeTab, RetrievedDocumentsButton, RichTextEditor, SERVICE_COLOR_ORDER, SUPPORTED_LOCALES, SandboxConfig, SearchableMultiSelect, SendNotificationDialog, SignupButton, SkeletonActivityStatBox, SkeletonAddSkillsLoading, SkeletonCreatePathwaySearchList, SkeletonDiscoverFilterBox, SkeletonEducationBox, SkeletonMultiplier, SkeletonPathwayBox, SkeletonProfileInfoCard, SkeletonSkillBox, SkillBox, SkillDetailModal, SkillLeaderboardChart, SkillsBox, SkillsList, SlashSkillPicker, SourceChip, Spinner, StatCard, StepHeader, SummerNoteTextEditor, TAURI_COMMANDS, TAURI_EVENTS, TRACES_PAGE_SIZE, TenantSwitcher, TimeFilter, TimeTrackingProvider, TimedExam, ToolCallIndicator, ToolDialogs, TopBanner, TranscriptFileCards, TranscriptRollupBadges, TranscriptTurnDetails, TrendSparkline, USER_ONBOARDING_FORM_SLUG, USER_ONBOARDING_FORM_VERSION, USER_ONBOARDING_SUBMISSION_SLUG, UpgradePackageModal, UserAvatar, UserOnboardingWizard, UserProfileDialog, UserProfileLink, Version, WebContainersI18nProvider, WorkflowSidebar, addBookmarksTab, areChartFiltersEqual, availablePlacementExams, buildOnboardingAgentPath, buildUserOnboardingFormMetadata, buildUserOnboardingSubmissionMetadata, coerceOnboardingAgent, coerceOnboardingAgents, coerceUserOnboardingForm, colorForRank, colorForSeries, conversationDocuments, emptyUserOnboardingForm, findLastResumeBlock, findOnboardingAgent, findSequentialParent, flattenVerticalBlocks, formatAuditTimestamp, formatCompactNumber, formatFileSize, formatLatencySeconds, formatResult, formatTimeZoneLabel, getCatalog, getFirstAvailableUnit, getFriendlyToolName, getLLMModelDisplayName, getLocalLLMModel, getLocalLLMToolSupport, getNextUnitIframe, getOrg, getParentBlockById, getParentsInfosFromSublessonId, getPreviousUnitIframe, getQueryLabel, getRandomCourseImage, getSectorById, getTenant, getUnitToIframe, getUserId, getUserName, granularityForFilter, hasOnboardingContent, humanizeAuditToken, humanizeFieldName, inBrowserPrint, inIframe, inferProviderKeysFromModel, initialCuaDriverInstallState, initialModelDownloadState, isCoworkEnabled, isEmailLike, isFileReference, isLlmUsageForbidden, isLlmUsageUnavailable, isLocalLLMEnabled, isPlatformNavbarCreditBalanceVisible, isSlashCommandToken, isTauriApp, isValidLocale, isValidTimeZone, llmUsageDateArgs, components as markdownComponents, modelSupportsCowork, onboardingPrimaryButtonClass, onboardingSecondaryButtonClass, readUserOnboardingForm, readUserOnboardingSubmission, readUserOnboardingSubmissions, resolveAuditTimeZone, resolveCreateAgentLabels, resolveUserIdentity, sanitizeCss, setCoworkEnabled, setLocalLLMEnabled, setLocalLLMModel, setLocalLLMToolSupport, smallestCoworkModel, summarizeTranscriptTurns, toFileReference, toRetrievedDocuments, toToolCallInfos, useAnalyticsGlobalFilters, useAnalyticsScope, useAnalyticsSettings, useAuditLog, useCatalogSearch, useChartFilters, useChatPrivacy, useChatState, useCourseDetail, useCourseMetadata, useCourses, useCuaDriver, useDiscover, useEdxIframe, useFinancial, useIframeMessageHandler, useLlmDisplayName, useLlmProviderCatalogue, useLlmTraces, useLlmUsage, useLocalStorage, useMemory, useModelDownload, useMonetization, useOverview, usePlatformAuditLabels, usePlatformAuditLog, useProfileActivityStats, useProfileCredentials, useProfilePathways, useProfilePrograms, useProfileSkills, useProfileTimeSpent, usePrograms, useReports, useScopedMentorDbId, useScopedMentorId, useSelectedLocalModel, useSlashSkillPicker, useSlashSkills, useT, useTauri, useTimeTracking, useTopics, useTranscripts, useUserCourses, useUserMetadata, useUsers, useWebContainersI18n, useWebContainersLocale };
|
|
248299
|
+
export { ACCESS_COURSE_LABEL, ALL_CATEGORIES, AccessTimeHeatmap, AccessiblePaginate, AddMentorToProjectModal, AddSkillDialog, Admin, AdvancedTab, AgentConfigPrompts, AgentScopeLink, AgentSkills, AlertsTab, AnalyticsAgentPicker, AnalyticsAreaChart, AnalyticsAuditLogStats, AnalyticsBarChart, AnalyticsControlBar, AnalyticsCourseDetail, AnalyticsCourses, AnalyticsFinancialStats, AnalyticsGlobalFiltersProvider, AnalyticsLayout, AnalyticsLlmUsageStats, AnalyticsMemoryStats, AnalyticsMonetizationStats, AnalyticsNotice, AnalyticsOverview, AnalyticsPlatformAuditLog, AnalyticsProgramDetail, AnalyticsPrograms, AnalyticsReportDownload, AnalyticsReports, AnalyticsScopeProvider, AnalyticsSettingsProvider, AnalyticsTopicsStats, AnalyticsTraces, AnalyticsTranscriptsStats, AnalyticsUsersStats, AppleRestrictionModal, ApplyWizard, AuditLogChangesView, AuditLogJsonView, BUY_NOW_LABEL, BillingTab, CATALOGS, CHART_ORDINAL_RAMP, CHART_SERIES_COLORS, CHART_SINGLE_SERIES_COLOR, CREATE_AGENT_LABELS, CUA_DRIVER_REPO_URL, CUA_DRIVER_TAURI_COMMANDS, CUA_DRIVER_TAURI_EVENTS, CardInfoIcon, CategorizedDropdownMenu, ChartCardWrapper, ChartFiltersProvider, ChartLoading, ChartTooltipCard, ChatContext, ChatPrivacyToggle, ChatProvider, CompanyDialog, ConnectorManagementDialog, CopyButtonIcon, CourseAccessGuard, CourseCardSkeleton, CourseContentLoading, CourseOutline, CourseOutlineContext, CourseOutlineDrawer, CreateAgentForm, CreateAgentModal, CreateProjectModal, CreateWorkflowModal, CredentialBox, CredentialMiniBoxSkeleton, CredentialsList, CreditBalance, CustomDateRangePicker, CustomTooltip, DEFAULT_COWORK_REQUIRED_SIZE_GB, DEFAULT_LOCALE, DEFAULT_USER_IDENTITY_ORDER, DefaultEmptyBox, DeleteProjectModal, DeleteWorkflowModal, DiscoverContentCard, DiscoverFacetsFilter, DiscoverFilterDrawer, DocumentSidebar, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, ENROLL_NOW_COURSE_STARTING_SOON_LABEL, ENROLL_NOW_LABEL, EditAlertDialog, EducationBox, EducationDialog, EducationTab, EdxIframeContext, EmptyStats, ExperienceBox, ExperienceDialog, ExperienceTab, FacetFilterContext, Footer, GradebookTab, GroupsFilterDropdown, INVITATION_ONLY_LABEL, InstitutionDialog, IntegrationsTab, InviteUserContent, InviteUserDialog, InvitedUsersDialog, LOCAL_LLM_CHANGED_EVENT, LOCAL_MODELS, LlmModelBadge, Loader, LocalLLMTab, LocalModelsContent, LoginButton, MACOS_PERMISSIONS_COMMANDS, MEMORY_PAGE_SIZE, Markdown, MemoryAdminTab, MinimumMentorAlert, MonetizationTab, NotificationDisplay, NotificationDropdown, ONBOARDING_FIELD_TYPES, ONBOARDING_SECTORS, OnboardingField, OnboardingShell, OnboardingWizard, PLATFORM_AUDIT_DEEP_PAGING_THRESHOLD, PLATFORM_AUDIT_PAGE_SIZE, PaywallModal, PlacementExam, PlacementExamsDropdown, PlatformAuditLogDetailSheet, PlatformNavbar, PlatformNavbarSearch, Profile, ProfileTimeChart, ProgressDots, ProjectActionButtons, ProjectFilesModal, ProjectInstructionsModal, ProjectLandingPage, ProjectMentorsList, ProjectsPage, REQUEST_ACCESS_COURSE_STARTING_SOON_LABEL, REQUEST_ACCESS_LABEL, RankedBars, RenameProjectModal, ResumeBox, ResumeTab, RetrievedDocumentsButton, RichTextEditor, SERVICE_COLOR_ORDER, SUPPORTED_LOCALES, SandboxConfig, SearchableMultiSelect, SendNotificationDialog, SignupButton, SkeletonActivityStatBox, SkeletonAddSkillsLoading, SkeletonCreatePathwaySearchList, SkeletonDiscoverFilterBox, SkeletonEducationBox, SkeletonMultiplier, SkeletonPathwayBox, SkeletonProfileInfoCard, SkeletonSkillBox, SkillBox, SkillDetailModal, SkillLeaderboardChart, SkillsBox, SkillsList, SlashSkillPicker, SourceChip, Spinner, StatCard, StepHeader, SummerNoteTextEditor, TAURI_COMMANDS, TAURI_EVENTS, TRACES_PAGE_SIZE, TenantSwitcher, TimeFilter, TimeTrackingProvider, TimedExam, ToolCallIndicator, ToolDialogs, TopBanner, TranscriptFileCards, TranscriptRollupBadges, TranscriptTurnDetails, TrendSparkline, USER_ONBOARDING_FORM_SLUG, USER_ONBOARDING_FORM_VERSION, USER_ONBOARDING_SUBMISSION_SLUG, UpgradePackageModal, UserAvatar, UserOnboardingWizard, UserProfileDialog, UserProfileLink, Version, WebContainersI18nProvider, WorkflowSidebar, addBookmarksTab, areChartFiltersEqual, availablePlacementExams, buildOnboardingAgentPath, buildUserOnboardingFormMetadata, buildUserOnboardingSubmissionMetadata, coerceOnboardingAgent, coerceOnboardingAgents, coerceUserOnboardingForm, colorForRank, colorForSeries, conversationDocuments, emptyUserOnboardingForm, findLastResumeBlock, findOnboardingAgent, findSequentialParent, flattenVerticalBlocks, formatAuditTimestamp, formatCompactNumber, formatFileSize, formatLatencySeconds, formatResult, formatTimeZoneLabel, getCatalog, getFirstAvailableUnit, getFriendlyToolName, getLLMModelDisplayName, getLocalLLMModel, getLocalLLMToolSupport, getNextUnitIframe, getOrg, getParentBlockById, getParentsInfosFromSublessonId, getPreviousUnitIframe, getQueryLabel, getRandomCourseImage, getSectorById, getTenant, getUnitToIframe, getUserId, getUserName, granularityForFilter, hasDistinctName, hasOnboardingContent, humanizeAuditToken, humanizeFieldName, inBrowserPrint, inIframe, inferProviderKeysFromModel, initialCuaDriverInstallState, initialModelDownloadState, isCoworkEnabled, isEmailLike, isFileReference, isLlmUsageForbidden, isLlmUsageUnavailable, isLocalLLMEnabled, isPlatformNavbarCreditBalanceVisible, isSlashCommandToken, isTauriApp, isValidLocale, isValidTimeZone, llmUsageDateArgs, components as markdownComponents, modelSupportsCowork, onboardingPrimaryButtonClass, onboardingSecondaryButtonClass, readUserOnboardingForm, readUserOnboardingSubmission, readUserOnboardingSubmissions, resolveAuditTimeZone, resolveCreateAgentLabels, resolveUserIdentity, sanitizeCss, setCoworkEnabled, setLocalLLMEnabled, setLocalLLMModel, setLocalLLMToolSupport, smallestCoworkModel, summarizeTranscriptTurns, toFileReference, toRetrievedDocuments, toToolCallInfos, useAnalyticsGlobalFilters, useAnalyticsScope, useAnalyticsSettings, useAuditLog, useCatalogSearch, useChartFilters, useChatPrivacy, useChatState, useCourseDetail, useCourseMetadata, useCourses, useCuaDriver, useDiscover, useEdxIframe, useFinancial, useIframeMessageHandler, useLlmDisplayName, useLlmProviderCatalogue, useLlmTraces, useLlmUsage, useLocalStorage, useMemory, useModelDownload, useMonetization, useOverview, usePlatformAuditLabels, usePlatformAuditLog, useProfileActivityStats, useProfileCredentials, useProfilePathways, useProfilePrograms, useProfileSkills, useProfileTimeSpent, usePrograms, useReports, useScopedMentorDbId, useScopedMentorId, useSelectedLocalModel, useSlashSkillPicker, useSlashSkills, useT, useTauri, useTimeTracking, useTopics, useTranscripts, useUserCourses, useUserMetadata, useUsers, useWebContainersI18n, useWebContainersLocale };
|
|
248216
248300
|
//# sourceMappingURL=index.esm.js.map
|