@iota-uz/sdk 0.4.23 → 0.4.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/applet/host.cjs +97 -10
- package/dist/applet/host.cjs.map +1 -1
- package/dist/applet/host.d.cts +9 -1
- package/dist/applet/host.d.ts +9 -1
- package/dist/applet/host.mjs +97 -10
- package/dist/applet/host.mjs.map +1 -1
- package/dist/bichat/index.cjs +1288 -330
- package/dist/bichat/index.cjs.map +1 -1
- package/dist/bichat/index.d.cts +1056 -784
- package/dist/bichat/index.d.ts +1056 -784
- package/dist/bichat/index.mjs +1287 -333
- package/dist/bichat/index.mjs.map +1 -1
- package/dist/index.cjs +97 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +97 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/tailwind/compiled.css +1 -1
package/dist/bichat/index.cjs
CHANGED
|
@@ -3303,12 +3303,151 @@ function useBranding() {
|
|
|
3303
3303
|
}, [context.extensions?.branding, t]);
|
|
3304
3304
|
return branding;
|
|
3305
3305
|
}
|
|
3306
|
-
function
|
|
3306
|
+
function hashString(str) {
|
|
3307
|
+
let hash = 0;
|
|
3308
|
+
for (let i = 0; i < str.length; i++) {
|
|
3309
|
+
const char = str.charCodeAt(i);
|
|
3310
|
+
hash = (hash << 5) - hash + char;
|
|
3311
|
+
hash = hash & hash;
|
|
3312
|
+
}
|
|
3313
|
+
return Math.abs(hash);
|
|
3314
|
+
}
|
|
3315
|
+
var colorPalette = [
|
|
3316
|
+
{ bg: "bg-blue-500", text: "text-white" },
|
|
3317
|
+
{ bg: "bg-green-500", text: "text-white" },
|
|
3318
|
+
{ bg: "bg-purple-500", text: "text-white" },
|
|
3319
|
+
{ bg: "bg-pink-500", text: "text-white" },
|
|
3320
|
+
{ bg: "bg-indigo-500", text: "text-white" },
|
|
3321
|
+
{ bg: "bg-teal-500", text: "text-white" },
|
|
3322
|
+
{ bg: "bg-orange-500", text: "text-white" },
|
|
3323
|
+
{ bg: "bg-cyan-500", text: "text-white" },
|
|
3324
|
+
{ bg: "bg-amber-500", text: "text-white" },
|
|
3325
|
+
{ bg: "bg-lime-500", text: "text-white" }
|
|
3326
|
+
];
|
|
3327
|
+
var sizeClasses = {
|
|
3328
|
+
xs: "w-6 h-6 text-[10px]",
|
|
3329
|
+
sm: "w-8 h-8 text-xs",
|
|
3330
|
+
md: "w-10 h-10 text-sm",
|
|
3331
|
+
lg: "w-12 h-12 text-base"
|
|
3332
|
+
};
|
|
3333
|
+
function UserAvatar({
|
|
3334
|
+
firstName,
|
|
3335
|
+
lastName,
|
|
3336
|
+
initials: providedInitials,
|
|
3337
|
+
size = "md",
|
|
3338
|
+
className = ""
|
|
3339
|
+
}) {
|
|
3340
|
+
const derivedInitials = (() => {
|
|
3341
|
+
const firstChar = firstName?.trim()?.charAt(0) || "";
|
|
3342
|
+
const lastChar = lastName?.trim()?.charAt(0) || "";
|
|
3343
|
+
const combined = `${firstChar}${lastChar}`.trim();
|
|
3344
|
+
return combined || "U";
|
|
3345
|
+
})();
|
|
3346
|
+
const initials = (providedInitials?.trim() || derivedInitials).toUpperCase();
|
|
3347
|
+
const fullName = `${firstName}${lastName}`;
|
|
3348
|
+
const colorIndex = hashString(fullName) % colorPalette.length;
|
|
3349
|
+
const colors = colorPalette[colorIndex];
|
|
3350
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3351
|
+
"div",
|
|
3352
|
+
{
|
|
3353
|
+
className: `
|
|
3354
|
+
${sizeClasses[size]}
|
|
3355
|
+
${colors.bg}
|
|
3356
|
+
${colors.text}
|
|
3357
|
+
${className}
|
|
3358
|
+
rounded-full
|
|
3359
|
+
flex
|
|
3360
|
+
items-center
|
|
3361
|
+
justify-center
|
|
3362
|
+
font-semibold
|
|
3363
|
+
flex-shrink-0
|
|
3364
|
+
select-none
|
|
3365
|
+
`,
|
|
3366
|
+
"aria-label": `${firstName} ${lastName}`,
|
|
3367
|
+
title: `${firstName} ${lastName}`,
|
|
3368
|
+
children: initials
|
|
3369
|
+
}
|
|
3370
|
+
);
|
|
3371
|
+
}
|
|
3372
|
+
var MemoizedUserAvatar = React.memo(UserAvatar);
|
|
3373
|
+
MemoizedUserAvatar.displayName = "UserAvatar";
|
|
3374
|
+
var overlapClasses = {
|
|
3375
|
+
xs: "-ml-1.5",
|
|
3376
|
+
sm: "-ml-2"
|
|
3377
|
+
};
|
|
3378
|
+
var badgeSizeClasses = {
|
|
3379
|
+
xs: "w-6 h-6 text-[10px]",
|
|
3380
|
+
sm: "w-8 h-8 text-xs"
|
|
3381
|
+
};
|
|
3382
|
+
function AvatarStackInner({
|
|
3383
|
+
users,
|
|
3384
|
+
max = 3,
|
|
3385
|
+
size = "sm",
|
|
3386
|
+
onClick,
|
|
3387
|
+
className = ""
|
|
3388
|
+
}) {
|
|
3389
|
+
const visible = users.slice(0, max);
|
|
3390
|
+
const overflow = users.length - max;
|
|
3391
|
+
const interactive = typeof onClick === "function";
|
|
3392
|
+
const overlap = overlapClasses[size];
|
|
3393
|
+
const badgeSize = badgeSizeClasses[size];
|
|
3394
|
+
const handleKeyDown = (e) => {
|
|
3395
|
+
if (interactive && (e.key === "Enter" || e.key === " ")) {
|
|
3396
|
+
e.preventDefault();
|
|
3397
|
+
onClick();
|
|
3398
|
+
}
|
|
3399
|
+
};
|
|
3400
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3401
|
+
"div",
|
|
3402
|
+
{
|
|
3403
|
+
className: `inline-flex items-center ${interactive ? "cursor-pointer transition-opacity hover:opacity-80" : ""} ${className}`,
|
|
3404
|
+
onClick: interactive ? onClick : void 0,
|
|
3405
|
+
onKeyDown: interactive ? handleKeyDown : void 0,
|
|
3406
|
+
role: interactive ? "button" : void 0,
|
|
3407
|
+
tabIndex: interactive ? 0 : void 0,
|
|
3408
|
+
"aria-label": interactive ? `${users.length} members` : void 0,
|
|
3409
|
+
children: [
|
|
3410
|
+
visible.map((user, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3411
|
+
"div",
|
|
3412
|
+
{
|
|
3413
|
+
className: `${i > 0 ? overlap : ""} ring-2 ring-white dark:ring-gray-900 rounded-full`,
|
|
3414
|
+
style: { zIndex: visible.length - i },
|
|
3415
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3416
|
+
MemoizedUserAvatar,
|
|
3417
|
+
{
|
|
3418
|
+
firstName: user.firstName,
|
|
3419
|
+
lastName: user.lastName,
|
|
3420
|
+
initials: user.initials,
|
|
3421
|
+
size
|
|
3422
|
+
}
|
|
3423
|
+
)
|
|
3424
|
+
},
|
|
3425
|
+
`${user.firstName}-${user.lastName}-${i}`
|
|
3426
|
+
)),
|
|
3427
|
+
overflow > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3428
|
+
"div",
|
|
3429
|
+
{
|
|
3430
|
+
className: `${overlap} ${badgeSize} rounded-full bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-300 font-medium flex items-center justify-center flex-shrink-0 ring-2 ring-white dark:ring-gray-900`,
|
|
3431
|
+
style: { zIndex: 0 },
|
|
3432
|
+
children: [
|
|
3433
|
+
"+",
|
|
3434
|
+
overflow
|
|
3435
|
+
]
|
|
3436
|
+
}
|
|
3437
|
+
)
|
|
3438
|
+
]
|
|
3439
|
+
}
|
|
3440
|
+
);
|
|
3441
|
+
}
|
|
3442
|
+
var AvatarStack = React.memo(AvatarStackInner);
|
|
3443
|
+
AvatarStack.displayName = "AvatarStack";
|
|
3444
|
+
function ChatHeader({ session, onBack, readOnly, logoSlot, actionsSlot, members, onMembersClick }) {
|
|
3307
3445
|
const { t } = useTranslation();
|
|
3308
3446
|
const branding = useBranding();
|
|
3309
3447
|
const BackButton = onBack ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3310
3448
|
"button",
|
|
3311
3449
|
{
|
|
3450
|
+
type: "button",
|
|
3312
3451
|
onClick: onBack,
|
|
3313
3452
|
className: "cursor-pointer p-2 hover:bg-gray-100 dark:hover:bg-gray-700 active:bg-gray-200 dark:active:bg-gray-600 rounded-lg transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
|
|
3314
3453
|
"aria-label": t("BiChat.Chat.GoBack"),
|
|
@@ -3327,23 +3466,42 @@ function ChatHeader({ session, onBack, readOnly, logoSlot, actionsSlot }) {
|
|
|
3327
3466
|
] }) });
|
|
3328
3467
|
}
|
|
3329
3468
|
const resolvedSessionTitle = session.title?.trim() || t("BiChat.Chat.NewChat");
|
|
3469
|
+
const isGroupSession = Boolean(session.isGroup || session.memberCount && session.memberCount > 1);
|
|
3470
|
+
const memberCount = session.memberCount ?? 0;
|
|
3471
|
+
const stackUsers = members && members.length > 0 ? members : [];
|
|
3330
3472
|
return /* @__PURE__ */ jsxRuntime.jsx("header", { className: "bichat-header border-b border-gray-200 dark:border-gray-700 px-4 py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
3331
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
3473
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
3332
3474
|
BackButton,
|
|
3333
3475
|
Logo,
|
|
3334
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3476
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
3477
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
3478
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg font-semibold text-[var(--bichat-text)] truncate", children: resolvedSessionTitle }),
|
|
3479
|
+
session.pinned && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3480
|
+
"svg",
|
|
3481
|
+
{
|
|
3482
|
+
className: "w-4 h-4 text-[var(--bichat-primary)] flex-shrink-0",
|
|
3483
|
+
fill: "currentColor",
|
|
3484
|
+
viewBox: "0 0 20 20",
|
|
3485
|
+
role: "img",
|
|
3486
|
+
"aria-label": t("BiChat.Chat.Pinned"),
|
|
3487
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 2a1 1 0 011 1v1.323l3.954 1.582 1.599-.8a1 1 0 01.894 1.79l-1.233.616 1.738 5.42a1 1 0 01-.285 1.05A3.989 3.989 0 0115 15a3.989 3.989 0 01-2.667-1.019 1 1 0 01-.285-1.05l1.715-5.349L11 6.477V16h2a1 1 0 110 2H7a1 1 0 110-2h2V6.477L6.237 7.582l1.715 5.349a1 1 0 01-.285 1.05A3.989 3.989 0 015 15a3.989 3.989 0 01-2.667-1.019 1 1 0 01-.285-1.05l1.738-5.42-1.233-.617a1 1 0 01.894-1.788l1.599.799L9 4.323V3a1 1 0 011-1z" })
|
|
3488
|
+
}
|
|
3489
|
+
),
|
|
3490
|
+
isGroupSession && stackUsers.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3491
|
+
AvatarStack,
|
|
3492
|
+
{
|
|
3493
|
+
users: stackUsers,
|
|
3494
|
+
max: 3,
|
|
3495
|
+
size: "xs",
|
|
3496
|
+
onClick: onMembersClick,
|
|
3497
|
+
className: "flex-shrink-0"
|
|
3498
|
+
}
|
|
3499
|
+
)
|
|
3500
|
+
] }),
|
|
3501
|
+
isGroupSession && memberCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400 mt-0.5", children: memberCount === 1 ? t("BiChat.Chat.OneMember") : t("BiChat.Chat.MemberCount").replace("{{count}}", String(memberCount)) })
|
|
3502
|
+
] })
|
|
3345
3503
|
] }),
|
|
3346
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3504
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
|
|
3347
3505
|
readOnly && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 py-1 text-xs bg-amber-100 dark:bg-amber-900/30 text-amber-800 dark:text-amber-200 rounded", children: t("BiChat.Chat.ReadOnly") }),
|
|
3348
3506
|
session.status === "archived" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-2 py-1 text-xs bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded", children: t("BiChat.Chat.Archived") }),
|
|
3349
3507
|
actionsSlot
|
|
@@ -4218,6 +4376,7 @@ function UserMessage({
|
|
|
4218
4376
|
turn,
|
|
4219
4377
|
turnId,
|
|
4220
4378
|
initials = "U",
|
|
4379
|
+
authorName,
|
|
4221
4380
|
slots,
|
|
4222
4381
|
classNames: classNameOverrides,
|
|
4223
4382
|
onCopy,
|
|
@@ -4425,6 +4584,16 @@ function UserMessage({
|
|
|
4425
4584
|
};
|
|
4426
4585
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.root, children: [
|
|
4427
4586
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.wrapper, children: [
|
|
4587
|
+
authorName && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4588
|
+
"span",
|
|
4589
|
+
{
|
|
4590
|
+
id: `${turn.id}-author`,
|
|
4591
|
+
role: "note",
|
|
4592
|
+
"aria-label": authorName,
|
|
4593
|
+
className: "mb-1 px-1 text-[11px] text-right text-gray-500 dark:text-gray-400",
|
|
4594
|
+
children: authorName
|
|
4595
|
+
}
|
|
4596
|
+
),
|
|
4428
4597
|
normalizedAttachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.attachments, children: renderSlot(
|
|
4429
4598
|
slots?.attachments,
|
|
4430
4599
|
attachmentsSlotProps,
|
|
@@ -4436,20 +4605,28 @@ function UserMessage({
|
|
|
4436
4605
|
}
|
|
4437
4606
|
)
|
|
4438
4607
|
) }),
|
|
4439
|
-
turn.content && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4440
|
-
|
|
4608
|
+
turn.content && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4609
|
+
"div",
|
|
4441
4610
|
{
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4611
|
+
ref: bubbleRef,
|
|
4612
|
+
className: classes.bubble,
|
|
4613
|
+
"aria-describedby": authorName ? `${turn.id}-author` : void 0,
|
|
4614
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.content, children: isEditing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4615
|
+
EditForm,
|
|
4616
|
+
{
|
|
4617
|
+
draftContent,
|
|
4618
|
+
onDraftChange: handleDraftChange,
|
|
4619
|
+
onSave: handleEditSave,
|
|
4620
|
+
onCancel: handleEditCancel,
|
|
4621
|
+
onKeyDown: handleEditKeyDown,
|
|
4622
|
+
textareaRef: editTextareaRef,
|
|
4623
|
+
disabled: false,
|
|
4624
|
+
originalContent: turn.content,
|
|
4625
|
+
t
|
|
4626
|
+
}
|
|
4627
|
+
) : renderSlot(slots?.content, contentSlotProps, turn.content) })
|
|
4451
4628
|
}
|
|
4452
|
-
)
|
|
4629
|
+
),
|
|
4453
4630
|
!hideActions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${classes.actions} ${isCopied ? "opacity-100" : ""}`, children: renderSlot(
|
|
4454
4631
|
slots?.actions,
|
|
4455
4632
|
actionsSlotProps,
|
|
@@ -4498,19 +4675,25 @@ function UserTurnView({
|
|
|
4498
4675
|
turn,
|
|
4499
4676
|
slots,
|
|
4500
4677
|
classNames,
|
|
4501
|
-
initials
|
|
4678
|
+
initials,
|
|
4502
4679
|
hideAvatar,
|
|
4503
4680
|
hideActions,
|
|
4504
4681
|
hideTimestamp,
|
|
4505
|
-
allowEdit
|
|
4682
|
+
allowEdit,
|
|
4683
|
+
showAuthorName = false
|
|
4506
4684
|
}) {
|
|
4507
4685
|
const { handleEdit, handleCopy } = useChatMessaging();
|
|
4686
|
+
const author = turn.userTurn.author;
|
|
4687
|
+
const fullName = [author?.firstName || "", author?.lastName || ""].join(" ").trim();
|
|
4688
|
+
const authorName = showAuthorName && fullName.length > 0 ? fullName : void 0;
|
|
4689
|
+
const resolvedInitials = initials ?? author?.initials ?? "U";
|
|
4508
4690
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4509
4691
|
UserMessage,
|
|
4510
4692
|
{
|
|
4511
4693
|
turn: turn.userTurn,
|
|
4512
4694
|
turnId: turn.id,
|
|
4513
|
-
initials,
|
|
4695
|
+
initials: resolvedInitials,
|
|
4696
|
+
authorName,
|
|
4514
4697
|
slots,
|
|
4515
4698
|
classNames,
|
|
4516
4699
|
onCopy: handleCopy,
|
|
@@ -8505,7 +8688,7 @@ function StreamingBubble({ content, normalizedContent }) {
|
|
|
8505
8688
|
}
|
|
8506
8689
|
function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readOnly }) {
|
|
8507
8690
|
const { t } = useTranslation();
|
|
8508
|
-
const { currentSessionId, fetching } = useChatSession();
|
|
8691
|
+
const { session, currentSessionId, fetching } = useChatSession();
|
|
8509
8692
|
const {
|
|
8510
8693
|
turns,
|
|
8511
8694
|
streamingContent,
|
|
@@ -8520,6 +8703,7 @@ function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readO
|
|
|
8520
8703
|
() => streamingContent ? normalizeStreamingMarkdown(streamingContent) : "",
|
|
8521
8704
|
[streamingContent]
|
|
8522
8705
|
);
|
|
8706
|
+
const showAuthorNames = Boolean(session?.isGroup);
|
|
8523
8707
|
const showEphemeral = showActivityTrace || showTypingIndicator;
|
|
8524
8708
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1 min-h-0", children: [
|
|
8525
8709
|
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "h-full overflow-y-auto overflow-x-hidden px-4 py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto space-y-6", children: [
|
|
@@ -8529,6 +8713,10 @@ function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readO
|
|
|
8529
8713
|
const prevDate = index > 0 ? new Date(turns[index - 1].createdAt) : null;
|
|
8530
8714
|
const showDateSeparator = !!prevDate && !dateFns.isSameDay(turnDate, prevDate);
|
|
8531
8715
|
const isLast = index === turns.length - 1;
|
|
8716
|
+
const userTurnProps = {
|
|
8717
|
+
allowEdit: readOnly ? false : isLast,
|
|
8718
|
+
showAuthorName: showAuthorNames
|
|
8719
|
+
};
|
|
8532
8720
|
return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
|
|
8533
8721
|
showDateSeparator && /* @__PURE__ */ jsxRuntime.jsx(DateSeparator, { date: turnDate }),
|
|
8534
8722
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -8538,7 +8726,7 @@ function MessageList({ renderUserTurn, renderAssistantTurn, thinkingVerbs, readO
|
|
|
8538
8726
|
isLastTurn: isLast,
|
|
8539
8727
|
renderUserTurn,
|
|
8540
8728
|
renderAssistantTurn,
|
|
8541
|
-
userTurnProps
|
|
8729
|
+
userTurnProps,
|
|
8542
8730
|
assistantTurnProps: readOnly ? { allowRegenerate: false } : void 0
|
|
8543
8731
|
}
|
|
8544
8732
|
)
|
|
@@ -10744,71 +10932,689 @@ function SessionArtifactsPanel({
|
|
|
10744
10932
|
}
|
|
10745
10933
|
);
|
|
10746
10934
|
}
|
|
10935
|
+
var DialogContext = React.createContext(null);
|
|
10936
|
+
var FOCUSABLE_SELECTOR = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
10937
|
+
function InlineDialog({ open, onClose, className, children }) {
|
|
10938
|
+
const containerRef = React.useRef(null);
|
|
10939
|
+
const previousFocusRef = React.useRef(null);
|
|
10940
|
+
React.useEffect(() => {
|
|
10941
|
+
if (!open) {
|
|
10942
|
+
return;
|
|
10943
|
+
}
|
|
10944
|
+
previousFocusRef.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
10945
|
+
const container = containerRef.current;
|
|
10946
|
+
if (!container) {
|
|
10947
|
+
return;
|
|
10948
|
+
}
|
|
10949
|
+
const getFocusable = () => Array.from(
|
|
10950
|
+
container.querySelectorAll(FOCUSABLE_SELECTOR)
|
|
10951
|
+
);
|
|
10952
|
+
const handler = (e) => {
|
|
10953
|
+
if (e.key === "Escape") {
|
|
10954
|
+
onClose();
|
|
10955
|
+
return;
|
|
10956
|
+
}
|
|
10957
|
+
if (e.key !== "Tab") {
|
|
10958
|
+
return;
|
|
10959
|
+
}
|
|
10960
|
+
const focusable = getFocusable();
|
|
10961
|
+
if (focusable.length === 0) {
|
|
10962
|
+
e.preventDefault();
|
|
10963
|
+
container.focus();
|
|
10964
|
+
return;
|
|
10965
|
+
}
|
|
10966
|
+
const first = focusable[0];
|
|
10967
|
+
const last = focusable[focusable.length - 1];
|
|
10968
|
+
if (e.shiftKey && document.activeElement === first) {
|
|
10969
|
+
e.preventDefault();
|
|
10970
|
+
last.focus();
|
|
10971
|
+
} else if (!e.shiftKey && document.activeElement === last) {
|
|
10972
|
+
e.preventDefault();
|
|
10973
|
+
first.focus();
|
|
10974
|
+
}
|
|
10975
|
+
};
|
|
10976
|
+
(getFocusable()[0] ?? container)?.focus();
|
|
10977
|
+
container.addEventListener("keydown", handler);
|
|
10978
|
+
return () => {
|
|
10979
|
+
container.removeEventListener("keydown", handler);
|
|
10980
|
+
previousFocusRef.current?.focus();
|
|
10981
|
+
};
|
|
10982
|
+
}, [open, onClose]);
|
|
10983
|
+
if (!open) {
|
|
10984
|
+
return null;
|
|
10985
|
+
}
|
|
10986
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DialogContext.Provider, { value: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10987
|
+
"div",
|
|
10988
|
+
{
|
|
10989
|
+
ref: containerRef,
|
|
10990
|
+
className,
|
|
10991
|
+
onClick: onClose,
|
|
10992
|
+
tabIndex: -1,
|
|
10993
|
+
children
|
|
10994
|
+
}
|
|
10995
|
+
) });
|
|
10996
|
+
}
|
|
10997
|
+
function InlineDialogBackdrop(props) {
|
|
10998
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", ...props });
|
|
10999
|
+
}
|
|
11000
|
+
function InlineDialogPanel({
|
|
11001
|
+
children,
|
|
11002
|
+
onClick,
|
|
11003
|
+
...rest
|
|
11004
|
+
}) {
|
|
11005
|
+
const ref = React.useRef(null);
|
|
11006
|
+
React.useEffect(() => {
|
|
11007
|
+
if (!ref.current) {
|
|
11008
|
+
return;
|
|
11009
|
+
}
|
|
11010
|
+
const target = ref.current.querySelector("[data-autofocus]") ?? ref.current.querySelector(
|
|
11011
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
11012
|
+
);
|
|
11013
|
+
target?.focus();
|
|
11014
|
+
}, []);
|
|
11015
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11016
|
+
"div",
|
|
11017
|
+
{
|
|
11018
|
+
ref,
|
|
11019
|
+
role: "dialog",
|
|
11020
|
+
"aria-modal": "true",
|
|
11021
|
+
onClick: (e) => {
|
|
11022
|
+
e.stopPropagation();
|
|
11023
|
+
onClick?.(e);
|
|
11024
|
+
},
|
|
11025
|
+
...rest,
|
|
11026
|
+
children
|
|
11027
|
+
}
|
|
11028
|
+
);
|
|
11029
|
+
}
|
|
11030
|
+
function InlineDialogTitle(props) {
|
|
11031
|
+
return /* @__PURE__ */ jsxRuntime.jsx("h2", { ...props });
|
|
11032
|
+
}
|
|
11033
|
+
function InlineDialogDescription(props) {
|
|
11034
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { ...props });
|
|
11035
|
+
}
|
|
10747
11036
|
|
|
10748
|
-
// ui/src/bichat/components/
|
|
11037
|
+
// ui/src/bichat/components/SessionMembersModal.tsx
|
|
10749
11038
|
init_useTranslation();
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
11039
|
+
init_useTranslation();
|
|
11040
|
+
function ConfirmModalBase({
|
|
11041
|
+
isOpen,
|
|
11042
|
+
title,
|
|
11043
|
+
message,
|
|
11044
|
+
onConfirm,
|
|
11045
|
+
onCancel,
|
|
11046
|
+
confirmText,
|
|
11047
|
+
cancelText,
|
|
11048
|
+
isDanger = false
|
|
10756
11049
|
}) {
|
|
10757
11050
|
const { t } = useTranslation();
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
role: "alert",
|
|
10766
|
-
children: [
|
|
10767
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 mt-0.5 flex items-center justify-center w-7 h-7 rounded-full bg-red-100 dark:bg-red-900/40", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
10768
|
-
react.Warning,
|
|
10769
|
-
{
|
|
10770
|
-
className: "w-4 h-4 text-red-600 dark:text-red-400",
|
|
10771
|
-
weight: "fill"
|
|
10772
|
-
}
|
|
10773
|
-
) }),
|
|
11051
|
+
const resolvedConfirmText = confirmText?.trim() ? confirmText : t("BiChat.Common.Confirm");
|
|
11052
|
+
const resolvedCancelText = cancelText?.trim() ? cancelText : t("BiChat.Common.Cancel");
|
|
11053
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(InlineDialog, { open: isOpen, onClose: onCancel, className: "relative z-40", children: [
|
|
11054
|
+
/* @__PURE__ */ jsxRuntime.jsx(InlineDialogBackdrop, { className: "fixed inset-0 bg-black/40 dark:bg-black/60 backdrop-blur-sm transition-opacity duration-200" }),
|
|
11055
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(InlineDialogPanel, { className: "bg-white dark:bg-gray-800 rounded-2xl shadow-xl dark:shadow-2xl dark:shadow-black/30 max-w-sm w-full overflow-hidden", children: [
|
|
11056
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 pt-6 pb-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-4", children: [
|
|
11057
|
+
isDanger && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 flex items-center justify-center w-10 h-10 rounded-xl bg-red-50 dark:bg-red-950/40 border border-red-200/60 dark:border-red-800/40", children: /* @__PURE__ */ jsxRuntime.jsx(react.WarningCircle, { size: 22, weight: "duotone", className: "text-red-600 dark:text-red-400" }) }),
|
|
10774
11058
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
10775
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10776
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
onClick: onRetry,
|
|
10782
|
-
className: "cursor-pointer inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-white bg-red-600 hover:bg-red-700 active:bg-red-800 dark:bg-red-700 dark:hover:bg-red-600 rounded-lg transition-colors shadow-sm",
|
|
10783
|
-
type: "button",
|
|
10784
|
-
children: [
|
|
10785
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.ArrowClockwise, { className: "w-3.5 h-3.5" }),
|
|
10786
|
-
t("BiChat.StreamError.Retry")
|
|
10787
|
-
]
|
|
10788
|
-
}
|
|
10789
|
-
),
|
|
10790
|
-
onRegenerate && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10791
|
-
"button",
|
|
10792
|
-
{
|
|
10793
|
-
onClick: onRegenerate,
|
|
10794
|
-
className: "cursor-pointer inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-lg transition-colors shadow-sm",
|
|
10795
|
-
type: "button",
|
|
10796
|
-
children: [
|
|
10797
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.ArrowsCounterClockwise, { className: "w-3.5 h-3.5" }),
|
|
10798
|
-
t("BiChat.StreamError.Regenerate")
|
|
10799
|
-
]
|
|
10800
|
-
}
|
|
10801
|
-
)
|
|
10802
|
-
] })
|
|
10803
|
-
] }),
|
|
10804
|
-
onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11059
|
+
/* @__PURE__ */ jsxRuntime.jsx(InlineDialogTitle, { className: "text-base font-semibold text-gray-900 dark:text-gray-100 leading-snug", children: title }),
|
|
11060
|
+
/* @__PURE__ */ jsxRuntime.jsx(InlineDialogDescription, { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 leading-relaxed", children: message })
|
|
11061
|
+
] })
|
|
11062
|
+
] }) }),
|
|
11063
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-2.5 px-6 pb-5", children: [
|
|
11064
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10805
11065
|
"button",
|
|
10806
11066
|
{
|
|
10807
|
-
onClick: onDismiss,
|
|
10808
|
-
className: "cursor-pointer flex-shrink-0 mt-0.5 inline-flex items-center justify-center w-6 h-6 text-red-400 dark:text-red-500 hover:text-red-600 dark:hover:text-red-300 hover:bg-red-100 dark:hover:bg-red-900/40 rounded-md transition-colors",
|
|
10809
11067
|
type: "button",
|
|
10810
|
-
|
|
10811
|
-
|
|
11068
|
+
onClick: onCancel,
|
|
11069
|
+
...isDanger ? { "data-autofocus": true } : {},
|
|
11070
|
+
className: "cursor-pointer px-4 py-2 text-sm font-medium rounded-xl text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700/60 hover:bg-gray-200 dark:hover:bg-gray-700 active:bg-gray-250 dark:active:bg-gray-600 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
11071
|
+
"data-testid": "confirm-modal-cancel",
|
|
11072
|
+
children: resolvedCancelText
|
|
11073
|
+
}
|
|
11074
|
+
),
|
|
11075
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11076
|
+
"button",
|
|
11077
|
+
{
|
|
11078
|
+
type: "button",
|
|
11079
|
+
...!isDanger ? { "data-autofocus": true } : {},
|
|
11080
|
+
onClick: onConfirm,
|
|
11081
|
+
className: [
|
|
11082
|
+
"cursor-pointer px-4 py-2 text-sm font-medium rounded-xl text-white",
|
|
11083
|
+
"transition-all duration-150 shadow-sm hover:shadow",
|
|
11084
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
11085
|
+
isDanger ? "bg-red-600 hover:bg-red-700 active:bg-red-800 focus-visible:ring-red-500/50" : "bg-primary-600 hover:bg-primary-700 active:bg-primary-800 focus-visible:ring-primary-500/50"
|
|
11086
|
+
].join(" "),
|
|
11087
|
+
"data-testid": "confirm-modal-confirm",
|
|
11088
|
+
children: resolvedConfirmText
|
|
11089
|
+
}
|
|
11090
|
+
)
|
|
11091
|
+
] })
|
|
11092
|
+
] }) })
|
|
11093
|
+
] });
|
|
11094
|
+
}
|
|
11095
|
+
var ConfirmModal = React.memo(ConfirmModalBase);
|
|
11096
|
+
ConfirmModal.displayName = "ConfirmModal";
|
|
11097
|
+
var ConfirmModal_default = ConfirmModal;
|
|
11098
|
+
var ROLES = ["editor", "viewer"];
|
|
11099
|
+
function RoleSegmentedControl({
|
|
11100
|
+
value,
|
|
11101
|
+
onChange,
|
|
11102
|
+
disabled,
|
|
11103
|
+
size = "md",
|
|
11104
|
+
t
|
|
11105
|
+
}) {
|
|
11106
|
+
const btnBase = size === "sm" ? "px-2 py-0.5 text-[11px]" : "px-3 py-1 text-xs";
|
|
11107
|
+
const currentIndex = ROLES.indexOf(value);
|
|
11108
|
+
const handleKeyDown = (e) => {
|
|
11109
|
+
if (disabled) {
|
|
11110
|
+
return;
|
|
11111
|
+
}
|
|
11112
|
+
let nextIndex = null;
|
|
11113
|
+
if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
11114
|
+
e.preventDefault();
|
|
11115
|
+
nextIndex = currentIndex <= 0 ? ROLES.length - 1 : currentIndex - 1;
|
|
11116
|
+
} else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
11117
|
+
e.preventDefault();
|
|
11118
|
+
nextIndex = currentIndex >= ROLES.length - 1 ? 0 : currentIndex + 1;
|
|
11119
|
+
}
|
|
11120
|
+
if (nextIndex !== null) {
|
|
11121
|
+
const nextRole = ROLES[nextIndex];
|
|
11122
|
+
onChange(nextRole);
|
|
11123
|
+
const target = e.currentTarget.querySelector(`[data-role="${nextRole}"]`);
|
|
11124
|
+
target?.focus();
|
|
11125
|
+
}
|
|
11126
|
+
};
|
|
11127
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11128
|
+
"div",
|
|
11129
|
+
{
|
|
11130
|
+
role: "radiogroup",
|
|
11131
|
+
"aria-label": t("BiChat.Share.RoleLabel"),
|
|
11132
|
+
className: "inline-flex rounded-lg border border-gray-200 dark:border-gray-700 p-0.5 bg-gray-50 dark:bg-gray-800/50",
|
|
11133
|
+
onKeyDown: handleKeyDown,
|
|
11134
|
+
children: ROLES.map((role) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
11135
|
+
"button",
|
|
11136
|
+
{
|
|
11137
|
+
type: "button",
|
|
11138
|
+
role: "radio",
|
|
11139
|
+
"aria-checked": value === role,
|
|
11140
|
+
tabIndex: value === role ? 0 : -1,
|
|
11141
|
+
"data-role": role,
|
|
11142
|
+
disabled,
|
|
11143
|
+
onClick: () => onChange(role),
|
|
11144
|
+
className: `${btnBase} cursor-pointer rounded-md font-medium transition-all duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 disabled:opacity-50 disabled:cursor-not-allowed ${value === role ? "bg-primary-600 text-white shadow-sm" : "text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100"}`,
|
|
11145
|
+
children: role === "editor" ? t("BiChat.Share.RoleEditor") : t("BiChat.Share.RoleViewer")
|
|
11146
|
+
},
|
|
11147
|
+
role
|
|
11148
|
+
))
|
|
11149
|
+
}
|
|
11150
|
+
);
|
|
11151
|
+
}
|
|
11152
|
+
function MemberSkeleton() {
|
|
11153
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 rounded-xl px-3 py-2.5", "aria-hidden": "true", children: [
|
|
11154
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 rounded-full bg-gray-200 dark:bg-gray-700 animate-pulse flex-shrink-0" }),
|
|
11155
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-1.5", children: [
|
|
11156
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 w-28 rounded bg-gray-200 dark:bg-gray-700 animate-pulse" }),
|
|
11157
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2.5 w-16 rounded bg-gray-100 dark:bg-gray-800 animate-pulse" })
|
|
11158
|
+
] }),
|
|
11159
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-16 rounded-lg bg-gray-200 dark:bg-gray-700 animate-pulse" })
|
|
11160
|
+
] });
|
|
11161
|
+
}
|
|
11162
|
+
function SessionMembersModal({ isOpen, sessionId, dataSource, onClose }) {
|
|
11163
|
+
const headingId = React.useId();
|
|
11164
|
+
const { t } = useTranslation();
|
|
11165
|
+
const statusTimerRef = React.useRef();
|
|
11166
|
+
const [loading, setLoading] = React.useState(false);
|
|
11167
|
+
const [saving, setSaving] = React.useState(false);
|
|
11168
|
+
const [error, setError] = React.useState(null);
|
|
11169
|
+
const [users, setUsers] = React.useState([]);
|
|
11170
|
+
const [members, setMembers] = React.useState([]);
|
|
11171
|
+
const [selectedUser, setSelectedUser] = React.useState(null);
|
|
11172
|
+
const [selectedRole, setSelectedRole] = React.useState("editor");
|
|
11173
|
+
const [query, setQuery] = React.useState("");
|
|
11174
|
+
const [confirmRemove, setConfirmRemove] = React.useState(null);
|
|
11175
|
+
const [statusMessage, setStatusMessage] = React.useState(null);
|
|
11176
|
+
const [dropdownOpen, setDropdownOpen] = React.useState(false);
|
|
11177
|
+
const [dropdownHighlightIndex, setDropdownHighlightIndex] = React.useState(0);
|
|
11178
|
+
const dropdownOptionRefs = React.useRef([]);
|
|
11179
|
+
const canManageMembers = Boolean(
|
|
11180
|
+
dataSource.listUsers && dataSource.listSessionMembers && dataSource.addSessionMember && dataSource.updateSessionMemberRole && dataSource.removeSessionMember
|
|
11181
|
+
);
|
|
11182
|
+
const refresh = React.useCallback(async () => {
|
|
11183
|
+
if (!sessionId || !canManageMembers) {
|
|
11184
|
+
return;
|
|
11185
|
+
}
|
|
11186
|
+
setLoading(true);
|
|
11187
|
+
setError(null);
|
|
11188
|
+
try {
|
|
11189
|
+
const [usersData, membersData] = await Promise.all([
|
|
11190
|
+
dataSource.listUsers(),
|
|
11191
|
+
dataSource.listSessionMembers(sessionId)
|
|
11192
|
+
]);
|
|
11193
|
+
setUsers(usersData);
|
|
11194
|
+
setMembers(membersData);
|
|
11195
|
+
} catch {
|
|
11196
|
+
setError(t("BiChat.Share.LoadFailed"));
|
|
11197
|
+
} finally {
|
|
11198
|
+
setLoading(false);
|
|
11199
|
+
}
|
|
11200
|
+
}, [canManageMembers, dataSource, sessionId, t]);
|
|
11201
|
+
React.useEffect(() => {
|
|
11202
|
+
if (!isOpen) {
|
|
11203
|
+
return;
|
|
11204
|
+
}
|
|
11205
|
+
void refresh();
|
|
11206
|
+
}, [isOpen, refresh]);
|
|
11207
|
+
React.useEffect(() => {
|
|
11208
|
+
if (!isOpen) {
|
|
11209
|
+
setQuery("");
|
|
11210
|
+
setSelectedUser(null);
|
|
11211
|
+
setSelectedRole("editor");
|
|
11212
|
+
setError(null);
|
|
11213
|
+
setConfirmRemove(null);
|
|
11214
|
+
setStatusMessage(null);
|
|
11215
|
+
setDropdownOpen(false);
|
|
11216
|
+
setDropdownHighlightIndex(0);
|
|
11217
|
+
}
|
|
11218
|
+
}, [isOpen]);
|
|
11219
|
+
const memberIDs = React.useMemo(() => new Set(members.map((m) => m.user.id)), [members]);
|
|
11220
|
+
const availableUsers = React.useMemo(
|
|
11221
|
+
() => users.filter((user) => !memberIDs.has(user.id)),
|
|
11222
|
+
[users, memberIDs]
|
|
11223
|
+
);
|
|
11224
|
+
const filteredUsers = React.useMemo(() => {
|
|
11225
|
+
if (!query.trim()) {
|
|
11226
|
+
return availableUsers;
|
|
11227
|
+
}
|
|
11228
|
+
const q = query.toLowerCase();
|
|
11229
|
+
return availableUsers.filter(
|
|
11230
|
+
(u) => u.firstName.toLowerCase().includes(q) || u.lastName.toLowerCase().includes(q) || `${u.firstName} ${u.lastName}`.toLowerCase().includes(q)
|
|
11231
|
+
);
|
|
11232
|
+
}, [availableUsers, query]);
|
|
11233
|
+
React.useEffect(() => {
|
|
11234
|
+
setDropdownHighlightIndex(
|
|
11235
|
+
(i) => Math.min(Math.max(0, i), Math.max(0, filteredUsers.length - 1))
|
|
11236
|
+
);
|
|
11237
|
+
}, [filteredUsers.length]);
|
|
11238
|
+
React.useEffect(() => () => clearTimeout(statusTimerRef.current), []);
|
|
11239
|
+
const flashStatus = React.useCallback((msg) => {
|
|
11240
|
+
clearTimeout(statusTimerRef.current);
|
|
11241
|
+
setStatusMessage(msg);
|
|
11242
|
+
statusTimerRef.current = setTimeout(() => setStatusMessage(null), 3e3);
|
|
11243
|
+
}, []);
|
|
11244
|
+
const handleAdd = React.useCallback(async () => {
|
|
11245
|
+
if (!sessionId || !selectedUser || !dataSource.addSessionMember) {
|
|
11246
|
+
return;
|
|
11247
|
+
}
|
|
11248
|
+
setSaving(true);
|
|
11249
|
+
setError(null);
|
|
11250
|
+
try {
|
|
11251
|
+
await dataSource.addSessionMember(sessionId, selectedUser.id, selectedRole);
|
|
11252
|
+
setSelectedUser(null);
|
|
11253
|
+
setQuery("");
|
|
11254
|
+
flashStatus(t("BiChat.Share.MemberAdded"));
|
|
11255
|
+
await refresh();
|
|
11256
|
+
} catch {
|
|
11257
|
+
setError(t("BiChat.Share.AddFailed"));
|
|
11258
|
+
} finally {
|
|
11259
|
+
setSaving(false);
|
|
11260
|
+
}
|
|
11261
|
+
}, [sessionId, selectedUser, selectedRole, dataSource.addSessionMember, refresh, t, flashStatus]);
|
|
11262
|
+
const handleUpdateRole = React.useCallback(async (userId, role) => {
|
|
11263
|
+
if (!sessionId || !dataSource.updateSessionMemberRole) {
|
|
11264
|
+
return;
|
|
11265
|
+
}
|
|
11266
|
+
setSaving(true);
|
|
11267
|
+
setError(null);
|
|
11268
|
+
try {
|
|
11269
|
+
await dataSource.updateSessionMemberRole(sessionId, userId, role);
|
|
11270
|
+
await refresh();
|
|
11271
|
+
} catch {
|
|
11272
|
+
setError(t("BiChat.Share.UpdateFailed"));
|
|
11273
|
+
} finally {
|
|
11274
|
+
setSaving(false);
|
|
11275
|
+
}
|
|
11276
|
+
}, [sessionId, dataSource.updateSessionMemberRole, refresh]);
|
|
11277
|
+
const handleRemove = React.useCallback(async (userId) => {
|
|
11278
|
+
if (!sessionId || !dataSource.removeSessionMember) {
|
|
11279
|
+
return;
|
|
11280
|
+
}
|
|
11281
|
+
setSaving(true);
|
|
11282
|
+
setError(null);
|
|
11283
|
+
try {
|
|
11284
|
+
await dataSource.removeSessionMember(sessionId, userId);
|
|
11285
|
+
flashStatus(t("BiChat.Share.MemberRemoved"));
|
|
11286
|
+
await refresh();
|
|
11287
|
+
} catch {
|
|
11288
|
+
setError(t("BiChat.Share.RemoveFailed"));
|
|
11289
|
+
} finally {
|
|
11290
|
+
setSaving(false);
|
|
11291
|
+
}
|
|
11292
|
+
}, [sessionId, dataSource.removeSessionMember, refresh, flashStatus]);
|
|
11293
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11294
|
+
/* @__PURE__ */ jsxRuntime.jsxs(InlineDialog, { open: isOpen, onClose, className: "relative z-40", children: [
|
|
11295
|
+
/* @__PURE__ */ jsxRuntime.jsx(InlineDialogBackdrop, { className: "fixed inset-0 bg-black/40 dark:bg-black/60 backdrop-blur-sm transition-opacity duration-200" }),
|
|
11296
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11297
|
+
InlineDialogPanel,
|
|
11298
|
+
{
|
|
11299
|
+
"aria-labelledby": headingId,
|
|
11300
|
+
className: "bg-white dark:bg-gray-800 rounded-2xl shadow-xl dark:shadow-2xl dark:shadow-black/30 max-w-md w-full",
|
|
11301
|
+
children: [
|
|
11302
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-6 pt-5 pb-4", children: [
|
|
11303
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
11304
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-9 h-9 rounded-xl bg-primary-50 dark:bg-primary-950/40 border border-primary-200/60 dark:border-primary-800/40", children: /* @__PURE__ */ jsxRuntime.jsx(react.UsersThree, { size: 18, weight: "duotone", className: "text-primary-600 dark:text-primary-400" }) }),
|
|
11305
|
+
/* @__PURE__ */ jsxRuntime.jsx(InlineDialogTitle, { id: headingId, className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: t("BiChat.Share.Title") })
|
|
11306
|
+
] }),
|
|
11307
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11308
|
+
"button",
|
|
11309
|
+
{
|
|
11310
|
+
type: "button",
|
|
11311
|
+
onClick: onClose,
|
|
11312
|
+
className: "rounded-lg p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 dark:hover:text-gray-300 dark:hover:bg-gray-700 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50",
|
|
11313
|
+
"aria-label": t("BiChat.Common.Close"),
|
|
11314
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { size: 18 })
|
|
11315
|
+
}
|
|
11316
|
+
)
|
|
11317
|
+
] }),
|
|
11318
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pb-5 space-y-4", children: [
|
|
11319
|
+
!canManageMembers && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-amber-200 bg-amber-50 px-3 py-2.5 text-xs text-amber-700 dark:border-amber-800/60 dark:bg-amber-900/20 dark:text-amber-300", children: t("BiChat.Share.Unsupported") }),
|
|
11320
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-red-200 bg-red-50 px-3 py-2.5 text-xs text-red-700 dark:border-red-800/60 dark:bg-red-900/20 dark:text-red-300", children: error }),
|
|
11321
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: statusMessage }),
|
|
11322
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
11323
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400", children: [
|
|
11324
|
+
t("BiChat.Share.Members"),
|
|
11325
|
+
!loading && members.length > 0 ? ` (${members.length})` : ""
|
|
11326
|
+
] }),
|
|
11327
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-64 overflow-y-auto -mx-1 px-1 space-y-1", children: loading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11328
|
+
/* @__PURE__ */ jsxRuntime.jsx(MemberSkeleton, {}),
|
|
11329
|
+
/* @__PURE__ */ jsxRuntime.jsx(MemberSkeleton, {}),
|
|
11330
|
+
/* @__PURE__ */ jsxRuntime.jsx(MemberSkeleton, {})
|
|
11331
|
+
] }) : members.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-8 text-gray-400 dark:text-gray-500", children: [
|
|
11332
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.UsersThree, { size: 32, weight: "thin", className: "mb-2" }),
|
|
11333
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: t("BiChat.Share.Empty") })
|
|
11334
|
+
] }) : members.map((member) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11335
|
+
"div",
|
|
11336
|
+
{
|
|
11337
|
+
className: "flex items-center gap-3 rounded-xl px-3 py-2 transition-colors hover:bg-gray-50 dark:hover:bg-gray-700/40",
|
|
11338
|
+
children: [
|
|
11339
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11340
|
+
MemoizedUserAvatar,
|
|
11341
|
+
{
|
|
11342
|
+
firstName: member.user.firstName,
|
|
11343
|
+
lastName: member.user.lastName,
|
|
11344
|
+
initials: member.user.initials,
|
|
11345
|
+
size: "sm"
|
|
11346
|
+
}
|
|
11347
|
+
),
|
|
11348
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "truncate text-sm font-medium text-gray-900 dark:text-gray-100", children: [
|
|
11349
|
+
member.user.firstName,
|
|
11350
|
+
" ",
|
|
11351
|
+
member.user.lastName
|
|
11352
|
+
] }) }),
|
|
11353
|
+
member.role === "owner" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-amber-50 dark:bg-amber-900/20 border border-amber-200/60 dark:border-amber-800/40 px-2.5 py-0.5 text-[11px] font-medium text-amber-700 dark:text-amber-300", children: [
|
|
11354
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Crown, { size: 12, weight: "duotone" }),
|
|
11355
|
+
t("BiChat.Share.RoleOwner")
|
|
11356
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
|
|
11357
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11358
|
+
RoleSegmentedControl,
|
|
11359
|
+
{
|
|
11360
|
+
value: member.role,
|
|
11361
|
+
onChange: (role) => handleUpdateRole(member.user.id, role),
|
|
11362
|
+
disabled: saving,
|
|
11363
|
+
size: "sm",
|
|
11364
|
+
t
|
|
11365
|
+
}
|
|
11366
|
+
),
|
|
11367
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11368
|
+
"button",
|
|
11369
|
+
{
|
|
11370
|
+
type: "button",
|
|
11371
|
+
disabled: saving,
|
|
11372
|
+
onClick: () => setConfirmRemove(member),
|
|
11373
|
+
className: "cursor-pointer rounded-lg p-1.5 text-gray-400 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-500/50",
|
|
11374
|
+
"aria-label": `${t("BiChat.Share.Remove")} ${member.user.firstName} ${member.user.lastName}`,
|
|
11375
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(react.Trash, { size: 14 })
|
|
11376
|
+
}
|
|
11377
|
+
)
|
|
11378
|
+
] })
|
|
11379
|
+
]
|
|
11380
|
+
},
|
|
11381
|
+
member.user.id
|
|
11382
|
+
)) })
|
|
11383
|
+
] }),
|
|
11384
|
+
canManageMembers && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-gray-200 dark:border-gray-700 p-3 space-y-3", children: [
|
|
11385
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400", children: t("BiChat.Share.AddMember") }),
|
|
11386
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11387
|
+
"div",
|
|
11388
|
+
{
|
|
11389
|
+
className: "relative",
|
|
11390
|
+
onBlur: (e) => {
|
|
11391
|
+
if (!e.currentTarget.contains(e.relatedTarget)) {
|
|
11392
|
+
setDropdownOpen(false);
|
|
11393
|
+
}
|
|
11394
|
+
},
|
|
11395
|
+
children: [
|
|
11396
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
11397
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11398
|
+
react.MagnifyingGlass,
|
|
11399
|
+
{
|
|
11400
|
+
size: 14,
|
|
11401
|
+
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 dark:text-gray-500"
|
|
11402
|
+
}
|
|
11403
|
+
),
|
|
11404
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11405
|
+
"input",
|
|
11406
|
+
{
|
|
11407
|
+
type: "text",
|
|
11408
|
+
className: "w-full rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800/60 pl-8 pr-3 py-2 text-sm text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 transition-colors focus:border-primary-400 dark:focus:border-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500/20",
|
|
11409
|
+
placeholder: t("BiChat.Share.SearchUsers"),
|
|
11410
|
+
value: selectedUser ? `${selectedUser.firstName} ${selectedUser.lastName}` : query,
|
|
11411
|
+
onFocus: () => {
|
|
11412
|
+
setDropdownOpen(true);
|
|
11413
|
+
setDropdownHighlightIndex(0);
|
|
11414
|
+
if (selectedUser) {
|
|
11415
|
+
setSelectedUser(null);
|
|
11416
|
+
setQuery("");
|
|
11417
|
+
}
|
|
11418
|
+
},
|
|
11419
|
+
onChange: (e) => {
|
|
11420
|
+
setQuery(e.target.value);
|
|
11421
|
+
setSelectedUser(null);
|
|
11422
|
+
setDropdownOpen(true);
|
|
11423
|
+
setDropdownHighlightIndex(0);
|
|
11424
|
+
},
|
|
11425
|
+
onKeyDown: (e) => {
|
|
11426
|
+
if (!dropdownOpen || filteredUsers.length === 0) {
|
|
11427
|
+
if (e.key === "Escape") {
|
|
11428
|
+
setDropdownOpen(false);
|
|
11429
|
+
}
|
|
11430
|
+
return;
|
|
11431
|
+
}
|
|
11432
|
+
if (e.key === "Escape") {
|
|
11433
|
+
e.preventDefault();
|
|
11434
|
+
setDropdownOpen(false);
|
|
11435
|
+
setDropdownHighlightIndex(0);
|
|
11436
|
+
return;
|
|
11437
|
+
}
|
|
11438
|
+
if (e.key === "ArrowDown") {
|
|
11439
|
+
e.preventDefault();
|
|
11440
|
+
const next = (dropdownHighlightIndex + 1) % filteredUsers.length;
|
|
11441
|
+
setDropdownHighlightIndex(next);
|
|
11442
|
+
setTimeout(() => dropdownOptionRefs.current[next]?.focus(), 0);
|
|
11443
|
+
return;
|
|
11444
|
+
}
|
|
11445
|
+
if (e.key === "ArrowUp") {
|
|
11446
|
+
e.preventDefault();
|
|
11447
|
+
const next = dropdownHighlightIndex <= 0 ? filteredUsers.length - 1 : dropdownHighlightIndex - 1;
|
|
11448
|
+
setDropdownHighlightIndex(next);
|
|
11449
|
+
setTimeout(() => dropdownOptionRefs.current[next]?.focus(), 0);
|
|
11450
|
+
return;
|
|
11451
|
+
}
|
|
11452
|
+
if (e.key === "Enter") {
|
|
11453
|
+
e.preventDefault();
|
|
11454
|
+
const user = filteredUsers[dropdownHighlightIndex];
|
|
11455
|
+
if (user) {
|
|
11456
|
+
setSelectedUser(user);
|
|
11457
|
+
setQuery("");
|
|
11458
|
+
setDropdownOpen(false);
|
|
11459
|
+
}
|
|
11460
|
+
}
|
|
11461
|
+
}
|
|
11462
|
+
}
|
|
11463
|
+
)
|
|
11464
|
+
] }),
|
|
11465
|
+
dropdownOpen && !selectedUser && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute z-10 mt-1 max-h-48 w-full overflow-auto rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 shadow-lg py-1", children: filteredUsers.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-sm text-gray-500 dark:text-gray-400", children: availableUsers.length === 0 ? t("BiChat.Share.NoUsersAvailable") : t("BiChat.Share.NoSearchResults") }) : filteredUsers.map((user, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11466
|
+
"button",
|
|
11467
|
+
{
|
|
11468
|
+
type: "button",
|
|
11469
|
+
ref: (el) => {
|
|
11470
|
+
dropdownOptionRefs.current[index] = el;
|
|
11471
|
+
},
|
|
11472
|
+
className: `flex w-full items-center gap-2.5 px-3 py-2 cursor-pointer transition-colors hover:bg-primary-50 dark:hover:bg-primary-900/20 ${index === dropdownHighlightIndex ? "bg-primary-50 dark:bg-primary-900/20" : ""}`,
|
|
11473
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
11474
|
+
onClick: () => {
|
|
11475
|
+
setSelectedUser(user);
|
|
11476
|
+
setQuery("");
|
|
11477
|
+
setDropdownOpen(false);
|
|
11478
|
+
},
|
|
11479
|
+
children: [
|
|
11480
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11481
|
+
MemoizedUserAvatar,
|
|
11482
|
+
{
|
|
11483
|
+
firstName: user.firstName,
|
|
11484
|
+
lastName: user.lastName,
|
|
11485
|
+
initials: user.initials,
|
|
11486
|
+
size: "xs"
|
|
11487
|
+
}
|
|
11488
|
+
),
|
|
11489
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-900 dark:text-gray-100", children: [
|
|
11490
|
+
user.firstName,
|
|
11491
|
+
" ",
|
|
11492
|
+
user.lastName
|
|
11493
|
+
] })
|
|
11494
|
+
]
|
|
11495
|
+
},
|
|
11496
|
+
user.id
|
|
11497
|
+
)) })
|
|
11498
|
+
]
|
|
11499
|
+
}
|
|
11500
|
+
),
|
|
11501
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
11502
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11503
|
+
RoleSegmentedControl,
|
|
11504
|
+
{
|
|
11505
|
+
value: selectedRole,
|
|
11506
|
+
onChange: setSelectedRole,
|
|
11507
|
+
disabled: saving,
|
|
11508
|
+
t
|
|
11509
|
+
}
|
|
11510
|
+
),
|
|
11511
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11512
|
+
"button",
|
|
11513
|
+
{
|
|
11514
|
+
type: "button",
|
|
11515
|
+
onClick: handleAdd,
|
|
11516
|
+
disabled: saving || !selectedUser,
|
|
11517
|
+
className: "inline-flex cursor-pointer items-center gap-1.5 rounded-xl bg-primary-600 px-3.5 py-2 text-sm font-medium text-white shadow-sm transition-all duration-150 hover:bg-primary-700 hover:shadow active:bg-primary-800 disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
11518
|
+
children: [
|
|
11519
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.UserPlus, { size: 14 }),
|
|
11520
|
+
t("BiChat.Share.Add")
|
|
11521
|
+
]
|
|
11522
|
+
}
|
|
11523
|
+
)
|
|
11524
|
+
] })
|
|
11525
|
+
] })
|
|
11526
|
+
] })
|
|
11527
|
+
]
|
|
11528
|
+
}
|
|
11529
|
+
) })
|
|
11530
|
+
] }),
|
|
11531
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11532
|
+
ConfirmModal,
|
|
11533
|
+
{
|
|
11534
|
+
isOpen: !!confirmRemove,
|
|
11535
|
+
isDanger: true,
|
|
11536
|
+
title: t("BiChat.Share.RemoveConfirmTitle"),
|
|
11537
|
+
message: confirmRemove ? t("BiChat.Share.RemoveConfirmMessage").replace(
|
|
11538
|
+
"{{name}}",
|
|
11539
|
+
`${confirmRemove.user.firstName} ${confirmRemove.user.lastName}`
|
|
11540
|
+
) : "",
|
|
11541
|
+
confirmText: t("BiChat.Share.Remove"),
|
|
11542
|
+
onConfirm: () => {
|
|
11543
|
+
if (confirmRemove) {
|
|
11544
|
+
void handleRemove(confirmRemove.user.id);
|
|
11545
|
+
}
|
|
11546
|
+
setConfirmRemove(null);
|
|
11547
|
+
},
|
|
11548
|
+
onCancel: () => setConfirmRemove(null)
|
|
11549
|
+
}
|
|
11550
|
+
)
|
|
11551
|
+
] });
|
|
11552
|
+
}
|
|
11553
|
+
|
|
11554
|
+
// ui/src/bichat/components/StreamError.tsx
|
|
11555
|
+
init_useTranslation();
|
|
11556
|
+
function StreamError({
|
|
11557
|
+
error,
|
|
11558
|
+
onRetry,
|
|
11559
|
+
onRegenerate,
|
|
11560
|
+
onDismiss,
|
|
11561
|
+
compact = false
|
|
11562
|
+
}) {
|
|
11563
|
+
const { t } = useTranslation();
|
|
11564
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11565
|
+
framerMotion.motion.div,
|
|
11566
|
+
{
|
|
11567
|
+
initial: { opacity: 0, y: 10 },
|
|
11568
|
+
animate: { opacity: 1, y: 0 },
|
|
11569
|
+
exit: { opacity: 0, y: -10 },
|
|
11570
|
+
className: `flex items-start gap-3 ${compact ? "px-3 py-2.5" : "px-4 py-3"} bg-red-50 dark:bg-red-950/40 border border-red-200/80 dark:border-red-900/60 rounded-xl shadow-sm`,
|
|
11571
|
+
role: "alert",
|
|
11572
|
+
children: [
|
|
11573
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 mt-0.5 flex items-center justify-center w-7 h-7 rounded-full bg-red-100 dark:bg-red-900/40", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11574
|
+
react.Warning,
|
|
11575
|
+
{
|
|
11576
|
+
className: "w-4 h-4 text-red-600 dark:text-red-400",
|
|
11577
|
+
weight: "fill"
|
|
11578
|
+
}
|
|
11579
|
+
) }),
|
|
11580
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
11581
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-red-800 dark:text-red-200 leading-snug", children: t("BiChat.Error.Generic") }),
|
|
11582
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs text-red-600/80 dark:text-red-400/70 break-words leading-relaxed", children: error }),
|
|
11583
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
11584
|
+
onRetry && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11585
|
+
"button",
|
|
11586
|
+
{
|
|
11587
|
+
onClick: onRetry,
|
|
11588
|
+
className: "cursor-pointer inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-white bg-red-600 hover:bg-red-700 active:bg-red-800 dark:bg-red-700 dark:hover:bg-red-600 rounded-lg transition-colors shadow-sm",
|
|
11589
|
+
type: "button",
|
|
11590
|
+
children: [
|
|
11591
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.ArrowClockwise, { className: "w-3.5 h-3.5" }),
|
|
11592
|
+
t("BiChat.StreamError.Retry")
|
|
11593
|
+
]
|
|
11594
|
+
}
|
|
11595
|
+
),
|
|
11596
|
+
onRegenerate && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11597
|
+
"button",
|
|
11598
|
+
{
|
|
11599
|
+
onClick: onRegenerate,
|
|
11600
|
+
className: "cursor-pointer inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700 rounded-lg transition-colors shadow-sm",
|
|
11601
|
+
type: "button",
|
|
11602
|
+
children: [
|
|
11603
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.ArrowsCounterClockwise, { className: "w-3.5 h-3.5" }),
|
|
11604
|
+
t("BiChat.StreamError.Regenerate")
|
|
11605
|
+
]
|
|
11606
|
+
}
|
|
11607
|
+
)
|
|
11608
|
+
] })
|
|
11609
|
+
] }),
|
|
11610
|
+
onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11611
|
+
"button",
|
|
11612
|
+
{
|
|
11613
|
+
onClick: onDismiss,
|
|
11614
|
+
className: "cursor-pointer flex-shrink-0 mt-0.5 inline-flex items-center justify-center w-6 h-6 text-red-400 dark:text-red-500 hover:text-red-600 dark:hover:text-red-300 hover:bg-red-100 dark:hover:bg-red-900/40 rounded-md transition-colors",
|
|
11615
|
+
type: "button",
|
|
11616
|
+
"aria-label": t("BiChat.Chat.DismissNotification"),
|
|
11617
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(react.X, { className: "w-3.5 h-3.5" })
|
|
10812
11618
|
}
|
|
10813
11619
|
)
|
|
10814
11620
|
]
|
|
@@ -10872,7 +11678,8 @@ function ChatSessionCore({
|
|
|
10872
11678
|
updateQueueItem
|
|
10873
11679
|
} = useChatInput();
|
|
10874
11680
|
const isArchived = session?.status === "archived";
|
|
10875
|
-
const
|
|
11681
|
+
const accessReadOnly = session?.access ? !session.access.canWrite : false;
|
|
11682
|
+
const effectiveReadOnly = Boolean(readOnly ?? isReadOnly) || isArchived || accessReadOnly;
|
|
10876
11683
|
const [restoring, setRestoring] = React.useState(false);
|
|
10877
11684
|
const handleRestore = React.useCallback(async () => {
|
|
10878
11685
|
if (!session?.id) {
|
|
@@ -10893,6 +11700,8 @@ function ChatSessionCore({
|
|
|
10893
11700
|
const [artifactsPanelExpanded, setArtifactsPanelExpanded] = React.useState(
|
|
10894
11701
|
artifactsPanelDefaultExpanded
|
|
10895
11702
|
);
|
|
11703
|
+
const [membersModalOpen, setMembersModalOpen] = React.useState(false);
|
|
11704
|
+
const [headerMembers, setHeaderMembers] = React.useState(null);
|
|
10896
11705
|
const [artifactsPanelWidth, setArtifactsPanelWidth] = React.useState(ARTIFACTS_PANEL_WIDTH_DEFAULT);
|
|
10897
11706
|
const [isResizingArtifactsPanel, setIsResizingArtifactsPanel] = React.useState(false);
|
|
10898
11707
|
const layoutContainerRef = React.useRef(null);
|
|
@@ -10927,6 +11736,25 @@ function ChatSessionCore({
|
|
|
10927
11736
|
} catch {
|
|
10928
11737
|
}
|
|
10929
11738
|
}, [artifactsPanelStorageKey, showArtifactsPanel]);
|
|
11739
|
+
React.useEffect(() => {
|
|
11740
|
+
if (!session?.id || !dataSource.listSessionMembers) {
|
|
11741
|
+
setHeaderMembers(null);
|
|
11742
|
+
return;
|
|
11743
|
+
}
|
|
11744
|
+
let cancelled = false;
|
|
11745
|
+
dataSource.listSessionMembers(session.id).then((members) => {
|
|
11746
|
+
if (!cancelled) {
|
|
11747
|
+
setHeaderMembers(members.map((m) => m.user));
|
|
11748
|
+
}
|
|
11749
|
+
}).catch(() => {
|
|
11750
|
+
if (!cancelled) {
|
|
11751
|
+
setHeaderMembers(null);
|
|
11752
|
+
}
|
|
11753
|
+
});
|
|
11754
|
+
return () => {
|
|
11755
|
+
cancelled = true;
|
|
11756
|
+
};
|
|
11757
|
+
}, [session?.id, dataSource.listSessionMembers]);
|
|
10930
11758
|
const handleArtifactsResizeStart = React.useCallback(() => {
|
|
10931
11759
|
setIsResizingArtifactsPanel(true);
|
|
10932
11760
|
}, []);
|
|
@@ -11016,8 +11844,26 @@ function ChatSessionCore({
|
|
|
11016
11844
|
}
|
|
11017
11845
|
}
|
|
11018
11846
|
};
|
|
11019
|
-
const
|
|
11020
|
-
|
|
11847
|
+
const canShowShareButton = Boolean(
|
|
11848
|
+
session?.access?.canManageMembers && dataSource.listUsers && dataSource.listSessionMembers && dataSource.addSessionMember && dataSource.updateSessionMemberRole && dataSource.removeSessionMember
|
|
11849
|
+
);
|
|
11850
|
+
const shareButton = canShowShareButton ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11851
|
+
"button",
|
|
11852
|
+
{
|
|
11853
|
+
type: "button",
|
|
11854
|
+
onClick: () => setMembersModalOpen(true),
|
|
11855
|
+
className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-xs font-medium text-gray-500 transition-all duration-150 hover:bg-gray-100 hover:text-gray-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200",
|
|
11856
|
+
"aria-label": t("BiChat.Share.Title"),
|
|
11857
|
+
title: t("BiChat.Share.Title"),
|
|
11858
|
+
children: [
|
|
11859
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.ShareNetwork, { className: "h-4 w-4" }),
|
|
11860
|
+
t("BiChat.Share.Button")
|
|
11861
|
+
]
|
|
11862
|
+
}
|
|
11863
|
+
) : null;
|
|
11864
|
+
const headerActions = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11865
|
+
shareButton,
|
|
11866
|
+
showArtifactsControls && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11021
11867
|
"button",
|
|
11022
11868
|
{
|
|
11023
11869
|
type: "button",
|
|
@@ -11037,7 +11883,7 @@ function ChatSessionCore({
|
|
|
11037
11883
|
}
|
|
11038
11884
|
),
|
|
11039
11885
|
actionsSlot
|
|
11040
|
-
] })
|
|
11886
|
+
] });
|
|
11041
11887
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11042
11888
|
"main",
|
|
11043
11889
|
{
|
|
@@ -11050,7 +11896,9 @@ function ChatSessionCore({
|
|
|
11050
11896
|
onBack,
|
|
11051
11897
|
readOnly: effectiveReadOnly,
|
|
11052
11898
|
logoSlot,
|
|
11053
|
-
actionsSlot: headerActions
|
|
11899
|
+
actionsSlot: headerActions,
|
|
11900
|
+
members: headerMembers ?? (session?.owner ? [session.owner] : void 0),
|
|
11901
|
+
onMembersClick: canShowShareButton ? () => setMembersModalOpen(true) : void 0
|
|
11054
11902
|
}
|
|
11055
11903
|
),
|
|
11056
11904
|
error && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -11247,6 +12095,15 @@ function ChatSessionCore({
|
|
|
11247
12095
|
) })
|
|
11248
12096
|
]
|
|
11249
12097
|
}
|
|
12098
|
+
),
|
|
12099
|
+
canShowShareButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12100
|
+
SessionMembersModal,
|
|
12101
|
+
{
|
|
12102
|
+
isOpen: membersModalOpen,
|
|
12103
|
+
sessionId: session?.id,
|
|
12104
|
+
dataSource,
|
|
12105
|
+
onClose: () => setMembersModalOpen(false)
|
|
12106
|
+
}
|
|
11250
12107
|
)
|
|
11251
12108
|
]
|
|
11252
12109
|
}
|
|
@@ -11269,7 +12126,7 @@ function ChatSession(props) {
|
|
|
11269
12126
|
// ui/src/bichat/index.ts
|
|
11270
12127
|
init_MarkdownRenderer();
|
|
11271
12128
|
init_ChartCard();
|
|
11272
|
-
var
|
|
12129
|
+
var sizeClasses2 = {
|
|
11273
12130
|
sm: {
|
|
11274
12131
|
container: "py-6 px-3",
|
|
11275
12132
|
title: "text-sm",
|
|
@@ -11294,7 +12151,7 @@ function EmptyState({
|
|
|
11294
12151
|
className = "",
|
|
11295
12152
|
size = "md"
|
|
11296
12153
|
}) {
|
|
11297
|
-
const sizes =
|
|
12154
|
+
const sizes = sizeClasses2[size];
|
|
11298
12155
|
const prefersReducedMotion2 = framerMotion.useReducedMotion();
|
|
11299
12156
|
const duration = prefersReducedMotion2 ? 0 : 0.4;
|
|
11300
12157
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -11354,7 +12211,7 @@ MemoizedEmptyState.displayName = "EmptyState";
|
|
|
11354
12211
|
|
|
11355
12212
|
// ui/src/bichat/components/EditableText.tsx
|
|
11356
12213
|
init_useTranslation();
|
|
11357
|
-
var
|
|
12214
|
+
var sizeClasses3 = {
|
|
11358
12215
|
sm: "text-sm",
|
|
11359
12216
|
md: "text-base",
|
|
11360
12217
|
lg: "text-lg"
|
|
@@ -11425,7 +12282,7 @@ var EditableText = React.forwardRef(
|
|
|
11425
12282
|
const handleBlur = () => {
|
|
11426
12283
|
handleSave();
|
|
11427
12284
|
};
|
|
11428
|
-
const sizeClass =
|
|
12285
|
+
const sizeClass = sizeClasses3[size];
|
|
11429
12286
|
if (isEditing) {
|
|
11430
12287
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11431
12288
|
"div",
|
|
@@ -11485,7 +12342,7 @@ var MemoizedEditableText = React.memo(EditableText);
|
|
|
11485
12342
|
|
|
11486
12343
|
// ui/src/bichat/components/SearchInput.tsx
|
|
11487
12344
|
init_useTranslation();
|
|
11488
|
-
var
|
|
12345
|
+
var sizeClasses4 = {
|
|
11489
12346
|
sm: {
|
|
11490
12347
|
container: "py-1.5 pl-8 pr-8 text-xs",
|
|
11491
12348
|
icon: 14,
|
|
@@ -11518,7 +12375,7 @@ function SearchInput({
|
|
|
11518
12375
|
const resolvedPlaceholder = placeholder ?? t("BiChat.Common.Search");
|
|
11519
12376
|
const resolvedAriaLabel = ariaLabel ?? t("BiChat.Common.Search");
|
|
11520
12377
|
const inputRef = React.useRef(null);
|
|
11521
|
-
const sizes =
|
|
12378
|
+
const sizes = sizeClasses4[size];
|
|
11522
12379
|
React.useEffect(() => {
|
|
11523
12380
|
if (autoFocus && inputRef.current) {
|
|
11524
12381
|
inputRef.current.focus();
|
|
@@ -11945,134 +12802,6 @@ function ToastContainer({ toasts, onDismiss, dismissLabel }) {
|
|
|
11945
12802
|
}
|
|
11946
12803
|
);
|
|
11947
12804
|
}
|
|
11948
|
-
|
|
11949
|
-
// ui/src/bichat/components/ConfirmModal.tsx
|
|
11950
|
-
init_useTranslation();
|
|
11951
|
-
function ConfirmModalBase({
|
|
11952
|
-
isOpen,
|
|
11953
|
-
title,
|
|
11954
|
-
message,
|
|
11955
|
-
onConfirm,
|
|
11956
|
-
onCancel,
|
|
11957
|
-
confirmText,
|
|
11958
|
-
cancelText,
|
|
11959
|
-
isDanger = false
|
|
11960
|
-
}) {
|
|
11961
|
-
const { t } = useTranslation();
|
|
11962
|
-
const resolvedConfirmText = confirmText?.trim() ? confirmText : t("BiChat.Common.Confirm");
|
|
11963
|
-
const resolvedCancelText = cancelText?.trim() ? cancelText : t("BiChat.Common.Cancel");
|
|
11964
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Dialog, { open: isOpen, onClose: onCancel, className: "relative z-40", children: [
|
|
11965
|
-
/* @__PURE__ */ jsxRuntime.jsx(react$1.DialogBackdrop, { className: "fixed inset-0 bg-black/40 dark:bg-black/60 backdrop-blur-sm transition-opacity duration-200" }),
|
|
11966
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50 p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.DialogPanel, { className: "bg-white dark:bg-gray-800 rounded-2xl shadow-xl dark:shadow-2xl dark:shadow-black/30 max-w-sm w-full overflow-hidden", children: [
|
|
11967
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 pt-6 pb-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3.5", children: [
|
|
11968
|
-
isDanger && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 flex items-center justify-center w-10 h-10 rounded-xl bg-red-50 dark:bg-red-950/40 border border-red-200/60 dark:border-red-800/40", children: /* @__PURE__ */ jsxRuntime.jsx(react.WarningCircle, { size: 22, weight: "duotone", className: "text-red-600 dark:text-red-400" }) }),
|
|
11969
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
11970
|
-
/* @__PURE__ */ jsxRuntime.jsx(react$1.DialogTitle, { className: "text-base font-semibold text-gray-900 dark:text-gray-100 leading-snug", children: title }),
|
|
11971
|
-
/* @__PURE__ */ jsxRuntime.jsx(react$1.Description, { className: "mt-2 text-sm text-gray-600 dark:text-gray-400 leading-relaxed", children: message })
|
|
11972
|
-
] })
|
|
11973
|
-
] }) }),
|
|
11974
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-2.5 px-6 pb-5", children: [
|
|
11975
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11976
|
-
"button",
|
|
11977
|
-
{
|
|
11978
|
-
type: "button",
|
|
11979
|
-
onClick: onCancel,
|
|
11980
|
-
...isDanger ? { "data-autofocus": true } : {},
|
|
11981
|
-
className: "cursor-pointer px-4 py-2 text-sm font-medium rounded-xl text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700/60 hover:bg-gray-200 dark:hover:bg-gray-700 active:bg-gray-250 dark:active:bg-gray-600 transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/50 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
11982
|
-
"data-testid": "confirm-modal-cancel",
|
|
11983
|
-
children: resolvedCancelText
|
|
11984
|
-
}
|
|
11985
|
-
),
|
|
11986
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11987
|
-
"button",
|
|
11988
|
-
{
|
|
11989
|
-
type: "button",
|
|
11990
|
-
...!isDanger ? { "data-autofocus": true } : {},
|
|
11991
|
-
onClick: onConfirm,
|
|
11992
|
-
className: [
|
|
11993
|
-
"cursor-pointer px-4 py-2 text-sm font-medium rounded-xl text-white",
|
|
11994
|
-
"transition-all duration-150 shadow-sm hover:shadow",
|
|
11995
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 dark:focus-visible:ring-offset-gray-800",
|
|
11996
|
-
isDanger ? "bg-red-600 hover:bg-red-700 active:bg-red-800 focus-visible:ring-red-500/50" : "bg-primary-600 hover:bg-primary-700 active:bg-primary-800 focus-visible:ring-primary-500/50"
|
|
11997
|
-
].join(" "),
|
|
11998
|
-
"data-testid": "confirm-modal-confirm",
|
|
11999
|
-
children: resolvedConfirmText
|
|
12000
|
-
}
|
|
12001
|
-
)
|
|
12002
|
-
] })
|
|
12003
|
-
] }) })
|
|
12004
|
-
] });
|
|
12005
|
-
}
|
|
12006
|
-
var ConfirmModal = React.memo(ConfirmModalBase);
|
|
12007
|
-
ConfirmModal.displayName = "ConfirmModal";
|
|
12008
|
-
var ConfirmModal_default = ConfirmModal;
|
|
12009
|
-
function hashString(str) {
|
|
12010
|
-
let hash = 0;
|
|
12011
|
-
for (let i = 0; i < str.length; i++) {
|
|
12012
|
-
const char = str.charCodeAt(i);
|
|
12013
|
-
hash = (hash << 5) - hash + char;
|
|
12014
|
-
hash = hash & hash;
|
|
12015
|
-
}
|
|
12016
|
-
return Math.abs(hash);
|
|
12017
|
-
}
|
|
12018
|
-
var colorPalette = [
|
|
12019
|
-
{ bg: "bg-blue-500", text: "text-white" },
|
|
12020
|
-
{ bg: "bg-green-500", text: "text-white" },
|
|
12021
|
-
{ bg: "bg-purple-500", text: "text-white" },
|
|
12022
|
-
{ bg: "bg-pink-500", text: "text-white" },
|
|
12023
|
-
{ bg: "bg-indigo-500", text: "text-white" },
|
|
12024
|
-
{ bg: "bg-teal-500", text: "text-white" },
|
|
12025
|
-
{ bg: "bg-orange-500", text: "text-white" },
|
|
12026
|
-
{ bg: "bg-cyan-500", text: "text-white" },
|
|
12027
|
-
{ bg: "bg-amber-500", text: "text-white" },
|
|
12028
|
-
{ bg: "bg-lime-500", text: "text-white" }
|
|
12029
|
-
];
|
|
12030
|
-
var sizeClasses4 = {
|
|
12031
|
-
sm: "w-8 h-8 text-xs",
|
|
12032
|
-
md: "w-10 h-10 text-sm",
|
|
12033
|
-
lg: "w-12 h-12 text-base"
|
|
12034
|
-
};
|
|
12035
|
-
function UserAvatar({
|
|
12036
|
-
firstName,
|
|
12037
|
-
lastName,
|
|
12038
|
-
initials: providedInitials,
|
|
12039
|
-
size = "md",
|
|
12040
|
-
className = ""
|
|
12041
|
-
}) {
|
|
12042
|
-
const derivedInitials = (() => {
|
|
12043
|
-
const firstChar = firstName?.trim()?.charAt(0) || "";
|
|
12044
|
-
const lastChar = lastName?.trim()?.charAt(0) || "";
|
|
12045
|
-
const combined = `${firstChar}${lastChar}`.trim();
|
|
12046
|
-
return combined || "U";
|
|
12047
|
-
})();
|
|
12048
|
-
const initials = (providedInitials?.trim() || derivedInitials).toUpperCase();
|
|
12049
|
-
const fullName = `${firstName}${lastName}`;
|
|
12050
|
-
const colorIndex = hashString(fullName) % colorPalette.length;
|
|
12051
|
-
const colors = colorPalette[colorIndex];
|
|
12052
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12053
|
-
"div",
|
|
12054
|
-
{
|
|
12055
|
-
className: `
|
|
12056
|
-
${sizeClasses4[size]}
|
|
12057
|
-
${colors.bg}
|
|
12058
|
-
${colors.text}
|
|
12059
|
-
${className}
|
|
12060
|
-
rounded-full
|
|
12061
|
-
flex
|
|
12062
|
-
items-center
|
|
12063
|
-
justify-center
|
|
12064
|
-
font-semibold
|
|
12065
|
-
flex-shrink-0
|
|
12066
|
-
select-none
|
|
12067
|
-
`,
|
|
12068
|
-
"aria-label": `${firstName} ${lastName}`,
|
|
12069
|
-
title: `${firstName} ${lastName}`,
|
|
12070
|
-
children: initials
|
|
12071
|
-
}
|
|
12072
|
-
);
|
|
12073
|
-
}
|
|
12074
|
-
var MemoizedUserAvatar = React.memo(UserAvatar);
|
|
12075
|
-
MemoizedUserAvatar.displayName = "UserAvatar";
|
|
12076
12805
|
function PermissionGuard({
|
|
12077
12806
|
permissions,
|
|
12078
12807
|
mode = "all",
|
|
@@ -12514,6 +13243,11 @@ var SessionItem = React.memo(
|
|
|
12514
13243
|
const isTitleGenerating = !session.title?.trim();
|
|
12515
13244
|
const displayTitle = isTitleGenerating ? t("BiChat.Common.Generating") : session.title ?? t("BiChat.Common.Untitled");
|
|
12516
13245
|
const lastActivity = formatRelativeTime(session.updatedAt, t);
|
|
13246
|
+
const accessRole = session.access?.role ?? "owner";
|
|
13247
|
+
const roleLabel = accessRole === "editor" ? t("BiChat.Share.RoleEditor") : accessRole === "viewer" ? t("BiChat.Share.RoleViewer") : accessRole === "read_all" ? t("BiChat.Share.RoleReadOnly") : "";
|
|
13248
|
+
const visibilityLabel = session.isGroup ? t("BiChat.Sidebar.GroupChat") : accessRole === "editor" || accessRole === "viewer" ? t("BiChat.Sidebar.SharedWithYou") : "";
|
|
13249
|
+
const isGroupOrShared = Boolean(session.isGroup || session.memberCount && session.memberCount > 1);
|
|
13250
|
+
const metaParts = [lastActivity, visibilityLabel, roleLabel].filter(Boolean);
|
|
12517
13251
|
const { handlers: longPressHandlers } = useLongPress({
|
|
12518
13252
|
delay: 500,
|
|
12519
13253
|
onLongPress: (e) => {
|
|
@@ -12655,17 +13389,23 @@ var SessionItem = React.memo(
|
|
|
12655
13389
|
"data-testid": `${testIdPrefix}-session-${session.id}`,
|
|
12656
13390
|
...longPressHandlers,
|
|
12657
13391
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
12658
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
12659
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
|
|
12663
|
-
|
|
12664
|
-
|
|
12665
|
-
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
13392
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 min-w-0 flex-1", children: [
|
|
13393
|
+
isGroupOrShared && /* @__PURE__ */ jsxRuntime.jsx(react.UsersThree, { size: 14, weight: "duotone", className: "text-primary-500 dark:text-primary-400 mt-1 flex-shrink-0" }),
|
|
13394
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
|
|
13395
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13396
|
+
MemoizedEditableText,
|
|
13397
|
+
{
|
|
13398
|
+
ref: editableTitleRef,
|
|
13399
|
+
value: displayTitle,
|
|
13400
|
+
onSave: (newTitle) => onRename?.(newTitle),
|
|
13401
|
+
isLoading: isTitleGenerating
|
|
13402
|
+
}
|
|
13403
|
+
),
|
|
13404
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-gray-400 dark:text-gray-500 truncate mt-0.5", children: [
|
|
13405
|
+
metaParts.join(" \u2022 "),
|
|
13406
|
+
isGroupOrShared && session.memberCount && session.memberCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center ml-1 rounded-full bg-primary-50 dark:bg-primary-900/30 px-1.5 text-[10px] font-medium text-primary-600 dark:text-primary-400", children: session.memberCount })
|
|
13407
|
+
] })
|
|
13408
|
+
] })
|
|
12669
13409
|
] }),
|
|
12670
13410
|
!isTouch && hasContextMenu && /* @__PURE__ */ jsxRuntime.jsxs(react$1.Menu, { children: [
|
|
12671
13411
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13019,24 +13759,23 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
|
|
|
13019
13759
|
setOffset((prev) => prev + limit);
|
|
13020
13760
|
}
|
|
13021
13761
|
}, [fetching, hasMore]);
|
|
13022
|
-
const
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13762
|
+
const loadMoreNodeRef = React.useRef(null);
|
|
13763
|
+
const loadMoreRef = React.useCallback((node) => {
|
|
13764
|
+
loadMoreNodeRef.current = node;
|
|
13765
|
+
}, []);
|
|
13766
|
+
React.useEffect(() => {
|
|
13767
|
+
const node = loadMoreNodeRef.current;
|
|
13768
|
+
if (!node || fetching || !hasMore) {
|
|
13769
|
+
return;
|
|
13770
|
+
}
|
|
13771
|
+
const observer = new IntersectionObserver((entries) => {
|
|
13772
|
+
if (entries[0].isIntersecting) {
|
|
13773
|
+
handleLoadMore();
|
|
13026
13774
|
}
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
}
|
|
13032
|
-
},
|
|
13033
|
-
{ threshold: 0.1 }
|
|
13034
|
-
);
|
|
13035
|
-
observer.observe(node);
|
|
13036
|
-
return () => observer.disconnect();
|
|
13037
|
-
},
|
|
13038
|
-
[fetching, hasMore, handleLoadMore]
|
|
13039
|
-
);
|
|
13775
|
+
}, { threshold: 0.1 });
|
|
13776
|
+
observer.observe(node);
|
|
13777
|
+
return () => observer.disconnect();
|
|
13778
|
+
}, [fetching, hasMore, handleLoadMore]);
|
|
13040
13779
|
const derivedUsers = React.useMemo(() => {
|
|
13041
13780
|
if (dataSource.listUsers) {
|
|
13042
13781
|
return users;
|
|
@@ -13094,57 +13833,61 @@ function AllChatsList({ dataSource, onSessionSelect, activeSessionId }) {
|
|
|
13094
13833
|
role: "list",
|
|
13095
13834
|
"aria-label": t("BiChat.AllChats.OrganizationChatSessions"),
|
|
13096
13835
|
children: [
|
|
13097
|
-
chats.map((chat) =>
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
|
|
13115
|
-
|
|
13836
|
+
chats.map((chat) => {
|
|
13837
|
+
const owner = chat.owner ?? {
|
|
13838
|
+
firstName: "",
|
|
13839
|
+
lastName: "",
|
|
13840
|
+
initials: "U"
|
|
13841
|
+
};
|
|
13842
|
+
const ownerName = [owner.firstName, owner.lastName].filter(Boolean).join(" ");
|
|
13843
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13844
|
+
framerMotion.motion.div,
|
|
13845
|
+
{
|
|
13846
|
+
initial: { opacity: 0, y: -10 },
|
|
13847
|
+
animate: { opacity: 1, y: 0 },
|
|
13848
|
+
exit: { opacity: 0, y: -10 },
|
|
13849
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13850
|
+
"div",
|
|
13851
|
+
{
|
|
13852
|
+
role: "link",
|
|
13853
|
+
tabIndex: 0,
|
|
13854
|
+
onClick: () => onSessionSelect(chat.id),
|
|
13855
|
+
onKeyDown: (e) => {
|
|
13856
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
13857
|
+
e.preventDefault();
|
|
13858
|
+
onSessionSelect(chat.id);
|
|
13859
|
+
}
|
|
13860
|
+
},
|
|
13861
|
+
className: `
|
|
13116
13862
|
block px-3 py-2 rounded-lg transition-smooth group cursor-pointer
|
|
13117
13863
|
${chat.id === activeSessionId ? "bg-primary-50/50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 border-l-4 border-primary-400 dark:border-primary-600" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 border-l-4 border-transparent"}
|
|
13118
13864
|
`,
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
chat.
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
chat.status === "archived" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 mt-1 px-2 py-0.5 bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 rounded-full text-xs", children: [
|
|
13138
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 12, className: "w-3 h-3" }),
|
|
13139
|
-
t("BiChat.Chat.Archived")
|
|
13865
|
+
"aria-current": chat.id === activeSessionId ? "page" : void 0,
|
|
13866
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
13867
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13868
|
+
MemoizedUserAvatar,
|
|
13869
|
+
{
|
|
13870
|
+
firstName: owner.firstName,
|
|
13871
|
+
lastName: owner.lastName,
|
|
13872
|
+
initials: owner.initials,
|
|
13873
|
+
size: "sm"
|
|
13874
|
+
}
|
|
13875
|
+
),
|
|
13876
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
13877
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium truncate", children: chat.title || t("BiChat.Common.Untitled") }),
|
|
13878
|
+
ownerName && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 truncate", children: ownerName }),
|
|
13879
|
+
chat.status === "archived" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1 mt-1 px-2 py-0.5 bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 rounded-full text-xs", children: [
|
|
13880
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Archive, { size: 12, className: "w-3 h-3" }),
|
|
13881
|
+
t("BiChat.Chat.Archived")
|
|
13882
|
+
] })
|
|
13140
13883
|
] })
|
|
13141
13884
|
] })
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
)
|
|
13885
|
+
}
|
|
13886
|
+
)
|
|
13887
|
+
},
|
|
13888
|
+
chat.id
|
|
13889
|
+
);
|
|
13890
|
+
}),
|
|
13148
13891
|
hasMore && /* @__PURE__ */ jsxRuntime.jsx("div", { ref: loadMoreRef, className: "py-4 text-center", children: fetching ? /* @__PURE__ */ jsxRuntime.jsx(SessionSkeleton, { count: 2 }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
13149
13892
|
"button",
|
|
13150
13893
|
{
|
|
@@ -13914,19 +14657,22 @@ function Sidebar2({
|
|
|
13914
14657
|
animate: "visible",
|
|
13915
14658
|
role: "list",
|
|
13916
14659
|
"aria-label": t("BiChat.Sidebar.PinnedChats"),
|
|
13917
|
-
children: pinnedSessions.map((session) =>
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13921
|
-
|
|
13922
|
-
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
14660
|
+
children: pinnedSessions.map((session) => {
|
|
14661
|
+
const canWrite = session.access?.canWrite ?? true;
|
|
14662
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14663
|
+
SessionItem_default,
|
|
14664
|
+
{
|
|
14665
|
+
session,
|
|
14666
|
+
isActive: session.id === activeSessionId,
|
|
14667
|
+
onSelect: () => handleSessionSelect(session.id),
|
|
14668
|
+
onArchive: canWrite ? () => handleSessionArchive(session.id) : void 0,
|
|
14669
|
+
onPin: canWrite ? () => handleSessionPin(session.id, session.pinned) : void 0,
|
|
14670
|
+
onRename: canWrite ? (newTitle) => handleSessionRename(session.id, newTitle) : void 0,
|
|
14671
|
+
onRegenerateTitle: canWrite ? () => handleSessionRegenerateTitle(session.id) : void 0
|
|
14672
|
+
},
|
|
14673
|
+
session.id
|
|
14674
|
+
);
|
|
14675
|
+
})
|
|
13930
14676
|
}
|
|
13931
14677
|
),
|
|
13932
14678
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-gray-200 dark:border-gray-700 my-3" })
|
|
@@ -13948,19 +14694,22 @@ function Sidebar2({
|
|
|
13948
14694
|
animate: "visible",
|
|
13949
14695
|
role: "list",
|
|
13950
14696
|
"aria-label": `${group.name} chats`,
|
|
13951
|
-
children: group.sessions.map((session) =>
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
14697
|
+
children: group.sessions.map((session) => {
|
|
14698
|
+
const canWrite = session.access?.canWrite ?? true;
|
|
14699
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14700
|
+
SessionItem_default,
|
|
14701
|
+
{
|
|
14702
|
+
session,
|
|
14703
|
+
isActive: session.id === activeSessionId,
|
|
14704
|
+
onSelect: () => handleSessionSelect(session.id),
|
|
14705
|
+
onArchive: canWrite ? () => handleSessionArchive(session.id) : void 0,
|
|
14706
|
+
onPin: canWrite ? () => handleSessionPin(session.id, session.pinned) : void 0,
|
|
14707
|
+
onRename: canWrite ? (newTitle) => handleSessionRename(session.id, newTitle) : void 0,
|
|
14708
|
+
onRegenerateTitle: canWrite ? () => handleSessionRegenerateTitle(session.id) : void 0
|
|
14709
|
+
},
|
|
14710
|
+
session.id
|
|
14711
|
+
);
|
|
14712
|
+
})
|
|
13964
14713
|
}
|
|
13965
14714
|
)
|
|
13966
14715
|
] }, group.name)),
|
|
@@ -16121,6 +16870,76 @@ function useScrollToBottom(items) {
|
|
|
16121
16870
|
scrollToBottom
|
|
16122
16871
|
};
|
|
16123
16872
|
}
|
|
16873
|
+
function useHttpDataSourceConfigFromApplet(options) {
|
|
16874
|
+
return React.useMemo(() => {
|
|
16875
|
+
const ctx = typeof window !== "undefined" ? window.__APPLET_CONTEXT__ : void 0;
|
|
16876
|
+
if (!ctx) {
|
|
16877
|
+
throw new Error(
|
|
16878
|
+
"Applet context not found. Ensure window.__APPLET_CONTEXT__ is injected by the backend."
|
|
16879
|
+
);
|
|
16880
|
+
}
|
|
16881
|
+
const rpcEndpoint = ctx.config?.rpcUIEndpoint ?? "/rpc";
|
|
16882
|
+
const streamEndpoint = ctx.config?.streamEndpoint ?? "/stream";
|
|
16883
|
+
const csrfToken = ctx.session?.csrfToken ?? (typeof window !== "undefined" ? window.__CSRF_TOKEN__ : void 0) ?? "";
|
|
16884
|
+
const isDev = typeof undefined?.DEV === "boolean" && undefined?.DEV;
|
|
16885
|
+
if (!csrfToken && isDev) {
|
|
16886
|
+
console.warn(
|
|
16887
|
+
"[useHttpDataSourceConfigFromApplet] CSRF token is empty \u2014 requests may be rejected by the server."
|
|
16888
|
+
);
|
|
16889
|
+
}
|
|
16890
|
+
return {
|
|
16891
|
+
baseUrl: "",
|
|
16892
|
+
rpcEndpoint,
|
|
16893
|
+
streamEndpoint,
|
|
16894
|
+
csrfToken,
|
|
16895
|
+
timeout: options?.timeout ?? 12e4
|
|
16896
|
+
};
|
|
16897
|
+
}, [options?.timeout]);
|
|
16898
|
+
}
|
|
16899
|
+
var SESSION_PATH_REGEX = /\/session\/([^/]+)/;
|
|
16900
|
+
function useBichatRouter({
|
|
16901
|
+
navigate,
|
|
16902
|
+
pathname,
|
|
16903
|
+
onNavigate
|
|
16904
|
+
}) {
|
|
16905
|
+
const activeSessionId = React.useMemo(
|
|
16906
|
+
() => pathname.match(SESSION_PATH_REGEX)?.[1],
|
|
16907
|
+
[pathname]
|
|
16908
|
+
);
|
|
16909
|
+
const maybeClose = React.useCallback(() => {
|
|
16910
|
+
onNavigate?.();
|
|
16911
|
+
}, [onNavigate]);
|
|
16912
|
+
const onSessionSelect = React.useCallback(
|
|
16913
|
+
(sessionId) => {
|
|
16914
|
+
if (sessionId) {
|
|
16915
|
+
navigate(`/session/${sessionId}`);
|
|
16916
|
+
} else {
|
|
16917
|
+
navigate("/");
|
|
16918
|
+
}
|
|
16919
|
+
maybeClose();
|
|
16920
|
+
},
|
|
16921
|
+
[navigate, maybeClose]
|
|
16922
|
+
);
|
|
16923
|
+
const onNewChat = React.useCallback(() => {
|
|
16924
|
+
navigate("/");
|
|
16925
|
+
maybeClose();
|
|
16926
|
+
}, [navigate, maybeClose]);
|
|
16927
|
+
const onArchivedView = React.useCallback(() => {
|
|
16928
|
+
navigate("/archived");
|
|
16929
|
+
maybeClose();
|
|
16930
|
+
}, [navigate, maybeClose]);
|
|
16931
|
+
const onBack = React.useCallback(() => {
|
|
16932
|
+
navigate("/");
|
|
16933
|
+
maybeClose();
|
|
16934
|
+
}, [navigate, maybeClose]);
|
|
16935
|
+
return {
|
|
16936
|
+
activeSessionId,
|
|
16937
|
+
onSessionSelect,
|
|
16938
|
+
onNewChat,
|
|
16939
|
+
onArchivedView,
|
|
16940
|
+
onBack
|
|
16941
|
+
};
|
|
16942
|
+
}
|
|
16124
16943
|
|
|
16125
16944
|
// ui/src/bichat/index.ts
|
|
16126
16945
|
init_IotaContext();
|
|
@@ -16424,10 +17243,59 @@ function resolveArtifactName(artifact) {
|
|
|
16424
17243
|
}
|
|
16425
17244
|
return `${label} artifact`;
|
|
16426
17245
|
}
|
|
17246
|
+
function mapSessionUser(rawUser) {
|
|
17247
|
+
if (!isRecord2(rawUser)) {
|
|
17248
|
+
return void 0;
|
|
17249
|
+
}
|
|
17250
|
+
const rawId = rawUser.id;
|
|
17251
|
+
const id = readNonEmptyString(rawId) ?? (typeof rawId === "number" && Number.isFinite(rawId) ? String(rawId) : null);
|
|
17252
|
+
if (!id) {
|
|
17253
|
+
return void 0;
|
|
17254
|
+
}
|
|
17255
|
+
const firstName = readString2(rawUser.firstName);
|
|
17256
|
+
const lastName = readString2(rawUser.lastName);
|
|
17257
|
+
const initials = readNonEmptyString(rawUser.initials) || `${firstName.charAt(0)}${lastName.charAt(0)}`.trim().toUpperCase() || "U";
|
|
17258
|
+
return {
|
|
17259
|
+
id,
|
|
17260
|
+
firstName,
|
|
17261
|
+
lastName,
|
|
17262
|
+
initials
|
|
17263
|
+
};
|
|
17264
|
+
}
|
|
17265
|
+
function mapSessionAccess(rawAccess) {
|
|
17266
|
+
if (!isRecord2(rawAccess)) {
|
|
17267
|
+
return void 0;
|
|
17268
|
+
}
|
|
17269
|
+
const role = readString2(rawAccess.role).toLowerCase();
|
|
17270
|
+
const source = readString2(rawAccess.source).toLowerCase();
|
|
17271
|
+
const normalizedRole = role === "owner" || role === "editor" || role === "viewer" || role === "read_all" ? role : "none";
|
|
17272
|
+
const normalizedSource = source === "owner" || source === "member" || source === "permission" ? source : "none";
|
|
17273
|
+
const canRead = rawAccess.canRead === true || rawAccess.canRead === "true";
|
|
17274
|
+
const canWrite = rawAccess.canWrite === true || rawAccess.canWrite === "true";
|
|
17275
|
+
const canManageMembers = rawAccess.canManageMembers === true || rawAccess.canManageMembers === "true";
|
|
17276
|
+
if (normalizedRole === "none" && normalizedSource === "none" && !canRead && !canWrite && !canManageMembers) {
|
|
17277
|
+
return void 0;
|
|
17278
|
+
}
|
|
17279
|
+
return {
|
|
17280
|
+
role: normalizedRole,
|
|
17281
|
+
source: normalizedSource,
|
|
17282
|
+
canRead,
|
|
17283
|
+
canWrite,
|
|
17284
|
+
canManageMembers
|
|
17285
|
+
};
|
|
17286
|
+
}
|
|
16427
17287
|
function toSession(session) {
|
|
16428
17288
|
return {
|
|
16429
|
-
|
|
16430
|
-
|
|
17289
|
+
id: readString2(session.id),
|
|
17290
|
+
title: readString2(session.title),
|
|
17291
|
+
status: session.status === "archived" ? "archived" : "active",
|
|
17292
|
+
pinned: Boolean(session.pinned),
|
|
17293
|
+
createdAt: readString2(session.createdAt),
|
|
17294
|
+
updatedAt: readString2(session.updatedAt),
|
|
17295
|
+
owner: mapSessionUser(session.owner),
|
|
17296
|
+
isGroup: Boolean(session.isGroup),
|
|
17297
|
+
memberCount: typeof session.memberCount === "number" ? session.memberCount : void 0,
|
|
17298
|
+
access: mapSessionAccess(session.access)
|
|
16431
17299
|
};
|
|
16432
17300
|
}
|
|
16433
17301
|
function toSessionArtifact(artifact) {
|
|
@@ -16701,6 +17569,7 @@ function sanitizeConversationTurn(rawTurn, index, fallbackSessionID) {
|
|
|
16701
17569
|
id: userTurnID,
|
|
16702
17570
|
content: readString2(rawTurn.userTurn.content),
|
|
16703
17571
|
attachments: sanitizeUserAttachments(rawTurn.userTurn.attachments, turnID),
|
|
17572
|
+
author: mapSessionUser(rawTurn.userTurn.author),
|
|
16704
17573
|
createdAt: readString2(rawTurn.userTurn.createdAt, createdAt)
|
|
16705
17574
|
},
|
|
16706
17575
|
assistantTurn: sanitizeAssistantTurn(rawTurn.assistantTurn, createdAt, turnID),
|
|
@@ -17193,6 +18062,68 @@ async function clearSessionHistory(callRPC, sessionId) {
|
|
|
17193
18062
|
async function compactSessionHistory(callRPC, sessionId) {
|
|
17194
18063
|
return callRPC("bichat.session.compact", { id: sessionId });
|
|
17195
18064
|
}
|
|
18065
|
+
async function listUsers(callRPC) {
|
|
18066
|
+
const data = await callRPC("bichat.user.list", {});
|
|
18067
|
+
return data.users.map((user) => ({
|
|
18068
|
+
id: String(user.id),
|
|
18069
|
+
firstName: user.firstName || "",
|
|
18070
|
+
lastName: user.lastName || "",
|
|
18071
|
+
initials: user.initials || ""
|
|
18072
|
+
}));
|
|
18073
|
+
}
|
|
18074
|
+
async function listAllSessions(callRPC, options) {
|
|
18075
|
+
const data = await callRPC("bichat.session.listAll", {
|
|
18076
|
+
limit: options?.limit ?? 50,
|
|
18077
|
+
offset: options?.offset ?? 0,
|
|
18078
|
+
includeArchived: options?.includeArchived ?? false,
|
|
18079
|
+
userId: options?.userId ?? null
|
|
18080
|
+
});
|
|
18081
|
+
return {
|
|
18082
|
+
sessions: data.sessions.map(toSession),
|
|
18083
|
+
total: typeof data.total === "number" ? data.total : data.sessions.length,
|
|
18084
|
+
hasMore: Boolean(data.hasMore)
|
|
18085
|
+
};
|
|
18086
|
+
}
|
|
18087
|
+
async function listSessionMembers(callRPC, sessionId) {
|
|
18088
|
+
const data = await callRPC("bichat.session.members.list", { sessionId });
|
|
18089
|
+
return data.members.map((member) => ({
|
|
18090
|
+
user: {
|
|
18091
|
+
id: String(member.user.id),
|
|
18092
|
+
firstName: member.user.firstName,
|
|
18093
|
+
lastName: member.user.lastName,
|
|
18094
|
+
initials: member.user.initials
|
|
18095
|
+
},
|
|
18096
|
+
role: (() => {
|
|
18097
|
+
const normalizedRole = (member.role || "").toLowerCase();
|
|
18098
|
+
if (normalizedRole === "owner") {
|
|
18099
|
+
return "owner";
|
|
18100
|
+
}
|
|
18101
|
+
if (normalizedRole === "editor") {
|
|
18102
|
+
return "editor";
|
|
18103
|
+
}
|
|
18104
|
+
return "viewer";
|
|
18105
|
+
})(),
|
|
18106
|
+
createdAt: member.createdAt,
|
|
18107
|
+
updatedAt: member.updatedAt
|
|
18108
|
+
}));
|
|
18109
|
+
}
|
|
18110
|
+
async function addSessionMember(callRPC, sessionId, userId, role) {
|
|
18111
|
+
await callRPC("bichat.session.members.add", {
|
|
18112
|
+
sessionId,
|
|
18113
|
+
userId,
|
|
18114
|
+
role: role.toUpperCase()
|
|
18115
|
+
});
|
|
18116
|
+
}
|
|
18117
|
+
async function updateSessionMemberRole(callRPC, sessionId, userId, role) {
|
|
18118
|
+
await callRPC("bichat.session.members.updateRole", {
|
|
18119
|
+
sessionId,
|
|
18120
|
+
userId,
|
|
18121
|
+
role: role.toUpperCase()
|
|
18122
|
+
});
|
|
18123
|
+
}
|
|
18124
|
+
async function removeSessionMember(callRPC, sessionId, userId) {
|
|
18125
|
+
await callRPC("bichat.session.members.remove", { sessionId, userId });
|
|
18126
|
+
}
|
|
17196
18127
|
|
|
17197
18128
|
// ui/src/bichat/utils/sseParser.ts
|
|
17198
18129
|
function* processDataLines(lines) {
|
|
@@ -17805,7 +18736,12 @@ async function uploadSessionArtifacts(callRPC, sessionId, files, uploadFileFn) {
|
|
|
17805
18736
|
const data = await callRPC("bichat.session.uploadArtifacts", {
|
|
17806
18737
|
sessionId,
|
|
17807
18738
|
attachments: uploads.map((upload) => ({
|
|
17808
|
-
|
|
18739
|
+
id: String(upload.id),
|
|
18740
|
+
filename: upload.name,
|
|
18741
|
+
uploadId: upload.id,
|
|
18742
|
+
mimeType: upload.mimetype || "application/octet-stream",
|
|
18743
|
+
sizeBytes: upload.size,
|
|
18744
|
+
url: upload.url
|
|
17809
18745
|
}))
|
|
17810
18746
|
});
|
|
17811
18747
|
return {
|
|
@@ -17932,6 +18868,24 @@ var HttpDataSource = class {
|
|
|
17932
18868
|
async compactSessionHistory(sessionId) {
|
|
17933
18869
|
return compactSessionHistory(this.boundCallRPC, sessionId);
|
|
17934
18870
|
}
|
|
18871
|
+
async listUsers() {
|
|
18872
|
+
return listUsers(this.boundCallRPC);
|
|
18873
|
+
}
|
|
18874
|
+
async listAllSessions(options) {
|
|
18875
|
+
return listAllSessions(this.boundCallRPC, options);
|
|
18876
|
+
}
|
|
18877
|
+
async listSessionMembers(sessionId) {
|
|
18878
|
+
return listSessionMembers(this.boundCallRPC, sessionId);
|
|
18879
|
+
}
|
|
18880
|
+
async addSessionMember(sessionId, userId, role) {
|
|
18881
|
+
return addSessionMember(this.boundCallRPC, sessionId, userId, role);
|
|
18882
|
+
}
|
|
18883
|
+
async updateSessionMemberRole(sessionId, userId, role) {
|
|
18884
|
+
return updateSessionMemberRole(this.boundCallRPC, sessionId, userId, role);
|
|
18885
|
+
}
|
|
18886
|
+
async removeSessionMember(sessionId, userId) {
|
|
18887
|
+
return removeSessionMember(this.boundCallRPC, sessionId, userId);
|
|
18888
|
+
}
|
|
17935
18889
|
// -------------------------------------------------------------------------
|
|
17936
18890
|
// Message transport (delegates to MessageTransport)
|
|
17937
18891
|
// -------------------------------------------------------------------------
|
|
@@ -18067,6 +19021,7 @@ exports.AttachmentGrid = MemoizedAttachmentGrid;
|
|
|
18067
19021
|
exports.AttachmentPreview = AttachmentPreview_default;
|
|
18068
19022
|
exports.AttachmentUpload = AttachmentUpload_default;
|
|
18069
19023
|
exports.Avatar = Avatar;
|
|
19024
|
+
exports.AvatarStack = AvatarStack;
|
|
18070
19025
|
exports.BiChatLayout = BiChatLayout;
|
|
18071
19026
|
exports.Bubble = Bubble;
|
|
18072
19027
|
exports.CHART_VISUAL = CHART_VISUAL;
|
|
@@ -18110,6 +19065,7 @@ exports.SessionArtifactList = SessionArtifactList;
|
|
|
18110
19065
|
exports.SessionArtifactPreview = SessionArtifactPreview;
|
|
18111
19066
|
exports.SessionArtifactsPanel = SessionArtifactsPanel;
|
|
18112
19067
|
exports.SessionItem = SessionItem_default;
|
|
19068
|
+
exports.SessionMembersModal = SessionMembersModal;
|
|
18113
19069
|
exports.SessionSkeleton = SessionSkeleton;
|
|
18114
19070
|
exports.Sidebar = Sidebar2;
|
|
18115
19071
|
exports.Skeleton = MemoizedSkeleton;
|
|
@@ -18176,6 +19132,7 @@ exports.useActionButtonContext = useActionButtonContext;
|
|
|
18176
19132
|
exports.useAttachments = useAttachments;
|
|
18177
19133
|
exports.useAutoScroll = useAutoScroll;
|
|
18178
19134
|
exports.useAvatarContext = useAvatarContext;
|
|
19135
|
+
exports.useBichatRouter = useBichatRouter;
|
|
18179
19136
|
exports.useBubbleContext = useBubbleContext;
|
|
18180
19137
|
exports.useChatInput = useChatInput;
|
|
18181
19138
|
exports.useChatMessaging = useChatMessaging;
|
|
@@ -18183,6 +19140,7 @@ exports.useChatSession = useChatSession;
|
|
|
18183
19140
|
exports.useConfig = useConfig;
|
|
18184
19141
|
exports.useDataTable = useDataTable;
|
|
18185
19142
|
exports.useFocusTrap = useFocusTrap;
|
|
19143
|
+
exports.useHttpDataSourceConfigFromApplet = useHttpDataSourceConfigFromApplet;
|
|
18186
19144
|
exports.useImageGallery = useImageGallery;
|
|
18187
19145
|
exports.useIotaContext = useIotaContext;
|
|
18188
19146
|
exports.useKeyboardShortcuts = useKeyboardShortcuts;
|