@iota-uz/sdk 0.4.16 → 0.4.19
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/bichat/index.cjs +524 -76
- package/dist/bichat/index.cjs.map +1 -1
- package/dist/bichat/index.d.cts +15 -6
- package/dist/bichat/index.d.ts +15 -6
- package/dist/bichat/index.mjs +526 -78
- package/dist/bichat/index.mjs.map +1 -1
- package/package.json +1 -1
- package/tailwind/compiled.css +1 -1
package/dist/bichat/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import React, { createContext, lazy, memo, forwardRef, useState, useRef, useMemo
|
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import ReactApexChart from 'react-apexcharts';
|
|
4
4
|
import ApexCharts from 'apexcharts';
|
|
5
|
-
import { X, Bug, ArrowUp, ArrowDown, Stack, Paperclip, PaperPlaneRight, CircleNotch, ArrowUUpLeft, PencilSimple, Check, Bookmark, ArrowsClockwise, Archive, Trash, DotsThree, Warning, ArrowClockwise, Image, ArrowCounterClockwise, ImageBroken, CaretLeft, CaretRight, Info, CheckCircle, XCircle, Spinner, MagnifyingGlass, WarningCircle, CaretDown, Copy, FilePdf, FileXls, FileCsv, FileDoc, FileCode, FileText, File, ChartBar, DownloadSimple, Download, ChatCircleDots, PencilSimpleLine, ArrowLeft, PaperPlaneTilt, ArrowRight, Timer, Lightning, Database, Wrench, ClockCounterClockwise, Lightbulb, Package, Plus, ArrowsCounterClockwise, Gear, Users, List, CaretLineLeft, CaretLineRight, Code, ArrowSquareOut, SpinnerGap, FloppyDisk, Sidebar } from '@phosphor-icons/react';
|
|
5
|
+
import { X, Bug, ArrowUp, ArrowDown, Stack, Paperclip, PaperPlaneRight, CircleNotch, ArrowUUpLeft, PencilSimple, Check, Bookmark, ArrowsClockwise, Archive, Trash, DotsThree, Warning, ArrowClockwise, Image, ArrowCounterClockwise, ImageBroken, CaretLeft, CaretRight, Info, CheckCircle, XCircle, Spinner, MagnifyingGlass, WarningCircle, CaretDown, Copy, FilePdf, FileXls, FileCsv, FileDoc, FileCode, FileText, File as File$1, ChartBar, DownloadSimple, Download, ChatCircleDots, PencilSimpleLine, ArrowLeft, PaperPlaneTilt, ArrowRight, Timer, Lightning, Database, Wrench, ClockCounterClockwise, Lightbulb, Package, Plus, ArrowsCounterClockwise, Gear, Users, List, CaretLineLeft, CaretLineRight, Code, ArrowSquareOut, SpinnerGap, FloppyDisk, Sidebar } from '@phosphor-icons/react';
|
|
6
6
|
import { Prism } from 'react-syntax-highlighter';
|
|
7
7
|
import { vscDarkPlus, vs } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
|
8
8
|
import ReactMarkdown from 'react-markdown';
|
|
@@ -54,14 +54,15 @@ function useTranslation() {
|
|
|
54
54
|
const { translations, language } = locale;
|
|
55
55
|
const t = useCallback(
|
|
56
56
|
(key2, params) => {
|
|
57
|
-
|
|
57
|
+
const raw = translations[key2];
|
|
58
|
+
let text = typeof raw === "string" && raw.trim() ? raw : key2;
|
|
58
59
|
if (params) {
|
|
59
60
|
Object.keys(params).forEach((paramKey) => {
|
|
60
61
|
const value = params[paramKey];
|
|
61
62
|
text = text.replace(new RegExp(`{{${paramKey}}}`, "g"), String(value));
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
|
-
return text;
|
|
65
|
+
return text.trim() ? text : key2;
|
|
65
66
|
},
|
|
66
67
|
[translations]
|
|
67
68
|
);
|
|
@@ -1507,6 +1508,10 @@ var ChatMachine = class {
|
|
|
1507
1508
|
}
|
|
1508
1509
|
/** Sets turns from fetch, preserving pending user-only turns if server hasn't caught up. */
|
|
1509
1510
|
_setTurnsFromFetch(fetchedTurns) {
|
|
1511
|
+
if (!Array.isArray(fetchedTurns)) {
|
|
1512
|
+
console.warn("[ChatMachine] Ignoring malformed turns payload from fetchSession");
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1510
1515
|
const prev = this.state.messaging.turns;
|
|
1511
1516
|
const hasPendingUserOnly = prev.length > 0 && !prev[prev.length - 1].assistantTurn;
|
|
1512
1517
|
if (hasPendingUserOnly && (!fetchedTurns || fetchedTurns.length === 0)) {
|
|
@@ -1896,6 +1901,7 @@ var ChatMachine = class {
|
|
|
1896
1901
|
const curSessionId = this.state.session.currentSessionId;
|
|
1897
1902
|
const curPendingQuestion = this.state.messaging.pendingQuestion;
|
|
1898
1903
|
if (!curSessionId || !curPendingQuestion) return;
|
|
1904
|
+
const previousTurns = this.state.messaging.turns;
|
|
1899
1905
|
this._updateMessaging({ loading: true });
|
|
1900
1906
|
this._updateSession({ error: null, errorRetryable: false });
|
|
1901
1907
|
const previousPendingQuestion = curPendingQuestion;
|
|
@@ -1913,19 +1919,28 @@ var ChatMachine = class {
|
|
|
1913
1919
|
const fetchResult = await this.dataSource.fetchSession(curSessionId);
|
|
1914
1920
|
if (this.disposed) return;
|
|
1915
1921
|
if (fetchResult) {
|
|
1916
|
-
this.
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1922
|
+
this._updateSession({ session: fetchResult.session });
|
|
1923
|
+
this._updateMessaging({ pendingQuestion: fetchResult.pendingQuestion || null });
|
|
1924
|
+
const hasMalformedRefresh = previousTurns.length > 0 && Array.isArray(fetchResult.turns) && fetchResult.turns.length === 0;
|
|
1925
|
+
if (hasMalformedRefresh) {
|
|
1926
|
+
console.warn("[ChatMachine] Preserving previous turns due to empty post-HITL refetch payload", {
|
|
1927
|
+
sessionId: curSessionId,
|
|
1928
|
+
previousTurnCount: previousTurns.length
|
|
1929
|
+
});
|
|
1930
|
+
this._updateSession({
|
|
1931
|
+
error: "Failed to fully refresh session. Showing last known messages.",
|
|
1932
|
+
errorRetryable: true
|
|
1933
|
+
});
|
|
1934
|
+
} else {
|
|
1935
|
+
this._setTurnsFromFetch(fetchResult.turns);
|
|
1936
|
+
}
|
|
1920
1937
|
} else {
|
|
1921
|
-
this.
|
|
1922
|
-
this._updateSession({ error: "Failed to load updated session", errorRetryable: false });
|
|
1938
|
+
this._updateSession({ error: "Failed to load updated session", errorRetryable: true });
|
|
1923
1939
|
}
|
|
1924
1940
|
} catch (fetchErr) {
|
|
1925
1941
|
if (this.disposed) return;
|
|
1926
|
-
this._updateMessaging({ pendingQuestion: previousPendingQuestion });
|
|
1927
1942
|
const normalized = normalizeRPCError(fetchErr, "Failed to load updated session");
|
|
1928
|
-
this._updateSession({ error: normalized.userMessage, errorRetryable:
|
|
1943
|
+
this._updateSession({ error: normalized.userMessage, errorRetryable: true });
|
|
1929
1944
|
}
|
|
1930
1945
|
}
|
|
1931
1946
|
} else {
|
|
@@ -2447,7 +2462,7 @@ function getFileVisual(mimeType, filename) {
|
|
|
2447
2462
|
};
|
|
2448
2463
|
}
|
|
2449
2464
|
return {
|
|
2450
|
-
icon: File,
|
|
2465
|
+
icon: File$1,
|
|
2451
2466
|
iconColor: "text-gray-400 dark:text-gray-500",
|
|
2452
2467
|
bgColor: "bg-gray-100 dark:bg-gray-800",
|
|
2453
2468
|
label: (mime.split("/")[1] || "FILE").toUpperCase().slice(0, 4)
|
|
@@ -3285,7 +3300,7 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
3285
3300
|
const [currentStep, setCurrentStep] = useState(0);
|
|
3286
3301
|
const [answers, setAnswers] = useState({});
|
|
3287
3302
|
const [otherTexts, setOtherTexts] = useState({});
|
|
3288
|
-
const questions = pendingQuestion.questions;
|
|
3303
|
+
const questions = Array.isArray(pendingQuestion.questions) ? pendingQuestion.questions : [];
|
|
3289
3304
|
const currentQuestion = questions[currentStep];
|
|
3290
3305
|
const isLastStep = currentStep === questions.length - 1;
|
|
3291
3306
|
const isFirstStep = currentStep === 0;
|
|
@@ -3379,9 +3394,31 @@ function InlineQuestionForm({ pendingQuestion }) {
|
|
|
3379
3394
|
e.preventDefault();
|
|
3380
3395
|
handleNext();
|
|
3381
3396
|
};
|
|
3382
|
-
if (!currentQuestion)
|
|
3397
|
+
if (!currentQuestion) {
|
|
3398
|
+
return /* @__PURE__ */ jsxs("div", { className: "animate-slide-up rounded-2xl border border-amber-200 dark:border-amber-700/50 bg-gradient-to-b from-amber-50/70 to-white dark:from-amber-950/20 dark:to-gray-900/80 shadow-sm overflow-hidden p-4", children: [
|
|
3399
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-800 dark:text-gray-200", children: t("BiChat.Error.SomethingWentWrong") }),
|
|
3400
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-gray-500 dark:text-gray-400", children: t("BiChat.Error.UnexpectedError") }),
|
|
3401
|
+
/* @__PURE__ */ jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxs(
|
|
3402
|
+
"button",
|
|
3403
|
+
{
|
|
3404
|
+
type: "button",
|
|
3405
|
+
onClick: handleRejectPendingQuestion,
|
|
3406
|
+
disabled: loading,
|
|
3407
|
+
className: "cursor-pointer inline-flex items-center gap-1.5 px-3 py-1.5 text-sm rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 disabled:opacity-40",
|
|
3408
|
+
children: [
|
|
3409
|
+
/* @__PURE__ */ jsx(X, { size: 14, weight: "bold" }),
|
|
3410
|
+
t("BiChat.InlineQuestion.Dismiss")
|
|
3411
|
+
]
|
|
3412
|
+
}
|
|
3413
|
+
) })
|
|
3414
|
+
] });
|
|
3415
|
+
}
|
|
3383
3416
|
const isMultiSelect = currentQuestion.type === "MULTIPLE_CHOICE";
|
|
3384
|
-
const options = currentQuestion.options || []
|
|
3417
|
+
const options = (currentQuestion.options || []).filter((option) => Boolean(option && typeof option.label === "string")).map((option, index) => ({
|
|
3418
|
+
id: option.id || `${currentQuestion.id}-option-${index}`,
|
|
3419
|
+
label: option.label,
|
|
3420
|
+
value: option.value || option.label
|
|
3421
|
+
}));
|
|
3385
3422
|
const isOtherSelected = currentAnswer?.customText !== void 0;
|
|
3386
3423
|
const canProceed = isCurrentAnswerValid();
|
|
3387
3424
|
return /* @__PURE__ */ jsx("div", { className: "animate-slide-up rounded-2xl border border-gray-200 dark:border-gray-700/50 bg-gradient-to-b from-primary-50/80 to-white dark:from-primary-950/30 dark:to-gray-900/80 shadow-sm overflow-hidden", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
|
|
@@ -4295,7 +4332,8 @@ function TurnBubble({
|
|
|
4295
4332
|
userTurn: classNames?.userTurn ?? defaultClassNames3.userTurn,
|
|
4296
4333
|
assistantTurn: classNames?.assistantTurn ?? defaultClassNames3.assistantTurn
|
|
4297
4334
|
};
|
|
4298
|
-
const
|
|
4335
|
+
const userContent = typeof turn.userTurn?.content === "string" ? turn.userTurn.content : "";
|
|
4336
|
+
const isSystemSummaryTurn = userContent.trim() === "" && turn.assistantTurn?.role === "system";
|
|
4299
4337
|
return /* @__PURE__ */ jsxs("div", { className: classes.root, "data-turn-id": turn.id, children: [
|
|
4300
4338
|
!isSystemSummaryTurn && /* @__PURE__ */ jsx("div", { className: classes.userTurn, children: renderUserTurn ? renderUserTurn(turn) : /* @__PURE__ */ jsx(
|
|
4301
4339
|
UserTurnView,
|
|
@@ -6062,6 +6100,8 @@ function WarningBox({ message }) {
|
|
|
6062
6100
|
}
|
|
6063
6101
|
function ArtifactActions({ url }) {
|
|
6064
6102
|
const { t } = useTranslation();
|
|
6103
|
+
const openLabel = t("BiChat.Artifacts.OpenInNewTab");
|
|
6104
|
+
const downloadLabel = t("BiChat.Artifacts.Download");
|
|
6065
6105
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6066
6106
|
/* @__PURE__ */ jsxs(
|
|
6067
6107
|
"a",
|
|
@@ -6072,7 +6112,7 @@ function ArtifactActions({ url }) {
|
|
|
6072
6112
|
className: "inline-flex items-center gap-2 rounded-lg border border-gray-200 px-3 py-1.5 text-xs font-medium text-gray-700 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-800",
|
|
6073
6113
|
children: [
|
|
6074
6114
|
/* @__PURE__ */ jsx(ArrowSquareOut, { className: "h-3.5 w-3.5", weight: "bold" }),
|
|
6075
|
-
|
|
6115
|
+
openLabel
|
|
6076
6116
|
]
|
|
6077
6117
|
}
|
|
6078
6118
|
),
|
|
@@ -6086,7 +6126,7 @@ function ArtifactActions({ url }) {
|
|
|
6086
6126
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary-600 px-3 py-1.5 text-xs font-medium text-white shadow-sm transition-colors hover:bg-primary-700",
|
|
6087
6127
|
children: [
|
|
6088
6128
|
/* @__PURE__ */ jsx(DownloadSimple, { className: "h-3.5 w-3.5", weight: "bold" }),
|
|
6089
|
-
|
|
6129
|
+
downloadLabel
|
|
6090
6130
|
]
|
|
6091
6131
|
}
|
|
6092
6132
|
)
|
|
@@ -7406,6 +7446,7 @@ var EditableText = forwardRef(
|
|
|
7406
7446
|
setIsEditing(false);
|
|
7407
7447
|
};
|
|
7408
7448
|
const handleKeyDown = (e) => {
|
|
7449
|
+
e.stopPropagation();
|
|
7409
7450
|
if (e.key === "Enter") {
|
|
7410
7451
|
e.preventDefault();
|
|
7411
7452
|
handleSave();
|
|
@@ -7439,6 +7480,7 @@ var EditableText = forwardRef(
|
|
|
7439
7480
|
value: editValue,
|
|
7440
7481
|
onChange: (e) => setEditValue(e.target.value),
|
|
7441
7482
|
onKeyDown: handleKeyDown,
|
|
7483
|
+
onKeyUp: (e) => e.stopPropagation(),
|
|
7442
7484
|
onBlur: handleBlur,
|
|
7443
7485
|
maxLength,
|
|
7444
7486
|
placeholder: resolvedPlaceholder,
|
|
@@ -8069,12 +8111,63 @@ function DefaultErrorContent({
|
|
|
8069
8111
|
] })
|
|
8070
8112
|
] });
|
|
8071
8113
|
}
|
|
8114
|
+
function StaticEmergencyErrorContent({
|
|
8115
|
+
error,
|
|
8116
|
+
onReset
|
|
8117
|
+
}) {
|
|
8118
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-col items-center justify-center p-8 text-center min-h-[200px]", children: /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col items-center", children: [
|
|
8119
|
+
/* @__PURE__ */ jsxs("div", { className: "relative mb-5", children: [
|
|
8120
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 rounded-full bg-red-100 scale-150 blur-md" }),
|
|
8121
|
+
/* @__PURE__ */ jsx("div", { className: "relative flex items-center justify-center w-14 h-14 rounded-full bg-red-50 border border-red-200/60", children: /* @__PURE__ */ jsx(WarningCircle, { size: 28, className: "text-red-500", weight: "fill" }) })
|
|
8122
|
+
] }),
|
|
8123
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-900 mb-1.5", children: "Something went wrong" }),
|
|
8124
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mb-5 max-w-md leading-relaxed", children: error?.message || "An unexpected UI error occurred." }),
|
|
8125
|
+
onReset && /* @__PURE__ */ jsxs(
|
|
8126
|
+
"button",
|
|
8127
|
+
{
|
|
8128
|
+
type: "button",
|
|
8129
|
+
onClick: onReset,
|
|
8130
|
+
className: "flex items-center gap-2 px-5 py-2.5 bg-red-600 hover:bg-red-700 active:bg-red-800 text-white rounded-lg transition-colors shadow-sm text-sm font-medium",
|
|
8131
|
+
children: [
|
|
8132
|
+
/* @__PURE__ */ jsx(ArrowClockwise, { size: 16, weight: "bold" }),
|
|
8133
|
+
"Try again"
|
|
8134
|
+
]
|
|
8135
|
+
}
|
|
8136
|
+
)
|
|
8137
|
+
] }) });
|
|
8138
|
+
}
|
|
8139
|
+
var FallbackGuard = class extends Component {
|
|
8140
|
+
constructor(props) {
|
|
8141
|
+
super(props);
|
|
8142
|
+
this.state = { fallbackFailed: false };
|
|
8143
|
+
}
|
|
8144
|
+
static getDerivedStateFromError() {
|
|
8145
|
+
return { fallbackFailed: true };
|
|
8146
|
+
}
|
|
8147
|
+
componentDidCatch(error, errorInfo) {
|
|
8148
|
+
this.props.onFallbackError?.(error, errorInfo);
|
|
8149
|
+
}
|
|
8150
|
+
render() {
|
|
8151
|
+
if (this.state.fallbackFailed) {
|
|
8152
|
+
return /* @__PURE__ */ jsx(StaticEmergencyErrorContent, { error: this.props.primaryError, onReset: this.props.onReset });
|
|
8153
|
+
}
|
|
8154
|
+
return this.props.renderFallback();
|
|
8155
|
+
}
|
|
8156
|
+
};
|
|
8072
8157
|
var ErrorBoundary = class extends Component {
|
|
8073
8158
|
constructor(props) {
|
|
8074
8159
|
super(props);
|
|
8075
8160
|
this.handleReset = () => {
|
|
8076
8161
|
this.setState({ hasError: false, error: null });
|
|
8077
8162
|
};
|
|
8163
|
+
this.handleFallbackError = (error, errorInfo) => {
|
|
8164
|
+
console.error("React Error Boundary fallback crashed:", {
|
|
8165
|
+
primaryError: this.state.error,
|
|
8166
|
+
fallbackError: error,
|
|
8167
|
+
errorInfo
|
|
8168
|
+
});
|
|
8169
|
+
this.props.onError?.(error, errorInfo);
|
|
8170
|
+
};
|
|
8078
8171
|
this.state = { hasError: false, error: null };
|
|
8079
8172
|
}
|
|
8080
8173
|
static getDerivedStateFromError(error) {
|
|
@@ -8086,13 +8179,24 @@ var ErrorBoundary = class extends Component {
|
|
|
8086
8179
|
}
|
|
8087
8180
|
render() {
|
|
8088
8181
|
if (this.state.hasError) {
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8182
|
+
return /* @__PURE__ */ jsx(
|
|
8183
|
+
FallbackGuard,
|
|
8184
|
+
{
|
|
8185
|
+
primaryError: this.state.error,
|
|
8186
|
+
onReset: this.handleReset,
|
|
8187
|
+
onFallbackError: this.handleFallbackError,
|
|
8188
|
+
renderFallback: () => {
|
|
8189
|
+
if (this.props.fallback) {
|
|
8190
|
+
if (typeof this.props.fallback === "function") {
|
|
8191
|
+
return this.props.fallback(this.state.error, this.handleReset);
|
|
8192
|
+
}
|
|
8193
|
+
return this.props.fallback;
|
|
8194
|
+
}
|
|
8195
|
+
return /* @__PURE__ */ jsx(DefaultErrorContent, { error: this.state.error, onReset: this.handleReset });
|
|
8196
|
+
}
|
|
8197
|
+
},
|
|
8198
|
+
`${this.state.error?.name ?? "Error"}:${this.state.error?.message ?? ""}`
|
|
8199
|
+
);
|
|
8096
8200
|
}
|
|
8097
8201
|
return this.props.children;
|
|
8098
8202
|
}
|
|
@@ -8485,6 +8589,9 @@ var SessionItem = memo(
|
|
|
8485
8589
|
onSelect(session.id);
|
|
8486
8590
|
},
|
|
8487
8591
|
onKeyDown: (e) => {
|
|
8592
|
+
const target = e.target;
|
|
8593
|
+
const isFromEditable = !!target?.closest('input, textarea, [contenteditable="true"]');
|
|
8594
|
+
if (isFromEditable) return;
|
|
8488
8595
|
if (e.key === "Enter" || e.key === " ") {
|
|
8489
8596
|
e.preventDefault();
|
|
8490
8597
|
onSelect(session.id);
|
|
@@ -9243,6 +9350,15 @@ function Sidebar2({
|
|
|
9243
9350
|
useEffect(() => {
|
|
9244
9351
|
fetchSessions();
|
|
9245
9352
|
}, [fetchSessions, refreshKey]);
|
|
9353
|
+
useEffect(() => {
|
|
9354
|
+
const handleSessionsUpdated = () => {
|
|
9355
|
+
setRefreshKey((k) => k + 1);
|
|
9356
|
+
};
|
|
9357
|
+
window.addEventListener("bichat:sessions-updated", handleSessionsUpdated);
|
|
9358
|
+
return () => {
|
|
9359
|
+
window.removeEventListener("bichat:sessions-updated", handleSessionsUpdated);
|
|
9360
|
+
};
|
|
9361
|
+
}, []);
|
|
9246
9362
|
useEffect(() => {
|
|
9247
9363
|
if (!activeSessionId) {
|
|
9248
9364
|
refreshForActiveSessionRef.current = null;
|
|
@@ -9617,13 +9733,14 @@ function Sidebar2({
|
|
|
9617
9733
|
anchor: "top start",
|
|
9618
9734
|
className: "w-48 bg-white/95 dark:bg-gray-900/95 backdrop-blur-lg rounded-xl shadow-lg border border-gray-200/80 dark:border-gray-700/60 z-30 [--anchor-gap:8px] mb-1 p-1.5",
|
|
9619
9735
|
children: [
|
|
9620
|
-
onArchivedView && /* @__PURE__ */ jsx(MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxs(
|
|
9736
|
+
onArchivedView && /* @__PURE__ */ jsx(MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxs(
|
|
9621
9737
|
"button",
|
|
9622
9738
|
{
|
|
9623
9739
|
onClick: (e) => {
|
|
9624
9740
|
e.preventDefault();
|
|
9625
9741
|
e.stopPropagation();
|
|
9626
9742
|
onArchivedView();
|
|
9743
|
+
close();
|
|
9627
9744
|
},
|
|
9628
9745
|
className: `cursor-pointer flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-[13px] text-gray-600 dark:text-gray-300 transition-colors ${focus ? "bg-gray-100 dark:bg-gray-800/70" : ""}`,
|
|
9629
9746
|
"aria-label": t("BiChat.Sidebar.ArchivedChats"),
|
|
@@ -9633,13 +9750,14 @@ function Sidebar2({
|
|
|
9633
9750
|
]
|
|
9634
9751
|
}
|
|
9635
9752
|
) }),
|
|
9636
|
-
showAllChatsTab && activeTab !== "all-chats" && /* @__PURE__ */ jsx(MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxs(
|
|
9753
|
+
showAllChatsTab && activeTab !== "all-chats" && /* @__PURE__ */ jsx(MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxs(
|
|
9637
9754
|
"button",
|
|
9638
9755
|
{
|
|
9639
9756
|
onClick: (e) => {
|
|
9640
9757
|
e.preventDefault();
|
|
9641
9758
|
e.stopPropagation();
|
|
9642
9759
|
setActiveTab("all-chats");
|
|
9760
|
+
close();
|
|
9643
9761
|
},
|
|
9644
9762
|
className: `cursor-pointer flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-[13px] text-gray-600 dark:text-gray-300 transition-colors ${focus ? "bg-gray-100 dark:bg-gray-800/70" : ""}`,
|
|
9645
9763
|
"aria-label": t("BiChat.Sidebar.AllChats"),
|
|
@@ -9649,13 +9767,14 @@ function Sidebar2({
|
|
|
9649
9767
|
]
|
|
9650
9768
|
}
|
|
9651
9769
|
) }),
|
|
9652
|
-
showAllChatsTab && activeTab === "all-chats" && /* @__PURE__ */ jsx(MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxs(
|
|
9770
|
+
showAllChatsTab && activeTab === "all-chats" && /* @__PURE__ */ jsx(MenuItem, { children: ({ focus, close }) => /* @__PURE__ */ jsxs(
|
|
9653
9771
|
"button",
|
|
9654
9772
|
{
|
|
9655
9773
|
onClick: (e) => {
|
|
9656
9774
|
e.preventDefault();
|
|
9657
9775
|
e.stopPropagation();
|
|
9658
9776
|
setActiveTab("my-chats");
|
|
9777
|
+
close();
|
|
9659
9778
|
},
|
|
9660
9779
|
className: `cursor-pointer flex w-full items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-[13px] text-gray-600 dark:text-gray-300 transition-colors ${focus ? "bg-gray-100 dark:bg-gray-800/70" : ""}`,
|
|
9661
9780
|
"aria-label": t("BiChat.Sidebar.MyChats"),
|
|
@@ -9770,7 +9889,11 @@ function ArchivedChatList({
|
|
|
9770
9889
|
const confirmRestore = async () => {
|
|
9771
9890
|
if (!sessionToRestore) return;
|
|
9772
9891
|
try {
|
|
9773
|
-
|
|
9892
|
+
const restoredSessionID = sessionToRestore;
|
|
9893
|
+
await dataSource.unarchiveSession(restoredSessionID);
|
|
9894
|
+
window.dispatchEvent(new CustomEvent("bichat:sessions-updated", {
|
|
9895
|
+
detail: { reason: "restored", sessionId: restoredSessionID }
|
|
9896
|
+
}));
|
|
9774
9897
|
setRefreshKey((k) => k + 1);
|
|
9775
9898
|
toast.success(t("BiChat.Archived.ChatRestoredSuccessfully"));
|
|
9776
9899
|
} catch (err) {
|
|
@@ -12032,6 +12155,7 @@ function toSessionArtifact(artifact) {
|
|
|
12032
12155
|
id: artifact.id,
|
|
12033
12156
|
sessionId: artifact.sessionId,
|
|
12034
12157
|
messageId: artifact.messageId,
|
|
12158
|
+
uploadId: artifact.uploadId,
|
|
12035
12159
|
type: artifact.type,
|
|
12036
12160
|
name: artifact.name,
|
|
12037
12161
|
description: artifact.description,
|
|
@@ -12042,21 +12166,272 @@ function toSessionArtifact(artifact) {
|
|
|
12042
12166
|
createdAt: artifact.createdAt
|
|
12043
12167
|
};
|
|
12044
12168
|
}
|
|
12045
|
-
function
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12169
|
+
function warnMalformedSessionPayload(message, details) {
|
|
12170
|
+
console.warn(`[BiChat] ${message}`, details || {});
|
|
12171
|
+
}
|
|
12172
|
+
function readString(value, fallback = "") {
|
|
12173
|
+
return typeof value === "string" ? value : fallback;
|
|
12174
|
+
}
|
|
12175
|
+
function readNonEmptyString(value) {
|
|
12176
|
+
if (typeof value !== "string") return null;
|
|
12177
|
+
const trimmed = value.trim();
|
|
12178
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
12179
|
+
}
|
|
12180
|
+
function readFiniteNumber(value, fallback = 0) {
|
|
12181
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
12182
|
+
}
|
|
12183
|
+
function readOptionalFiniteNumber(value) {
|
|
12184
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
12185
|
+
}
|
|
12186
|
+
function normalizeQuestionType(rawType) {
|
|
12187
|
+
const normalized = readString(rawType).trim().toUpperCase().replace(/[\s-]+/g, "_");
|
|
12188
|
+
return normalized === "MULTIPLE_CHOICE" ? "MULTIPLE_CHOICE" : "SINGLE_CHOICE";
|
|
12189
|
+
}
|
|
12190
|
+
function normalizeMessageRole(rawRole) {
|
|
12191
|
+
const normalized = readString(rawRole).trim().toLowerCase();
|
|
12192
|
+
if (normalized === "user" /* User */) return "user" /* User */;
|
|
12193
|
+
if (normalized === "system" /* System */) return "system" /* System */;
|
|
12194
|
+
if (normalized === "tool" /* Tool */) return "tool" /* Tool */;
|
|
12195
|
+
return "assistant" /* Assistant */;
|
|
12196
|
+
}
|
|
12197
|
+
function sanitizeAttachment(rawAttachment, turnId, index) {
|
|
12198
|
+
if (!isRecord(rawAttachment)) {
|
|
12199
|
+
warnMalformedSessionPayload("Dropped malformed attachment entry", { turnId, index });
|
|
12200
|
+
return null;
|
|
12201
|
+
}
|
|
12202
|
+
const filename = readString(rawAttachment.filename, "attachment");
|
|
12203
|
+
const mimeType = readString(rawAttachment.mimeType, "application/octet-stream");
|
|
12204
|
+
const id = readNonEmptyString(rawAttachment.id) || void 0;
|
|
12205
|
+
const clientKey = readNonEmptyString(rawAttachment.clientKey) || id || `${turnId}-attachment-${index}`;
|
|
12057
12206
|
return {
|
|
12058
|
-
id
|
|
12059
|
-
|
|
12207
|
+
id,
|
|
12208
|
+
clientKey,
|
|
12209
|
+
filename,
|
|
12210
|
+
mimeType,
|
|
12211
|
+
sizeBytes: readFiniteNumber(rawAttachment.sizeBytes),
|
|
12212
|
+
uploadId: readOptionalFiniteNumber(rawAttachment.uploadId),
|
|
12213
|
+
base64Data: readNonEmptyString(rawAttachment.base64Data) || void 0,
|
|
12214
|
+
url: readNonEmptyString(rawAttachment.url) || void 0,
|
|
12215
|
+
preview: readNonEmptyString(rawAttachment.preview) || void 0
|
|
12216
|
+
};
|
|
12217
|
+
}
|
|
12218
|
+
function sanitizeUserAttachments(rawAttachments, turnId) {
|
|
12219
|
+
if (!Array.isArray(rawAttachments)) return [];
|
|
12220
|
+
const result = [];
|
|
12221
|
+
for (let i = 0; i < rawAttachments.length; i++) {
|
|
12222
|
+
const sanitized = sanitizeAttachment(rawAttachments[i], turnId, i);
|
|
12223
|
+
if (sanitized) result.push(sanitized);
|
|
12224
|
+
}
|
|
12225
|
+
return result;
|
|
12226
|
+
}
|
|
12227
|
+
function sanitizeAssistantArtifacts(rawArtifacts, turnId) {
|
|
12228
|
+
if (!Array.isArray(rawArtifacts)) return [];
|
|
12229
|
+
const artifacts = [];
|
|
12230
|
+
for (let i = 0; i < rawArtifacts.length; i++) {
|
|
12231
|
+
const raw = rawArtifacts[i];
|
|
12232
|
+
if (!isRecord(raw)) {
|
|
12233
|
+
warnMalformedSessionPayload("Dropped malformed assistant artifact", { turnId, index: i });
|
|
12234
|
+
continue;
|
|
12235
|
+
}
|
|
12236
|
+
const type = readString(raw.type).toLowerCase();
|
|
12237
|
+
if (type !== "excel" && type !== "pdf") {
|
|
12238
|
+
continue;
|
|
12239
|
+
}
|
|
12240
|
+
const url = readNonEmptyString(raw.url);
|
|
12241
|
+
if (!url) {
|
|
12242
|
+
warnMalformedSessionPayload("Dropped assistant artifact without url", { turnId, index: i });
|
|
12243
|
+
continue;
|
|
12244
|
+
}
|
|
12245
|
+
artifacts.push({
|
|
12246
|
+
type,
|
|
12247
|
+
filename: readString(raw.filename, "download"),
|
|
12248
|
+
url,
|
|
12249
|
+
sizeReadable: readNonEmptyString(raw.sizeReadable) || void 0,
|
|
12250
|
+
rowCount: typeof raw.rowCount === "number" && Number.isFinite(raw.rowCount) ? raw.rowCount : void 0,
|
|
12251
|
+
description: readNonEmptyString(raw.description) || void 0
|
|
12252
|
+
});
|
|
12253
|
+
}
|
|
12254
|
+
return artifacts;
|
|
12255
|
+
}
|
|
12256
|
+
function sanitizeAssistantTurn(rawAssistantTurn, fallbackCreatedAt, turnId) {
|
|
12257
|
+
if (rawAssistantTurn == null) return void 0;
|
|
12258
|
+
if (!isRecord(rawAssistantTurn)) {
|
|
12259
|
+
warnMalformedSessionPayload("Dropped malformed assistant turn payload", { turnId });
|
|
12260
|
+
return void 0;
|
|
12261
|
+
}
|
|
12262
|
+
const assistantID = readNonEmptyString(rawAssistantTurn.id);
|
|
12263
|
+
if (!assistantID) {
|
|
12264
|
+
warnMalformedSessionPayload("Dropped assistant turn without id", { turnId });
|
|
12265
|
+
return void 0;
|
|
12266
|
+
}
|
|
12267
|
+
const citations = Array.isArray(rawAssistantTurn.citations) ? rawAssistantTurn.citations.filter((item) => isRecord(item)).map((item, index) => ({
|
|
12268
|
+
id: readString(item.id, `${assistantID}-citation-${index}`),
|
|
12269
|
+
type: readString(item.type),
|
|
12270
|
+
title: readString(item.title),
|
|
12271
|
+
url: readString(item.url),
|
|
12272
|
+
startIndex: readFiniteNumber(item.startIndex),
|
|
12273
|
+
endIndex: readFiniteNumber(item.endIndex),
|
|
12274
|
+
excerpt: readNonEmptyString(item.excerpt) || void 0
|
|
12275
|
+
})) : [];
|
|
12276
|
+
const toolCalls = Array.isArray(rawAssistantTurn.toolCalls) ? rawAssistantTurn.toolCalls.filter((item) => isRecord(item)).map((item, index) => ({
|
|
12277
|
+
id: readString(item.id, `${assistantID}-tool-${index}`),
|
|
12278
|
+
name: readString(item.name),
|
|
12279
|
+
arguments: readString(item.arguments),
|
|
12280
|
+
result: readNonEmptyString(item.result) || void 0,
|
|
12281
|
+
error: readNonEmptyString(item.error) || void 0,
|
|
12282
|
+
durationMs: readFiniteNumber(item.durationMs)
|
|
12283
|
+
})) : [];
|
|
12284
|
+
const codeOutputs = Array.isArray(rawAssistantTurn.codeOutputs) ? rawAssistantTurn.codeOutputs.filter((item) => isRecord(item)).map((item) => ({
|
|
12285
|
+
type: (() => {
|
|
12286
|
+
const normalizedType = readString(item.type, "text").toLowerCase();
|
|
12287
|
+
if (normalizedType === "image" || normalizedType === "error") return normalizedType;
|
|
12288
|
+
return "text";
|
|
12289
|
+
})(),
|
|
12290
|
+
content: readString(item.content),
|
|
12291
|
+
filename: readNonEmptyString(item.filename) || void 0,
|
|
12292
|
+
mimeType: readNonEmptyString(item.mimeType) || void 0,
|
|
12293
|
+
sizeBytes: readOptionalFiniteNumber(item.sizeBytes)
|
|
12294
|
+
})) : [];
|
|
12295
|
+
const debugTrace = isRecord(rawAssistantTurn.debug) ? {
|
|
12296
|
+
generationMs: readOptionalFiniteNumber(rawAssistantTurn.debug.generationMs),
|
|
12297
|
+
usage: isRecord(rawAssistantTurn.debug.usage) ? {
|
|
12298
|
+
promptTokens: readFiniteNumber(rawAssistantTurn.debug.usage.promptTokens),
|
|
12299
|
+
completionTokens: readFiniteNumber(rawAssistantTurn.debug.usage.completionTokens),
|
|
12300
|
+
totalTokens: readFiniteNumber(rawAssistantTurn.debug.usage.totalTokens),
|
|
12301
|
+
cachedTokens: readOptionalFiniteNumber(rawAssistantTurn.debug.usage.cachedTokens),
|
|
12302
|
+
cost: readOptionalFiniteNumber(rawAssistantTurn.debug.usage.cost)
|
|
12303
|
+
} : void 0,
|
|
12304
|
+
tools: Array.isArray(rawAssistantTurn.debug.tools) ? rawAssistantTurn.debug.tools.filter((tool) => isRecord(tool)).map((tool) => ({
|
|
12305
|
+
callId: readNonEmptyString(tool.callId) || void 0,
|
|
12306
|
+
name: readString(tool.name),
|
|
12307
|
+
arguments: readNonEmptyString(tool.arguments) || void 0,
|
|
12308
|
+
result: readNonEmptyString(tool.result) || void 0,
|
|
12309
|
+
error: readNonEmptyString(tool.error) || void 0,
|
|
12310
|
+
durationMs: readOptionalFiniteNumber(tool.durationMs)
|
|
12311
|
+
})) : []
|
|
12312
|
+
} : void 0;
|
|
12313
|
+
return {
|
|
12314
|
+
id: assistantID,
|
|
12315
|
+
role: normalizeMessageRole(rawAssistantTurn.role),
|
|
12316
|
+
content: readString(rawAssistantTurn.content),
|
|
12317
|
+
explanation: readNonEmptyString(rawAssistantTurn.explanation) || void 0,
|
|
12318
|
+
citations,
|
|
12319
|
+
toolCalls,
|
|
12320
|
+
chartData: void 0,
|
|
12321
|
+
artifacts: sanitizeAssistantArtifacts(rawAssistantTurn.artifacts, turnId),
|
|
12322
|
+
codeOutputs,
|
|
12323
|
+
debug: debugTrace,
|
|
12324
|
+
createdAt: readString(rawAssistantTurn.createdAt, fallbackCreatedAt)
|
|
12325
|
+
};
|
|
12326
|
+
}
|
|
12327
|
+
function sanitizeConversationTurn(rawTurn, index, fallbackSessionID) {
|
|
12328
|
+
if (!isRecord(rawTurn)) {
|
|
12329
|
+
warnMalformedSessionPayload("Dropped malformed turn payload (not an object)", { index });
|
|
12330
|
+
return null;
|
|
12331
|
+
}
|
|
12332
|
+
if (!isRecord(rawTurn.userTurn)) {
|
|
12333
|
+
warnMalformedSessionPayload("Dropped malformed turn payload (missing user turn)", { index });
|
|
12334
|
+
return null;
|
|
12335
|
+
}
|
|
12336
|
+
const userTurnID = readNonEmptyString(rawTurn.userTurn.id);
|
|
12337
|
+
if (!userTurnID) {
|
|
12338
|
+
warnMalformedSessionPayload("Dropped malformed turn payload (missing user turn id)", { index });
|
|
12339
|
+
return null;
|
|
12340
|
+
}
|
|
12341
|
+
const turnID = readString(rawTurn.id, userTurnID);
|
|
12342
|
+
const createdAt = readString(
|
|
12343
|
+
rawTurn.createdAt,
|
|
12344
|
+
readString(rawTurn.userTurn.createdAt, (/* @__PURE__ */ new Date()).toISOString())
|
|
12345
|
+
);
|
|
12346
|
+
return {
|
|
12347
|
+
id: turnID,
|
|
12348
|
+
sessionId: readString(rawTurn.sessionId, fallbackSessionID),
|
|
12349
|
+
userTurn: {
|
|
12350
|
+
id: userTurnID,
|
|
12351
|
+
content: readString(rawTurn.userTurn.content),
|
|
12352
|
+
attachments: sanitizeUserAttachments(rawTurn.userTurn.attachments, turnID),
|
|
12353
|
+
createdAt: readString(rawTurn.userTurn.createdAt, createdAt)
|
|
12354
|
+
},
|
|
12355
|
+
assistantTurn: sanitizeAssistantTurn(rawTurn.assistantTurn, createdAt, turnID),
|
|
12356
|
+
createdAt
|
|
12357
|
+
};
|
|
12358
|
+
}
|
|
12359
|
+
function sanitizeConversationTurns(rawTurns, sessionID) {
|
|
12360
|
+
if (!Array.isArray(rawTurns)) {
|
|
12361
|
+
warnMalformedSessionPayload("Session payload contained non-array turns field", { sessionID });
|
|
12362
|
+
return [];
|
|
12363
|
+
}
|
|
12364
|
+
const turns = [];
|
|
12365
|
+
let dropped = 0;
|
|
12366
|
+
for (let i = 0; i < rawTurns.length; i++) {
|
|
12367
|
+
const sanitizedTurn = sanitizeConversationTurn(rawTurns[i], i, sessionID);
|
|
12368
|
+
if (sanitizedTurn) {
|
|
12369
|
+
turns.push(sanitizedTurn);
|
|
12370
|
+
} else {
|
|
12371
|
+
dropped++;
|
|
12372
|
+
}
|
|
12373
|
+
}
|
|
12374
|
+
if (dropped > 0) {
|
|
12375
|
+
warnMalformedSessionPayload("Dropped malformed turns from session payload", {
|
|
12376
|
+
sessionID,
|
|
12377
|
+
dropped,
|
|
12378
|
+
total: rawTurns.length
|
|
12379
|
+
});
|
|
12380
|
+
}
|
|
12381
|
+
return turns;
|
|
12382
|
+
}
|
|
12383
|
+
function sanitizePendingQuestion(rawPendingQuestion, sessionID) {
|
|
12384
|
+
if (!rawPendingQuestion) return null;
|
|
12385
|
+
const checkpointID = readNonEmptyString(rawPendingQuestion.checkpointId);
|
|
12386
|
+
if (!checkpointID) {
|
|
12387
|
+
warnMalformedSessionPayload("Dropped malformed pendingQuestion without checkpointId", { sessionID });
|
|
12388
|
+
return null;
|
|
12389
|
+
}
|
|
12390
|
+
if (!Array.isArray(rawPendingQuestion.questions)) {
|
|
12391
|
+
warnMalformedSessionPayload("Pending question had non-array questions payload", {
|
|
12392
|
+
sessionID,
|
|
12393
|
+
checkpointID
|
|
12394
|
+
});
|
|
12395
|
+
}
|
|
12396
|
+
const questions = Array.isArray(rawPendingQuestion.questions) ? rawPendingQuestion.questions.filter((question) => {
|
|
12397
|
+
if (!question || !isRecord(question)) {
|
|
12398
|
+
warnMalformedSessionPayload("Dropped malformed question from pendingQuestion", {
|
|
12399
|
+
sessionID,
|
|
12400
|
+
checkpointID
|
|
12401
|
+
});
|
|
12402
|
+
return false;
|
|
12403
|
+
}
|
|
12404
|
+
return true;
|
|
12405
|
+
}).map((question, index) => {
|
|
12406
|
+
const questionID = readString(question.id, `${checkpointID}-q-${index}`);
|
|
12407
|
+
const options = Array.isArray(question.options) ? question.options.filter((option) => {
|
|
12408
|
+
if (!option || !isRecord(option)) {
|
|
12409
|
+
warnMalformedSessionPayload("Dropped malformed pendingQuestion option", {
|
|
12410
|
+
sessionID,
|
|
12411
|
+
checkpointID,
|
|
12412
|
+
questionID
|
|
12413
|
+
});
|
|
12414
|
+
return false;
|
|
12415
|
+
}
|
|
12416
|
+
return true;
|
|
12417
|
+
}).map((option, optionIndex) => {
|
|
12418
|
+
const label = readString(option.label);
|
|
12419
|
+
return {
|
|
12420
|
+
id: readString(option.id, `${questionID}-opt-${optionIndex}`),
|
|
12421
|
+
label,
|
|
12422
|
+
value: label
|
|
12423
|
+
};
|
|
12424
|
+
}) : [];
|
|
12425
|
+
return {
|
|
12426
|
+
id: questionID,
|
|
12427
|
+
text: readString(question.text),
|
|
12428
|
+
type: normalizeQuestionType(question.type),
|
|
12429
|
+
options
|
|
12430
|
+
};
|
|
12431
|
+
}) : [];
|
|
12432
|
+
return {
|
|
12433
|
+
id: checkpointID,
|
|
12434
|
+
turnId: readString(rawPendingQuestion.turnId),
|
|
12060
12435
|
questions,
|
|
12061
12436
|
status: "PENDING"
|
|
12062
12437
|
};
|
|
@@ -12252,7 +12627,8 @@ var HttpDataSource = class {
|
|
|
12252
12627
|
this.abortController = null;
|
|
12253
12628
|
this.config = {
|
|
12254
12629
|
streamEndpoint: "/stream",
|
|
12255
|
-
|
|
12630
|
+
uploadEndpoint: "/api/uploads",
|
|
12631
|
+
timeout: 12e4,
|
|
12256
12632
|
...config
|
|
12257
12633
|
};
|
|
12258
12634
|
if (config.navigateToSession) {
|
|
@@ -12287,6 +12663,83 @@ var HttpDataSource = class {
|
|
|
12287
12663
|
}
|
|
12288
12664
|
return headers;
|
|
12289
12665
|
}
|
|
12666
|
+
createUploadHeaders(additionalHeaders) {
|
|
12667
|
+
const headers = new Headers({
|
|
12668
|
+
...this.config.headers,
|
|
12669
|
+
...additionalHeaders
|
|
12670
|
+
});
|
|
12671
|
+
const csrfToken = this.getCSRFToken();
|
|
12672
|
+
if (csrfToken) {
|
|
12673
|
+
headers.set("X-CSRF-Token", csrfToken);
|
|
12674
|
+
}
|
|
12675
|
+
headers.delete("Content-Type");
|
|
12676
|
+
return headers;
|
|
12677
|
+
}
|
|
12678
|
+
async uploadFile(file) {
|
|
12679
|
+
const formData = new FormData();
|
|
12680
|
+
formData.append("file", file);
|
|
12681
|
+
const response = await fetch(`${this.config.baseUrl}${this.config.uploadEndpoint}`, {
|
|
12682
|
+
method: "POST",
|
|
12683
|
+
headers: this.createUploadHeaders(),
|
|
12684
|
+
body: formData
|
|
12685
|
+
});
|
|
12686
|
+
let payload = null;
|
|
12687
|
+
try {
|
|
12688
|
+
payload = await response.json();
|
|
12689
|
+
} catch {
|
|
12690
|
+
payload = null;
|
|
12691
|
+
}
|
|
12692
|
+
if (!response.ok) {
|
|
12693
|
+
const errorMessage = isRecord(payload) && typeof payload.error === "string" ? payload.error : `Upload failed: HTTP ${response.status}`;
|
|
12694
|
+
throw new Error(errorMessage);
|
|
12695
|
+
}
|
|
12696
|
+
if (!isRecord(payload) || typeof payload.id !== "number" || payload.id <= 0) {
|
|
12697
|
+
throw new Error("Upload failed: invalid response payload");
|
|
12698
|
+
}
|
|
12699
|
+
return {
|
|
12700
|
+
id: payload.id,
|
|
12701
|
+
url: typeof payload.url === "string" ? payload.url : "",
|
|
12702
|
+
path: typeof payload.path === "string" ? payload.path : "",
|
|
12703
|
+
name: typeof payload.name === "string" ? payload.name : file.name,
|
|
12704
|
+
mimetype: typeof payload.mimetype === "string" ? payload.mimetype : file.type,
|
|
12705
|
+
size: typeof payload.size === "number" && Number.isFinite(payload.size) ? payload.size : file.size
|
|
12706
|
+
};
|
|
12707
|
+
}
|
|
12708
|
+
async attachmentToFile(attachment) {
|
|
12709
|
+
if (attachment.base64Data && attachment.base64Data.trim().length > 0) {
|
|
12710
|
+
const base64Data = attachment.base64Data.trim();
|
|
12711
|
+
const dataUrl = base64Data.startsWith("data:") ? base64Data : `data:${attachment.mimeType || "application/octet-stream"};base64,${base64Data}`;
|
|
12712
|
+
const blob = await fetch(dataUrl).then((response) => response.blob());
|
|
12713
|
+
return new File([blob], attachment.filename, {
|
|
12714
|
+
type: attachment.mimeType || blob.type || "application/octet-stream"
|
|
12715
|
+
});
|
|
12716
|
+
}
|
|
12717
|
+
if (attachment.url) {
|
|
12718
|
+
const response = await fetch(attachment.url);
|
|
12719
|
+
if (!response.ok) {
|
|
12720
|
+
throw new Error(`Failed to read attachment source: HTTP ${response.status}`);
|
|
12721
|
+
}
|
|
12722
|
+
const blob = await response.blob();
|
|
12723
|
+
return new File([blob], attachment.filename, {
|
|
12724
|
+
type: attachment.mimeType || blob.type || "application/octet-stream"
|
|
12725
|
+
});
|
|
12726
|
+
}
|
|
12727
|
+
throw new Error(`Attachment "${attachment.filename}" has no uploadable data`);
|
|
12728
|
+
}
|
|
12729
|
+
async ensureAttachmentUpload(attachment) {
|
|
12730
|
+
if (typeof attachment.uploadId === "number" && attachment.uploadId > 0) {
|
|
12731
|
+
return {
|
|
12732
|
+
id: attachment.uploadId,
|
|
12733
|
+
url: attachment.url || "",
|
|
12734
|
+
path: "",
|
|
12735
|
+
name: attachment.filename,
|
|
12736
|
+
mimetype: attachment.mimeType,
|
|
12737
|
+
size: attachment.sizeBytes
|
|
12738
|
+
};
|
|
12739
|
+
}
|
|
12740
|
+
const file = await this.attachmentToFile(attachment);
|
|
12741
|
+
return this.uploadFile(file);
|
|
12742
|
+
}
|
|
12290
12743
|
async callRPC(method, params) {
|
|
12291
12744
|
return this.rpc.callTyped(method, params);
|
|
12292
12745
|
}
|
|
@@ -12309,11 +12762,22 @@ var HttpDataSource = class {
|
|
|
12309
12762
|
return { artifacts: [], hasMore: false, nextOffset: 0 };
|
|
12310
12763
|
})
|
|
12311
12764
|
]);
|
|
12312
|
-
const
|
|
12765
|
+
const sanitizedTurns = sanitizeConversationTurns(data.turns, id);
|
|
12766
|
+
const turns = attachArtifactsToTurns(
|
|
12767
|
+
normalizeTurns(sanitizedTurns),
|
|
12768
|
+
artifactsData.artifacts || []
|
|
12769
|
+
);
|
|
12770
|
+
const pendingQuestion = sanitizePendingQuestion(data.pendingQuestion, id);
|
|
12771
|
+
if (data.pendingQuestion && pendingQuestion && pendingQuestion.questions.length === 0) {
|
|
12772
|
+
warnMalformedSessionPayload("Pending question normalized to zero renderable questions", {
|
|
12773
|
+
sessionID: id,
|
|
12774
|
+
checkpointID: pendingQuestion.id
|
|
12775
|
+
});
|
|
12776
|
+
}
|
|
12313
12777
|
return {
|
|
12314
12778
|
session: toSession(data.session),
|
|
12315
12779
|
turns,
|
|
12316
|
-
pendingQuestion
|
|
12780
|
+
pendingQuestion
|
|
12317
12781
|
};
|
|
12318
12782
|
} catch (err) {
|
|
12319
12783
|
if (isSessionNotFoundError(err)) {
|
|
@@ -12345,27 +12809,12 @@ var HttpDataSource = class {
|
|
|
12345
12809
|
return { artifacts: [] };
|
|
12346
12810
|
}
|
|
12347
12811
|
validateFileCount(0, files.length, 10);
|
|
12348
|
-
|
|
12349
|
-
|
|
12350
|
-
validateAttachmentFile(file);
|
|
12351
|
-
const base64Data = await convertToBase64(file);
|
|
12352
|
-
attachments.push({
|
|
12353
|
-
clientKey: crypto.randomUUID(),
|
|
12354
|
-
filename: file.name,
|
|
12355
|
-
mimeType: file.type,
|
|
12356
|
-
sizeBytes: file.size,
|
|
12357
|
-
base64Data
|
|
12358
|
-
});
|
|
12359
|
-
}
|
|
12812
|
+
files.forEach((file) => validateAttachmentFile(file));
|
|
12813
|
+
const uploads = await Promise.all(files.map((file) => this.uploadFile(file)));
|
|
12360
12814
|
const data = await this.callRPC("bichat.session.uploadArtifacts", {
|
|
12361
12815
|
sessionId,
|
|
12362
|
-
attachments:
|
|
12363
|
-
|
|
12364
|
-
// Backend will assign ID
|
|
12365
|
-
filename: a.filename,
|
|
12366
|
-
mimeType: a.mimeType,
|
|
12367
|
-
sizeBytes: a.sizeBytes,
|
|
12368
|
-
base64Data: a.base64Data
|
|
12816
|
+
attachments: uploads.map((upload) => ({
|
|
12817
|
+
uploadId: upload.id
|
|
12369
12818
|
}))
|
|
12370
12819
|
});
|
|
12371
12820
|
return {
|
|
@@ -12396,22 +12845,21 @@ var HttpDataSource = class {
|
|
|
12396
12845
|
signal.addEventListener("abort", onExternalAbort);
|
|
12397
12846
|
}
|
|
12398
12847
|
const url = `${this.config.baseUrl}${this.config.streamEndpoint}`;
|
|
12399
|
-
const payload = {
|
|
12400
|
-
sessionId,
|
|
12401
|
-
content,
|
|
12402
|
-
debugMode: options?.debugMode ?? false,
|
|
12403
|
-
replaceFromMessageId: options?.replaceFromMessageID,
|
|
12404
|
-
attachments: attachments.map((a) => ({
|
|
12405
|
-
filename: a.filename,
|
|
12406
|
-
mimeType: a.mimeType,
|
|
12407
|
-
sizeBytes: a.sizeBytes,
|
|
12408
|
-
base64Data: a.base64Data,
|
|
12409
|
-
url: a.url
|
|
12410
|
-
}))
|
|
12411
|
-
};
|
|
12412
12848
|
let connectionTimeoutID;
|
|
12413
12849
|
let connectionTimedOut = false;
|
|
12414
12850
|
try {
|
|
12851
|
+
const uploads = await Promise.all(
|
|
12852
|
+
attachments.map((attachment) => this.ensureAttachmentUpload(attachment))
|
|
12853
|
+
);
|
|
12854
|
+
const payload = {
|
|
12855
|
+
sessionId,
|
|
12856
|
+
content,
|
|
12857
|
+
debugMode: options?.debugMode ?? false,
|
|
12858
|
+
replaceFromMessageId: options?.replaceFromMessageID,
|
|
12859
|
+
attachments: uploads.map((upload) => ({
|
|
12860
|
+
uploadId: upload.id
|
|
12861
|
+
}))
|
|
12862
|
+
};
|
|
12415
12863
|
const timeoutMs = this.config.timeout ?? 0;
|
|
12416
12864
|
if (timeoutMs > 0) {
|
|
12417
12865
|
connectionTimeoutID = setTimeout(() => {
|